summaryrefslogtreecommitdiff
path: root/lib/dolce/table
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dolce/table')
-rw-r--r--lib/dolce/table/detail-drawing-columns.tsx80
-rw-r--r--lib/dolce/table/drawing-list-columns.tsx87
-rw-r--r--lib/dolce/table/drawing-list-table.tsx144
-rw-r--r--lib/dolce/table/file-list-columns.tsx70
-rw-r--r--lib/dolce/table/gtt-drawing-list-columns.tsx166
5 files changed, 547 insertions, 0 deletions
diff --git a/lib/dolce/table/detail-drawing-columns.tsx b/lib/dolce/table/detail-drawing-columns.tsx
new file mode 100644
index 00000000..7f519179
--- /dev/null
+++ b/lib/dolce/table/detail-drawing-columns.tsx
@@ -0,0 +1,80 @@
+"use client";
+
+import { ColumnDef } from "@tanstack/react-table";
+import { DetailDwgReceiptItem } from "../actions";
+
+export const detailDrawingColumns: ColumnDef<DetailDwgReceiptItem>[] = [
+ {
+ accessorKey: "RegisterSerialNo",
+ header: "일련번호",
+ minSize: 80,
+ cell: ({ row }) => {
+ return <div className="text-center">{row.getValue("RegisterSerialNo")}</div>;
+ },
+ },
+ {
+ accessorKey: "DrawingRevNo",
+ header: "Revision",
+ minSize: 100,
+ cell: ({ row }) => {
+ return <div className="font-medium">{row.getValue("DrawingRevNo")}</div>;
+ },
+ },
+ {
+ accessorKey: "Status",
+ header: "상태",
+ minSize: 120,
+ cell: ({ row }) => {
+ return <div className="text-center">{row.getValue("Status")}</div>;
+ },
+ },
+ {
+ accessorKey: "CategoryENM",
+ header: "카테고리",
+ minSize: 120,
+ cell: ({ row }) => {
+ const categoryENM = row.getValue("CategoryENM") as string;
+ const categoryNM = row.original.CategoryNM;
+ return <div>{categoryENM || categoryNM}</div>;
+ },
+ },
+ {
+ accessorKey: "DrawingUsageENM",
+ header: "도면용도",
+ minSize: 100,
+ cell: ({ row }) => {
+ const usageENM = row.getValue("DrawingUsageENM") as string | null;
+ const usageNM = row.original.DrawingUsageNM;
+ return <div>{usageENM || usageNM}</div>;
+ },
+ },
+ {
+ accessorKey: "RegisterKindENM",
+ header: "등록종류",
+ minSize: 180,
+ cell: ({ row }) => {
+ const kindENM = row.getValue("RegisterKindENM") as string | null;
+ const kindNM = row.original.RegisterKindNM;
+ return <div>{kindENM || kindNM}</div>;
+ },
+ },
+ {
+ accessorKey: "CreateUserNM",
+ header: "생성자",
+ minSize: 150,
+ cell: ({ row }) => {
+ const userENM = row.original.CreateUserENM;
+ const userNM = row.getValue("CreateUserNM") as string;
+ return <div>{userENM || userNM}</div>;
+ },
+ },
+ {
+ accessorKey: "CreateDt",
+ header: "생성일시",
+ minSize: 200,
+ cell: ({ row }) => {
+ return <div className="text-sm text-muted-foreground">{row.getValue("CreateDt")}</div>;
+ },
+ },
+];
+
diff --git a/lib/dolce/table/drawing-list-columns.tsx b/lib/dolce/table/drawing-list-columns.tsx
new file mode 100644
index 00000000..0e18266d
--- /dev/null
+++ b/lib/dolce/table/drawing-list-columns.tsx
@@ -0,0 +1,87 @@
+"use client";
+
+import { ColumnDef } from "@tanstack/react-table";
+import { DwgReceiptItem } from "../actions";
+
+export const drawingListColumns: ColumnDef<DwgReceiptItem>[] = [
+ {
+ accessorKey: "DrawingNo",
+ header: "도면번호",
+ minSize: 200,
+ cell: ({ row }) => {
+ return <div className="font-medium">{row.getValue("DrawingNo")}</div>;
+ },
+ },
+ {
+ accessorKey: "DrawingName",
+ header: "도면명",
+ minSize: 400,
+ cell: ({ row }) => {
+ return <div>{row.getValue("DrawingName")}</div>;
+ },
+ },
+ {
+ accessorKey: "Discipline",
+ header: "설계공종",
+ minSize: 80,
+ },
+ {
+ accessorKey: "Manager",
+ header: "담당자명",
+ minSize: 200,
+ cell: ({ row }) => {
+ const managerENM = row.original.ManagerENM;
+ const manager = row.getValue("Manager");
+ return <div>{managerENM || manager}</div>;
+ },
+ },
+ {
+ accessorKey: "AppDwg_PlanDate",
+ header: "승인도면 예정일",
+ minSize: 140,
+ cell: ({ row }) => {
+ const date = row.getValue("AppDwg_PlanDate") as string;
+ if (!date || date.length !== 8) return null;
+ return `${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6, 8)}`;
+ },
+ },
+ {
+ accessorKey: "AppDwg_ResultDate",
+ header: "승인도면 결과일",
+ minSize: 140,
+ cell: ({ row }) => {
+ const date = row.getValue("AppDwg_ResultDate") as string;
+ if (!date || date.length !== 8) return null;
+ return `${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6, 8)}`;
+ },
+ },
+ {
+ accessorKey: "WorDwg_PlanDate",
+ header: "작업도면 예정일",
+ minSize: 140,
+ cell: ({ row }) => {
+ const date = row.getValue("WorDwg_PlanDate") as string;
+ if (!date || date.length !== 8) return null;
+ return `${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6, 8)}`;
+ },
+ },
+ {
+ accessorKey: "WorDwg_ResultDate",
+ header: "작업도면 결과일",
+ minSize: 140,
+ cell: ({ row }) => {
+ const date = row.getValue("WorDwg_ResultDate") as string;
+ if (!date || date.length !== 8) return null;
+ return `${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6, 8)}`;
+ },
+ },
+ {
+ accessorKey: "CreateDt",
+ header: "생성일시",
+ minSize: 200,
+ cell: ({ row }) => {
+ return <div className="text-sm text-muted-foreground">{row.getValue("CreateDt")}</div>;
+ },
+ },
+];
+
diff --git a/lib/dolce/table/drawing-list-table.tsx b/lib/dolce/table/drawing-list-table.tsx
new file mode 100644
index 00000000..cc01f8ba
--- /dev/null
+++ b/lib/dolce/table/drawing-list-table.tsx
@@ -0,0 +1,144 @@
+"use client";
+
+import {
+ ColumnDef,
+ flexRender,
+ getCoreRowModel,
+ useReactTable,
+ getSortedRowModel,
+ SortingState,
+} from "@tanstack/react-table";
+import { useState } from "react";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table";
+import { ArrowUpDown, ArrowUp, ArrowDown } from "lucide-react";
+
+interface DrawingListTableProps<TData, TValue> {
+ columns: ColumnDef<TData, TValue>[];
+ data: TData[];
+ onRowClick?: (row: TData) => void;
+ selectedRow?: TData;
+ getRowId?: (row: TData) => string;
+}
+
+export function DrawingListTable<TData, TValue>({
+ columns,
+ data,
+ onRowClick,
+ selectedRow,
+ getRowId,
+}: DrawingListTableProps<TData, TValue>) {
+ const [sorting, setSorting] = useState<SortingState>([]);
+
+ const table = useReactTable({
+ data,
+ columns,
+ getCoreRowModel: getCoreRowModel(),
+ getSortedRowModel: getSortedRowModel(),
+ onSortingChange: setSorting,
+ state: {
+ sorting,
+ },
+ });
+
+ // 행이 선택되었는지 확인하는 함수
+ const isRowSelected = (row: TData): boolean => {
+ if (!selectedRow || !getRowId) return false;
+ return getRowId(row) === getRowId(selectedRow);
+ };
+
+ return (
+ <div className="rounded-md border overflow-x-auto max-w-full max-h-[600px] overflow-y-auto">
+ <Table className="min-w-max">
+ <TableHeader className="sticky top-0 z-10 bg-background">
+ {table.getHeaderGroups().map((headerGroup) => (
+ <TableRow key={headerGroup.id}>
+ {headerGroup.headers.map((header) => {
+ const isSorted = header.column.getIsSorted();
+ const canSort = header.column.getCanSort();
+
+ return (
+ <TableHead
+ key={header.id}
+ style={{ minWidth: header.column.columnDef.minSize }}
+ className="bg-background"
+ >
+ {header.isPlaceholder ? null : (
+ <div
+ className={`flex items-center gap-2 ${
+ canSort ? "cursor-pointer select-none hover:text-primary" : ""
+ }`}
+ onClick={
+ canSort
+ ? header.column.getToggleSortingHandler()
+ : undefined
+ }
+ >
+ {flexRender(
+ header.column.columnDef.header,
+ header.getContext()
+ )}
+ {canSort && (
+ <span className="text-muted-foreground">
+ {isSorted === "asc" ? (
+ <ArrowUp className="h-4 w-4" />
+ ) : isSorted === "desc" ? (
+ <ArrowDown className="h-4 w-4" />
+ ) : (
+ <ArrowUpDown className="h-4 w-4 opacity-50" />
+ )}
+ </span>
+ )}
+ </div>
+ )}
+ </TableHead>
+ );
+ })}
+ </TableRow>
+ ))}
+ </TableHeader>
+ <TableBody>
+ {table.getRowModel().rows?.length ? (
+ table.getRowModel().rows.map((row) => {
+ const isSelected = isRowSelected(row.original);
+ return (
+ <TableRow
+ key={row.id}
+ data-state={row.getIsSelected() && "selected"}
+ onClick={() => onRowClick?.(row.original)}
+ className={`cursor-pointer transition-colors ${
+ isSelected
+ ? "bg-accent hover:bg-accent"
+ : "hover:bg-muted/50"
+ }`}
+ >
+ {row.getVisibleCells().map((cell) => (
+ <TableCell
+ key={cell.id}
+ style={{ minWidth: cell.column.columnDef.minSize }}
+ >
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
+ </TableCell>
+ ))}
+ </TableRow>
+ );
+ })
+ ) : (
+ <TableRow>
+ <TableCell colSpan={columns.length} className="h-24 text-center">
+ 데이터가 없습니다.
+ </TableCell>
+ </TableRow>
+ )}
+ </TableBody>
+ </Table>
+ </div>
+ );
+}
+
diff --git a/lib/dolce/table/file-list-columns.tsx b/lib/dolce/table/file-list-columns.tsx
new file mode 100644
index 00000000..f703d56d
--- /dev/null
+++ b/lib/dolce/table/file-list-columns.tsx
@@ -0,0 +1,70 @@
+"use client";
+
+import { ColumnDef } from "@tanstack/react-table";
+import { FileInfoItem } from "../actions";
+import { Button } from "@/components/ui/button";
+import { Download } from "lucide-react";
+
+interface FileListColumnsProps {
+ onDownload: (file: FileInfoItem) => void;
+}
+
+export const createFileListColumns = ({
+ onDownload,
+}: FileListColumnsProps): ColumnDef<FileInfoItem>[] => [
+ {
+ accessorKey: "FileSeq",
+ header: "순번",
+ minSize: 80,
+ cell: ({ row }) => {
+ return <div className="text-center">{row.getValue("FileSeq")}</div>;
+ },
+ },
+ {
+ accessorKey: "FileName",
+ header: "파일명",
+ minSize: 300,
+ cell: ({ row }) => {
+ return <div className="font-medium">{row.getValue("FileName")}</div>;
+ },
+ },
+ {
+ accessorKey: "FileSize",
+ header: "파일크기",
+ minSize: 100,
+ cell: ({ row }) => {
+ const size = parseInt(row.getValue("FileSize") as string);
+ if (isNaN(size) || size === 0) return "-";
+
+ if (size < 1024) return `${size} B`;
+ if (size < 1024 * 1024) return `${(size / 1024).toFixed(2)} KB`;
+ return `${(size / (1024 * 1024)).toFixed(2)} MB`;
+ },
+ },
+ {
+ accessorKey: "CreateDt",
+ header: "생성일시",
+ minSize: 200,
+ cell: ({ row }) => {
+ return <div className="text-sm text-muted-foreground">{row.getValue("CreateDt")}</div>;
+ },
+ },
+ {
+ id: "actions",
+ header: "다운로드",
+ minSize: 120,
+ cell: ({ row }) => {
+ return (
+ <Button
+ variant="outline"
+ size="sm"
+ onClick={() => onDownload(row.original)}
+ >
+ <Download className="h-4 w-4 mr-2" />
+ 다운로드
+ </Button>
+ );
+ },
+ },
+];
+
diff --git a/lib/dolce/table/gtt-drawing-list-columns.tsx b/lib/dolce/table/gtt-drawing-list-columns.tsx
new file mode 100644
index 00000000..2ff2d7e2
--- /dev/null
+++ b/lib/dolce/table/gtt-drawing-list-columns.tsx
@@ -0,0 +1,166 @@
+"use client";
+
+import { ColumnDef } from "@tanstack/react-table";
+import { GttDwgReceiptItem } from "../actions";
+
+// 날짜 포맷 헬퍼
+function formatDate(dateStr: string | null): string | null {
+ if (!dateStr || dateStr.length !== 8) return null;
+ return `${dateStr.substring(0, 4)}-${dateStr.substring(4, 6)}-${dateStr.substring(6, 8)}`;
+}
+
+// Document Type 필터
+export type DocumentType = "ALL" | "GTT_DELIVERABLES" | "SHI_INPUT";
+
+interface GttDrawingListColumnsOptions {
+ documentType: DocumentType;
+}
+
+export function createGttDrawingListColumns({
+ documentType,
+}: GttDrawingListColumnsOptions): ColumnDef<GttDwgReceiptItem>[] {
+ const baseColumns: ColumnDef<GttDwgReceiptItem>[] = [
+ {
+ accessorKey: "DrawingNo",
+ header: "도면번호",
+ minSize: 200,
+ cell: ({ row }) => {
+ return <div className="font-medium">{row.getValue("DrawingNo")}</div>;
+ },
+ },
+ {
+ accessorKey: "DrawingName",
+ header: "도면명",
+ minSize: 400,
+ cell: ({ row }) => {
+ return <div>{row.getValue("DrawingName")}</div>;
+ },
+ },
+ {
+ accessorKey: "Discipline",
+ header: "설계공종",
+ minSize: 80,
+ },
+ {
+ accessorKey: "Manager",
+ header: "담당자명",
+ minSize: 200,
+ cell: ({ row }) => {
+ const managerENM = row.original.ManagerENM;
+ const manager = row.getValue("Manager");
+ return <div>{managerENM || manager}</div>;
+ },
+ },
+ {
+ accessorKey: "DrawingMoveGbn",
+ header: "구분",
+ minSize: 120,
+ },
+ ];
+
+ // Document Type에 따른 날짜 컬럼
+ const dateColumns: ColumnDef<GttDwgReceiptItem>[] = [];
+
+ // ALL: 모든 컬럼 표시
+ if (documentType === "ALL") {
+ dateColumns.push(
+ {
+ accessorKey: "GTTInput_PlanDate",
+ header: "GTT Input 예정일",
+ minSize: 150,
+ cell: ({ row }) => formatDate(row.getValue("GTTInput_PlanDate")),
+ },
+ {
+ accessorKey: "GTTInput_ResultDate",
+ header: "GTT Input 결과일",
+ minSize: 150,
+ cell: ({ row }) => formatDate(row.getValue("GTTInput_ResultDate")),
+ },
+ {
+ accessorKey: "GTTPreDwg_PlanDate",
+ header: "GTT Pre 예정일",
+ minSize: 140,
+ cell: ({ row }) => formatDate(row.getValue("GTTPreDwg_PlanDate")),
+ },
+ {
+ accessorKey: "GTTPreDwg_ResultDate",
+ header: "GTT Pre 결과일",
+ minSize: 140,
+ cell: ({ row }) => formatDate(row.getValue("GTTPreDwg_ResultDate")),
+ },
+ {
+ accessorKey: "GTTWorkingDwg_PlanDate",
+ header: "GTT Working 예정일",
+ minSize: 160,
+ cell: ({ row }) => formatDate(row.getValue("GTTWorkingDwg_PlanDate")),
+ },
+ {
+ accessorKey: "GTTWorkingDwg_ResultDate",
+ header: "GTT Working 결과일",
+ minSize: 160,
+ cell: ({ row }) => formatDate(row.getValue("GTTWorkingDwg_ResultDate")),
+ }
+ );
+ }
+ // SHI_INPUT: 도면제출 (GTTInput만)
+ else if (documentType === "SHI_INPUT") {
+ dateColumns.push(
+ {
+ accessorKey: "GTTInput_PlanDate",
+ header: "Input 예정일",
+ minSize: 120,
+ cell: ({ row }) => formatDate(row.getValue("GTTInput_PlanDate")),
+ },
+ {
+ accessorKey: "GTTInput_ResultDate",
+ header: "Input 결과일",
+ minSize: 120,
+ cell: ({ row }) => formatDate(row.getValue("GTTInput_ResultDate")),
+ }
+ );
+ }
+ // GTT_DELIVERABLES: 도면입수 (Pre, Working)
+ else if (documentType === "GTT_DELIVERABLES") {
+ dateColumns.push(
+ {
+ accessorKey: "GTTPreDwg_PlanDate",
+ header: "Pre 예정일",
+ minSize: 120,
+ cell: ({ row }) => formatDate(row.getValue("GTTPreDwg_PlanDate")),
+ },
+ {
+ accessorKey: "GTTPreDwg_ResultDate",
+ header: "Pre 결과일",
+ minSize: 120,
+ cell: ({ row }) => formatDate(row.getValue("GTTPreDwg_ResultDate")),
+ },
+ {
+ accessorKey: "GTTWorkingDwg_PlanDate",
+ header: "Working 예정일",
+ minSize: 130,
+ cell: ({ row }) => formatDate(row.getValue("GTTWorkingDwg_PlanDate")),
+ },
+ {
+ accessorKey: "GTTWorkingDwg_ResultDate",
+ header: "Working 결과일",
+ minSize: 130,
+ cell: ({ row }) => formatDate(row.getValue("GTTWorkingDwg_ResultDate")),
+ }
+ );
+ }
+
+ // 생성일시 컬럼
+ const endColumns: ColumnDef<GttDwgReceiptItem>[] = [
+ {
+ accessorKey: "CreateDt",
+ header: "생성일시",
+ minSize: 200,
+ cell: ({ row }) => {
+ return <div className="text-sm text-muted-foreground">{row.getValue("CreateDt")}</div>;
+ },
+ },
+ ];
+
+ return [...baseColumns, ...dateColumns, ...endColumns];
+}
+