From 37f55540833c2d5894513eca9fc8f7c6233fc2d2 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Thu, 29 May 2025 05:17:13 +0000 Subject: (대표님) 0529 14시 16분 변경사항 저장 (Vendor Data, Docu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendor-rfq-table/rfqs-table-columns.tsx | 424 +++++++++++++++++++++ 1 file changed, 424 insertions(+) create mode 100644 lib/tech-vendor-rfq-response/vendor-rfq-table/rfqs-table-columns.tsx (limited to 'lib/tech-vendor-rfq-response/vendor-rfq-table/rfqs-table-columns.tsx') diff --git a/lib/tech-vendor-rfq-response/vendor-rfq-table/rfqs-table-columns.tsx b/lib/tech-vendor-rfq-response/vendor-rfq-table/rfqs-table-columns.tsx new file mode 100644 index 00000000..69a5e7e7 --- /dev/null +++ b/lib/tech-vendor-rfq-response/vendor-rfq-table/rfqs-table-columns.tsx @@ -0,0 +1,424 @@ +"use client" + +import * as React from "react" +import { useRouter } from "next/navigation" +import { ColumnDef } from "@tanstack/react-table" +import { + Ellipsis, + MessageSquare, + Package, + Paperclip, +} from "lucide-react" +import { toast } from "sonner" + +import { Button } from "@/components/ui/button" +import { Checkbox } from "@/components/ui/checkbox" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuTrigger +} from "@/components/ui/dropdown-menu" +import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" +import { Badge } from "@/components/ui/badge" + +import { getErrorMessage } from "@/lib/handle-error" +import { formatDate, formatDateTime } from "@/lib/utils" +import { modifyRfqVendor } from "../../rfqs-tech/service" +import type { RfqWithAll } from "../types" +import type { DataTableRowAction } from "@/types/table" + +type NextRouter = ReturnType + +interface GetColumnsProps { + setRowAction: React.Dispatch< + React.SetStateAction | null> + > + router: NextRouter + openAttachmentsSheet: (rfqId: number) => void + openCommentSheet: (rfqId: number) => void +} + +/** + * tanstack table 컬럼 정의 (Nested Header) + */ +export function getColumns({ + setRowAction, + router, + openAttachmentsSheet, + openCommentSheet, +}: GetColumnsProps): ColumnDef[] { + // 1) 체크박스(Select) 컬럼 + const selectColumn: ColumnDef = { + id: "select", + header: ({ table }) => ( + table.toggleAllPageRowsSelected(!!value)} + aria-label="Select all" + /> + ), + cell: ({ row }) => ( + row.toggleSelected(!!value)} + aria-label="Select row" + /> + ), + size: 40, + enableSorting: false, + enableHiding: false, + } + + // 2) Actions (Dropdown) + const actionsColumn: ColumnDef = { + id: "actions", + enableHiding: false, + cell: ({ row }) => { + const [isUpdatePending, startUpdateTransition] = React.useTransition() + + return ( + + + + + + + RFQ Response + + { + startUpdateTransition(async () => { + let newStatus: + | "ACCEPTED" + | "DECLINED" + | "REVIEWING" + + switch (value) { + case "ACCEPTED": + newStatus = "ACCEPTED" + break + case "DECLINED": + newStatus = "DECLINED" + break + default: + newStatus = "REVIEWING" + } + + await toast.promise( + modifyRfqVendor({ + id: row.original.responseId, + status: newStatus, + }), + { + loading: "Updating response status...", + success: "Response status updated", + error: (err) => getErrorMessage(err), + } + ) + }) + }} + > + {[ + { value: "ACCEPTED", label: "Accept RFQ" }, + { value: "DECLINED", label: "Decline RFQ" }, + ].map((rep) => ( + + {rep.label} + + ))} + + + + {/* { + router.push(`/vendor/rfqs/${row.original.rfqId}`) + }} + > + View Details + */} + {/* openAttachmentsSheet(row.original.rfqId)}> + View Attachments + + openCommentSheet(row.original.rfqId)}> + View Comments + + setRowAction({ row, type: "items" })}> + View Items + */} + + + ) + }, + size: 40, + } + + // 3) RFQ Code 컬럼 + const rfqCodeColumn: ColumnDef = { + id: "rfqCode", + accessorKey: "rfqCode", + enableResizing: true, + header: ({ column }) => ( + + ), + // cell: ({ row }) => { + // return ( + // + // ) + // }, + cell: ({ row }) => row.original.rfqCode || "-", + size: 150, + } + + + + // 4) 응답 상태 컬럼 + const responseStatusColumn: ColumnDef = { + id: "responseStatus", + accessorKey: "responseStatus", + enableResizing: true, + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const status = row.original.responseStatus; + let variant: "default" | "secondary" | "destructive" | "outline"; + + switch (status) { + case "REVIEWING": + variant = "default"; + break; + case "ACCEPTED": + variant = "secondary"; + break; + case "DECLINED": + variant = "destructive"; + break; + default: + variant = "outline"; + } + + return {status}; + }, + size: 150, + } + + // 5) 프로젝트 이름 컬럼 + const projectNameColumn: ColumnDef = { + id: "projectName", + accessorKey: "projectName", + enableResizing: true, + header: ({ column }) => ( + + ), + cell: ({ row }) => row.original.projectName || "-", + size: 150, + } + + // 6) RFQ Description 컬럼 + const descriptionColumn: ColumnDef = { + id: "rfqDescription", + accessorKey: "rfqDescription", + enableResizing: true, + header: ({ column }) => ( + + ), + cell: ({ row }) => row.original.rfqDescription || "-", + size: 200, + } + + // 7) Due Date 컬럼 + const dueDateColumn: ColumnDef = { + id: "rfqDueDate", + accessorKey: "rfqDueDate", + enableResizing: true, + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const date = row.original.rfqDueDate; + return date ? formatDate(date) : "-"; + }, + size: 120, + } + + // 8) Last Updated 컬럼 + const updatedAtColumn: ColumnDef = { + id: "respondedAt", + accessorKey: "respondedAt", + enableResizing: true, + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const date = row.original.respondedAt; + return date ? formatDateTime(date) : "-"; + }, + size: 150, + } + + // 9) Items 컬럼 - 뱃지로 아이템 개수 표시 + const itemsColumn: ColumnDef = { + id: "items", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const rfq = row.original + const count = rfq.items?.length ?? 0 + + function handleClick() { + setRowAction({ row, type: "items" }) + } + + return ( + + ) + }, + enableSorting: false, + maxSize: 80, + } + + // 10) Attachments 컬럼 - 뱃지로 파일 개수 표시 + const attachmentsColumn: ColumnDef = { + id: "attachments", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const attachCount = row.original.attachments?.length ?? 0 + + function handleClick(e: React.MouseEvent) { + e.preventDefault() + openAttachmentsSheet(row.original.rfqId) + } + + return ( + + ) + }, + enableSorting: false, + maxSize: 80, + } + + // 11) Comments 컬럼 - 뱃지로 댓글 개수 표시 + const commentsColumn: ColumnDef = { + id: "comments", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const commCount = row.original.comments?.length ?? 0 + + function handleClick() { + setRowAction({ row, type: "comments" }) + openCommentSheet(row.original.rfqId) + } + + return ( + + ) + }, + enableSorting: false, + maxSize: 80, + } + + // 최종 컬럼 구성 - TBE/CBE 관련 컬럼 제외 + return [ + selectColumn, + rfqCodeColumn, + responseStatusColumn, + projectNameColumn, + descriptionColumn, + dueDateColumn, + itemsColumn, + attachmentsColumn, + commentsColumn, + updatedAtColumn, + actionsColumn, + ] +} \ No newline at end of file -- cgit v1.2.3