summaryrefslogtreecommitdiff
path: root/lib/vendor-document-list/plant/upload/table.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-09-19 07:51:27 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-09-19 07:51:27 +0000
commit9ecdfb23fe3df6a5df86782385002c562dfc1198 (patch)
tree4188cb7e6bf2c862d9c86a59d79946bd41217227 /lib/vendor-document-list/plant/upload/table.tsx
parentb67861fbb424c7ad47ad1538f75e2945bd8890c5 (diff)
(대표님) rfq 히스토리, swp 등
Diffstat (limited to 'lib/vendor-document-list/plant/upload/table.tsx')
-rw-r--r--lib/vendor-document-list/plant/upload/table.tsx223
1 files changed, 223 insertions, 0 deletions
diff --git a/lib/vendor-document-list/plant/upload/table.tsx b/lib/vendor-document-list/plant/upload/table.tsx
new file mode 100644
index 00000000..92507900
--- /dev/null
+++ b/lib/vendor-document-list/plant/upload/table.tsx
@@ -0,0 +1,223 @@
+// lib/vendor-document-list/plant/upload/table.tsx
+"use client"
+
+import * as React from "react"
+import type {
+ DataTableAdvancedFilterField,
+ DataTableFilterField,
+ DataTableRowAction,
+} from "@/types/table"
+
+import { useDataTable } from "@/hooks/use-data-table"
+import { DataTable } from "@/components/data-table/data-table"
+import { DataTableAdvancedToolbar } from "@/components/data-table/data-table-advanced-toolbar"
+import { getColumns } from "./columns"
+import { getStageSubmissions } from "./service"
+import { StageSubmissionView } from "@/db/schema"
+import { StageSubmissionToolbarActions } from "./toolbar-actions"
+import { useRouter, useSearchParams, usePathname } from "next/navigation"
+import { ProjectFilter } from "./components/project-filter"
+import { SingleUploadDialog } from "./components/single-upload-dialog"
+import { HistoryDialog } from "./components/history-dialog"
+import { ViewSubmissionDialog } from "./components/view-submission-dialog"
+
+interface StageSubmissionsTableProps {
+ promises: Promise<[
+ Awaited<ReturnType<typeof getStageSubmissions>>,
+ { projects: Array<{ id: number; code: string }> }
+ ]>
+ selectedProjectId?: number | null
+}
+
+export function StageSubmissionsTable({ promises, selectedProjectId }: StageSubmissionsTableProps) {
+ const [{ data, pageCount }, { projects }] = React.use(promises)
+ const router = useRouter()
+ const pathname = usePathname()
+ const searchParams = useSearchParams()
+
+ const [rowAction, setRowAction] = React.useState<DataTableRowAction<StageSubmissionView> | null>(null)
+
+ const columns = React.useMemo(
+ () => getColumns({ setRowAction }),
+ [setRowAction]
+ )
+
+ // 프로젝트 필터 핸들러
+ const handleProjectChange = (projectId: number | null) => {
+ const current = new URLSearchParams(Array.from(searchParams.entries()))
+
+ if (projectId) {
+ current.set("projectId", projectId.toString())
+ } else {
+ current.delete("projectId")
+ }
+
+ // 페이지를 1로 리셋
+ current.set("page", "1")
+
+ const search = current.toString()
+ const query = search ? `?${search}` : ""
+
+ router.push(`${pathname}${query}`)
+ }
+
+ // Filter fields - 프로젝트 필터 제거
+ const filterFields: DataTableFilterField<StageSubmissionView>[] = [
+ {
+ id: "stageStatus",
+ label: "Stage Status",
+ options: [
+ { label: "Planned", value: "PLANNED" },
+ { label: "In Progress", value: "IN_PROGRESS" },
+ { label: "Submitted", value: "SUBMITTED" },
+ { label: "Approved", value: "APPROVED" },
+ { label: "Rejected", value: "REJECTED" },
+ { label: "Completed", value: "COMPLETED" },
+ ]
+ },
+ {
+ id: "latestSubmissionStatus",
+ label: "Submission Status",
+ options: [
+ { label: "Submitted", value: "SUBMITTED" },
+ { label: "Under Review", value: "UNDER_REVIEW" },
+ { label: "Draft", value: "DRAFT" },
+ { label: "Withdrawn", value: "WITHDRAWN" },
+ ]
+ },
+ {
+ id: "requiresSubmission",
+ label: "Requires Submission",
+ options: [
+ { label: "Yes", value: "true" },
+ { label: "No", value: "false" },
+ ]
+ },
+ {
+ id: "requiresSync",
+ label: "Requires Sync",
+ options: [
+ { label: "Yes", value: "true" },
+ { label: "No", value: "false" },
+ ]
+ },
+ {
+ id: "isOverdue",
+ label: "Overdue",
+ options: [
+ { label: "Yes", value: "true" },
+ { label: "No", value: "false" },
+ ]
+ }
+ ]
+
+ const advancedFilterFields: DataTableAdvancedFilterField<StageSubmissionView>[] = [
+ {
+ id: "docNumber",
+ label: "Doc Number",
+ type: "text",
+ },
+ {
+ id: "documentTitle",
+ label: "Document Title",
+ type: "text",
+ },
+ {
+ id: "stageName",
+ label: "Stage Name",
+ type: "text",
+ },
+ {
+ id: "stagePlanDate",
+ label: "Due Date",
+ type: "date",
+ },
+ {
+ id: "daysUntilDue",
+ label: "Days Until Due",
+ type: "number",
+ },
+ ]
+
+ const { table } = useDataTable({
+ data,
+ columns,
+ pageCount,
+ filterFields,
+ enablePinning: true,
+ enableAdvancedFilter: true,
+ initialState: {
+ sorting: [
+ { id: "isOverdue", desc: true },
+ { id: "daysUntilDue", desc: false }
+ ],
+ columnPinning: { right: ["actions"] },
+ },
+ getRowId: (originalRow) => `${originalRow.documentId}-${originalRow.stageId}`,
+ shallow: false,
+ clearOnDefault: true,
+ columnResizeMode: "onEnd",
+ })
+
+ return (
+ <>
+ <DataTable table={table}>
+ {/* 프로젝트 필터를 툴바 위에 배치 */}
+ <div className="flex items-center justify-between pb-3">
+ <ProjectFilter
+ projects={projects}
+ value={selectedProjectId}
+ onValueChange={handleProjectChange}
+ />
+ <div className="text-sm text-muted-foreground">
+ {data.length} record(s) found
+ </div>
+ </div>
+
+ <DataTableAdvancedToolbar
+ table={table}
+ filterFields={advancedFilterFields}
+ shallow={false}
+ >
+ <StageSubmissionToolbarActions
+ table={table}
+ rowAction={rowAction}
+ setRowAction={setRowAction}
+ />
+ </DataTableAdvancedToolbar>
+ </DataTable>
+
+ {/* Upload Dialog */}
+ {rowAction?.type === "upload" && (
+ <SingleUploadDialog
+ open={true}
+ onOpenChange={(open) => !open && setRowAction(null)}
+ submission={rowAction.row.original}
+ onUploadComplete={() => {
+ setRowAction(null)
+ // 테이블 새로고침
+ window.location.reload()
+ }}
+ />
+ )}
+
+ {/* View Submission Dialog */}
+ {rowAction?.type === "view" && (
+ <ViewSubmissionDialog
+ open={true}
+ onOpenChange={(open) => !open && setRowAction(null)}
+ submission={rowAction.row.original}
+ />
+ )}
+
+ {/* History Dialog */}
+ {rowAction?.type === "history" && (
+ <HistoryDialog
+ open={true}
+ onOpenChange={(open) => !open && setRowAction(null)}
+ submission={rowAction.row.original}
+ />
+ )}
+ </>
+ )
+} \ No newline at end of file