update the confirm modal

This commit is contained in:
Nate Kelley 2025-03-13 11:25:17 -06:00
parent 71c4c16bc9
commit 9e4e8ca43c
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
7 changed files with 133 additions and 57 deletions

View File

@ -86,8 +86,7 @@ export const useDeleteCollection = () => {
return await openConfirmModal({
title: 'Delete Collection',
content: 'Are you sure you want to delete this collection?',
onOk: deleteMethod,
useReject: true
onOk: deleteMethod
});
}

View File

@ -149,10 +149,7 @@ export const useDeleteDashboards = () => {
return await openConfirmModal({
title: 'Delete Dashboard',
content: 'Are you sure you want to delete this dashboard?',
onOk: () => {
method();
},
useReject: true
onOk: method
});
}
);

View File

@ -31,7 +31,6 @@ export const ApiKeysController: React.FC = () => {
const handleDeleteApiKey = useMemoizedFn(async (id: string) => {
openConfirmModal({
title: 'Delete API key',
useReject: false,
content: 'Are you sure you want to delete this API key? This action cannot be undone.',
onOk: async () => {
try {

View File

@ -34,8 +34,8 @@ export interface ModalProps {
};
};
header: {
title: string;
description?: string;
title: React.ReactNode;
description?: React.ReactNode;
};
width?: number;
children?: React.ReactNode;

View File

@ -0,0 +1,55 @@
import React from 'react';
import { AppModal } from './AppModal';
export interface ConfirmProps {
title: string | React.ReactNode;
description?: string | React.ReactNode;
content: string | React.ReactNode;
onOk: () => Promise<void> | void;
onCancel?: () => Promise<void> | void;
width?: number;
cancelButtonProps?: {
className?: string;
text?: string;
};
primaryButtonProps?: {
className?: string;
text?: string;
};
}
export interface ConfirmModalProps extends ConfirmProps {
open: boolean;
onClose: () => void;
}
export const ConfirmModal: React.FC<ConfirmModalProps> = React.memo(
({ title, content, onOk, onCancel, width, cancelButtonProps, description, open, onClose }) => {
return (
<AppModal
open={open}
width={width}
onClose={onClose}
header={{
title,
description
}}
footer={{
secondaryButton: onCancel
? {
text: cancelButtonProps?.text ?? 'Cancel',
onClick: onCancel
}
: undefined,
primaryButton: {
text: 'OK',
onClick: onOk
}
}}>
{content}
</AppModal>
);
}
);
ConfirmModal.displayName = 'ConfirmModal';

View File

@ -1,9 +1,11 @@
'use client';
import { ConfirmModal, ConfirmProps } from '@/components/ui/modal/ConfirmModal';
import { Toaster } from '@/components/ui/toaster/Toaster';
import React, { PropsWithChildren } from 'react';
import { toast, type ExternalToast } from 'sonner';
import { useContextSelector, createContext } from 'use-context-selector';
import { useOpenConfirmModal } from './useConfirmModal';
export type NotificationType = 'success' | 'info' | 'warning' | 'error';
@ -103,47 +105,7 @@ const openSuccessMessage = (message: string) => {
return openMessage({ type: 'success', message });
};
const openConfirmModal = (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();
// }
// });
});
};
export const useBusterNotificationsInternal = () => {
const useBusterNotificationsInternal = () => {
return {
openErrorNotification,
openInfoNotification,
@ -152,29 +114,32 @@ export const useBusterNotificationsInternal = () => {
openErrorMessage,
openInfoMessage,
openSuccessMessage,
openConfirmModal,
openNotification
};
};
const BusterNotifications = createContext<ReturnType<typeof useBusterNotificationsInternal>>(
{} as ReturnType<typeof useBusterNotificationsInternal>
type BusterNotificationsContext = ReturnType<typeof useBusterNotificationsInternal> & {
openConfirmModal: ReturnType<typeof useOpenConfirmModal>['openConfirmModal'];
};
const BusterNotifications = createContext<BusterNotificationsContext>(
{} as BusterNotificationsContext
);
export const BusterNotificationsProvider: React.FC<PropsWithChildren> = ({ children }) => {
const { openConfirmModal, confirmModalProps } = useOpenConfirmModal();
const value = useBusterNotificationsInternal();
return (
<BusterNotifications.Provider value={value}>
<BusterNotifications.Provider value={{ ...value, openConfirmModal }}>
{children}
<Toaster />
<ConfirmModal {...confirmModalProps} />
</BusterNotifications.Provider>
);
};
const useBusterNotificationsSelector = <T,>(
selector: (state: ReturnType<typeof useBusterNotificationsInternal>) => T
) => {
const useBusterNotificationsSelector = <T,>(selector: (state: BusterNotificationsContext) => T) => {
return useContextSelector(BusterNotifications, selector);
};

View File

@ -0,0 +1,61 @@
import { ConfirmModalProps, ConfirmProps } from '@/components/ui/modal/ConfirmModal';
import { useState, useRef } from 'react';
const defaultConfirmModalProps: ConfirmProps = {
title: '',
content: '',
onOk: async () => {},
onCancel: async () => {}
};
export const useOpenConfirmModal = () => {
const [open, setOpen] = useState(false);
const confirmModalPropsRef = useRef<ConfirmProps>(defaultConfirmModalProps);
const resolveRef = useRef<((value: void) => void) | null>(null);
const rejectRef = useRef<((reason?: any) => void) | null>(null);
const openConfirmModal = (props: ConfirmProps): Promise<void> => {
return new Promise((resolve, reject) => {
resolveRef.current = resolve;
rejectRef.current = reject;
confirmModalPropsRef.current = {
...props,
onOk: async () => {
try {
await props.onOk();
resolve();
} catch (error) {
reject(error);
} finally {
setOpen(false);
}
},
onCancel: async () => {
try {
await props.onCancel?.();
resolve();
} catch (error) {
reject(error);
} finally {
setOpen(false);
}
}
};
setOpen(true);
});
};
const onCloseConfirmModal = () => {
setOpen(false);
};
const confirmModalProps: ConfirmModalProps = {
...confirmModalPropsRef.current,
open,
onClose: onCloseConfirmModal
};
return { openConfirmModal, confirmModalProps };
};