'use client'; /** * 작업일지 모달 * * - 헤더: sam-design 작업일지 스타일 * - 내부 문서: 스크린샷 기준 작업일지 양식 * - API 연동 완료 (2025-01-14) */ import { useState, useEffect } from 'react'; import { Printer, X, Loader2 } from 'lucide-react'; import { Dialog, DialogContent, DialogTitle, } from '@/components/ui/dialog'; import { VisuallyHidden } from '@radix-ui/react-visually-hidden'; import { Button } from '@/components/ui/button'; import { printArea } from '@/lib/print-utils'; import { getWorkOrderById } from '../WorkOrders/actions'; import type { WorkOrder, WorkOrderItem } from '../WorkOrders/types'; import { ITEM_STATUS_LABELS } from '../WorkOrders/types'; interface WorkLogModalProps { open: boolean; onOpenChange: (open: boolean) => void; workOrderId: string | null; } // 작업 통계 타입 interface WorkStats { orderQty: number; completedQty: number; inProgressQty: number; waitingQty: number; progress: number; } // 품목 데이터에서 작업 통계 계산 function calculateWorkStats(items: WorkOrderItem[]): WorkStats { const orderQty = items.length; const completedQty = items.filter(i => i.status === 'completed').length; const inProgressQty = items.filter(i => i.status === 'in_progress').length; const waitingQty = items.filter(i => i.status === 'waiting').length; const progress = orderQty > 0 ? Math.round((completedQty / orderQty) * 100) : 0; return { orderQty, completedQty, inProgressQty, waitingQty, progress, }; } export function WorkLogModal({ open, onOpenChange, workOrderId }: WorkLogModalProps) { const [order, setOrder] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); // 모달 열릴 때 데이터 fetch useEffect(() => { if (open && workOrderId) { setIsLoading(true); setError(null); getWorkOrderById(workOrderId) .then((result) => { if (result.success && result.data) { setOrder(result.data); } else { setError(result.error || '데이터를 불러올 수 없습니다.'); } }) .catch(() => { setError('서버 오류가 발생했습니다.'); }) .finally(() => { setIsLoading(false); }); } else if (!open) { // 모달 닫힐 때 상태 초기화 setOrder(null); setError(null); } }, [open, workOrderId]); const handlePrint = () => { printArea({ title: '작업일지 인쇄' }); }; if (!workOrderId) return null; // 로딩 상태 if (isLoading) { return ( 작업일지 로딩 중
); } // 에러 상태 if (error || !order) { return ( 작업일지 오류

{error || '데이터를 불러올 수 없습니다.'}

); } const today = new Date().toLocaleDateString('ko-KR', { year: 'numeric', month: '2-digit', day: '2-digit', }).replace(/\. /g, '-').replace('.', ''); const documentNo = `WL-${order.processCode.toUpperCase().slice(0, 3)}`; // 품목 데이터 const items = order.items || []; // 작업 통계 계산 const workStats = calculateWorkStats(items); // 주 담당자 const primaryAssignee = order.assignees?.find(a => a.isPrimary)?.name || order.assignee || '-'; return ( {/* 접근성을 위한 숨겨진 타이틀 */} 작업일지 - {order.workOrderNo} {/* 모달 헤더 - sam-design 스타일 (인쇄 시 숨김) */}
작업일지 {order.processName} 생산부서 ({documentNo})
{/* 문서 본문 (인쇄 시 이 영역만 출력) */}
{/* 문서 헤더: 로고 + 제목 + 결재라인 */}
{/* 좌측: 로고 영역 */}
KD 정동기업
{/* 중앙: 문서 제목 */}

작 업 일 지

{documentNo}

{order.processName} 생산부서

{/* 우측: 결재라인 */}
{/* 첫 번째 행: 결재 + 작성/검토/승인 */} {/* 두 번째 행: 이름 + 날짜 */} {/* 세 번째 행: 부서 */}
작성 검토 승인
{primaryAssignee}
{new Date().toLocaleDateString('ko-KR', { month: '2-digit', day: '2-digit' }).replace('. ', '/').replace('.', '')}
판매/전진 생산 품질
{/* 기본 정보 테이블 */}
{/* Row 1 */}
발주처
{order.client}
현장명
{order.projectName}
{/* Row 2 */}
작업일자
{today}
LOT NO.
{order.lotNo}
{/* Row 3 */}
납기일
{order.dueDate !== '-' ? new Date(order.dueDate).toLocaleDateString('ko-KR', { year: 'numeric', month: '2-digit', day: '2-digit', }).replace(/\. /g, '-').replace('.', '') : '-'}
작업지시번호
{order.workOrderNo}
{/* 품목 테이블 */}
{/* 테이블 헤더 */}
No
품목명
층/부호
규격
수량
상태
{/* 테이블 데이터 */} {items.length > 0 ? ( items.map((item, index) => (
{item.no}
{item.productName}
{item.floorCode}
{item.specification}
{item.quantity}
{ITEM_STATUS_LABELS[item.status]}
)) ) : (
등록된 품목이 없습니다.
)}
{/* 작업내역 */}
{/* 검정 헤더 */}
{order.processName} 작업내역
{/* 수량 및 진행률 */}
지시수량
{workStats.orderQty} EA
완료수량
{workStats.completedQty} EA
진행률
{workStats.progress}%
{/* 상세 상태 */}
대기
{workStats.waitingQty} EA
작업중
{workStats.inProgressQty} EA
완료
{workStats.completedQty} EA
{/* 특이 사항 */}
특이사항
{order.note || '-'}
); }