summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-12-08 10:19:28 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-12-08 10:19:28 +0000
commitb5ef49dce92c8994530f6ff670c81693c8716daf (patch)
treee4a611bb1abe5e9925977ac2cb6ee0b231a7381a /lib
parenta346304c13b600c18bbea3f9ce21b1399b1310e9 (diff)
(최겸) 구매 방문실사 도로명주소 적용
Diffstat (limited to 'lib')
-rw-r--r--lib/site-visit/client-site-visit-wrapper.tsx1
-rw-r--r--lib/site-visit/site-visit-detail-dialog.tsx67
-rw-r--r--lib/site-visit/vendor-info-sheet.tsx58
3 files changed, 58 insertions, 68 deletions
diff --git a/lib/site-visit/client-site-visit-wrapper.tsx b/lib/site-visit/client-site-visit-wrapper.tsx
index ab63fa0b..f2655475 100644
--- a/lib/site-visit/client-site-visit-wrapper.tsx
+++ b/lib/site-visit/client-site-visit-wrapper.tsx
@@ -496,6 +496,7 @@ export function ClientSiteVisitWrapper({
hasAttachments: siteVisitRequests.find(r => r.id === selectedSiteVisitRequestId)?.vendorInfo?.hasAttachments || false,
otherInfo: siteVisitRequests.find(r => r.id === selectedSiteVisitRequestId)?.vendorInfo?.otherInfo || "",
} : null}
+ vendorCountry={siteVisitRequests.find(r => r.id === selectedSiteVisitRequestId)?.vendorInfo?.country || ""}
/>
)}
diff --git a/lib/site-visit/site-visit-detail-dialog.tsx b/lib/site-visit/site-visit-detail-dialog.tsx
index 74e749c4..634d2aef 100644
--- a/lib/site-visit/site-visit-detail-dialog.tsx
+++ b/lib/site-visit/site-visit-detail-dialog.tsx
@@ -7,7 +7,6 @@ import { FileText, Download } from "lucide-react"
import { toast } from "sonner"
import { Button } from "@/components/ui/button"
-import { Input } from "@/components/ui/input"
import {
Dialog,
DialogContent,
@@ -59,7 +58,6 @@ interface SiteVisitRequest {
// 협력업체 정보
vendorInfo?: {
id: number
- country?: string
siteVisitRequestId: number
factoryName: string
factoryLocation: string
@@ -103,40 +101,6 @@ export function SiteVisitDetailDialog({
onOpenChange,
selectedRequest,
}: SiteVisitDetailDialogProps) {
- const vendorCountry = (selectedRequest?.vendorInfo as any)?.country || ""
- const isDomestic = vendorCountry === "KR"
-
- const [factoryLocation, setFactoryLocation] = React.useState(
- selectedRequest?.vendorInfo?.factoryLocation || ""
- )
- const [factoryAddress, setFactoryAddress] = React.useState(
- selectedRequest?.vendorInfo?.factoryAddress || ""
- )
-
- React.useEffect(() => {
- setFactoryLocation(selectedRequest?.vendorInfo?.factoryLocation || "")
- setFactoryAddress(selectedRequest?.vendorInfo?.factoryAddress || "")
- }, [selectedRequest?.vendorInfo?.factoryLocation, selectedRequest?.vendorInfo?.factoryAddress])
-
- React.useEffect(() => {
- const handleMessage = (event: MessageEvent) => {
- if (!event.data || event.data.type !== "JUSO_SELECTED") return
- const { roadAddrPart1, roadAddrPart2, addrDetail } = event.data.payload || {}
- const combinedRoad = [roadAddrPart1, roadAddrPart2].filter(Boolean).join(" ").trim()
- setFactoryLocation(combinedRoad || factoryLocation)
- setFactoryAddress(addrDetail || factoryAddress)
- }
- window.addEventListener("message", handleMessage)
- return () => window.removeEventListener("message", handleMessage)
- }, [factoryLocation, factoryAddress])
-
- const handleJusoSearch = () => {
- window.open(
- "/api/juso",
- "jusoSearch",
- "width=570,height=420,scrollbars=yes,resizable=yes"
- )
- }
return (
<Dialog open={isOpen} onOpenChange={onOpenChange}>
@@ -165,35 +129,8 @@ export function SiteVisitDetailDialog({
<h4 className="font-semibold mb-2">공장 기본 정보</h4>
<div className="space-y-2 text-sm">
<div><span className="font-medium">공장명:</span> {selectedRequest.vendorInfo.factoryName}</div>
- <div className="flex items-center justify-between gap-2">
- <span className="font-medium">공장위치(도로명):</span>
- {isDomestic && (
- <Button
- type="button"
- variant="secondary"
- size="sm"
- onClick={handleJusoSearch}
- aria-label="도로명 주소 검색"
- >
- 주소 검색
- </Button>
- )}
- </div>
- <Input
- value={factoryLocation}
- onChange={(e) => setFactoryLocation(e.target.value)}
- readOnly={!isDomestic}
- className={!isDomestic ? "" : "bg-muted text-muted-foreground"}
- placeholder="도로명 주소"
- />
- <div><span className="font-medium">공장주소(상세):</span></div>
- <Input
- value={factoryAddress}
- onChange={(e) => setFactoryAddress(e.target.value)}
- readOnly={!isDomestic}
- className={!isDomestic ? "" : "bg-muted text-muted-foreground"}
- placeholder="상세 주소"
- />
+ <div><span className="font-medium">공장위치:</span> {selectedRequest.vendorInfo.factoryLocation}</div>
+ <div><span className="font-medium">공장주소:</span> {selectedRequest.vendorInfo.factoryAddress}</div>
</div>
</div>
diff --git a/lib/site-visit/vendor-info-sheet.tsx b/lib/site-visit/vendor-info-sheet.tsx
index 2a20e212..ad2fa16b 100644
--- a/lib/site-visit/vendor-info-sheet.tsx
+++ b/lib/site-visit/vendor-info-sheet.tsx
@@ -61,6 +61,7 @@ interface VendorInfoSheetProps {
onSubmit: (data: VendorInfoFormValues & { attachments?: File[] }) => Promise<void>
siteVisitRequestId: number
initialData?: VendorInfoFormValues | null
+ vendorCountry?: string
}
export function VendorInfoSheet({
@@ -69,10 +70,12 @@ export function VendorInfoSheet({
onSubmit,
siteVisitRequestId,
initialData,
+ vendorCountry = "",
}: VendorInfoSheetProps) {
const [isPending, setIsPending] = React.useState(false)
const [selectedFiles, setSelectedFiles] = React.useState<File[]>([])
const fileInputRef = React.useRef<HTMLInputElement>(null)
+ const isDomestic = vendorCountry === "KR"
const form = useForm<VendorInfoFormValues>({
resolver: zodResolver(vendorInfoSchema),
@@ -114,6 +117,36 @@ export function VendorInfoSheet({
}
}, [isOpen, form, initialData])
+ // 도로명 주소 검색 결과 수신 (내자만 적용)
+ React.useEffect(() => {
+ if (!isOpen || !isDomestic) return
+
+ const handleMessage = (event: MessageEvent) => {
+ if (!event.data || event.data.type !== "JUSO_SELECTED") return
+ const { roadAddrPart1, roadAddrPart2, addrDetail } = event.data.payload || {}
+ const combinedRoad = [roadAddrPart1, roadAddrPart2].filter(Boolean).join(" ").trim()
+
+ if (combinedRoad) {
+ form.setValue("factoryLocation", combinedRoad, { shouldDirty: true })
+ }
+ if (addrDetail) {
+ form.setValue("factoryAddress", addrDetail, { shouldDirty: true })
+ }
+ }
+
+ window.addEventListener("message", handleMessage)
+ return () => window.removeEventListener("message", handleMessage)
+ }, [isOpen, isDomestic, form])
+
+ const handleJusoSearch = () => {
+ if (!isDomestic) return
+ window.open(
+ "/api/juso",
+ "jusoSearch",
+ "width=570,height=420,scrollbars=yes,resizable=yes"
+ )
+ }
+
// 파일 업로드 핸들러
const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
const files = event.target.files
@@ -202,7 +235,25 @@ export function VendorInfoSheet({
<FormItem>
<FormLabel>실사 지역 *</FormLabel>
<FormControl>
- <Input placeholder="국가 또는 지역 (예: Finland, 부산)" {...field} disabled={isPending} />
+ <div className="flex gap-2">
+ <Input
+ placeholder="국가 또는 지역 (예: Finland, 부산)"
+ {...field}
+ disabled={isPending || isDomestic}
+ readOnly={isDomestic}
+ className={isDomestic ? "bg-muted text-muted-foreground" : undefined}
+ />
+ {isDomestic && (
+ <Button
+ type="button"
+ variant="secondary"
+ onClick={handleJusoSearch}
+ disabled={isPending}
+ >
+ 주소 검색
+ </Button>
+ )}
+ </div>
</FormControl>
<FormMessage />
</FormItem>
@@ -220,8 +271,9 @@ export function VendorInfoSheet({
<Textarea
placeholder="상세 주소를 입력하세요"
{...field}
- disabled={isPending}
- className="min-h-[80px]"
+ disabled={isPending || isDomestic}
+ readOnly={isDomestic}
+ className={isDomestic ? "bg-muted text-muted-foreground min-h-[80px]" : "min-h-[80px]"}
/>
</FormControl>
<FormMessage />