Files
sam-react-prod/src/components/production/WorkerScreen/WorkLogModal.tsx

156 lines
5.0 KiB
TypeScript
Raw Normal View History

'use client';
/**
*
*
* document-system (2026-01-22)
* (2026-01-29)
* - DocumentViewer
* - //
* - processType WorkLogContent ()
*/
import { useState, useEffect } from 'react';
import { Loader2 } from 'lucide-react';
import { DocumentViewer } from '@/components/document-system';
import { getWorkOrderById } from '../WorkOrders/actions';
import type { WorkOrder, ProcessType } from '../WorkOrders/types';
import { WorkLogContent } from './WorkLogContent';
import {
ScreenWorkLogContent,
SlatWorkLogContent,
BendingWorkLogContent,
} from '../WorkOrders/documents';
interface WorkLogModalProps {
open: boolean;
onOpenChange: (open: boolean) => void;
workOrderId: string | null;
processType?: ProcessType;
}
export function WorkLogModal({ open, onOpenChange, workOrderId, processType }: WorkLogModalProps) {
const [order, setOrder] = useState<WorkOrder | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
// 목업 WorkOrder 생성
const createMockOrder = (id: string, pType?: ProcessType): WorkOrder => ({
id,
workOrderNo: 'KD-WO-260129-01',
lotNo: 'KD-SA-260129-01',
processId: 1,
processName: pType === 'slat' ? '슬랫' : pType === 'bending' ? '절곡' : '스크린',
processCode: pType || 'screen',
processType: pType || 'screen',
status: 'in_progress',
client: '(주)경동',
projectName: '서울 강남 현장',
dueDate: '2026-02-05',
assignee: '홍길동',
assignees: [{ id: '1', name: '홍길동', isPrimary: true }],
orderDate: '2026-01-20',
scheduledDate: '2026-01-29',
shipmentDate: '2026-02-05',
salesOrderDate: '2026-01-15',
isAssigned: true,
isStarted: true,
priority: 3,
priorityLabel: '긴급',
shutterCount: 12,
department: '생산부',
items: [
{ id: '1', no: 1, status: 'in_progress', productName: '와이어 스크린', floorCode: '1층/FSS-01', specification: '8,260 X 8,350', quantity: 2, unit: 'EA' },
{ id: '2', no: 2, status: 'waiting', productName: '메쉬 스크린', floorCode: '2층/FSS-03', specification: '6,400 X 5,200', quantity: 4, unit: 'EA' },
{ id: '3', no: 3, status: 'completed', productName: '광폭 와이어', floorCode: '3층/FSS-05', specification: '12,000 X 4,500', quantity: 1, unit: 'EA' },
],
currentStep: { key: 'cutting', label: '절단', order: 2 },
completedSteps: ['material_input'],
totalProgress: 25,
issues: [],
memo: '',
createdAt: '2026-01-20T09:00:00',
updatedAt: '2026-01-29T14:00:00',
});
// 모달 열릴 때 데이터 fetch
useEffect(() => {
if (open && workOrderId) {
// 목업 ID인 경우 API 호출 생략
if (workOrderId.startsWith('mock-')) {
setOrder(createMockOrder(workOrderId, processType));
setError(null);
return;
}
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, processType]);
if (!workOrderId) return null;
// 로딩/에러 상태는 DocumentViewer 내부에서 처리
const subtitle = order ? `${order.processName} 생산부서` : undefined;
// 공정 타입에 따라 콘텐츠 분기
const renderContent = () => {
if (!order) return null;
// processType prop 또는 order의 processType 사용
const type = processType || order.processType;
switch (type) {
case 'screen':
return <ScreenWorkLogContent data={order} />;
case 'slat':
return <SlatWorkLogContent data={order} />;
case 'bending':
return <BendingWorkLogContent data={order} />;
default:
return <WorkLogContent data={order} />;
}
};
return (
<DocumentViewer
title="작업일지"
subtitle={subtitle}
preset="inspection"
open={open}
onOpenChange={onOpenChange}
>
{isLoading ? (
<div className="flex items-center justify-center h-64 bg-white">
<Loader2 className="w-8 h-8 animate-spin text-muted-foreground" />
</div>
) : error || !order ? (
<div className="flex flex-col items-center justify-center h-64 gap-4 bg-white">
<p className="text-muted-foreground">{error || '데이터를 불러올 수 없습니다.'}</p>
</div>
) : (
renderContent()
)}
</DocumentViewer>
);
}