/** * 할인하기 모달 * * - 공급가액 표시 (읽기 전용) * - 할인율 입력 (% 단위, 소수점 첫째자리까지) * - 할인금액 입력 (원 단위) * - 할인 후 공급가액 자동 계산 * - 할인율 ↔ 할인금액 상호 계산 */ "use client"; import { useState, useEffect, useCallback } from "react"; import { formatNumber } from "@/lib/utils/amount"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from "../ui/dialog"; import { Button } from "../ui/button"; import { Input } from "../ui/input"; import { Label } from "../ui/label"; // ============================================================================= // Props // ============================================================================= interface DiscountModalProps { open: boolean; onOpenChange: (open: boolean) => void; /** 공급가액 (할인 전 금액) */ supplyAmount: number; /** 기존 할인율 (%) */ initialDiscountRate?: number; /** 기존 할인금액 (원) */ initialDiscountAmount?: number; /** 적용 콜백 */ onApply: (discountRate: number, discountAmount: number) => void; } // ============================================================================= // 컴포넌트 // ============================================================================= export function DiscountModal({ open, onOpenChange, supplyAmount, initialDiscountRate = 0, initialDiscountAmount = 0, onApply, }: DiscountModalProps) { // --------------------------------------------------------------------------- // 상태 // --------------------------------------------------------------------------- const [discountRate, setDiscountRate] = useState(""); const [discountAmount, setDiscountAmount] = useState(""); // --------------------------------------------------------------------------- // 초기화 // --------------------------------------------------------------------------- useEffect(() => { if (open) { // 모달이 열릴 때 초기값 설정 if (initialDiscountRate > 0) { setDiscountRate(initialDiscountRate.toString()); setDiscountAmount(initialDiscountAmount.toString()); } else if (initialDiscountAmount > 0) { setDiscountAmount(initialDiscountAmount.toString()); const rate = supplyAmount > 0 ? (initialDiscountAmount / supplyAmount) * 100 : 0; setDiscountRate(rate.toFixed(1)); } else { setDiscountRate(""); setDiscountAmount(""); } } }, [open, initialDiscountRate, initialDiscountAmount, supplyAmount]); // --------------------------------------------------------------------------- // 핸들러 // --------------------------------------------------------------------------- // 할인율 변경 → 할인금액 자동 계산 const handleDiscountRateChange = useCallback( (value: string) => { // 숫자와 소수점만 허용 const sanitized = value.replace(/[^0-9.]/g, ""); // 소수점이 여러 개인 경우 첫 번째만 유지 const parts = sanitized.split("."); const formatted = parts.length > 2 ? parts[0] + "." + parts.slice(1).join("") : sanitized; setDiscountRate(formatted); const rate = parseFloat(formatted) || 0; if (rate >= 0 && rate <= 100) { const amount = Math.round(supplyAmount * (rate / 100)); setDiscountAmount(amount.toString()); } }, [supplyAmount] ); // 할인금액 변경 → 할인율 자동 계산 const handleDiscountAmountChange = useCallback( (value: string) => { // 숫자만 허용 const sanitized = value.replace(/[^0-9]/g, ""); setDiscountAmount(sanitized); const amount = parseInt(sanitized) || 0; if (supplyAmount > 0 && amount >= 0 && amount <= supplyAmount) { const rate = (amount / supplyAmount) * 100; setDiscountRate(rate.toFixed(1)); } }, [supplyAmount] ); // 적용 const handleApply = useCallback(() => { const rate = parseFloat(discountRate) || 0; const amount = parseInt(discountAmount) || 0; onApply(rate, amount); onOpenChange(false); }, [discountRate, discountAmount, onApply, onOpenChange]); // 취소 const handleCancel = useCallback(() => { onOpenChange(false); }, [onOpenChange]); // --------------------------------------------------------------------------- // 계산 // --------------------------------------------------------------------------- const discountedAmount = supplyAmount - (parseInt(discountAmount) || 0); // --------------------------------------------------------------------------- // 렌더링 // --------------------------------------------------------------------------- return ( 할인하기
{/* 공급가액 (읽기 전용) */}
{/* 할인율 */}
handleDiscountRateChange(e.target.value)} className="pr-8 text-right" /> %
{/* 할인금액 */}
handleDiscountAmountChange(e.target.value.replace(/,/g, ""))} className="pr-8 text-right" />
{/* 할인 후 공급가액 (읽기 전용) */}
); }