"use client"; /** * 수주 수정 컴포넌트 (Edit Mode) * IntegratedDetailTemplate 마이그레이션 완료 (2026-01-20) * * - 기본 정보 (읽기전용) * - 수주/배송 정보 (편집 가능) * - 비고 (편집 가능) * - 품목 내역 (생산 시작 후 수정 불가) */ import { useState, useEffect, useMemo, useCallback } from "react"; import { useRouter } from "next/navigation"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { PhoneInput } from "@/components/ui/phone-input"; import { Checkbox } from "@/components/ui/checkbox"; import { Label } from "@/components/ui/label"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { AlertTriangle } from "lucide-react"; import { toast } from "sonner"; import { IntegratedDetailTemplate } from "@/components/templates/IntegratedDetailTemplate"; import { orderSalesConfig } from "./orderSalesConfig"; import { BadgeSm } from "@/components/atoms/BadgeSm"; import { formatAmount } from "@/utils/formatAmount"; import { OrderItem, getOrderById, updateOrder, type OrderStatus, } from "@/components/orders"; // 수정 폼 데이터 interface EditFormData { // 읽기전용 정보 lotNumber: string; quoteNumber: string; client: string; siteName: string; manager: string; contact: string; status: OrderStatus; // 수정 가능 정보 expectedShipDate: string; expectedShipDateUndecided: boolean; deliveryRequestDate: string; deliveryMethod: string; shippingCost: string; receiver: string; receiverContact: string; address: string; addressDetail: string; remarks: string; // 품목 (수정 제한) items: OrderItem[]; canEditItems: boolean; subtotal: number; discountRate: number; totalAmount: number; } // 배송방식 옵션 const DELIVERY_METHODS = [ { value: "direct", label: "직접배차" }, { value: "pickup", label: "상차" }, { value: "courier", label: "택배" }, ]; // 운임비용 옵션 const SHIPPING_COSTS = [ { value: "free", label: "무료" }, { value: "prepaid", label: "선불" }, { value: "collect", label: "착불" }, { value: "negotiable", label: "협의" }, ]; // 상태 뱃지 헬퍼 function getOrderStatusBadge(status: OrderStatus) { const statusConfig: Record = { order_registered: { label: "수주등록", className: "bg-gray-100 text-gray-700 border-gray-200" }, order_confirmed: { label: "수주확정", className: "bg-gray-100 text-gray-700 border-gray-200" }, production_ordered: { label: "생산지시완료", className: "bg-blue-100 text-blue-700 border-blue-200" }, in_production: { label: "생산중", className: "bg-green-100 text-green-700 border-green-200" }, rework: { label: "재작업중", className: "bg-orange-100 text-orange-700 border-orange-200" }, work_completed: { label: "작업완료", className: "bg-blue-600 text-white border-blue-600" }, shipped: { label: "출하완료", className: "bg-gray-500 text-white border-gray-500" }, cancelled: { label: "취소", className: "bg-red-100 text-red-700 border-red-200" }, }; const config = statusConfig[status]; return ( {config.label} ); } interface OrderSalesDetailEditProps { orderId: string; } export function OrderSalesDetailEdit({ orderId }: OrderSalesDetailEditProps) { const router = useRouter(); const [form, setForm] = useState(null); const [loading, setLoading] = useState(true); const [isSaving, setIsSaving] = useState(false); // 데이터 로드 (API) useEffect(() => { async function loadOrder() { try { setLoading(true); const result = await getOrderById(orderId); if (result.success && result.data) { const order = result.data; // 상태에 따라 품목 수정 가능 여부 결정 const canEditItems = !["in_production", "rework", "work_completed", "shipped"].includes( order.status ); // Order 데이터를 EditFormData로 변환 setForm({ lotNumber: order.lotNumber, quoteNumber: order.quoteNumber || "", client: order.client, siteName: order.siteName, manager: order.manager || "", contact: order.contact || "", status: order.status, expectedShipDate: order.expectedShipDate || "", expectedShipDateUndecided: !order.expectedShipDate, deliveryRequestDate: order.deliveryRequestDate || "", deliveryMethod: order.deliveryMethod || "", shippingCost: order.shippingCost || "", receiver: order.receiver || "", receiverContact: order.receiverContact || "", address: order.address || "", addressDetail: order.addressDetail || "", remarks: order.remarks || "", items: order.items || [], canEditItems, subtotal: order.subtotal || order.amount, discountRate: order.discountRate || 0, totalAmount: order.amount, }); } else { toast.error(result.error || "수주 정보를 불러오는데 실패했습니다."); router.push("/sales/order-management-sales"); } } catch (error) { console.error("Error loading order:", error); toast.error("수주 정보를 불러오는 중 오류가 발생했습니다."); router.push("/sales/order-management-sales"); } finally { setLoading(false); } } loadOrder(); }, [orderId, router]); const handleCancel = () => { // V2 패턴: ?mode=view로 이동 (기본값이므로 쿼리 없이 이동) router.push(`/sales/order-management-sales/${orderId}`); }; // IntegratedDetailTemplate용 onSubmit 핸들러 const handleSubmit = useCallback(async (): Promise<{ success: boolean; error?: string }> => { if (!form) return { success: false, error: "폼 데이터가 없습니다." }; // 유효성 검사 if (!form.deliveryRequestDate) { return { success: false, error: "납품요청일을 입력해주세요." }; } if (!form.receiver.trim()) { return { success: false, error: "수신(반장/업체)을 입력해주세요." }; } if (!form.receiverContact.trim()) { return { success: false, error: "수신처 연락처를 입력해주세요." }; } try { // API 연동 const result = await updateOrder(orderId, { clientId: undefined, // 기존 값 유지 siteName: form.siteName, expectedShipDate: form.expectedShipDateUndecided ? undefined : form.expectedShipDate, deliveryRequestDate: form.deliveryRequestDate, deliveryMethod: form.deliveryMethod, shippingCost: form.shippingCost, receiver: form.receiver, receiverContact: form.receiverContact, address: form.address, addressDetail: form.addressDetail, remarks: form.remarks, items: form.items.map((item) => ({ itemId: item.id ? parseInt(item.id, 10) : undefined, itemCode: item.itemCode, itemName: item.itemName, specification: item.spec, quantity: item.quantity, unit: item.unit, unitPrice: item.unitPrice, })), }); if (result.success) { toast.success("수주가 수정되었습니다."); // V2 패턴: 저장 후 view 모드로 이동 router.push(`/sales/order-management-sales/${orderId}`); return { success: true }; } else { return { success: false, error: result.error || "수주 수정에 실패했습니다." }; } } catch (error) { console.error("Error updating order:", error); return { success: false, error: "수주 수정 중 오류가 발생했습니다." }; } }, [form, orderId, router]); // 동적 config (수정 모드용 타이틀) const dynamicConfig = useMemo(() => { return { ...orderSalesConfig, title: "수주 수정", actions: { ...orderSalesConfig.actions, showEdit: false, // 수정 모드에서는 수정 버튼 숨김 showDelete: false, }, }; }, []); // 커스텀 헤더 액션 (상태 뱃지) const customHeaderActions = useMemo(() => { if (!form) return null; return (
{form.lotNumber} {getOrderStatusBadge(form.status)}
); }, [form]); // 폼 콘텐츠 렌더링 const renderFormContent = useCallback(() => { if (!form) return null; return (
{/* 기본 정보 (읽기전용) */} 기본 정보 (읽기전용)

{form.lotNumber}

{form.quoteNumber}

{form.manager}

{form.client}

{form.siteName}

{form.contact}

{/* 수주/배송 정보 (편집 가능) */} 수주/배송 정보
{/* 출고예정일 */}
setForm({ ...form, expectedShipDate: e.target.value }) } disabled={form.expectedShipDateUndecided} className="flex-1" />
setForm({ ...form, expectedShipDateUndecided: checked as boolean, expectedShipDate: checked ? "" : form.expectedShipDate, }) } />
{/* 납품요청일 */}
setForm({ ...form, deliveryRequestDate: e.target.value }) } />
{/* 배송방식 */}
{/* 운임비용 */}
{/* 수신(반장/업체) */}
setForm({ ...form, receiver: e.target.value }) } />
{/* 수신처 연락처 */}
setForm({ ...form, receiverContact: value }) } />
{/* 수신처 주소 */}
setForm({ ...form, address: e.target.value }) } placeholder="주소" className="mb-2" /> setForm({ ...form, addressDetail: e.target.value }) } placeholder="상세주소" />
{/* 비고 */} 비고