diff options
Diffstat (limited to 'lib/vendor-document-list/plant/upload/table.tsx')
| -rw-r--r-- | lib/vendor-document-list/plant/upload/table.tsx | 223 |
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 |
