|
|
@@ -0,0 +1,151 @@
|
|
|
+import React, { createContext, useState, useContext } from 'react';
|
|
|
+
|
|
|
+type ModalContextType = {
|
|
|
+ showConfirm: (message: string) => Promise<boolean>;
|
|
|
+ showPrompt: (
|
|
|
+ message: string,
|
|
|
+ defaultValue?: string
|
|
|
+ ) => Promise<string | undefined>;
|
|
|
+ showAlert: (message: string) => Promise<void>;
|
|
|
+};
|
|
|
+const ModalContext = createContext<ModalContextType>(null!);
|
|
|
+
|
|
|
+interface ModalState<T> {
|
|
|
+ isOpen: boolean;
|
|
|
+ message: string;
|
|
|
+ defaultValue?: string;
|
|
|
+ resolve: ((value: T) => void) | null;
|
|
|
+}
|
|
|
+
|
|
|
+export function ModalProvider({ children }: { children: React.ReactNode }) {
|
|
|
+ const [confirmState, setConfirmState] = useState<ModalState<boolean>>({
|
|
|
+ isOpen: false,
|
|
|
+ message: '',
|
|
|
+ resolve: null,
|
|
|
+ });
|
|
|
+ const [promptState, setPromptState] = useState<
|
|
|
+ ModalState<string | undefined>
|
|
|
+ >({ isOpen: false, message: '', resolve: null });
|
|
|
+ const [alertState, setAlertState] = useState<ModalState<void>>({
|
|
|
+ isOpen: false,
|
|
|
+ message: '',
|
|
|
+ resolve: null,
|
|
|
+ });
|
|
|
+ const inputRef = React.useRef<HTMLInputElement>(null);
|
|
|
+
|
|
|
+ const showConfirm = (message: string): Promise<boolean> => {
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ setConfirmState({ isOpen: true, message, resolve });
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ const showPrompt = (
|
|
|
+ message: string,
|
|
|
+ defaultValue?: string
|
|
|
+ ): Promise<string | undefined> => {
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ setPromptState({ isOpen: true, message, defaultValue, resolve });
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ const showAlert = (message: string): Promise<void> => {
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ setAlertState({ isOpen: true, message, resolve });
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleConfirm = (result: boolean) => {
|
|
|
+ confirmState.resolve?.(result);
|
|
|
+ setConfirmState({ isOpen: false, message: '', resolve: null });
|
|
|
+ };
|
|
|
+
|
|
|
+ const handlePrompt = (result?: string) => {
|
|
|
+ promptState.resolve?.(result);
|
|
|
+ setPromptState({ isOpen: false, message: '', resolve: null });
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleAlertClose = () => {
|
|
|
+ alertState.resolve?.();
|
|
|
+ setAlertState({ isOpen: false, message: '', resolve: null });
|
|
|
+ };
|
|
|
+
|
|
|
+ return (
|
|
|
+ <ModalContext.Provider value={{ showConfirm, showPrompt, showAlert }}>
|
|
|
+ {children}
|
|
|
+
|
|
|
+ {/* Confirm Modal */}
|
|
|
+ {confirmState.isOpen && (
|
|
|
+ <dialog className="modal modal-open z-[1100]">
|
|
|
+ <div className="modal-box">
|
|
|
+ <h3 className="font-bold text-lg">{confirmState.message}</h3>
|
|
|
+ <div className="modal-action">
|
|
|
+ <button
|
|
|
+ className="btn btn-ghost"
|
|
|
+ onClick={() => handleConfirm(false)}
|
|
|
+ >
|
|
|
+ Cancel
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ className="btn btn-error"
|
|
|
+ onClick={() => handleConfirm(true)}
|
|
|
+ >
|
|
|
+ Confirm
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </dialog>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {/* Prompt Modal */}
|
|
|
+ {promptState.isOpen && (
|
|
|
+ <dialog className="modal modal-open z-[1100]">
|
|
|
+ <div className="modal-box">
|
|
|
+ <h3 className="font-bold text-lg">{promptState.message}</h3>
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ className="input input-bordered w-full mt-2"
|
|
|
+ defaultValue={promptState.defaultValue}
|
|
|
+ ref={inputRef}
|
|
|
+ onKeyDown={(e) => {
|
|
|
+ if (e.key === 'Enter') {
|
|
|
+ handlePrompt((e.target as HTMLInputElement).value);
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <div className="modal-action">
|
|
|
+ <button className="btn btn-ghost" onClick={() => handlePrompt()}>
|
|
|
+ Cancel
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ className="btn btn-primary"
|
|
|
+ onClick={() => handlePrompt(inputRef.current?.value)}
|
|
|
+ >
|
|
|
+ Submit
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </dialog>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {/* Alert Modal */}
|
|
|
+ {alertState.isOpen && (
|
|
|
+ <dialog className="modal modal-open z-[1100]">
|
|
|
+ <div className="modal-box">
|
|
|
+ <h3 className="font-bold text-lg">{alertState.message}</h3>
|
|
|
+ <div className="modal-action">
|
|
|
+ <button className="btn" onClick={handleAlertClose}>
|
|
|
+ OK
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </dialog>
|
|
|
+ )}
|
|
|
+ </ModalContext.Provider>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+export function useModals() {
|
|
|
+ const context = useContext(ModalContext);
|
|
|
+ if (!context) throw new Error('useModals must be used within ModalProvider');
|
|
|
+ return context;
|
|
|
+}
|