Skip to content

Commit

Permalink
OH2-288 | Implement hospital infos edit (#675)
Browse files Browse the repository at this point in the history
* update: Add update hospital state

* feature(OH2-288): Implement edit hospital infos

* chore: Add e2e tests

* fix: Update hospital edit payload and edit button styles

---------

Co-authored-by: SteveGT96 <[email protected]>
  • Loading branch information
SteveGT96 and SteveGT96 authored Oct 15, 2024
1 parent 1e4b29b commit 98d1c48
Show file tree
Hide file tree
Showing 22 changed files with 550 additions and 8 deletions.
48 changes: 48 additions & 0 deletions cypress/integrations/admin_activities/hospital/edit_hospital.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/// <reference types="cypress" />

const STARTS_PATH = "/admin";

describe("Edit Hospital Activity specs", () => {
it("should render the ui", () => {
cy.authenticate(STARTS_PATH);
cy.dataCy("hospital-infos").click();
cy.dataCy("edit-hospital").click();
cy.dataCy("activity-title").contains("Edit hospital");
});

it("should fail to edit the hospitalInfo", () => {
cy.byId("description").clear().type("FAIL");
cy.byId("email").clear().type("[email protected]");
cy.dataCy("submit-form").click();
cy.dataCy("dialog-info").should("not.exist");
cy.dataCy("info-box").contains("Invalid payload");
});

it("should successfully save hospital infos changes", () => {
cy.byId("description").clear().type("St. LUKE Hospital");
cy.byId("email").clear().type("[email protected]");
cy.byId("currencyCod").clear().type("FCFA");
cy.dataCy("submit-form").click();
cy.dataCy("dialog-info").contains("updated successfully");
cy.dataCy("approve-dialog").click();
});

it("should redirect after hospital info update", () => {
cy.dataCy("activity-title").contains("Wards");
});

it("should cancel the discard of the hospital infos", () => {
cy.dataCy("edit-hospital").first().click();
cy.dataCy("cancel-form").click();
cy.dataCy("dialog-info").contains("lost");
cy.dataCy("close-dialog").click().click();
cy.dataCy("dialog-info").should("not.be.visible");
});

it("should cancel the update of the hospital infos", () => {
cy.dataCy("cancel-form").click();
cy.dataCy("dialog-info").contains("lost");
cy.dataCy("approve-dialog").click();
cy.dataCy("activity-title").contains("Wards");
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useAppDispatch, useAppSelector } from "libraries/hooks/redux";
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router";
import { updateHospital } from "state/hospital";
import { PATHS } from "../../../../../consts";
import { HospitalDTO } from "../../../../../generated";
import HospitalForm from "../hospitalForm/HospitalForm";
import { getInitialFields } from "../hospitalForm/consts";

export const EditHospital = () => {
const dispatch = useAppDispatch();
const { t } = useTranslation();

const hospital = useAppSelector((state) => state.hospital.getHospital.data);
const update = useAppSelector((state) => state.hospital.updateHospital);

const navigate = useNavigate();

const handleSubmit = (value: HospitalDTO) => {
dispatch(
updateHospital({
code: hospital!.code!!,
hospitalDTO: { ...hospital, ...value },
})
);
};

useEffect(() => {
if (!hospital) {
navigate(PATHS.admin);
}
}, [navigate, hospital]);

return (
<HospitalForm
onSubmit={handleSubmit}
isLoading={!!update.isLoading}
resetButtonLabel={t("common.cancel")}
submitButtonLabel={t("hospital.updateHospital")}
fields={getInitialFields(hospital)}
/>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./EditHospital";
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
import { useFormik } from "formik";
import { useAppDispatch, useAppSelector } from "libraries/hooks/redux";
import { get, has } from "lodash";
import React, { FC, useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router";
import { object, string } from "yup";
import checkIcon from "../../../../../assets/check-icon.png";
import warningIcon from "../../../../../assets/warning-icon.png";
import { PATHS } from "../../../../../consts";
import {
formatAllFieldValues,
getFromFields,
} from "../../../../../libraries/formDataHandling/functions";
import { updateHospitalReset } from "../../../../../state/hospital";
import Button from "../../../button/Button";
import ConfirmationDialog from "../../../confirmationDialog/ConfirmationDialog";
import InfoBox from "../../../infoBox/InfoBox";
import TextField from "../../../textField/TextField";
import "./styles.scss";
import { IHospitalFormProps } from "./types";

const HospitalForm: FC<IHospitalFormProps> = ({
fields,
onSubmit,
submitButtonLabel,
resetButtonLabel,
isLoading,
}) => {
const dispatch = useAppDispatch();
const { t } = useTranslation();
const navigate = useNavigate();
const infoBoxRef = useRef<HTMLDivElement>(null);
const [openDiscardConfirmation, setOpenDiscardConfirmation] = useState(false);

const hospitalStore = useAppSelector((state) => state.hospital);

const errorMessage = useMemo(
() =>
hospitalStore.updateHospital.error?.message ?? t("common.somethingwrong"),
[t, hospitalStore.updateHospital.error?.message]
);

const initialValues = getFromFields(fields, "value");

const validationSchema = object({
description: string().required(t("common.required")),
address: string().notRequired(),
city: string().notRequired(),
fax: string().notRequired(),
telephone: string().notRequired(),
email: string().notRequired().email(t("validations.email")),
currencyCod: string().notRequired(),
});

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 handleDiscardConfirmation = () => {
setOpenDiscardConfirmation(false);
navigate(-1);
};

useEffect(() => {
return () => {
dispatch(updateHospitalReset());
};
}, []);

return (
<div className="hospitalForm">
<form className="hospitalForm__form" onSubmit={formik.handleSubmit}>
<div className="row start-sm center-xs">
<div className="hospitalForm__item halfWidth">
<TextField
field={formik.getFieldProps("description")}
theme="regular"
label={t("hospital.description")}
isValid={isValid("description")}
errorText={getErrorText("description")}
onBlur={formik.handleBlur}
type="text"
disabled={isLoading}
/>
</div>
<div className="hospitalForm__item halfWidth">
<TextField
field={formik.getFieldProps("address")}
theme="regular"
label={t("hospital.address")}
isValid={isValid("address")}
errorText={getErrorText("address")}
onBlur={formik.handleBlur}
type="text"
disabled={isLoading}
/>
</div>
<div className="hospitalForm__item halfWidth">
<TextField
field={formik.getFieldProps("city")}
theme="regular"
label={t("hospital.city")}
isValid={isValid("city")}
errorText={getErrorText("city")}
onBlur={formik.handleBlur}
type="text"
disabled={isLoading}
/>
</div>

<div className="hospitalForm__item halfWidth">
<TextField
field={formik.getFieldProps("telephone")}
theme="regular"
label={t("hospital.telephone")}
isValid={isValid("telephone")}
errorText={getErrorText("telephone")}
onBlur={formik.handleBlur}
type="text"
disabled={isLoading}
/>
</div>
<div className="hospitalForm__item halfWidth">
<TextField
field={formik.getFieldProps("fax")}
theme="regular"
label={t("hospital.fax")}
isValid={isValid("fax")}
errorText={getErrorText("fax")}
onBlur={formik.handleBlur}
type="text"
disabled={isLoading}
/>
</div>
<div className="hospitalForm__item halfWidth">
<TextField
field={formik.getFieldProps("email")}
theme="regular"
label={t("hospital.email")}
isValid={isValid("email")}
errorText={getErrorText("email")}
onBlur={formik.handleBlur}
type="email"
disabled={isLoading}
/>
</div>
<div className="hospitalForm__item halfWidth">
<TextField
field={formik.getFieldProps("currencyCod")}
theme="regular"
label={t("hospital.currencyCod")}
type="text"
isValid={isValid("currencyCod")}
errorText={getErrorText("currencyCod")}
onBlur={formik.handleBlur}
disabled={isLoading}
/>
</div>
</div>

<div className="hospitalForm__buttonSet">
<div className="submit_button">
<Button
type="submit"
dataCy="submit-form"
variant="contained"
disabled={isLoading}
>
{submitButtonLabel}
</Button>
</div>
<div className="discard_button">
<Button
type="button"
variant="text"
dataCy="cancel-form"
disabled={isLoading}
onClick={() => setOpenDiscardConfirmation(true)}
>
{t("common.discard")}
</Button>
</div>
</div>
<ConfirmationDialog
isOpen={openDiscardConfirmation}
title={t("common.discard")}
info={t("hospital.discardChanges")}
icon={warningIcon}
primaryButtonLabel={t("common.ok")}
secondaryButtonLabel={t("common.discard")}
handlePrimaryButtonClick={handleDiscardConfirmation}
handleSecondaryButtonClick={() => setOpenDiscardConfirmation(false)}
/>
{hospitalStore.updateHospital.status === "FAIL" && (
<div ref={infoBoxRef} className="info-box-container">
<InfoBox type="error" message={errorMessage} />
</div>
)}
<ConfirmationDialog
isOpen={!!hospitalStore.updateHospital.hasSucceeded}
title={t("hospital.updated")}
icon={checkIcon}
info={t("hospital.updateSuccess")}
primaryButtonLabel="Ok"
handlePrimaryButtonClick={() => {
navigate(PATHS.admin);
}}
handleSecondaryButtonClick={() => ({})}
/>
</form>
</div>
);
};

export default HospitalForm;
15 changes: 15 additions & 0 deletions src/components/accessories/admin/hospital/hospitalForm/consts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { HospitalFormFieldName } from ".";
import { HospitalDTO } from "../../../../../generated";
import { TFields } from "../../../../../libraries/formDataHandling/types";

export const getInitialFields: (
hospital: HospitalDTO | undefined
) => TFields<HospitalFormFieldName> = (hospital) => ({
description: { type: "text", value: hospital?.description ?? "" },
address: { type: "text", value: hospital?.address ?? "" },
city: { type: "text", value: hospital?.city ?? "" },
telephone: { type: "text", value: hospital?.telephone ?? "" },
fax: { type: "text", value: hospital?.fax ?? "" },
email: { type: "text", value: hospital?.email ?? "" },
currencyCod: { type: "text", value: hospital?.currencyCod ?? "" },
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./HospitalForm";
export * from "./types";
Loading

0 comments on commit 98d1c48

Please sign in to comment.