From a6b9cdaf9ea5ed548292632f821e36453f377a83 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 12 May 2025 11:36:25 +0000 Subject: (대표님) procurement-rfq 작업업 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/procurement-rfqs/table/rfq-table-column.tsx | 373 ++++++++++++++++++++++++ 1 file changed, 373 insertions(+) create mode 100644 lib/procurement-rfqs/table/rfq-table-column.tsx (limited to 'lib/procurement-rfqs/table/rfq-table-column.tsx') diff --git a/lib/procurement-rfqs/table/rfq-table-column.tsx b/lib/procurement-rfqs/table/rfq-table-column.tsx new file mode 100644 index 00000000..3cf06315 --- /dev/null +++ b/lib/procurement-rfqs/table/rfq-table-column.tsx @@ -0,0 +1,373 @@ +"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 { ProcurementRfqsView } from "@/db/schema" +import { Check, Pencil, X } from "lucide-react" +import { Button } from "@/components/ui/button" +import { toast } from "sonner" +import { Input } from "@/components/ui/input" +import { updateRfqRemark } from "../services" + +interface GetColumnsProps { + setRowAction: React.Dispatch | null>>; + // 상태와 상태 설정 함수를 props로 받음 + editingCell: EditingCellState | null; + setEditingCell: (state: EditingCellState | null) => void; + updateRemark: (rfqId: number, remark: string) => Promise; +} + +export interface EditingCellState { + rowId: string | number; + value: string; +} + + +export function getColumns({ + setRowAction, + editingCell, + setEditingCell, + updateRemark, +}: GetColumnsProps): ColumnDef[] { + + + + return [ + { + id: "select", + // Remove the "Select all" checkbox in header since we're doing single-select + header: () => Select, + cell: ({ row, table }) => ( + { + // 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 }) => ( + + ), + cell: ({ row }) =>
{row.getValue("status")}
, + meta: { + excelHeader: "status" + }, + enableResizing: true, + minSize: 80, + size: 100, + }, + { + accessorKey: "projectCode", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue("projectCode")}
, + meta: { + excelHeader: "프로젝트" + }, + enableResizing: true, + size: 120, + }, + { + accessorKey: "series", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue("series")}
, + meta: { + excelHeader: "시리즈" + }, + enableResizing: true, + minSize: 80, + size: 100, + }, + { + accessorKey: "rfqSealedYn", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue("rfqSealedYn") ? "Y":"N"}
, + meta: { + excelHeader: "RFQ 밀봉" + }, + enableResizing: true, + minSize: 80, + size: 100, + }, + { + accessorKey: "rfqCode", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue("rfqCode")}
, + meta: { + excelHeader: "RFQ NO." + }, + enableResizing: true, + size: 120, + }, + { + accessorKey: "po_no", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue("po_no")}
, + meta: { + excelHeader: "대표 PR NO." + }, + enableResizing: true, + size: 120, + }, + { + accessorKey: "itemCode", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue("itemCode")}
, + meta: { + excelHeader: "자재그룹" + }, + enableResizing: true, + size: 120, + }, + { + accessorKey: "majorItemMaterialCode", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue("majorItemMaterialCode")}
, + meta: { + excelHeader: "자재코드" + }, + enableResizing: true, + minSize: 80, + size: 120, + }, + { + accessorKey: "itemName", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue("itemName")}
, + meta: { + excelHeader: "자재명" + }, + enableResizing: true, + size: 140, + }, + { + accessorKey: "prItemsCount", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue("prItemsCount")}
, + meta: { + excelHeader: "PR 건수" + }, + enableResizing: true, + // size: 80, + }, + { + accessorKey: "rfqSendDate", + header: ({ column }) => ( + + ), + cell: ({ cell }) => { + const value = cell.getValue(); + return value ? formatDate(value as Date, "KR") : ""; + }, + meta: { + excelHeader: "RFQ 전송일" + }, + enableResizing: true, + size: 120, + }, + { + accessorKey: "earliestQuotationSubmittedAt", + header: ({ column }) => ( + + ), + cell: ({ cell }) => { + const value = cell.getValue(); + return value ? formatDate(value as Date, "KR") : ""; + }, + meta: { + excelHeader: "첫회신 접수일" + }, + enableResizing: true, + // size: 140, + }, + { + accessorKey: "dueDate", + header: ({ column }) => ( + + ), + cell: ({ cell }) => { + const value = cell.getValue(); + return value ? formatDate(value as Date, "KR") : ""; + }, + meta: { + excelHeader: "RFQ 마감일" + }, + enableResizing: true, + minSize: 80, + size: 120, + }, + { + accessorKey: "sentByUserName", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue("sentByUserName")}
, + meta: { + excelHeader: "RFQ 요청자" + }, + enableResizing: true, + size: 120, + }, + { + accessorKey: "updatedAt", + header: ({ column }) => ( + + ), + cell: ({ cell }) => formatDateTime(cell.getValue() as Date, "KR"), + meta: { + excelHeader: "updated At" + }, + enableResizing: true, + size: 140, + }, + + { + accessorKey: "remark", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const rowId = row.id + const value = row.getValue("remark") as string + const isEditing = editingCell && editingCell.rowId === rowId + + const startEditing = () => { + setEditingCell({ + rowId, + value: value || "" + }) + } + + const cancelEditing = () => { + setEditingCell(null) + } + + const saveChanges = async () => { + if (!editingCell) return + + try { + + // 컴포넌트에서 전달받은 업데이트 함수 사용 + await updateRemark(row.original.id, editingCell.value) + row.original.remark = editingCell.value; + + // 편집 모드 종료 + setEditingCell(null) + } catch (error) { + console.error("비고 업데이트 오류:", error) + } + } + + // 키보드 이벤트 처리 + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + saveChanges() + } else if (e.key === "Escape") { + cancelEditing() + } + } + + if (isEditing) { + return ( +
+ setEditingCell({ + ...editingCell, + value: e.target.value + })} + onKeyDown={handleKeyDown} + autoFocus + className="h-8 w-full" + /> +
+ + +
+
+ ) + } + + return ( +
+
{value || "-"}
+ +
+ ) + }, + meta: { + excelHeader: "비고" + }, + enableResizing: true, + size: 200, + } + ] +} \ No newline at end of file -- cgit v1.2.3