File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
'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<string[]> {
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<AdminMenuFormState> {
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<AdminMenuFormState> {
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<AdminMenuFormState> {
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' };
}