173 lines
5.4 KiB
TypeScript
173 lines
5.4 KiB
TypeScript
|
|
'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}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
}
|