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
|
"use client"
import * as React from "react"
import { Badge } from "@/components/ui/badge"
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
interface SiteVisitRequest {
id: number
investigationId: number
requesterId: number | null
inspectionDuration: string | null
requestedStartDate: Date | null
requestedEndDate: Date | null
shiAttendees: Record<string, unknown> | null
shiAttendeeDetails?: string | null
vendorRequests: Record<string, unknown> | null
additionalRequests: string | null
status: string
sentAt: Date | null
createdAt: Date
updatedAt: Date
// 실사 정보
evaluationType: string | null //구매담당자가 작성한 실사방법
investigationMethod: string | null // QM담당자가 작성한 실사방법
investigationAddress: string | null
investigationNotes: string | null
forecastedAt: Date | null
actualAt: Date | null
result: string | null
resultNotes: string | null
// PQ 정보
pqItems: string | null
// 요청자 정보
requesterName: string | null
requesterEmail: string | null
requesterTitle: string | null
// QM 매니저 정보
qmManagerName: string | null
qmManagerEmail: string | null
qmManagerTitle: string | null
// 협력업체 정보
vendorInfo?: {
id: number
siteVisitRequestId: number
factoryName: string
factoryLocation: string
factoryAddress: string
factoryPicName: string
factoryPicPhone: string
factoryPicEmail: string
factoryDirections: string | null
accessProcedure: string | null
hasAttachments: boolean
otherInfo: string | null
submittedAt: Date
submittedBy: number
createdAt: Date
updatedAt: Date
} | null
// SHI 첨부파일
shiAttachments?: Array<{
id: number
siteVisitRequestId: number
vendorSiteVisitInfoId: number | null
fileName: string
originalFileName: string
filePath: string
fileSize: number
mimeType: string
createdAt: Date
updatedAt: Date
}> | null
}
interface ShiAttendeesDialogProps {
isOpen: boolean
onOpenChange: (open: boolean) => void
selectedRequest: SiteVisitRequest | null
}
export function ShiAttendeesDialog({
isOpen,
onOpenChange,
selectedRequest,
}: ShiAttendeesDialogProps) {
return (
<Dialog open={isOpen} onOpenChange={onOpenChange}>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>SHI 참석자 정보</DialogTitle>
<DialogDescription>
방문실사에 참석 예정인 SHI 인력 정보입니다.
</DialogDescription>
</DialogHeader>
{selectedRequest && selectedRequest.shiAttendees && (
<div className="space-y-4">
{Object.entries(selectedRequest.shiAttendees as Record<string, unknown>).map(([key, value]) => {
if (value && typeof value === 'object' && 'checked' in value && value.checked) {
const attendee = value as { checked: boolean; count: number; details?: string }
const departmentLabels: Record<string, string> = {
technicalSales: "기술영업",
design: "설계",
procurement: "구매",
quality: "품질",
production: "생산",
commissioning: "시운전",
other: "기타"
}
return (
<div key={key} className="border rounded-lg p-4">
<div className="flex items-center justify-between mb-2">
<h4 className="font-semibold">{departmentLabels[key] || key}</h4>
<Badge variant="outline">{attendee.count}명</Badge>
</div>
{attendee.details && (
<div className="text-sm text-muted-foreground">
<span className="font-medium">참석자 정보:</span> {attendee.details}
</div>
)}
</div>
)
}
return null
})}
{/* 전체 참석자 상세정보 */}
{selectedRequest.shiAttendeeDetails && (
<div className="border rounded-lg p-4">
<h4 className="font-semibold mb-2">전체 참석자 상세정보</h4>
<p className="text-sm whitespace-pre-wrap">{selectedRequest.shiAttendeeDetails}</p>
</div>
)}
</div>
)}
</DialogContent>
</Dialog>
)
}
|