diff options
Diffstat (limited to 'app')
| -rw-r--r-- | app/[lng]/evcp/(evcp)/items/page.tsx | 29 | ||||
| -rw-r--r-- | app/[lng]/evcp/(evcp)/vendors/[id]/info/items/page.tsx | 4 | ||||
| -rw-r--r-- | app/[lng]/evcp/(evcp)/vendors/[id]/info/layout.tsx | 6 | ||||
| -rw-r--r-- | app/[lng]/evcp/(evcp)/vendors/[id]/info/materials/page.tsx | 56 | ||||
| -rw-r--r-- | app/[lng]/partners/(partners)/rfq-all/[id]/page.tsx | 3 | ||||
| -rw-r--r-- | app/api/admin/clear-test-data/route.ts | 136 |
6 files changed, 182 insertions, 52 deletions
diff --git a/app/[lng]/evcp/(evcp)/items/page.tsx b/app/[lng]/evcp/(evcp)/items/page.tsx index 31dcaf11..0c44bf0a 100644 --- a/app/[lng]/evcp/(evcp)/items/page.tsx +++ b/app/[lng]/evcp/(evcp)/items/page.tsx @@ -8,6 +8,7 @@ import { Shell } from "@/components/shell" import { searchParamsCache } from "@/lib/items/validations" import { getItems } from "@/lib/items/service" import { ItemsTable } from "@/lib/items/table/items-table" +import { ViewModeToggle } from "@/components/data-table/view-mode-toggle" interface IndexPageProps { searchParams: Promise<SearchParams> @@ -19,43 +20,35 @@ export default async function IndexPage(props: IndexPageProps) { // pageSize 기반으로 모드 자동 결정 const isInfiniteMode = search.perPage >= 1_000_000 - - console.log('Page searchParams:', searchParams) - console.log('Parsed search:', search) - console.log('isInfiniteMode (pageSize >= 1M):', isInfiniteMode) - + // 페이지네이션 모드일 때만 서버에서 데이터 가져오기 // 무한 스크롤 모드에서는 클라이언트에서 SWR로 데이터 로드 - const promises = isInfiniteMode - ? null - : Promise.all([ + const promises = isInfiniteMode + ? undefined + : Promise.all([ getItems(search), // searchParamsCache의 결과를 그대로 사용 ]) - + return ( <Shell className="gap-2"> <div className="flex items-center justify-between space-y-2"> <div className="flex items-center justify-between space-y-2"> <div> <h2 className="text-2xl font-bold tracking-tight"> - Package Items + 패키지 정보 </h2> <p className="text-muted-foreground"> - {/* Item을 등록하고 관리할 수 있습니다. */} - {isInfiniteMode && ( - <span className="ml-2 text-xs bg-blue-100 text-blue-800 px-2 py-1 rounded"> - 무한 스크롤 모드 - </span> - )} + S-EDP로부터 수신된 패키지 정보이며 PR 전 입찰, 견적에 사용되며 벤더 데이터, 문서와 연결됩니다. </p> </div> </div> + </div> - + <React.Suspense fallback={<Skeleton className="h-7 w-52" />}> {/* DateRangePicker 등 추가 컴포넌트 */} </React.Suspense> - + <React.Suspense fallback={ <DataTableSkeleton diff --git a/app/[lng]/evcp/(evcp)/vendors/[id]/info/items/page.tsx b/app/[lng]/evcp/(evcp)/vendors/[id]/info/items/page.tsx index e9ff17b4..5d5838c6 100644 --- a/app/[lng]/evcp/(evcp)/vendors/[id]/info/items/page.tsx +++ b/app/[lng]/evcp/(evcp)/vendors/[id]/info/items/page.tsx @@ -41,10 +41,10 @@ export default async function SettingsAccountPage(props: IndexPageProps) { <div className="space-y-6"> <div> <h3 className="text-lg font-medium"> - Possible Items + 공급품목(패키지) </h3> <p className="text-sm text-muted-foreground"> - 딜리버리가 가능한 아이템 리스트를 확인할 수 있습니다. + {/* 딜리버리가 가능한 아이템 리스트를 확인할 수 있습니다. */} </p> </div> <Separator /> diff --git a/app/[lng]/evcp/(evcp)/vendors/[id]/info/layout.tsx b/app/[lng]/evcp/(evcp)/vendors/[id]/info/layout.tsx index 00c3f640..7e2cd4f6 100644 --- a/app/[lng]/evcp/(evcp)/vendors/[id]/info/layout.tsx +++ b/app/[lng]/evcp/(evcp)/vendors/[id]/info/layout.tsx @@ -35,10 +35,14 @@ export default async function SettingsLayout({ href: `/${lng}/evcp/vendors/${id}/info`, }, { - title: "공급품목", + title: "공급품목(패키지)", href: `/${lng}/evcp/vendors/${id}/info/items`, }, { + title: "공급품목(자재그룹)", + href: `/${lng}/evcp/vendors/${id}/info/materials`, + }, + { title: "견적 히스토리", href: `/${lng}/evcp/vendors/${id}/info/rfq-history`, }, diff --git a/app/[lng]/evcp/(evcp)/vendors/[id]/info/materials/page.tsx b/app/[lng]/evcp/(evcp)/vendors/[id]/info/materials/page.tsx new file mode 100644 index 00000000..0ebb66ba --- /dev/null +++ b/app/[lng]/evcp/(evcp)/vendors/[id]/info/materials/page.tsx @@ -0,0 +1,56 @@ +import { Separator } from "@/components/ui/separator" +import { type SearchParams } from "@/types/table" +import { getValidFilters } from "@/lib/data-table" +import { searchParamsMaterialCache } from "@/lib/vendors/validations" +import { getVendorMaterials } from "@/lib/vendors/service" +import { VendorMaterialsTable } from "@/lib/vendors/materials-table/item-table" + +interface IndexPageProps { + // Next.js 13 App Router에서 기본으로 주어지는 객체들 + params: { + lng: string + id: string + } + searchParams: Promise<SearchParams> +} + +export default async function SettingsAccountPage(props: IndexPageProps) { + const resolvedParams = await props.params + const lng = resolvedParams.lng + const id = resolvedParams.id + + const idAsNumber = Number(id) + + // 2) SearchParams 파싱 (Zod) + // - "filters", "page", "perPage", "sort" 등 contact 전용 컬럼 + const searchParams = await props.searchParams + const search = searchParamsMaterialCache.parse(searchParams) + const validFilters = getValidFilters(search.filters) + + + + const promises = Promise.all([ + getVendorMaterials({ + ...search, + filters: validFilters, + }, + idAsNumber) + ]) + // 4) 렌더링 + return ( + <div className="space-y-6"> + <div> + <h3 className="text-lg font-medium"> + 공급품목(자재 그룹) + </h3> + <p className="text-sm text-muted-foreground"> + {/* 딜리버리가 가능한 공급품목(자재 그룹)을 확인할 수 있습니다. */} + </p> + </div> + <Separator /> + <div> + <VendorMaterialsTable promises={promises} vendorId={idAsNumber}/> + </div> + </div> + ) +}
\ No newline at end of file diff --git a/app/[lng]/partners/(partners)/rfq-all/[id]/page.tsx b/app/[lng]/partners/(partners)/rfq-all/[id]/page.tsx index c8858704..772a9840 100644 --- a/app/[lng]/partners/(partners)/rfq-all/[id]/page.tsx +++ b/app/[lng]/partners/(partners)/rfq-all/[id]/page.tsx @@ -23,6 +23,7 @@ export async function generateMetadata({ params }: PageProps): Promise<Metadata> } export default async function VendorQuotationPage({ params }: PageProps) { + const quotationId = parseInt(params.id) if (isNaN(quotationId)) { @@ -49,7 +50,7 @@ export default async function VendorQuotationPage({ params }: PageProps) { with: { rfq: true, // 관계 설정 필요 vendor: true, // 관계 설정 필요 - items: true, // 관계 설정 필요 + // items: true, // 관계 설정 필요 } }) diff --git a/app/api/admin/clear-test-data/route.ts b/app/api/admin/clear-test-data/route.ts index 9a5c8458..8442e5de 100644 --- a/app/api/admin/clear-test-data/route.ts +++ b/app/api/admin/clear-test-data/route.ts @@ -1,44 +1,107 @@ // app/api/admin/clear-test-data/route.ts -import db from '@/db/db' -import { formEntries, forms, formMetas, tags } from '@/db/schema/vendorData' +import db from '@/db/db' +import { + formEntries, + forms, + formMetas, + tags, + tagTypes, + tagSubfields, + tagSubfieldOptions, + tagClasses, + tagClassAttributes, + tagTypeClassFormMappings, + vendorDataReportTemps +} from '@/db/schema/vendorData' import { NextRequest } from 'next/server' export async function DELETE(request: NextRequest) { - try { - // 외래키 참조 순서를 고려하여 삭제 (자식 테이블부터) - console.log('Clearing test data...') + // 외래키 참조 순서를 고려하여 삭제 (자식 테이블부터 부모 테이블 순) + console.log('Clearing all test data...') - // 1. form_entries 삭제 + const deletedCounts = { + tagClassAttributes: 0, + tagClasses: 0, + tagSubfieldOptions: 0, + tagSubfields: 0, + tagTypes: 0, + tagTypeClassFormMappings: 0, + vendorDataReportTemps: 0, + formEntries: 0, + tags: 0, + forms: 0, + formMetas: 0 + } + + // 1. tagClassAttributes 삭제 (가장 하위 자식) + const deletedTagClassAttributes = await db.delete(tagClassAttributes) + deletedCounts.tagClassAttributes = deletedTagClassAttributes.rowCount || 0 + console.log('Deleted tag class attributes:', deletedCounts.tagClassAttributes) + + // 2. tagClasses 삭제 + const deletedTagClasses = await db.delete(tagClasses) + deletedCounts.tagClasses = deletedTagClasses.rowCount || 0 + console.log('Deleted tag classes:', deletedCounts.tagClasses) + + // 3. tagSubfieldOptions 삭제 + const deletedTagSubfieldOptions = await db.delete(tagSubfieldOptions) + deletedCounts.tagSubfieldOptions = deletedTagSubfieldOptions.rowCount || 0 + console.log('Deleted tag subfield options:', deletedCounts.tagSubfieldOptions) + + // 4. tagSubfields 삭제 + const deletedTagSubfields = await db.delete(tagSubfields) + deletedCounts.tagSubfields = deletedTagSubfields.rowCount || 0 + console.log('Deleted tag subfields:', deletedCounts.tagSubfields) + + // 5. tagTypes 삭제 + const deletedTagTypes = await db.delete(tagTypes) + deletedCounts.tagTypes = deletedTagTypes.rowCount || 0 + console.log('Deleted tag types:', deletedCounts.tagTypes) + + // 6. tagTypeClassFormMappings 삭제 + const deletedMappings = await db.delete(tagTypeClassFormMappings) + deletedCounts.tagTypeClassFormMappings = deletedMappings.rowCount || 0 + console.log('Deleted tag type class form mappings:', deletedCounts.tagTypeClassFormMappings) + + // 7. vendorDataReportTemps 삭제 + const deletedVendorReports = await db.delete(vendorDataReportTemps) + deletedCounts.vendorDataReportTemps = deletedVendorReports.rowCount || 0 + console.log('Deleted vendor data report temps:', deletedCounts.vendorDataReportTemps) + + // 8. formEntries 삭제 const deletedEntries = await db.delete(formEntries) - console.log('Deleted form entries') - - // 2. tags 삭제 + deletedCounts.formEntries = deletedEntries.rowCount || 0 + console.log('Deleted form entries:', deletedCounts.formEntries) + + // 9. tags 삭제 const deletedTags = await db.delete(tags) - console.log('Deleted tags') - - // 3. forms 삭제 + deletedCounts.tags = deletedTags.rowCount || 0 + console.log('Deleted tags:', deletedCounts.tags) + + // 10. forms 삭제 const deletedForms = await db.delete(forms) - console.log('Deleted forms') - - // 4. form_metas 삭제 + deletedCounts.forms = deletedForms.rowCount || 0 + console.log('Deleted forms:', deletedCounts.forms) + + // 11. formMetas 삭제 const deletedMetas = await db.delete(formMetas) - console.log('Deleted form metas') - - return Response.json({ - success: true, + deletedCounts.formMetas = deletedMetas.rowCount || 0 + console.log('Deleted form metas:', deletedCounts.formMetas) + + console.log('All test data cleared successfully') + + return Response.json({ + success: true, message: 'All test data cleared successfully', - deleted: { - formEntries: deletedEntries, - tags: deletedTags, - forms: deletedForms, - formMetas: deletedMetas - } + deleted: deletedCounts, + totalDeleted: Object.values(deletedCounts).reduce((sum, count) => sum + count, 0) }) + } catch (error) { console.error('Error clearing test data:', error) - return Response.json({ - error: 'Failed to clear data', + return Response.json({ + error: 'Failed to clear data', details: error instanceof Error ? error.message : 'Unknown error' }, { status: 500 }) } @@ -47,14 +110,27 @@ export async function DELETE(request: NextRequest) { // GET 요청도 지원 (브라우저에서 직접 접근 시) export async function GET() { if (process.env.NODE_ENV !== 'development') { - return Response.json({ - error: 'Not allowed in production' + return Response.json({ + error: 'Not allowed in production' }, { status: 403 }) } return Response.json({ message: 'Use DELETE method to clear test data', endpoint: '/api/admin/clear-test-data', - method: 'DELETE' + method: 'DELETE', + tables: [ + 'tagClassAttributes', + 'tagClasses', + 'tagSubfieldOptions', + 'tagSubfields', + 'tagTypes', + 'tagTypeClassFormMappings', + 'vendorDataReportTemps', + 'formEntries', + 'tags', + 'forms', + 'formMetas' + ] }) }
\ No newline at end of file |
