import { toast } from "sonner"; import { ApiClientError } from "@/lib/api/client"; export type NotifyOptions = { description?: string; duration?: number; /** Optional click-through button (e.g. "View" → navigate to the related page). */ action?: { label: string; onClick: () => void }; }; function baseOptions(opts?: NotifyOptions) { return { description: opts?.description, duration: opts?.duration ?? 4000, action: opts?.action ? { label: opts.action.label, onClick: opts.action.onClick } : undefined, }; } /** Toast notifications — use for transient success/error/info across the app */ export const notify = { success(message: string, opts?: NotifyOptions) { toast.success(message, baseOptions(opts)); }, error(message: string, opts?: NotifyOptions) { toast.error(message, { ...baseOptions(opts), duration: opts?.duration ?? 5500 }); }, warning(message: string, opts?: NotifyOptions) { toast.warning(message, baseOptions(opts)); }, info(message: string, opts?: NotifyOptions) { toast.info(message, baseOptions(opts)); }, loading(message: string) { return toast.loading(message); }, dismiss(id?: string | number) { toast.dismiss(id); }, promise( promise: Promise, messages: { loading: string; success: string; error?: string } ) { return toast.promise(promise, { loading: messages.loading, success: messages.success, error: messages.error ?? messages.loading, }); }, }; export function getErrorMessage(err: unknown, fallback: string): string { // ApiClientError.message is the raw (usually English) backend message; prefer // the caller's localized fallback. For code-specific localized text, use the // useApiError() hook instead of this helper. if (err instanceof ApiClientError) return fallback; if (err instanceof Error && err.message) return err.message; return fallback; } export function notifyError(err: unknown, fallback: string) { notify.error(getErrorMessage(err, fallback)); }