From 1a6a984d3c301e1b26e26065e1727871fb6669be Mon Sep 17 00:00:00 2001 From: fogouang <74138682+loique70@users.noreply.github.com> Date: Tue, 18 Jun 2024 07:13:58 -0700 Subject: [PATCH] OH2-318 | Types / Delivery Result CRUD (#612) * Add delivery result type * correction of description type error --------- Co-authored-by: Alessandro Domanico --- .../accessories/admin/types/TypesAdmin.tsx | 1 + .../DeliveryResultType.tsx | 70 ++++++ .../DeliveryResultTypeForm.tsx | 213 ++++++++++++++++++ .../deliveryResultTypeForm/consts.ts | 10 + .../deliveryResultTypeForm/index.ts | 2 + .../deliveryResultTypeForm/styles.scss | 77 +++++++ .../deliveryResultTypeForm/types.ts | 13 ++ .../DeliveryResultTypeTable.tsx | 126 +++++++++++ .../deliveryResultTypeTable/index.ts | 3 + .../deliveryResultTypeTable/styles.scss | 13 ++ .../EditDeliveryResultType.tsx | 51 +++++ .../editDeliveryResultType/index.ts | 1 + .../editDeliveryResultType/styles.scss | 5 + .../components/deliveryresulttypes/index.ts | 7 + .../NewDeliveryResultType.tsx | 41 ++++ .../newDeliveryResultType/index.ts | 1 + .../newDeliveryResultType/styles.scss | 5 + .../deliveryresulttypes/styles.scss | 3 + .../admin/types/components/index.ts | 1 + src/consts.ts | 3 + .../fixtures/deliveryResultTypeDTO.js | 18 ++ src/mockServer/routes/deliveryResultType.js | 45 ++++ src/mockServer/server.js | 2 + src/resources/i18n/en.json | 20 +- src/routes/Admin/TypesRoutes.tsx | 16 ++ src/state/types/deliveryResultType/actions.ts | 153 +++++++++++++ src/state/types/deliveryResultType/consts.ts | 35 +++ src/state/types/deliveryResultType/index.ts | 5 + src/state/types/deliveryResultType/initial.ts | 9 + src/state/types/deliveryResultType/reducer.ts | 150 ++++++++++++ src/state/types/deliveryResultType/types.ts | 9 + src/state/types/reducer.ts | 2 + src/state/types/types.ts | 2 + 33 files changed, 1111 insertions(+), 1 deletion(-) create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/DeliveryResultType.tsx create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/DeliveryResultTypeForm.tsx create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/consts.ts create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/index.ts create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/styles.scss create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/types.ts create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeTable/DeliveryResultTypeTable.tsx create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeTable/index.ts create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeTable/styles.scss create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/editDeliveryResultType/EditDeliveryResultType.tsx create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/editDeliveryResultType/index.ts create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/editDeliveryResultType/styles.scss create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/index.ts create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/newDeliveryResultType/NewDeliveryResultType.tsx create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/newDeliveryResultType/index.ts create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/newDeliveryResultType/styles.scss create mode 100644 src/components/accessories/admin/types/components/deliveryresulttypes/styles.scss create mode 100644 src/mockServer/fixtures/deliveryResultTypeDTO.js create mode 100644 src/mockServer/routes/deliveryResultType.js create mode 100644 src/state/types/deliveryResultType/actions.ts create mode 100644 src/state/types/deliveryResultType/consts.ts create mode 100644 src/state/types/deliveryResultType/index.ts create mode 100644 src/state/types/deliveryResultType/initial.ts create mode 100644 src/state/types/deliveryResultType/reducer.ts create mode 100644 src/state/types/deliveryResultType/types.ts diff --git a/src/components/accessories/admin/types/TypesAdmin.tsx b/src/components/accessories/admin/types/TypesAdmin.tsx index 0746c7fd6..30e4daf5d 100644 --- a/src/components/accessories/admin/types/TypesAdmin.tsx +++ b/src/components/accessories/admin/types/TypesAdmin.tsx @@ -32,6 +32,7 @@ const TypesAdmin = () => { { label: t("types.diseases"), value: "diseases" }, { label: t("types.deliveries"), value: "deliveries" }, { label: t("types.admissions"), value: "admissions" }, + { label: t("types.deliveryResultType"), value: "deliveryresulttypes" }, { label: t("types.discharges"), value: "discharges" }, ]; diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/DeliveryResultType.tsx b/src/components/accessories/admin/types/components/deliveryresulttypes/DeliveryResultType.tsx new file mode 100644 index 000000000..62ac42b35 --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/DeliveryResultType.tsx @@ -0,0 +1,70 @@ +import React, { useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { useDispatch } from "react-redux"; +import { useNavigate } from "react-router"; +import { + deleteDeliveryResultType, + deleteDeliveryResultTypeReset, + getDeliveryResultType, +} from "../../../../../../state/types/deliveryResultType/actions"; +import { PATHS } from "../../../../../../consts"; +import Button from "../../../../button/Button"; +import "./styles.scss"; +import { setTypeMode } from "../../../../../../state/types/config"; +import DeliveryResultTypeTable from "./deliveryResultTypeTable"; +import { DeliveryResultTypeDTO } from "../../../../../../generated"; + +const DelevyResultType = () => { + const navigate = useNavigate(); + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(getDeliveryResultType()); + dispatch(setTypeMode("manage")); + + return () => { + dispatch(deleteDeliveryResultTypeReset()); + }; + }, [dispatch]); + + const handleEdit = (row: DeliveryResultTypeDTO) => { + navigate( + PATHS.admin_delivery_result_types_edit.replace(":code", row.code!), + { + state: row, + } + ); + }; + + const handleDelete = (row: DeliveryResultTypeDTO) => { + dispatch(deleteDeliveryResultType(row.code ?? "")); + }; + + const { t } = useTranslation(); + return ( + <> +

{t("deliveryResultType.title")}

+ +
+ { + navigate("./new"); + }} + type="button" + variant="contained" + color="primary" + > + {t("deliveryResultType.addDeliveryResultType")} + + } + /> +
+ + ); +}; + +export default DelevyResultType; diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/DeliveryResultTypeForm.tsx b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/DeliveryResultTypeForm.tsx new file mode 100644 index 000000000..e37bf1439 --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/DeliveryResultTypeForm.tsx @@ -0,0 +1,213 @@ +import { useFormik } from "formik"; +import { get, has } from "lodash"; +import React, { + FC, + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from "react"; +import { useTranslation } from "react-i18next"; +import { object, string } from "yup"; +import warningIcon from "../../../../../../../assets/warning-icon.png"; +import checkIcon from "../../../../../../../assets/check-icon.png"; +import "./styles.scss"; +import { IDeliveryResultTypeFormProps } from "./types"; +import { useDispatch, useSelector } from "react-redux"; +import { useNavigate } from "react-router"; +import { IState } from "../../../../../../../types"; +import { IDeliveryResultTypeState } from "../../../../../../../state/types/deliveryResultType/types"; +import { + formatAllFieldValues, + getFromFields, +} from "../../../../../../../libraries/formDataHandling/functions"; +import { + createDeliveryResultTypeReset, + updateDeliveryResultTypeReset, +} from "../../../../../../../state/types/deliveryResultType/actions"; +import TextField from "../../../../../textField/TextField"; +import Button from "../../../../../button/Button"; +import ConfirmationDialog from "../../../../../confirmationDialog/ConfirmationDialog"; +import InfoBox from "../../../../../infoBox/InfoBox"; +import { PATHS } from "../../../../../../../consts"; + +const DeliveryResultTypeForm: FC = ({ + fields, + onSubmit, + creationMode, + submitButtonLabel, + resetButtonLabel, + isLoading, +}) => { + const dispatch = useDispatch(); + const { t } = useTranslation(); + const navigate = useNavigate(); + const infoBoxRef = useRef(null); + const [openResetConfirmation, setOpenResetConfirmation] = useState(false); + + const deliveryResultTypesStore = useSelector< + IState, + IDeliveryResultTypeState + >((state) => state.types.deliveryResult); + + const errorMessage = useMemo( + () => + (creationMode + ? deliveryResultTypesStore.create.error?.message + : deliveryResultTypesStore.update.error?.message) ?? + t("common.somethingwrong"), + [ + creationMode, + t, + deliveryResultTypesStore.create.error?.message, + deliveryResultTypesStore.update.error?.message, + ] + ); + + const initialValues = getFromFields(fields, "value"); + + const validationSchema = object({ + code: string().required(t("common.required")), + description: string().required(t("common.required")), + }); + + const formik = useFormik({ + initialValues, + validationSchema, + enableReinitialize: true, + onSubmit: (values) => { + const formattedValues = formatAllFieldValues(fields, values); + onSubmit(formattedValues as any); + }, + }); + + const isValid = (fieldName: string): boolean => { + return has(formik.touched, fieldName) && has(formik.errors, fieldName); + }; + + const getErrorText = (fieldName: string): string => { + return has(formik.touched, fieldName) + ? (get(formik.errors, fieldName) as string) + : ""; + }; + + const handleResetConfirmation = () => { + setOpenResetConfirmation(false); + navigate(-1); + }; + + const cleanUp = useCallback(() => { + if (creationMode) { + dispatch(createDeliveryResultTypeReset()); + } else { + dispatch(updateDeliveryResultTypeReset()); + } + }, [creationMode, dispatch]); + + useEffect(() => { + return cleanUp; + }, [cleanUp]); + + return ( +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ setOpenResetConfirmation(false)} + /> + {(creationMode + ? deliveryResultTypesStore.create.status === "FAIL" + : deliveryResultTypesStore.update.status === "FAIL") && ( +
+ +
+ )} + { + navigate(PATHS.admin_delivery_result_types); + }} + handleSecondaryButtonClick={() => ({})} + /> + +
+ ); +}; + +export default DeliveryResultTypeForm; diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/consts.ts b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/consts.ts new file mode 100644 index 000000000..dd0576805 --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/consts.ts @@ -0,0 +1,10 @@ +import { DeliveryResultTypeDTO } from "../../../../../../../generated"; +import { TFields } from "../../../../../../../libraries/formDataHandling/types"; +import { DeliveryResultTypeFormFieldName } from "./types"; + +export const getInitialFields: ( + diseaseType: DeliveryResultTypeDTO | undefined +) => TFields = (diseaseType) => ({ + code: { type: "text", value: diseaseType?.code ?? "" }, + description: { type: "text", value: diseaseType?.description ?? "" }, +}); diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/index.ts b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/index.ts new file mode 100644 index 000000000..de3c7da20 --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/index.ts @@ -0,0 +1,2 @@ +export * from "./DeliveryResultTypeForm"; +export * from "./types"; diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/styles.scss b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/styles.scss new file mode 100644 index 000000000..d687707ea --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/styles.scss @@ -0,0 +1,77 @@ +@import "../../../../../../../../node_modules/susy/sass/susy"; +@import "../../../../../../../styles/variables"; + +.deliveryResultTypesForm { + display: inline-block; + flex-direction: column; + align-items: center; + width: 100%; + + .formInsertMode { + margin: 0px 0px 20px; + } + + .row { + justify-content: space-between; + } + + .deliveryResultTypesForm__item { + margin: 7px 0px; + padding: 0px 15px; + width: 50%; + @include susy-media($narrow) { + padding: 0px 10px; + } + @include susy-media($tablet_land) { + padding: 0px 10px; + } + @include susy-media($medium-up) { + width: 25%; + } + @include susy-media($tablet_port) { + width: 50%; + } + @include susy-media($smartphone) { + width: 100%; + } + .textField, + .selectField { + width: 100%; + } + + &.halfWidth { + width: 50%; + @include susy-media($smartphone) { + width: 100%; + } + } + &.fullWidth { + width: 100%; + } + } + + .deliveryResultTypesForm__buttonSet { + display: flex; + margin-top: 25px; + padding: 0px 15px; + flex-direction: row-reverse; + @include susy-media($smartphone_small) { + display: block; + } + + .submit_button, + .reset_button { + .MuiButton-label { + font-size: smaller; + letter-spacing: 1px; + font-weight: 600; + } + button { + @include susy-media($smartphone_small) { + width: 100%; + margin-top: 10px; + } + } + } + } +} diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/types.ts b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/types.ts new file mode 100644 index 000000000..1fbae1fbb --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeForm/types.ts @@ -0,0 +1,13 @@ +import { DeliveryResultTypeDTO } from "../../../../../../../generated"; +import { TFields } from "../../../../../../../libraries/formDataHandling/types"; + +export interface IDeliveryResultTypeFormProps { + fields: TFields; + onSubmit: (adm: DeliveryResultTypeDTO) => void; + creationMode: boolean; + submitButtonLabel: string; + resetButtonLabel: string; + isLoading: boolean; +} + +export type DeliveryResultTypeFormFieldName = "code" | "description"; diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeTable/DeliveryResultTypeTable.tsx b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeTable/DeliveryResultTypeTable.tsx new file mode 100644 index 000000000..21d6c5e11 --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeTable/DeliveryResultTypeTable.tsx @@ -0,0 +1,126 @@ +import React, { ReactNode, useRef } from "react"; +import { useTranslation } from "react-i18next"; +import { useDispatch, useSelector } from "react-redux"; +import { ApiResponse } from "../../../../../../../state/types"; +import { IState } from "../../../../../../../types"; +import { DeliveryResultTypeDTO } from "../../../../../../../generated"; +import InfoBox from "../../../../../infoBox/InfoBox"; +import { CircularProgress } from "@material-ui/core"; +import Table from "../../../../../table/Table"; +import ConfirmationDialog from "../../../../../confirmationDialog/ConfirmationDialog"; +import { deleteDeliveryResultTypeReset } from "../../../../../../../state/types/deliveryResultType/actions"; +import checkIcon from "../../../../../../../assets/check-icon.png"; +import "./styles.scss"; + +interface IOwnProps { + onEdit: (row: any) => void; + onDelete: (row: any) => void; + headerActions?: ReactNode; +} + +const DeliveryResultTypeTable = (props: IOwnProps) => { + const { onDelete, onEdit, headerActions } = props; + const dispatch = useDispatch(); + const { t } = useTranslation(); + const infoBoxRef = useRef(null); + + const header = ["code", "description"]; + + const label = { + code: t("deliveryResultType.code"), + description: t("deliveryResultType.description"), + }; + const order = ["code", "description"]; + + const { data, status, error } = useSelector< + IState, + ApiResponse + >((state) => state.types.deliveryResult.getAll); + + const deleteDeliveryResultType = useSelector>( + (state) => state.types.deliveryResult.delete + ); + + const handleEdit = (row: DeliveryResultTypeDTO) => { + onEdit((data ?? []).find((item) => item.code === row?.code)); + }; + + const handleDelete = (row: DeliveryResultTypeDTO) => { + onDelete(row); + }; + + const formatDataToDisplay = (data: DeliveryResultTypeDTO[]) => { + return data.map((item) => { + return { + code: item.code, + description: item.description, + }; + }); + }; + + return ( +
+ {(() => { + switch (status) { + case "FAIL": + return ( +
+ +
+ ); + case "LOADING": + return ; + + case "SUCCESS": + return ( + <> + + {deleteDeliveryResultType.status === "FAIL" && ( +
+ +
+ )} + { + dispatch(deleteDeliveryResultTypeReset()); + }} + handleSecondaryButtonClick={() => ({})} + /> + + ); + case "SUCCESS_EMPTY": + return ; + default: + return; + } + })()} + + ); +}; + +export default DeliveryResultTypeTable; diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeTable/index.ts b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeTable/index.ts new file mode 100644 index 000000000..ba7239c7e --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeTable/index.ts @@ -0,0 +1,3 @@ +import DeliveryResultTypeTable from "./DeliveryResultTypeTable"; + +export default DeliveryResultTypeTable; diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeTable/styles.scss b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeTable/styles.scss new file mode 100644 index 000000000..796157cad --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/deliveryResultTypeTable/styles.scss @@ -0,0 +1,13 @@ +.deliveryResultTypesTable { + display: grid; + margin-top: 50px; + + .fullWidth { + width: 100%; + } + + .loader { + margin-left: 50%; + position: relative; + } +} diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/editDeliveryResultType/EditDeliveryResultType.tsx b/src/components/accessories/admin/types/components/deliveryresulttypes/editDeliveryResultType/EditDeliveryResultType.tsx new file mode 100644 index 000000000..35571b3b4 --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/editDeliveryResultType/EditDeliveryResultType.tsx @@ -0,0 +1,51 @@ +import { useTranslation } from "react-i18next"; +import React, { useEffect } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { Navigate, useLocation, useParams } from "react-router"; +import { DeliveryResultTypeDTO } from "../../../../../../../generated"; +import { IState } from "../../../../../../../types"; +import { ApiResponse } from "../../../../../../../state/types"; +import { PATHS } from "../../../../../../../consts"; +import { setTypeMode } from "../../../../../../../state/types/config"; +import "./styles.scss"; +import DeliveryResultTypeForm from "../deliveryResultTypeForm/DeliveryResultTypeForm"; +import { getInitialFields } from "../deliveryResultTypeForm/consts"; +import { updateDeliveryResultType } from "../../../../../../../state/types/deliveryResultType/actions"; + +export const EditDeliveryResultType = () => { + const dispatch = useDispatch(); + const { t } = useTranslation(); + const { state }: { state: DeliveryResultTypeDTO | undefined } = useLocation(); + const { code } = useParams(); + const update = useSelector>( + (state) => state.types.deliveryResult.update + ); + + const handleSubmit = (value: DeliveryResultTypeDTO) => { + dispatch(updateDeliveryResultType(value)); + }; + + useEffect(() => { + dispatch(setTypeMode("edit")); + }); + + if (state?.code !== code) { + return ; + } + + return ( +
+

+ {t("deliveryResultType.editDeliveryResultType")} +

+ +
+ ); +}; diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/editDeliveryResultType/index.ts b/src/components/accessories/admin/types/components/deliveryresulttypes/editDeliveryResultType/index.ts new file mode 100644 index 000000000..0729721be --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/editDeliveryResultType/index.ts @@ -0,0 +1 @@ +export * from "./EditDeliveryResultType"; diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/editDeliveryResultType/styles.scss b/src/components/accessories/admin/types/components/deliveryresulttypes/editDeliveryResultType/styles.scss new file mode 100644 index 000000000..4274ed01f --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/editDeliveryResultType/styles.scss @@ -0,0 +1,5 @@ +.editDeliverResultType { + .title { + margin-bottom: 10px; + } +} diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/index.ts b/src/components/accessories/admin/types/components/deliveryresulttypes/index.ts new file mode 100644 index 000000000..b3dd56e30 --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/index.ts @@ -0,0 +1,7 @@ +import DeliveryResultType from "./DeliveryResultType"; + +export default DeliveryResultType; +export * from "./editDeliveryResultType"; +export * from "./newDeliveryResultType"; +export * from "./deliveryResultTypeForm"; +export * from "./deliveryResultTypeTable"; diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/newDeliveryResultType/NewDeliveryResultType.tsx b/src/components/accessories/admin/types/components/deliveryresulttypes/newDeliveryResultType/NewDeliveryResultType.tsx new file mode 100644 index 000000000..88d207036 --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/newDeliveryResultType/NewDeliveryResultType.tsx @@ -0,0 +1,41 @@ +import { useTranslation } from "react-i18next"; +import React, { useEffect } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { IState } from "../../../../../../../types"; +import { ApiResponse } from "../../../../../../../state/types"; +import { DeliveryResultTypeDTO } from "../../../../../../../generated"; +import { setTypeMode } from "../../../../../../../state/types/config"; +import "./styles.scss"; +import DeliveryResultTypeForm from "../deliveryResultTypeForm/DeliveryResultTypeForm"; +import { getInitialFields } from "../deliveryResultTypeForm/consts"; +import { createDeliveryResultType } from "../../../../../../../state/types/deliveryResultType/actions"; + +export const NewDeliveryResultType = () => { + const dispatch = useDispatch(); + const { t } = useTranslation(); + const create = useSelector>( + (state) => state.types.deliveryResult.create + ); + + useEffect(() => { + dispatch(setTypeMode("edit")); + }); + + const handleSubmit = (value: DeliveryResultTypeDTO) => { + dispatch(createDeliveryResultType(value)); + }; + + return ( +
+

{t("deliveryResultType.addDeliveryResultType")}

+ +
+ ); +}; diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/newDeliveryResultType/index.ts b/src/components/accessories/admin/types/components/deliveryresulttypes/newDeliveryResultType/index.ts new file mode 100644 index 000000000..61149ec94 --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/newDeliveryResultType/index.ts @@ -0,0 +1 @@ +export * from "./NewDeliveryResultType"; diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/newDeliveryResultType/styles.scss b/src/components/accessories/admin/types/components/deliveryresulttypes/newDeliveryResultType/styles.scss new file mode 100644 index 000000000..84c77e246 --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/newDeliveryResultType/styles.scss @@ -0,0 +1,5 @@ +.newDeliveryResultType { + .title { + margin-bottom: 10px; + } +} diff --git a/src/components/accessories/admin/types/components/deliveryresulttypes/styles.scss b/src/components/accessories/admin/types/components/deliveryresulttypes/styles.scss new file mode 100644 index 000000000..8a3fb80f4 --- /dev/null +++ b/src/components/accessories/admin/types/components/deliveryresulttypes/styles.scss @@ -0,0 +1,3 @@ +.deliveryResultTypes { + margin-top: 50px; +} diff --git a/src/components/accessories/admin/types/components/index.ts b/src/components/accessories/admin/types/components/index.ts index 6d91356d1..7d1178790 100644 --- a/src/components/accessories/admin/types/components/index.ts +++ b/src/components/accessories/admin/types/components/index.ts @@ -1,3 +1,4 @@ export * from "./vaccines"; export * from "./exams"; export * from "./operations"; +export * from "./deliveryresulttypes"; diff --git a/src/consts.ts b/src/consts.ts index 61f38f525..2b8bebd89 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -54,6 +54,9 @@ export const PATHS = { admin_deliveries_types: "/admin/types/deliveries", admin_deliveries_types_new: "/admin/types/deliveries/new", admin_deliveries_types_edit: "/admin/types/deliveries/:code/edit", + admin_delivery_result_types: "/admin/types/deliveryresulttypes", + admin_delivery_result_types_new: "/admin/types/deliveryresulttypes/new", + admin_delivery_result_types_edit: "/admin/types/deliveryresulttypes/:code/edit", admin_admissions_types: "/admin/types/admissions", admin_admissions_types_new: "/admin/types/admissions/new", admin_admissions_types_edit: "/admin/types/admissions/:code/edit", diff --git a/src/mockServer/fixtures/deliveryResultTypeDTO.js b/src/mockServer/fixtures/deliveryResultTypeDTO.js new file mode 100644 index 000000000..20e9bda56 --- /dev/null +++ b/src/mockServer/fixtures/deliveryResultTypeDTO.js @@ -0,0 +1,18 @@ +export const deliveryResultTypeDTO = [ + { + code: "MP", + description: "1.MATERNAL AND PERINATAL DISEASES", + }, + { + code: "FK", + description: "2.FAKE DISEASE", + }, + { + code: "MA", + description: "3.MATERNAL AND PERINATAL DISEASES", + }, + { + code: "FG", + description: "4.FAKE DISEASE", + }, +]; diff --git a/src/mockServer/routes/deliveryResultType.js b/src/mockServer/routes/deliveryResultType.js new file mode 100644 index 000000000..e58eaef04 --- /dev/null +++ b/src/mockServer/routes/deliveryResultType.js @@ -0,0 +1,45 @@ +import { deliveryResultTypeDTO } from "../fixtures/deliveryResultTypeDTO"; + +export const deliveryResultTypeRoutes = (server) => { + server.namespace("/deliveryresulttypes", () => { + server.get("/").intercept((req, res) => { + res.status(200).json(deliveryResultTypeDTO); + }); + server.post("/").intercept((req, res) => { + const body = req.jsonBody(); + switch (body.code) { + case "FAIL": + res + .status(400) + .json({ message: "Fail to create delivery result type" }); + break; + default: + res.status(200).json(body); + } + }); + server.put("/").intercept((req, res) => { + const body = req.jsonBody(); + switch (body.code) { + case "FAIL": + res + .status(400) + .json({ message: "Fail to update delivery result type" }); + break; + default: + res.status(200).json(body); + } + }); + server.delete("/:code").intercept((req, res) => { + const code = req.params.code; + switch (code) { + case "FAIL": + res + .status(400) + .json({ message: "Fail to delete delivery result type" }); + break; + default: + res.status(200).json(true); + } + }); + }); +}; diff --git a/src/mockServer/server.js b/src/mockServer/server.js index 718e2f515..35c1929d2 100644 --- a/src/mockServer/server.js +++ b/src/mockServer/server.js @@ -29,6 +29,7 @@ import { vaccineRoutes } from "./routes/vaccine"; import { vaccineTypesRoutes } from "./routes/vaccineTypes"; import { deliveryTypesRoutes } from "./routes/deliveryTypes"; import { suppliersRoutes } from "./routes/suppliers"; +import { deliveryResultTypeRoutes } from "./routes/deliveryResultType"; export function makeServer() { Polly.register(XHRAdapter); @@ -67,6 +68,7 @@ export function makeServer() { vaccineTypesRoutes(server); suppliersRoutes(server); deliveryTypesRoutes(server); + deliveryResultTypeRoutes(server); }); return server; } diff --git a/src/resources/i18n/en.json b/src/resources/i18n/en.json index 250e7a638..320befe93 100644 --- a/src/resources/i18n/en.json +++ b/src/resources/i18n/en.json @@ -849,7 +849,8 @@ "discharges": "Types of discharge", "deliveries": "Types of delivery", "operations": "Type of operations", - "chooseATypeToStart": "Choose a type to start..." + "chooseATypeToStart": "Choose a type to start...", + "deliveryResultType": "Types of delivery result" }, "vaccineTypes": { "code": "Code", @@ -1013,6 +1014,23 @@ "createSuccess": "Disease has been created successfully!", "updateSuccess": "Disease {{code}} has been updated successfully!" }, + "deliveryResultType": { + "code": "Code", + "description": "Description", + "title": "Manage delivery result types", + "addDeliveryResultType": "New delivery result type", + "deleted": "Deleted", + "deleteSuccess": "The delivery result type has been deleted successfully!", + "saveDeliveryResultTypes": "Save", + "editDeliveryResultType": "Edit delivery result type", + "updateDeliveryResultType": "Save changes", + "created": "Delivery result type created", + "createSuccess": "The delivery result type has been created successfully!", + "updated": "Delivery result type updated", + "updateSuccess": "The delivery result type has been updated successfully!", + "cancelCreation": "Are you sure to cancel the delivery result type creation?", + "cancelUpdate": "Are you sure to cancel the delivery result type update?" + }, "examTypes": { "code": "Code", "description": "Description", diff --git a/src/routes/Admin/TypesRoutes.tsx b/src/routes/Admin/TypesRoutes.tsx index a24bd4953..79b7a79dc 100644 --- a/src/routes/Admin/TypesRoutes.tsx +++ b/src/routes/Admin/TypesRoutes.tsx @@ -31,6 +31,10 @@ import DeliveryTypes, { EditDeliveryType, NewDeliveryType, } from "../../components/accessories/admin/types/components/deliveries"; +import DeliveryResultType, { + EditDeliveryResultType, + NewDeliveryResultType, +} from "../../components/accessories/admin/types/components/deliveryresulttypes"; const TypesRoutes = () => { const routes: { element: ReactNode; path: string }[] = [ @@ -118,6 +122,18 @@ const TypesRoutes = () => { path: "deliveries/:code/edit", element: , }, + { + path: "deliveryresulttypes", + element: , + }, + { + path: "deliveryresulttypes/new", + element: , + }, + { + path: "deliveryresulttypes/:code/edit", + element: , + }, ]; return ( diff --git a/src/state/types/deliveryResultType/actions.ts b/src/state/types/deliveryResultType/actions.ts new file mode 100644 index 000000000..2aa356f6c --- /dev/null +++ b/src/state/types/deliveryResultType/actions.ts @@ -0,0 +1,153 @@ +import { isEmpty } from "lodash"; +import { Dispatch } from "redux"; +import { + DeliveryResultTypeApi, + DeliveryResultTypeDTO, +} from "../../../generated"; +import { customConfiguration } from "../../../libraries/apiUtils/configuration"; +import { IAction } from "../../types"; +import { + CREATE_DELIVERY_RESULT_TYPE_FAIL, + CREATE_DELIVERY_RESULT_TYPE_LOADING, + CREATE_DELIVERY_RESULT_TYPE_RESET, + CREATE_DELIVERY_RESULT_TYPE_SUCCESS, + DELETE_DELIVERY_RESULT_TYPE_FAIL, + DELETE_DELIVERY_RESULT_TYPE_LOADING, + DELETE_DELIVERY_RESULT_TYPE_RESET, + DELETE_DELIVERY_RESULT_TYPE_SUCCESS, + GET_DELIVERY_RESULT_TYPE_FAIL, + GET_DELIVERY_RESULT_TYPE_LOADING, + GET_DELIVERY_RESULT_TYPE_SUCCESS, + GET_DELIVERY_RESULT_TYPE_SUCCESS_EMPTY, + UPDATE_DELIVERY_RESULT_TYPE_FAIL, + UPDATE_DELIVERY_RESULT_TYPE_LOADING, + UPDATE_DELIVERY_RESULT_TYPE_RESET, + UPDATE_DELIVERY_RESULT_TYPE_SUCCESS, +} from "./consts"; + +const deliveryResultTypeApi = new DeliveryResultTypeApi(customConfiguration()); + +export const getDeliveryResultType = + () => + (dispatch: Dispatch>): void => { + dispatch({ + type: GET_DELIVERY_RESULT_TYPE_LOADING, + }); + deliveryResultTypeApi.getDeliveryResultTypes({}).subscribe( + (payload) => { + if (typeof payload === "object" && !isEmpty(payload)) { + dispatch({ + type: GET_DELIVERY_RESULT_TYPE_SUCCESS, + payload: payload, + }); + } else { + dispatch({ + type: GET_DELIVERY_RESULT_TYPE_SUCCESS_EMPTY, + payload: [], + }); + } + }, + (error) => { + dispatch({ + type: GET_DELIVERY_RESULT_TYPE_FAIL, + error: error?.response, + }); + } + ); + }; + +export const createDeliveryResultType = + (newDeliveryResultType: DeliveryResultTypeDTO) => + (dispatch: Dispatch>): void => { + dispatch({ + type: CREATE_DELIVERY_RESULT_TYPE_LOADING, + }); + deliveryResultTypeApi + .newDeliveryResultType({ deliveryResultTypeDTO: newDeliveryResultType }) + .subscribe( + (payload) => { + dispatch({ + type: CREATE_DELIVERY_RESULT_TYPE_SUCCESS, + payload: payload, + }); + }, + (error) => { + dispatch({ + type: CREATE_DELIVERY_RESULT_TYPE_FAIL, + error: error?.response, + }); + } + ); + }; + +export const createDeliveryResultTypeReset = + () => + (dispatch: Dispatch>): void => { + dispatch({ + type: CREATE_DELIVERY_RESULT_TYPE_RESET, + }); + }; + +export const updateDeliveryResultType = + (updateDeliveryResultType: DeliveryResultTypeDTO) => + (dispatch: Dispatch>): void => { + dispatch({ + type: UPDATE_DELIVERY_RESULT_TYPE_LOADING, + }); + deliveryResultTypeApi + .updateDeliveryResultTypes({ + deliveryResultTypeDTO: updateDeliveryResultType, + }) + .subscribe( + (payload) => { + dispatch({ + type: UPDATE_DELIVERY_RESULT_TYPE_SUCCESS, + payload: payload, + }); + }, + (error) => { + dispatch({ + type: UPDATE_DELIVERY_RESULT_TYPE_FAIL, + error: error?.response, + }); + } + ); + }; + +export const updateDeliveryResultTypeReset = + () => + (dispatch: Dispatch>): void => { + dispatch({ + type: UPDATE_DELIVERY_RESULT_TYPE_RESET, + }); + }; + +export const deleteDeliveryResultType = + (code: string) => + (dispatch: Dispatch>): void => { + dispatch({ + type: DELETE_DELIVERY_RESULT_TYPE_LOADING, + }); + deliveryResultTypeApi.deleteDeliveryResultType({ code }).subscribe( + (payload) => { + dispatch({ + type: DELETE_DELIVERY_RESULT_TYPE_SUCCESS, + payload: { deleted: payload, code }, + }); + }, + (error) => { + dispatch({ + type: DELETE_DELIVERY_RESULT_TYPE_FAIL, + error: error?.response, + }); + } + ); + }; + +export const deleteDeliveryResultTypeReset = + () => + (dispatch: Dispatch>): void => { + dispatch({ + type: DELETE_DELIVERY_RESULT_TYPE_RESET, + }); + }; diff --git a/src/state/types/deliveryResultType/consts.ts b/src/state/types/deliveryResultType/consts.ts new file mode 100644 index 000000000..45e1322b2 --- /dev/null +++ b/src/state/types/deliveryResultType/consts.ts @@ -0,0 +1,35 @@ +export const GET_DELIVERY_RESULT_TYPE_LOADING = + "deliveryResultType/GET_DELIVERY_RESULT_TYPE_LOADING"; +export const GET_DELIVERY_RESULT_TYPE_SUCCESS = + "deliveryResultType/GET_DELIVERY_RESULT_TYPE_SUCCESS"; +export const GET_DELIVERY_RESULT_TYPE_FAIL = + "diseaseTypes/GET_DELIVERY_RESULT_TYPE_FAIL"; +export const GET_DELIVERY_RESULT_TYPE_SUCCESS_EMPTY = + "deliveryResultType/GET_DELIVERY_RESULT_TYPE_EMPTY"; + +export const CREATE_DELIVERY_RESULT_TYPE_LOADING = + "deliveryResultType/CREATE_DELIVERY_RESULT_TYPE_LOADING"; +export const CREATE_DELIVERY_RESULT_TYPE_SUCCESS = + "deliveryResultType/CREATE_DELIVERY_RESULT_TYPE_SUCCESS"; +export const CREATE_DELIVERY_RESULT_TYPE_FAIL = + "deliveryResultType/CREATE_DELIVERY_RESULT_TYPE_FAIL"; +export const CREATE_DELIVERY_RESULT_TYPE_RESET = + "deliveryResultType/CREATE_DELIVERY_RESULT_TYPE_RESET"; + +export const UPDATE_DELIVERY_RESULT_TYPE_LOADING = + "deliveryResultType/UPDATE_DELIVERY_RESULT_TYPE_LOADING"; +export const UPDATE_DELIVERY_RESULT_TYPE_SUCCESS = + "deliveryResultType/UPDATE_DELIVERY_RESULT_TYPE_SUCCESS"; +export const UPDATE_DELIVERY_RESULT_TYPE_FAIL = + "deliveryResultType/UPDATE_DELIVERY_RESULT_TYPE_FAIL"; +export const UPDATE_DELIVERY_RESULT_TYPE_RESET = + "deliveryResultType/UPDATE_DELIVERY_RESULT_TYPE_RESET"; + +export const DELETE_DELIVERY_RESULT_TYPE_LOADING = + "deliveryResultType/DELETE_DELIVERY_RESULT_TYPE_LOADING"; +export const DELETE_DELIVERY_RESULT_TYPE_SUCCESS = + "deliveryResultType/DELETE_DELIVERY_RESULT_TYPE_SUCCESS"; +export const DELETE_DELIVERY_RESULT_TYPE_FAIL = + "deliveryResultType/DELETE_DELIVERY_RESULT_TYPE_FAIL"; +export const DELETE_DELIVERY_RESULT_TYPE_RESET = + "deliveryResultType/DELETE_DELIVERY_RESULT_TYPE_RESET"; diff --git a/src/state/types/deliveryResultType/index.ts b/src/state/types/deliveryResultType/index.ts new file mode 100644 index 000000000..dbfb25277 --- /dev/null +++ b/src/state/types/deliveryResultType/index.ts @@ -0,0 +1,5 @@ +export * from "./types"; +export * from "./actions"; +export * from "./initial"; +export * from "./reducer"; +export * from "./consts"; diff --git a/src/state/types/deliveryResultType/initial.ts b/src/state/types/deliveryResultType/initial.ts new file mode 100644 index 000000000..a58c72993 --- /dev/null +++ b/src/state/types/deliveryResultType/initial.ts @@ -0,0 +1,9 @@ +import { ApiResponse } from "../../types"; +import { IDeliveryResultTypeState } from "./types"; + +export const initial: IDeliveryResultTypeState = { + getAll: new ApiResponse({ status: "IDLE", data: [] }), + create: new ApiResponse({ status: "IDLE" }), + update: new ApiResponse({ status: "IDLE" }), + delete: new ApiResponse({ status: "IDLE" }), +}; diff --git a/src/state/types/deliveryResultType/reducer.ts b/src/state/types/deliveryResultType/reducer.ts new file mode 100644 index 000000000..419e51759 --- /dev/null +++ b/src/state/types/deliveryResultType/reducer.ts @@ -0,0 +1,150 @@ +import produce from "immer"; +import { VaccineTypeDTO } from "../../../generated"; +import { IAction } from "../../types"; +import { + CREATE_DELIVERY_RESULT_TYPE_FAIL, + CREATE_DELIVERY_RESULT_TYPE_LOADING, + CREATE_DELIVERY_RESULT_TYPE_RESET, + CREATE_DELIVERY_RESULT_TYPE_SUCCESS, + DELETE_DELIVERY_RESULT_TYPE_FAIL, + DELETE_DELIVERY_RESULT_TYPE_LOADING, + DELETE_DELIVERY_RESULT_TYPE_RESET, + DELETE_DELIVERY_RESULT_TYPE_SUCCESS, + GET_DELIVERY_RESULT_TYPE_FAIL, + GET_DELIVERY_RESULT_TYPE_LOADING, + GET_DELIVERY_RESULT_TYPE_SUCCESS, + GET_DELIVERY_RESULT_TYPE_SUCCESS_EMPTY, + UPDATE_DELIVERY_RESULT_TYPE_FAIL, + UPDATE_DELIVERY_RESULT_TYPE_LOADING, + UPDATE_DELIVERY_RESULT_TYPE_RESET, + UPDATE_DELIVERY_RESULT_TYPE_SUCCESS, +} from "./consts"; +import { initial } from "./initial"; +import { IDeliveryResultTypeState } from "./types"; + +export default produce( + (draft: IDeliveryResultTypeState, action: IAction) => { + switch (action.type) { + /** + * Create delivery result type + */ + case CREATE_DELIVERY_RESULT_TYPE_LOADING: { + draft.create.status = "LOADING"; + break; + } + + case CREATE_DELIVERY_RESULT_TYPE_SUCCESS: { + draft.create.status = "SUCCESS"; + draft.create.data = action.payload; + draft.getAll.data = [...(draft.getAll.data ?? []), action.payload]; + delete draft.create.error; + break; + } + + case CREATE_DELIVERY_RESULT_TYPE_FAIL: { + draft.create.status = "FAIL"; + draft.create.error = action.error; + break; + } + + case CREATE_DELIVERY_RESULT_TYPE_RESET: { + draft.create.status = "IDLE"; + delete draft.create.error; + break; + } + + /** + * Get delivery result types + */ + case GET_DELIVERY_RESULT_TYPE_LOADING: { + draft.getAll.status = "LOADING"; + break; + } + + case GET_DELIVERY_RESULT_TYPE_SUCCESS: { + draft.getAll.status = "SUCCESS"; + draft.getAll.data = action.payload; + delete draft.getAll.error; + break; + } + + case GET_DELIVERY_RESULT_TYPE_FAIL: { + draft.getAll.status = "FAIL"; + draft.getAll.error = action.error; + break; + } + + case GET_DELIVERY_RESULT_TYPE_SUCCESS_EMPTY: { + draft.getAll.status = "SUCCESS_EMPTY"; + draft.getAll.data = []; + delete draft.getAll.error; + break; + } + + /** + * Update delivery result type + */ + case UPDATE_DELIVERY_RESULT_TYPE_LOADING: { + draft.update.status = "LOADING"; + delete draft.update.error; + break; + } + + case UPDATE_DELIVERY_RESULT_TYPE_SUCCESS: { + draft.update.status = "SUCCESS"; + draft.update.data = action.payload; + draft.getAll.data = draft.getAll.data?.map((e) => { + return e.code === action.payload.code + ? (action.payload as VaccineTypeDTO) + : e; + }); + delete draft.update.error; + break; + } + + case UPDATE_DELIVERY_RESULT_TYPE_FAIL: { + draft.update.status = "FAIL"; + draft.update.error = action.error; + break; + } + + case UPDATE_DELIVERY_RESULT_TYPE_RESET: { + draft.update.status = "IDLE"; + delete draft.update.error; + break; + } + + /** + * Delete delivery result type + */ + case DELETE_DELIVERY_RESULT_TYPE_LOADING: { + draft.delete.status = "LOADING"; + delete draft.delete.error; + break; + } + + case DELETE_DELIVERY_RESULT_TYPE_SUCCESS: { + draft.delete.status = "SUCCESS"; + draft.delete.data = action.payload.deleted; + draft.getAll.data = draft.getAll.data?.filter((e) => { + return e.code !== action.payload.code; + }); + delete draft.delete.error; + break; + } + + case DELETE_DELIVERY_RESULT_TYPE_FAIL: { + draft.delete.status = "FAIL"; + draft.delete.error = action.error; + break; + } + + case DELETE_DELIVERY_RESULT_TYPE_RESET: { + draft.delete.status = "IDLE"; + delete draft.delete.error; + break; + } + } + }, + initial +); diff --git a/src/state/types/deliveryResultType/types.ts b/src/state/types/deliveryResultType/types.ts new file mode 100644 index 000000000..5e3fca76e --- /dev/null +++ b/src/state/types/deliveryResultType/types.ts @@ -0,0 +1,9 @@ +import { DeliveryResultTypeDTO } from "../../../generated"; +import { ApiResponse } from "../../types"; + +export type IDeliveryResultTypeState = { + getAll: ApiResponse>; + create: ApiResponse; + update: ApiResponse; + delete: ApiResponse; +}; diff --git a/src/state/types/reducer.ts b/src/state/types/reducer.ts index 751d621f9..cd436345e 100644 --- a/src/state/types/reducer.ts +++ b/src/state/types/reducer.ts @@ -7,6 +7,7 @@ import exams from "./exams/reducer"; import diseases from "./diseases/reducer"; import discharges from "./discharges/reducer"; import deliveries from "./deliveries/reducer"; +import deliveryResult from "./deliveryResultType/reducer"; const typesReducer = combineReducers({ vaccines: vaccineTypes, @@ -17,6 +18,7 @@ const typesReducer = combineReducers({ exams, discharges, deliveries, + deliveryResult, }); export default typesReducer; diff --git a/src/state/types/types.ts b/src/state/types/types.ts index f21f99ad7..dd111de7e 100644 --- a/src/state/types/types.ts +++ b/src/state/types/types.ts @@ -2,6 +2,7 @@ import { IAdmissionTypesState } from "./admissions"; import { ITypeConfigsState } from "./config"; import { IDischargeTypesState } from "./discharges"; import { IDeliveryTypesState } from "./deliveries"; +import { IDeliveryResultTypeState } from "./deliveryResultType"; import { IDiseaseTypesState } from "./diseases"; import { IOperationTypesState } from "./operations"; import { IVaccineTypesState } from "./vaccines"; @@ -16,4 +17,5 @@ export type ITypesState = { exams: IExamTypesState; discharges: IDischargeTypesState; deliveries: IDeliveryTypesState; + deliveryResult: IDeliveryResultTypeState; };