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
|
import { Building2, Package, DollarSign, Calendar, FileText } from 'lucide-react'
import { formatDate } from '@/lib/utils'
import { GENERAL_CONTRACT_TYPE_LABELS, GeneralContractType } from '@/lib/general-contracts/types'
interface GeneralContractInfoHeaderProps {
contract: {
id: number
contractNumber: string
revision: number
status: string
category: string
type: string
name: string
vendorName?: string
vendorCode?: string
startDate: string
endDate: string
validityEndDate: string
contractAmount?: string
currency?: string
registeredAt: string
signedAt?: string
linkedRfqOrItb?: string
linkedBidNumber?: string
linkedPoNumber?: string
}
}
const statusLabels = {
'Draft': '임시저장',
'Request to Review': '조건검토요청',
'Confirm to Review': '조건검토완료',
'Contract Accept Request': '계약승인요청',
'Complete the Contract': '계약체결',
'Reject to Accept Contract': '계약승인거절',
'Contract Delete': '계약폐기',
'PCR Request': 'PCR요청',
'VO Request': 'VO요청',
'PCR Accept': 'PCR승인',
'PCR Reject': 'PCR거절'
}
const categoryLabels = {
'단가계약': '단가계약',
'일반계약': '일반계약',
'매각계약': '매각계약'
}
export function GeneralContractInfoHeader({ contract }: GeneralContractInfoHeaderProps) {
return (
<div className="bg-white border rounded-lg p-6 mb-6 shadow-sm">
{/* 3개 섹션을 Grid로 배치 - 각 섹션이 동일한 width로 꽉 채움 */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{/* 왼쪽 섹션: 계약 기본 정보 */}
<div className="w-full space-y-4">
{/* 계약번호 */}
<div className="mb-4">
<div className="flex items-center gap-2 text-sm text-gray-500 mb-2">
<FileText className="w-4 h-4" />
<span>계약번호 (Rev.)</span>
</div>
<div className="font-mono font-medium text-gray-900">
{contract.contractNumber} (Rev.{contract.revision})
</div>
</div>
{/* 계약명 */}
<div className="mb-4">
<div className="flex items-center gap-2 text-sm text-gray-500 mb-2">
<Package className="w-4 h-4" />
<span>계약명</span>
</div>
<div className="font-medium text-gray-900">{contract.name}</div>
</div>
{/* 협력업체 */}
<div className="mb-4">
<div className="flex items-center gap-2 text-sm text-gray-500 mb-2">
<Building2 className="w-4 h-4" />
<span>협력업체</span>
</div>
<div className="font-medium text-gray-900">
{contract.vendorName || '협력업체 미선택'}
{contract.vendorCode && (
<span className="text-sm text-gray-500 ml-2">({contract.vendorCode})</span>
)}
</div>
</div>
{/* 계약금액 */}
{contract.contractAmount && (
<div className="mb-4">
<div className="flex items-center gap-2 text-sm text-gray-500 mb-2">
<DollarSign className="w-4 h-4" />
<span>계약금액</span>
</div>
<div className="font-semibold text-gray-900">
{new Intl.NumberFormat('ko-KR', {
style: 'currency',
currency: contract.currency || 'KRW',
}).format(Number(contract.contractAmount))}
</div>
</div>
)}
</div>
{/* 가운데 섹션: 계약 분류 정보 */}
<div className="w-full border-l border-gray-100 pl-6">
<div className="space-y-3">
<div className="flex flex-col gap-1">
<span className="text-gray-500 text-sm">계약상태</span>
<span className="font-medium">{statusLabels[contract.status as keyof typeof statusLabels] || contract.status}</span>
</div>
<div className="flex flex-col gap-1">
<span className="text-gray-500 text-sm">계약구분</span>
<span className="font-medium">{categoryLabels[contract.category as keyof typeof categoryLabels] || contract.category}</span>
</div>
<div className="flex flex-col gap-1">
<span className="text-gray-500 text-sm">계약종류</span>
<span className="font-medium">{GENERAL_CONTRACT_TYPE_LABELS[contract.type as GeneralContractType] || contract.type}</span>
</div>
<div className="flex flex-col gap-1">
<span className="text-gray-500 text-sm">통화</span>
<span className="font-mono font-medium">{contract.currency || 'KRW'}</span>
</div>
</div>
</div>
{/* 오른쪽 섹션: 일정 및 연계 정보 */}
<div className="w-full border-l border-gray-100 pl-6">
<div className="flex items-center gap-2 mb-3 text-sm text-gray-500">
<Calendar className="w-4 h-4" />
<span>일정 및 연계 정보</span>
</div>
<div className="space-y-3">
<div>
<span className="text-gray-500 text-sm">계약기간</span>
<div className="font-medium">
{formatDate(contract.startDate, 'KR')} ~ {formatDate(contract.endDate, 'KR')}
</div>
</div>
<div>
<span className="text-gray-500 text-sm">계약 유효기간</span>
<div className="font-medium">{formatDate(contract.validityEndDate, 'KR')}</div>
</div>
{contract.signedAt && (
<div>
<span className="text-gray-500 text-sm">계약체결일</span>
<div className="font-medium">{formatDate(contract.signedAt, 'KR')}</div>
</div>
)}
{contract.registeredAt && (
<div>
<span className="text-gray-500 text-sm">등록일</span>
<div className="font-medium">{formatDate(contract.registeredAt, 'KR')}</div>
</div>
)}
{(contract.linkedRfqOrItb || contract.linkedBidNumber || contract.linkedPoNumber) && (
<div className="space-y-2">
<span className="text-gray-500 text-sm font-medium">연계 정보</span>
{contract.linkedRfqOrItb && (
<div>
<span className="text-gray-500 text-xs">연계 견적/입찰번호</span>
<div className="font-medium text-sm">{contract.linkedRfqOrItb}</div>
</div>
)}
{contract.linkedBidNumber && (
<div>
<span className="text-gray-500 text-xs">연계 BID번호</span>
<div className="font-medium text-sm">{contract.linkedBidNumber}</div>
</div>
)}
{contract.linkedPoNumber && (
<div>
<span className="text-gray-500 text-xs">연계 PO번호</span>
<div className="font-medium text-sm">{contract.linkedPoNumber}</div>
</div>
)}
</div>
)}
</div>
</div>
</div>
</div>
)
}
|