From cad5fa6497193e6d613808149ecebced8aea19fc Mon Sep 17 00:00:00 2001 From: Julian Roeland Date: Thu, 3 Oct 2024 13:40:04 +0200 Subject: [PATCH] :sparkles: - feat: implemented useFormDialog hook --- src/hooks/dialog/useFormDialog.tsx | 127 +++++++++++++++++++++++++++++ src/hooks/dialog/useprompt.tsx | 57 ++++++------- 2 files changed, 152 insertions(+), 32 deletions(-) create mode 100644 src/hooks/dialog/useFormDialog.tsx diff --git a/src/hooks/dialog/useFormDialog.tsx b/src/hooks/dialog/useFormDialog.tsx new file mode 100644 index 00000000..4036f4b5 --- /dev/null +++ b/src/hooks/dialog/useFormDialog.tsx @@ -0,0 +1,127 @@ +import { + AttributeData, + Form, + FormField, + FormProps, + ModalProps, + P, +} from "@maykin-ui/admin-ui"; +import React, { useContext, useEffect } from "react"; + +import { ModalServiceContext } from "../../contexts"; +import { useDialog } from "./usedialog"; + +/** + * Returns a function which, when called: shows a form dialog with a + * confirmation callback and an optional cancellation callback. + */ +export const useFormDialog = () => { + const dialog = useDialog(); + + /** + * Shows a prompt dialog with a confirmation callback and an optional + * cancellation callback. + * @param title + * @param message + * @param fields + * @param labelConfirm + * @param labelCancel + * @param onConfirm + * @param onCancel + * @param modalProps + * @param formProps + */ + const fn = ( + title: string, + message: React.ReactNode, + fields: FormField[], + labelConfirm: string, + labelCancel: string, + onConfirm: (data: AttributeData) => void, + onCancel?: () => void, + modalProps?: Partial, + formProps?: FormProps, + ) => { + dialog( + title, + <> + {typeof message === "string" ?

{message}

: message} + + , + undefined, + { allowClose: false, ...modalProps }, + ); + }; + + return fn; +}; + +const PromptForm = ({ + message, + fields, + labelConfirm, + labelCancel, + onConfirm, + onCancel, + formProps, +}: { + message: React.ReactNode; + fields: FormField[]; + labelConfirm: string; + labelCancel: string; + onConfirm: (data: AttributeData) => void; + onCancel?: () => void; + formProps?: FormProps; +}) => { + const { setModalProps } = useContext(ModalServiceContext); + + useEffect(() => { + // Delay the focus slightly to ensure modal and form are fully rendered + const timer = setTimeout(() => { + // We focus a form element, and if none are found, we focus the submit button, and otherwise none + const formElement: HTMLFormElement | null = document.querySelector( + "form input , form textarea , form select , form button[type=submit]", + ); + if (formElement) { + formElement.focus(); + } + }, 100); + + return () => clearTimeout(timer); + }, []); + + return ( + <> + {typeof message === "string" ?

{message}

: message} +
{ + setModalProps({ open: false }); + onCancel?.(); + }, + }, + ]} + validateOnChange={true} + onSubmit={(_, data) => { + setModalProps({ open: false }); + onConfirm(data); + }} + {...formProps} + /> + + ); +}; diff --git a/src/hooks/dialog/useprompt.tsx b/src/hooks/dialog/useprompt.tsx index cc3e548a..50a44ace 100644 --- a/src/hooks/dialog/useprompt.tsx +++ b/src/hooks/dialog/useprompt.tsx @@ -1,16 +1,15 @@ -import React, { useContext } from "react"; +import { FormField } from "@maykin-ui/admin-ui"; +import React from "react"; -import { Form, ModalProps, P } from "../../components"; -import { ModalServiceContext } from "../../contexts"; -import { useDialog } from "./usedialog"; +import { ModalProps } from "../../components"; +import { useFormDialog } from "./useFormDialog"; /** * Returns a function which, when called: shows a prompt dialog with a * confirmation callback and an optional cancellation callback. */ export const usePrompt = () => { - const dialog = useDialog(); - const { setModalProps } = useContext(ModalServiceContext); + const formDialog = useFormDialog(); /** * Shows a prompt dialog with a confirmation callback and an optional @@ -34,33 +33,27 @@ export const usePrompt = () => { onCancel?: () => void, modalProps?: Partial, ) => { - dialog( + const fields: FormField[] = [ + { + label, + name: "message", + required: true, + type: "text", + }, + ]; + + formDialog( title, - <> - {typeof message === "string" ?

{message}

: message} - { - setModalProps({ open: false }); - onCancel?.(); - }, - }, - ]} - validateOnChange={true} - onSubmit={(_, { message }) => { - setModalProps({ open: false }); - onConfirm(message as string); - }} - /> - , - undefined, - { allowClose: false, ...modalProps }, + message, + fields, + labelConfirm, + labelCancel, + (data) => { + const message = data.message as string; + onConfirm(message); + }, + onCancel, + modalProps, ); };