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 { redirect, unstable_rethrow } from 'next/navigation';
import { verifySession } from '@/lib/auth/dal';
import { BackendRequestError } from '@/lib/http/backend-fetch';
import {
createBannedWord,
deleteBannedWord,
uploadBannedWordExcel,
} from '@/lib/data/repositories/banned-word-repository';
import {
DUPLICATE_WORD_MESSAGE,
validateBannedWord,
type BannedWordFormState,
type ExcelUploadResult,
} from '@/lib/domain/banned-word-form';
import { BANNED_WORDS_PATH } from '@/lib/domain/banned-word-query';
const SAVE_FAILED_MESSAGE = '등록하지 못했습니다. 잠시 후 다시 시도해 주세요.';
const DELETE_FAILED_MESSAGE = '삭제하지 못했습니다. 잠시 후 다시 시도해 주세요.';
const UPLOAD_FAILED_MESSAGE =
'엑셀 파일을 등록하지 못했습니다. 잠시 후 다시 시도해 주세요.';
function failureMessage(error: unknown, fallback: string): string {
return error instanceof BackendRequestError ? error.message : fallback;
}
function readString(formData: FormData, key: string): string {
const value = formData.get(key);
return typeof value === 'string' ? value : '';
}
/** 기획 SYS_WRD_002 ② — 등록이 끝나면 목록으로 돌아간다. */
export async function createBannedWordAction(
_prevState: BannedWordFormState,
formData: FormData
): Promise<BannedWordFormState> {
await verifySession();
const validation = validateBannedWord(readString(formData, 'word'));
if (!validation.ok) {
return { status: 'error', errors: validation.errors };
}
let result;
try {
result = await createBannedWord(validation.value);
} catch (error) {
// 이슈: 세션이 밀렸을 때 backendFetch가 던지는 redirect를 이 catch가 삼키면 안 된다.
unstable_rethrow(error);
return { status: 'error', message: failureMessage(error, SAVE_FAILED_MESSAGE) };
}
if (result.status === 'duplicate') {
return { status: 'error', errors: { word: DUPLICATE_WORD_MESSAGE } };
}
revalidatePath(BANNED_WORDS_PATH);
redirect(BANNED_WORDS_PATH);
}
export async function deleteBannedWordAction(
id: number
): Promise<{ status: 'success' } | { status: 'error'; message: string }> {
await verifySession();
try {
await deleteBannedWord(id);
} catch (error) {
unstable_rethrow(error);
return { status: 'error', message: failureMessage(error, DELETE_FAILED_MESSAGE) };
}
revalidatePath(BANNED_WORDS_PATH);
return { status: 'success' };
}
export async function uploadBannedWordExcelAction(
formData: FormData
): Promise<
| { status: 'success'; result: ExcelUploadResult }
| { status: 'error'; message: string }
> {
await verifySession();
const file = formData.get('file');
if (!(file instanceof File) || file.size === 0) {
return { status: 'error', message: '엑셀 파일을 첨부해 주세요.' };
}
let result: ExcelUploadResult;
try {
result = await uploadBannedWordExcel(file);
} catch (error) {
unstable_rethrow(error);
return { status: 'error', message: failureMessage(error, UPLOAD_FAILED_MESSAGE) };
}
revalidatePath(BANNED_WORDS_PATH);
return { status: 'success', result };
}