feat(WEB): 공정관리 드래그 순서변경, 수주서/출고증 리디자인, 체크리스트 관리 추가
- 공정관리: 드래그&드롭 순서 변경 기능 추가 (reorderProcesses API) - 수주서(SalesOrderDocument): 기획서 D1.8 기준 리디자인, 출고증과 동일 자재 섹션 구조 - 출고증(ShipmentOrderDocument): 레이아웃 개선 - 체크리스트 관리 페이지 신규 추가 (master-data/checklist-management) - QMS 품질감사: 타입 및 목데이터 수정 - menuRefresh 유틸 정리 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
172
src/components/checklist-management/ChecklistForm.tsx
Normal file
172
src/components/checklist-management/ChecklistForm.tsx
Normal file
@@ -0,0 +1,172 @@
|
||||
'use client';
|
||||
|
||||
/**
|
||||
* 점검표 등록/수정 폼 컴포넌트
|
||||
*
|
||||
* 기획서 스크린샷 2 기준:
|
||||
* - 기본 정보: 점검표 번호(자동), 점검표명, 상태
|
||||
*/
|
||||
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import { IntegratedDetailTemplate } from '@/components/templates/IntegratedDetailTemplate';
|
||||
import { toast } from 'sonner';
|
||||
import type { Checklist } from '@/types/checklist';
|
||||
import { createChecklist, updateChecklist } from './actions';
|
||||
import type { DetailConfig } from '@/components/templates/IntegratedDetailTemplate/types';
|
||||
|
||||
const createConfig: DetailConfig = {
|
||||
title: '점검표',
|
||||
description: '새로운 점검표를 등록합니다',
|
||||
basePath: '',
|
||||
fields: [],
|
||||
actions: {
|
||||
showBack: true,
|
||||
showEdit: false,
|
||||
showDelete: false,
|
||||
showSave: true,
|
||||
submitLabel: '등록',
|
||||
},
|
||||
};
|
||||
|
||||
const editConfig: DetailConfig = {
|
||||
...createConfig,
|
||||
description: '점검표 정보를 수정합니다',
|
||||
actions: {
|
||||
...createConfig.actions,
|
||||
submitLabel: '저장',
|
||||
},
|
||||
};
|
||||
|
||||
interface ChecklistFormProps {
|
||||
mode: 'create' | 'edit';
|
||||
initialData?: Checklist;
|
||||
}
|
||||
|
||||
export function ChecklistForm({ mode, initialData }: ChecklistFormProps) {
|
||||
const router = useRouter();
|
||||
const isEdit = mode === 'edit';
|
||||
|
||||
const [checklistName, setChecklistName] = useState(initialData?.checklistName || '');
|
||||
const [status, setStatus] = useState<string>(initialData?.status || '사용');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const handleSubmit = async (): Promise<{ success: boolean; error?: string }> => {
|
||||
if (!checklistName.trim()) {
|
||||
toast.error('점검표명을 입력해주세요.');
|
||||
return { success: false, error: '점검표명을 입력해주세요.' };
|
||||
}
|
||||
|
||||
const formData = {
|
||||
checklistName: checklistName.trim(),
|
||||
status: status as '사용' | '미사용',
|
||||
};
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
if (isEdit && initialData?.id) {
|
||||
const result = await updateChecklist(initialData.id, formData);
|
||||
if (result.success) {
|
||||
toast.success('점검표가 수정되었습니다.');
|
||||
router.push(`/ko/master-data/checklist-management/${initialData.id}`);
|
||||
return { success: true };
|
||||
} else {
|
||||
toast.error(result.error || '수정에 실패했습니다.');
|
||||
return { success: false, error: result.error };
|
||||
}
|
||||
} else {
|
||||
const result = await createChecklist(formData);
|
||||
if (result.success && result.data) {
|
||||
toast.success('점검표가 등록되었습니다.');
|
||||
router.push(`/ko/master-data/checklist-management/${result.data.id}`);
|
||||
return { success: true };
|
||||
} else {
|
||||
toast.error(result.error || '등록에 실패했습니다.');
|
||||
return { success: false, error: result.error };
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
toast.error('처리 중 오류가 발생했습니다.');
|
||||
return { success: false, error: '처리 중 오류가 발생했습니다.' };
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
if (isEdit && initialData?.id) {
|
||||
router.push(`/ko/master-data/checklist-management/${initialData.id}`);
|
||||
} else {
|
||||
router.push('/ko/master-data/checklist-management');
|
||||
}
|
||||
};
|
||||
|
||||
const renderFormContent = useCallback(
|
||||
() => (
|
||||
<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 sm:grid-cols-3 gap-6">
|
||||
<div className="space-y-2">
|
||||
<Label>점검표 번호</Label>
|
||||
<Input
|
||||
value={initialData?.checklistCode || '자동생성'}
|
||||
disabled
|
||||
className="bg-muted"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="checklistName">점검표 *</Label>
|
||||
<Input
|
||||
id="checklistName"
|
||||
value={checklistName}
|
||||
onChange={(e) => setChecklistName(e.target.value)}
|
||||
placeholder="점검표명을 입력하세요"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>상태</Label>
|
||||
<Select value={status} onValueChange={setStatus}>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="사용">사용</SelectItem>
|
||||
<SelectItem value="미사용">미사용</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
),
|
||||
[checklistName, status, initialData?.checklistCode]
|
||||
);
|
||||
|
||||
const config = isEdit ? editConfig : createConfig;
|
||||
|
||||
return (
|
||||
<IntegratedDetailTemplate
|
||||
config={config}
|
||||
mode={isEdit ? 'edit' : 'create'}
|
||||
isLoading={false}
|
||||
onCancel={handleCancel}
|
||||
onSubmit={handleSubmit}
|
||||
renderForm={renderFormContent}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user