Skip to content

Commit

Permalink
App history provider (ohcnetwork#4592)
Browse files Browse the repository at this point in the history
* Implement useHistory and Providers for its API

* Upgrade `PageTitle`'s goBack

* `HistoryAPIProvider` for `AppRouter`

* reset history if sidebar item clicked
  • Loading branch information
rithviknishad authored Jan 23, 2023
1 parent 28deee4 commit b7af79f
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 16 deletions.
7 changes: 6 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useDispatch, useSelector } from "react-redux";
import { getConfig, getCurrentUser } from "./Redux/actions";
import { useAbortableEffect, statusType } from "./Common/utils";
import axios from "axios";
import { HistoryAPIProvider } from "./CAREUI/misc/HistoryAPIProvider";

const Loading = loadable(() => import("./Components/Common/Loading"));

Expand Down Expand Up @@ -68,7 +69,11 @@ const App: React.FC = () => {
}

if (currentUser?.data) {
return <AppRouter />;
return (
<HistoryAPIProvider>
<AppRouter />
</HistoryAPIProvider>
);
} else {
return <SessionRouter />;
}
Expand Down
38 changes: 38 additions & 0 deletions src/CAREUI/misc/HistoryAPIProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useLocationChange } from "raviger";
import { createContext, ReactNode, useState } from "react";

export const HistoryContext = createContext<string[]>([]);
// eslint-disable-next-line @typescript-eslint/no-empty-function
export const ResetHistoryContext = createContext(() => {});

export const HistoryAPIProvider = (props: { children: ReactNode }) => {
const [history, setHistory] = useState<string[]>([]);

useLocationChange(
(newLocation) => {
setHistory((history) => {
if (history.length && newLocation.fullPath === history[0])
// Ignore push if navigate to same path (for some weird unknown reasons?)
return history;

if (history.length > 1 && newLocation.fullPath === history[1])
// Pop current path if navigate back to previous path
return history.slice(1);

// Otherwise just push the current path
return [newLocation.fullPath, ...history];
});
},
{ onInitial: true }
);

const resetHistory = () => setHistory((history) => history.slice(0, 1));

return (
<HistoryContext.Provider value={history}>
<ResetHistoryContext.Provider value={resetHistory}>
{props.children}
</ResetHistoryContext.Provider>
</HistoryContext.Provider>
);
};
26 changes: 26 additions & 0 deletions src/Common/hooks/useAppHistory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { navigate } from "raviger";
import { useContext } from "react";
import {
HistoryContext,
ResetHistoryContext,
} from "../../CAREUI/misc/HistoryAPIProvider";

export default function useAppHistory() {
const history = useContext(HistoryContext);
const resetHistory = useContext(ResetHistoryContext);

const goBack = (fallbackUrl?: string) => {
if (history.length > 1)
// Navigate to history present in the app navigation history stack.
return navigate(history[1]);

if (fallbackUrl)
// Otherwise, use provided fallback url if provided.
return navigate(fallbackUrl);

// Otherwise, fallback to browser's go back behaviour.
window.history.back();
};

return { history, resetHistory, goBack };
}
20 changes: 14 additions & 6 deletions src/Components/Common/PageTitle.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import React, { useEffect, useRef } from "react";
import Breadcrumbs from "./Breadcrumbs";
import PageHeadTitle from "./PageHeadTitle";
import { classNames, goBack } from "../../Utils/utils";
import { classNames } from "../../Utils/utils";
import useAppHistory from "../../Common/hooks/useAppHistory";

interface PageTitleProps {
title: string;
hideBack?: boolean;
backUrl?: string;
backButtonCB?: () => number | void;
className?: string;
componentRight?: React.ReactNode;
/**
* If `false` is returned, prevents from going back.
*/
onBackClick?: () => boolean | void;
justifyContents?:
| "justify-center"
| "justify-start"
Expand All @@ -26,8 +30,8 @@ export default function PageTitle({
title,
hideBack = false,
backUrl,
backButtonCB,
className = "",
onBackClick,
componentRight = <></>,
breadcrumbs = true,
crumbsReplacements = {},
Expand All @@ -42,16 +46,20 @@ export default function PageTitle({
}
}, [divRef, focusOnLoad]);

const onBackButtonClick = () =>
backButtonCB ? goBack(backButtonCB()) : goBack(backUrl);
const { goBack } = useAppHistory();

return (
<div ref={divRef} className={`pt-4 mb-4 ${className}`}>
<PageHeadTitle title={title} />
<div className={classNames("flex items-center", justifyContents)}>
<div className="flex items-center">
{!hideBack && (
<button onClick={onBackButtonClick}>
<button
onClick={() => {
if (onBackClick && onBackClick() === false) return;
goBack(backUrl);
}}
>
<i className="fas fa-chevron-left text-2xl rounded-md p-2 hover:bg-gray-200 mr-1">
{" "}
</i>
Expand Down
4 changes: 3 additions & 1 deletion src/Components/Common/Sidebar/SidebarItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Link } from "raviger";
import { useTranslation } from "react-i18next";
import CareIcon from "../../../CAREUI/icons/CareIcon";
import useAppHistory from "../../../Common/hooks/useAppHistory";

export type SidebarIcon = React.ReactNode;

Expand All @@ -19,6 +20,7 @@ const SidebarItemBase = ({
...props
}: SidebarItemBaseProps) => {
const { t } = useTranslation();
const { resetHistory } = useAppHistory();

return (
<Link
Expand All @@ -31,7 +33,7 @@ const SidebarItemBase = ({
target={external && "_blank"}
rel={external && "noreferrer"}
href={props.to ?? ""}
onClick={props.do}
onClick={props.do ?? resetHistory}
>
<span className={`tooltip-text tooltip-right ${!shrinked && "hidden"}`}>
{t(props.text)}
Expand Down
8 changes: 1 addition & 7 deletions src/Components/Facility/AddBedForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,7 @@ export const AddBedForm = (props: BedFormProps) => {
<div className="px-2 pb-2 max-w-3xl mx-auto">
<PageTitle
title={headerText}
backButtonCB={() => {
navigate(`/facility/${facilityId}/location/${locationId}/beds`, {
replace: true,
});

return 0;
}}
backUrl={`/facility/${facilityId}/location/${locationId}/beds`}
crumbsReplacements={{
[facilityId]: { name: facilityName },
[locationId]: {
Expand Down
3 changes: 2 additions & 1 deletion src/Components/Patient/PatientRegister.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1012,9 +1012,10 @@ export const PatientRegister = (props: PatientRegisterProps) => {
<PageTitle
title={headerText}
className="mb-11"
backButtonCB={() => {
onBackClick={() => {
if (showImport) {
setShowImport(false);
return false;
}
}}
crumbsReplacements={{
Expand Down
3 changes: 3 additions & 0 deletions src/Utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ export const calculateApache2Score = (apacheParams: ApacheParams): number => {
return totalScore;
};

/**
* Deprecated. Use `goBack` from the `useAppHistory` hook instead.
*/
export const goBack = (deltaOrUrl?: string | number | false | void) => {
if (typeof deltaOrUrl === "number") {
window.history.go(-deltaOrUrl);
Expand Down

0 comments on commit b7af79f

Please sign in to comment.