import { BackendError } from '@/services/backend'; const NETWORK_PATTERN = /failed to fetch|networkerror|network request failed|load failed|fetch failed/i; export function isBackendNetworkError(error: unknown): boolean { if (error instanceof BackendError) { return error.status === 0 || error.code === 'NETWORK_ERROR'; } if (error instanceof Error) { return NETWORK_PATTERN.test(error.message); } return false; } const CONFLICT_ALREADY_EXISTS = /already exists|account with this email|ایمیل.*وجود|قبلاً ثبت/i; const INVALID_CREDENTIALS_MESSAGE = 'ایمیل یا رمز عبور اشتباه است. اگر حساب ندارید، ابتدا ثبت‌نام کنید.'; export function getBackendErrorMessage( error: unknown, fallback = 'خطا در ارتباط با سرور. لطفاً دوباره تلاش کنید.' ): string { if (error instanceof BackendError) { if (error.status === 0 || error.code === 'NETWORK_ERROR') { return 'سرور در دسترس نیست. لطفاً چند لحظه بعد دوباره تلاش کنید.'; } // Must run before generic 401 — login failures also return status 401. if (error.code === 'INVALID_CREDENTIALS') { return INVALID_CREDENTIALS_MESSAGE; } if (error.status === 401 || error.code === 'UNAUTHORIZED') { return 'نشست شما منقضی شده است. لطفاً دوباره وارد شوید.'; } if (error.status === 503 || error.code === 'SERVICE_UNAVAILABLE') { if (error.message && /هوش مصنوعی|OPENAI/.test(error.message)) { return error.message; } return 'سرویس هوش مصنوعی موقتاً در دسترس نیست. لطفاً چند لحظه بعد دوباره تلاش کنید.'; } if (error.code === 'RATE_LIMIT_EXCEEDED') { return 'تعداد تلاش‌ها بیش از حد مجاز است. لطفاً کمی صبر کنید و دوباره تلاش کنید.'; } if (error.code === 'CONFLICT' || error.status === 409) { if (CONFLICT_ALREADY_EXISTS.test(error.message)) { return 'حسابی با این ایمیل از قبل وجود دارد. لطفاً وارد شوید.'; } return error.message || 'این عملیات قبلاً انجام شده است.'; } if (error.code === 'VALIDATION_ERROR' || error.status === 422) { return localizeValidationMessage(error.message) || 'اطلاعات واردشده نامعتبر است.'; } return localizeKnownEnglishMessage(error.message) || fallback; } if (error instanceof Error && NETWORK_PATTERN.test(error.message)) { return 'سرور در دسترس نیست. لطفاً چند لحظه بعد دوباره تلاش کنید.'; } if (error instanceof Error && error.message) { return localizeKnownEnglishMessage(error.message) || error.message; } return fallback; } /** Login-specific copy; keeps credential failures distinct from session expiry. */ export function getLoginErrorMessage(error: unknown): string { if (error instanceof BackendError) { if (error.code === 'INVALID_CREDENTIALS') { return INVALID_CREDENTIALS_MESSAGE; } if (error.status === 401 && /invalid email or password/i.test(error.message)) { return INVALID_CREDENTIALS_MESSAGE; } if (error.code === 'RATE_LIMIT_EXCEEDED') { return 'تعداد تلاش‌های ورود زیاد بوده است. لطفاً چند دقیقه صبر کنید و دوباره تلاش کنید.'; } if (error.status === 0 || error.code === 'NETWORK_ERROR') { return 'سرور در دسترس نیست. لطفاً اتصال اینترنت را بررسی کنید و دوباره تلاش کنید.'; } if (error.code === 'VALIDATION_ERROR' || error.status === 422) { return localizeValidationMessage(error.message) || 'ایمیل یا رمز عبور واردشده نامعتبر است.'; } } return getBackendErrorMessage(error, 'ورود انجام نشد. لطفاً دوباره تلاش کنید.'); } function localizeValidationMessage(message: string | undefined): string | null { if (!message) return null; const lower = message.toLowerCase(); if (lower.includes('email')) { return 'فرمت ایمیل نامعتبر است.'; } if (lower.includes('password')) { return 'رمز عبور نامعتبر است.'; } return localizeKnownEnglishMessage(message); } function localizeKnownEnglishMessage(message: string | undefined): string | null { if (!message) return null; if (/invalid email or password/i.test(message)) { return INVALID_CREDENTIALS_MESSAGE; } if (CONFLICT_ALREADY_EXISTS.test(message)) { return 'حسابی با این ایمیل از قبل وجود دارد. لطفاً وارد شوید.'; } // Prefer Persian UI copy over raw English API text. if (/^[A-Za-z0-9\s.,'"\-_:!?()]+$/.test(message.trim())) { return null; } return message; }