"use client" import * as React from "react" import { type ColumnDef } from "@tanstack/react-table" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Checkbox } from "@/components/ui/checkbox" import { Eye, Calendar, Users, CheckCircle, XCircle, Clock, AlertTriangle } from "lucide-react" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" import { biddingStatusLabels, contractTypeLabels, } from "@/db/schema" import { formatDate } from "@/lib/utils" import { DataTableRowAction } from "@/types/table" type BiddingReceiveItem = { id: number biddingNumber: string originalBiddingNumber: string | null title: string status: string contractType: string prNumber: string | null submissionStartDate: Date | null submissionEndDate: Date | null bidPicName: string | null supplyPicName: string | null createdBy: string | null createdAt: Date | null updatedAt: Date | null // 참여 현황 participantExpected: number participantParticipated: number participantDeclined: number participantPending: number // 개찰 정보 openedAt: Date | null openedBy: string | null } interface GetColumnsProps { setRowAction: React.Dispatch | null>> onParticipantClick?: (biddingId: number, participantType: 'expected' | 'participated' | 'declined' | 'pending') => void } // 상태별 배지 색상 const getStatusBadgeVariant = (status: string) => { switch (status) { case 'received_quotation': return 'secondary' case 'bidding_opened': return 'default' case 'bidding_closed': return 'outline' default: return 'outline' } } // 금액 포맷팅 const formatCurrency = (amount: string | number | null, currency = 'KRW') => { if (!amount) return '-' const numAmount = typeof amount === 'string' ? parseFloat(amount) : amount if (isNaN(numAmount)) return '-' return new Intl.NumberFormat('ko-KR', { style: 'currency', currency: currency, minimumFractionDigits: 0, maximumFractionDigits: 0, }).format(numAmount) } export function getBiddingsReceiveColumns({ setRowAction, onParticipantClick }: GetColumnsProps): ColumnDef[] { return [ // ░░░ 선택 ░░░ { id: "select", header: "", cell: ({ row }) => ( { // single select 모드에서는 다른 행들의 선택을 해제 row.toggleSelected(!!value) }} aria-label="행 선택" /> ), size: 50, enableSorting: false, enableHiding: false, }, // ░░░ 입찰번호 ░░░ { accessorKey: "biddingNumber", header: ({ column }) => , cell: ({ row }) => (
{row.original.biddingNumber}
), size: 120, meta: { excelHeader: "입찰번호" }, }, // ░░░ 입찰명 ░░░ { accessorKey: "title", header: ({ column }) => , cell: ({ row }) => (
{/* */} {row.original.title}
), size: 200, meta: { excelHeader: "입찰명" }, }, // ░░░ 원입찰번호 ░░░ { accessorKey: "originalBiddingNumber", header: ({ column }) => , cell: ({ row }) => (
{row.original.originalBiddingNumber || '-'}
), size: 120, meta: { excelHeader: "원입찰번호" }, }, // ░░░ 진행상태 ░░░ { accessorKey: "status", header: ({ column }) => , cell: ({ row }) => ( {biddingStatusLabels[row.original.status]} ), size: 120, meta: { excelHeader: "진행상태" }, }, // ░░░ 계약구분 ░░░ { accessorKey: "contractType", header: ({ column }) => , cell: ({ row }) => ( {contractTypeLabels[row.original.contractType]} ), size: 100, meta: { excelHeader: "계약구분" }, }, // ░░░ 입찰서제출기간 ░░░ { id: "submissionPeriod", header: ({ column }) => , cell: ({ row }) => { const startDate = row.original.submissionStartDate const endDate = row.original.submissionEndDate if (!startDate || !endDate) return - const startObj = new Date(startDate) const endObj = new Date(endDate) // UI 표시용 KST 변환 const formatKst = (d: Date) => new Date(d.getTime() + 9 * 60 * 60 * 1000).toISOString().slice(0, 16).replace('T', ' ') return (
{formatKst(startObj)} ~ {formatKst(endObj)}
) }, size: 140, meta: { excelHeader: "입찰서제출기간" }, }, // ░░░ P/R번호 ░░░ { accessorKey: "prNumber", header: ({ column }) => , cell: ({ row }) => ( {row.original.prNumber || '-'} ), size: 100, meta: { excelHeader: "P/R번호" }, }, // ░░░ 입찰담당자 ░░░ { accessorKey: "bidPicName", header: ({ column }) => , cell: ({ row }) => { const bidPic = row.original.bidPicName const supplyPic = row.original.supplyPicName const displayName = bidPic || supplyPic || "-" return {displayName} }, size: 100, meta: { excelHeader: "입찰담당자" }, }, // ░░░ 참여예정협력사 ░░░ { id: "participantExpected", header: ({ column }) => , cell: ({ row }) => ( ), size: 100, meta: { excelHeader: "참여예정협력사" }, }, // ░░░ 참여협력사 ░░░ { id: "participantParticipated", header: ({ column }) => , cell: ({ row }) => ( ), size: 100, meta: { excelHeader: "참여협력사" }, }, // ░░░ 포기협력사 ░░░ { id: "participantDeclined", header: ({ column }) => , cell: ({ row }) => ( ), size: 100, meta: { excelHeader: "포기협력사" }, }, // ░░░ 미제출협력사 ░░░ { id: "participantPending", header: ({ column }) => , cell: ({ row }) => ( ), size: 100, meta: { excelHeader: "미제출협력사" }, }, // ░░░ 개찰자명 ░░░ { id: "openedBy", header: ({ column }) => , cell: ({ row }) => { const openedBy = row.original.openedBy return {openedBy || '-'} }, size: 100, meta: { excelHeader: "개찰자명" }, }, // ░░░ 개찰일 ░░░ { id: "openedAt", header: ({ column }) => , cell: ({ row }) => { const openedAt = row.original.openedAt return {openedAt ? formatDate(openedAt, "KR") : '-'} }, size: 100, meta: { excelHeader: "개찰일" }, }, // ░░░ 등록자 ░░░ { accessorKey: "createdBy", header: ({ column }) => , cell: ({ row }) => ( {row.original.createdBy || '-'} ), size: 100, meta: { excelHeader: "등록자" }, }, // ░░░ 등록일시 ░░░ { accessorKey: "createdAt", header: ({ column }) => , cell: ({ row }) => ( {row.original.createdAt ? formatDate(row.original.createdAt, "KR") : '-'} ), size: 100, meta: { excelHeader: "등록일시" }, }, // ═══════════════════════════════════════════════════════════════ // 액션 // ═══════════════════════════════════════════════════════════════ // { // id: "actions", // header: "액션", // cell: ({ row }) => ( // // // // // // setRowAction({ row, type: "view" })}> // // 상세보기 // // // // ), // size: 50, // enableSorting: false, // enableHiding: false, // }, ] }