Skip to content

Commit

Permalink
update: Update app state and landing page
Browse files Browse the repository at this point in the history
  • Loading branch information
SteveGT96 committed Dec 4, 2023
1 parent 236fbd0 commit 3728755
Show file tree
Hide file tree
Showing 66 changed files with 10,211 additions and 9,966 deletions.
17,745 changes: 8,928 additions & 8,817 deletions api/oh.yaml

Large diffs are not rendered by default.

322 changes: 161 additions & 161 deletions src/components/activities/loginActivity/LoginActivity.tsx
Original file line number Diff line number Diff line change
@@ -1,161 +1,161 @@
import { FC, useEffect } from "react";
import { InputAdornment } from "@material-ui/core";
import { Link as RouterLink } from "react-router-dom";
import Link from "@material-ui/core/Link";
import { RemoveRedEye } from "@material-ui/icons";
import classNames from "classnames";
import { useFormik } from "formik";
import get from "lodash.get";
import has from "lodash.has";
import { default as React, useState } from "react";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { object, string } from "yup";
import logo from "../../../assets/logo-color.svg";
import { HospitalDTO } from "../../../generated";
import { useAuthentication } from "../../../libraries/authUtils/useAuthentication";
import { setAuthenticationThunk } from "../../../state/main/actions";
import { IState } from "../../../types";
import Button from "../../accessories/button/Button";
import Footer from "../../accessories/footer/Footer";
import TextField from "../../accessories/textField/TextField";
import "./styles.scss";
import { IValues } from "./types";
import { getHospital } from "../../../state/hospital/actions";

const LoginActivity: FC = () => {
useAuthentication();
const { t } = useTranslation();
const dispatch = useDispatch();

const initialValues: IValues = {
username: "",
password: "",
};

const validationSchema = object({
username: string().required(t("login.insertavalidusername")),
password: string().required(t("login.insertthepassword")),
});

const formik = useFormik({
initialValues,
validationSchema,
onSubmit: (values: IValues) => {
dispatch(setAuthenticationThunk(values.username, values.password));
},
});

const [state, setState] = useState({ isPasswordVisible: false });

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) : "";
};
const errorMessage = useSelector<IState>((state) => {
const error = state.main.authentication.error;
return error?.status == 401
? t("errors.incorrectcredentials")
: error?.message ?? t("errors.somethingwrong");
});

const status = useSelector<IState>(
(state) => state.main.authentication.status || "IDLE"
);

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

const hospital = useSelector<IState>(
(state) => state.hospital.getHospital.data
) as HospitalDTO;

return (
<div className="login">
<div className="container login__background">
<img
src={logo}
alt="Open Hospital"
className="login__logo"
width="150px"
/>
<div className="login__title">
{hospital?.description ?? t("login.signin")}
</div>
<div className="login__panel">
<form className="login__panel__form" onSubmit={formik.handleSubmit}>
<div className="login__panel__textField">
<TextField
field={formik.getFieldProps("username")}
theme="regular"
label={t("login.username")}
isValid={isValid("username")}
errorText={getErrorText("username")}
onBlur={formik.handleBlur}
/>
</div>
<div className="login__panel__textField">
<TextField
field={formik.getFieldProps("password")}
theme="regular"
label={t("login.password")}
type={state.isPasswordVisible ? "text" : "password"}
isValid={isValid("password")}
errorText={getErrorText("password")}
onBlur={formik.handleBlur}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<div
className="login__passwordToggler"
onClick={() =>
setState({
isPasswordVisible: !state.isPasswordVisible,
})
}
>
<RemoveRedEye />
</div>
</InputAdornment>
),
}}
/>
</div>
<div
className={classNames("login__invalidCredentials", {
hidden: status !== "FAIL",
})}
>
{errorMessage}
</div>
<div className="login__buttonContainer">
<Button
type="submit"
variant="contained"
color="primary"
disabled={status === "LOADING"}
>
{t("login.login")}
</Button>
</div>
</form>
<div>
<RouterLink to="/forgot">
<Link className="login__panel__resetPassword" component="button">
{t("login.forgotpassword")}
</Link>
</RouterLink>
</div>
&emsp;
</div>
</div>
<Footer />
</div>
);
};

export default LoginActivity;
import { FC, useEffect } from "react";
import { InputAdornment } from "@material-ui/core";
import { Link as RouterLink } from "react-router-dom";
import Link from "@material-ui/core/Link";
import { RemoveRedEye } from "@material-ui/icons";
import classNames from "classnames";
import { useFormik } from "formik";
import get from "lodash.get";
import has from "lodash.has";
import { default as React, useState } from "react";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { object, string } from "yup";
import logo from "../../../assets/logo-color.svg";
import { HospitalDTO } from "../../../generated";
import { useAuthentication } from "../../../libraries/authUtils/useAuthentication";
import { setAuthenticationThunk } from "../../../state/main/actions";
import { IState } from "../../../types";
import Button from "../../accessories/button/Button";
import Footer from "../../accessories/footer/Footer";
import TextField from "../../accessories/textField/TextField";
import "./styles.scss";
import { IValues } from "./types";
import { getHospital } from "../../../state/hospital/actions";

const LoginActivity: FC = () => {
useAuthentication();
const { t } = useTranslation();
const dispatch = useDispatch();

const initialValues: IValues = {
username: "",
password: "",
};

const validationSchema = object({
username: string().required(t("login.insertavalidusername")),
password: string().required(t("login.insertthepassword")),
});

const formik = useFormik({
initialValues,
validationSchema,
onSubmit: (values: IValues) => {
dispatch(setAuthenticationThunk(values.username, values.password));
},
});

const [state, setState] = useState({ isPasswordVisible: false });

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) : "";
};
const errorMessage = useSelector<IState>((state) => {
const error = state.main.authentication.error;
return error?.status == 401
? t("errors.incorrectcredentials")
: error?.message ?? t("errors.somethingwrong");
});

const status = useSelector<IState>(
(state) => state.main.authentication.status || "IDLE"
);

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

const hospital = useSelector<IState>(
(state) => state.hospital.getHospital.data
) as HospitalDTO;

return (
<div className="login">
<div className="container login__background">
<img
src={logo}
alt="Open Hospital"
className="login__logo"
width="150px"
/>
<div className="login__title">
{hospital?.description ?? t("login.signin")}
</div>
<div className="login__panel">
<form className="login__panel__form" onSubmit={formik.handleSubmit}>
<div className="login__panel__textField">
<TextField
field={formik.getFieldProps("username")}
theme="regular"
label={t("login.username")}
isValid={isValid("username")}
errorText={getErrorText("username")}
onBlur={formik.handleBlur}
/>
</div>
<div className="login__panel__textField">
<TextField
field={formik.getFieldProps("password")}
theme="regular"
label={t("login.password")}
type={state.isPasswordVisible ? "text" : "password"}
isValid={isValid("password")}
errorText={getErrorText("password")}
onBlur={formik.handleBlur}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<div
className="login__passwordToggler"
onClick={() =>
setState({
isPasswordVisible: !state.isPasswordVisible,
})
}
>
<RemoveRedEye />
</div>
</InputAdornment>
),
}}
/>
</div>
<div
className={classNames("login__invalidCredentials", {
hidden: status !== "FAIL",
})}
>
{errorMessage}
</div>
<div className="login__buttonContainer">
<Button
type="submit"
variant="contained"
color="primary"
disabled={status === "LOADING"}
>
{t("login.login")}
</Button>
</div>
</form>
<div>
<RouterLink to="/forgot">
<Link className="login__panel__resetPassword" component="button">
{t("login.forgotpassword")}
</Link>
</RouterLink>
</div>
&emsp;
</div>
</div>
<Footer />
</div>
);
};

export default LoginActivity;
62 changes: 34 additions & 28 deletions src/components/activities/loginActivity/RedirectAfterLogin.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
import React, { useMemo } from "react";
import { useSelector } from "react-redux";
import { Navigate, useLocation } from "react-router";
import { useLandingPageRoute } from "../../../libraries/hooks/useLandingPageRoute";
import { TAPIResponseStatus } from "../../../state/types";
import { IState } from "../../../types";
import { IRedirectAfterLogin } from "./types";

export const RedirectAfterLogin: React.FC<IRedirectAfterLogin> = ({
children,
}) => {
const location = useLocation();
const landingPageRoute = useLandingPageRoute();
const to = useMemo(
() => location.state?.from || landingPageRoute,
[landingPageRoute, location]
);

const status = useSelector<IState, TAPIResponseStatus>(
(state) => state.main.authentication.status || "IDLE"
);

if (status === "SUCCESS") {
return <Navigate to={to} />;
}

return <>{children}</>;
};
import React, { useMemo } from "react";
import { useSelector } from "react-redux";
import { Navigate, useLocation } from "react-router";
import { useLandingPageRoute } from "../../../libraries/hooks/useLandingPageRoute";
import { TAPIResponseStatus } from "../../../state/types";
import { IState } from "../../../types";
import { IRedirectAfterLogin } from "./types";

export const RedirectAfterLogin: React.FC<IRedirectAfterLogin> = ({
children,
}) => {
const location = useLocation();
const landingPageRoute = useLandingPageRoute();
const to = useMemo(
() => location.state?.from || landingPageRoute,
[landingPageRoute, location]
);

const state = useSelector<IState, IState>((state) => state);

const status = useMemo(
() =>
["SUCCESS", "FAIL"].includes(state.main.settings.status!)
? state.main.authentication.status!
: state.main.settings.status!,
[state.main.settings.status, state.main.authentication.status]
);

if (status === "SUCCESS") {
return <Navigate to={to} />;
}

return <>{children}</>;
};
Loading

0 comments on commit 3728755

Please sign in to comment.