'use client'; /** * 공정상세 섹션 컴포넌트 * * 기획 화면에 맞춘 레이아웃: * - 자재 투입 필요 섹션 (흰색 박스, 검은색 전체너비 버튼) * - 공정 단계 (N단계) + N/N 완료 * - 숫자 뱃지 + 공정명 + 검사 뱃지 + 진행률 * - 검사 항목: 검사 요청 버튼 * - 상세 정보: 위치, 규격, LOT, 자재 */ import { useState } from 'react'; import { ChevronDown } from 'lucide-react'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { AlertDialog, AlertDialogAction, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog'; import { cn } from '@/lib/utils'; import type { ProcessStep, ProcessStepItem } from './types'; // Mock 공정 단계 데이터 (기획서 기준 8단계) const MOCK_PROCESS_STEPS: ProcessStep[] = [ { id: 'step-1', stepNo: 1, name: '자재투입', completed: 0, total: 3, items: [ { id: 'item-1-1', itemNo: '#1', location: '1층 1호-A', isPriority: true, spec: 'W2500 × H3000', material: '스크린 원단', lot: 'LOT-스크-2025-001', }, { id: 'item-1-2', itemNo: '#2', location: '1층 2호-B', isPriority: false, spec: 'W2600 × H3120', material: '스크린 원단', lot: 'LOT-스크-2025-002', }, { id: 'item-1-3', itemNo: '#3', location: '2층 3호-C', isPriority: false, spec: 'W2700 × H3240', material: '스크린 원단', lot: 'LOT-스크-2025-003', }, ], }, { id: 'step-2', stepNo: 2, name: '절단매수확인', completed: 0, total: 3, items: [], }, { id: 'step-3', stepNo: 3, name: '원단 절단', completed: 3, total: 3, items: [], }, { id: 'step-4', stepNo: 4, name: '절단 Check', isInspection: true, completed: 0, total: 3, items: [], }, { id: 'step-5', stepNo: 5, name: '미싱', completed: 1, total: 3, items: [ { id: 'item-5-1', itemNo: '#1', location: '1층 1호-A', isPriority: true, spec: 'W2500 × H3000', material: '스크린 원단', lot: 'LOT-스크-2025-001', }, { id: 'item-5-2', itemNo: '#2', location: '1층 2호-B', isPriority: false, spec: 'W2600 × H3120', material: '스크린 원단', lot: 'LOT-스크-2025-002', }, { id: 'item-5-3', itemNo: '#3', location: '2층 3호-C', isPriority: false, spec: 'W2700 × H3240', material: '스크린 원단', lot: 'LOT-스크-2025-003', }, ], }, { id: 'step-6', stepNo: 6, name: '앤드락 작업', completed: 0, total: 3, items: [], }, { id: 'step-7', stepNo: 7, name: '중간검사', isInspection: true, completed: 0, total: 3, items: [], }, { id: 'step-8', stepNo: 8, name: '포장', completed: 0, total: 3, items: [], }, ]; interface ProcessDetailSectionProps { isExpanded: boolean; materialRequired: boolean; onMaterialInput: () => void; } export function ProcessDetailSection({ isExpanded, materialRequired, onMaterialInput, }: ProcessDetailSectionProps) { const [steps, setSteps] = useState(MOCK_PROCESS_STEPS); const [expandedSteps, setExpandedSteps] = useState>(new Set(['step-1'])); const [inspectionDialogOpen, setInspectionDialogOpen] = useState(false); const [inspectionStepName, setInspectionStepName] = useState(''); const [pendingInspectionStepId, setPendingInspectionStepId] = useState(null); const totalSteps = steps.length; const completedSteps = steps.filter((s) => s.completed === s.total).length; const toggleStep = (stepId: string) => { setExpandedSteps((prev) => { const next = new Set(prev); if (next.has(stepId)) { next.delete(stepId); } else { next.add(stepId); } return next; }); }; // 검사 요청 핸들러 const handleInspectionRequest = (step: ProcessStep) => { setInspectionStepName(step.name); setPendingInspectionStepId(step.id); setInspectionDialogOpen(true); }; // 검사 요청 확인 후 완료 처리 const handleInspectionConfirm = () => { if (pendingInspectionStepId) { setSteps((prev) => prev.map((step) => step.id === pendingInspectionStepId ? { ...step, completed: step.total } : step ) ); // 다음 단계 펼치기 const stepIndex = steps.findIndex((s) => s.id === pendingInspectionStepId); if (stepIndex < steps.length - 1) { setExpandedSteps((prev) => new Set([...prev, steps[stepIndex + 1].id])); } } setInspectionDialogOpen(false); setPendingInspectionStepId(null); }; if (!isExpanded) return null; return (
{/* 자재 투입 필요 섹션 */} {materialRequired && (

자재 투입 필요

)} {/* 공정 단계 헤더 */}

공정 단계 ({totalSteps}단계)

{completedSteps} / {totalSteps} 완료
{/* 공정 단계 목록 */}
{steps.map((step) => ( toggleStep(step.id)} onInspectionRequest={() => handleInspectionRequest(step)} /> ))}
{/* 검사 요청 완료 다이얼로그 */} 검사 요청 완료 {inspectionStepName} 검사 요청이 품질팀에 전송되었습니다. 확인
); } // ===== 하위 컴포넌트 ===== interface ProcessStepCardProps { step: ProcessStep; isExpanded: boolean; onToggle: () => void; onInspectionRequest: () => void; } function ProcessStepCard({ step, isExpanded, onToggle, onInspectionRequest }: ProcessStepCardProps) { const isCompleted = step.completed === step.total; const hasItems = step.items.length > 0; return (
{/* 헤더 */}
{/* 숫자 뱃지 */}
{step.stepNo}
{/* 공정명 + 검사 뱃지 */}
{step.name} {step.isInspection && ( 검사 )}
{/* 진행률 + 완료 표시 */}
{isCompleted && ( 완료 )} {step.completed}/{step.total} {(hasItems || step.isInspection) && ( )}
{/* 검사 요청 버튼 (검사 항목일 때만) */} {step.isInspection && !isCompleted && isExpanded && (
)} {/* 상세 항목 리스트 */} {hasItems && isExpanded && (
{step.items.map((item, index) => ( ))}
)}
); } interface ProcessStepItemCardProps { item: ProcessStepItem; index: number; isCompleted: boolean; } function ProcessStepItemCard({ item, index, isCompleted }: ProcessStepItemCardProps) { return (
{/* 인덱스 뱃지 */}
{index}
{/* 상세 정보 */}
{/* 첫 번째 줄: #N + 위치 + 선행생산 + 완료 */}
{item.itemNo} {item.location} {item.isPriority && ( 선행 생산 )} {isCompleted && ( 완료 )}
{/* 두 번째 줄: 규격 + 자재 */}
규격: {item.spec} 자재: {item.material}
{/* 세 번째 줄: LOT */}
LOT: {item.lot}
); }