From 48a03500d8af84ccc056a5ae529f9359a8edb201 Mon Sep 17 00:00:00 2001 From: yassinedorbozgithub Date: Wed, 5 Feb 2025 17:35:36 +0100 Subject: [PATCH] refactor(frontend): update language dialogs --- .../components/languages/LanguageDialog.tsx | 150 ------------------ .../src/components/languages/LanguageForm.tsx | 127 +++++++++++++++ .../languages/LanguageFormDialog.tsx | 37 +++++ frontend/src/components/languages/index.tsx | 31 ++-- 4 files changed, 177 insertions(+), 168 deletions(-) delete mode 100644 frontend/src/components/languages/LanguageDialog.tsx create mode 100644 frontend/src/components/languages/LanguageForm.tsx create mode 100644 frontend/src/components/languages/LanguageFormDialog.tsx diff --git a/frontend/src/components/languages/LanguageDialog.tsx b/frontend/src/components/languages/LanguageDialog.tsx deleted file mode 100644 index 14012bc9..00000000 --- a/frontend/src/components/languages/LanguageDialog.tsx +++ /dev/null @@ -1,150 +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 { - Dialog, - DialogActions, - DialogContent, - FormControlLabel, - Switch, -} from "@mui/material"; -import { FC, useEffect } 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 { Input } from "@/app-components/inputs/Input"; -import { useCreate } from "@/hooks/crud/useCreate"; -import { useUpdate } from "@/hooks/crud/useUpdate"; -import { DialogControlProps } from "@/hooks/useDialog"; -import { useToast } from "@/hooks/useToast"; -import { useTranslate } from "@/hooks/useTranslate"; -import { EntityType } from "@/services/types"; -import { ILanguage, ILanguageAttributes } from "@/types/language.types"; - -export type LanguageDialogProps = DialogControlProps; -export const LanguageDialog: FC = ({ - open, - data, - closeDialog, - ...rest -}) => { - const { t } = useTranslate(); - const { toast } = useToast(); - const { mutateAsync: createLanguage } = useCreate(EntityType.LANGUAGE, { - onError: () => { - toast.error(t("message.internal_server_error")); - }, - onSuccess() { - closeDialog(); - toast.success(t("message.success_save")); - }, - }); - const { mutateAsync: updateLanguage } = useUpdate(EntityType.LANGUAGE, { - onError: () => { - toast.error(t("message.internal_server_error")); - }, - onSuccess() { - closeDialog(); - toast.success(t("message.success_save")); - }, - }); - const { - reset, - register, - formState: { errors }, - handleSubmit, - control, - } = useForm({ - defaultValues: { - title: data?.title || "", - code: data?.code || "", - isRTL: data?.isRTL || false, - }, - }); - const validationRules = { - title: { - required: t("message.title_is_required"), - }, - code: { - required: t("message.code_is_required"), - }, - }; - const onSubmitForm = async (params: ILanguageAttributes) => { - if (data) { - updateLanguage({ id: data.id, params }); - } else { - createLanguage(params); - } - }; - - useEffect(() => { - if (open) reset(); - }, [open, reset]); - - useEffect(() => { - if (data) { - reset({ - title: data.title, - code: data.code, - isRTL: data.isRTL, - }); - } else { - reset(); - } - }, [data, reset]); - - return ( - -
- - {data ? t("title.edit_label") : t("title.new_label")} - - - - - - - - - - - ( - } - label={t("label.is_rtl")} - /> - )} - /> - - - - - - -
-
- ); -}; diff --git a/frontend/src/components/languages/LanguageForm.tsx b/frontend/src/components/languages/LanguageForm.tsx new file mode 100644 index 00000000..3f42f074 --- /dev/null +++ b/frontend/src/components/languages/LanguageForm.tsx @@ -0,0 +1,127 @@ +/* + * 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 { FormControlLabel, Switch } from "@mui/material"; +import { FC, Fragment, useEffect } from "react"; +import { Controller, useForm } from "react-hook-form"; + +import { ContentContainer, ContentItem } from "@/app-components/dialogs/"; +import { Input } from "@/app-components/inputs/Input"; +import { useCreate } from "@/hooks/crud/useCreate"; +import { useUpdate } from "@/hooks/crud/useUpdate"; +import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; +import { EntityType } from "@/services/types"; +import { ComponentFormProps } from "@/types/common/dialogs.types"; +import { ILanguage, ILanguageAttributes } from "@/types/language.types"; + +export const LanguageForm: FC> = ({ + data, + Wrapper = Fragment, + WrapperProps, + ...rest +}) => { + const { t } = useTranslate(); + const { toast } = useToast(); + const options = { + onError: () => { + rest.onError?.(); + toast.error(t("message.internal_server_error")); + }, + onSuccess() { + rest.onSuccess?.(); + toast.success(t("message.success_save")); + }, + }; + const { mutate: createLanguage } = useCreate(EntityType.LANGUAGE, options); + const { mutate: updateLanguage } = useUpdate(EntityType.LANGUAGE, options); + const { + reset, + register, + formState: { errors }, + handleSubmit, + control, + } = useForm({ + defaultValues: { + title: data?.title || "", + code: data?.code || "", + isRTL: data?.isRTL || false, + }, + }); + const validationRules = { + title: { + required: t("message.title_is_required"), + }, + code: { + required: t("message.code_is_required"), + }, + }; + const onSubmitForm = (params: ILanguageAttributes) => { + if (data) { + updateLanguage({ id: data.id, params }); + } else { + createLanguage(params); + } + }; + + useEffect(() => { + if (data) { + reset({ + title: data.title, + code: data.code, + isRTL: data.isRTL, + }); + } else { + reset(); + } + }, [data, reset]); + + return ( + +
+ + + + + + + + + ( + } + label={t("label.is_rtl")} + /> + )} + /> + + +
+
+ ); +}; diff --git a/frontend/src/components/languages/LanguageFormDialog.tsx b/frontend/src/components/languages/LanguageFormDialog.tsx new file mode 100644 index 00000000..007544ba --- /dev/null +++ b/frontend/src/components/languages/LanguageFormDialog.tsx @@ -0,0 +1,37 @@ +/* + * 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 { FC } from "react"; + +import { FormDialog } from "@/app-components/dialogs"; +import { useTranslate } from "@/hooks/useTranslate"; +import { ComponentFormDialogProps } from "@/types/common/dialogs.types"; +import { ILanguage } from "@/types/language.types"; + +import { LanguageForm } from "./LanguageForm"; + +export const LanguageFormDialog: FC> = ({ + payload, + ...rest +}) => { + const { t } = useTranslate(); + + return ( + { + rest.onClose(true); + }} + Wrapper={FormDialog} + WrapperProps={{ + title: payload ? t("title.edit_language") : t("title.new_language"), + ...rest, + }} + /> + ); +}; diff --git a/frontend/src/components/languages/index.tsx b/frontend/src/components/languages/index.tsx index 2b59a49e..1d914634 100644 --- a/frontend/src/components/languages/index.tsx +++ b/frontend/src/components/languages/index.tsx @@ -12,7 +12,7 @@ import { Button, Grid, Paper, Switch } from "@mui/material"; import { GridColDef } from "@mui/x-data-grid"; import { useQueryClient } from "react-query"; -import { DeleteDialog } from "@/app-components/dialogs/DeleteDialog"; +import { ConfirmDialogBody } from "@/app-components/dialogs"; import { FilterTextfield } from "@/app-components/inputs/FilterTextfield"; import { ActionColumnLabel, @@ -24,7 +24,7 @@ import { isSameEntity } from "@/hooks/crud/helpers"; import { useDelete } from "@/hooks/crud/useDelete"; import { useFind } from "@/hooks/crud/useFind"; import { useUpdate } from "@/hooks/crud/useUpdate"; -import { getDisplayDialogs, useDialog } from "@/hooks/useDialog"; +import { useDialogs } from "@/hooks/useDialogs"; import { useHasPermission } from "@/hooks/useHasPermission"; import { useSearch } from "@/hooks/useSearch"; import { useToast } from "@/hooks/useToast"; @@ -35,14 +35,12 @@ import { ILanguage } from "@/types/language.types"; import { PermissionAction } from "@/types/permission.types"; import { getDateTimeFormatter } from "@/utils/date"; -import { LanguageDialog } from "./LanguageDialog"; +import { LanguageFormDialog } from "./LanguageFormDialog"; export const Languages = () => { const { t } = useTranslate(); const { toast } = useToast(); - const addDialogCtl = useDialog(false); - const editDialogCtl = useDialog(false); - const deleteDialogCtl = useDialog(false); + const dialogs = useDialogs(); const queryClient = useQueryClient(); const hasPermission = useHasPermission(); const { onSearch, searchPayload } = useSearch({ @@ -75,7 +73,6 @@ export const Languages = () => { return isSameEntity(qEntity, EntityType.NLP_SAMPLE); }, }); - deleteDialogCtl.closeDialog(); toast.success(t("message.item_delete_success")); }, }); @@ -94,12 +91,18 @@ export const Languages = () => { [ { label: ActionColumnLabel.Edit, - action: (row) => editDialogCtl.openDialog(row), + action: (row) => dialogs.open(LanguageFormDialog, row), requires: [PermissionAction.UPDATE], }, { label: ActionColumnLabel.Delete, - action: (row) => deleteDialogCtl.openDialog(row.id), + action: async ({ id }) => { + const isConfirmed = await dialogs.confirm(ConfirmDialogBody); + + if (isConfirmed) { + deleteLanguage(id); + } + }, requires: [PermissionAction.DELETE], isDisabled: (row) => row.isDefault, }, @@ -182,14 +185,6 @@ export const Languages = () => { return ( - - - { - if (deleteDialogCtl?.data) deleteLanguage(deleteDialogCtl.data); - }} - /> { startIcon={} variant="contained" sx={{ float: "right" }} - onClick={() => addDialogCtl.openDialog()} + onClick={() => dialogs.open(LanguageFormDialog, null)} > {t("button.add")}