diff options
Diffstat (limited to 'lib/rfq-last/vendor/add-vendor-dialog.tsx')
| -rw-r--r-- | lib/rfq-last/vendor/add-vendor-dialog.tsx | 231 |
1 files changed, 56 insertions, 175 deletions
diff --git a/lib/rfq-last/vendor/add-vendor-dialog.tsx b/lib/rfq-last/vendor/add-vendor-dialog.tsx index bcf882a1..eddd09b0 100644 --- a/lib/rfq-last/vendor/add-vendor-dialog.tsx +++ b/lib/rfq-last/vendor/add-vendor-dialog.tsx @@ -11,34 +11,18 @@ import { } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; -import { - Command, - CommandEmpty, - CommandGroup, - CommandInput, - CommandItem, - CommandList, -} from "@/components/ui/command"; -import { - Popover, - PopoverContent, - PopoverTrigger -} from "@/components/ui/popover"; -import { Check, ChevronsUpDown, Loader2, X, Plus, FileText, Shield, Globe, Settings } from "lucide-react"; -import { cn } from "@/lib/utils"; +import { Loader2, X } from "lucide-react"; import { toast } from "sonner"; import { addVendorsToRfq, getRfqItemsAction } from "../service"; -import { getVendorsForSelection } from "@/lib/b-rfq/service"; import { Badge } from "@/components/ui/badge"; import { getMrcTypeByMatnr } from "@/lib/mdg/actions/material-service"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { ScrollArea } from "@/components/ui/scroll-area"; -import { Alert, AlertDescription } from "@/components/ui/alert"; -import { Info } from "lucide-react"; import { Checkbox } from "@/components/ui/checkbox"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; -import { Separator } from "@/components/ui/separator"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { VendorSelector } from "@/components/common/vendor/vendor-selector"; +import { VendorSearchItem } from "@/components/common/vendor/vendor-service"; interface VendorContract { vendorId: number; @@ -63,9 +47,7 @@ export function AddVendorDialog({ onSuccess, }: AddVendorDialogProps) { const [isLoading, setIsLoading] = React.useState(false); - const [vendorOpen, setVendorOpen] = React.useState(false); - const [vendorList, setVendorList] = React.useState<any[]>([]); - const [selectedVendors, setSelectedVendors] = React.useState<any[]>([]); + const [selectedVendors, setSelectedVendors] = React.useState<VendorSearchItem[]>([]); const [activeTab, setActiveTab] = React.useState<"vendors" | "contracts">("vendors"); // 각 벤더별 기본계약 요구사항 상태 @@ -148,25 +130,11 @@ export function AddVendorDialog({ } }, [rfqId]); - // 벤더 로드 - const loadVendors = React.useCallback(async () => { - try { - const result = await getVendorsForSelection(); - if (result) { - setVendorList(result); - } - } catch (error) { - console.error("Failed to load vendors:", error); - toast.error("벤더 목록을 불러오는데 실패했습니다."); - } - }, []); - React.useEffect(() => { if (open) { - loadVendors(); checkMrcType(); } - }, [open, loadVendors, checkMrcType]); + }, [open, checkMrcType]); // 초기화 React.useEffect(() => { @@ -184,17 +152,28 @@ export function AddVendorDialog({ }, [open]); // 외자업체 여부 확인 - const isInternationalVendor = (vendor: any) => { + const isInternationalVendor = (vendor: VendorSearchItem) => { return vendor.country && vendor.country !== "KR" && vendor.country !== "한국"; }; - // 벤더 추가 - const handleAddVendor = (vendor: any) => { - if (!selectedVendors.find(v => v.id === vendor.id)) { - const updatedVendors = [...selectedVendors, vendor]; - setSelectedVendors(updatedVendors); - - // 해당 벤더의 기본계약 설정 추가 + // 벤더 선택 변경 핸들러 + const handleVendorsChange = (vendors: VendorSearchItem[]) => { + const prevVendorIds = selectedVendors.map(v => v.id); + const newVendorIds = vendors.map(v => v.id); + + // 새로 추가된 벤더들 찾기 + const addedVendors = vendors.filter(v => !prevVendorIds.includes(v.id)); + + // 제거된 벤더들 찾기 + const removedVendorIds = prevVendorIds.filter(id => !newVendorIds.includes(id)); + + // 제거된 벤더의 계약 정보 삭제 + if (removedVendorIds.length > 0) { + setVendorContracts(vendorContracts.filter(c => !removedVendorIds.includes(c.vendorId))); + } + + // 새로 추가된 벤더의 계약 정보 추가 + const newContracts = addedVendors.map(vendor => { const isInternational = isInternationalVendor(vendor); let shouldCheckAgreement = false; @@ -207,23 +186,19 @@ export function AddVendorDialog({ shouldCheckAgreement = hasMrcTypeP && !isInternational; } - setVendorContracts([ - ...vendorContracts, - { - vendorId: vendor.id, - agreementYn: shouldCheckAgreement, - ndaYn: shouldCheckAgreement, - gtcType: isInternational ? defaultContract.gtcType : "none" - } - ]); + return { + vendorId: vendor.id, + agreementYn: shouldCheckAgreement, + ndaYn: shouldCheckAgreement, + gtcType: isInternational ? defaultContract.gtcType : "none" + }; + }); + + if (newContracts.length > 0) { + setVendorContracts([...vendorContracts, ...newContracts]); } - setVendorOpen(false); - }; - - // 벤더 제거 - const handleRemoveVendor = (vendorId: number) => { - setSelectedVendors(selectedVendors.filter(v => v.id !== vendorId)); - setVendorContracts(vendorContracts.filter(c => c.vendorId !== vendorId)); + + setSelectedVendors(vendors); }; // 개별 벤더의 계약 설정 업데이트 @@ -308,11 +283,6 @@ export function AddVendorDialog({ } }; - // 이미 선택된 벤더인지 확인 - const isVendorSelected = (vendorId: number) => { - return selectedVendors.some(v => v.id === vendorId); - }; - // 선택된 벤더가 있고 계약 탭으로 이동 가능한지 const canProceedToContracts = selectedVendors.length > 0; @@ -354,112 +324,21 @@ export function AddVendorDialog({ </CardHeader> <CardContent> <div className="space-y-4"> - {/* 벤더 추가 버튼 */} - <Popover open={vendorOpen} onOpenChange={setVendorOpen}> - <PopoverTrigger asChild> - <Button - variant="outline" - role="combobox" - aria-expanded={vendorOpen} - className="w-full justify-between" - disabled={vendorList.length === 0} - > - <span className="flex items-center gap-2"> - <Plus className="h-4 w-4" /> - 벤더 선택하기 - </span> - <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" /> - </Button> - </PopoverTrigger> - <PopoverContent className="w-[500px] p-0" align="start"> - <Command> - <CommandInput placeholder="벤더명 또는 코드로 검색..." /> - <CommandList - onWheel={(e) => { - e.stopPropagation(); - const target = e.currentTarget; - target.scrollTop += e.deltaY; - }} - > - <CommandEmpty>검색 결과가 없습니다.</CommandEmpty> - <CommandGroup> - {vendorList - .filter(vendor => !isVendorSelected(vendor.id)) - .map((vendor) => ( - <CommandItem - key={vendor.id} - value={`${vendor.vendorCode} ${vendor.vendorName}`} - onSelect={() => handleAddVendor(vendor)} - > - <div className="flex items-center gap-2 w-full"> - <Badge variant="outline" className="shrink-0"> - {vendor.vendorCode} - </Badge> - <span className="truncate">{vendor.vendorName}</span> - {vendor.country && ( - <Badge - variant={vendor.country === "KR" || vendor.country === "한국" ? "default" : "secondary"} - className="ml-auto" - > - {vendor.country} - </Badge> - )} - </div> - </CommandItem> - ))} - </CommandGroup> - </CommandList> - </Command> - </PopoverContent> - </Popover> - - {/* 선택된 벤더 목록 */} - {selectedVendors.length > 0 && ( - <div className="space-y-2"> - - <div className="space-y-2"> - {selectedVendors.map((vendor, index) => ( - <div - key={vendor.id} - className="flex items-center justify-between p-2 rounded-lg bg-secondary/50" - > - <div className="flex items-center gap-2"> - <span className="text-sm text-muted-foreground"> - {index + 1}. - </span> - <Badge variant="outline"> - {vendor.vendorCode} - </Badge> - <span className="text-sm font-medium"> - {vendor.vendorName} - </span> - {vendor.country && ( - <Badge - variant={vendor.country === "KR" || vendor.country === "한국" ? "default" : "secondary"} - className="text-xs" - > - {vendor.country} - </Badge> - )} - </div> - <Button - variant="ghost" - size="sm" - onClick={() => handleRemoveVendor(vendor.id)} - className="h-8 w-8 p-0" - > - <X className="h-4 w-4" /> - </Button> - </div> - ))} - </div> - </div> - )} + {/* 벤더 선택 */} + <VendorSelector + selectedVendors={selectedVendors} + onVendorsChange={handleVendorsChange} + singleSelect={false} + placeholder="벤더명 또는 코드로 검색..." + noValuePlaceHolder="벤더를 선택하세요" + showInitialData={true} + includeCountry={true} + /> {selectedVendors.length === 0 && ( <div className="text-center py-8 text-muted-foreground"> <p className="text-sm">아직 선택된 벤더가 없습니다.</p> - <p className="text-xs mt-1">위 버튼을 클릭하여 벤더를 추가하세요.</p> + <p className="text-xs mt-1">위 필드를 클릭하여 벤더를 검색하고 추가하세요.</p> </div> )} </div> @@ -564,14 +443,16 @@ export function AddVendorDialog({ <div key={vendor.id} className="border rounded-lg p-4 space-y-3"> <div className="flex items-center justify-between"> <div className="flex items-center gap-2"> - <Badge variant="outline">{vendor.vendorCode}</Badge> + <Badge variant="outline">{vendor.vendorCode || "-"}</Badge> <span className="font-medium">{vendor.vendorName}</span> - <Badge - variant={isInternational ? "secondary" : "default"} - className="text-xs" - > - {vendor.country || "미지정"} - </Badge> + {vendor.country && ( + <Badge + variant={isInternational ? "secondary" : "default"} + className="text-xs" + > + {vendor.country} + </Badge> + )} </div> </div> |
