"use client" import React, { useState, useCallback } from "react" import { Button } from "@/components/ui/button" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" import { VendorSelector } from "./vendor-selector" import { VendorSearchItem } from "./vendor-service" /** * 벤더 단일 선택 Dialog 컴포넌트 * * @description * - VendorSelector를 Dialog로 래핑한 단일 선택 컴포넌트 * - 버튼 클릭 시 Dialog가 열리고, 벤더를 선택하면 Dialog가 닫히며 결과를 반환 * * @VendorSearchItem_Structure * 상태에서 관리되는 벤더 객체의 형태: * ```typescript * interface VendorSearchItem { * id: number; // 벤더 ID * vendorName: string; // 벤더명 * vendorCode: string | null; // 벤더코드 (없을 수 있음) * taxId: string | null; // 사업자번호 * status: string; // 벤더 상태 (ACTIVE, PENDING_REVIEW 등) * displayText: string; // 표시용 텍스트 (vendorName + vendorCode) * } * ``` * * @state * - open: Dialog 열림/닫힘 상태 * - selectedVendor: 현재 선택된 벤더 (단일) * - tempSelectedVendor: Dialog 내에서 임시로 선택된 벤더 (확인 버튼 클릭 전까지) * * @callback * - onVendorSelect: 벤더 선택 완료 시 호출되는 콜백 * - 매개변수: VendorSearchItem | null * - 선택된 벤더 정보 또는 null (선택 해제 시) * * @usage * ```tsx * { * setSelectedVendor(vendor); * console.log('선택된 벤더:', vendor); * }} * placeholder="벤더를 검색하세요..." * /> * ``` */ interface VendorSelectorDialogSingleProps { /** Dialog를 여는 트리거 버튼 텍스트 */ triggerLabel?: string /** 현재 선택된 벤더 */ selectedVendor?: VendorSearchItem | null /** 벤더 선택 완료 시 호출되는 콜백 */ onVendorSelect?: (vendor: VendorSearchItem | null) => void /** 검색 입력창 placeholder */ placeholder?: string /** Dialog 제목 */ title?: string /** Dialog 설명 */ description?: string /** 트리거 버튼 비활성화 여부 */ disabled?: boolean /** 트리거 버튼 variant */ triggerVariant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" /** 제외할 벤더 ID들 */ excludeVendorIds?: Set /** 초기 데이터 표시 여부 */ showInitialData?: boolean /** 벤더 상태 필터 */ statusFilter?: string } export function VendorSelectorDialogSingle({ triggerLabel = "벤더 선택", selectedVendor = null, onVendorSelect, placeholder = "벤더를 검색하세요...", title = "벤더 선택", description = "원하는 벤더를 검색하고 선택해주세요.", disabled = false, triggerVariant = "outline", excludeVendorIds, showInitialData = true, statusFilter }: VendorSelectorDialogSingleProps) { // Dialog 열림/닫힘 상태 const [open, setOpen] = useState(false) // Dialog 내에서 임시로 선택된 벤더 (확인 버튼 클릭 전까지) const [tempSelectedVendor, setTempSelectedVendor] = useState(null) // Dialog 열림 시 현재 선택된 벤더로 임시 선택 초기화 const handleOpenChange = useCallback((newOpen: boolean) => { setOpen(newOpen) if (newOpen) { setTempSelectedVendor(selectedVendor || null) } }, [selectedVendor]) // 벤더 선택 처리 (Dialog 내에서) const handleVendorChange = useCallback((vendors: VendorSearchItem[]) => { setTempSelectedVendor(vendors.length > 0 ? vendors[0] : null) }, []) // 확인 버튼 클릭 시 선택 완료 const handleConfirm = useCallback(() => { onVendorSelect?.(tempSelectedVendor) setOpen(false) }, [tempSelectedVendor, onVendorSelect]) // 취소 버튼 클릭 시 const handleCancel = useCallback(() => { setTempSelectedVendor(selectedVendor || null) setOpen(false) }, [selectedVendor]) // 선택 해제 const handleClear = useCallback(() => { setTempSelectedVendor(null) }, []) return ( {title} {description}
{tempSelectedVendor && ( )}
) } /** * 사용 예시: * * ```tsx * const [selectedVendor, setSelectedVendor] = useState(null); * * return ( * { * setSelectedVendor(vendor); * if (vendor) { * console.log('선택된 벤더:', { * id: vendor.id, * name: vendor.vendorName, * code: vendor.vendorCode, * status: vendor.status * }); * } else { * console.log('벤더 선택이 해제되었습니다.'); * } * }} * title="벤더 선택" * description="협력업체를 검색하고 선택해주세요." * statusFilter="ACTIVE" // ACTIVE 상태의 벤더만 표시 * /> * ); * ``` */