summaryrefslogtreecommitdiff
path: root/lib/techsales-rfq/table/rfq-table-column.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-07-21 07:54:26 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-07-21 07:54:26 +0000
commit14f61e24947fb92dd71ec0a7196a6e815f8e66da (patch)
tree317c501d64662d05914330628f867467fba78132 /lib/techsales-rfq/table/rfq-table-column.tsx
parent194bd4bd7e6144d5c09c5e3f5476d254234dce72 (diff)
(최겸)기술영업 RFQ 담당자 초대, 요구사항 반영
Diffstat (limited to 'lib/techsales-rfq/table/rfq-table-column.tsx')
-rw-r--r--lib/techsales-rfq/table/rfq-table-column.tsx831
1 files changed, 412 insertions, 419 deletions
diff --git a/lib/techsales-rfq/table/rfq-table-column.tsx b/lib/techsales-rfq/table/rfq-table-column.tsx
index 89054d0e..f41857cd 100644
--- a/lib/techsales-rfq/table/rfq-table-column.tsx
+++ b/lib/techsales-rfq/table/rfq-table-column.tsx
@@ -1,420 +1,413 @@
-"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 { Paperclip, Package, FileText, BarChart3 } from "lucide-react"
-import { Button } from "@/components/ui/button"
-
-// 기본적인 RFQ 타입 정의 (rfq-table.tsx 파일과 일치해야 함)
-type TechSalesRfq = {
- id: number
- rfqCode: string | null
- description: 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
- pspid: string
- projNm: string
- sector: string
- projMsrm: number
- ptypeNm: string
- attachmentCount: number
- hasTbeAttachments: boolean
- hasCbeAttachments: boolean
- quotationCount: number
- itemCount: number
- // 나머지 필드는 사용할 때마다 추가
- [key: string]: unknown
-}
-
-interface GetColumnsProps {
- setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<TechSalesRfq> | null>>;
- openAttachmentsSheet: (rfqId: number, attachmentType?: 'RFQ_COMMON' | 'TBE_RESULT' | 'CBE_RESULT') => void;
- openItemsDialog: (rfq: TechSalesRfq) => void;
-}
-
-export function getColumns({
- setRowAction,
- openAttachmentsSheet,
- openItemsDialog,
-}: 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" as const })
- } 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: "description",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="RFQ Title" />
- ),
- cell: ({ row }) => <div>{row.getValue("description")}</div>,
- meta: {
- excelHeader: "RFQ Title"
- },
- enableResizing: true,
- size: 200,
- },
- {
- accessorKey: "projNm",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="프로젝트명" />
- ),
- cell: ({ row }) => {
- const projNm = row.getValue("projNm") as string;
- return (
- <Button
- variant="link"
- className="p-0 h-auto font-normal text-left justify-start hover:underline"
- onClick={() => setRowAction({ row, type: "view" as const })}
- >
- {projNm}
- </Button>
- );
- },
- 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="최초 전송일" />
- ),
- cell: ({ cell }) => {
- const value = cell.getValue();
- return value ? formatDate(value as Date, "KR") : "";
- },
- meta: {
- excelHeader: "최초 전송일"
- },
- 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, "KR") : "";
- },
- 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, "KR") : "";
- },
- meta: {
- excelHeader: "수정일"
- },
- enableResizing: true,
- size: 160,
- },
- // 우측 고정 컬럼들
- {
- id: "items",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="아이템" />
- ),
- cell: ({ row }) => {
- const rfq = row.original
- const itemCount = rfq.itemCount || 0
-
- const handleClick = () => {
- openItemsDialog(rfq)
- }
-
- return (
- <Button
- variant="ghost"
- size="sm"
- className="relative h-8 w-8 p-0 group"
- onClick={handleClick}
- aria-label={`View ${itemCount} items`}
- >
- <Package className="h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" />
- {itemCount > 0 && (
- <span className="pointer-events-none absolute -top-1 -right-1 inline-flex h-4 min-w-[1rem] items-center justify-center rounded-full bg-primary px-1 text-[0.625rem] font-medium leading-none text-primary-foreground">
- {itemCount}
- </span>
- )}
- <span className="sr-only">
- {itemCount > 0 ? `${itemCount} 아이템` : "아이템 없음"}
- </span>
- </Button>
- )
- },
- enableSorting: false,
- enableResizing: false,
- size: 80,
- meta: {
- excelHeader: "아이템"
- },
- },
- {
- id: "attachments",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="RFQ 첨부파일" />
- ),
- cell: ({ row }) => {
- const rfq = row.original
- const attachmentCount = rfq.attachmentCount || 0
-
- const handleClick = () => {
- openAttachmentsSheet(rfq.id, 'RFQ_COMMON')
- }
-
- return (
- <Button
- variant="ghost"
- size="sm"
- className="relative h-8 w-8 p-0 group"
- onClick={handleClick}
- aria-label={
- attachmentCount > 0 ? `View ${attachmentCount} attachments` : "Add attachments"
- }
- >
- <Paperclip className="h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" />
- {attachmentCount > 0 && (
- <span className="pointer-events-none absolute -top-1 -right-1 inline-flex h-4 min-w-[1rem] items-center justify-center rounded-full bg-primary px-1 text-[0.625rem] font-medium leading-none text-primary-foreground">
- {attachmentCount}
- </span>
- )}
- <span className="sr-only">
- {attachmentCount > 0 ? `${attachmentCount} 첨부파일` : "첨부파일 추가"}
- </span>
- </Button>
- )
- },
- enableSorting: false,
- enableResizing: false,
- size: 80,
- meta: {
- excelHeader: "첨부파일"
- },
- },
- {
- id: "tbe-attachments",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="TBE 결과" />
- ),
- cell: ({ row }) => {
- const rfq = row.original
- const hasTbeAttachments = rfq.hasTbeAttachments
-
- const handleClick = () => {
- openAttachmentsSheet(rfq.id, 'TBE_RESULT')
- }
-
- return (
- <Button
- variant="ghost"
- size="sm"
- className="relative h-8 w-8 p-0 group"
- onClick={handleClick}
- aria-label={hasTbeAttachments ? "TBE 첨부파일 있음" : "TBE 첨부파일 추가"}
- >
- <FileText className="h-4 w-4 text-muted-foreground group-hover:text-green-600 transition-colors" />
- {hasTbeAttachments && (
- <span className="pointer-events-none absolute -top-1 -right-1 inline-flex h-3 w-3 rounded-full bg-red-500"></span>
- )}
- <span className="sr-only">
- {hasTbeAttachments ? "TBE 첨부파일 있음" : "TBE 첨부파일 추가"}
- </span>
- </Button>
- )
- },
- enableSorting: false,
- enableResizing: false,
- size: 80,
- meta: {
- excelHeader: "TBE 결과"
- },
- },
- {
- id: "cbe-attachments",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="CBE 결과" />
- ),
- cell: ({ row }) => {
- const rfq = row.original
- const hasCbeAttachments = rfq.hasCbeAttachments
-
- const handleClick = () => {
- openAttachmentsSheet(rfq.id, 'CBE_RESULT')
- }
-
- return (
- <Button
- variant="ghost"
- size="sm"
- className="relative h-8 w-8 p-0 group"
- onClick={handleClick}
- aria-label={hasCbeAttachments ? "CBE 첨부파일 있음" : "CBE 첨부파일 추가"}
- >
- <BarChart3 className="h-4 w-4 text-muted-foreground group-hover:text-blue-600 transition-colors" />
- {hasCbeAttachments && (
- <span className="pointer-events-none absolute -top-1 -right-1 inline-flex h-3 w-3 rounded-full bg-red-500"></span>
- )}
- <span className="sr-only">
- {hasCbeAttachments ? "CBE 첨부파일 있음" : "CBE 첨부파일 추가"}
- </span>
- </Button>
- )
- },
- enableSorting: false,
- enableResizing: false,
- size: 80,
- meta: {
- excelHeader: "CBE 결과"
- },
- },
- ]
+"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 { Paperclip, Package, FileText, BarChart3 } from "lucide-react"
+import { Button } from "@/components/ui/button"
+import { TechSalesRfq } from "./rfq-table"
+
+interface GetColumnsProps {
+ setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<TechSalesRfq> | null>>;
+ openAttachmentsSheet: (rfqId: number, attachmentType?: 'RFQ_COMMON' | 'TBE_RESULT' | 'CBE_RESULT') => void;
+ openItemsDialog: (rfq: TechSalesRfq) => void;
+}
+
+export function getColumns({
+ setRowAction,
+ openAttachmentsSheet,
+ openItemsDialog,
+}: 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" as const })
+ } 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: "description",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="RFQ Title" />
+ ),
+ cell: ({ row }) => <div>{row.getValue("description")}</div>,
+ meta: {
+ excelHeader: "RFQ Title"
+ },
+ enableResizing: true,
+ size: 200,
+ },
+ {
+ accessorKey: "projNm",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="프로젝트명" />
+ ),
+ cell: ({ row }) => {
+ const projNm = row.getValue("projNm") as string;
+ return (
+ <Button
+ variant="link"
+ className="p-0 h-auto font-normal text-left justify-start hover:underline"
+ onClick={() => setRowAction({ row, type: "view" as const })}
+ >
+ {projNm}
+ </Button>
+ );
+ },
+ meta: {
+ excelHeader: "프로젝트명"
+ },
+ enableResizing: true,
+ size: 160,
+ },
+ {
+ accessorKey: "workTypes",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="공종" />
+ ),
+ cell: ({ row }) => {
+ const workTypes = row.getValue("workTypes") as string | null;
+ return (
+ <div className="max-w-[150px]">
+ {workTypes ? (
+ <span className="text-sm truncate block" title={workTypes}>
+ {workTypes}
+ </span>
+ ) : (
+ <span className="text-muted-foreground text-sm">-</span>
+ )}
+ </div>
+ );
+ },
+ meta: {
+ excelHeader: "공종"
+ },
+ enableResizing: true,
+ size: 120,
+ },
+ // {
+ // 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="최초 전송일" />
+ ),
+ cell: ({ cell }) => {
+ const value = cell.getValue();
+ return value ? formatDate(value as Date, "KR") : "";
+ },
+ meta: {
+ excelHeader: "최초 전송일"
+ },
+ 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, "KR") : "";
+ },
+ 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, "KR") : "";
+ },
+ meta: {
+ excelHeader: "수정일"
+ },
+ enableResizing: true,
+ size: 160,
+ },
+ // 우측 고정 컬럼들
+ {
+ id: "items",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="아이템" />
+ ),
+ cell: ({ row }) => {
+ const rfq = row.original
+ const itemCount = rfq.itemCount || 0
+
+ const handleClick = () => {
+ openItemsDialog(rfq)
+ }
+
+ return (
+ <Button
+ variant="ghost"
+ size="sm"
+ className="relative h-8 w-8 p-0 group"
+ onClick={handleClick}
+ aria-label={`View ${itemCount} items`}
+ >
+ <Package className="h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" />
+ {itemCount > 0 && (
+ <span className="pointer-events-none absolute -top-1 -right-1 inline-flex h-4 min-w-[1rem] items-center justify-center rounded-full bg-primary px-1 text-[0.625rem] font-medium leading-none text-primary-foreground">
+ {itemCount}
+ </span>
+ )}
+ <span className="sr-only">
+ {itemCount > 0 ? `${itemCount} 아이템` : "아이템 없음"}
+ </span>
+ </Button>
+ )
+ },
+ enableSorting: false,
+ enableResizing: false,
+ size: 80,
+ meta: {
+ excelHeader: "아이템"
+ },
+ },
+ {
+ id: "attachments",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="RFQ 첨부파일" />
+ ),
+ cell: ({ row }) => {
+ const rfq = row.original
+ const attachmentCount = rfq.attachmentCount || 0
+
+ const handleClick = () => {
+ openAttachmentsSheet(rfq.id, 'RFQ_COMMON')
+ }
+
+ return (
+ <Button
+ variant="ghost"
+ size="sm"
+ className="relative h-8 w-8 p-0 group"
+ onClick={handleClick}
+ aria-label={
+ attachmentCount > 0 ? `View ${attachmentCount} attachments` : "Add attachments"
+ }
+ >
+ <Paperclip className="h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" />
+ {attachmentCount > 0 && (
+ <span className="pointer-events-none absolute -top-1 -right-1 inline-flex h-4 min-w-[1rem] items-center justify-center rounded-full bg-primary px-1 text-[0.625rem] font-medium leading-none text-primary-foreground">
+ {attachmentCount}
+ </span>
+ )}
+ <span className="sr-only">
+ {attachmentCount > 0 ? `${attachmentCount} 첨부파일` : "첨부파일 추가"}
+ </span>
+ </Button>
+ )
+ },
+ enableSorting: false,
+ enableResizing: false,
+ size: 80,
+ meta: {
+ excelHeader: "첨부파일"
+ },
+ },
+ {
+ id: "tbe-attachments",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="TBE 결과" />
+ ),
+ cell: ({ row }) => {
+ const rfq = row.original
+ const hasTbeAttachments = rfq.hasTbeAttachments
+
+ const handleClick = () => {
+ openAttachmentsSheet(rfq.id, 'TBE_RESULT')
+ }
+
+ return (
+ <Button
+ variant="ghost"
+ size="sm"
+ className="relative h-8 w-8 p-0 group"
+ onClick={handleClick}
+ aria-label={hasTbeAttachments ? "TBE 첨부파일 있음" : "TBE 첨부파일 추가"}
+ >
+ <FileText className="h-4 w-4 text-muted-foreground group-hover:text-green-600 transition-colors" />
+ {hasTbeAttachments && (
+ <span className="pointer-events-none absolute -top-1 -right-1 inline-flex h-3 w-3 rounded-full bg-red-500"></span>
+ )}
+ <span className="sr-only">
+ {hasTbeAttachments ? "TBE 첨부파일 있음" : "TBE 첨부파일 추가"}
+ </span>
+ </Button>
+ )
+ },
+ enableSorting: false,
+ enableResizing: false,
+ size: 80,
+ meta: {
+ excelHeader: "TBE 결과"
+ },
+ },
+ {
+ id: "cbe-attachments",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="CBE 결과" />
+ ),
+ cell: ({ row }) => {
+ const rfq = row.original
+ const hasCbeAttachments = rfq.hasCbeAttachments
+
+ const handleClick = () => {
+ openAttachmentsSheet(rfq.id, 'CBE_RESULT')
+ }
+
+ return (
+ <Button
+ variant="ghost"
+ size="sm"
+ className="relative h-8 w-8 p-0 group"
+ onClick={handleClick}
+ aria-label={hasCbeAttachments ? "CBE 첨부파일 있음" : "CBE 첨부파일 추가"}
+ >
+ <BarChart3 className="h-4 w-4 text-muted-foreground group-hover:text-blue-600 transition-colors" />
+ {hasCbeAttachments && (
+ <span className="pointer-events-none absolute -top-1 -right-1 inline-flex h-3 w-3 rounded-full bg-red-500"></span>
+ )}
+ <span className="sr-only">
+ {hasCbeAttachments ? "CBE 첨부파일 있음" : "CBE 첨부파일 추가"}
+ </span>
+ </Button>
+ )
+ },
+ enableSorting: false,
+ enableResizing: false,
+ size: 80,
+ meta: {
+ excelHeader: "CBE 결과"
+ },
+ },
+ ]
} \ No newline at end of file