summaryrefslogtreecommitdiff
path: root/lib/rfq-last/table/rfq-table-columns.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rfq-last/table/rfq-table-columns.tsx')
-rw-r--r--lib/rfq-last/table/rfq-table-columns.tsx338
1 files changed, 337 insertions, 1 deletions
diff --git a/lib/rfq-last/table/rfq-table-columns.tsx b/lib/rfq-last/table/rfq-table-columns.tsx
index 62f14579..58c45aa0 100644
--- a/lib/rfq-last/table/rfq-table-columns.tsx
+++ b/lib/rfq-last/table/rfq-table-columns.tsx
@@ -24,7 +24,7 @@ type NextRouter = ReturnType<typeof useRouter>;
interface GetColumnsProps {
setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<RfqsLastView> | null>>;
- rfqCategory?: "general" | "itb" | "rfq";
+ rfqCategory?: "general" | "itb" | "rfq" | "pre_bidding";
router: NextRouter;
}
@@ -756,6 +756,342 @@ export function getRfqColumns({
}
// ═══════════════════════════════════════════════════════════════
+ // 사전견적(입찰) 컬럼 정의
+ // ═══════════════════════════════════════════════════════════════
+ if (rfqCategory === "pre_bidding") {
+ return [
+ // Checkbox
+ {
+ id: "select",
+ header: ({ table }) => (
+ <Checkbox
+ checked={table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && "indeterminate")}
+ onCheckedChange={(v) => table.toggleAllPageRowsSelected(!!v)}
+ aria-label="select all"
+ className="translate-y-0.5"
+ />
+ ),
+ cell: ({ row }) => (
+ <Checkbox
+ checked={row.getIsSelected()}
+ onCheckedChange={(v) => row.toggleSelected(!!v)}
+ aria-label="select row"
+ className="translate-y-0.5"
+ />
+ ),
+ size: 40,
+ enableSorting: false,
+ enableHiding: false,
+ },
+
+ // 견적 No.
+ {
+ accessorKey: "rfqCode",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적 No." />,
+ cell: ({ row }) => (
+ <span className="font-mono font-medium">{row.original.rfqCode}</span>
+ ),
+ size: 120,
+ },
+
+ // 입찰 No. (추가)
+ {
+ accessorKey: "biddingNumber",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="입찰 No." />,
+ cell: ({ row }) => (
+ <span className="font-mono font-medium">{row.original.biddingNumber || "-"}</span>
+ ),
+ size: 120,
+ },
+
+ // 상세 - 수정됨
+ {
+ id: "detail",
+ header: "상세",
+ cell: ({ row }) => (
+ <Button
+ variant="ghost"
+ size="icon"
+ className="h-8 w-8"
+ onClick={() => router.push(`/evcp/rfq-last/${row.original.id}`)}
+ >
+ <Eye className="h-4 w-4" />
+ </Button>
+ ),
+ size: 60,
+ },
+
+ // 견적상태
+ {
+ accessorKey: "status",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적상태" />,
+ cell: ({ row }) => (
+ <Badge variant={getStatusBadgeVariant(row.original.status)}>
+ {row.original.status}
+ </Badge>
+ ),
+ size: 120,
+ },
+
+ // 프로젝트 (프로젝트명)
+ {
+ accessorKey: "projectName",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="프로젝트 (프로젝트명)" />,
+ cell: ({ row }) => (
+ <div className="flex flex-col">
+ <span className="font-mono text-xs text-muted-foreground">
+ {row.original.projectCode}
+ </span>
+ <span className="max-w-[200px] truncate" title={row.original.projectName || ""}>
+ {row.original.projectName || "-"}
+ </span>
+ </div>
+ ),
+ size: 220,
+ },
+
+ // // 시리즈
+ // {
+ // accessorKey: "series",
+ // header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="시리즈" />,
+ // cell: ({ row }) => {
+ // const series = row.original.series;
+ // if (!series) return "-";
+ // const label = series === "SS" ? "시리즈 통합" : series === "II" ? "품목 통합" : series;
+ // return <Badge variant="outline">{label}</Badge>;
+ // },
+ // size: 100,
+ // },
+
+ // // 선급
+ // {
+ // accessorKey: "classNo",
+ // header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="선급" />,
+ // cell: ({ row }) => row.original.classNo || "-",
+ // size: 80,
+ // },
+
+ // 견적명
+ {
+ accessorKey: "rfqTitle",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적명" />,
+ cell: ({ row }) => (
+ <div className="max-w-[200px] truncate" title={row.original.rfqTitle || ""}>
+ {row.original.rfqTitle || "-"}
+ </div>
+ ),
+ size: 200,
+ },
+
+ // 자재그룹 (자재그룹명)
+ {
+ accessorKey: "majorItemMaterialDescription",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="자재그룹 (자재그룹명)" />,
+ cell: ({ row }) => (
+ <div className="flex flex-col">
+ <span className="font-mono text-xs text-muted-foreground">
+ {row.original.majorItemMaterialCategory}
+ </span>
+ <span className="max-w-[150px] truncate" title={row.original.majorItemMaterialDescription || ""}>
+ {row.original.majorItemMaterialDescription || "-"}
+ </span>
+ </div>
+ ),
+ size: 180,
+ },
+
+ // 자재코드
+ {
+ accessorKey: "itemCode",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="자재코드" />,
+ cell: ({ row }) => (
+ <span className="font-mono text-sm">{row.original.itemCode || "-"}</span>
+ ),
+ size: 100,
+ },
+ // 자재명
+ {
+ accessorKey: "itemName",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="자재명" />,
+ cell: ({ row }) => (
+ <span className="font-mono text-sm">{row.original.itemName || "-"}</span>
+ ),
+ size: 100,
+ },
+
+ // 견적 자료
+ {
+ id: "rfqDocument",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적 자료" />,
+ cell: ({ row }) => (
+ <Button
+ variant="ghost"
+ size="sm"
+ onClick={() => setRowAction({ row, type: "attachment" })}
+ >
+ <FileText className="h-4 w-4" />
+ </Button>
+ ),
+ size: 80,
+ },
+
+ // 견적품목수
+ {
+ accessorKey: "prItemsCount",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적품목수" />,
+ cell: ({ row }) => (
+ <Button
+ variant="ghost"
+ size="sm"
+ className="font-mono text-sm p-1 h-auto"
+ onClick={() => setRowAction({ row, type: "items" })}
+ >
+ {row.original.prItemsCount || 0}
+ </Button>
+ ),
+ size: 90,
+ },
+
+ // 견적생성일
+ {
+ accessorKey: "createdAt",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적생성일" />,
+ cell: ({ row }) => {
+ const date = row.original.createdAt;
+ return date ? format(new Date(date), "yyyy-MM-dd") : "-";
+ },
+ size: 100,
+ },
+
+ // 견적발송일
+ {
+ accessorKey: "rfqSendDate",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적발송일" />,
+ cell: ({ row }) => {
+ const date = row.original.rfqSendDate;
+ return date ? format(new Date(date), "yyyy-MM-dd") : "-";
+ },
+ size: 100,
+ },
+
+ // 견적마감일
+ {
+ accessorKey: "dueDate",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적마감일" />,
+ cell: ({ row }) => {
+ const date = row.original.dueDate;
+ if (!date) return "-";
+
+ const now = new Date();
+ const dueDate = new Date(date);
+ const daysLeft = differenceInDays(dueDate, now);
+
+ // 상태별 스타일과 아이콘 설정
+ let statusIcon;
+ let statusText;
+ let statusClass;
+
+ if (daysLeft < 0) {
+ const daysOverdue = Math.abs(daysLeft);
+ statusIcon = <XCircle className="h-4 w-4" />;
+ statusText = `${daysOverdue}일 지남`;
+ statusClass = "text-red-600";
+ } else if (daysLeft === 0) {
+ statusIcon = <AlertTriangle className="h-4 w-4" />;
+ statusText = "오늘 마감";
+ statusClass = "text-orange-600";
+ } else if (daysLeft <= 3) {
+ statusIcon = <AlertCircle className="h-4 w-4" />;
+ statusText = `${daysLeft}일 남음`;
+ statusClass = "text-amber-600";
+ } else if (daysLeft <= 7) {
+ statusIcon = <Clock className="h-4 w-4" />;
+ statusText = `${daysLeft}일 남음`;
+ statusClass = "text-blue-600";
+ } else {
+ statusIcon = <CheckCircle className="h-4 w-4" />;
+ statusText = `${daysLeft}일 남음`;
+ statusClass = "text-green-600";
+ }
+
+ return (
+ <div className="flex flex-col gap-1">
+ <span className="text-sm text-muted-foreground">
+ {format(dueDate, "yyyy-MM-dd")}
+ </span>
+ <div className={`flex items-center gap-1 ${statusClass}`}>
+ {statusIcon}
+ <span className="text-xs font-medium">{statusText}</span>
+ </div>
+ </div>
+ );
+ },
+ size: 120,
+ },
+
+ // 계약기간 (추가)
+ {
+ id: "contractPeriod",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="계약기간" />,
+ cell: ({ row }) => {
+ const start = row.original.contractStartDate;
+ const end = row.original.contractEndDate;
+
+ if (!start && !end) return "-";
+
+ return (
+ <div className="flex flex-col text-xs">
+ <span>{start ? format(new Date(start), "yyyy-MM-dd") : "미정"}</span>
+ <span className="text-muted-foreground">~</span>
+ <span>{end ? format(new Date(end), "yyyy-MM-dd") : "미정"}</span>
+ </div>
+ );
+ },
+ size: 120,
+ },
+
+ // 구매담당자
+ {
+ accessorKey: "picUserName",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="구매담당자" />,
+ cell: ({ row }) => {
+ const name = row.original.picUserName || row.original.picName || "-";
+ const picCode = row.original.picCode || "";
+ return name === "-" ? "-" : `${name}(${picCode})`;
+ },
+ size: 100,
+ },
+
+ // 최종수정일
+ {
+ accessorKey: "updatedAt",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="최종수정일" />,
+ cell: ({ row }) => {
+ const date = row.original.updatedAt;
+ return date ? format(new Date(date), "yyyy-MM-dd HH:mm") : "-";
+ },
+ size: 120,
+ },
+
+ // 최종수정자
+ {
+ accessorKey: "updatedByUserName",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="최종수정자" />,
+ cell: ({ row }) => row.original.updatedByUserName || "-",
+ size: 100,
+ },
+
+ // 비고
+ {
+ accessorKey: "remark",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="비고" />,
+ cell: ({ row }) => row.original.remark || "-",
+ size: 150,
+ },
+ ];
+ }
+
+ // ═══════════════════════════════════════════════════════════════
// 일반견적 컬럼 정의
// ═══════════════════════════════════════════════════════════════
if (rfqCategory === "general") {