Restyle toasts and centralize friendly error handling.
Replace the default react-toastify look with project-styled toast cards (icon chip, rounded shell, RTL-aware container, type-colored progress bar) via a new notify helper and globals.css overrides. Add a central error layer (src/lib/errors.ts): classify any caught error by HTTP status / network condition, log the full technical detail (including the raw backend message) to the console only, and surface a friendly, localized message to the user. Raw backend messages are no longer shown. All ~190 toast call sites across 22 files move to notify, routing backend errors through notify.error(err, fallback); dead apiErrorMessage/formatApiError helpers removed. Adds an `errors` section to the fa/en dictionaries. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import { useState } from 'react';
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { FileText, Search, User, Wallet, CreditCard, XCircle, Download } from 'lucide-react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { notify } from '@/lib/notify';
|
||||
import api from '@/lib/api';
|
||||
import { useT, useLocale } from '@/i18n/I18nProvider';
|
||||
import type { Invoice, InvoiceStatus, PaymentMethod } from '@/types';
|
||||
@@ -51,12 +51,12 @@ export default function AdminInvoicesPage() {
|
||||
mutationFn: ({ invoiceId, nextStatus, reason }: { invoiceId: string; nextStatus: InvoiceStatus; reason: string }) =>
|
||||
api.patch(`/billing/admin/invoices/${invoiceId}/status`, { status: nextStatus, reason }).then((r) => r.data),
|
||||
onSuccess: () => {
|
||||
toast.success(inv.statusUpdated);
|
||||
notify.success(inv.statusUpdated);
|
||||
setStatusReason('');
|
||||
queryClient.invalidateQueries({ queryKey: ['admin-invoices'] });
|
||||
queryClient.invalidateQueries({ queryKey: ['admin-invoice', selectedId] });
|
||||
},
|
||||
onError: (err: any) => toast.error(err.response?.data?.message || inv.statusUpdateFailed),
|
||||
onError: (err: any) => notify.error(err, inv.statusUpdateFailed),
|
||||
});
|
||||
|
||||
const downloadPdfMutation = useMutation({
|
||||
@@ -71,7 +71,7 @@ export default function AdminInvoicesPage() {
|
||||
link.remove();
|
||||
window.URL.revokeObjectURL(url);
|
||||
},
|
||||
onError: () => toast.error(inv.downloadFailed),
|
||||
onError: () => notify.error(inv.downloadFailed),
|
||||
});
|
||||
|
||||
const formatPrice = (amount: number) => Number(amount || 0).toLocaleString('en-US');
|
||||
@@ -80,7 +80,7 @@ export default function AdminInvoicesPage() {
|
||||
const handleStatusUpdate = (nextStatus: InvoiceStatus) => {
|
||||
if (!selectedInvoice) return;
|
||||
if (!statusReason.trim()) {
|
||||
toast.error(inv.reasonRequired);
|
||||
notify.error(inv.reasonRequired);
|
||||
return;
|
||||
}
|
||||
updateStatusMutation.mutate({
|
||||
|
||||
Reference in New Issue
Block a user