diff options
Diffstat (limited to 'lib/bidding/failure/biddings-failure-columns.tsx')
| -rw-r--r-- | lib/bidding/failure/biddings-failure-columns.tsx | 130 |
1 files changed, 88 insertions, 42 deletions
diff --git a/lib/bidding/failure/biddings-failure-columns.tsx b/lib/bidding/failure/biddings-failure-columns.tsx index 8a888079..3046dbc0 100644 --- a/lib/bidding/failure/biddings-failure-columns.tsx +++ b/lib/bidding/failure/biddings-failure-columns.tsx @@ -5,8 +5,9 @@ import { type ColumnDef } from "@tanstack/react-table" import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
- Eye, Calendar, FileX, DollarSign, AlertTriangle, RefreshCw
+ Eye, Calendar, FileX, DollarSign, AlertTriangle, RefreshCw, FileText
} from "lucide-react"
+import { Checkbox } from "@/components/ui/checkbox"
import {
Tooltip,
TooltipContent,
@@ -27,6 +28,7 @@ import { } from "@/db/schema"
import { formatDate } from "@/lib/utils"
import { DataTableRowAction } from "@/types/table"
+import { downloadFile } from "@/lib/file-download"
type BiddingFailureItem = {
id: number
@@ -55,6 +57,15 @@ type BiddingFailureItem = { disposalUpdatedAt: Date | null // 폐찰수정일
disposalUpdatedBy: string | null // 폐찰수정자
+ // 폐찰 정보
+ closureReason: string | null // 폐찰사유
+ closureDocuments: {
+ id: number
+ fileName: string
+ originalFileName: string
+ filePath: string
+ }[] // 폐찰 첨부파일들
+
// 기타 정보
createdBy: string | null
createdAt: Date | null
@@ -94,6 +105,25 @@ const formatCurrency = (amount: string | number | null, currency = 'KRW') => { export function getBiddingsFailureColumns({ setRowAction }: GetColumnsProps): ColumnDef<BiddingFailureItem>[] {
return [
+ // ░░░ 선택 ░░░
+ {
+ id: "select",
+ header: "",
+ cell: ({ row }) => (
+ <Checkbox
+ checked={row.getIsSelected()}
+ onCheckedChange={(value) => {
+ // single select 모드에서는 다른 행들의 선택을 해제
+ row.toggleSelected(!!value)
+ }}
+ aria-label="행 선택"
+ />
+ ),
+ size: 50,
+ enableSorting: false,
+ enableHiding: false,
+ },
+
// ░░░ 입찰번호 ░░░
{
accessorKey: "biddingNumber",
@@ -188,7 +218,7 @@ export function getBiddingsFailureColumns({ setRowAction }: GetColumnsProps): Co accessorKey: "biddingRegistrationDate",
header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="입찰등록일" />,
cell: ({ row }) => (
- <span className="text-sm">{formatDate(row.original.biddingRegistrationDate, "KR")}</span>
+ <span className="text-sm">{row.original.biddingRegistrationDate ? formatDate(row.original.biddingRegistrationDate, "KR") : '-'}</span>
),
size: 100,
meta: { excelHeader: "입찰등록일" },
@@ -216,7 +246,7 @@ export function getBiddingsFailureColumns({ setRowAction }: GetColumnsProps): Co cell: ({ row }) => (
<div className="flex items-center gap-1">
<AlertTriangle className="h-4 w-4 text-red-500" />
- <span className="text-sm">{formatDate(row.original.disposalDate, "KR")}</span>
+ <span className="text-sm">{row.original.disposalDate ? formatDate(row.original.disposalDate, "KR") : '-'}</span>
</div>
),
size: 100,
@@ -230,7 +260,7 @@ export function getBiddingsFailureColumns({ setRowAction }: GetColumnsProps): Co cell: ({ row }) => (
<div className="flex items-center gap-1">
<FileX className="h-4 w-4 text-red-500" />
- <span className="text-sm">{formatDate(row.original.disposalUpdatedAt, "KR")}</span>
+ <span className="text-sm">{row.original.disposalUpdatedAt ? formatDate(row.original.disposalUpdatedAt, "KR") : '-'}</span>
</div>
),
size: 100,
@@ -248,6 +278,57 @@ export function getBiddingsFailureColumns({ setRowAction }: GetColumnsProps): Co meta: { excelHeader: "폐찰수정자" },
},
+ // ░░░ 폐찰사유 ░░░
+ {
+ id: "closureReason",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="폐찰사유" />,
+ cell: ({ row }) => (
+ <div className="max-w-[200px] truncate" title={row.original.closureReason || undefined}>
+ <span className="text-sm">{row.original.closureReason || '-'}</span>
+ </div>
+ ),
+ size: 150,
+ meta: { excelHeader: "폐찰사유" },
+ },
+
+ // ░░░ 폐찰첨부파일 ░░░
+ {
+ id: "closureDocuments",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="폐찰첨부파일" />,
+ cell: ({ row }) => {
+ const documents = row.original.closureDocuments || []
+
+ if (documents.length === 0) {
+ return <span className="text-sm text-muted-foreground">-</span>
+ }
+
+ return (
+ <div className="flex flex-wrap gap-1 max-w-[200px]">
+ {documents.map((doc) => (
+ <Button
+ key={doc.id}
+ variant="link"
+ size="sm"
+ className="p-0 h-auto text-xs underline"
+ onClick={async () => {
+ try {
+ await downloadFile(doc.filePath, doc.originalFileName)
+ } catch (error) {
+ console.error('파일 다운로드 실패:', error)
+ }
+ }}
+ >
+ <FileText className="mr-1 h-3 w-3" />
+ {doc.originalFileName}
+ </Button>
+ ))}
+ </div>
+ )
+ },
+ size: 200,
+ meta: { excelHeader: "폐찰첨부파일" },
+ },
+
// ░░░ P/R번호 ░░░
{
accessorKey: "prNumber",
@@ -267,7 +348,7 @@ export function getBiddingsFailureColumns({ setRowAction }: GetColumnsProps): Co <span className="text-sm">{row.original.createdBy || '-'}</span>
),
size: 100,
- meta: { excelHeader: "등록자" },
+ meta: { excelHeader: "최종수정자" },
},
// ░░░ 등록일시 ░░░
@@ -275,46 +356,11 @@ export function getBiddingsFailureColumns({ setRowAction }: GetColumnsProps): Co accessorKey: "createdAt",
header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="등록일시" />,
cell: ({ row }) => (
- <span className="text-sm">{formatDate(row.original.createdAt, "KR")}</span>
+ <span className="text-sm">{row.original.createdAt ? formatDate(row.original.createdAt, "KR") : '-'}</span>
),
size: 100,
- meta: { excelHeader: "등록일시" },
+ meta: { excelHeader: "최종일시" },
},
- // ═══════════════════════════════════════════════════════════════
- // 액션
- // ═══════════════════════════════════════════════════════════════
- {
- id: "actions",
- header: "액션",
- cell: ({ row }) => (
- <DropdownMenu>
- <DropdownMenuTrigger asChild>
- <Button variant="ghost" className="h-8 w-8 p-0">
- <span className="sr-only">메뉴 열기</span>
- <FileX className="h-4 w-4" />
- </Button>
- </DropdownMenuTrigger>
- <DropdownMenuContent align="end">
- <DropdownMenuItem onClick={() => setRowAction({ row, type: "view" })}>
- <Eye className="mr-2 h-4 w-4" />
- 상세보기
- </DropdownMenuItem>
- <DropdownMenuItem onClick={() => setRowAction({ row, type: "history" })}>
- <Calendar className="mr-2 h-4 w-4" />
- 이력보기
- </DropdownMenuItem>
- <DropdownMenuSeparator />
- <DropdownMenuItem onClick={() => setRowAction({ row, type: "rebid" })}>
- <RefreshCw className="mr-2 h-4 w-4" />
- 재입찰
- </DropdownMenuItem>
- </DropdownMenuContent>
- </DropdownMenu>
- ),
- size: 50,
- enableSorting: false,
- enableHiding: false,
- },
]
}
|
