fix: includes the dynamic fields in creation form

This commit is contained in:
hexastack 2025-02-04 14:53:22 +01:00
parent 02c50d76a1
commit 8112b80f94

View File

@ -1,14 +1,16 @@
/* /*
* Copyright © 2024 Hexastack. All rights reserved. * Copyright © 2025 Hexastack. All rights reserved.
* *
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/ */
import { Dialog, DialogActions, DialogContent } from "@mui/material";
import AddIcon from "@mui/icons-material/Add";
import { Button, Dialog, DialogActions, DialogContent } from "@mui/material";
import { FC, useEffect } from "react"; import { FC, useEffect } from "react";
import { useForm } from "react-hook-form"; import { useFieldArray, useForm } from "react-hook-form";
import DialogButtons from "@/app-components/buttons/DialogButtons"; import DialogButtons from "@/app-components/buttons/DialogButtons";
import { DialogTitle } from "@/app-components/dialogs/DialogTitle"; import { DialogTitle } from "@/app-components/dialogs/DialogTitle";
@ -21,10 +23,10 @@ import { DialogControlProps } from "@/hooks/useDialog";
import { useToast } from "@/hooks/useToast"; import { useToast } from "@/hooks/useToast";
import { useTranslate } from "@/hooks/useTranslate"; import { useTranslate } from "@/hooks/useTranslate";
import { EntityType } from "@/services/types"; import { EntityType } from "@/services/types";
import { import { ContentFieldType, IContentType } from "@/types/content-type.types";
IContentType,
IContentTypeAttributes, import { FieldInput } from "./components/FieldInput";
} from "@/types/content-type.types"; import { FIELDS_FORM_DEFAULT_VALUES, READ_ONLY_FIELDS } from "./constants";
export type ContentTypeDialogProps = DialogControlProps<IContentType>; export type ContentTypeDialogProps = DialogControlProps<IContentType>;
export const ContentTypeDialog: FC<ContentTypeDialogProps> = ({ export const ContentTypeDialog: FC<ContentTypeDialogProps> = ({
@ -37,15 +39,32 @@ export const ContentTypeDialog: FC<ContentTypeDialogProps> = ({
const { const {
handleSubmit, handleSubmit,
register, register,
control,
reset, reset,
setValue,
formState: { errors }, formState: { errors },
} = useForm<IContentTypeAttributes>({ } = useForm<Partial<IContentType>>({
defaultValues: { name: data?.name || "" }, defaultValues: {
name: data?.name || "",
fields: data?.fields || FIELDS_FORM_DEFAULT_VALUES,
},
}); });
const CloseAndReset = () => { const { append, fields, remove } = useFieldArray({
closeDialog(); name: "fields",
reset(); control,
}; });
useEffect(() => {
if (data) {
reset({
name: data.name,
fields: data.fields,
});
} else {
reset();
}
}, [data, reset]);
const { mutateAsync: createContentType } = useCreate( const { mutateAsync: createContentType } = useCreate(
EntityType.CONTENT_TYPE, EntityType.CONTENT_TYPE,
{ {
@ -70,40 +89,18 @@ export const ContentTypeDialog: FC<ContentTypeDialogProps> = ({
}, },
}, },
); );
const validationRules = { const onSubmitForm = async (params) => {
name: {
required: t("message.name_is_required"),
},
};
const onSubmitForm = async (params: IContentTypeAttributes) => {
if (data) { if (data) {
updateContentType({ updateContentType({ id: data.id, params });
id: data.id,
params,
});
} else { } else {
createContentType(params); createContentType({ ...params, name: params.name || "" });
} }
}; };
useEffect(() => {
if (open) reset();
}, [open, reset]);
useEffect(() => {
if (data) {
reset({
name: data.name,
});
} else {
reset();
}
}, [data, reset]);
return ( return (
<Dialog open={open} fullWidth onClose={CloseAndReset}> <Dialog open={open} fullWidth onClose={closeDialog}>
<form onSubmit={handleSubmit(onSubmitForm)}> <form onSubmit={handleSubmit(onSubmitForm)}>
<DialogTitle onClose={CloseAndReset}> <DialogTitle onClose={closeDialog}>
{data ? t("title.edit_content_type") : t("title.new_content_type")} {data ? t("title.edit_content_type") : t("title.new_content_type")}
</DialogTitle> </DialogTitle>
<DialogContent> <DialogContent>
@ -112,12 +109,41 @@ export const ContentTypeDialog: FC<ContentTypeDialogProps> = ({
<Input <Input
label={t("label.name")} label={t("label.name")}
error={!!errors.name} error={!!errors.name}
{...register("name", validationRules.name)} {...register("name", {
helperText={errors.name ? errors.name.message : null} required: t("message.name_is_required"),
})}
required required
autoFocus autoFocus
/> />
</ContentItem> </ContentItem>
{fields.map((f, index) => (
<ContentItem
key={f.id}
display="flex"
justifyContent="space-between"
gap={2}
>
<FieldInput
setValue={setValue}
control={control}
remove={remove}
index={index}
disabled={READ_ONLY_FIELDS.includes(f.label as any)}
/>
</ContentItem>
))}
<ContentItem>
<Button
startIcon={<AddIcon />}
variant="contained"
onClick={() =>
append({ label: "", name: "", type: ContentFieldType.TEXT })
}
>
{t("button.add")}
</Button>
</ContentItem>
</ContentContainer> </ContentContainer>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>