From 53ad72732f781e6c6d5ddb3776ea47aec010af8e Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 4 Aug 2025 09:39:21 +0000 Subject: (최겸) PQ/실사 수정 및 개발 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/[lng]/evcp/(evcp)/pq-criteria/[id]/page.tsx | 81 ---- .../evcp/(evcp)/pq-criteria/[pqListId]/page.tsx | 68 ++++ app/[lng]/evcp/(evcp)/pq-criteria/page.tsx | 132 +++---- .../pq_new/[vendorId]/[submissionId]/page.tsx | 430 +++++++++++---------- app/[lng]/evcp/(evcp)/pq_new/page.tsx | 196 +++++----- app/[lng]/partners/pq/page.tsx | 9 +- app/[lng]/partners/pq_new/[id]/page.tsx | 3 + app/[lng]/partners/pq_new/page.tsx | 64 ++- app/[lng]/partners/site-visit/page.tsx | 30 ++ .../(procurement)/pq-criteria/[id]/page.tsx | 81 ---- .../(procurement)/pq-criteria/[pqListId]/page.tsx | 68 ++++ .../procurement/(procurement)/pq-criteria/page.tsx | 129 +++---- .../pq_new/[vendorId]/[submissionId]/page.tsx | 430 +++++++++++---------- .../procurement/(procurement)/pq_new/page.tsx | 193 ++++----- 14 files changed, 967 insertions(+), 947 deletions(-) delete mode 100644 app/[lng]/evcp/(evcp)/pq-criteria/[id]/page.tsx create mode 100644 app/[lng]/evcp/(evcp)/pq-criteria/[pqListId]/page.tsx create mode 100644 app/[lng]/partners/site-visit/page.tsx delete mode 100644 app/[lng]/procurement/(procurement)/pq-criteria/[id]/page.tsx create mode 100644 app/[lng]/procurement/(procurement)/pq-criteria/[pqListId]/page.tsx (limited to 'app') diff --git a/app/[lng]/evcp/(evcp)/pq-criteria/[id]/page.tsx b/app/[lng]/evcp/(evcp)/pq-criteria/[id]/page.tsx deleted file mode 100644 index 55b1e9df..00000000 --- a/app/[lng]/evcp/(evcp)/pq-criteria/[id]/page.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import * as React from "react" -import { type SearchParams } from "@/types/table" -import { getValidFilters } from "@/lib/data-table" -import { Skeleton } from "@/components/ui/skeleton" -import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" -import { Shell } from "@/components/shell" -import { searchParamsCache } from "@/lib/pq/validations" -import { getPQs } from "@/lib/pq/service" -import { PqsTable } from "@/lib/pq/table/pq-table" -import { ProjectSelectorWrapper } from "@/components/pq/project-select-wrapper" -import { notFound } from "next/navigation" - -interface ProjectPageProps { - params: { id: string } - searchParams: Promise -} - -export default async function ProjectPage(props: ProjectPageProps) { - const resolvedParams = await props.params - const id = resolvedParams.id - - const projectId = parseInt(id, 10) - - // 유효하지 않은 projectId 확인 - if (isNaN(projectId)) { - notFound() - } - - const searchParams = await props.searchParams - const search = searchParamsCache.parse(searchParams) - - // filters가 없는 경우를 처리 - const validFilters = getValidFilters(search.filters) - - // 프로젝트별 PQ 데이터 가져오기 - const promises = Promise.all([ - getPQs({ - ...search, - filters: validFilters, - }, projectId, false) - ]) - - return ( - -
-
-

- Pre-Qualification Check Sheet -

-

- 협력업체 등록을 위한, 협력업체가 제출할 PQ 항목을: 프로젝트별로 관리할 수 있습니다. -

-
- -
- - }> - {/* */} - - - - } - > - - -
- ) -} \ No newline at end of file diff --git a/app/[lng]/evcp/(evcp)/pq-criteria/[pqListId]/page.tsx b/app/[lng]/evcp/(evcp)/pq-criteria/[pqListId]/page.tsx new file mode 100644 index 00000000..15cb3bf3 --- /dev/null +++ b/app/[lng]/evcp/(evcp)/pq-criteria/[pqListId]/page.tsx @@ -0,0 +1,68 @@ +import * as React from "react" +import { type SearchParams } from "@/types/table" +import { getValidFilters } from "@/lib/data-table" +import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" +import { Shell } from "@/components/shell" +import { searchParamsCache } from "@/lib/pq/validations" +import { getPQsByListId } from "@/lib/pq/service" +import { PqsTable } from "@/lib/pq/pq-criteria/pq-table" +import { notFound } from "next/navigation" + +interface PQDetailPageProps { + params: Promise<{ pqListId: string }> + searchParams: Promise +} + +export default async function PQDetailPage(props: PQDetailPageProps) { + const params = await props.params + const searchParams = await props.searchParams + const search = searchParamsCache.parse(searchParams) + + const pqListId = parseInt(params.pqListId) + if (isNaN(pqListId)) { + notFound() + } + + // filters가 없는 경우를 처리 + const validFilters = getValidFilters(search.filters) + + // PQ 항목들 가져오기 + const promises = Promise.all([ + getPQsByListId(pqListId, { + ...search, + filters: validFilters, + }) + ]) + + return ( + +
+
+

+ PQ 항목 관리 +

+ {/*

+ 선택한 PQ 목록의 세부 항목들을 관리할 수 있습니다. +

*/} +
+
+ + + } + > + + +
+ ) +} \ No newline at end of file diff --git a/app/[lng]/evcp/(evcp)/pq-criteria/page.tsx b/app/[lng]/evcp/(evcp)/pq-criteria/page.tsx index 20d16085..1a337cc9 100644 --- a/app/[lng]/evcp/(evcp)/pq-criteria/page.tsx +++ b/app/[lng]/evcp/(evcp)/pq-criteria/page.tsx @@ -1,73 +1,61 @@ -import * as React from "react" -import { type SearchParams } from "@/types/table" -import { getValidFilters } from "@/lib/data-table" -import { Skeleton } from "@/components/ui/skeleton" -import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" -import { Shell } from "@/components/shell" -import { searchParamsCache } from "@/lib/pq/validations" -import { getPQs } from "@/lib/pq/service" -import { PqsTable } from "@/lib/pq/table/pq-table" -import { ProjectSelectorWrapper } from "@/components/pq/project-select-wrapper" -import { InformationButton } from "@/components/information/information-button" -interface IndexPageProps { - searchParams: Promise -} - -export default async function IndexPage(props: IndexPageProps) { - const searchParams = await props.searchParams - const search = searchParamsCache.parse(searchParams) - - // filters가 없는 경우를 처리 - - const validFilters = getValidFilters(search.filters) - - // onlyGeneral: true로 설정하여 일반 PQ 항목만 가져옴 - const promises = Promise.all([ - getPQs({ - ...search, - filters: validFilters, - }, null, true) - ]) - - return ( - -
-
-
-

- PQ 항목 관리 -

- -
- {/*

- 협력업체 등록을 위한, 협력업체가 제출할 PQ 항목을 관리할 수 있습니다. -

*/} -
- -
- - }> - {/* */} - - - - } - > - - -
- ) +import * as React from "react" +import { type SearchParams } from "@/types/table" +import { getValidFilters } from "@/lib/data-table" +import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" +import { Shell } from "@/components/shell" +import { searchParamsCache } from "@/lib/pq/validations" +import { getPQLists } from "@/lib/pq/service" +import { PqListsTable } from "@/lib/pq/table/pq-lists-table" +import { getProjects } from "@/lib/pq/service" + +interface ProjectPageProps { + searchParams: Promise +} + +export default async function ProjectPage(props: ProjectPageProps) { + const searchParams = await props.searchParams + const search = searchParamsCache.parse(searchParams) + + // filters가 없는 경우를 처리 + const validFilters = getValidFilters(search.filters) + + // // 프로젝트별 PQ 데이터 가져오기 + const promises = Promise.all([ + getPQLists({ + ...search, + filters: validFilters, + }), + getProjects() + ]) + + return ( + +
+
+

+ PQ 리스트 관리 +

+ {/*

+ 협력업체 등록을 위한, 협력업체가 제출할 PQ 항목을: 프로젝트별로 관리할 수 있습니다. +

*/} +
+
+ + + } + > + + +
+ ) } \ No newline at end of file diff --git a/app/[lng]/evcp/(evcp)/pq_new/[vendorId]/[submissionId]/page.tsx b/app/[lng]/evcp/(evcp)/pq_new/[vendorId]/[submissionId]/page.tsx index 28ce3128..bd8d2347 100644 --- a/app/[lng]/evcp/(evcp)/pq_new/[vendorId]/[submissionId]/page.tsx +++ b/app/[lng]/evcp/(evcp)/pq_new/[vendorId]/[submissionId]/page.tsx @@ -1,215 +1,217 @@ -import * as React from "react" -import { Metadata } from "next" -import Link from "next/link" -import { notFound } from "next/navigation" -import { ArrowLeft } from "lucide-react" -import { Shell } from "@/components/shell" -import { Button } from "@/components/ui/button" -import { Badge } from "@/components/ui/badge" -import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" -import { Separator } from "@/components/ui/separator" -import { getPQById, getPQDataByVendorId } from "@/lib/pq/service" -import { unstable_noStore as noStore } from 'next/cache' -import { PQReviewWrapper } from "@/components/pq-input/pq-review-wrapper" - -export const metadata: Metadata = { - title: "PQ 검토", - description: "협력업체의 Pre-Qualification 답변을 검토합니다.", -} - -// 페이지가 기본적으로 동적임을 나타냄 -export const dynamic = "force-dynamic" - -interface PQReviewPageProps { - params: Promise<{ - vendorId: string; - submissionId: string; - }> -} - -export default async function PQReviewPage(props: PQReviewPageProps) { - // 캐시 비활성화 - noStore() - - const params = await props.params - const vendorId = parseInt(params.vendorId, 10) - const submissionId = parseInt(params.submissionId, 10) - - try { - // PQ Submission 정보 조회 - const pqSubmission = await getPQById(submissionId, vendorId) - - // PQ 데이터 조회 (질문과 답변) - const pqData = await getPQDataByVendorId(vendorId, pqSubmission.projectId || undefined) - - // 프로젝트 정보 (프로젝트 PQ인 경우) - const projectInfo = pqSubmission.projectId ? { - id: pqSubmission.projectId, - projectCode: pqSubmission.projectCode || '', - projectName: pqSubmission.projectName || '', - status: pqSubmission.status, - submittedAt: pqSubmission.submittedAt, - } : null - - // PQ 유형 및 상태 레이블 - const typeLabel = pqSubmission.type === "GENERAL" ? "일반 PQ" : "프로젝트 PQ" - const statusLabel = getStatusLabel(pqSubmission.status) - const statusVariant = getStatusVariant(pqSubmission.status) - - // 수정 가능 여부 (SUBMITTED 상태일 때만 가능) - const canReview = pqSubmission.status === "SUBMITTED" - - return ( - -
-
- -
-

- {pqSubmission.vendorName} - {typeLabel} -

-
- {statusLabel} - {projectInfo && ( - - {projectInfo.projectName} ({projectInfo.projectCode}) - - )} -
-
-
-
- - {/* 상태별 알림 */} - {pqSubmission.status === "SUBMITTED" && ( - - 제출 완료 - - 협력업체가 {formatDate(pqSubmission.submittedAt)}에 PQ를 제출했습니다. 검토 후 승인 또는 거부할 수 있습니다. - - - )} - - {pqSubmission.status === "APPROVED" && ( - - 승인됨 - - {formatDate(pqSubmission.approvedAt)}에 승인되었습니다. - - - )} - - {pqSubmission.status === "REJECTED" && ( - - 거부됨 - - {formatDate(pqSubmission.rejectedAt)}에 거부되었습니다. - {pqSubmission.rejectReason && ( -
- 사유: {pqSubmission.rejectReason} -
- )} -
-
- )} - - - - {/* PQ 검토 컴포넌트 */} - - - PQ 검토 - 협력업체 정보 - - - - - - - -
-

협력업체 정보

-
-
-

업체명

-

{pqSubmission.vendorName}

-
-
-

업체 코드

-

{pqSubmission.vendorCode}

-
-
-

상태

-

{pqSubmission.vendorStatus}

-
- {/* 필요시 추가 정보 표시 */} -
-
-
-
-
- ) - } catch (error) { - console.error("Error loading PQ:", error) - notFound() - } -} - -// 상태 레이블 함수 -function getStatusLabel(status: string): string { - switch (status) { - case "REQUESTED": - return "요청됨"; - case "IN_PROGRESS": - return "진행 중"; - case "SUBMITTED": - return "제출됨"; - case "APPROVED": - return "승인됨"; - case "REJECTED": - return "거부됨"; - default: - return status; - } -} - -// 상태별 Badge 스타일 -function getStatusVariant(status: string): "default" | "outline" | "secondary" | "destructive" | "success" { - switch (status) { - case "REQUESTED": - return "outline"; - case "IN_PROGRESS": - return "secondary"; - case "SUBMITTED": - return "default"; - case "APPROVED": - return "success"; - case "REJECTED": - return "destructive"; - default: - return "outline"; - } -} - -// 날짜 형식화 함수 -function formatDate(date: Date | null) { - if (!date) return "날짜 없음"; - return new Date(date).toLocaleDateString("ko-KR", { - year: "numeric", - month: "long", - day: "numeric", - hour: "2-digit", - minute: "2-digit" - }); +import * as React from "react" +import { Metadata } from "next" +import Link from "next/link" +import { notFound } from "next/navigation" +import { ArrowLeft } from "lucide-react" +import { Shell } from "@/components/shell" +import { Button } from "@/components/ui/button" +import { Badge } from "@/components/ui/badge" +import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" +import { Separator } from "@/components/ui/separator" +import { getPQById, getPQDataByVendorId } from "@/lib/pq/service" +import { unstable_noStore as noStore } from 'next/cache' +import { PQReviewWrapper } from "@/components/pq-input/pq-review-wrapper" + +export const metadata: Metadata = { + title: "PQ 검토", + description: "협력업체의 Pre-Qualification 답변을 검토합니다.", +} + +// 페이지가 기본적으로 동적임을 나타냄 +export const dynamic = "force-dynamic" + +interface PQReviewPageProps { + params: Promise<{ + vendorId: string; + submissionId: string; + }> +} + +export default async function PQReviewPage(props: PQReviewPageProps) { + // 캐시 비활성화 + noStore() + + const params = await props.params + const vendorId = parseInt(params.vendorId, 10) + const submissionId = parseInt(params.submissionId, 10) + + try { + // PQ Submission 정보 조회 + const pqSubmission = await getPQById(submissionId, vendorId) + + // PQ 데이터 조회 (질문과 답변) + const pqData = await getPQDataByVendorId(vendorId, pqSubmission.projectId || undefined) + + // 프로젝트 정보 (프로젝트 PQ인 경우) + const projectInfo = pqSubmission.projectId ? { + id: pqSubmission.projectId, + projectCode: pqSubmission.projectCode || '', + projectName: pqSubmission.projectName || '', + status: pqSubmission.status, + submittedAt: pqSubmission.submittedAt, + } : null + + // PQ 유형 및 상태 레이블 + const typeLabel = pqSubmission.type === "GENERAL" ? "일반 PQ" : + pqSubmission.type === "PROJECT" ? "프로젝트 PQ" : + pqSubmission.type === "NON_INSPECTION" ? "미실사 PQ" : "일반 PQ" + const statusLabel = getStatusLabel(pqSubmission.status) + const statusVariant = getStatusVariant(pqSubmission.status) + + // 수정 가능 여부 (SUBMITTED 상태일 때만 가능) + const canReview = pqSubmission.status === "SUBMITTED" + + return ( + +
+
+ +
+

+ {pqSubmission.vendorName} - {typeLabel} +

+
+ {statusLabel} + {projectInfo && ( + + {projectInfo.projectName} ({projectInfo.projectCode}) + + )} +
+
+
+
+ + {/* 상태별 알림 */} + {pqSubmission.status === "SUBMITTED" && ( + + 제출 완료 + + 협력업체가 {formatDate(pqSubmission.submittedAt)}에 PQ를 제출했습니다. 검토 후 승인 또는 거부할 수 있습니다. + + + )} + + {pqSubmission.status === "APPROVED" && ( + + 승인됨 + + {formatDate(pqSubmission.approvedAt)}에 승인되었습니다. + + + )} + + {pqSubmission.status === "REJECTED" && ( + + 거부됨 + + {formatDate(pqSubmission.rejectedAt)}에 거부되었습니다. + {pqSubmission.rejectReason && ( +
+ 사유: {pqSubmission.rejectReason} +
+ )} +
+
+ )} + + + + {/* PQ 검토 컴포넌트 */} + + + PQ 검토 + 협력업체 정보 + + + + + + + +
+

협력업체 정보

+
+
+

업체명

+

{pqSubmission.vendorName}

+
+
+

업체 코드

+

{pqSubmission.vendorCode}

+
+
+

상태

+

{pqSubmission.vendorStatus}

+
+ {/* 필요시 추가 정보 표시 */} +
+
+
+
+
+ ) + } catch (error) { + console.error("Error loading PQ:", error) + notFound() + } +} + +// 상태 레이블 함수 +function getStatusLabel(status: string): string { + switch (status) { + case "REQUESTED": + return "요청됨"; + case "IN_PROGRESS": + return "진행 중"; + case "SUBMITTED": + return "제출됨"; + case "APPROVED": + return "승인됨"; + case "REJECTED": + return "거부됨"; + default: + return status; + } +} + +// 상태별 Badge 스타일 +function getStatusVariant(status: string): "default" | "outline" | "secondary" | "destructive" | "success" { + switch (status) { + case "REQUESTED": + return "outline"; + case "IN_PROGRESS": + return "secondary"; + case "SUBMITTED": + return "default"; + case "APPROVED": + return "success"; + case "REJECTED": + return "destructive"; + default: + return "outline"; + } +} + +// 날짜 형식화 함수 +function formatDate(date: Date | null) { + if (!date) return "날짜 없음"; + return new Date(date).toLocaleDateString("ko-KR", { + year: "numeric", + month: "long", + day: "numeric", + hour: "2-digit", + minute: "2-digit" + }); } \ No newline at end of file diff --git a/app/[lng]/evcp/(evcp)/pq_new/page.tsx b/app/[lng]/evcp/(evcp)/pq_new/page.tsx index f2dddce5..0e6d3196 100644 --- a/app/[lng]/evcp/(evcp)/pq_new/page.tsx +++ b/app/[lng]/evcp/(evcp)/pq_new/page.tsx @@ -1,99 +1,99 @@ -import * as React from "react" -import { Metadata } from "next" -import { type SearchParams } from "@/types/table" -import { getValidFilters } from "@/lib/data-table" -import { Shell } from "@/components/shell" -import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" -import { searchParamsPQReviewCache } from "@/lib/pq/validations" -import { getPQSubmissions } from "@/lib/pq/service" -import { PQSubmissionsTable } from "@/lib/pq/pq-review-table-new/vendors-table" -import { InformationButton } from "@/components/information/information-button" -export const metadata: Metadata = { - title: "협력업체 PQ/실사 현황", - description: "", -} - -interface PQReviewPageProps { - searchParams: Promise -} - -export default async function PQReviewPage(props: PQReviewPageProps) { - const searchParams = await props.searchParams - const search = searchParamsPQReviewCache.parse(searchParams) - const validFilters = getValidFilters(search.filters) - - // 디버깅 로그 추가 - console.log("=== PQ Page Debug ==="); - console.log("Raw searchParams:", searchParams); - console.log("Raw basicFilters param:", searchParams.basicFilters); - console.log("Raw pqBasicFilters param:", searchParams.pqBasicFilters); - console.log("Parsed search:", search); - console.log("search.filters:", search.filters); - console.log("search.basicFilters:", search.basicFilters); - console.log("search.pqBasicFilters:", search.pqBasicFilters); - console.log("validFilters:", validFilters); - - // 기본 필터 처리 (통일된 이름 사용) - let basicFilters = [] - if (search.basicFilters && search.basicFilters.length > 0) { - basicFilters = search.basicFilters - console.log("Using search.basicFilters:", basicFilters); - } else if (search.pqBasicFilters && search.pqBasicFilters.length > 0) { - // 하위 호환성을 위해 기존 이름도 지원 - basicFilters = search.pqBasicFilters - console.log("Using search.pqBasicFilters:", basicFilters); - } else { - console.log("No basic filters found"); - } - - // 모든 필터를 합쳐서 처리 - const allFilters = [...validFilters, ...basicFilters] - - console.log("Final allFilters:", allFilters); - - // 조인 연산자도 통일된 이름 사용 - const joinOperator = search.basicJoinOperator || search.pqBasicJoinOperator || search.joinOperator || 'and'; - console.log("Final joinOperator:", joinOperator); - - // Promise.all로 감싸서 전달 - const promises = Promise.all([ - getPQSubmissions({ - ...search, - filters: allFilters, - joinOperator, - }) - ]) - - return ( - -
-
-
-
-

- 협력업체 PQ/실사 현황 -

- -
-
-
-
- - {/* Items처럼 직접 테이블 렌더링 */} - - } - > - - -
- ) +import * as React from "react" +import { Metadata } from "next" +import { type SearchParams } from "@/types/table" +import { getValidFilters } from "@/lib/data-table" +import { Shell } from "@/components/shell" +import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" +import { searchParamsPQReviewCache } from "@/lib/pq/validations" +import { getPQSubmissions } from "@/lib/pq/service" +import { PQSubmissionsTable } from "@/lib/pq/pq-review-table-new/vendors-table" +import { InformationButton } from "@/components/information/information-button" +export const metadata: Metadata = { + title: "PQ 검토/실사 의뢰", + description: "", +} + +interface PQReviewPageProps { + searchParams: Promise +} + +export default async function PQReviewPage(props: PQReviewPageProps) { + const searchParams = await props.searchParams + const search = searchParamsPQReviewCache.parse(searchParams) + const validFilters = getValidFilters(search.filters) + + // 디버깅 로그 추가 + console.log("=== PQ Page Debug ==="); + console.log("Raw searchParams:", searchParams); + console.log("Raw basicFilters param:", searchParams.basicFilters); + console.log("Raw pqBasicFilters param:", searchParams.pqBasicFilters); + console.log("Parsed search:", search); + console.log("search.filters:", search.filters); + console.log("search.basicFilters:", search.basicFilters); + console.log("search.pqBasicFilters:", search.pqBasicFilters); + console.log("validFilters:", validFilters); + + // 기본 필터 처리 (통일된 이름 사용) + let basicFilters = [] + if (search.basicFilters && search.basicFilters.length > 0) { + basicFilters = search.basicFilters + console.log("Using search.basicFilters:", basicFilters); + } else if (search.pqBasicFilters && search.pqBasicFilters.length > 0) { + // 하위 호환성을 위해 기존 이름도 지원 + basicFilters = search.pqBasicFilters + console.log("Using search.pqBasicFilters:", basicFilters); + } else { + console.log("No basic filters found"); + } + + // 모든 필터를 합쳐서 처리 + const allFilters = [...validFilters, ...basicFilters] + + console.log("Final allFilters:", allFilters); + + // 조인 연산자도 통일된 이름 사용 + const joinOperator = search.basicJoinOperator || search.pqBasicJoinOperator || search.joinOperator || 'and'; + console.log("Final joinOperator:", joinOperator); + + // Promise.all로 감싸서 전달 + const promises = Promise.all([ + getPQSubmissions({ + ...search, + filters: allFilters, + joinOperator, + }) + ]) + + return ( + +
+
+
+
+

+ PQ 검토/실사 의뢰 +

+ +
+
+
+
+ + {/* Items처럼 직접 테이블 렌더링 */} + + } + > + + +
+ ) } \ No newline at end of file diff --git a/app/[lng]/partners/pq/page.tsx b/app/[lng]/partners/pq/page.tsx index 71741c6c..87bcd409 100644 --- a/app/[lng]/partners/pq/page.tsx +++ b/app/[lng]/partners/pq/page.tsx @@ -10,11 +10,14 @@ export const dynamic = "force-dynamic" export default async function PQInputPage({ searchParams, }: { - searchParams: { projectId?: string } + searchParams: Promise<{ projectId?: string }> }) { // Opt out of caching for this route noStore() + // searchParams를 await + const resolvedSearchParams = await searchParams + // 세션 const session = await getServerSession(authOptions) // 세션에서 vendorId 가져오기 @@ -26,7 +29,7 @@ export default async function PQInputPage({ const projectPQs = await getPQProjectsByVendorId(idAsNumber) // searchParams에서 projectId 파싱 - const projectIdParam = searchParams.projectId + const projectIdParam = resolvedSearchParams.projectId const projectId = projectIdParam ? parseInt(projectIdParam, 10) : undefined // 현재 선택된 프로젝트를 위한 PQ 데이터 가져오기 @@ -40,7 +43,7 @@ export default async function PQInputPage({ pqData={selectedProjectPQData} projectPQs={projectPQs} vendorId={idAsNumber} - rawSearchParams={searchParams} + rawSearchParams={resolvedSearchParams} /> ) } \ No newline at end of file diff --git a/app/[lng]/partners/pq_new/[id]/page.tsx b/app/[lng]/partners/pq_new/[id]/page.tsx index 52085163..41c59b47 100644 --- a/app/[lng]/partners/pq_new/[id]/page.tsx +++ b/app/[lng]/partners/pq_new/[id]/page.tsx @@ -110,11 +110,14 @@ export default async function PQEditPage(props: PQEditPageProps) { const pageTitle = pqSubmission.type === "PROJECT" ? `프로젝트 PQ - ${pqSubmission.projectName || pqSubmission.projectCode}` + : pqSubmission.type === "NON_INSPECTION" + ? "미실사 PQ" : "일반 PQ"; // 프로젝트 정보 (프로젝트 PQ인 경우) const projectPQ = pqSubmission.projectId ? { id: pqSubmission.projectId, + projectId: pqSubmission.projectId, projectCode: pqSubmission.projectCode || '', projectName: pqSubmission.projectName || '', status: pqSubmission.status, diff --git a/app/[lng]/partners/pq_new/page.tsx b/app/[lng]/partners/pq_new/page.tsx index f822eacc..389a35a2 100644 --- a/app/[lng]/partners/pq_new/page.tsx +++ b/app/[lng]/partners/pq_new/page.tsx @@ -6,7 +6,7 @@ import { authOptions } from "@/app/api/auth/[...nextauth]/route"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; -import { LogIn, Edit, Eye } from "lucide-react"; +import { LogIn, Edit, Eye, Ellipsis } from "lucide-react"; import { Shell } from "@/components/shell"; import { Table, @@ -19,6 +19,13 @@ import { import { unstable_noStore as noStore } from 'next/cache'; import { getAllPQsByVendorId, getPQStatusCounts } from "@/lib/pq/service"; import { InformationButton } from "@/components/information/information-button"; +import { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, +} from "@/components/ui/dropdown-menu"; + export const metadata: Metadata = { title: "사전 평가 (PQ) 목록", description: "요청된 사전 평가 목록을 확인하고 작성합니다.", @@ -218,8 +225,14 @@ export default async function PQListPage() { return ( - - {pq.type === "PROJECT" ? "프로젝트" : "일반"} + + {pq.type === "PROJECT" ? "프로젝트" : + pq.type === "NON_INSPECTION" ? "미실사" : + "일반"} @@ -238,24 +251,35 @@ export default async function PQListPage() { {getFormattedDate(pq.approvedAt)} -
- {canEdit && ( - - )} - {canView && ( - - )} -
+ + + {canEdit && ( + + + + 작성 + + + )} + {canView && ( + + + + 보기 + + + )} + +
); diff --git a/app/[lng]/partners/site-visit/page.tsx b/app/[lng]/partners/site-visit/page.tsx new file mode 100644 index 00000000..92580b35 --- /dev/null +++ b/app/[lng]/partners/site-visit/page.tsx @@ -0,0 +1,30 @@ +import { getServerSession } from "next-auth" +import { authOptions } from "@/app/api/auth/[...nextauth]/route" +import { getSiteVisitRequestsByVendorId } from "@/lib/site-visit/service" +import { ClientSiteVisitWrapper } from "@/lib/site-visit/client-site-visit-wrapper" +import { unstable_noStore as noStore } from 'next/cache' + +// 페이지가 기본적으로 동적임을 나타냄 +export const dynamic = "force-dynamic" + +export default async function SiteVisitPage() { + // Opt out of caching for this route + noStore() + + // 세션 + const session = await getServerSession(authOptions) + // 세션에서 vendorId 가져오기 + const vendorId = session?.user.companyId + const idAsNumber = Number(vendorId) + + // 방문실사 요청 목록 가져오기 + const siteVisitRequests = await getSiteVisitRequestsByVendorId(idAsNumber) + + // 클라이언트 컴포넌트로 데이터 전달 + return ( + + ) +} \ No newline at end of file diff --git a/app/[lng]/procurement/(procurement)/pq-criteria/[id]/page.tsx b/app/[lng]/procurement/(procurement)/pq-criteria/[id]/page.tsx deleted file mode 100644 index 55b1e9df..00000000 --- a/app/[lng]/procurement/(procurement)/pq-criteria/[id]/page.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import * as React from "react" -import { type SearchParams } from "@/types/table" -import { getValidFilters } from "@/lib/data-table" -import { Skeleton } from "@/components/ui/skeleton" -import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" -import { Shell } from "@/components/shell" -import { searchParamsCache } from "@/lib/pq/validations" -import { getPQs } from "@/lib/pq/service" -import { PqsTable } from "@/lib/pq/table/pq-table" -import { ProjectSelectorWrapper } from "@/components/pq/project-select-wrapper" -import { notFound } from "next/navigation" - -interface ProjectPageProps { - params: { id: string } - searchParams: Promise -} - -export default async function ProjectPage(props: ProjectPageProps) { - const resolvedParams = await props.params - const id = resolvedParams.id - - const projectId = parseInt(id, 10) - - // 유효하지 않은 projectId 확인 - if (isNaN(projectId)) { - notFound() - } - - const searchParams = await props.searchParams - const search = searchParamsCache.parse(searchParams) - - // filters가 없는 경우를 처리 - const validFilters = getValidFilters(search.filters) - - // 프로젝트별 PQ 데이터 가져오기 - const promises = Promise.all([ - getPQs({ - ...search, - filters: validFilters, - }, projectId, false) - ]) - - return ( - -
-
-

- Pre-Qualification Check Sheet -

-

- 협력업체 등록을 위한, 협력업체가 제출할 PQ 항목을: 프로젝트별로 관리할 수 있습니다. -

-
- -
- - }> - {/* */} - - - - } - > - - -
- ) -} \ No newline at end of file diff --git a/app/[lng]/procurement/(procurement)/pq-criteria/[pqListId]/page.tsx b/app/[lng]/procurement/(procurement)/pq-criteria/[pqListId]/page.tsx new file mode 100644 index 00000000..15cb3bf3 --- /dev/null +++ b/app/[lng]/procurement/(procurement)/pq-criteria/[pqListId]/page.tsx @@ -0,0 +1,68 @@ +import * as React from "react" +import { type SearchParams } from "@/types/table" +import { getValidFilters } from "@/lib/data-table" +import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" +import { Shell } from "@/components/shell" +import { searchParamsCache } from "@/lib/pq/validations" +import { getPQsByListId } from "@/lib/pq/service" +import { PqsTable } from "@/lib/pq/pq-criteria/pq-table" +import { notFound } from "next/navigation" + +interface PQDetailPageProps { + params: Promise<{ pqListId: string }> + searchParams: Promise +} + +export default async function PQDetailPage(props: PQDetailPageProps) { + const params = await props.params + const searchParams = await props.searchParams + const search = searchParamsCache.parse(searchParams) + + const pqListId = parseInt(params.pqListId) + if (isNaN(pqListId)) { + notFound() + } + + // filters가 없는 경우를 처리 + const validFilters = getValidFilters(search.filters) + + // PQ 항목들 가져오기 + const promises = Promise.all([ + getPQsByListId(pqListId, { + ...search, + filters: validFilters, + }) + ]) + + return ( + +
+
+

+ PQ 항목 관리 +

+ {/*

+ 선택한 PQ 목록의 세부 항목들을 관리할 수 있습니다. +

*/} +
+
+ + + } + > + + +
+ ) +} \ No newline at end of file diff --git a/app/[lng]/procurement/(procurement)/pq-criteria/page.tsx b/app/[lng]/procurement/(procurement)/pq-criteria/page.tsx index 4d2f2d0c..1a337cc9 100644 --- a/app/[lng]/procurement/(procurement)/pq-criteria/page.tsx +++ b/app/[lng]/procurement/(procurement)/pq-criteria/page.tsx @@ -1,70 +1,61 @@ -import * as React from "react" -import { type SearchParams } from "@/types/table" -import { getValidFilters } from "@/lib/data-table" -import { Skeleton } from "@/components/ui/skeleton" -import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" -import { Shell } from "@/components/shell" -import { searchParamsCache } from "@/lib/pq/validations" -import { getPQs } from "@/lib/pq/service" -import { PqsTable } from "@/lib/pq/table/pq-table" -import { ProjectSelectorWrapper } from "@/components/pq/project-select-wrapper" - -interface IndexPageProps { - searchParams: Promise -} - -export default async function IndexPage(props: IndexPageProps) { - const searchParams = await props.searchParams - const search = searchParamsCache.parse(searchParams) - - // filters가 없는 경우를 처리 - - const validFilters = getValidFilters(search.filters) - - // onlyGeneral: true로 설정하여 일반 PQ 항목만 가져옴 - const promises = Promise.all([ - getPQs({ - ...search, - filters: validFilters, - }, null, true) - ]) - - return ( - -
-
-

- PQ 항목 관리 -

- {/*

- 협력업체 등록을 위한, 협력업체가 제출할 PQ 항목을 관리할 수 있습니다. -

*/} -
- -
- - }> - {/* */} - - - - } - > - - -
- ) +import * as React from "react" +import { type SearchParams } from "@/types/table" +import { getValidFilters } from "@/lib/data-table" +import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" +import { Shell } from "@/components/shell" +import { searchParamsCache } from "@/lib/pq/validations" +import { getPQLists } from "@/lib/pq/service" +import { PqListsTable } from "@/lib/pq/table/pq-lists-table" +import { getProjects } from "@/lib/pq/service" + +interface ProjectPageProps { + searchParams: Promise +} + +export default async function ProjectPage(props: ProjectPageProps) { + const searchParams = await props.searchParams + const search = searchParamsCache.parse(searchParams) + + // filters가 없는 경우를 처리 + const validFilters = getValidFilters(search.filters) + + // // 프로젝트별 PQ 데이터 가져오기 + const promises = Promise.all([ + getPQLists({ + ...search, + filters: validFilters, + }), + getProjects() + ]) + + return ( + +
+
+

+ PQ 리스트 관리 +

+ {/*

+ 협력업체 등록을 위한, 협력업체가 제출할 PQ 항목을: 프로젝트별로 관리할 수 있습니다. +

*/} +
+
+ + + } + > + + +
+ ) } \ No newline at end of file diff --git a/app/[lng]/procurement/(procurement)/pq_new/[vendorId]/[submissionId]/page.tsx b/app/[lng]/procurement/(procurement)/pq_new/[vendorId]/[submissionId]/page.tsx index 28ce3128..b82075e9 100644 --- a/app/[lng]/procurement/(procurement)/pq_new/[vendorId]/[submissionId]/page.tsx +++ b/app/[lng]/procurement/(procurement)/pq_new/[vendorId]/[submissionId]/page.tsx @@ -1,215 +1,217 @@ -import * as React from "react" -import { Metadata } from "next" -import Link from "next/link" -import { notFound } from "next/navigation" -import { ArrowLeft } from "lucide-react" -import { Shell } from "@/components/shell" -import { Button } from "@/components/ui/button" -import { Badge } from "@/components/ui/badge" -import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" -import { Separator } from "@/components/ui/separator" -import { getPQById, getPQDataByVendorId } from "@/lib/pq/service" -import { unstable_noStore as noStore } from 'next/cache' -import { PQReviewWrapper } from "@/components/pq-input/pq-review-wrapper" - -export const metadata: Metadata = { - title: "PQ 검토", - description: "협력업체의 Pre-Qualification 답변을 검토합니다.", -} - -// 페이지가 기본적으로 동적임을 나타냄 -export const dynamic = "force-dynamic" - -interface PQReviewPageProps { - params: Promise<{ - vendorId: string; - submissionId: string; - }> -} - -export default async function PQReviewPage(props: PQReviewPageProps) { - // 캐시 비활성화 - noStore() - - const params = await props.params - const vendorId = parseInt(params.vendorId, 10) - const submissionId = parseInt(params.submissionId, 10) - - try { - // PQ Submission 정보 조회 - const pqSubmission = await getPQById(submissionId, vendorId) - - // PQ 데이터 조회 (질문과 답변) - const pqData = await getPQDataByVendorId(vendorId, pqSubmission.projectId || undefined) - - // 프로젝트 정보 (프로젝트 PQ인 경우) - const projectInfo = pqSubmission.projectId ? { - id: pqSubmission.projectId, - projectCode: pqSubmission.projectCode || '', - projectName: pqSubmission.projectName || '', - status: pqSubmission.status, - submittedAt: pqSubmission.submittedAt, - } : null - - // PQ 유형 및 상태 레이블 - const typeLabel = pqSubmission.type === "GENERAL" ? "일반 PQ" : "프로젝트 PQ" - const statusLabel = getStatusLabel(pqSubmission.status) - const statusVariant = getStatusVariant(pqSubmission.status) - - // 수정 가능 여부 (SUBMITTED 상태일 때만 가능) - const canReview = pqSubmission.status === "SUBMITTED" - - return ( - -
-
- -
-

- {pqSubmission.vendorName} - {typeLabel} -

-
- {statusLabel} - {projectInfo && ( - - {projectInfo.projectName} ({projectInfo.projectCode}) - - )} -
-
-
-
- - {/* 상태별 알림 */} - {pqSubmission.status === "SUBMITTED" && ( - - 제출 완료 - - 협력업체가 {formatDate(pqSubmission.submittedAt)}에 PQ를 제출했습니다. 검토 후 승인 또는 거부할 수 있습니다. - - - )} - - {pqSubmission.status === "APPROVED" && ( - - 승인됨 - - {formatDate(pqSubmission.approvedAt)}에 승인되었습니다. - - - )} - - {pqSubmission.status === "REJECTED" && ( - - 거부됨 - - {formatDate(pqSubmission.rejectedAt)}에 거부되었습니다. - {pqSubmission.rejectReason && ( -
- 사유: {pqSubmission.rejectReason} -
- )} -
-
- )} - - - - {/* PQ 검토 컴포넌트 */} - - - PQ 검토 - 협력업체 정보 - - - - - - - -
-

협력업체 정보

-
-
-

업체명

-

{pqSubmission.vendorName}

-
-
-

업체 코드

-

{pqSubmission.vendorCode}

-
-
-

상태

-

{pqSubmission.vendorStatus}

-
- {/* 필요시 추가 정보 표시 */} -
-
-
-
-
- ) - } catch (error) { - console.error("Error loading PQ:", error) - notFound() - } -} - -// 상태 레이블 함수 -function getStatusLabel(status: string): string { - switch (status) { - case "REQUESTED": - return "요청됨"; - case "IN_PROGRESS": - return "진행 중"; - case "SUBMITTED": - return "제출됨"; - case "APPROVED": - return "승인됨"; - case "REJECTED": - return "거부됨"; - default: - return status; - } -} - -// 상태별 Badge 스타일 -function getStatusVariant(status: string): "default" | "outline" | "secondary" | "destructive" | "success" { - switch (status) { - case "REQUESTED": - return "outline"; - case "IN_PROGRESS": - return "secondary"; - case "SUBMITTED": - return "default"; - case "APPROVED": - return "success"; - case "REJECTED": - return "destructive"; - default: - return "outline"; - } -} - -// 날짜 형식화 함수 -function formatDate(date: Date | null) { - if (!date) return "날짜 없음"; - return new Date(date).toLocaleDateString("ko-KR", { - year: "numeric", - month: "long", - day: "numeric", - hour: "2-digit", - minute: "2-digit" - }); +import * as React from "react" +import { Metadata } from "next" +import Link from "next/link" +import { notFound } from "next/navigation" +import { ArrowLeft } from "lucide-react" +import { Shell } from "@/components/shell" +import { Button } from "@/components/ui/button" +import { Badge } from "@/components/ui/badge" +import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" +import { Separator } from "@/components/ui/separator" +import { getPQById, getPQDataByVendorId } from "@/lib/pq/service" +import { unstable_noStore as noStore } from 'next/cache' +import { PQReviewWrapper } from "@/components/pq-input/pq-review-wrapper" + +export const metadata: Metadata = { + title: "PQ 검토", + description: "협력업체의 Pre-Qualification 답변을 검토합니다.", +} + +// 페이지가 기본적으로 동적임을 나타냄 +export const dynamic = "force-dynamic" + +interface PQReviewPageProps { + params: Promise<{ + vendorId: string; + submissionId: string; + }> +} + +export default async function PQReviewPage(props: PQReviewPageProps) { + // 캐시 비활성화 + noStore() + + const params = await props.params + const vendorId = parseInt(params.vendorId, 10) + const submissionId = parseInt(params.submissionId, 10) + + try { + // PQ Submission 정보 조회 + const pqSubmission = await getPQById(submissionId, vendorId) + + // PQ 데이터 조회 (질문과 답변) + const pqData = await getPQDataByVendorId(vendorId, pqSubmission.projectId || undefined) + + // 프로젝트 정보 (프로젝트 PQ인 경우) + const projectInfo = pqSubmission.projectId ? { + id: pqSubmission.projectId, + projectCode: pqSubmission.projectCode || '', + projectName: pqSubmission.projectName || '', + status: pqSubmission.status, + submittedAt: pqSubmission.submittedAt, + } : null + + // PQ 유형 및 상태 레이블 + const typeLabel = pqSubmission.type === "GENERAL" ? "일반 PQ" : + pqSubmission.type === "PROJECT" ? "프로젝트 PQ" : + pqSubmission.type === "NON_INSPECTION" ? "미실사 PQ" : "일반 PQ" + const statusLabel = getStatusLabel(pqSubmission.status) + const statusVariant = getStatusVariant(pqSubmission.status) + + // 수정 가능 여부 (SUBMITTED 상태일 때만 가능) + const canReview = pqSubmission.status === "SUBMITTED" + + return ( + +
+
+ +
+

+ {pqSubmission.vendorName} - {typeLabel} +

+
+ {statusLabel} + {projectInfo && ( + + {projectInfo.projectName} ({projectInfo.projectCode}) + + )} +
+
+
+
+ + {/* 상태별 알림 */} + {pqSubmission.status === "SUBMITTED" && ( + + 제출 완료 + + 협력업체가 {formatDate(pqSubmission.submittedAt)}에 PQ를 제출했습니다. 검토 후 승인 또는 거부할 수 있습니다. + + + )} + + {pqSubmission.status === "APPROVED" && ( + + 승인됨 + + {formatDate(pqSubmission.approvedAt)}에 승인되었습니다. + + + )} + + {pqSubmission.status === "REJECTED" && ( + + 거부됨 + + {formatDate(pqSubmission.rejectedAt)}에 거부되었습니다. + {pqSubmission.rejectReason && ( +
+ 사유: {pqSubmission.rejectReason} +
+ )} +
+
+ )} + + + + {/* PQ 검토 컴포넌트 */} + + + PQ 검토 + 협력업체 정보 + + + + + + + +
+

협력업체 정보

+
+
+

업체명

+

{pqSubmission.vendorName}

+
+
+

업체 코드

+

{pqSubmission.vendorCode}

+
+
+

상태

+

{pqSubmission.vendorStatus}

+
+ {/* 필요시 추가 정보 표시 */} +
+
+
+
+
+ ) + } catch (error) { + console.error("Error loading PQ:", error) + notFound() + } +} + +// 상태 레이블 함수 +function getStatusLabel(status: string): string { + switch (status) { + case "REQUESTED": + return "요청됨"; + case "IN_PROGRESS": + return "진행 중"; + case "SUBMITTED": + return "제출됨"; + case "APPROVED": + return "승인됨"; + case "REJECTED": + return "거부됨"; + default: + return status; + } +} + +// 상태별 Badge 스타일 +function getStatusVariant(status: string): "default" | "outline" | "secondary" | "destructive" | "success" { + switch (status) { + case "REQUESTED": + return "outline"; + case "IN_PROGRESS": + return "secondary"; + case "SUBMITTED": + return "default"; + case "APPROVED": + return "success"; + case "REJECTED": + return "destructive"; + default: + return "outline"; + } +} + +// 날짜 형식화 함수 +function formatDate(date: Date | null) { + if (!date) return "날짜 없음"; + return new Date(date).toLocaleDateString("ko-KR", { + year: "numeric", + month: "long", + day: "numeric", + hour: "2-digit", + minute: "2-digit" + }); } \ No newline at end of file diff --git a/app/[lng]/procurement/(procurement)/pq_new/page.tsx b/app/[lng]/procurement/(procurement)/pq_new/page.tsx index 550ac87d..0e6d3196 100644 --- a/app/[lng]/procurement/(procurement)/pq_new/page.tsx +++ b/app/[lng]/procurement/(procurement)/pq_new/page.tsx @@ -1,96 +1,99 @@ -import * as React from "react" -import { Metadata } from "next" -import { type SearchParams } from "@/types/table" -import { getValidFilters } from "@/lib/data-table" -import { Shell } from "@/components/shell" -import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" -import { searchParamsPQReviewCache } from "@/lib/pq/validations" -import { getPQSubmissions } from "@/lib/pq/service" -import { PQSubmissionsTable } from "@/lib/pq/pq-review-table-new/vendors-table" - -export const metadata: Metadata = { - title: "협력업체 PQ/실사 현황", - description: "", -} - -interface PQReviewPageProps { - searchParams: Promise -} - -export default async function PQReviewPage(props: PQReviewPageProps) { - const searchParams = await props.searchParams - const search = searchParamsPQReviewCache.parse(searchParams) - const validFilters = getValidFilters(search.filters) - - // 디버깅 로그 추가 - console.log("=== PQ Page Debug ==="); - console.log("Raw searchParams:", searchParams); - console.log("Raw basicFilters param:", searchParams.basicFilters); - console.log("Raw pqBasicFilters param:", searchParams.pqBasicFilters); - console.log("Parsed search:", search); - console.log("search.filters:", search.filters); - console.log("search.basicFilters:", search.basicFilters); - console.log("search.pqBasicFilters:", search.pqBasicFilters); - console.log("validFilters:", validFilters); - - // 기본 필터 처리 (통일된 이름 사용) - let basicFilters = [] - if (search.basicFilters && search.basicFilters.length > 0) { - basicFilters = search.basicFilters - console.log("Using search.basicFilters:", basicFilters); - } else if (search.pqBasicFilters && search.pqBasicFilters.length > 0) { - // 하위 호환성을 위해 기존 이름도 지원 - basicFilters = search.pqBasicFilters - console.log("Using search.pqBasicFilters:", basicFilters); - } else { - console.log("No basic filters found"); - } - - // 모든 필터를 합쳐서 처리 - const allFilters = [...validFilters, ...basicFilters] - - console.log("Final allFilters:", allFilters); - - // 조인 연산자도 통일된 이름 사용 - const joinOperator = search.basicJoinOperator || search.pqBasicJoinOperator || search.joinOperator || 'and'; - console.log("Final joinOperator:", joinOperator); - - // Promise.all로 감싸서 전달 - const promises = Promise.all([ - getPQSubmissions({ - ...search, - filters: allFilters, - joinOperator, - }) - ]) - - return ( - -
-
-
-

- 협력업체 PQ/실사 현황 -

-
-
-
- - {/* Items처럼 직접 테이블 렌더링 */} - - } - > - - -
- ) +import * as React from "react" +import { Metadata } from "next" +import { type SearchParams } from "@/types/table" +import { getValidFilters } from "@/lib/data-table" +import { Shell } from "@/components/shell" +import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" +import { searchParamsPQReviewCache } from "@/lib/pq/validations" +import { getPQSubmissions } from "@/lib/pq/service" +import { PQSubmissionsTable } from "@/lib/pq/pq-review-table-new/vendors-table" +import { InformationButton } from "@/components/information/information-button" +export const metadata: Metadata = { + title: "PQ 검토/실사 의뢰", + description: "", +} + +interface PQReviewPageProps { + searchParams: Promise +} + +export default async function PQReviewPage(props: PQReviewPageProps) { + const searchParams = await props.searchParams + const search = searchParamsPQReviewCache.parse(searchParams) + const validFilters = getValidFilters(search.filters) + + // 디버깅 로그 추가 + console.log("=== PQ Page Debug ==="); + console.log("Raw searchParams:", searchParams); + console.log("Raw basicFilters param:", searchParams.basicFilters); + console.log("Raw pqBasicFilters param:", searchParams.pqBasicFilters); + console.log("Parsed search:", search); + console.log("search.filters:", search.filters); + console.log("search.basicFilters:", search.basicFilters); + console.log("search.pqBasicFilters:", search.pqBasicFilters); + console.log("validFilters:", validFilters); + + // 기본 필터 처리 (통일된 이름 사용) + let basicFilters = [] + if (search.basicFilters && search.basicFilters.length > 0) { + basicFilters = search.basicFilters + console.log("Using search.basicFilters:", basicFilters); + } else if (search.pqBasicFilters && search.pqBasicFilters.length > 0) { + // 하위 호환성을 위해 기존 이름도 지원 + basicFilters = search.pqBasicFilters + console.log("Using search.pqBasicFilters:", basicFilters); + } else { + console.log("No basic filters found"); + } + + // 모든 필터를 합쳐서 처리 + const allFilters = [...validFilters, ...basicFilters] + + console.log("Final allFilters:", allFilters); + + // 조인 연산자도 통일된 이름 사용 + const joinOperator = search.basicJoinOperator || search.pqBasicJoinOperator || search.joinOperator || 'and'; + console.log("Final joinOperator:", joinOperator); + + // Promise.all로 감싸서 전달 + const promises = Promise.all([ + getPQSubmissions({ + ...search, + filters: allFilters, + joinOperator, + }) + ]) + + return ( + +
+
+
+
+

+ PQ 검토/실사 의뢰 +

+ +
+
+
+
+ + {/* Items처럼 직접 테이블 렌더링 */} + + } + > + + +
+ ) } \ No newline at end of file -- cgit v1.2.3