summaryrefslogtreecommitdiff
path: root/lib/po/vendor-table/vendor-po-items-dialog.tsx
blob: d3b333717961a07a57259326fd2e633298f0fa94 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
"use client"

import * as React from "react"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"
import { Badge } from "@/components/ui/badge"
import { Skeleton } from "@/components/ui/skeleton"
import { VendorPO, VendorPOItem } from "./types"
import { getVendorPOItemsByContractNo } from "./service"

interface VendorPOItemsDialogProps {
  open: boolean
  onOpenChange: (open: boolean) => void
  po: VendorPO | null
}

export function VendorPOItemsDialog({ open, onOpenChange, po }: VendorPOItemsDialogProps) {
  const [items, setItems] = React.useState<VendorPOItem[]>([])
  const [loading, setLoading] = React.useState(false)
  const [error, setError] = React.useState<string | null>(null)

  // 상세품목 데이터 로드
  React.useEffect(() => {
    if (!open || !po) {
      setItems([])
      setError(null)
      return
    }

    const loadItems = async () => {
      setLoading(true)
      setError(null)
      try {
        const vendorPOItems = await getVendorPOItemsByContractNo(po.contractNo)
        setItems(vendorPOItems)
      } catch (err) {
        console.error("Failed to load vendor PO items:", err)
        setError("상세품목을 불러오는 중 오류가 발생했습니다.")
      } finally {
        setLoading(false)
      }
    }

    loadItems()
  }, [open, po])

  if (!po) return null

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-[95vw] max-h-[90vh] w-full flex flex-col">
        <DialogHeader className="flex-shrink-0">
          <DialogTitle className="text-lg font-semibold">
            상세품목 현황 - {po.contractNo}
          </DialogTitle>
          <DialogDescription>
            {po.contractName} ({items.length}개 품목)
          </DialogDescription>
        </DialogHeader>

        <div className="flex-1 overflow-hidden">
          {loading ? (
            <div className="space-y-4">
              <div className="text-center py-4 text-muted-foreground">
                상세품목을 불러오는 중...
              </div>
              <div className="space-y-2">
                {Array.from({ length: 3 }).map((_, i) => (
                  <Skeleton key={i} className="h-12 w-full" />
                ))}
              </div>
            </div>
          ) : error ? (
            <div className="text-center py-8 text-destructive">
              {error}
            </div>
          ) : items.length === 0 ? (
            <div className="text-center py-8 text-muted-foreground">
              등록된 상세품목이 없습니다.
            </div>
          ) : (
            <div className="overflow-auto max-h-[60vh]">
              <Table>
                <TableHeader className="sticky top-0 bg-background z-10">
                  <TableRow>
                    <TableHead className="min-w-[120px] whitespace-nowrap">PO/계약번호</TableHead>
                    <TableHead className="min-w-[100px] whitespace-nowrap">품번</TableHead>
                    <TableHead className="min-w-[100px] whitespace-nowrap">P/R번호</TableHead>
                    <TableHead className="min-w-[120px] whitespace-nowrap">자재그룹(명)</TableHead>
                    <TableHead className="min-w-[100px] whitespace-nowrap">단가기준</TableHead>
                    <TableHead className="min-w-[100px] whitespace-nowrap">자재번호</TableHead>
                    <TableHead className="min-w-[200px] whitespace-nowrap">품목/자재내역</TableHead>
                    <TableHead className="min-w-[200px] whitespace-nowrap">자재내역사양</TableHead>
                    <TableHead className="min-w-[120px] whitespace-nowrap">설계자재번호</TableHead>
                    <TableHead className="min-w-[100px] whitespace-nowrap">Fitting No.</TableHead>
                    <TableHead className="min-w-[80px] whitespace-nowrap">Cert.</TableHead>
                    <TableHead className="min-w-[80px] whitespace-nowrap">재질</TableHead>
                    <TableHead className="min-w-[150px] whitespace-nowrap">규격</TableHead>
                    <TableHead className="min-w-[80px] text-right whitespace-nowrap">수량</TableHead>
                    <TableHead className="min-w-[80px] whitespace-nowrap">수량단위</TableHead>
                    <TableHead className="min-w-[80px] text-right whitespace-nowrap">중량</TableHead>
                    <TableHead className="min-w-[80px] whitespace-nowrap">중량단위</TableHead>
                    <TableHead className="min-w-[100px] text-right whitespace-nowrap">총중량</TableHead>
                    <TableHead className="min-w-[100px] text-right whitespace-nowrap">단가기준</TableHead>
                    <TableHead className="min-w-[80px] whitespace-nowrap">단가단위</TableHead>
                    <TableHead className="min-w-[100px] whitespace-nowrap">가격단위값</TableHead>
                    <TableHead className="min-w-[120px] text-right whitespace-nowrap">PO계약금액</TableHead>
                    <TableHead className="min-w-[100px] text-right whitespace-nowrap">조정금액</TableHead>
                    <TableHead className="min-w-[100px] whitespace-nowrap">납기일자</TableHead>
                    <TableHead className="min-w-[80px] whitespace-nowrap">VAT구분</TableHead>
                    <TableHead className="min-w-[120px] whitespace-nowrap">철의장 SPEC</TableHead>
                    <TableHead className="min-w-[100px] whitespace-nowrap">P/R 담당자</TableHead>
                  </TableRow>
                </TableHeader>
              <TableBody>
                {items.map((item, index) => (
                  <TableRow key={`${item.contractNo}-${item.itemNo}-${index}`}>
                    <TableCell className="font-medium">{item.contractNo || '-'}</TableCell>
                    <TableCell>{item.itemNo || '-'}</TableCell>
                    <TableCell>{item.prNo || '-'}</TableCell>
                    <TableCell>{item.materialGroup || '-'}</TableCell>
                    <TableCell>{item.priceStandard || '-'}</TableCell>
                    <TableCell className="font-mono text-sm">{item.materialNo || '-'}</TableCell>
                    <TableCell className="max-w-[200px]">
                      <div className="truncate" title={item.itemDescription || ''}>
                        {item.itemDescription || '-'}
                      </div>
                    </TableCell>
                    <TableCell className="max-w-[200px]">
                      <div className="truncate" title={item.materialSpec || ''}>
                        {item.materialSpec || '-'}
                      </div>
                    </TableCell>
                    <TableCell>{item.designMaterialNo || '-'}</TableCell>
                    <TableCell>{item.fittingNo || '-'}</TableCell>
                    <TableCell>{item.cert || '-'}</TableCell>
                    <TableCell>{item.material || '-'}</TableCell>
                    <TableCell>{item.specification || '-'}</TableCell>
                    <TableCell className="text-right font-mono">
                      {item.quantity?.toLocaleString() || '-'}
                    </TableCell>
                    <TableCell>{item.quantityUnit || '-'}</TableCell>
                    <TableCell className="text-right font-mono">
                      {item.weight ? item.weight.toLocaleString() : '-'}
                    </TableCell>
                    <TableCell>{item.weightUnit || '-'}</TableCell>
                    <TableCell className="text-right font-mono">
                      {item.totalWeight ? item.totalWeight.toLocaleString() : '-'}
                    </TableCell>
                    <TableCell className="text-right font-mono">
                      {item.unitPrice?.toLocaleString() || '-'}
                    </TableCell>
                    <TableCell>{item.priceUnit || '-'}</TableCell>
                    <TableCell>{item.priceUnitValue || '-'}</TableCell>
                    <TableCell className="text-right font-mono font-semibold">
                      {item.contractAmount?.toLocaleString() || '-'}
                    </TableCell>
                    <TableCell className="text-right font-mono">
                      {item.adjustmentAmount ? item.adjustmentAmount.toLocaleString() : '-'}
                    </TableCell>
                    <TableCell>{item.deliveryDate || '-'}</TableCell>
                    <TableCell>{item.vatType || '-'}</TableCell>
                    <TableCell>{item.steelSpec || '-'}</TableCell>
                    <TableCell>{item.prManager || '-'}</TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
            </div>
          )}
        </div>

        {items.length > 0 && (
          <div className="flex justify-between items-center pt-4 border-t flex-shrink-0">
            <div className="text-sm text-muted-foreground">
              총 {items.length}개 품목
            </div>
            <div className="text-sm font-medium">
              총 계약금액: {items.reduce((sum, item) => sum + item.contractAmount, 0).toLocaleString()} 원
            </div>
          </div>
        )}
      </DialogContent>
    </Dialog>
  )
}