'use client'; import { useState, useEffect, useCallback } from 'react'; import { toast } from 'sonner'; import { formatNumber } from '@/lib/utils/amount'; import { Loader2 } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { FormField } from '@/components/molecules/FormField'; import { DatePicker } from '@/components/ui/date-picker'; import { TimePicker } from '@/components/ui/time-picker'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from '@/components/ui/dialog'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import type { ManualInputFormData } from './types'; import { DEDUCTION_OPTIONS, ACCOUNT_SUBJECT_OPTIONS } from './types'; import { getCardList, createCardTransaction } from './actions'; import { getTodayString } from '@/lib/utils/date'; interface ManualInputModalProps { open: boolean; onOpenChange: (open: boolean) => void; onSuccess: () => void; } const initialFormData: ManualInputFormData = { cardId: '', usedDate: getTodayString(), usedTime: '', approvalNumber: '', approvalType: 'approved', supplyAmount: 0, taxAmount: 0, merchantName: '', businessNumber: '', deductionType: 'deductible', accountSubject: '', vendorName: '', description: '', memo: '', }; export function ManualInputModal({ open, onOpenChange, onSuccess }: ManualInputModalProps) { const [formData, setFormData] = useState(initialFormData); const [cardOptions, setCardOptions] = useState>([]); const [isSubmitting, setIsSubmitting] = useState(false); const [isLoadingCards, setIsLoadingCards] = useState(false); // 카드 목록 로드 useEffect(() => { if (open) { setIsLoadingCards(true); getCardList() .then(result => { if (result.success) setCardOptions(result.data); }) .finally(() => setIsLoadingCards(false)); setFormData(initialFormData); } }, [open]); const handleChange = useCallback((key: keyof ManualInputFormData, value: string | number) => { setFormData(prev => ({ ...prev, [key]: value })); }, []); const totalAmount = formData.supplyAmount + formData.taxAmount; const handleSubmit = useCallback(async () => { if (!formData.cardId) { toast.error('카드를 선택해주세요.'); return; } if (!formData.usedDate) { toast.error('사용일을 입력해주세요.'); return; } if (formData.supplyAmount <= 0 && formData.taxAmount <= 0) { toast.error('공급가액 또는 세액을 입력해주세요.'); return; } setIsSubmitting(true); try { const result = await createCardTransaction(formData); if (result.success) { toast.success('카드사용 내역이 등록되었습니다.'); onOpenChange(false); onSuccess(); } else { toast.error(result.error || '등록에 실패했습니다.'); } } catch { toast.error('등록 중 오류가 발생했습니다.'); } finally { setIsSubmitting(false); } }, [formData, onOpenChange, onSuccess]); return ( 카드사용 수기 입력
{/* 카드 선택 (동적 API Select - FormField 예외) */}
{/* 사용일 + 사용시간 (공통 DatePicker/TimePicker) */}
handleChange('usedDate', v)} placeholder="날짜 선택" className="mt-1" />
handleChange('usedTime', v)} placeholder="시간 선택" showSeconds secondStep={1} minuteStep={1} className="mt-1" />
{/* 승인번호 + 승인유형 */}
handleChange('approvalNumber', v)} placeholder="승인번호" />
handleChange('approvalType', v)} className="flex items-center gap-4 mt-2" >
{/* 공급가액 + 세액 */}
handleChange('supplyAmount', Number(v) || 0)} placeholder="0" /> handleChange('taxAmount', Number(v) || 0)} placeholder="0" />
{/* 가맹점명 + 사업자번호 */}
handleChange('merchantName', v)} placeholder="가맹점명" /> handleChange('businessNumber', v)} placeholder="123-12-12345" />
{/* 공제여부 + 계정과목 (Select - FormField 예외) */}
{/* 증빙/판매자상호 + 내역 */}
handleChange('vendorName', v)} placeholder="증빙/판매자상호" /> handleChange('description', v)} placeholder="내역" />
{/* 메모 */} handleChange('memo', v)} rows={3} /> {/* 합계 금액 */}
합계 금액 (공급가액 + 세액) {formatNumber(totalAmount)}원
); }