feat: add toast notifications for error handling and success messages across various components

This commit is contained in:
Your Name
2026-03-22 16:48:07 +02:00
parent 70d7f09110
commit ce610f5c6e
11 changed files with 80 additions and 19 deletions

View File

@@ -1,6 +1,7 @@
import { useEffect, useMemo, useState, type FormEvent } from 'react';
import { Helmet } from 'react-helmet-async';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import {
AlertTriangle,
BarChart3,
@@ -222,7 +223,9 @@ export default function AccountPage() {
setSubmitError(null);
if (mode === 'register' && password !== confirmPassword) {
setSubmitError(t('account.passwordMismatch'));
const msg = t('account.passwordMismatch');
setSubmitError(msg);
toast.error(msg);
return;
}
@@ -236,7 +239,9 @@ export default function AccountPage() {
setPassword('');
setConfirmPassword('');
} catch (error) {
setSubmitError(error instanceof Error ? error.message : t('account.loadFailed'));
const msg = error instanceof Error ? error.message : t('account.loadFailed');
setSubmitError(msg);
toast.error(msg);
}
};
@@ -248,7 +253,9 @@ export default function AccountPage() {
setUsage(null);
setApiKeys([]);
} catch (error) {
setSubmitError(error instanceof Error ? error.message : t('account.loadFailed'));
const msg = error instanceof Error ? error.message : t('account.loadFailed');
setSubmitError(msg);
toast.error(msg);
}
};
@@ -264,7 +271,9 @@ export default function AccountPage() {
setRevealedKey(key.raw_key ?? null);
setNewKeyName('');
} catch (error) {
setNewKeyError(error instanceof Error ? error.message : t('account.loadFailed'));
const msg = error instanceof Error ? error.message : t('account.loadFailed');
setNewKeyError(msg);
toast.error(msg);
} finally {
setNewKeyCreating(false);
}

View File

@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
import { Helmet } from 'react-helmet-async';
import { Mail, Send, CheckCircle, AlertCircle, Loader2 } from 'lucide-react';
import { isAxiosError } from 'axios';
import { toast } from 'sonner';
import SEOHead from '@/components/seo/SEOHead';
import { generateWebPage, getSiteOrigin } from '@/utils/seo';
import { getApiClient } from '@/services/api';
@@ -40,14 +41,18 @@ export default function ContactPage() {
message: data.get('message'),
});
setSubmitted(true);
toast.success(t('pages.contact.successMessage'));
} catch (err: unknown) {
let errMsg = '';
if (isAxiosError(err) && err.response?.data?.error) {
setError(err.response.data.error);
errMsg = err.response.data.error;
} else if (err instanceof Error) {
setError(err.message);
errMsg = err.message;
} else {
setError(String(err));
errMsg = String(err);
}
setError(errMsg);
toast.error(errMsg);
} finally {
setLoading(false);
}

View File

@@ -2,6 +2,7 @@ import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Helmet } from 'react-helmet-async';
import { Mail } from 'lucide-react';
import { toast } from 'sonner';
import { getApiClient } from '../services/api';
const api = getApiClient();
@@ -21,8 +22,11 @@ export default function ForgotPasswordPage() {
try {
await api.post('/auth/forgot-password', { email });
setSubmitted(true);
toast.success(t('auth.forgotPassword.sent'));
} catch {
setError(t('auth.forgotPassword.error'));
const errMsg = t('auth.forgotPassword.error');
setError(errMsg);
toast.error(errMsg);
} finally {
setLoading(false);
}

View File

@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
import { useSearchParams, useNavigate } from 'react-router-dom';
import { Helmet } from 'react-helmet-async';
import { KeyRound } from 'lucide-react';
import { toast } from 'sonner';
import { getApiClient } from '../services/api';
const api = getApiClient();
@@ -24,11 +25,15 @@ export default function ResetPasswordPage() {
setError(null);
if (password.length < 8) {
setError(t('auth.resetPassword.tooShort'));
const msg = t('auth.resetPassword.tooShort');
setError(msg);
toast.error(msg);
return;
}
if (password !== confirm) {
setError(t('account.passwordMismatch'));
const msg = t('account.passwordMismatch');
setError(msg);
toast.error(msg);
return;
}
@@ -36,9 +41,12 @@ export default function ResetPasswordPage() {
try {
await api.post('/auth/reset-password', { token, password });
setSuccess(true);
toast.success(t('auth.resetPassword.success'));
setTimeout(() => navigate('/account'), 3000);
} catch (err) {
setError(err instanceof Error ? err.message : t('auth.resetPassword.error'));
const errMsg = err instanceof Error ? err.message : t('auth.resetPassword.error');
setError(errMsg);
toast.error(errMsg);
} finally {
setLoading(false);
}