'use server'; import { revalidatePath } from 'next/cache'; import { verifySession } from '@/lib/auth/dal'; import { createAdminMenu, deleteAdminMenu, fetchAdminMenus, updateAdminMenu, } from '@/lib/data/repositories/admin-menu-repository'; import { ADMIN_MENU_ROOT_PATH } from '@/lib/domain/admin-menu'; import { validateAdminMenu, type AdminMenuFormState, type AdminMenuValues, } from '@/lib/domain/admin-menu-form'; import { BackendRequestError } from '@/lib/http/backend-fetch'; const INVALID_REQUEST_MESSAGE = '요청이 올바르지 않습니다.'; const SAVE_FAILED_MESSAGE = '저장하지 못했습니다. 잠시 후 다시 시도해 주세요.'; const DELETE_FAILED_MESSAGE = '삭제하지 못했습니다. 잠시 후 다시 시도해 주세요.'; function readString(formData: FormData, key: string): string { const value = formData.get(key); return typeof value === 'string' ? value : ''; } function readNumber(formData: FormData, key: string): number { const trimmed = readString(formData, key).trim(); return trimmed === '' ? NaN : Number(trimmed); } function readValues(formData: FormData): AdminMenuValues { return { name: readString(formData, 'name'), sortOrder: readNumber(formData, 'sortOrder'), roleId: readString(formData, 'roleId'), isTopActive: readString(formData, 'isTopActive') === 'true', url: readString(formData, 'url'), opensNewWindow: readString(formData, 'opensNewWindow') === 'true', description: readString(formData, 'description'), isActive: readString(formData, 'isActive') === 'true', }; } async function allowedRoleIds(): Promise { const menus = await fetchAdminMenus(); return [...new Set(menus.map((menu) => menu.roleId).filter(Boolean))]; } function describeFailure(error: unknown, fallback: string): string { return error instanceof BackendRequestError ? error.message : fallback; } export async function createAdminMenuAction( _prevState: AdminMenuFormState, formData: FormData ): Promise { await verifySession(); const parentId = readString(formData, 'parentId').trim(); if (!parentId) { return { status: 'error', message: INVALID_REQUEST_MESSAGE }; } const validation = validateAdminMenu( readValues(formData), await allowedRoleIds() ); if (!validation.ok) { return { status: 'error', errors: validation.errors }; } try { await createAdminMenu(parentId, validation.values); } catch (error) { return { status: 'error', message: describeFailure(error, SAVE_FAILED_MESSAGE) }; } revalidatePath(ADMIN_MENU_ROOT_PATH); return { status: 'success' }; } export async function updateAdminMenuAction( _prevState: AdminMenuFormState, formData: FormData ): Promise { await verifySession(); const menuId = readString(formData, 'menuId').trim(); if (!menuId) { return { status: 'error', message: INVALID_REQUEST_MESSAGE }; } const validation = validateAdminMenu( readValues(formData), await allowedRoleIds() ); if (!validation.ok) { return { status: 'error', errors: validation.errors }; } try { await updateAdminMenu(menuId, validation.values); } catch (error) { return { status: 'error', message: describeFailure(error, SAVE_FAILED_MESSAGE) }; } revalidatePath(ADMIN_MENU_ROOT_PATH); return { status: 'success' }; } export async function deleteAdminMenuAction( menuId: string ): Promise { await verifySession(); if (!menuId) { return { status: 'error', message: INVALID_REQUEST_MESSAGE }; } try { await deleteAdminMenu(menuId); } catch (error) { return { status: 'error', message: describeFailure(error, DELETE_FAILED_MESSAGE) }; } revalidatePath(ADMIN_MENU_ROOT_PATH); return { status: 'success' }; }