import { AxiosError } from 'axios'; import classNames from 'clsx'; import React from 'react'; import toast, { Toast } from 'react-hot-toast'; import { defineMessages, FormattedMessage, MessageDescriptor } from 'react-intl'; import { Link } from 'react-router-dom'; import { Icon } from './components/ui'; import { httpErrorMessages } from './utils/errors'; type ToastText = string | MessageDescriptor type ToastType = 'success' | 'error' | 'info' interface IToastOptions { action?(): void actionLink?: string actionLabel?: ToastText duration?: number } const DEFAULT_DURATION = 4000; const renderText = (text: ToastText) => { if (typeof text === 'string') { return text; } else { return ; } }; const buildToast = (t: Toast, message: ToastText, type: ToastType, opts: Omit = {}) => { const { action, actionLabel, actionLink } = opts; const dismissToast = () => toast.dismiss(t.id); const renderIcon = () => { switch (type) { case 'success': return ( ); case 'info': return ( ); case 'error': return ( ); } }; const renderAction = () => { const classNames = 'ml-3 mt-0.5 flex-shrink-0 rounded-full text-sm font-medium text-primary-600 dark:text-accent-blue hover:underline focus:outline-none'; if (action && actionLabel) { return ( ); } if (actionLink && actionLabel) { return ( {renderText(actionLabel)} ); } return null; }; return (
{renderIcon()}

{renderText(message)}

{/* Action */} {renderAction()}
{/* Dismiss Button */}
); }; const createToast = (type: ToastType, message: ToastText, opts?: IToastOptions) => { const duration = opts?.duration || DEFAULT_DURATION; toast.custom((t) => buildToast(t, message, type, opts), { duration, }); }; function info(message: ToastText, opts?: IToastOptions) { createToast('info', message, opts); } function success(message: ToastText, opts?: IToastOptions) { createToast('success', message, opts); } function error(message: ToastText, opts?: IToastOptions) { createToast('error', message, opts); } const messages = defineMessages({ unexpectedMessage: { id: 'alert.unexpected.message', defaultMessage: 'An unexpected error occurred.' }, }); function showAlertForError(networkError: AxiosError) { if (networkError?.response) { const { data, status, statusText } = networkError.response; if (status === 502) { return error('The server is down'); } if (status === 404 || status === 410) { // Skip these errors as they are reflected in the UI return null; } let message: string | undefined = statusText; if (data?.error) { message = data.error; } if (!message) { message = httpErrorMessages.find((httpError) => httpError.code === status)?.description; } if (message) { return error(message); } } else { console.error(networkError); return error(messages.unexpectedMessage); } } export default { info, success, error, showAlertForError, };