diff options
| author | joonhoekim <26rote@gmail.com> | 2025-12-01 19:52:06 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-12-01 19:52:06 +0900 |
| commit | 44b74ff4170090673b6eeacd8c528e0abf47b7aa (patch) | |
| tree | 3f3824b4e2cb24536c1677188b4cae5b8909d3da /lib/b-rfq/initial/short-list-confirm-dialog.tsx | |
| parent | 4953e770929b82ef77da074f77071ebd0f428529 (diff) | |
(김준회) deprecated code 정리
Diffstat (limited to 'lib/b-rfq/initial/short-list-confirm-dialog.tsx')
| -rw-r--r-- | lib/b-rfq/initial/short-list-confirm-dialog.tsx | 269 |
1 files changed, 0 insertions, 269 deletions
diff --git a/lib/b-rfq/initial/short-list-confirm-dialog.tsx b/lib/b-rfq/initial/short-list-confirm-dialog.tsx deleted file mode 100644 index 92c62dc0..00000000 --- a/lib/b-rfq/initial/short-list-confirm-dialog.tsx +++ /dev/null @@ -1,269 +0,0 @@ -"use client" - -import * as React from "react" -import { zodResolver } from "@hookform/resolvers/zod" -import { useForm } from "react-hook-form" -import { toast } from "sonner" -import { z } from "zod" -import { Loader2, Building, CheckCircle2, XCircle } from "lucide-react" - -import { Button } from "@/components/ui/button" -import { Checkbox } from "@/components/ui/checkbox" -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from "@/components/ui/dialog" -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from "@/components/ui/form" -import { Badge } from "@/components/ui/badge" -import { Separator } from "@/components/ui/separator" -import { ScrollArea } from "@/components/ui/scroll-area" - -import { shortListConfirm } from "../service" -import { InitialRfqDetailView } from "@/db/schema" - -const shortListSchema = z.object({ - selectedVendorIds: z.array(z.number()).min(1, "최소 1개 이상의 벤더를 선택해야 합니다."), -}) - -type ShortListFormData = z.infer<typeof shortListSchema> - -interface ShortListConfirmDialogProps { - open: boolean - onOpenChange: (open: boolean) => void - rfqId: number - vendors: InitialRfqDetailView[] - onSuccess?: () => void -} - -export function ShortListConfirmDialog({ - open, - onOpenChange, - rfqId, - vendors, - onSuccess -}: ShortListConfirmDialogProps) { - const [isLoading, setIsLoading] = React.useState(false) - - const form = useForm<ShortListFormData>({ - resolver: zodResolver(shortListSchema), - defaultValues: { - selectedVendorIds: vendors - .filter(vendor => vendor.shortList === true) - .map(vendor => vendor.vendorId) - .filter(Boolean) as number[] - }, - }) - - const watchedSelectedIds = form.watch("selectedVendorIds") - - // 선택된/탈락된 벤더 계산 - const selectedVendors = vendors.filter(vendor => - vendor.vendorId && watchedSelectedIds.includes(vendor.vendorId) - ) - const rejectedVendors = vendors.filter(vendor => - vendor.vendorId && !watchedSelectedIds.includes(vendor.vendorId) - ) - - async function onSubmit(data: ShortListFormData) { - if (!rfqId) return - - setIsLoading(true) - - try { - const result = await shortListConfirm({ - rfqId, - selectedVendorIds: data.selectedVendorIds, - rejectedVendorIds: vendors - .filter(v => v.vendorId && !data.selectedVendorIds.includes(v.vendorId)) - .map(v => v.vendorId!) - }) - - if (result.success) { - toast.success(result.message) - onOpenChange(false) - form.reset() - onSuccess?.() - } else { - toast.error(result.message || "Short List 확정에 실패했습니다.") - } - } catch (error) { - console.error("Short List confirm error:", error) - toast.error("Short List 확정 중 오류가 발생했습니다.") - } finally { - setIsLoading(false) - } - } - - const handleVendorToggle = (vendorId: number, checked: boolean) => { - const currentSelected = form.getValues("selectedVendorIds") - - if (checked) { - form.setValue("selectedVendorIds", [...currentSelected, vendorId]) - } else { - form.setValue("selectedVendorIds", currentSelected.filter(id => id !== vendorId)) - } - } - - return ( - <Dialog open={open} onOpenChange={onOpenChange}> - <DialogContent className="max-w-4xl max-h-[80vh]"> - <DialogHeader> - <DialogTitle className="flex items-center gap-2"> - <CheckCircle2 className="h-5 w-5 text-green-600" /> - Short List 확정 - </DialogTitle> - <DialogDescription> - 최종 RFQ로 진행할 벤더를 선택해주세요. 선택되지 않은 벤더에게는 자동으로 Letter of Regret이 발송됩니다. - </DialogDescription> - </DialogHeader> - - <Form {...form}> - <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6"> - <FormField - control={form.control} - name="selectedVendorIds" - render={() => ( - <FormItem> - <FormLabel className="text-base font-semibold"> - 벤더 선택 ({vendors.length}개 업체) - </FormLabel> - <FormControl> - <ScrollArea className="h-[400px] border rounded-md p-4"> - <div className="space-y-4"> - {vendors.map((vendor) => { - const isSelected = vendor.vendorId && watchedSelectedIds.includes(vendor.vendorId) - - return ( - <div - key={vendor.vendorId} - className={`flex items-start space-x-3 p-3 rounded-lg border transition-colors ${ - isSelected - ? 'border-green-200 bg-green-50' - : 'border-red-100 bg-red-50' - }`} - > - <Checkbox - checked={isSelected} - onCheckedChange={(checked) => - vendor.vendorId && handleVendorToggle(vendor.vendorId, !!checked) - } - className="mt-1" - /> - <div className="flex-1 space-y-2"> - <div className="flex items-center gap-2"> - <Building className="h-4 w-4 text-muted-foreground" /> - <span className="font-medium">{vendor.vendorName}</span> - {isSelected ? ( - <Badge variant="secondary" className="bg-green-100 text-green-800"> - 선택됨 - </Badge> - ) : ( - <Badge variant="secondary" className="bg-red-100 text-red-800"> - 탈락 - </Badge> - )} - </div> - <div className="text-sm text-muted-foreground"> - <span className="font-mono">{vendor.vendorCode}</span> - {vendor.vendorCountry && ( - <> - <span className="mx-2">•</span> - <span>{vendor.vendorCountry === "KR" ? "국내" : "해외"}</span> - </> - )} - {vendor.vendorCategory && ( - <> - <span className="mx-2">•</span> - <span>{vendor.vendorCategory}</span> - </> - )} - {vendor.vendorBusinessSize && ( - <> - <span className="mx-2">•</span> - <span>{vendor.vendorBusinessSize}</span> - </> - )} - </div> - <div className="text-xs text-muted-foreground"> - RFQ 상태: <Badge variant="outline" className="text-xs"> - {vendor.initialRfqStatus} - </Badge> - </div> - </div> - </div> - ) - })} - </div> - </ScrollArea> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - - {/* 요약 정보 */} - <div className="grid grid-cols-2 gap-4 p-4 bg-muted/50 rounded-lg"> - <div className="space-y-2"> - <div className="flex items-center gap-2 text-green-700"> - <CheckCircle2 className="h-4 w-4" /> - <span className="font-medium">선택된 벤더</span> - </div> - <div className="text-2xl font-bold text-green-700"> - {selectedVendors.length}개 업체 - </div> - {selectedVendors.length > 0 && ( - <div className="text-sm text-muted-foreground"> - {selectedVendors.map(v => v.vendorName).join(", ")} - </div> - )} - </div> - <div className="space-y-2"> - <div className="flex items-center gap-2 text-red-700"> - <XCircle className="h-4 w-4" /> - <span className="font-medium">탈락 벤더</span> - </div> - <div className="text-2xl font-bold text-red-700"> - {rejectedVendors.length}개 업체 - </div> - {rejectedVendors.length > 0 && ( - <div className="text-sm text-muted-foreground"> - Letter of Regret 발송 예정 - </div> - )} - </div> - </div> - - <DialogFooter> - <Button - type="button" - variant="outline" - onClick={() => onOpenChange(false)} - disabled={isLoading} - > - 취소 - </Button> - <Button - type="submit" - disabled={isLoading || selectedVendors.length === 0} - > - {isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} - Short List 확정 - </Button> - </DialogFooter> - </form> - </Form> - </DialogContent> - </Dialog> - ) -}
\ No newline at end of file |
