diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/approval-line/service.ts | 17 | ||||
| -rw-r--r-- | lib/approval-line/table/approval-line-table-columns.tsx | 15 | ||||
| -rw-r--r-- | lib/approval-line/table/approval-line-table.tsx | 5 | ||||
| -rw-r--r-- | lib/approval-line/table/create-approval-line-sheet.tsx | 17 | ||||
| -rw-r--r-- | lib/approval-line/table/update-approval-line-sheet.tsx | 17 | ||||
| -rw-r--r-- | lib/approval-line/validations.ts | 1 | ||||
| -rw-r--r-- | lib/approval-template/service.ts | 11 | ||||
| -rw-r--r-- | lib/revalidate.ts | 32 |
8 files changed, 115 insertions, 0 deletions
diff --git a/lib/approval-line/service.ts b/lib/approval-line/service.ts index 3000e25f..f3c3fb95 100644 --- a/lib/approval-line/service.ts +++ b/lib/approval-line/service.ts @@ -1,6 +1,7 @@ 'use server'; import db from '@/db/db'; +import { revalidateI18nPaths } from '@/lib/revalidate'; import { and, asc, @@ -21,6 +22,14 @@ import { filterColumns } from '@/lib/filter-columns'; // --------------------------------------------- export type ApprovalLine = typeof approvalLines.$inferSelect; +// --------------------------------------------- +// Revalidation helpers +// --------------------------------------------- + +async function revalidateApprovalLinesPaths() { + await revalidateI18nPaths('/evcp/approval/line'); +} + export interface ApprovalLineWithUsage extends ApprovalLine { templateCount: number; // 사용 중인 템플릿 수 @@ -193,6 +202,7 @@ export async function getApprovalLine(id: string): Promise<ApprovalLine | null> interface CreateInput { name: string; description?: string; + category?: string | null; // eslint-disable-next-line @typescript-eslint/no-explicit-any aplns: any[]; // 결재선 구성 (JSON) createdBy: number; @@ -215,12 +225,14 @@ export async function createApprovalLine(data: CreateInput): Promise<ApprovalLin .values({ name: data.name, description: data.description, + category: data.category ?? null, // eslint-disable-next-line @typescript-eslint/no-explicit-any aplns: data.aplns as any, createdBy: data.createdBy, }) .returning(); + await revalidateApprovalLinesPaths(); return newLine; } @@ -230,6 +242,7 @@ export async function createApprovalLine(data: CreateInput): Promise<ApprovalLin interface UpdateInput { name?: string; description?: string; + category?: string | null; // eslint-disable-next-line @typescript-eslint/no-explicit-any aplns?: any[]; // 결재선 구성 (JSON) updatedBy: number; @@ -263,6 +276,7 @@ export async function updateApprovalLine(id: string, data: UpdateInput): Promise .set({ name: data.name ?? existing.name, description: data.description ?? existing.description, + category: data.category ?? existing.category, // eslint-disable-next-line @typescript-eslint/no-explicit-any aplns: (data.aplns as any) ?? (existing.aplns as any), updatedAt: new Date(), @@ -271,6 +285,7 @@ export async function updateApprovalLine(id: string, data: UpdateInput): Promise const result = await getApprovalLine(id); if (!result) throw new Error('업데이트된 결재선을 조회할 수 없습니다.'); + await revalidateApprovalLinesPaths(); return result; } @@ -305,6 +320,7 @@ export async function duplicateApprovalLine( const duplicated = await createApprovalLine({ name: newName, description: existing.description ? `${existing.description} (복사본)` : undefined, + category: existing.category ?? null, // eslint-disable-next-line @typescript-eslint/no-explicit-any aplns: existing.aplns as any, createdBy, @@ -322,6 +338,7 @@ export async function duplicateApprovalLine( export async function deleteApprovalLine(id: string): Promise<{ success: boolean; error?: string }> { try { await db.delete(approvalLines).where(eq(approvalLines.id, id)); + await revalidateApprovalLinesPaths(); return { success: true }; } catch (error) { return { diff --git a/lib/approval-line/table/approval-line-table-columns.tsx b/lib/approval-line/table/approval-line-table-columns.tsx index 5b35b92c..a9cf58e1 100644 --- a/lib/approval-line/table/approval-line-table-columns.tsx +++ b/lib/approval-line/table/approval-line-table-columns.tsx @@ -68,6 +68,21 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<Approva }, }, { + accessorKey: "category", + header: ({ column }) => ( + <DataTableColumnHeader column={column} title="카테고리" /> + ), + cell: ({ row }) => { + return ( + <div className="flex space-x-2"> + <span className="max-w-[200px] truncate"> + {row.getValue("category") || "-"} + </span> + </div> + ) + }, + }, + { accessorKey: "description", header: ({ column }) => ( <DataTableColumnHeader column={column} title="설명" /> diff --git a/lib/approval-line/table/approval-line-table.tsx b/lib/approval-line/table/approval-line-table.tsx index 21b9972c..61cddf8b 100644 --- a/lib/approval-line/table/approval-line-table.tsx +++ b/lib/approval-line/table/approval-line-table.tsx @@ -47,6 +47,11 @@ export function ApprovalLineTable({ promises }: ApprovalLineTableProps) { type: 'text', }, { + id: 'category', + label: '카테고리', + type: 'text', + }, + { id: 'description', label: '설명', type: 'text', diff --git a/lib/approval-line/table/create-approval-line-sheet.tsx b/lib/approval-line/table/create-approval-line-sheet.tsx index fdc8cc64..c19d11ab 100644 --- a/lib/approval-line/table/create-approval-line-sheet.tsx +++ b/lib/approval-line/table/create-approval-line-sheet.tsx @@ -20,6 +20,7 @@ import { FormMessage, } from "@/components/ui/form" import { Input } from "@/components/ui/input" +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Textarea } from "@/components/ui/textarea" import { Separator } from "@/components/ui/separator" import { toast } from "sonner" @@ -46,6 +47,7 @@ export function CreateApprovalLineSheet({ open, onOpenChange }: CreateApprovalLi resolver: zodResolver(ApprovalLineSchema), defaultValues: { name: "", + category: "", description: "", aplns: [ // 기안자는 항상 첫 번째로 고정 (플레이스홀더) @@ -104,6 +106,7 @@ export function CreateApprovalLineSheet({ open, onOpenChange }: CreateApprovalLi await createApprovalLine({ name: data.name, + category: data.category || undefined, description: data.description, aplns: data.aplns, createdBy: Number(session.user.id), @@ -150,6 +153,20 @@ export function CreateApprovalLineSheet({ open, onOpenChange }: CreateApprovalLi <FormField control={form.control} + name="category" + render={({ field }) => ( + <FormItem> + <FormLabel>카테고리</FormLabel> + <FormControl> + <Input placeholder="카테고리를 입력하세요" {...field} /> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + + <FormField + control={form.control} name="description" render={({ field }) => ( <FormItem> diff --git a/lib/approval-line/table/update-approval-line-sheet.tsx b/lib/approval-line/table/update-approval-line-sheet.tsx index efc720de..9153eb38 100644 --- a/lib/approval-line/table/update-approval-line-sheet.tsx +++ b/lib/approval-line/table/update-approval-line-sheet.tsx @@ -61,6 +61,7 @@ export function UpdateApprovalLineSheet({ open, onOpenChange, line }: UpdateAppr resolver: zodResolver(ApprovalLineSchema), defaultValues: { name: "", + category: "", description: "", aplns: [], }, @@ -94,6 +95,7 @@ export function UpdateApprovalLineSheet({ open, onOpenChange, line }: UpdateAppr form.reset({ name: line.name, + category: line.category || "", description: line.description || "", aplns: nextAplns as ApprovalLineFormData["aplns"], }); @@ -140,6 +142,7 @@ export function UpdateApprovalLineSheet({ open, onOpenChange, line }: UpdateAppr try { await updateApprovalLine(line.id, { name: data.name, + category: data.category || null, description: data.description, aplns: data.aplns, updatedBy: Number(session.user.id), @@ -190,6 +193,20 @@ export function UpdateApprovalLineSheet({ open, onOpenChange, line }: UpdateAppr <FormField control={form.control} + name="category" + render={({ field }) => ( + <FormItem> + <FormLabel>카테고리</FormLabel> + <FormControl> + <Input placeholder="카테고리를 입력하세요" {...field} /> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + + <FormField + control={form.control} name="description" render={({ field }) => ( <FormItem> diff --git a/lib/approval-line/validations.ts b/lib/approval-line/validations.ts index 4f55454a..141c12e6 100644 --- a/lib/approval-line/validations.ts +++ b/lib/approval-line/validations.ts @@ -7,6 +7,7 @@ export const SearchParamsApprovalLineCache = SearchParamsApprovalTemplateCache; // 결재선 생성/수정 스키마 export const ApprovalLineSchema = z.object({ name: z.string().min(1, '결재선 이름은 필수입니다'), + category: z.string().optional(), description: z.string().optional(), aplns: z.array(z.object({ id: z.string(), diff --git a/lib/approval-template/service.ts b/lib/approval-template/service.ts index 5dc989d9..cb687c4f 100644 --- a/lib/approval-template/service.ts +++ b/lib/approval-template/service.ts @@ -1,6 +1,7 @@ 'use server'; import db from '@/db/db'; +import { revalidateI18nPaths } from '@/lib/revalidate'; import { and, asc, @@ -28,6 +29,13 @@ export type ApprovalTemplateVariable = typeof approvalTemplateVariables.$inferSelect; export type ApprovalTemplateHistory = typeof approvalTemplateHistory.$inferSelect; +// --------------------------------------------- +// Revalidation helpers +// --------------------------------------------- +async function revalidateApprovalTemplatesPaths() { + await revalidateI18nPaths('/evcp/approval/template'); +} + export interface ApprovalTemplateWithVariables extends ApprovalTemplate { variables: ApprovalTemplateVariable[]; @@ -209,6 +217,7 @@ export async function createApprovalTemplate(data: CreateInput): Promise<Approva const result = await getApprovalTemplate(newTemplate.id); if (!result) throw new Error('생성된 템플릿을 조회할 수 없습니다.'); + await revalidateApprovalTemplatesPaths(); return result; } @@ -262,6 +271,7 @@ export async function updateApprovalTemplate(id: string, data: UpdateInput): Pro const result = await getApprovalTemplate(id); if (!result) throw new Error('업데이트된 템플릿을 조회할 수 없습니다.'); + await revalidateApprovalTemplatesPaths(); return result; } @@ -320,6 +330,7 @@ export async function duplicateApprovalTemplate( export async function deleteApprovalTemplate(id: string): Promise<{ success: boolean; error?: string }> { try { await db.delete(approvalTemplates).where(eq(approvalTemplates.id, id)); + await revalidateApprovalTemplatesPaths(); return { success: true }; } catch (error) { return { diff --git a/lib/revalidate.ts b/lib/revalidate.ts new file mode 100644 index 00000000..08c572ee --- /dev/null +++ b/lib/revalidate.ts @@ -0,0 +1,32 @@ +"use server" + +import { revalidatePath } from "next/cache" +import { languages } from "@/i18n/settings" + +/** + * 지정된 base 경로에 대해 지원 언어별로 revalidatePath를 호출합니다. + * 예: basePath가 "/evcp/approval/line" 이면 + * - /ko/evcp/approval/line + * - /en/evcp/approval/line + * 등의 경로를 무효화합니다. + */ +export async function revalidateI18nPaths(basePath: string): Promise<void> { + for (const lng of languages) { + try { + revalidatePath(`/${lng}${basePath}`) + } catch { + // ignore + } + } +} + +/** + * 여러 base 경로를 한 번에 무효화합니다. + */ +export async function revalidateI18nPathsMany(basePaths: string[]): Promise<void> { + for (const basePath of basePaths) { + await revalidateI18nPaths(basePath) + } +} + + |
