diff options
| author | 0-Zz-ang <s1998319@gmail.com> | 2025-11-19 09:50:12 +0900 |
|---|---|---|
| committer | 0-Zz-ang <s1998319@gmail.com> | 2025-11-19 09:50:12 +0900 |
| commit | 2f1bef8eeff5d6cd30c4de808402893deb35335d (patch) | |
| tree | b3a286bca25df3a038ace20969855b8485878b7b /lib/compliance/table | |
| parent | 84277bd79bd6a2bff0f6ef6840f1790db06036e6 (diff) | |
준법설문조사 리비전관리
Diffstat (limited to 'lib/compliance/table')
3 files changed, 90 insertions, 36 deletions
diff --git a/lib/compliance/table/compliance-survey-templates-toolbar.tsx b/lib/compliance/table/compliance-survey-templates-toolbar.tsx index 6776b70a..3e5f7f4d 100644 --- a/lib/compliance/table/compliance-survey-templates-toolbar.tsx +++ b/lib/compliance/table/compliance-survey-templates-toolbar.tsx @@ -16,6 +16,11 @@ interface ComplianceSurveyTemplatesToolbarActionsProps { } export function ComplianceSurveyTemplatesToolbarActions({ table }: ComplianceSurveyTemplatesToolbarActionsProps) { + const templates = React.useMemo( + () => table.getPreFilteredRowModel().rows.map((row) => row.original), + [table], + ); + return ( <div className="flex items-center gap-2"> {/** 1) 선택된 로우가 있으면 삭제 다이얼로그 */} @@ -27,7 +32,7 @@ export function ComplianceSurveyTemplatesToolbarActions({ table }: ComplianceSur /> ) : null} - <ComplianceTemplateCreateDialog /> + <ComplianceTemplateCreateDialog templates={templates} /> {/** 2) 레드플래그 담당자 관리 */} <RedFlagManagersDialog /> diff --git a/lib/compliance/table/compliance-template-create-dialog.tsx b/lib/compliance/table/compliance-template-create-dialog.tsx index 5b7e1092..db4ede4e 100644 --- a/lib/compliance/table/compliance-template-create-dialog.tsx +++ b/lib/compliance/table/compliance-template-create-dialog.tsx @@ -29,19 +29,33 @@ import { Switch } from "@/components/ui/switch" import { Plus, Loader2 } from "lucide-react" import { toast } from "sonner" import { createComplianceSurveyTemplate } from "../services" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" +import { complianceSurveyTemplates } from "@/db/schema/compliance" const createTemplateSchema = z.object({ name: z.string().min(1, "템플릿명을 입력해주세요.").max(100, "템플릿명은 100자 이하여야 합니다."), description: z.string().min(1, "설명을 입력해주세요.").max(500, "설명은 500자 이하여야 합니다."), - version: z.string().min(1, "버전을 입력해주세요.").max(20, "버전은 20자 이하여야 합니다."), isActive: z.boolean().default(true), }) type CreateTemplateFormValues = z.infer<typeof createTemplateSchema> -export function ComplianceTemplateCreateDialog() { +interface ComplianceTemplateCreateDialogProps { + templates?: typeof complianceSurveyTemplates.$inferSelect[] +} + +export function ComplianceTemplateCreateDialog({ + templates = [], +}: ComplianceTemplateCreateDialogProps) { const [open, setOpen] = React.useState(false) const [isSubmitting, setIsSubmitting] = React.useState(false) + const [selectedTemplateId, setSelectedTemplateId] = React.useState<string>("none") // react-hook-form 세팅 const form = useForm<CreateTemplateFormValues>({ @@ -49,19 +63,54 @@ export function ComplianceTemplateCreateDialog() { defaultValues: { name: "", description: "", - version: "1.0", isActive: true, }, mode: "onChange", }) + const selectedTemplate = React.useMemo(() => { + if (selectedTemplateId === "none") { + return undefined + } + return templates.find((template) => String(template.id) === selectedTemplateId) + }, [selectedTemplateId, templates]) + + const nextVersionLabel = React.useMemo(() => { + if (!selectedTemplate) { + return null + } + const baseVersion = selectedTemplate.version || "1.0" + const numericValue = Number(baseVersion) + if (!Number.isNaN(numericValue)) { + const hasDecimal = baseVersion.includes(".") + const decimalDigits = hasDecimal ? baseVersion.split(".")[1]?.length ?? 0 : 0 + const incremented = numericValue + 1 + return hasDecimal ? incremented.toFixed(decimalDigits) : String(incremented) + } + return "1.0" + }, [selectedTemplate]) + + React.useEffect(() => { + if (selectedTemplate) { + form.setValue("name", selectedTemplate.name ?? "") + form.setValue("description", selectedTemplate.description ?? "") + } + }, [selectedTemplate, form]) + async function onSubmit(data: CreateTemplateFormValues) { setIsSubmitting(true) try { - const result = await createComplianceSurveyTemplate(data) + const baseTemplateNumericId = + selectedTemplateId !== "none" ? Number(selectedTemplateId) : undefined + + const result = await createComplianceSurveyTemplate({ + ...data, + baseTemplateId: baseTemplateNumericId, + }) if (result) { toast.success("새로운 설문조사 템플릿이 생성되었습니다.") form.reset() + setSelectedTemplateId("none") setOpen(false) // 페이지 새로고침으로 데이터 업데이트 window.location.reload() @@ -77,6 +126,7 @@ export function ComplianceTemplateCreateDialog() { function handleDialogOpenChange(nextOpen: boolean) { if (!nextOpen) { form.reset() + setSelectedTemplateId("none") } setOpen(nextOpen) } @@ -133,22 +183,37 @@ export function ComplianceTemplateCreateDialog() { )} /> - <FormField - control={form.control} - name="version" - render={({ field }) => ( - <FormItem> - <FormLabel>버전 *</FormLabel> - <FormControl> - <Input - placeholder="예: 1.0" - {...field} - /> - </FormControl> - <FormMessage /> - </FormItem> + <div className="space-y-2"> + <FormLabel>기존 템플릿 불러오기 (선택)</FormLabel> + <Select + value={selectedTemplateId} + onValueChange={(value) => setSelectedTemplateId(value)} + > + <FormControl> + <SelectTrigger> + <SelectValue placeholder="불러올 템플릿을 선택하세요" /> + </SelectTrigger> + </FormControl> + <SelectContent> + <SelectItem value="none">선택하지 않음</SelectItem> + {templates.map((template) => ( + <SelectItem key={template.id} value={String(template.id)}> + {template.name} (v{template.version}) + </SelectItem> + ))} + </SelectContent> + </Select> + {selectedTemplate ? ( + <p className="text-sm text-muted-foreground"> + 선택한 템플릿을 기반으로 새 버전(v{nextVersionLabel})이 생성되며, + 기존 템플릿은 자동으로 비활성화됩니다. + </p> + ) : ( + <p className="text-sm text-muted-foreground"> + 템플릿을 선택하지 않으면 새 템플릿이 기본 버전(v1.0)으로 생성됩니다. + </p> )} - /> + </div> <FormField control={form.control} diff --git a/lib/compliance/table/compliance-template-edit-sheet.tsx b/lib/compliance/table/compliance-template-edit-sheet.tsx index 3ac4870a..96ffa8f5 100644 --- a/lib/compliance/table/compliance-template-edit-sheet.tsx +++ b/lib/compliance/table/compliance-template-edit-sheet.tsx @@ -33,7 +33,6 @@ import { useRouter } from "next/navigation"; const templateSchema = z.object({ name: z.string().min(1, "템플릿명을 입력하세요"), description: z.string().min(1, "설명을 입력하세요"), - version: z.string().min(1, "버전을 입력하세요"), isActive: z.boolean(), }); @@ -58,7 +57,6 @@ export function ComplianceTemplateEditSheet({ defaultValues: { name: template.name, description: template.description, - version: template.version, isActive: template.isActive, }, }); @@ -128,20 +126,6 @@ export function ComplianceTemplateEditSheet({ <FormField control={form.control} - name="version" - render={({ field }) => ( - <FormItem> - <FormLabel>버전</FormLabel> - <FormControl> - <Input placeholder="버전을 입력하세요" {...field} /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - - <FormField - control={form.control} name="isActive" render={({ field }) => ( <FormItem className="flex flex-row items-start space-x-3 space-y-0"> |
