ERP-node/frontend/lib/utils/toastUtils.ts

83 lines
2.2 KiB
TypeScript

import { toast } from "sonner";
/**
* 서버/catch 에러에서 사용자에게 보여줄 메시지를 추출
*/
function extractErrorMessage(error: unknown): string | null {
if (!error) return null;
if (error instanceof Error) {
return error.message;
}
if (typeof error === "string") {
return error;
}
if (typeof error === "object" && error !== null) {
const obj = error as Record<string, any>;
return (
obj.response?.data?.message ||
obj.response?.data?.error ||
obj.message ||
obj.error ||
null
);
}
return null;
}
/**
* 친절한 에러 토스트를 표시합니다.
*
* @param title - 어떤 작업에서 문제가 발생했는지 (예: "메뉴 저장에 실패했습니다")
* @param error - catch 블록의 error 객체 또는 에러 메시지 문자열
* @param options - 추가 옵션
* @param options.guidance - 사용자에게 안내할 해결 방법 (예: "네트워크 연결을 확인해 주세요")
* @param options.duration - 토스트 표시 시간 (ms)
*/
export function showErrorToast(
title: string,
error?: unknown,
options?: {
guidance?: string;
duration?: number;
}
) {
const errorMessage = extractErrorMessage(error);
const guidance = options?.guidance;
const descriptionParts: string[] = [];
if (errorMessage) descriptionParts.push(errorMessage);
if (guidance) descriptionParts.push(guidance);
const description =
descriptionParts.length > 0 ? descriptionParts.join("\n") : undefined;
toast.error(title, {
description,
duration: options?.duration || 5000,
});
}
/**
* API 응답 기반 에러 토스트
* API 호출 실패 시 응답 메시지를 포함하여 친절하게 표시합니다.
*/
export function showApiErrorToast(
action: string,
response?: { message?: string; error?: string } | null,
fallbackError?: unknown
) {
const apiMessage = response?.message || response?.error;
const errorMessage = apiMessage || extractErrorMessage(fallbackError);
const description = errorMessage || "잠시 후 다시 시도해 주세요.";
toast.error(`${action}에 실패했습니다`, {
description,
duration: 5000,
});
}