'use client'; /** * 배차차량 수정 페이지 * 3개 섹션: 기본정보(운임비용만 편집), 배차정보(모두 편집), 배송비정보(공급가액 편집→자동계산) */ import { useState, useCallback, useEffect } from 'react'; import { useRouter } from 'next/navigation'; import { Input } from '@/components/ui/input'; import { DateTimePicker } from '@/components/ui/date-time-picker'; import { Label } from '@/components/ui/label'; import { Badge } from '@/components/ui/badge'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { IntegratedDetailTemplate } from '@/components/templates/IntegratedDetailTemplate'; import { vehicleDispatchEditConfig } from './vehicleDispatchConfig'; import { isNextRedirectError } from '@/lib/utils/redirect-error'; import { getVehicleDispatchById, updateVehicleDispatch } from './actions'; import { VEHICLE_DISPATCH_STATUS_LABELS, VEHICLE_DISPATCH_STATUS_STYLES, FREIGHT_COST_LABELS, } from './types'; import type { VehicleDispatchDetail, VehicleDispatchEditFormData, FreightCostType, } from './types'; import { formatNumber as formatAmount } from '@/lib/utils/amount'; // 운임비용 옵션 const freightCostOptions: { value: FreightCostType; label: string }[] = Object.entries( FREIGHT_COST_LABELS ).map(([value, label]) => ({ value: value as FreightCostType, label })); interface VehicleDispatchEditProps { id: string; } export function VehicleDispatchEdit({ id }: VehicleDispatchEditProps) { const router = useRouter(); // 상세 데이터 const [detail, setDetail] = useState(null); // 폼 상태 const [formData, setFormData] = useState({ freightCostType: 'prepaid', logisticsCompany: '', arrivalDateTime: '', tonnage: '', vehicleNo: '', driverContact: '', remarks: '', supplyAmount: 0, vat: 0, totalAmount: 0, }); // 로딩/에러 const [isLoading, setIsLoading] = useState(true); const [isSubmitting, setIsSubmitting] = useState(false); const [error, setError] = useState(null); const [validationErrors, setValidationErrors] = useState>({}); // 데이터 로드 const loadData = useCallback(async () => { setIsLoading(true); setError(null); try { const result = await getVehicleDispatchById(id); if (result.success && result.data) { const d = result.data; setDetail(d); setFormData({ freightCostType: d.freightCostType, logisticsCompany: d.logisticsCompany, arrivalDateTime: d.arrivalDateTime, tonnage: d.tonnage, vehicleNo: d.vehicleNo, driverContact: d.driverContact, remarks: d.remarks, supplyAmount: d.supplyAmount, vat: d.vat, totalAmount: d.totalAmount, }); } else { setError(result.error || '배차차량 정보를 불러오는 데 실패했습니다.'); } } catch (err) { console.error('[VehicleDispatchEdit] loadData error:', err); setError('데이터를 불러오는 중 오류가 발생했습니다.'); } finally { setIsLoading(false); } }, [id]); useEffect(() => { loadData(); }, [loadData]); // 공급가액 변경 → 부가세/합계 자동 계산 const handleSupplyAmountChange = useCallback((value: string) => { const amount = parseInt(value.replace(/[^0-9]/g, ''), 10) || 0; const vat = Math.round(amount * 0.1); const total = amount + vat; setFormData(prev => ({ ...prev, supplyAmount: amount, vat, totalAmount: total, })); if (Object.keys(validationErrors).length > 0) setValidationErrors({}); }, [validationErrors]); // 폼 입력 핸들러 const handleInputChange = (field: keyof VehicleDispatchEditFormData, value: string) => { setFormData(prev => ({ ...prev, [field]: value })); if (Object.keys(validationErrors).length > 0) setValidationErrors({}); }; const handleCancel = useCallback(() => { router.push(`/ko/outbound/vehicle-dispatches/${id}?mode=view`); }, [router, id]); const handleSubmit = useCallback(async (): Promise<{ success: boolean; error?: string }> => { setIsSubmitting(true); try { const result = await updateVehicleDispatch(id, formData); if (!result.success) { return { success: false, error: result.error || '배차차량 수정에 실패했습니다.' }; } return { success: true }; } catch (err) { if (isNextRedirectError(err)) throw err; console.error('[VehicleDispatchEdit] handleSubmit error:', err); const errorMessage = err instanceof Error ? err.message : '저장 중 오류가 발생했습니다.'; return { success: false, error: errorMessage }; } finally { setIsSubmitting(false); } }, [id, formData]); // 동적 config const dynamicConfig = { ...vehicleDispatchEditConfig, title: detail?.dispatchNo ? `배차차량 수정 (${detail.dispatchNo})` : '배차차량 수정', }; // 폼 컨텐츠 렌더링 const renderFormContent = useCallback( (_props: { formData: Record; onChange: (key: string, value: unknown) => void; mode: string; errors: Record; }) => { if (!detail) return null; return (
{/* 상태 배지 */}
{VEHICLE_DISPATCH_STATUS_LABELS[detail.status]}
{/* 카드 1: 기본 정보 (운임비용만 편집 가능) */} 기본 정보
{detail.dispatchNo}
{detail.lotNo || detail.shipmentNo}
{detail.siteName}
{detail.orderCustomer}
{VEHICLE_DISPATCH_STATUS_LABELS[detail.status]}
{detail.writer}
{/* 카드 2: 배차 정보 (모두 편집 가능) */} 배차 정보
handleInputChange('logisticsCompany', e.target.value)} placeholder="물류업체명" disabled={isSubmitting} />
handleInputChange('arrivalDateTime', val)} disabled={isSubmitting} />
handleInputChange('tonnage', e.target.value)} placeholder="예: 3.5 톤" disabled={isSubmitting} />
handleInputChange('vehicleNo', e.target.value)} placeholder="예: 경기12차1234" disabled={isSubmitting} />
handleInputChange('driverContact', e.target.value)} placeholder="010-0000-0000" disabled={isSubmitting} />
handleInputChange('remarks', e.target.value)} placeholder="비고" disabled={isSubmitting} />
{/* 카드 3: 배송비 정보 (공급가액 편집 → 자동계산) */} 배송비 정보
handleSupplyAmountChange(e.target.value)} placeholder="0" disabled={isSubmitting} />
); }, [detail, formData, validationErrors, isSubmitting, handleSupplyAmountChange] ); if (error && !isLoading) { return ( ; onChange: (key: string, value: unknown) => void; mode: string; errors: Record; }) => (
{error || '배차차량 정보를 찾을 수 없습니다.'}
)} /> ); } return ( { return await handleSubmit(); }} renderForm={renderFormContent} /> ); }