summaryrefslogtreecommitdiff
path: root/lib/b-rfq/initial/short-list-confirm-dialog.tsx
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-12-01 19:52:06 +0900
committerjoonhoekim <26rote@gmail.com>2025-12-01 19:52:06 +0900
commit44b74ff4170090673b6eeacd8c528e0abf47b7aa (patch)
tree3f3824b4e2cb24536c1677188b4cae5b8909d3da /lib/b-rfq/initial/short-list-confirm-dialog.tsx
parent4953e770929b82ef77da074f77071ebd0f428529 (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.tsx269
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