diff options
Diffstat (limited to 'lib/evaluation-criteria/table/reg-eval-criteria-update-sheet.tsx')
| -rw-r--r-- | lib/evaluation-criteria/table/reg-eval-criteria-update-sheet.tsx | 233 |
1 files changed, 146 insertions, 87 deletions
diff --git a/lib/evaluation-criteria/table/reg-eval-criteria-update-sheet.tsx b/lib/evaluation-criteria/table/reg-eval-criteria-update-sheet.tsx index bbf4f36d..f48fdf2e 100644 --- a/lib/evaluation-criteria/table/reg-eval-criteria-update-sheet.tsx +++ b/lib/evaluation-criteria/table/reg-eval-criteria-update-sheet.tsx @@ -13,7 +13,8 @@ import { } from '@/components/ui/card'; import { getRegEvalCriteriaWithDetails, - modifyRegEvalCriteriaWithDetails, + modifyRegEvalCriteriaFixed, + modifyRegEvalCriteriaVariable, } from '../service'; import { Form, @@ -64,7 +65,6 @@ const regEvalCriteriaFormSchema = z.object({ classification: z.string().min(1, '구분은 필수 항목입니다.'), range: z.string().nullable().optional(), remarks: z.string().nullable().optional(), - // 새로운 필드들 추가 scoreType: z.enum(['fixed', 'variable']).default('fixed'), variableScoreMin: z.coerce.number().nullable().optional(), variableScoreMax: z.coerce.number().nullable().optional(), @@ -72,13 +72,13 @@ const regEvalCriteriaFormSchema = z.object({ criteriaDetails: z.array( z.object({ id: z.number().optional(), - detail: z.string().min(1, '평가내용은 필수 항목입니다.'), + detail: z.string().optional(), scoreEquipShip: z.coerce.number().nullable().optional(), scoreEquipMarine: z.coerce.number().nullable().optional(), scoreBulkShip: z.coerce.number().nullable().optional(), scoreBulkMarine: z.coerce.number().nullable().optional(), }) - ).min(1, '최소 1개의 평가 내용이 필요합니다.'), + ).optional(), }); type RegEvalCriteriaFormData = z.infer<typeof regEvalCriteriaFormSchema>; @@ -341,38 +341,86 @@ function RegEvalCriteriaUpdateSheet({ }, [open, criteriaData, form]); const onSubmit = async (data: RegEvalCriteriaFormData) => { - startTransition(async () => { try { - const criteriaDataToUpdate = { - category: data.category, - category2: data.category2, - item: data.item, - classification: data.classification, - range: data.range, - remarks: data.remarks, - scoreType: data.scoreType, - variableScoreMin: data.variableScoreMin != null - ? String(data.variableScoreMin) : null, - variableScoreMax: data.variableScoreMax != null - ? String(data.variableScoreMax) : null, - variableScoreUnit: data.variableScoreUnit, - }; - - const detailList = data.criteriaDetails.map((detailItem) => ({ - id: detailItem.id, - detail: detailItem.detail, - scoreEquipShip: detailItem.scoreEquipShip != null - ? String(detailItem.scoreEquipShip) : null, - scoreEquipMarine: detailItem.scoreEquipMarine != null - ? String(detailItem.scoreEquipMarine) : null, - scoreBulkShip: detailItem.scoreBulkShip != null - ? String(detailItem.scoreBulkShip) : null, - scoreBulkMarine: detailItem.scoreBulkMarine != null - ? String(detailItem.scoreBulkMarine) : null, - })); - - await modifyRegEvalCriteriaWithDetails(criteriaData.id, criteriaDataToUpdate, detailList); + if (data.scoreType === 'fixed') { + // 고정 점수 검증 + if (!data.criteriaDetails || data.criteriaDetails.length === 0) { + toast.error('고정 점수 유형에서는 최소 1개의 평가내용이 필요합니다.'); + return; + } + + // 평가내용이 비어있는지 확인 + const hasEmptyDetail = data.criteriaDetails.some((detail: NonNullable<RegEvalCriteriaFormData['criteriaDetails']>[0]) => + !detail.detail || (detail.detail && detail.detail.trim() === '') + ); + if (hasEmptyDetail) { + toast.error('평가내용을 입력해주세요.'); + return; + } + + const criteriaDataToUpdate = { + category: data.category, + category2: data.category2, + item: data.item, + classification: data.classification, + range: data.range || null, + remarks: data.remarks || null, + scoreType: data.scoreType, + variableScoreMin: null, // 고정 점수에서는 null + variableScoreMax: null, // 고정 점수에서는 null + variableScoreUnit: null, // 고정 점수에서는 null + }; + + const detailList = data.criteriaDetails.map((detailItem: NonNullable<RegEvalCriteriaFormData['criteriaDetails']>[0]) => ({ + id: detailItem.id, + detail: detailItem.detail?.trim() || '', + scoreEquipShip: detailItem.scoreEquipShip != null ? String(detailItem.scoreEquipShip) : null, + scoreEquipMarine: detailItem.scoreEquipMarine != null ? String(detailItem.scoreEquipMarine) : null, + scoreBulkShip: detailItem.scoreBulkShip != null ? String(detailItem.scoreBulkShip) : null, + scoreBulkMarine: detailItem.scoreBulkMarine != null ? String(detailItem.scoreBulkMarine) : null, + })); + + await modifyRegEvalCriteriaFixed(criteriaData.id, criteriaDataToUpdate, detailList); + + } else if (data.scoreType === 'variable') { + // 변동 점수 검증 + if (data.variableScoreMin == null) { + toast.error('변동 점수 유형에서는 최소 점수가 필수입니다.'); + return; + } + if (data.variableScoreMax == null) { + toast.error('변동 점수 유형에서는 최대 점수가 필수입니다.'); + return; + } + if (!data.variableScoreUnit || data.variableScoreUnit.trim() === '') { + toast.error('변동 점수 유형에서는 단위가 필수입니다.'); + return; + } + if (Number(data.variableScoreMin) >= Number(data.variableScoreMax)) { + toast.error('최소 점수는 최대 점수보다 작아야 합니다.'); + return; + } + + const criteriaDataToUpdate = { + category: data.category, + category2: data.category2, + item: data.item, + classification: data.classification, + range: data.range || null, + remarks: data.remarks || null, + scoreType: data.scoreType, + variableScoreMin: String(data.variableScoreMin), + variableScoreMax: String(data.variableScoreMax), + variableScoreUnit: data.variableScoreUnit.trim(), + }; + + await modifyRegEvalCriteriaVariable(criteriaData.id, criteriaDataToUpdate); + } else { + toast.error('올바른 점수 유형을 선택해주세요.'); + return; + } + toast.success('평가 기준이 수정되었습니다.'); onSuccess(); onOpenChange(false); @@ -490,30 +538,6 @@ function RegEvalCriteriaUpdateSheet({ /> <FormField control={form.control} - name="scoreType" - render={({ field }) => ( - <FormItem> - <FormLabel>점수유형</FormLabel> - <FormControl> - <Select onValueChange={field.onChange} value={field.value}> - <SelectTrigger> - <SelectValue placeholder="선택" /> - </SelectTrigger> - <SelectContent> - <SelectItem value="fixed">고정점수</SelectItem> - <SelectItem value="variable">변동점수</SelectItem> - </SelectContent> - </Select> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - </div> - - <div className="grid grid-cols-2 gap-4"> - <FormField - control={form.control} name="classification" render={({ field }) => ( <FormItem> @@ -525,6 +549,7 @@ function RegEvalCriteriaUpdateSheet({ </FormItem> )} /> + </div> <FormField control={form.control} name="range" @@ -541,16 +566,55 @@ function RegEvalCriteriaUpdateSheet({ </FormItem> )} /> - </div> - {/* 변동점수 설정 */} + + + <FormField + control={form.control} + name="remarks" + render={({ field }) => ( + <FormItem> + <FormLabel>비고</FormLabel> + <FormControl> + <Textarea + placeholder="비고를 입력하세요." + {...field} + value={field.value ?? ''} + /> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + <FormField + control={form.control} + name="scoreType" + render={({ field }) => ( + <FormItem> + <FormLabel>점수유형</FormLabel> + <FormControl> + <Select onValueChange={field.onChange} value={field.value}> + <SelectTrigger> + <SelectValue placeholder="선택" /> + </SelectTrigger> + <SelectContent> + <SelectItem value="fixed">고정점수</SelectItem> + <SelectItem value="variable">변동점수</SelectItem> + </SelectContent> + </Select> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + {/* 변동점수 설정 */} {scoreType === 'variable' && ( <> <Separator /> <div className="space-y-4"> <h4 className="font-medium">변동점수 설정</h4> <div className="grid grid-cols-3 gap-4"> - <FormField + <FormField control={form.control} name="variableScoreMin" render={({ field }) => ( @@ -559,8 +623,9 @@ function RegEvalCriteriaUpdateSheet({ <FormControl> <Input type="number" - step="0.01" - placeholder="0.00" + min="0" + step="1" + placeholder="점수 입력 (0 이상)" {...field} value={field.value ?? ''} /> @@ -578,8 +643,9 @@ function RegEvalCriteriaUpdateSheet({ <FormControl> <Input type="number" - step="0.01" - placeholder="0.00" + min="0" + step="1" + placeholder="점수 입력 (0 이상)" {...field} value={field.value ?? ''} /> @@ -596,7 +662,7 @@ function RegEvalCriteriaUpdateSheet({ <FormLabel>점수단위</FormLabel> <FormControl> <Input - placeholder="예: 점, %" + placeholder="예: 감점, 가점" {...field} value={field.value ?? ''} /> @@ -609,27 +675,9 @@ function RegEvalCriteriaUpdateSheet({ </div> </> )} - - <FormField - control={form.control} - name="remarks" - render={({ field }) => ( - <FormItem> - <FormLabel>비고</FormLabel> - <FormControl> - <Textarea - placeholder="비고를 입력하세요." - {...field} - value={field.value ?? ''} - /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> </CardContent> </Card> - + {scoreType === 'fixed' && ( <Card> <CardHeader> <div className="flex items-center justify-between"> @@ -638,8 +686,7 @@ function RegEvalCriteriaUpdateSheet({ <CardDescription> {scoreType === 'fixed' ? '각 평가 옵션별 점수를 설정하세요.' - : '평가 옵션을 설정하세요. (점수는 변동점수 설정을 따릅니다.)' - } + : '평가 옵션을 설정하세요. (점수는 변동점수 설정을 따릅니다.)'} </CardDescription> </div> <Button @@ -680,6 +727,18 @@ function RegEvalCriteriaUpdateSheet({ </div> </CardContent> </Card> + )} + {scoreType === 'variable' && ( + <Card> + <CardHeader> + <CardTitle>변동 점수 설정</CardTitle> + <CardDescription> + 변동 점수 유형에서는 개별 평가 옵션을 설정할 수 없습니다. + 최소/최대 점수와 단위를 설정하여 점수 범위를 정의하세요. + </CardDescription> + </CardHeader> + </Card> + )} </div> </div> |
