diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-05-28 19:03:21 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-05-28 19:03:21 +0000 |
| commit | 5036cf2908792cef45f06256e71f10920f647f49 (patch) | |
| tree | 3116e7419e872d45025d1d48e6ddaffe2ba2dd38 /lib/techsales-rfq/table/rfq-table-column.tsx | |
| parent | 7ae037e9c2fc0be1fe68cecb461c5e1e837cb0da (diff) | |
(김준회) 기술영업 조선 RFQ (SHI/벤더)
Diffstat (limited to 'lib/techsales-rfq/table/rfq-table-column.tsx')
| -rw-r--r-- | lib/techsales-rfq/table/rfq-table-column.tsx | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/lib/techsales-rfq/table/rfq-table-column.tsx b/lib/techsales-rfq/table/rfq-table-column.tsx new file mode 100644 index 00000000..caaa1c97 --- /dev/null +++ b/lib/techsales-rfq/table/rfq-table-column.tsx @@ -0,0 +1,409 @@ +"use client" + +import * as React from "react" +import { ColumnDef } from "@tanstack/react-table" +import { formatDate, formatDateTime } from "@/lib/utils" +import { Checkbox } from "@/components/ui/checkbox" +import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" +import { DataTableRowAction } from "@/types/table" +import { Check, Pencil, X, Info } from "lucide-react" +import { Button } from "@/components/ui/button" +import { toast } from "sonner" +import { Input } from "@/components/ui/input" + +// 기본적인 RFQ 타입 정의 (rfq-table.tsx 파일과 일치해야 함) +type TechSalesRfq = { + id: number + rfqCode: string | null + itemId: number + itemName: string | null + materialCode: string | null + dueDate: Date + rfqSendDate: Date | null + status: "RFQ Created" | "RFQ Vendor Assignned" | "RFQ Sent" | "Quotation Analysis" | "Closed" + picCode: string | null + remark: string | null + cancelReason: string | null + createdAt: Date + updatedAt: Date + createdBy: number | null + createdByName: string + updatedBy: number | null + updatedByName: string + sentBy: number | null + sentByName: string | null + projectSnapshot: any + seriesSnapshot: any + pspid: string + projNm: string + sector: string + projMsrm: number + ptypeNm: string + attachmentCount: number + quotationCount: number + // 나머지 필드는 사용할 때마다 추가 + [key: string]: any +} + +interface GetColumnsProps { + setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<TechSalesRfq> | null>>; + // 상태와 상태 설정 함수를 props로 받음 + editingCell: EditingCellState | null; + setEditingCell: (state: EditingCellState | null) => void; + updateRemark: (rfqId: number, remark: string) => Promise<void>; +} + +export interface EditingCellState { + rowId: string | number; + value: string; +} + + +export function getColumns({ + setRowAction, + editingCell, + setEditingCell, + updateRemark, +}: GetColumnsProps): ColumnDef<TechSalesRfq>[] { + return [ + { + id: "select", + // Remove the "Select all" checkbox in header since we're doing single-select + header: () => <span className="sr-only">Select</span>, + cell: ({ row, table }) => ( + <Checkbox + checked={row.getIsSelected()} + onCheckedChange={(value) => { + // If selecting this row + if (value) { + // First deselect all rows (to ensure single selection) + table.toggleAllRowsSelected(false) + // Then select just this row + row.toggleSelected(true) + // Trigger the same action that was in the "Select" button + setRowAction({ row, type: "select" }) + } else { + // Just deselect this row + row.toggleSelected(false) + } + }} + aria-label="Select row" + className="translate-y-0.5" + /> + ), + enableSorting: false, + enableHiding: false, + enableResizing: false, + size: 40, + minSize: 40, + maxSize: 40, + }, + + { + accessorKey: "status", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="진행상태" /> + ), + cell: ({ row }) => <div>{row.getValue("status")}</div>, + meta: { + excelHeader: "진행상태" + }, + enableResizing: true, + minSize: 80, + size: 100, + }, + { + accessorKey: "rfqCode", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="RFQ No." /> + ), + cell: ({ row }) => <div>{row.getValue("rfqCode")}</div>, + meta: { + excelHeader: "RFQ No." + }, + enableResizing: true, + size: 120, + }, + { + accessorKey: "materialCode", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="자재코드" /> + ), + cell: ({ row }) => <div>{row.getValue("materialCode")}</div>, + meta: { + excelHeader: "자재코드" + }, + enableResizing: true, + minSize: 80, + size: 120, + }, + { + accessorKey: "itemName", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="자재명" /> + ), + cell: ({ row }) => <div>{row.getValue("itemName")}</div>, + meta: { + excelHeader: "자재명" + }, + enableResizing: true, + size: 180, + }, + { + accessorKey: "pspid", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="프로젝트 번호" /> + ), + cell: ({ row }) => <div>{row.getValue("pspid")}</div>, + meta: { + excelHeader: "프로젝트 번호" + }, + enableResizing: true, + size: 120, + }, + { + accessorKey: "projNm", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="프로젝트명" /> + ), + cell: ({ row }) => <div>{row.getValue("projNm")}</div>, + meta: { + excelHeader: "프로젝트명" + }, + enableResizing: true, + size: 160, + }, + { + accessorKey: "projMsrm", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="척수" /> + ), + cell: ({ row }) => <div>{row.getValue("projMsrm")}</div>, + meta: { + excelHeader: "척수" + }, + enableResizing: true, + minSize: 60, + size: 80, + }, + { + accessorKey: "ptypeNm", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="선종" /> + ), + cell: ({ row }) => <div>{row.getValue("ptypeNm")}</div>, + meta: { + excelHeader: "선종" + }, + enableResizing: true, + size: 120, + }, + { + accessorKey: "quotationCount", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="견적수" /> + ), + cell: ({ row }) => <div>{row.getValue("quotationCount")}</div>, + meta: { + excelHeader: "견적수" + }, + enableResizing: true, + size: 80, + }, + { + accessorKey: "rfqSendDate", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="RFQ 전송일" /> + ), + cell: ({ cell }) => { + const value = cell.getValue(); + return value ? formatDate(value as Date, "KR") : ""; + }, + meta: { + excelHeader: "RFQ 전송일" + }, + enableResizing: true, + size: 120, + }, + { + accessorKey: "dueDate", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="RFQ 마감일" /> + ), + cell: ({ cell }) => { + const value = cell.getValue(); + return value ? formatDate(value as Date, "KR") : ""; + }, + meta: { + excelHeader: "RFQ 마감일" + }, + enableResizing: true, + minSize: 80, + size: 120, + }, + { + accessorKey: "createdByName", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="요청자" /> + ), + cell: ({ row }) => <div>{row.getValue("createdByName")}</div>, + meta: { + excelHeader: "요청자" + }, + enableResizing: true, + size: 120, + }, + { + accessorKey: "createdAt", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="등록일" /> + ), + cell: ({ cell }) => { + const value = cell.getValue(); + return value ? formatDateTime(value as Date) : ""; + }, + meta: { + excelHeader: "등록일" + }, + enableResizing: true, + size: 160, + }, + { + accessorKey: "updatedAt", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="수정일" /> + ), + cell: ({ cell }) => { + const value = cell.getValue(); + return value ? formatDateTime(value as Date) : ""; + }, + meta: { + excelHeader: "수정일" + }, + enableResizing: true, + size: 160, + }, + // { + // accessorKey: "remark", + // header: ({ column }) => ( + // <DataTableColumnHeaderSimple column={column} title="비고" /> + // ), + // cell: ({ row }) => { + // const id = row.original.id; + // const value = row.getValue("remark") as string; + + // const isEditing = + // editingCell?.rowId === row.id && + // editingCell.value !== undefined; + + // const startEditing = () => { + // setEditingCell({ + // rowId: row.id, + // value: value || "" + // }); + // }; + + // const cancelEditing = () => { + // setEditingCell(null); + // }; + + // const saveChanges = async () => { + // if (!editingCell) return; + + // try { + // await updateRemark(id, editingCell.value); + // setEditingCell(null); + // } catch (error) { + // toast.error("비고 업데이트 중 오류가 발생했습니다."); + // console.error("Error updating remark:", error); + // } + // }; + + // const handleKeyDown = (e: React.KeyboardEvent) => { + // if (e.key === "Enter") { + // saveChanges(); + // } else if (e.key === "Escape") { + // cancelEditing(); + // } + // }; + + // if (isEditing) { + // return ( + // <div className="flex items-center gap-1"> + // <Input + // value={editingCell?.value || ""} + // onChange={(e) => setEditingCell({ + // rowId: row.id, + // value: e.target.value + // })} + // onKeyDown={handleKeyDown} + // autoFocus + // className="h-8 w-full" + // /> + // <Button + // variant="ghost" + // size="icon" + // onClick={saveChanges} + // className="h-8 w-8" + // > + // <Check className="h-4 w-4" /> + // </Button> + // <Button + // variant="ghost" + // size="icon" + // onClick={cancelEditing} + // className="h-8 w-8" + // > + // <X className="h-4 w-4" /> + // </Button> + // </div> + // ); + // } + + // return ( + // <div className="flex items-center gap-1 group"> + // <span className="truncate">{value || ""}</span> + // <Button + // variant="ghost" + // size="icon" + // onClick={startEditing} + // className="h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity" + // > + // <Pencil className="h-3 w-3" /> + // </Button> + // </div> + // ); + // }, + // meta: { + // excelHeader: "비고" + // }, + // enableResizing: true, + // size: 200, + // }, + { + id: "actions", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="액션" /> + ), + cell: ({ row }) => { + return ( + <Button + variant="ghost" + size="sm" + onClick={() => setRowAction({ row, type: "project-detail" })} + className="h-8 px-2 gap-1" + > + <Info className="h-4 w-4" /> + <span className="hidden sm:inline">프로젝트 상세</span> + </Button> + ); + }, + enableSorting: false, + enableHiding: false, + enableResizing: false, + size: 120, + minSize: 120, + maxSize: 120, + }, + ] +}
\ No newline at end of file |
