"use client"; /** * 수주 상세 보기 컴포넌트 (View Mode) * * - 문서 모달: 계약서, 거래명세서, 발주서 * - 기본 정보, 수주/배송 정보, 비고 * - 제품 내역 테이블 * - 상태별 버튼 차이 */ import { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { FileText, ArrowLeft, Edit, Factory, XCircle, FileSpreadsheet, FileCheck, ClipboardList, Eye, CheckCircle2, } from "lucide-react"; import { toast } from "sonner"; import { PageLayout } from "@/components/organisms/PageLayout"; import { PageHeader } from "@/components/organisms/PageHeader"; import { BadgeSm } from "@/components/atoms/BadgeSm"; import { formatAmount } from "@/utils/formatAmount"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from "@/components/ui/dialog"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Textarea } from "@/components/ui/textarea"; import { OrderDocumentModal, type OrderDocumentType, getOrderById, updateOrderStatus, type Order, type OrderStatus, } from "@/components/orders"; import { ServerErrorPage } from "@/components/common/ServerErrorPage"; // 상태 뱃지 헬퍼 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} ); } // 정보 표시 컴포넌트 function InfoItem({ label, value }: { label: string; value: string }) { return (

{label}

{value || "-"}

); } interface OrderSalesDetailViewProps { orderId: string; } export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) { const router = useRouter(); const [order, setOrder] = useState(null); const [loading, setLoading] = useState(true); const [isCancelDialogOpen, setIsCancelDialogOpen] = useState(false); const [isCancelling, setIsCancelling] = useState(false); const [isConfirmDialogOpen, setIsConfirmDialogOpen] = useState(false); const [isConfirming, setIsConfirming] = useState(false); // 취소 폼 상태 const [cancelReason, setCancelReason] = useState(""); const [cancelDetail, setCancelDetail] = useState(""); // 문서 모달 상태 const [documentModalOpen, setDocumentModalOpen] = useState(false); const [documentType, setDocumentType] = useState("contract"); // 데이터 로드 (API 호출) useEffect(() => { async function loadOrder() { try { setLoading(true); const result = await getOrderById(orderId); if (result.success && result.data) { setOrder(result.data); } else { toast.error(result.error || "수주 정보를 불러오는데 실패했습니다."); setOrder(null); } } catch (error) { console.error("Error loading order:", error); toast.error("수주 정보를 불러오는 중 오류가 발생했습니다."); setOrder(null); } finally { setLoading(false); } } loadOrder(); }, [orderId]); const handleBack = () => { router.push("/sales/order-management-sales"); }; const handleEdit = () => { // V2 패턴: ?mode=edit로 이동 router.push(`/sales/order-management-sales/${orderId}?mode=edit`); }; const handleProductionOrder = () => { // 생산지시 생성 페이지로 이동 router.push(`/sales/order-management-sales/${orderId}/production-order`); }; const handleViewProductionOrder = () => { // 생산지시 목록 페이지로 이동 (수주관리 내부) router.push(`/sales/order-management-sales/production-orders`); }; const handleCancel = () => { setCancelReason(""); setCancelDetail(""); setIsCancelDialogOpen(true); }; const handleConfirmCancel = async () => { if (!cancelReason) { toast.error("취소 사유를 선택해주세요."); return; } if (order) { setIsCancelling(true); try { const result = await updateOrderStatus(order.id, "cancelled"); if (result.success) { setOrder({ ...order, status: "cancelled" }); toast.success("수주가 취소되었습니다."); setIsCancelDialogOpen(false); setCancelReason(""); setCancelDetail(""); } else { toast.error(result.error || "수주 취소에 실패했습니다."); } } catch (error) { console.error("Error cancelling order:", error); toast.error("수주 취소 중 오류가 발생했습니다."); } finally { setIsCancelling(false); } } }; // 수주 확정 처리 const handleConfirmOrder = () => { setIsConfirmDialogOpen(true); }; const handleConfirmOrderSubmit = async () => { if (order) { setIsConfirming(true); try { const result = await updateOrderStatus(order.id, "order_confirmed"); if (result.success && result.data) { setOrder(result.data); toast.success("수주가 확정되었습니다."); setIsConfirmDialogOpen(false); } else { toast.error(result.error || "수주 확정에 실패했습니다."); } } catch (error) { console.error("Error confirming order:", error); toast.error("수주 확정 중 오류가 발생했습니다."); } finally { setIsConfirming(false); } } }; // 문서 모달 열기 const openDocumentModal = (type: OrderDocumentType) => { setDocumentType(type); setDocumentModalOpen(true); }; if (loading) { return (
); } if (!order) { return ( ); } // 상태별 버튼 표시 여부 const showEditButton = order.status !== "shipped" && order.status !== "cancelled"; // 수주 확정 버튼: 수주등록 상태에서만 표시 const showConfirmButton = order.status === "order_registered"; // 생산지시 생성 버튼: 출하완료, 취소, 생산지시완료 제외하고 표시 // (수주등록, 수주확정, 생산중, 재작업중, 작업완료에서 표시) const showProductionCreateButton = order.status !== "shipped" && order.status !== "cancelled" && order.status !== "production_ordered"; // 생산지시 보기 버튼: 생산지시완료 상태에서 숨김 (기획서 오류로 제거) const showProductionViewButton = false; const showCancelButton = order.status !== "shipped" && order.status !== "cancelled" && order.status !== "production_ordered"; return ( {/* 헤더 */} {showEditButton && ( )} {showConfirmButton && ( )} {showProductionCreateButton && ( )} {showProductionViewButton && ( )} {showCancelButton && ( )}
} />
{/* 수주 정보 헤더 */}
{order.lotNumber} {getOrderStatusBadge(order.status)}
수주일: {order.orderDate}
{/* 문서 버튼들 */}
문서:
{/* 기본 정보 */} 기본 정보
{/* 수주/배송 정보 */} 수주/배송 정보
{/* 비고 */} {order.remarks && ( 비고

{order.remarks}

)} {/* 제품 내역 */} 제품 내역
순번 품목코드 품명 부호 규격 수량 단위 단가 금액 {order.items.map((item, index) => ( {index + 1} {item.itemCode} {item.itemName} {item.type || "-"} {item.symbol || "-"} {item.spec} {item.quantity} {item.unit} {formatAmount(item.unitPrice)}원 {formatAmount(item.amount)}원 ))}
{/* 합계 */}
소계: {formatAmount(order.subtotal)}원
할인율: {order.discountRate}%
총금액: {formatAmount(order.totalAmount)}원
{/* 문서 모달 */} {/* 취소 확인 다이얼로그 */} 수주 취소
{/* 수주 정보 박스 */}
수주번호 {order.lotNumber}
발주처 {order.client}
현장명 {order.siteName}
현재 상태 {getOrderStatusBadge(order.status)}
{/* 취소 사유 선택 */}
{/* 상세 사유 입력 */}