summaryrefslogtreecommitdiff
path: root/lib/techsales-rfq/table/rfq-table-column.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-05-28 19:03:21 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-05-28 19:03:21 +0000
commit5036cf2908792cef45f06256e71f10920f647f49 (patch)
tree3116e7419e872d45025d1d48e6ddaffe2ba2dd38 /lib/techsales-rfq/table/rfq-table-column.tsx
parent7ae037e9c2fc0be1fe68cecb461c5e1e837cb0da (diff)
(김준회) 기술영업 조선 RFQ (SHI/벤더)
Diffstat (limited to 'lib/techsales-rfq/table/rfq-table-column.tsx')
-rw-r--r--lib/techsales-rfq/table/rfq-table-column.tsx409
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