From 8b23b471638a155fd1bfa3a8c853b26d9315b272 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Fri, 26 Sep 2025 09:57:24 +0000 Subject: (대표님) 권한관리, 문서업로드, rfq첨부, SWP문서룰 등 (최겸) 입찰 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/docu-list-rule/number-type-configs/service.ts | 7 +- .../table/number-type-configs-edit-dialog.tsx | 277 +++++++++++++-------- .../table/number-type-configs-toolbar-actions.tsx | 251 ++++++++++++------- lib/docu-list-rule/types.ts | 1 + 4 files changed, 332 insertions(+), 204 deletions(-) (limited to 'lib/docu-list-rule') diff --git a/lib/docu-list-rule/number-type-configs/service.ts b/lib/docu-list-rule/number-type-configs/service.ts index c29af464..b644c43a 100644 --- a/lib/docu-list-rule/number-type-configs/service.ts +++ b/lib/docu-list-rule/number-type-configs/service.ts @@ -166,12 +166,12 @@ export async function getNumberTypeConfigs(input: GetNumberTypeConfigsSchema) { } } -// Number Type Config 생성 export async function createNumberTypeConfig(input: { documentNumberTypeId: number codeGroupId: number | null sdq: number description?: string + delimiter?: string remark?: string }) { try { @@ -198,6 +198,7 @@ export async function createNumberTypeConfig(input: { codeGroupId: input.codeGroupId, sdq: input.sdq, description: input.description, + delimiter: input.delimiter, remark: input.remark, }) .returning({ id: documentNumberTypeConfigs.id }) @@ -218,12 +219,12 @@ export async function createNumberTypeConfig(input: { } } -// Number Type Config 수정 export async function updateNumberTypeConfig(input: { id: number codeGroupId: number | null sdq: number description?: string + delimiter?: string remark?: string }) { try { @@ -263,6 +264,7 @@ export async function updateNumberTypeConfig(input: { codeGroupId: input.codeGroupId, sdq: input.sdq, description: input.description, + delimiter: input.delimiter, remark: input.remark, updatedAt: new Date(), }) @@ -284,7 +286,6 @@ export async function updateNumberTypeConfig(input: { } } } - // Number Type Config 순서 변경 (간단한 방식) export async function updateNumberTypeConfigOrder(input: { id: number diff --git a/lib/docu-list-rule/number-type-configs/table/number-type-configs-edit-dialog.tsx b/lib/docu-list-rule/number-type-configs/table/number-type-configs-edit-dialog.tsx index cd2d6fc8..ad3478ff 100644 --- a/lib/docu-list-rule/number-type-configs/table/number-type-configs-edit-dialog.tsx +++ b/lib/docu-list-rule/number-type-configs/table/number-type-configs-edit-dialog.tsx @@ -2,6 +2,9 @@ import * as React from "react" import { Loader2 } from "lucide-react" +import { useForm } from "react-hook-form" +import { zodResolver } from "@hookform/resolvers/zod" +import * as z from "zod" import { toast } from "sonner" import { Button } from "@/components/ui/button" @@ -13,6 +16,14 @@ import { DialogHeader, DialogTitle, } from "@/components/ui/dialog" +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form" import { Select, SelectContent, @@ -21,18 +32,30 @@ import { SelectValue, } from "@/components/ui/select" import { Input } from "@/components/ui/input" -import { Label } from "@/components/ui/label" import { Textarea } from "@/components/ui/textarea" import { updateNumberTypeConfig, getActiveCodeGroups } from "@/lib/docu-list-rule/number-type-configs/service" import { NumberTypeConfig } from "@/lib/docu-list-rule/types" +const formSchema = z.object({ + codeGroupId: z.string().min(1, "Code Group을 선택해주세요."), + sdq: z.string().min(1, "순서를 입력해주세요.").refine( + (val) => !isNaN(Number(val)) && Number(val) > 0, + { message: "순서는 1 이상의 숫자여야 합니다." } + ), + description: z.string().optional(), + delimiter: z.string().max(10).optional(), + remark: z.string().optional(), +}) + +type FormData = z.infer + interface NumberTypeConfigsEditDialogProps { open: boolean onOpenChange: (open: boolean) => void data: NumberTypeConfig | null onSuccess?: () => void - existingConfigs?: NumberTypeConfig[] // 기존 configs 목록 추가 + existingConfigs?: NumberTypeConfig[] selectedProjectId?: number | null } @@ -41,29 +64,35 @@ export function NumberTypeConfigsEditDialog({ onOpenChange, data, onSuccess, - existingConfigs = [], // 기본값 추가 + existingConfigs = [], selectedProjectId, }: NumberTypeConfigsEditDialogProps) { const [isLoading, setIsLoading] = React.useState(false) const [codeGroups, setCodeGroups] = React.useState<{ id: number; description: string }[]>([]) - const [formData, setFormData] = React.useState({ - codeGroupId: "", - sdq: "", - description: "", - remark: "" + + const form = useForm({ + resolver: zodResolver(formSchema), + defaultValues: { + codeGroupId: "", + sdq: "", + description: "", + delimiter: "", + remark: "", + }, }) // 데이터가 변경될 때 폼 초기화 React.useEffect(() => { if (data) { - setFormData({ - codeGroupId: data.codeGroupId?.toString() || "", // null 체크 추가 + form.reset({ + codeGroupId: data.codeGroupId?.toString() || "", sdq: data.sdq.toString(), description: data.description || "", + delimiter: data.delimiter || "", remark: data.remark || "" }) } - }, [data]) + }, [data, form]) // Code Groups 로드 React.useEffect(() => { @@ -79,21 +108,23 @@ export function NumberTypeConfigsEditDialog({ })() }, [selectedProjectId]) - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault() - if (!data || !formData.codeGroupId || !formData.sdq) { - toast.error("필수 필드를 모두 입력해주세요.") + const onSubmit = async (values: FormData) => { + if (!data) { + toast.error("데이터를 찾을 수 없습니다.") return } - const newSdq = parseInt(formData.sdq) + const newSdq = parseInt(values.sdq) // 순서 중복 검증 (현재 수정 중인 항목 제외) const existingSdq = existingConfigs.find(config => config.sdq === newSdq && config.id !== data.id ) if (existingSdq) { - toast.error(`순서 ${newSdq}번은 이미 사용 중입니다. 다른 순서를 입력해주세요.`) + form.setError("sdq", { + type: "manual", + message: `순서 ${newSdq}번은 이미 사용 중입니다. 다른 순서를 입력해주세요.` + }) return } @@ -101,11 +132,11 @@ export function NumberTypeConfigsEditDialog({ try { const result = await updateNumberTypeConfig({ id: data.id, - codeGroupId: parseInt(formData.codeGroupId), - + codeGroupId: parseInt(values.codeGroupId), sdq: newSdq, - description: formData.description || undefined, - remark: formData.remark || undefined, + description: values.description || undefined, + delimiter: values.delimiter || undefined, + remark: values.remark || undefined, }) if (result.success) { @@ -135,91 +166,127 @@ export function NumberTypeConfigsEditDialog({ * 표시된 항목은 필수 입력사항입니다. -
-
-
- -
- -
-
-
- -
- setFormData(prev => ({ ...prev, sdq: e.target.value }))} - min="1" - /> -
-
-
- -
- setFormData(prev => ({ ...prev, description: e.target.value }))} - placeholder="예: PROJECT NO" - /> -
-
-
- -
-