feat: 공정관리 페이지 및 컴포넌트 추가
- 공정관리 목록/상세/등록/수정 페이지 구현 - ProcessListClient, ProcessDetail, ProcessForm 컴포넌트 추가 - ProcessWorkLogPreviewModal, RuleModal 추가 - MobileCard 공통 컴포넌트 추가 - WorkLogModal.tsx 개선 - .gitignore 업데이트 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
217
src/components/process-management/ProcessDetail.tsx
Normal file
217
src/components/process-management/ProcessDetail.tsx
Normal file
@@ -0,0 +1,217 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { List, Edit, Wrench } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { PageLayout } from '@/components/organisms/PageLayout';
|
||||
import { ProcessWorkLogPreviewModal } from './ProcessWorkLogPreviewModal';
|
||||
import type { Process } from '@/types/process';
|
||||
|
||||
interface ProcessDetailProps {
|
||||
process: Process;
|
||||
}
|
||||
|
||||
export function ProcessDetail({ process }: ProcessDetailProps) {
|
||||
const router = useRouter();
|
||||
const [workLogModalOpen, setWorkLogModalOpen] = useState(false);
|
||||
|
||||
const handleEdit = () => {
|
||||
router.push(`/ko/master-data/process-management/${process.id}/edit`);
|
||||
};
|
||||
|
||||
const handleList = () => {
|
||||
router.push('/ko/master-data/process-management');
|
||||
};
|
||||
|
||||
const handleViewWorkLog = () => {
|
||||
setWorkLogModalOpen(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<PageLayout>
|
||||
{/* 헤더 */}
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<div className="flex items-center gap-3">
|
||||
<Wrench className="h-6 w-6" />
|
||||
<h1 className="text-xl font-semibold">공정 상세</h1>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline" onClick={handleList}>
|
||||
<List className="h-4 w-4 mr-2" />
|
||||
목록
|
||||
</Button>
|
||||
<Button onClick={handleEdit}>
|
||||
<Edit className="h-4 w-4 mr-2" />
|
||||
수정
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
{/* 기본 정보 */}
|
||||
<Card>
|
||||
<CardHeader className="bg-muted/50">
|
||||
<CardTitle className="text-base">기본 정보</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div>
|
||||
<div className="text-sm text-muted-foreground mb-1">공정코드</div>
|
||||
<div className="font-medium">{process.processCode}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm text-muted-foreground mb-1">공정명</div>
|
||||
<div className="font-medium">{process.processName}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm text-muted-foreground mb-1">공정구분</div>
|
||||
<Badge variant="secondary">{process.processType}</Badge>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm text-muted-foreground mb-1">담당부서</div>
|
||||
<div className="font-medium">{process.department}</div>
|
||||
</div>
|
||||
<div className="md:col-span-2">
|
||||
<div className="text-sm text-muted-foreground mb-1">작업일지 양식</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-medium">
|
||||
{process.workLogTemplate || '-'}
|
||||
</span>
|
||||
{process.workLogTemplate && (
|
||||
<Button variant="outline" size="sm" onClick={handleViewWorkLog}>
|
||||
양식 보기
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 등록 정보 */}
|
||||
<Card>
|
||||
<CardHeader className="bg-muted/50">
|
||||
<CardTitle className="text-base">등록 정보</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<div className="text-sm text-muted-foreground mb-1">등록일</div>
|
||||
<div className="font-medium">{process.createdAt}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm text-muted-foreground mb-1">최종수정일</div>
|
||||
<div className="font-medium">{process.updatedAt}</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 자동 분류 규칙 */}
|
||||
<Card>
|
||||
<CardHeader className="bg-muted/50">
|
||||
<CardTitle className="text-base">자동 분류 규칙</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-6">
|
||||
{process.classificationRules.length === 0 ? (
|
||||
<div className="text-center py-12 text-muted-foreground">
|
||||
<Wrench className="h-12 w-12 mx-auto mb-4 opacity-30" />
|
||||
<p>등록된 자동 분류 규칙이 없습니다</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
{process.classificationRules.map((rule) => (
|
||||
<div
|
||||
key={rule.id}
|
||||
className="flex items-center justify-between p-4 border rounded-lg"
|
||||
>
|
||||
<div className="flex items-center gap-4">
|
||||
<Badge variant={rule.isActive ? 'default' : 'secondary'}>
|
||||
{rule.isActive ? '활성' : '비활성'}
|
||||
</Badge>
|
||||
<div>
|
||||
<div className="font-medium">
|
||||
{rule.ruleType} - "{rule.conditionValue}"
|
||||
</div>
|
||||
{rule.description && (
|
||||
<div className="text-sm text-muted-foreground">
|
||||
{rule.description}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Badge variant="outline">우선순위: {rule.priority}</Badge>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 세부 작업단계 */}
|
||||
<Card>
|
||||
<CardHeader className="bg-muted/50">
|
||||
<CardTitle className="text-base">세부 작업단계</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-6">
|
||||
{process.workSteps.length > 0 ? (
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
{process.workSteps.map((step, index) => (
|
||||
<div key={index} className="flex items-center gap-2">
|
||||
<Badge
|
||||
variant="outline"
|
||||
className="px-3 py-1.5 bg-muted/50"
|
||||
>
|
||||
<span className="bg-primary text-primary-foreground rounded-full w-5 h-5 flex items-center justify-center text-xs mr-2">
|
||||
{index + 1}
|
||||
</span>
|
||||
{step}
|
||||
</Badge>
|
||||
{index < process.workSteps.length - 1 && (
|
||||
<span className="text-muted-foreground">{'>'}</span>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-muted-foreground">-</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 작업 정보 */}
|
||||
<Card>
|
||||
<CardHeader className="bg-muted/50">
|
||||
<CardTitle className="text-base">작업 정보</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
<div>
|
||||
<div className="text-sm text-muted-foreground mb-1">필요인원</div>
|
||||
<div className="font-medium">{process.requiredWorkers}명</div>
|
||||
</div>
|
||||
{process.equipmentInfo && (
|
||||
<div>
|
||||
<div className="text-sm text-muted-foreground mb-1">설비정보</div>
|
||||
<div className="font-medium">{process.equipmentInfo}</div>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<div className="text-sm text-muted-foreground mb-1">설명</div>
|
||||
<div className="font-medium">{process.description || '-'}</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* 작업일지 양식 미리보기 모달 */}
|
||||
<ProcessWorkLogPreviewModal
|
||||
open={workLogModalOpen}
|
||||
onOpenChange={setWorkLogModalOpen}
|
||||
process={process}
|
||||
/>
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user