summaryrefslogtreecommitdiff
path: root/lib/bidding/detail/table/price-adjustment-dialog.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bidding/detail/table/price-adjustment-dialog.tsx')
-rw-r--r--lib/bidding/detail/table/price-adjustment-dialog.tsx195
1 files changed, 195 insertions, 0 deletions
diff --git a/lib/bidding/detail/table/price-adjustment-dialog.tsx b/lib/bidding/detail/table/price-adjustment-dialog.tsx
new file mode 100644
index 00000000..14bbd843
--- /dev/null
+++ b/lib/bidding/detail/table/price-adjustment-dialog.tsx
@@ -0,0 +1,195 @@
+"use client"
+
+import * as React from "react"
+import { Button } from "@/components/ui/button"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog"
+import { Label } from "@/components/ui/label"
+import { Textarea } from "@/components/ui/textarea"
+import { Switch } from "@/components/ui/switch"
+import { useToast } from "@/hooks/use-toast"
+import { updatePriceAdjustmentInfo } from "@/lib/bidding/detail/service"
+import { QuotationVendor } from "@/lib/bidding/detail/service"
+import { Loader2 } from "lucide-react"
+
+interface PriceAdjustmentDialogProps {
+ open: boolean
+ onOpenChange: (open: boolean) => void
+ vendor: QuotationVendor | null
+ onSuccess: () => void
+}
+
+export function PriceAdjustmentDialog({
+ open,
+ onOpenChange,
+ vendor,
+ onSuccess,
+}: PriceAdjustmentDialogProps) {
+ const { toast } = useToast()
+ const [isSubmitting, setIsSubmitting] = React.useState(false)
+
+ // 폼 상태
+ const [shiPriceAdjustmentApplied, setSHIPriceAdjustmentApplied] = React.useState<boolean | null>(null)
+ const [priceAdjustmentNote, setPriceAdjustmentNote] = React.useState("")
+ const [hasChemicalSubstance, setHasChemicalSubstance] = React.useState<boolean | null>(null)
+
+ // 다이얼로그가 열릴 때 벤더 정보로 폼 초기화
+ React.useEffect(() => {
+ if (open && vendor) {
+ setSHIPriceAdjustmentApplied(vendor.shiPriceAdjustmentApplied ?? null)
+ setPriceAdjustmentNote(vendor.priceAdjustmentNote || "")
+ setHasChemicalSubstance(vendor.hasChemicalSubstance ?? null)
+ }
+ }, [open, vendor])
+
+ const handleSubmit = async () => {
+ if (!vendor) return
+
+ setIsSubmitting(true)
+ try {
+ const result = await updatePriceAdjustmentInfo({
+ biddingCompanyId: vendor.id,
+ shiPriceAdjustmentApplied,
+ priceAdjustmentNote: priceAdjustmentNote || null,
+ hasChemicalSubstance,
+ })
+
+ if (result.success) {
+ toast({
+ title: "저장 완료",
+ description: "연동제 정보가 저장되었습니다.",
+ })
+ onOpenChange(false)
+ onSuccess()
+ } else {
+ toast({
+ title: "오류",
+ description: result.error || "저장 중 오류가 발생했습니다.",
+ variant: "destructive",
+ })
+ }
+ } catch (error) {
+ console.error("연동제 정보 저장 오류:", error)
+ toast({
+ title: "오류",
+ description: "저장 중 오류가 발생했습니다.",
+ variant: "destructive",
+ })
+ } finally {
+ setIsSubmitting(false)
+ }
+ }
+
+ if (!vendor) return null
+
+ return (
+ <Dialog open={open} onOpenChange={onOpenChange}>
+ <DialogContent className="sm:max-w-[500px]">
+ <DialogHeader>
+ <DialogTitle>연동제 적용 설정</DialogTitle>
+ <DialogDescription>
+ <span className="font-semibold text-primary">{vendor.vendorName}</span> 업체의 연동제 적용 여부 및 화학물질 정보를 설정합니다.
+ </DialogDescription>
+ </DialogHeader>
+
+ <div className="space-y-6 py-4">
+ {/* 업체가 제출한 연동제 요청 여부 (읽기 전용) */}
+ <div className="flex flex-row items-center justify-between rounded-lg border p-4 bg-muted/50">
+ <div className="space-y-0.5">
+ <Label className="text-base">업체 연동제 요청</Label>
+ <p className="text-sm text-muted-foreground">
+ 업체가 제출한 연동제 적용 요청 여부입니다.
+ </p>
+ </div>
+ <span className={`font-medium ${vendor.isPriceAdjustmentApplicableQuestion ? 'text-green-600' : 'text-gray-500'}`}>
+ {vendor.isPriceAdjustmentApplicableQuestion === null ? '미정' : vendor.isPriceAdjustmentApplicableQuestion ? '예' : '아니오'}
+ </span>
+ </div>
+
+ {/* SHI 연동제 적용여부 */}
+ <div className="flex flex-row items-center justify-between rounded-lg border p-4">
+ <div className="space-y-0.5">
+ <Label className="text-base">SHI 연동제 적용</Label>
+ <p className="text-sm text-muted-foreground">
+ 해당 업체에 연동제를 적용할지 결정합니다.
+ </p>
+ </div>
+ <div className="flex items-center gap-3">
+ <span className={`text-sm ${shiPriceAdjustmentApplied === false ? 'font-medium' : 'text-muted-foreground'}`}>
+ 미적용
+ </span>
+ <Switch
+ checked={shiPriceAdjustmentApplied === true}
+ onCheckedChange={(checked) => setSHIPriceAdjustmentApplied(checked)}
+ />
+ <span className={`text-sm ${shiPriceAdjustmentApplied === true ? 'font-medium' : 'text-muted-foreground'}`}>
+ 적용
+ </span>
+ </div>
+ </div>
+
+ {/* 연동제 Note */}
+ <div className="space-y-2">
+ <Label htmlFor="price-adjustment-note">연동제 Note</Label>
+ <Textarea
+ id="price-adjustment-note"
+ placeholder="연동제 관련 추가 사항을 입력하세요"
+ value={priceAdjustmentNote}
+ onChange={(e) => setPriceAdjustmentNote(e.target.value)}
+ rows={4}
+ />
+ </div>
+
+ {/* 화학물질 여부 */}
+ <div className="flex flex-row items-center justify-between rounded-lg border p-4">
+ <div className="space-y-0.5">
+ <Label className="text-base">화학물질 해당여부</Label>
+ <p className="text-sm text-muted-foreground">
+ 해당 업체가 화학물질 취급 대상인지 여부입니다.
+ </p>
+ </div>
+ <div className="flex items-center gap-3">
+ <span className={`text-sm ${hasChemicalSubstance === false ? 'font-medium' : 'text-muted-foreground'}`}>
+ 해당없음
+ </span>
+ <Switch
+ checked={hasChemicalSubstance === true}
+ onCheckedChange={(checked) => setHasChemicalSubstance(checked)}
+ />
+ <span className={`text-sm ${hasChemicalSubstance === true ? 'font-medium text-red-600' : 'text-muted-foreground'}`}>
+ 해당
+ </span>
+ </div>
+ </div>
+ </div>
+
+ <DialogFooter>
+ <Button
+ variant="outline"
+ onClick={() => onOpenChange(false)}
+ disabled={isSubmitting}
+ >
+ 취소
+ </Button>
+ <Button onClick={handleSubmit} disabled={isSubmitting}>
+ {isSubmitting ? (
+ <>
+ <Loader2 className="mr-2 h-4 w-4 animate-spin" />
+ 저장 중...
+ </>
+ ) : (
+ "저장"
+ )}
+ </Button>
+ </DialogFooter>
+ </DialogContent>
+ </Dialog>
+ )
+}
+