diff --git a/src/Routers/routes/ResourceRoutes.tsx b/src/Routers/routes/ResourceRoutes.tsx index 547aeb53610..357b7812513 100644 --- a/src/Routers/routes/ResourceRoutes.tsx +++ b/src/Routers/routes/ResourceRoutes.tsx @@ -1,5 +1,4 @@ -import { Redirect } from "raviger"; - +import View from "@/components/Common/View"; import BoardView from "@/components/Resource/ResourceBoard"; import ResourceDetails from "@/components/Resource/ResourceDetails"; import { ResourceDetailsUpdate } from "@/components/Resource/ResourceDetailsUpdate"; @@ -7,13 +6,8 @@ import ListView from "@/components/Resource/ResourceList"; import { AppRoutes } from "@/Routers/AppRouter"; -const getDefaultView = () => - localStorage.getItem("defaultResourceView") === "list" ? "list" : "board"; - const ResourceRoutes: AppRoutes = { - "/resource": () => , - "/resource/board": () => , - "/resource/list": () => , + "/resource": () => , "/resource/:id": ({ id }) => , "/resource/:id/update": ({ id }) => , }; diff --git a/src/Utils/ViewCache.ts b/src/Utils/ViewCache.ts new file mode 100644 index 00000000000..a2c2ed302ef --- /dev/null +++ b/src/Utils/ViewCache.ts @@ -0,0 +1,23 @@ +const getKey = (name: string) => { + return `${name}`; +}; + +/** + * Clears the view preference. + */ +const invalidate = (name: string) => { + localStorage.removeItem(getKey(name)); +}; + +/** + * Clears all the view preferences. + */ +const invalidateAll = () => { + const viewKeys = ["users", "resource", "appointments"]; + viewKeys.forEach(invalidate); +}; + +export default { + invalidate, + invalidateAll, +}; diff --git a/src/Utils/useView.ts b/src/Utils/useView.ts new file mode 100644 index 00000000000..d3f6b0031c3 --- /dev/null +++ b/src/Utils/useView.ts @@ -0,0 +1,26 @@ +import { useEffect, useState } from "react"; + +export function useView( + name: string, + defaultView: string, +): [string, (view: string) => void] { + const [view, setView] = useState(() => { + return localStorage.getItem(name) || defaultView; + }); + const updateView = (newView: string) => { + localStorage.setItem(name, newView); + setView(newView); + }; + useEffect(() => { + const interval = setInterval(() => { + const storedView = localStorage.getItem(name); + if (storedView !== view) { + setView(storedView || defaultView); + } + }, 100); + return () => { + clearInterval(interval); + }; + }, [name, view]); + return [view, updateView]; +} diff --git a/src/components/Auth/Login.tsx b/src/components/Auth/Login.tsx index 9fcd37a55ac..f4432d6c162 100644 --- a/src/components/Auth/Login.tsx +++ b/src/components/Auth/Login.tsx @@ -30,6 +30,7 @@ import BrowserWarning from "@/components/ErrorPages/BrowserWarning"; import { useAuthContext } from "@/hooks/useAuthUser"; import FiltersCache from "@/Utils/FiltersCache"; +import ViewCache from "@/Utils/ViewCache"; import routes from "@/Utils/request/api"; import mutate from "@/Utils/request/mutate"; import request from "@/Utils/request/request"; @@ -242,6 +243,7 @@ const Login = (props: LoginProps) => { const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); + ViewCache.invalidateAll(); const validated = validateData(); if (!validated) return; diff --git a/src/components/Common/View.tsx b/src/components/Common/View.tsx new file mode 100644 index 00000000000..cff36841db5 --- /dev/null +++ b/src/components/Common/View.tsx @@ -0,0 +1,24 @@ +import React, { ComponentType } from "react"; + +import { useView } from "@/Utils/useView"; + +export default function View({ + name, + board, + list, +}: { + name: "resource"; + board: ComponentType; + list: ComponentType; +}) { + const [view] = useView(name, "board"); + + const views: Record<"board" | "list", ComponentType> = { + board, + list, + }; + + const SelectedView = views[view as keyof typeof views] || board; + + return ; +} diff --git a/src/components/Facility/FacilityUsers.tsx b/src/components/Facility/FacilityUsers.tsx index 696e1d06b9b..6d4bb44d74d 100644 --- a/src/components/Facility/FacilityUsers.tsx +++ b/src/components/Facility/FacilityUsers.tsx @@ -1,5 +1,4 @@ import { useQuery } from "@tanstack/react-query"; -import { useState } from "react"; import { useTranslation } from "react-i18next"; import CareIcon from "@/CAREUI/icons/CareIcon"; @@ -17,6 +16,7 @@ import useFilters from "@/hooks/useFilters"; import routes from "@/Utils/request/api"; import query from "@/Utils/request/query"; +import { useView } from "@/Utils/useView"; const UserCardSkeleton = () => (
@@ -121,7 +121,8 @@ export default function FacilityUsers(props: { facilityId: string }) { limit: 15, cacheBlacklist: ["username"], }); - const [activeTab, setActiveTab] = useState<"card" | "list">("card"); + const [activeTab, setActiveTab] = useView("users", "card"); + const { facilityId } = props; let usersList: JSX.Element = <>; @@ -147,7 +148,7 @@ export default function FacilityUsers(props: { facilityId: string }) {
diff --git a/src/components/Resource/ResourceBoard.tsx b/src/components/Resource/ResourceBoard.tsx index 0b903e82829..0ec92836de3 100644 --- a/src/components/Resource/ResourceBoard.tsx +++ b/src/components/Resource/ResourceBoard.tsx @@ -24,6 +24,7 @@ import { RESOURCE_CHOICES } from "@/common/constants"; import routes from "@/Utils/request/api"; import request from "@/Utils/request/request"; +import { useView } from "@/Utils/useView"; import { ResourceRequest } from "@/types/resourceRequest/resourceRequest"; const KanbanBoard = lazy( @@ -36,6 +37,7 @@ const COMPLETED = ["COMPLETED", "REJECTED"]; const ACTIVE = resourceStatusOptions.filter((o) => !COMPLETED.includes(o)); export default function BoardView() { + const [, setView] = useView("resource", "board"); const { qParams, FilterBadges, advancedFilter, updateQuery } = useFilters({ limit: -1, cacheBlacklist: ["title"], @@ -45,11 +47,6 @@ export default function BoardView() { const appliedFilters = formatFilter(qParams); const { t } = useTranslation(); - const onListViewBtnClick = () => { - navigate("/resource/list", { query: qParams }); - localStorage.setItem("defaultResourceView", "list"); - }; - return (
@@ -97,7 +94,7 @@ export default function BoardView() {
- diff --git a/src/pages/Appointments/AppointmentsPage.tsx b/src/pages/Appointments/AppointmentsPage.tsx index 39d3431edb5..bc9a33e7a76 100644 --- a/src/pages/Appointments/AppointmentsPage.tsx +++ b/src/pages/Appointments/AppointmentsPage.tsx @@ -65,6 +65,7 @@ import useAuthUser from "@/hooks/useAuthUser"; import mutate from "@/Utils/request/mutate"; import query from "@/Utils/request/query"; +import { useView } from "@/Utils/useView"; import { dateQueryString, formatDisplayName, @@ -238,7 +239,7 @@ export default function AppointmentsPage(props: { facilityId?: string }) { const facilityId = props.facilityId ?? authUser.home_facility!; - const [viewMode, setViewMode] = useState<"board" | "list">("board"); + const [activeTab, setActiveTab] = useView("appointments", "board"); const schedulableUsersQuery = useQuery({ queryKey: ["schedulable-users", facilityId], @@ -328,8 +329,8 @@ export default function AppointmentsPage(props: { facilityId?: string }) { breadcrumbs={false} options={ setViewMode(value as "board" | "list")} + value={activeTab} + onValueChange={(value) => setActiveTab(value as "board" | "list")} > @@ -637,7 +638,7 @@ export default function AppointmentsPage(props: { facilityId?: string }) {
- {viewMode === "board" ? ( + {activeTab === "board" ? (
{(