mirror of https://github.com/buster-so/buster.git
180 lines
5.0 KiB
TypeScript
180 lines
5.0 KiB
TypeScript
'use client';
|
|
|
|
import React, { PropsWithChildren } from 'react';
|
|
import { toast, type ExternalToast } from 'sonner';
|
|
import { useMemoizedFn } from 'ahooks';
|
|
import {
|
|
useContextSelector,
|
|
createContext,
|
|
ContextSelector
|
|
} from '@fluentui/react-context-selector';
|
|
|
|
export type NotificationType = 'success' | 'info' | 'warning' | 'error';
|
|
|
|
export interface NotificationProps {
|
|
type?: NotificationType;
|
|
title?: string;
|
|
message?: string;
|
|
duration?: number;
|
|
action?: {
|
|
label: string;
|
|
onClick: () => void | (() => Promise<void>);
|
|
};
|
|
}
|
|
|
|
export const useBusterNotificationsInternal = () => {
|
|
const openNotification = useMemoizedFn((props: NotificationProps) => {
|
|
const { title, message, type } = props;
|
|
|
|
const hasTitle = !!title;
|
|
|
|
const toastOptions: ExternalToast = {
|
|
...props,
|
|
description: !hasTitle && message ? message : message,
|
|
position: 'top-center'
|
|
};
|
|
|
|
switch (type) {
|
|
case 'success':
|
|
return toast.success(title, toastOptions);
|
|
case 'info':
|
|
return toast.info(title, toastOptions);
|
|
case 'warning':
|
|
return toast.warning(title, toastOptions);
|
|
case 'error':
|
|
return toast.error(title, toastOptions);
|
|
default:
|
|
return toast(title, toastOptions);
|
|
}
|
|
});
|
|
|
|
const openErrorNotification = useMemoizedFn((data: NotificationProps | unknown) => {
|
|
const values = data || ({} as any);
|
|
const type = values.type || 'error';
|
|
const title = values.title || 'Error';
|
|
const message = values.message || 'Something went wrong. Please try again.';
|
|
return openNotification({ ...values, message, title, type });
|
|
});
|
|
|
|
const openInfoNotification = useMemoizedFn(
|
|
({ type = 'info', message = 'Info', title = 'Info', ...props }: NotificationProps) => {
|
|
return openNotification({ ...props, title, message, type });
|
|
}
|
|
);
|
|
|
|
const openSuccessNotification = useMemoizedFn(
|
|
({ type = 'success', title = 'Success', message = 'success', ...props }: NotificationProps) => {
|
|
return openNotification({ ...props, message, title, type });
|
|
}
|
|
);
|
|
|
|
const openWarningNotification = useMemoizedFn(
|
|
({ type = 'warning', title = 'Warning', message = 'Warning', ...props }: NotificationProps) => {
|
|
return openNotification({ ...props, message, title, type });
|
|
}
|
|
);
|
|
|
|
//MESSAGES
|
|
|
|
const openMessage = useMemoizedFn(
|
|
(props: {
|
|
type: NotificationType;
|
|
message: string;
|
|
onClose?: () => void;
|
|
duration?: number;
|
|
}) => {
|
|
return openNotification({
|
|
...props,
|
|
title: props.message,
|
|
message: ''
|
|
});
|
|
}
|
|
);
|
|
|
|
const openErrorMessage = useMemoizedFn((message: string) => {
|
|
return openMessage({ type: 'error', message });
|
|
});
|
|
|
|
const openInfoMessage = useMemoizedFn((message: string, duration?: number) => {
|
|
return openMessage({ type: 'info', message, duration });
|
|
});
|
|
|
|
const openSuccessMessage = useMemoizedFn((message: string) => {
|
|
return openMessage({ type: 'success', message });
|
|
});
|
|
|
|
const openConfirmModal = useMemoizedFn(
|
|
(props: {
|
|
title: string | React.ReactNode;
|
|
content: string | React.ReactNode;
|
|
onOk: () => void;
|
|
onCancel?: () => void;
|
|
icon?: React.ReactNode;
|
|
width?: string | number;
|
|
useReject?: boolean;
|
|
cancelButtonProps?: {
|
|
className?: string;
|
|
};
|
|
}): Promise<void> => {
|
|
const useReject = props.useReject ?? true;
|
|
|
|
return new Promise((resolve, reject) => {
|
|
// modal.confirm({
|
|
// icon: props.icon || <></>,
|
|
// ...props,
|
|
// className: cx(styles.modal, ''),
|
|
// cancelButtonProps: {
|
|
// ...props.cancelButtonProps,
|
|
// type: 'text'
|
|
// },
|
|
// okButtonProps: {
|
|
// ...props.okButtonProps,
|
|
// type: 'default'
|
|
// },
|
|
// onOk: async () => {
|
|
// await props.onOk();
|
|
// resolve();
|
|
// },
|
|
// onCancel: async () => {
|
|
// await props.onCancel?.();
|
|
// if (useReject) reject();
|
|
// else resolve();
|
|
// }
|
|
// });
|
|
});
|
|
}
|
|
);
|
|
|
|
return {
|
|
openErrorNotification,
|
|
openInfoNotification,
|
|
openSuccessNotification,
|
|
openWarningNotification,
|
|
openErrorMessage,
|
|
openInfoMessage,
|
|
openSuccessMessage,
|
|
openConfirmModal,
|
|
openNotification
|
|
};
|
|
};
|
|
|
|
const BusterNotifications = createContext<ReturnType<typeof useBusterNotificationsInternal>>(
|
|
{} as ReturnType<typeof useBusterNotificationsInternal>
|
|
);
|
|
|
|
export const BusterNotificationsProvider: React.FC<PropsWithChildren> = ({ children }) => {
|
|
const value = useBusterNotificationsInternal();
|
|
|
|
return <BusterNotifications.Provider value={value}>{children}</BusterNotifications.Provider>;
|
|
};
|
|
|
|
const useBusterNotificationsSelector = <T,>(
|
|
selector: ContextSelector<ReturnType<typeof useBusterNotificationsInternal>, T>
|
|
) => {
|
|
return useContextSelector(BusterNotifications, selector);
|
|
};
|
|
|
|
export const useBusterNotifications = () => {
|
|
return useBusterNotificationsSelector((state) => state);
|
|
};
|