summaryrefslogtreecommitdiff
path: root/lib/procurement-rfqs/vendor-response/table
diff options
context:
space:
mode:
Diffstat (limited to 'lib/procurement-rfqs/vendor-response/table')
-rw-r--r--lib/procurement-rfqs/vendor-response/table/vendor-quotations-table-columns.tsx333
-rw-r--r--lib/procurement-rfqs/vendor-response/table/vendor-quotations-table.tsx152
2 files changed, 0 insertions, 485 deletions
diff --git a/lib/procurement-rfqs/vendor-response/table/vendor-quotations-table-columns.tsx b/lib/procurement-rfqs/vendor-response/table/vendor-quotations-table-columns.tsx
deleted file mode 100644
index 1fb225d8..00000000
--- a/lib/procurement-rfqs/vendor-response/table/vendor-quotations-table-columns.tsx
+++ /dev/null
@@ -1,333 +0,0 @@
-"use client"
-
-import * as React from "react"
-import { type DataTableRowAction } from "@/types/table"
-import { type ColumnDef } from "@tanstack/react-table"
-import { Ellipsis, FileText, Pencil, Edit, Trash2 } from "lucide-react"
-import { formatCurrency, formatDate, formatDateTime } from "@/lib/utils"
-import { Badge } from "@/components/ui/badge"
-import { Button } from "@/components/ui/button"
-import { Checkbox } from "@/components/ui/checkbox"
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuSeparator,
- DropdownMenuShortcut,
- DropdownMenuTrigger,
-} from "@/components/ui/dropdown-menu"
-import {
- Tooltip,
- TooltipContent,
- TooltipProvider,
- TooltipTrigger,
-} from "@/components/ui/tooltip"
-import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"
-import Link from "next/link"
-import { ProcurementVendorQuotations } from "@/db/schema"
-import { useRouter } from "next/navigation"
-
-// 상태에 따른 배지 컴포넌트
-function StatusBadge({ status }: { status: string }) {
- switch (status) {
- case "Draft":
- return <Badge variant="outline">초안</Badge>
- case "Submitted":
- return <Badge variant="default">제출됨</Badge>
- case "Revised":
- return <Badge variant="secondary">수정됨</Badge>
- case "Rejected":
- return <Badge variant="destructive">반려됨</Badge>
- case "Accepted":
- return <Badge variant="default">승인됨</Badge>
- default:
- return <Badge>{status}</Badge>
- }
-}
-
-interface QuotationWithRfqCode extends ProcurementVendorQuotations {
- rfqCode?: string;
- rfq?: {
- id?: number;
- rfqCode?: string;
- status?: string;
- dueDate?: Date | string | null;
- rfqSendDate?: Date | string | null;
- item?: {
- id?: number;
- itemCode?: string;
- itemName?: string;
- } | null;
- } | null;
- vendor?: {
- id?: number;
- vendorName?: string;
- vendorCode?: string;
- } | null;
-}
-
-type NextRouter = ReturnType<typeof useRouter>;
-
-interface GetColumnsProps {
- setRowAction: React.Dispatch<
- React.SetStateAction<DataTableRowAction<QuotationWithRfqCode> | null>
- >
- router: NextRouter
-}
-
-/**
- * tanstack table 컬럼 정의 (RfqsTable 스타일)
- */
-export function getColumns({
- setRowAction,
- router,
-}: GetColumnsProps): ColumnDef<QuotationWithRfqCode>[] {
- // ----------------------------------------------------------------
- // 1) select 컬럼 (체크박스)
- // ----------------------------------------------------------------
- const selectColumn: ColumnDef<QuotationWithRfqCode> = {
- id: "select",
- header: ({ table }) => (
- <Checkbox
- checked={
- table.getIsAllPageRowsSelected() ||
- (table.getIsSomePageRowsSelected() && "indeterminate")
- }
- onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
- aria-label="Select all"
- className="translate-y-0.5"
- />
- ),
- cell: ({ row }) => (
- <Checkbox
- checked={row.getIsSelected()}
- onCheckedChange={(value) => row.toggleSelected(!!value)}
- aria-label="Select row"
- className="translate-y-0.5"
- />
- ),
- size: 40,
- enableSorting: false,
- enableHiding: false,
- }
-
- // ----------------------------------------------------------------
- // 2) actions 컬럼
- // ----------------------------------------------------------------
- const actionsColumn: ColumnDef<QuotationWithRfqCode> = {
- id: "actions",
- enableHiding: false,
- cell: ({ row }) => {
- const id = row.original.id
- const code = row.getValue("quotationCode") as string
- const tooltipText = `${code} 작성하기`
-
- return (
- <TooltipProvider>
- <Tooltip>
- <TooltipTrigger asChild>
- <Button
- variant="ghost"
- size="icon"
- onClick={() => router.push(`/partners/rfq-ship/${id}`)}
- className="h-8 w-8"
- >
- <Edit className="h-4 w-4" />
- <span className="sr-only">견적서 작성</span>
- </Button>
- </TooltipTrigger>
- <TooltipContent>
- <p>{tooltipText}</p>
- </TooltipContent>
- </Tooltip>
- </TooltipProvider>
- )
- },
- size: 50,
- }
-
- // ----------------------------------------------------------------
- // 3) 컬럼 정의 배열
- // ----------------------------------------------------------------
- const columnDefinitions = [
- {
- id: "quotationCode",
- label: "RFQ 번호",
- group: null,
- size: 150,
- minSize: 100,
- maxSize: 200,
- },
- {
- id: "quotationVersion",
- label: "RFQ 버전",
- group: null,
- size: 100,
- minSize: 80,
- maxSize: 120,
- },
- {
- id: "itemCode",
- label: "자재 그룹 코드",
- group: "RFQ 정보",
- size: 120,
- minSize: 100,
- maxSize: 150,
- },
- {
- id: "itemName",
- label: "자재 이름",
- group: "RFQ 정보",
- // size를 제거하여 유연한 크기 조정 허용
- minSize: 150,
- maxSize: 300,
- },
- {
- id: "rfqSendDate",
- label: "RFQ 송부일",
- group: "날짜 정보",
- size: 150,
- minSize: 120,
- maxSize: 180,
- },
- {
- id: "dueDate",
- label: "RFQ 마감일",
- group: "날짜 정보",
- size: 150,
- minSize: 120,
- maxSize: 180,
- },
- {
- id: "status",
- label: "상태",
- group: null,
- size: 100,
- minSize: 80,
- maxSize: 120,
- },
- {
- id: "totalPrice",
- label: "총액",
- group: null,
- size: 120,
- minSize: 100,
- maxSize: 150,
- },
- {
- id: "submittedAt",
- label: "제출일",
- group: "날짜 정보",
- size: 120,
- minSize: 100,
- maxSize: 150,
- },
- {
- id: "validUntil",
- label: "유효기간",
- group: "날짜 정보",
- size: 120,
- minSize: 100,
- maxSize: 150,
- },
- ];
-
- // ----------------------------------------------------------------
- // 4) 그룹별로 컬럼 정리 (중첩 헤더 생성)
- // ----------------------------------------------------------------
- const groupMap: Record<string, ColumnDef<QuotationWithRfqCode>[]> = {}
-
- columnDefinitions.forEach((cfg) => {
- const groupName = cfg.group || "_noGroup"
-
- if (!groupMap[groupName]) {
- groupMap[groupName] = []
- }
-
- // 개별 컬럼 정의
- const columnDef: ColumnDef<QuotationWithRfqCode> = {
- accessorKey: cfg.id,
- enableResizing: true,
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title={cfg.label} />
- ),
- cell: ({ row, cell }) => {
- // 각 컬럼별 특별한 렌더링 처리
- switch (cfg.id) {
- case "quotationCode":
- return row.original.quotationCode || "-"
-
- case "quotationVersion":
- return row.original.quotationVersion || "-"
-
- case "itemCode":
- const itemCode = row.original.rfq?.item?.itemCode;
- return itemCode ? itemCode : "-";
-
- case "itemName":
- const itemName = row.original.rfq?.item?.itemName;
- return itemName ? itemName : "-";
-
- case "rfqSendDate":
- const sendDate = row.original.rfq?.rfqSendDate;
- return sendDate ? formatDateTime(new Date(sendDate)) : "-";
-
- case "dueDate":
- const dueDate = row.original.rfq?.dueDate;
- return dueDate ? formatDateTime(new Date(dueDate)) : "-";
-
- case "status":
- return <StatusBadge status={row.getValue("status") as string} />
-
- case "totalPrice":
- const price = parseFloat(row.getValue("totalPrice") as string || "0")
- const currency = row.original.currency
- return formatCurrency(price, currency)
-
- case "submittedAt":
- const submitDate = row.getValue("submittedAt") as string | null
- return submitDate ? formatDate(new Date(submitDate)) : "-"
-
- case "validUntil":
- const validDate = row.getValue("validUntil") as string | null
- return validDate ? formatDate(new Date(validDate)) : "-"
-
- default:
- return row.getValue(cfg.id) ?? ""
- }
- },
- size: cfg.size,
- minSize: cfg.minSize,
- maxSize: cfg.maxSize,
- }
-
- groupMap[groupName].push(columnDef)
- })
-
- // ----------------------------------------------------------------
- // 5) 그룹별 중첩 컬럼 생성
- // ----------------------------------------------------------------
- const nestedColumns: ColumnDef<QuotationWithRfqCode>[] = []
- Object.entries(groupMap).forEach(([groupName, colDefs]) => {
- if (groupName === "_noGroup") {
- // 그룹이 없는 컬럼들은 직접 추가
- nestedColumns.push(...colDefs)
- } else {
- // 그룹이 있는 컬럼들은 중첩 구조로 추가
- nestedColumns.push({
- id: groupName,
- header: groupName,
- columns: colDefs,
- })
- }
- })
-
- // ----------------------------------------------------------------
- // 6) 최종 컬럼 배열
- // ----------------------------------------------------------------
- return [
- selectColumn,
- ...nestedColumns,
- actionsColumn,
- ]
-} \ No newline at end of file
diff --git a/lib/procurement-rfqs/vendor-response/table/vendor-quotations-table.tsx b/lib/procurement-rfqs/vendor-response/table/vendor-quotations-table.tsx
deleted file mode 100644
index 7ea0c69e..00000000
--- a/lib/procurement-rfqs/vendor-response/table/vendor-quotations-table.tsx
+++ /dev/null
@@ -1,152 +0,0 @@
-// lib/vendor-quotations/vendor-quotations-table.tsx
-"use client"
-
-import * as React from "react"
-import { type DataTableAdvancedFilterField, type DataTableFilterField, type 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 { Button } from "@/components/ui/button"
-import { ProcurementVendorQuotations } from "@/db/schema"
-import { useRouter } from "next/navigation"
-import { getColumns } from "./vendor-quotations-table-columns"
-
-interface QuotationWithRfqCode extends ProcurementVendorQuotations {
- rfqCode?: string;
- rfq?: {
- rfqCode?: string;
- } | null;
-}
-
-interface VendorQuotationsTableProps {
- promises: Promise<[{ data: ProcurementVendorQuotations[], pageCount: number }]>;
-}
-
-export function VendorQuotationsTable({ promises }: VendorQuotationsTableProps) {
- const [{ data, pageCount }] = React.use(promises);
- const router = useRouter();
-
- console.log(data ,"data")
-
- // 선택된 행 액션 상태
- const [rowAction, setRowAction] = React.useState<DataTableRowAction<QuotationWithRfqCode> | null>(null);
-
- // 테이블 컬럼 정의
- const columns = React.useMemo(() => getColumns({
- setRowAction,
- router,
- }), [setRowAction, router]);
-
- // 상태별 견적서 수 계산
- const statusCounts = React.useMemo(() => {
- return {
- Draft: data.filter(q => q.status === "Draft").length,
- Submitted: data.filter(q => q.status === "Submitted").length,
- Revised: data.filter(q => q.status === "Revised").length,
- Rejected: data.filter(q => q.status === "Rejected").length,
- Accepted: data.filter(q => q.status === "Accepted").length,
- };
- }, [data]);
-
- // 필터 필드
- const filterFields: DataTableFilterField<QuotationWithRfqCode>[] = [
- {
- id: "status",
- label: "상태",
- options: [
- { label: "초안", value: "Draft", count: statusCounts.Draft },
- { label: "제출됨", value: "Submitted", count: statusCounts.Submitted },
- { label: "수정됨", value: "Revised", count: statusCounts.Revised },
- { label: "반려됨", value: "Rejected", count: statusCounts.Rejected },
- { label: "승인됨", value: "Accepted", count: statusCounts.Accepted },
- ]
- },
- {
- id: "quotationCode",
- label: "견적서 번호",
- placeholder: "견적서 번호 검색...",
- },
- {
- id: "rfqCode",
- label: "RFQ 번호",
- placeholder: "RFQ 번호 검색...",
- }
- ];
-
- // 고급 필터 필드
- const advancedFilterFields: DataTableAdvancedFilterField<QuotationWithRfqCode>[] = [
- {
- id: "quotationCode",
- label: "견적서 번호",
- type: "text",
- },
- {
- id: "rfqCode",
- label: "RFQ 번호",
- type: "text",
- },
- {
- id: "status",
- label: "상태",
- type: "multi-select",
- options: [
- { label: "초안", value: "Draft" },
- { label: "제출됨", value: "Submitted" },
- { label: "수정됨", value: "Revised" },
- { label: "반려됨", value: "Rejected" },
- { label: "승인됨", value: "Accepted" },
- ],
- },
- {
- id: "validUntil",
- label: "유효기간",
- type: "date",
- },
- {
- id: "submittedAt",
- label: "제출일",
- type: "date",
- },
- ];
-
- // useDataTable 훅 사용 (RfqsTable 스타일로 개선)
- const { table } = useDataTable({
- data,
- columns,
- pageCount,
- filterFields,
- enablePinning: true,
- enableAdvancedFilter: true,
- enableColumnResizing: true, // 컬럼 크기 조정 허용
- columnResizeMode: 'onChange', // 실시간 크기 조정
- initialState: {
- sorting: [{ id: "updatedAt", desc: true }],
- columnPinning: { right: ["actions"] },
- },
- getRowId: (originalRow) => String(originalRow.id),
- shallow: false,
- clearOnDefault: true,
- defaultColumn: {
- minSize: 50,
- maxSize: 500,
- },
- });
-
- return (
- <div className="w-full">
- <div className="overflow-x-auto">
- <DataTable
- table={table}
- className="min-w-full"
- >
- <DataTableAdvancedToolbar
- table={table}
- filterFields={advancedFilterFields}
- shallow={false}
- >
- </DataTableAdvancedToolbar>
- </DataTable>
- </div>
- </div>
- );
-} \ No newline at end of file