From c972626a781b723eba48ea6f71b1ccd9f1ac2796 Mon Sep 17 00:00:00 2001 From: yassinedorbozgithub Date: Fri, 7 Feb 2025 06:24:52 +0100 Subject: [PATCH] refactor(frontend): update editUser dialog --- .../src/components/users/EditUserDialog.tsx | 153 ------------------ .../src/components/users/EditUserForm.tsx | 134 +++++++++++++++ .../components/users/EditUserFormDialog.tsx | 24 +++ 3 files changed, 158 insertions(+), 153 deletions(-) delete mode 100644 frontend/src/components/users/EditUserDialog.tsx create mode 100644 frontend/src/components/users/EditUserForm.tsx create mode 100644 frontend/src/components/users/EditUserFormDialog.tsx diff --git a/frontend/src/components/users/EditUserDialog.tsx b/frontend/src/components/users/EditUserDialog.tsx deleted file mode 100644 index 092bad94..00000000 --- a/frontend/src/components/users/EditUserDialog.tsx +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright © 2024 Hexastack. All rights reserved. - * - * 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. - * 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 { - Button, - Dialog, - DialogActions, - DialogContent, - Grid, -} from "@mui/material"; -import Link from "next/link"; -import { FC, useEffect, useState } from "react"; -import { Controller, useForm } from "react-hook-form"; - -import DialogButtons from "@/app-components/buttons/DialogButtons"; -import { DialogTitle } from "@/app-components/dialogs/DialogTitle"; -import { ContentContainer } from "@/app-components/dialogs/layouts/ContentContainer"; -import { ContentItem } from "@/app-components/dialogs/layouts/ContentItem"; -import AutoCompleteEntitySelect from "@/app-components/inputs/AutoCompleteEntitySelect"; -import { Input } from "@/app-components/inputs/Input"; -import { useUpdate } from "@/hooks/crud/useUpdate"; -import { DialogControlProps } from "@/hooks/useDialog"; -import { useToast } from "@/hooks/useToast"; -import { useTranslate } from "@/hooks/useTranslate"; -import { EntityType, Format } from "@/services/types"; -import { IRole } from "@/types/role.types"; -import { IUser, IUserAttributes } from "@/types/user.types"; - -const getFullName = (val: IUser) => `${val.first_name} ${val.last_name}`; - -export type EditUserDialogProps = DialogControlProps<{ - user: IUser; - roles: IRole[]; -}>; - -export const EditUserDialog: FC = ({ - open, - data, - closeDialog, - ...rest -}) => { - const { t } = useTranslate(); - const { toast } = useToast(); - const [fullName, setFullName] = useState(""); - const { mutateAsync: updateUser } = useUpdate(EntityType.USER, { - onError: (error) => { - toast.error(error.message || t("message.internal_server_error")); - }, - onSuccess() { - closeDialog(); - toast.success(t("message.success_save")); - }, - }); - const { - handleSubmit, - control, - reset, - formState: { errors }, - } = useForm({ - defaultValues: { roles: data?.roles.map((role) => role.id) }, - }); - const validationRules = { - roles: { - required: t("message.roles_is_required"), - }, - }; - const onSubmitForm = async (params: IUserAttributes) => { - if (data?.user.id) - updateUser({ - id: data.user.id, - params, - }); - }; - - useEffect(() => { - if (data?.user) setFullName(getFullName(data?.user)); - - if (open) reset({ roles: data?.user?.roles }); - }, [open, reset, data]); - - return ( - -
- - {t("title.manage_roles")} - - - - - - - - - - id) || []} - render={({ field }) => { - const { onChange, ...rest } = field; - - return ( - - autoFocus - searchFields={["name"]} - entity={EntityType.ROLE} - format={Format.BASIC} - labelKey="name" - label={t("label.roles")} - multiple={true} - {...field} - error={!!errors.roles} - helperText={ - errors.roles ? errors.roles.message : null - } - onChange={(_e, selected) => - onChange(selected.map(({ id }) => id)) - } - {...rest} - /> - ); - }} - /> - - - - - - - - - - - - - -
-
- ); -}; diff --git a/frontend/src/components/users/EditUserForm.tsx b/frontend/src/components/users/EditUserForm.tsx new file mode 100644 index 00000000..51b9f81d --- /dev/null +++ b/frontend/src/components/users/EditUserForm.tsx @@ -0,0 +1,134 @@ +/* + * Copyright © 2025 Hexastack. All rights reserved. + * + * 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. + * 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 { Button, Grid, Link } from "@mui/material"; +import { FC, Fragment, useEffect } from "react"; +import { Controller, useForm } from "react-hook-form"; + +import { ContentContainer, ContentItem } from "@/app-components/dialogs/"; +import AutoCompleteEntitySelect from "@/app-components/inputs/AutoCompleteEntitySelect"; +import { Input } from "@/app-components/inputs/Input"; +import { useUpdate } from "@/hooks/crud/useUpdate"; +import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; +import { EntityType, Format } from "@/services/types"; +import { ComponentFormProps } from "@/types/common/dialogs.types"; +import { IRole } from "@/types/role.types"; +import { IUser, IUserAttributes } from "@/types/user.types"; + +const getFullName = (user?: IUser) => `${user?.first_name} ${user?.last_name}`; + +export type EditUserFormData = { + user: IUser; + roles: IRole[]; +}; +export const EditUserForm: FC> = ({ + data, + Wrapper = Fragment, + WrapperProps, + ...rest +}) => { + const { t } = useTranslate(); + const { toast } = useToast(); + const { mutate: updateUser } = useUpdate(EntityType.USER, { + onError: (error) => { + rest.onError?.(); + toast.error(error.message || t("message.internal_server_error")); + }, + onSuccess() { + rest.onSuccess?.(); + toast.success(t("message.success_save")); + }, + }); + const { + reset, + control, + formState: { errors }, + handleSubmit, + } = useForm({ + defaultValues: { roles: data?.roles.map((role) => role.id) }, + }); + const validationRules = { + roles: { + required: t("message.roles_is_required"), + }, + }; + const onSubmitForm = (params: IUserAttributes) => { + if (data?.user.id) + updateUser({ + id: data.user.id, + params, + }); + }; + + useEffect(() => { + if (data?.user) reset({ roles: data?.user?.roles }); + }, [reset, data?.user]); + + return ( + +
+ + + + + + + + id) || []} + render={({ field }) => { + const { onChange, ...rest } = field; + + return ( + + autoFocus + searchFields={["name"]} + entity={EntityType.ROLE} + format={Format.BASIC} + labelKey="name" + label={t("label.roles")} + multiple={true} + {...field} + error={!!errors.roles} + helperText={errors.roles ? errors.roles.message : null} + onChange={(_e, selected) => + onChange(selected.map(({ id }) => id)) + } + {...rest} + /> + ); + }} + /> + + + + + + + + + +
+
+ ); +}; diff --git a/frontend/src/components/users/EditUserFormDialog.tsx b/frontend/src/components/users/EditUserFormDialog.tsx new file mode 100644 index 00000000..fc7cb5a1 --- /dev/null +++ b/frontend/src/components/users/EditUserFormDialog.tsx @@ -0,0 +1,24 @@ +/* + * Copyright © 2025 Hexastack. All rights reserved. + * + * 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. + * 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 { GenericFormDialog } from "@/app-components/dialogs"; +import { ComponentFormDialogProps } from "@/types/common/dialogs.types"; + +import { EditUserForm, EditUserFormData } from "./EditUserForm"; + +export const CategoryFormDialog = < + T extends EditUserFormData = EditUserFormData, +>( + props: ComponentFormDialogProps, +) => ( + + Form={EditUserForm} + editText="title.manage_roles" + {...props} + /> +);