2026-05-27 21:34:12 +03:30
|
|
|
import { toast } from "sonner";
|
|
|
|
|
import { ApiClientError } from "@/lib/api/client";
|
|
|
|
|
|
|
|
|
|
export type NotifyOptions = {
|
|
|
|
|
description?: string;
|
|
|
|
|
duration?: number;
|
2026-06-21 06:08:18 +03:30
|
|
|
/** Optional click-through button (e.g. "View" → navigate to the related page). */
|
|
|
|
|
action?: { label: string; onClick: () => void };
|
2026-05-27 21:34:12 +03:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function baseOptions(opts?: NotifyOptions) {
|
|
|
|
|
return {
|
|
|
|
|
description: opts?.description,
|
|
|
|
|
duration: opts?.duration ?? 4000,
|
2026-06-21 06:08:18 +03:30
|
|
|
action: opts?.action
|
|
|
|
|
? { label: opts.action.label, onClick: opts.action.onClick }
|
|
|
|
|
: undefined,
|
2026-05-27 21:34:12 +03:30
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 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<T>(
|
|
|
|
|
promise: Promise<T>,
|
|
|
|
|
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 {
|
2026-06-02 00:04:48 +03:30
|
|
|
// 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;
|
2026-05-27 21:34:12 +03:30
|
|
|
if (err instanceof Error && err.message) return err.message;
|
|
|
|
|
return fallback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function notifyError(err: unknown, fallback: string) {
|
|
|
|
|
notify.error(getErrorMessage(err, fallback));
|
|
|
|
|
}
|