File name
Commit message
Commit date
File name
Commit message
Commit date
09-14
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 };
}