Skip to content

Commit

Permalink
✨ - feat: implemented useFormDialog hook
Browse files Browse the repository at this point in the history
  • Loading branch information
Xaohs committed Oct 3, 2024
1 parent 93623aa commit cad5fa6
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 32 deletions.
127 changes: 127 additions & 0 deletions src/hooks/dialog/useFormDialog.tsx
Original file line number Diff line number Diff line change
@@ -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<ModalProps>,
formProps?: FormProps,
) => {
dialog(
title,
<>
{typeof message === "string" ? <P>{message}</P> : message}
<PromptForm
message={message}
fields={fields}
labelConfirm={labelConfirm}
labelCancel={labelCancel}
onConfirm={onConfirm}
onCancel={onCancel}
formProps={formProps}
/>
</>,
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" ? <P>{message}</P> : message}
<Form
fields={fields}
labelSubmit={labelConfirm}
secondaryActions={[
{
children: labelCancel,
type: "button",
variant: "secondary",
onClick: () => {
setModalProps({ open: false });
onCancel?.();
},
},
]}
validateOnChange={true}
onSubmit={(_, data) => {
setModalProps({ open: false });
onConfirm(data);
}}
{...formProps}
/>
</>
);
};
57 changes: 25 additions & 32 deletions src/hooks/dialog/useprompt.tsx
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -34,33 +33,27 @@ export const usePrompt = () => {
onCancel?: () => void,
modalProps?: Partial<ModalProps>,
) => {
dialog(
const fields: FormField[] = [
{
label,
name: "message",
required: true,
type: "text",
},
];

formDialog(
title,
<>
{typeof message === "string" ? <P>{message}</P> : message}
<Form
fields={[{ label, name: "message", required: true }]}
labelSubmit={labelConfirm}
secondaryActions={[
{
children: labelCancel,
variant: "secondary",
type: "button",
onClick: () => {
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,
);
};

Expand Down

0 comments on commit cad5fa6

Please sign in to comment.