summaryrefslogtreecommitdiff
path: root/lib/evaluation-criteria/table/reg-eval-criteria-create-dialog.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/evaluation-criteria/table/reg-eval-criteria-create-dialog.tsx')
-rw-r--r--lib/evaluation-criteria/table/reg-eval-criteria-create-dialog.tsx680
1 files changed, 424 insertions, 256 deletions
diff --git a/lib/evaluation-criteria/table/reg-eval-criteria-create-dialog.tsx b/lib/evaluation-criteria/table/reg-eval-criteria-create-dialog.tsx
index 2a668ca8..972af75d 100644
--- a/lib/evaluation-criteria/table/reg-eval-criteria-create-dialog.tsx
+++ b/lib/evaluation-criteria/table/reg-eval-criteria-create-dialog.tsx
@@ -1,7 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
-
'use client';
-
/* IMPORT */
import { Button } from '@/components/ui/button';
import {
@@ -11,11 +9,12 @@ import {
CardHeader,
CardTitle,
} from '@/components/ui/card';
-import { createRegEvalCriteriaWithDetails } from '../service';
+import { createRegEvalCriteriaFixed, createRegEvalCriteriaVariable } from '../service';
import {
Dialog,
DialogContent,
DialogDescription,
+ DialogFooter,
DialogHeader,
DialogTitle
} from '@/components/ui/dialog';
@@ -46,11 +45,11 @@ import { Textarea } from '@/components/ui/textarea';
import { toast } from 'sonner';
import { useForm, useFieldArray } from 'react-hook-form';
import { useEffect, useTransition } from 'react';
+import { useSession } from 'next-auth/react';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
// ----------------------------------------------------------------------------------------------------
-
/* TYPES */
const regEvalCriteriaFormSchema = z.object({
category: z.string().min(1, '평가부문은 필수 항목입니다.'),
@@ -59,18 +58,24 @@ 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(),
+ variableScoreUnit: z.string().nullable().optional(),
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>;
+
interface CriteriaDetailFormProps {
index: number
form: any
@@ -83,9 +88,8 @@ interface RegEvalCriteriaFormSheetProps {
onOpenChange: (open: boolean) => void,
onSuccess: () => void,
};
-
// ----------------------------------------------------------------------------------------------------
-
+/* CRITERIA DETAIL FORM COPONENT */
/* CRITERIA DETAIL FORM COPONENT */
function CriteriaDetailForm({
index,
@@ -99,7 +103,7 @@ function CriteriaDetailForm({
<Card>
<CardHeader>
<div className="flex items-center justify-between">
- <CardTitle className="text-lg">Detail Item - {index + 1}</CardTitle>
+ <CardTitle className="text-lg">평가 옵션 {index + 1}</CardTitle>
{canRemove && (
<Button
type="button"
@@ -127,91 +131,11 @@ function CriteriaDetailForm({
name={`criteriaDetails.${index}.detail`}
render={({ field }) => (
<FormItem>
- <FormLabel>평가내용</FormLabel>
+ <FormLabel>평가 옵션 내용</FormLabel>
<FormControl>
<Textarea
- placeholder="평가내용을 입력하세요."
- {...field}
- disabled={disabled}
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
- name={`criteriaDetails.${index}.scoreEquipShip`}
- render={({ field }) => (
- <FormItem>
- <FormLabel>배점/기자재/조선</FormLabel>
- <FormControl>
- <Input
- type="number"
- step="0.1"
- placeholder="배점/기자재/조선"
+ placeholder="평가 옵션 내용을 입력하세요. (예: 우수, 보통, 미흡)"
{...field}
- value={field.value ?? 0}
- disabled={disabled}
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
- name={`criteriaDetails.${index}.scoreEquipMarine`}
- render={({ field }) => (
- <FormItem>
- <FormLabel>배점/기자재/해양</FormLabel>
- <FormControl>
- <Input
- type="number"
- step="0.1"
- placeholder="배점/기자재/해양"
- {...field}
- value={field.value ?? 0}
- disabled={disabled}
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
- name={`criteriaDetails.${index}.scoreBulkShip`}
- render={({ field }) => (
- <FormItem>
- <FormLabel>배점/벌크/조선</FormLabel>
- <FormControl>
- <Input
- type="number"
- step="0.1"
- placeholder="배점/벌크/조선"
- {...field}
- value={field.value ?? 0}
- disabled={disabled}
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
- name={`criteriaDetails.${index}.scoreBulkMarine`}
- render={({ field }) => (
- <FormItem>
- <FormLabel>배점/벌크/해양</FormLabel>
- <FormControl>
- <Input
- type="number"
- step="0.1"
- placeholder="배점/벌크/해양"
- {...field}
- value={field.value ?? 0}
disabled={disabled}
/>
</FormControl>
@@ -219,11 +143,92 @@ function CriteriaDetailForm({
</FormItem>
)}
/>
+ <div className="grid grid-cols-4 gap-4">
+ <FormField
+ control={form.control}
+ name={`criteriaDetails.${index}.scoreEquipShip`}
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>기자재-조선</FormLabel>
+ <FormControl>
+ <Input
+ type="number"
+ step="0.01"
+ placeholder="0.00"
+ {...field}
+ value={field.value ?? ''}
+ disabled={disabled}
+ />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ <FormField
+ control={form.control}
+ name={`criteriaDetails.${index}.scoreEquipMarine`}
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>기자재-해양</FormLabel>
+ <FormControl>
+ <Input
+ type="number"
+ step="0.01"
+ placeholder="0.00"
+ {...field}
+ value={field.value ?? ''}
+ disabled={disabled}
+ />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ <FormField
+ control={form.control}
+ name={`criteriaDetails.${index}.scoreBulkShip`}
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>벌크-조선</FormLabel>
+ <FormControl>
+ <Input
+ type="number"
+ step="0.01"
+ placeholder="0.00"
+ {...field}
+ value={field.value ?? ''}
+ disabled={disabled}
+ />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ <FormField
+ control={form.control}
+ name={`criteriaDetails.${index}.scoreBulkMarine`}
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>벌크-해양</FormLabel>
+ <FormControl>
+ <Input
+ type="number"
+ step="0.01"
+ placeholder="0.00"
+ {...field}
+ value={field.value ?? ''}
+ disabled={disabled}
+ />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ </div>
</CardContent>
</Card>
)
}
-
/* CRITERIA FORM SHEET COPONENT */
function RegEvalCriteriaCreateDialog({
open,
@@ -231,6 +236,7 @@ function RegEvalCriteriaCreateDialog({
onSuccess,
}: RegEvalCriteriaFormSheetProps) {
const [isPending, startTransition] = useTransition();
+ const { data: session } = useSession();
const form = useForm<RegEvalCriteriaFormData>({
resolver: zodResolver(regEvalCriteriaFormSchema),
defaultValues: {
@@ -240,6 +246,10 @@ function RegEvalCriteriaCreateDialog({
classification: '',
range: '',
remarks: '',
+ scoreType: 'fixed',
+ variableScoreMin: null,
+ variableScoreMax: null,
+ variableScoreUnit: '',
criteriaDetails: [
{
id: undefined,
@@ -252,12 +262,11 @@ function RegEvalCriteriaCreateDialog({
],
},
});
-
const { fields, append, remove } = useFieldArray({
control: form.control,
name: 'criteriaDetails',
});
-
+ const scoreType = form.watch('scoreType');
useEffect(() => {
if (open) {
form.reset({
@@ -267,6 +276,10 @@ function RegEvalCriteriaCreateDialog({
classification: '',
range: '',
remarks: '',
+ scoreType: 'fixed',
+ variableScoreMin: null,
+ variableScoreMax: null,
+ variableScoreUnit: '',
criteriaDetails: [
{
id: undefined,
@@ -280,32 +293,92 @@ function RegEvalCriteriaCreateDialog({
})
}
}, [open, form]);
-
- const onSubmit = async (data: RegEvalCriteriaFormData) => {
+ const onSubmit = async (data: any) => {
startTransition(async () => {
try {
- const criteriaData = {
- category: data.category,
- category2: data.category2,
- item: data.item,
- classification: data.classification,
- range: data.range,
- remarks: data.remarks,
- };
- 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,
- }));
+ const userId = session?.user?.id ? Number(session.user.id) : 1;
+
+ 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 baseCriteriaData = {
+ 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
+ createdBy: userId,
+ updatedBy: userId,
+ };
+
+ const detailList = data.criteriaDetails.map((detailItem: NonNullable<RegEvalCriteriaFormData['criteriaDetails']>[0]) => ({
+ 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 createRegEvalCriteriaFixed(baseCriteriaData, detailList);
- await createRegEvalCriteriaWithDetails(criteriaData, detailList);
+ } else if (data.scoreType === 'variable') {
+ // 변동 점수 검증
+ if (data.variableScoreMin == null || data.variableScoreMin === '') {
+ toast.error('변동 점수 유형에서는 최소 점수가 필수입니다.');
+ return;
+ }
+ if (data.variableScoreMax == null || data.variableScoreMax === '') {
+ toast.error('변동 점수 유형에서는 최대 점수가 필수입니다.');
+ return;
+ }
+ if (!data.variableScoreUnit || data.variableScoreUnit.trim() === '') {
+ toast.error('변동 점수 유형에서는 단위가 필수입니다.');
+ return;
+ }
+ if (Number(data.variableScoreMin) >= Number(data.variableScoreMax)) {
+ toast.error('최소 점수는 최대 점수보다 작아야 합니다.');
+ return;
+ }
+
+ const variableCriteriaData = {
+ 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(),
+ createdBy: userId,
+ updatedBy: userId,
+ };
+
+ await createRegEvalCriteriaVariable(variableCriteriaData);
+ } else {
+ toast.error('올바른 점수 유형을 선택해주세요.');
+ return;
+ }
+
toast.success('평가 기준표가 생성되었습니다.');
onSuccess();
onOpenChange(false);
@@ -317,15 +390,13 @@ function RegEvalCriteriaCreateDialog({
}
})
}
-
if (!open) {
return null;
}
-
return (
<Dialog open={open} onOpenChange={onOpenChange}>
- <DialogContent className="w-1/3 max-w-[50vw] max-h-[90vh] overflow-y-auto">
- <DialogHeader className="mb-4">
+ <DialogContent className="max-w-4xl max-h-[90vh] flex flex-col">
+ <DialogHeader className="flex-shrink-0">
<DialogTitle className="font-bold">
새 협력업체 평가 기준표 생성
</DialogTitle>
@@ -334,33 +405,112 @@ function RegEvalCriteriaCreateDialog({
</DialogDescription>
</DialogHeader>
<Form {...form}>
- <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
- <ScrollArea className="overflow-y-auto">
+ <form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col flex-1 min-h-0">
+ <ScrollArea className="flex-1 pr-4 overflow-y-auto">
<div className="space-y-6">
<Card className="w-full">
<CardHeader>
- <CardTitle>Criterion Info</CardTitle>
+ <CardTitle>기준 정보</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
+ <div className="grid grid-cols-2 gap-4">
+ <FormField
+ control={form.control}
+ name="category"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>평가부문</FormLabel>
+ <FormControl>
+ <Select onValueChange={field.onChange} value={field.value || ''}>
+ <SelectTrigger>
+ <SelectValue placeholder="선택" />
+ </SelectTrigger>
+ <SelectContent>
+ {REG_EVAL_CRITERIA_CATEGORY.map((option) => (
+ <SelectItem key={option.value} value={option.value}>
+ {option.label}
+ </SelectItem>
+ ))}
+ </SelectContent>
+ </Select>
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ <FormField
+ control={form.control}
+ name="category2"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>점수구분</FormLabel>
+ <FormControl>
+ <Select onValueChange={field.onChange} value={field.value || ''}>
+ <SelectTrigger>
+ <SelectValue placeholder="선택" />
+ </SelectTrigger>
+ <SelectContent>
+ {REG_EVAL_CRITERIA_CATEGORY2.map((option) => (
+ <SelectItem key={option.value} value={option.value}>
+ {option.label}
+ </SelectItem>
+ ))}
+ </SelectContent>
+ </Select>
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ <FormField
+ control={form.control}
+ name="item"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>항목</FormLabel>
+ <FormControl>
+ <Select onValueChange={field.onChange} value={field.value || ''}>
+ <SelectTrigger>
+ <SelectValue placeholder="선택" />
+ </SelectTrigger>
+ <SelectContent>
+ {REG_EVAL_CRITERIA_ITEM.map((option) => (
+ <SelectItem key={option.value} value={option.value}>
+ {option.label}
+ </SelectItem>
+ ))}
+ </SelectContent>
+ </Select>
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ <FormField
+ control={form.control}
+ name="classification"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>구분</FormLabel>
+ <FormControl>
+ <Input placeholder="구분을 입력하세요." {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ </div>
<FormField
control={form.control}
- name="category"
+ name="range"
render={({ field }) => (
<FormItem>
- <FormLabel>평가부문</FormLabel>
+ <FormLabel>평가명</FormLabel>
<FormControl>
- <Select onValueChange={field.onChange} value={field.value || ''}>
- <SelectTrigger>
- <SelectValue placeholder="선택" />
- </SelectTrigger>
- <SelectContent>
- {REG_EVAL_CRITERIA_CATEGORY.map((option) => (
- <SelectItem key={option.value} value={option.value}>
- {option.label}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
+ <Input
+ placeholder="평가명을 입력하세요." {...field}
+ value={field.value ?? ''}
+ />
</FormControl>
<FormMessage />
</FormItem>
@@ -368,23 +518,16 @@ function RegEvalCriteriaCreateDialog({
/>
<FormField
control={form.control}
- name="category2"
+ name="remarks"
render={({ field }) => (
<FormItem>
- <FormLabel>점수구분</FormLabel>
+ <FormLabel>비고</FormLabel>
<FormControl>
- <Select onValueChange={field.onChange} value={field.value || ''}>
- <SelectTrigger>
- <SelectValue placeholder="선택" />
- </SelectTrigger>
- <SelectContent>
- {REG_EVAL_CRITERIA_CATEGORY2.map((option) => (
- <SelectItem key={option.value} value={option.value}>
- {option.label}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
+ <Textarea
+ placeholder="비고를 입력하세요."
+ {...field}
+ value={field.value ?? ''}
+ />
</FormControl>
<FormMessage />
</FormItem>
@@ -392,21 +535,18 @@ function RegEvalCriteriaCreateDialog({
/>
<FormField
control={form.control}
- name="item"
+ name="scoreType"
render={({ field }) => (
<FormItem>
- <FormLabel>항목</FormLabel>
+ <FormLabel>점수 유형</FormLabel>
<FormControl>
- <Select onValueChange={field.onChange} value={field.value || ''}>
+ <Select onValueChange={field.onChange} value={field.value}>
<SelectTrigger>
- <SelectValue placeholder="선택" />
+ <SelectValue placeholder="점수 유형 선택" />
</SelectTrigger>
<SelectContent>
- {REG_EVAL_CRITERIA_ITEM.map((option) => (
- <SelectItem key={option.value} value={option.value}>
- {option.label}
- </SelectItem>
- ))}
+ <SelectItem value="fixed">고정</SelectItem>
+ <SelectItem value="variable">변동</SelectItem>
</SelectContent>
</Select>
</FormControl>
@@ -414,123 +554,151 @@ function RegEvalCriteriaCreateDialog({
</FormItem>
)}
/>
- <FormField
- control={form.control}
- name="classification"
- render={({ field }) => (
- <FormItem>
- <FormLabel>구분</FormLabel>
- <FormControl>
- <Input placeholder="구분을 입력하세요." {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
- name="range"
- render={({ field }) => (
- <FormItem>
- <FormLabel>범위</FormLabel>
- <FormControl>
- <Input
- placeholder="범위를 입력하세요." {...field}
- value={field.value ?? ''}
+ {scoreType === 'variable' && (
+ <div className="grid grid-cols-3 gap-4">
+ <FormField
+ control={form.control}
+ name="variableScoreMin"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>최소점수</FormLabel>
+ <FormControl>
+ <Input
+ type="number"
+ min="0"
+ step="1"
+ placeholder="점수 입력 (0 이상)"
+ {...field}
+ value={field.value ?? ''}
+ />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
/>
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
- name="remarks"
- render={({ field }) => (
- <FormItem>
- <FormLabel>비고</FormLabel>
- <FormControl>
- <Textarea
- placeholder="비고를 입력하세요."
- {...field}
- value={field.value ?? ''}
+ <FormField
+ control={form.control}
+ name="variableScoreMax"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>최대점수</FormLabel>
+ <FormControl>
+ <Input
+ type="number"
+ min="0"
+ step="1"
+ placeholder="점수 입력 (0 이상)"
+ {...field}
+ value={field.value ?? ''}
+ />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ <FormField
+ control={form.control}
+ name="variableScoreUnit"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>점수단위</FormLabel>
+ <FormControl>
+ <Input
+ placeholder="예: 감점, 가점"
+ {...field}
+ value={field.value ?? ''}
+ />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
/>
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- </CardContent>
- </Card>
- <Card>
- <CardHeader>
- <div className="flex items-center justify-between">
- <div>
- <CardTitle>Evaluation Criteria Item</CardTitle>
- <CardDescription>
- Set Evaluation Criteria Item.
- </CardDescription>
</div>
- <Button
- type="button"
- variant="outline"
- size="sm"
- className="ml-4"
- onClick={() =>
- append({
- id: undefined,
- detail: '',
- scoreEquipShip: null,
- scoreEquipMarine: null,
- scoreBulkShip: null,
- scoreBulkMarine: null,
- })
- }
- disabled={isPending}
- >
- <Plus className="w-4 h-4 mr-2" />
- New Item
- </Button>
- </div>
- </CardHeader>
- <CardContent>
- <div className="space-y-4">
- {fields.map((field, index) => (
- <CriteriaDetailForm
- key={field.id}
- index={index}
- form={form}
- onRemove={() => remove(index)}
- canRemove={fields.length > 1}
- disabled={isPending}
- />
- ))}
- </div>
+ )}
</CardContent>
</Card>
+
+ {scoreType === 'fixed' && (
+ <Card>
+ <CardHeader>
+ <div className="flex items-center justify-between">
+ <div>
+ <CardTitle>평가 옵션 설정</CardTitle>
+ <CardDescription>
+ 평가 옵션을 설정합니다.
+ </CardDescription>
+ </div>
+ <Button
+ type="button"
+ variant="outline"
+ size="sm"
+ onClick={() =>
+ append({
+ id: undefined,
+ detail: '',
+ scoreEquipShip: null,
+ scoreEquipMarine: null,
+ scoreBulkShip: null,
+ scoreBulkMarine: null,
+ })
+ }
+ disabled={isPending}
+ >
+ <Plus className="w-4 h-4 mr-2" />
+ 항목 추가
+ </Button>
+ </div>
+ </CardHeader>
+ <CardContent>
+ <div className="space-y-4">
+ {fields.map((field, index) => (
+ <CriteriaDetailForm
+ key={field.id}
+ index={index}
+ form={form}
+ onRemove={() => remove(index)}
+ canRemove={fields.length > 1}
+ disabled={isPending}
+ />
+ ))}
+ </div>
+ </CardContent>
+ </Card>
+ )}
+
+ {scoreType === 'variable' && (
+ <Card>
+ <CardHeader>
+ <CardTitle>변동 점수 설정</CardTitle>
+ <CardDescription>
+ 변동 점수 유형에서는 개별 평가 옵션을 설정할 수 없습니다.
+ 최소/최대 점수와 단위를 설정하여 점수 범위를 정의하세요.
+ </CardDescription>
+ </CardHeader>
+ </Card>
+ )}
</div>
</ScrollArea>
- <div className="flex justify-end gap-2 pt-4 border-t">
+
+ <DialogFooter className="flex-shrink-0 mt-4 pt-4 border-t">
<Button
type="button"
variant="outline"
onClick={() => onOpenChange(false)}
disabled={isPending}
>
- Cancel
+ 취소
</Button>
<Button type="submit" disabled={isPending}>
- {isPending ? 'Saving...' : 'Create'}
+ {isPending ? '저장 중...' : '생성'}
</Button>
- </div>
+ </DialogFooter>
</form>
</Form>
</DialogContent>
</Dialog>
)
}
-
// ----------------------------------------------------------------------------------------------------
-
/* EXPORT */
export default RegEvalCriteriaCreateDialog; \ No newline at end of file