From b8b18192622085f1f15c4efe6418d3182dfe970f Mon Sep 17 00:00:00 2001 From: manmeetnagii Date: Sat, 4 Jan 2025 18:07:29 +0530 Subject: [PATCH 1/2] enhanced-resource-page --- public/locale/en.json | 1 + src/Routers/routes/ResourceRoutes.tsx | 12 +- src/components/Kanban/Board.tsx | 25 +- src/components/Resource/ResourcePage.tsx | 434 +++++++++++++++++++++++ 4 files changed, 441 insertions(+), 31 deletions(-) create mode 100644 src/components/Resource/ResourcePage.tsx diff --git a/public/locale/en.json b/public/locale/en.json index 7c9e4e49aca..b7ff848063a 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -1589,6 +1589,7 @@ "select_register_patient": "Select/Register Patient", "select_seven_day_period": "Select a seven day period", "select_skills": "Select and add some skills", + "select_status": "Select Status", "select_time": "Select time", "select_time_slot": "Select time slot", "select_wards": "Select wards", diff --git a/src/Routers/routes/ResourceRoutes.tsx b/src/Routers/routes/ResourceRoutes.tsx index 547aeb53610..5c2577b19d3 100644 --- a/src/Routers/routes/ResourceRoutes.tsx +++ b/src/Routers/routes/ResourceRoutes.tsx @@ -1,19 +1,11 @@ -import { Redirect } from "raviger"; - -import BoardView from "@/components/Resource/ResourceBoard"; import ResourceDetails from "@/components/Resource/ResourceDetails"; import { ResourceDetailsUpdate } from "@/components/Resource/ResourceDetailsUpdate"; -import ListView from "@/components/Resource/ResourceList"; +import ResourcePage from "@/components/Resource/ResourcePage"; 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/components/Kanban/Board.tsx b/src/components/Kanban/Board.tsx index 0023c494609..6f9783016d4 100644 --- a/src/components/Kanban/Board.tsx +++ b/src/components/Kanban/Board.tsx @@ -8,8 +8,6 @@ import { useInfiniteQuery } from "@tanstack/react-query"; import { ReactNode, RefObject, useEffect, useRef } from "react"; import { useTranslation } from "react-i18next"; -import CareIcon from "@/CAREUI/icons/CareIcon"; - import { callApi } from "@/Utils/request/query"; import { QueryRoute } from "@/Utils/request/types"; import { QueryOptions } from "@/Utils/request/useQuery"; @@ -37,25 +35,9 @@ export default function KanbanBoard( const board = useRef(null); return ( -
-
+
+
{props.title}
-
- {[0, 1].map((button, i) => ( - - ))} -
@@ -152,7 +134,7 @@ export function KanbanSection(
{ const target = e.target as HTMLDivElement; if ( @@ -184,6 +166,7 @@ export function KanbanSection( )} ))} + {provided.placeholder} {isFetchingNextPage && (
diff --git a/src/components/Resource/ResourcePage.tsx b/src/components/Resource/ResourcePage.tsx new file mode 100644 index 00000000000..007d47083d4 --- /dev/null +++ b/src/components/Resource/ResourcePage.tsx @@ -0,0 +1,434 @@ +import { Link, navigate } from "raviger"; +import { Suspense, lazy, useState } from "react"; +import { useTranslation } from "react-i18next"; + +import Chip from "@/CAREUI/display/Chip"; +import CareIcon from "@/CAREUI/icons/CareIcon"; + +import { Button } from "@/components/ui/button"; + +import { ExportButton } from "@/components/Common/Export"; +import Loading from "@/components/Common/Loading"; +import type { KanbanBoardType } from "@/components/Kanban/Board"; +import BadgesList from "@/components/Resource/ResourceBadges"; +import ResourceBlock from "@/components/Resource/ResourceBlock"; +import { formatFilter } from "@/components/Resource/ResourceCommons"; +import ListFilter from "@/components/Resource/ResourceFilter"; + +import useFilters from "@/hooks/useFilters"; + +import { RESOURCE_CHOICES } from "@/common/constants"; + +import routes from "@/Utils/request/api"; +import request from "@/Utils/request/request"; +import useTanStackQueryInstead from "@/Utils/request/useQuery"; +import { formatDateTime } from "@/Utils/utils"; +import { ResourceRequest } from "@/types/resourceRequest/resourceRequest"; + +import Page from "../Common/Page"; +import { Input } from "../ui/input"; +import { Label } from "../ui/label"; +import { ScrollArea, ScrollBar } from "../ui/scroll-area"; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectTrigger, + SelectValue, +} from "../ui/select"; +import { Tabs, TabsList, TabsTrigger } from "../ui/tabs"; + +const KanbanBoard = lazy( + () => import("@/components/Kanban/Board"), +) as KanbanBoardType; + +const resourceStatusOptions = RESOURCE_CHOICES.map((obj) => obj.text); + +const COMPLETED = ["COMPLETED", "REJECTED"]; +const ACTIVE = resourceStatusOptions.filter((o) => !COMPLETED.includes(o)); + +const ResourcePage = () => { + const { + qParams, + Pagination, + FilterBadges, + advancedFilter, + resultsPerPage, + updateQuery, + } = useFilters({ + limit: 12, + cacheBlacklist: ["title"], + }); + const [boardFilter, setBoardFilter] = useState(ACTIVE); + // eslint-disable-next-line + const appliedFilters = formatFilter(qParams); + const [viewMode, setViewMode] = useState<"board" | "list">("board"); + const { loading, data, refetch } = useTanStackQueryInstead( + routes.listResourceRequests, + { + query: formatFilter({ + ...qParams, + limit: resultsPerPage, + offset: (qParams.page ? qParams.page - 1 : 0) * resultsPerPage, + }), + }, + ); + const { t } = useTranslation(); + + const showResourceCardList = (data: ResourceRequest[]) => { + if (data && !data.length) { + return ( +
+ {t("no_results_found")} +
+ ); + } + + return data.map((resource: ResourceRequest, i) => ( +
+
+
+
{resource.title}
+
+ +
+
+
+ +
+ {resource.category || ""} +
+ +
+
+ +
+
+ {resource.status === "TRANSPORTATION TO BE ARRANGED" ? ( +
+ +
+ ) : ( +
+ +
+ )} + +
+ {resource.emergency && ( + + {t("emergency")} + + )} +
+
+ +
+
+ +
+ {formatDateTime(resource.modified_date) || "--"} +
+ +
+
+ +
+
+ +
+ {resource.origin_facility?.name} +
+ + +
+ +
+ {resource.approving_facility?.name} +
+ + +
+ +
+ {resource.assigned_facility?.name || t("yet_to_be_decided")} +
+ +
+
+ + {t("all_details")} + +
+
+
+ )); + }; + + return ( + +
+
+ + setViewMode(value as "board" | "list") + } + > + + + + {t("board")} + + + + {t("list")} + + + +
+ +
+ + } + > + {viewMode === "board" ? ( + <> +
+
+
+ + + +
+
+
+ updateQuery({ title: e.target.value })} + /> + +
+
+ + }> + + + title={} + sections={boardFilter.map((board) => ({ + id: board, + title: ( +

+ {board}{" "} + { + const { data } = await request( + routes.downloadResourceRequests, + { + query: { + ...formatFilter({ ...qParams, status: board }), + csv: true, + }, + }, + ); + return data ?? null; + }} + filenamePrefix={`resource_requests_${board}`} + /> +

+ ), + fetchOptions: (id) => ({ + route: routes.listResourceRequests, + options: { + query: formatFilter({ + ...qParams, + status: id, + }), + }, + }), + }))} + onDragEnd={(result) => { + if ( + result.source.droppableId !== + result.destination?.droppableId + ) + navigate( + `/resource/${result.draggableId}/update?status=${result.destination?.droppableId}`, + ); + }} + itemRender={(resource) => } + /> + +
+
+ + + ) : ( + <> +
+
+ updateQuery({ title: e.target.value })} + /> + +
+
+ + {loading ? ( + + ) : ( +
+
+ + + +
+ +
+
+ {t("resource")} +
+
+ {t("LOG_UPDATE_FIELD_LABEL__patient_category")} +
+
+ {t("consent__status")} +
+
+ {t("facilities")} +
+
+ {t("LOG_UPDATE_FIELD_LABEL__action")} +
+
+
{showResourceCardList(data?.results || [])}
+
+ +
+
+ )} + + + + )} +
+ ); +}; + +export default ResourcePage; From 88597fee69158dab3879654f4671a15b5e90076e Mon Sep 17 00:00:00 2001 From: manmeetnagii Date: Sun, 5 Jan 2025 20:04:41 +0530 Subject: [PATCH 2/2] enhanced-resource-page --- src/components/Resource/ResourceBoard.tsx | 162 ----------- src/components/Resource/ResourceCardList.tsx | 137 +++++++++ src/components/Resource/ResourceList.tsx | 283 ------------------- src/components/Resource/ResourcePage.tsx | 164 ++--------- 4 files changed, 153 insertions(+), 593 deletions(-) delete mode 100644 src/components/Resource/ResourceBoard.tsx create mode 100644 src/components/Resource/ResourceCardList.tsx delete mode 100644 src/components/Resource/ResourceList.tsx diff --git a/src/components/Resource/ResourceBoard.tsx b/src/components/Resource/ResourceBoard.tsx deleted file mode 100644 index 0b903e82829..00000000000 --- a/src/components/Resource/ResourceBoard.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import { navigate } from "raviger"; -import { Suspense, lazy, useState } from "react"; -import { useTranslation } from "react-i18next"; - -import CareIcon from "@/CAREUI/icons/CareIcon"; -import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover"; - -import { Button } from "@/components/ui/button"; - -import { ExportButton } from "@/components/Common/Export"; -import Loading from "@/components/Common/Loading"; -import PageTitle from "@/components/Common/PageTitle"; -import Tabs from "@/components/Common/Tabs"; -import SearchInput from "@/components/Form/SearchInput"; -import type { KanbanBoardType } from "@/components/Kanban/Board"; -import BadgesList from "@/components/Resource/ResourceBadges"; -import ResourceBlock from "@/components/Resource/ResourceBlock"; -import { formatFilter } from "@/components/Resource/ResourceCommons"; -import ListFilter from "@/components/Resource/ResourceFilter"; - -import useFilters from "@/hooks/useFilters"; - -import { RESOURCE_CHOICES } from "@/common/constants"; - -import routes from "@/Utils/request/api"; -import request from "@/Utils/request/request"; -import { ResourceRequest } from "@/types/resourceRequest/resourceRequest"; - -const KanbanBoard = lazy( - () => import("@/components/Kanban/Board"), -) as KanbanBoardType; - -const resourceStatusOptions = RESOURCE_CHOICES.map((obj) => obj.text); - -const COMPLETED = ["COMPLETED", "REJECTED"]; -const ACTIVE = resourceStatusOptions.filter((o) => !COMPLETED.includes(o)); - -export default function BoardView() { - const { qParams, FilterBadges, advancedFilter, updateQuery } = useFilters({ - limit: -1, - cacheBlacklist: ["title"], - }); - const [boardFilter, setBoardFilter] = useState(ACTIVE); - // eslint-disable-next-line - const appliedFilters = formatFilter(qParams); - const { t } = useTranslation(); - - const onListViewBtnClick = () => { - navigate("/resource/list", { query: qParams }); - localStorage.setItem("defaultResourceView", "list"); - }; - - return ( -
-
-
- { - const { data } = await request( - routes.downloadResourceRequests, - { - query: { ...appliedFilters, csv: true }, - }, - ); - return data ?? null; - }} - filenamePrefix="resource_requests" - /> - } - breadcrumbs={false} - /> -
- -
- updateQuery({ [e.name]: e.value })} - placeholder={t("search_resource")} - className="w-full md:w-60" - /> - setBoardFilter(tab ? COMPLETED : ACTIVE)} - currentTab={boardFilter !== ACTIVE ? 1 : 0} - /> -
- - advancedFilter.setShow(true)} - /> -
-
-
- }> - - title={} - sections={boardFilter.map((board) => ({ - id: board, - title: ( -

- {board}{" "} - { - const { data } = await request( - routes.downloadResourceRequests, - { - query: { - ...formatFilter({ ...qParams, status: board }), - csv: true, - }, - }, - ); - return data ?? null; - }} - filenamePrefix={`resource_requests_${board}`} - /> -

- ), - fetchOptions: (id) => ({ - route: routes.listResourceRequests, - options: { - query: formatFilter({ - ...qParams, - status: id, - }), - }, - }), - }))} - onDragEnd={(result) => { - if (result.source.droppableId !== result.destination?.droppableId) - navigate( - `/resource/${result.draggableId}/update?status=${result.destination?.droppableId}`, - ); - }} - itemRender={(resource) => } - /> -
- - -
- ); -} diff --git a/src/components/Resource/ResourceCardList.tsx b/src/components/Resource/ResourceCardList.tsx new file mode 100644 index 00000000000..02ab4fef8eb --- /dev/null +++ b/src/components/Resource/ResourceCardList.tsx @@ -0,0 +1,137 @@ +import { Link } from "raviger"; +import { useTranslation } from "react-i18next"; + +import Chip from "@/CAREUI/display/Chip"; +import CareIcon from "@/CAREUI/icons/CareIcon"; + +import { formatDateTime } from "@/Utils/utils"; +import { ResourceRequest } from "@/types/resourceRequest/resourceRequest"; + +interface ResourceCardListProps { + data: ResourceRequest[]; +} + +const ResourceCardList = ({ data }: ResourceCardListProps) => { + const { t } = useTranslation(); + + if (data && !data.length) { + return ( +
+ {t("no_results_found")} +
+ ); + } + + return data.map((resource: ResourceRequest, i) => ( +
+
+
+
{resource.title}
+
+ +
+
+ {resource.status === "TRANSPORTATION TO BE ARRANGED" ? ( +
+ +
+ ) : ( +
+ +
+ )} + +
+ {resource.emergency && ( + + {t("emergency")} + + )} +
+
+ +
+
+ +
+ {formatDateTime(resource.modified_date) || "--"} +
+ +
+
+ +
+
+ +
+ {resource.origin_facility?.name} +
+ + +
+ +
+ {resource.approving_facility?.name} +
+ + +
+ +
+ {resource.assigned_facility?.name || t("yet_to_be_decided")} +
+ +
+
+ + {t("all_details")} + +
+
+
+ )); +}; + +export default ResourceCardList; diff --git a/src/components/Resource/ResourceList.tsx b/src/components/Resource/ResourceList.tsx deleted file mode 100644 index f2f663184c8..00000000000 --- a/src/components/Resource/ResourceList.tsx +++ /dev/null @@ -1,283 +0,0 @@ -import { Link, navigate } from "raviger"; -import { useTranslation } from "react-i18next"; - -import Chip from "@/CAREUI/display/Chip"; -import CareIcon from "@/CAREUI/icons/CareIcon"; -import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover"; - -import { Button } from "@/components/ui/button"; - -import { ExportButton } from "@/components/Common/Export"; -import Loading from "@/components/Common/Loading"; -import Page from "@/components/Common/Page"; -import SearchInput from "@/components/Form/SearchInput"; -import BadgesList from "@/components/Resource/ResourceBadges"; -import { formatFilter } from "@/components/Resource/ResourceCommons"; -import ListFilter from "@/components/Resource/ResourceFilter"; - -import useFilters from "@/hooks/useFilters"; - -import routes from "@/Utils/request/api"; -import request from "@/Utils/request/request"; -import useTanStackQueryInstead from "@/Utils/request/useQuery"; -import { formatDateTime } from "@/Utils/utils"; -import { ResourceRequest } from "@/types/resourceRequest/resourceRequest"; - -export default function ListView() { - const { - qParams, - Pagination, - FilterBadges, - advancedFilter, - resultsPerPage, - updateQuery, - } = useFilters({ cacheBlacklist: ["title"], limit: 12 }); - - const { t } = useTranslation(); - - const onBoardViewBtnClick = () => { - navigate("/resource/board", { query: qParams }); - localStorage.setItem("defaultResourceView", "board"); - }; - const appliedFilters = formatFilter(qParams); - - const { loading, data, refetch } = useTanStackQueryInstead( - routes.listResourceRequests, - { - query: formatFilter({ - ...qParams, - limit: resultsPerPage, - offset: (qParams.page ? qParams.page - 1 : 0) * resultsPerPage, - }), - }, - ); - - const showResourceCardList = (data: ResourceRequest[]) => { - if (data && !data.length) { - return ( -
- {t("no_results_found")} -
- ); - } - - return data.map((resource: ResourceRequest, i) => ( -
-
-
-
{resource.title}
-
- -
-
-
- -
- {resource.category || ""} -
- -
-
- -
-
- {resource.status === "TRANSPORTATION TO BE ARRANGED" ? ( -
- -
- ) : ( -
- -
- )} - -
- {resource.emergency && ( - - {t("emergency")} - - )} -
-
- -
-
- -
- {formatDateTime(resource.modified_date) || "--"} -
- -
-
- -
-
- -
- {resource.origin_facility?.name} -
- - -
- -
- {resource.approving_facility?.name} -
- - -
- -
- {resource.assigned_facility?.name || t("yet_to_be_decided")} -
- -
-
- - {t("all_details")} - -
-
-
- )); - }; - - return ( - { - const { data } = await request(routes.downloadResourceRequests, { - query: { ...appliedFilters, csv: true }, - }); - return data ?? null; - }} - filenamePrefix="resource_requests" - /> - } - breadcrumbs={false} - options={ - <> -
-
- updateQuery({ [e.name]: e.value })} - placeholder={t("search_resource")} - /> -
- -
- - advancedFilter.setShow(true)} - /> -
- - } - > - - -
- {loading ? ( - - ) : ( -
-
- -
-
-
- {t("resource")} -
-
- {t("LOG_UPDATE_FIELD_LABEL__patient_category")} -
-
- {t("consent__status")} -
-
- {t("facilities")} -
-
- {t("LOG_UPDATE_FIELD_LABEL__action")} -
-
-
{showResourceCardList(data?.results || [])}
-
- -
-
- )} -
- -
- ); -} diff --git a/src/components/Resource/ResourcePage.tsx b/src/components/Resource/ResourcePage.tsx index 007d47083d4..8328278dc78 100644 --- a/src/components/Resource/ResourcePage.tsx +++ b/src/components/Resource/ResourcePage.tsx @@ -1,8 +1,7 @@ -import { Link, navigate } from "raviger"; +import { navigate } from "raviger"; import { Suspense, lazy, useState } from "react"; import { useTranslation } from "react-i18next"; -import Chip from "@/CAREUI/display/Chip"; import CareIcon from "@/CAREUI/icons/CareIcon"; import { Button } from "@/components/ui/button"; @@ -15,6 +14,7 @@ import ResourceBlock from "@/components/Resource/ResourceBlock"; import { formatFilter } from "@/components/Resource/ResourceCommons"; import ListFilter from "@/components/Resource/ResourceFilter"; +import useExport from "@/hooks/useExport"; import useFilters from "@/hooks/useFilters"; import { RESOURCE_CHOICES } from "@/common/constants"; @@ -22,7 +22,6 @@ import { RESOURCE_CHOICES } from "@/common/constants"; import routes from "@/Utils/request/api"; import request from "@/Utils/request/request"; import useTanStackQueryInstead from "@/Utils/request/useQuery"; -import { formatDateTime } from "@/Utils/utils"; import { ResourceRequest } from "@/types/resourceRequest/resourceRequest"; import Page from "../Common/Page"; @@ -38,6 +37,7 @@ import { SelectValue, } from "../ui/select"; import { Tabs, TabsList, TabsTrigger } from "../ui/tabs"; +import ResourceCardList from "./ResourceCardList"; const KanbanBoard = lazy( () => import("@/components/Kanban/Board"), @@ -64,6 +64,7 @@ const ResourcePage = () => { // eslint-disable-next-line const appliedFilters = formatFilter(qParams); const [viewMode, setViewMode] = useState<"board" | "list">("board"); + const { exportFile } = useExport(); const { loading, data, refetch } = useTanStackQueryInstead( routes.listResourceRequests, { @@ -74,143 +75,16 @@ const ResourcePage = () => { }), }, ); - const { t } = useTranslation(); - - const showResourceCardList = (data: ResourceRequest[]) => { - if (data && !data.length) { - return ( -
- {t("no_results_found")} -
- ); - } - - return data.map((resource: ResourceRequest, i) => ( -
-
-
-
{resource.title}
-
- -
-
-
- -
- {resource.category || ""} -
- -
-
-
-
- {resource.status === "TRANSPORTATION TO BE ARRANGED" ? ( -
- -
- ) : ( -
- -
- )} - -
- {resource.emergency && ( - - {t("emergency")} - - )} -
-
- -
-
- -
- {formatDateTime(resource.modified_date) || "--"} -
- -
-
- -
-
- -
- {resource.origin_facility?.name} -
- - -
- -
- {resource.approving_facility?.name} -
- - -
- -
- {resource.assigned_facility?.name || t("yet_to_be_decided")} -
- -
-
- - {t("all_details")} - -
-
-
- )); + const exportAction = async () => { + const { data } = await request(routes.downloadResourceRequests, { + query: { ...appliedFilters, csv: true }, + }); + return data ?? null; }; + const { t } = useTranslation(); + return ( {
@@ -413,7 +281,7 @@ const ResourcePage = () => { {t("LOG_UPDATE_FIELD_LABEL__action")}
-
{showResourceCardList(data?.results || [])}
+