diff --git a/apps/frontend/app/(default)/tailor/page.tsx b/apps/frontend/app/(default)/tailor/page.tsx index 35ec87c3d..7c9be3260 100644 --- a/apps/frontend/app/(default)/tailor/page.tsx +++ b/apps/frontend/app/(default)/tailor/page.tsx @@ -119,6 +119,40 @@ export default function TailorPage() { if (e.key === 'Enter') e.stopPropagation(); }; + const getPreviewErrorMessage = (err: unknown) => { + const errorMessage = err instanceof Error ? err.message : String(err ?? ''); + const normalized = errorMessage.toLowerCase(); + + if ( + normalized.includes('api key') || + normalized.includes('unauthorized') || + normalized.includes('authentication') || + errorMessage.includes('401') + ) { + return t('tailor.errors.apiKeyError'); + } + + if ( + normalized.includes('rate limit') || + normalized.includes('insufficient_quota') || + errorMessage.includes('429') + ) { + return t('tailor.errors.rateLimit'); + } + + if ( + normalized.includes('timed out') || + normalized.includes('timeout') || + normalized.includes('signal is aborted') || + normalized.includes('aborterror') || + errorMessage.includes('504') + ) { + return t('tailor.errors.timeout'); + } + + return t('tailor.errors.failedToPreview'); + }; + const buildConfirmPayload = (result: ImprovedResult) => { if (!masterResumeId) { throw new Error('Master resume ID is missing.'); @@ -197,28 +231,7 @@ export default function TailorPage() { setShowDiffModal(true); } catch (err) { console.error(err); - // Check for common error patterns - const errorMessage = err instanceof Error ? err.message : ''; - if ( - errorMessage.toLowerCase().includes('api key') || - errorMessage.toLowerCase().includes('unauthorized') || - errorMessage.toLowerCase().includes('authentication') || - errorMessage.includes('401') - ) { - setError(t('tailor.errors.apiKeyError')); - } else if ( - errorMessage.toLowerCase().includes('rate limit') || - errorMessage.includes('429') - ) { - setError(t('tailor.errors.rateLimit')); - } else if ( - errorMessage.toLowerCase().includes('timed out') || - errorMessage.toLowerCase().includes('timeout') - ) { - setError(t('tailor.errors.timeout')); - } else { - setError(t('tailor.errors.failedToPreview')); - } + setError(getPreviewErrorMessage(err)); } }; diff --git a/apps/frontend/messages/en.json b/apps/frontend/messages/en.json index 52b5fab03..6976ce752 100644 --- a/apps/frontend/messages/en.json +++ b/apps/frontend/messages/en.json @@ -563,6 +563,7 @@ "jobDescriptionTooShort": "Job description is too short. Add more detail and try again.", "apiKeyError": "Your API key isn't working. Check it in Settings.", "rateLimit": "Rate limit reached. Wait about a minute and try again.", + "timeout": "Resume preview timed out after 4 minutes. Try again with a shorter job description or a simpler prompt.", "failedToGenerate": "Couldn't generate the resume. Check your API key in Settings, then try again.", "timeout": "The request timed out. Please try again with a shorter job description or check your connection.", "failedToPreview": "Couldn't preview the resume. Check your API key in Settings, then try again.", diff --git a/apps/frontend/messages/es.json b/apps/frontend/messages/es.json index 6c4dae0e4..46df67dd8 100644 --- a/apps/frontend/messages/es.json +++ b/apps/frontend/messages/es.json @@ -563,6 +563,7 @@ "jobDescriptionTooShort": "La descripción del trabajo es demasiado corta. Añade más detalles e inténtalo de nuevo.", "apiKeyError": "Tu clave API no funciona. Revísala en Configuración.", "rateLimit": "Se alcanzó el límite de tasa. Espera aproximadamente un minuto e inténtalo de nuevo.", + "timeout": "La vista previa del currículum agotó el tiempo de espera tras 4 minutos. Inténtalo de nuevo con una descripción del trabajo más corta o un prompt más simple.", "failedToGenerate": "No se pudo generar el currículum. Revisa tu clave API en Configuración e inténtalo de nuevo.", "failedToPreview": "No se pudo previsualizar el currículum. Revisa tu clave API en Configuración e inténtalo de nuevo.", "failedToConfirm": "No se pudieron aplicar los cambios. Inténtalo de nuevo." diff --git a/apps/frontend/messages/ja.json b/apps/frontend/messages/ja.json index 7ec30c4d5..a5083dfb9 100644 --- a/apps/frontend/messages/ja.json +++ b/apps/frontend/messages/ja.json @@ -563,6 +563,7 @@ "jobDescriptionTooShort": "求人内容が短すぎます。詳細を追加してから、もう一度お試しください。", "apiKeyError": "API キーが機能していません。設定で確認してください。", "rateLimit": "レート制限に達しました。約1分待ってから再試行してください。", + "timeout": "履歴書プレビューは 4 分でタイムアウトしました。求人内容を短くするか、よりシンプルなプロンプトで再試行してください。", "failedToGenerate": "履歴書を生成できませんでした。設定で API キーを確認してから、もう一度お試しください。", "failedToPreview": "履歴書をプレビューできませんでした。設定で API キーを確認してから、もう一度お試しください。", "failedToConfirm": "変更を適用できませんでした。もう一度お試しください。" diff --git a/apps/frontend/messages/pt-BR.json b/apps/frontend/messages/pt-BR.json index a9f81d457..c198b885b 100644 --- a/apps/frontend/messages/pt-BR.json +++ b/apps/frontend/messages/pt-BR.json @@ -563,6 +563,7 @@ "jobDescriptionTooShort": "Descrição da vaga muito curta. Adicione mais detalhes e tente novamente.", "apiKeyError": "Sua chave de API não está funcionando. Verifique em Configurações.", "rateLimit": "Limite de requisições atingido. Aguarde cerca de um minuto e tente novamente.", + "timeout": "A prévia do currículo expirou após 4 minutos. Tente novamente com uma descrição de vaga mais curta ou um prompt mais simples.", "failedToGenerate": "Não foi possível gerar o currículo. Verifique sua chave de API em Configurações e tente novamente.", "failedToPreview": "Não foi possível pré-visualizar o currículo. Verifique sua chave de API em Configurações e tente novamente.", "failedToConfirm": "Não foi possível aplicar as alterações. Tente novamente." diff --git a/apps/frontend/messages/zh.json b/apps/frontend/messages/zh.json index 0d12c63ee..2243e3300 100644 --- a/apps/frontend/messages/zh.json +++ b/apps/frontend/messages/zh.json @@ -563,6 +563,7 @@ "jobDescriptionTooShort": "职位描述过短。请添加更多细节后重试。", "apiKeyError": "您的 API 密钥无效。请在设置中检查。", "rateLimit": "已达到速率限制。请等待约一分钟后重试。", + "timeout": "简历预览在 4 分钟后超时。请缩短职位描述,或改用更简单的提示词后重试。", "failedToGenerate": "无法生成简历。请在设置中检查 API 密钥后重试。", "timeout": "请求超时。请尝试使用更短的职位描述或检查网络连接后重试。", "failedToPreview": "无法预览简历。请在设置中检查 API 密钥后重试。",