"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 { 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>> } // 상태별 배지 색상 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 }: GetColumnsProps): ColumnDef[] { return [ // ░░░ 입찰번호 ░░░ { accessorKey: "biddingNumber", header: ({ column }) => , cell: ({ row }) => (
{row.original.biddingNumber}
), size: 120, meta: { excelHeader: "입찰번호" }, }, // ░░░ 입찰명 ░░░ { accessorKey: "title", header: ({ column }) => , cell: ({ row }) => (
), 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 now = new Date() const isActive = now >= new Date(startDate) && now <= new Date(endDate) const isPast = now > new Date(endDate) return (
{formatDate(startDate, "KR")} ~ {formatDate(endDate, "KR")}
{isActive && ( 진행중 )}
) }, 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 }) => (
{row.original.participantExpected}
), size: 100, meta: { excelHeader: "참여예정협력사" }, }, // ░░░ 참여협력사 ░░░ { id: "participantParticipated", header: ({ column }) => , cell: ({ row }) => (
{row.original.participantParticipated}
), size: 100, meta: { excelHeader: "참여협력사" }, }, // ░░░ 포기협력사 ░░░ { id: "participantDeclined", header: ({ column }) => , cell: ({ row }) => (
{row.original.participantDeclined}
), size: 100, meta: { excelHeader: "포기협력사" }, }, // ░░░ 미제출협력사 ░░░ { id: "participantPending", header: ({ column }) => , cell: ({ row }) => (
{row.original.participantPending}
), 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 }) => ( {formatDate(row.original.createdAt, "KR")} ), size: 100, meta: { excelHeader: "등록일시" }, }, // ═══════════════════════════════════════════════════════════════ // 액션 // ═══════════════════════════════════════════════════════════════ { id: "actions", header: "액션", cell: ({ row }) => ( setRowAction({ row, type: "view" })}> 상세보기 {row.original.status === 'bidding_closed' && ( <> setRowAction({ row, type: "open_bidding" })}> 개찰하기 )} ), size: 50, enableSorting: false, enableHiding: false, }, ] }