'use client'; /** * 세금계산서 수기 입력 팝업 * * - 구분 Select (매출/매입) * - 작성일자 DatePicker * - 공급자 정보: "카드 내역 불러오기" 버튼 + 공급자명/사업자번호 * - 공급가액/세액/합계 (합계 자동계산) * - 품목/과세유형/비고 * - 취소/저장 버튼 */ import { useState, useCallback, useEffect } from 'react'; import { toast } from 'sonner'; import { CreditCard } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { DatePicker } from '@/components/ui/date-picker'; import { FormField } from '@/components/molecules/FormField'; import { BusinessNumberInput } from '@/components/ui/business-number-input'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from '@/components/ui/dialog'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { getTodayString } from '@/lib/utils/date'; import { createTaxInvoice } from './actions'; import { CardHistoryModal } from './CardHistoryModal'; import type { InvoiceTab, TaxType, ManualEntryFormData, CardHistoryRecord } from './types'; import { DIVISION_OPTIONS, TAX_TYPE_OPTIONS } from './types'; interface ManualEntryModalProps { open: boolean; onOpenChange: (open: boolean) => void; onSuccess: () => void; defaultDivision?: InvoiceTab; } const initialFormData: ManualEntryFormData = { division: 'sales', writeDate: getTodayString(), vendorName: '', vendorBusinessNumber: '', supplyAmount: 0, taxAmount: 0, totalAmount: 0, itemName: '', taxType: 'taxable', memo: '', }; export function ManualEntryModal({ open, onOpenChange, onSuccess, defaultDivision = 'sales', }: ManualEntryModalProps) { const [formData, setFormData] = useState({ ...initialFormData, division: defaultDivision, }); const [isSaving, setIsSaving] = useState(false); const [showCardHistory, setShowCardHistory] = useState(false); // 모달 열릴 때 폼 초기화 useEffect(() => { if (open) { setFormData({ ...initialFormData, division: defaultDivision, }); } }, [open, defaultDivision]); // 공급가액/세액 변경 시 합계 자동 계산 const handleAmountChange = useCallback( (field: 'supplyAmount' | 'taxAmount', value: string) => { const numValue = Number(value) || 0; setFormData((prev) => { const updated = { ...prev, [field]: numValue }; updated.totalAmount = updated.supplyAmount + updated.taxAmount; return updated; }); }, [] ); // 필드 변경 const handleChange = useCallback( (field: keyof ManualEntryFormData, value: string) => { setFormData((prev) => ({ ...prev, [field]: value })); }, [] ); // 카드 내역 선택 시 const handleCardSelect = useCallback((record: CardHistoryRecord) => { setFormData((prev) => ({ ...prev, vendorName: record.merchantName, vendorBusinessNumber: record.businessNumber, supplyAmount: Math.round(record.amount / 1.1), taxAmount: record.amount - Math.round(record.amount / 1.1), totalAmount: record.amount, })); setShowCardHistory(false); }, []); // 저장 const handleSave = useCallback(async () => { if (!formData.vendorName.trim()) { toast.warning('공급자명을 입력해주세요.'); return; } if (formData.supplyAmount <= 0) { toast.warning('공급가액을 입력해주세요.'); return; } setIsSaving(true); try { const result = await createTaxInvoice(formData); if (result.success) { onSuccess(); } else { toast.error(result.error || '등록에 실패했습니다.'); } } catch { toast.error('서버 오류가 발생했습니다.'); } finally { setIsSaving(false); } }, [formData, onSuccess]); return ( <> 세금계산서 수기 입력
{/* 구분 + 작성일자 */}
handleChange('writeDate', date)} />
{/* 공급자 정보 */}
handleChange('vendorName', value)} placeholder="공급자명" />
handleChange('vendorBusinessNumber', value)} placeholder="000-00-00000" />
{/* 금액 */}
handleAmountChange('supplyAmount', value)} placeholder="0" /> handleAmountChange('taxAmount', value)} placeholder="0" />
{/* 품목 + 과세유형 */}
handleChange('itemName', value)} placeholder="품목" />
{/* 비고 */} handleChange('memo', value)} placeholder="비고" />
{/* 카드 내역 불러오기 팝업 (팝업 in 팝업) */} ); }