+
+
+
diff --git a/src/pages/Facility/settings/devices/DeviceLocationHistory.tsx b/src/pages/Facility/settings/devices/DeviceLocationHistory.tsx
new file mode 100644
index 00000000000..60367aa2dff
--- /dev/null
+++ b/src/pages/Facility/settings/devices/DeviceLocationHistory.tsx
@@ -0,0 +1,100 @@
+import { useQuery } from "@tanstack/react-query";
+import { useQueryParams } from "raviger";
+import { useTranslation } from "react-i18next";
+
+import { cn } from "@/lib/utils";
+
+import Page from "@/components/Common/Page";
+import PaginationComponent from "@/components/Common/Pagination";
+import { CardListSkeleton } from "@/components/Common/SkeletonLoading";
+
+import { RESULTS_PER_PAGE_LIMIT } from "@/common/constants";
+
+import query from "@/Utils/request/query";
+import { DeviceLocationCard } from "@/pages/Facility/settings/devices/components/DeviceLocationCard";
+import deviceApi from "@/types/device/deviceApi";
+
+interface Props {
+ facilityId: string;
+ deviceId: string;
+}
+
+const DeviceLocationHistory = ({ facilityId, deviceId }: Props) => {
+ const { t } = useTranslation();
+
+ const [qParams, setQueryParams] = useQueryParams<{ page?: number }>();
+
+ const { data: locationsData, isLoading } = useQuery({
+ queryKey: ["deviceLocationHistory", facilityId, deviceId, qParams],
+ queryFn: query(deviceApi.locationHistory, {
+ queryParams: {
+ limit: RESULTS_PER_PAGE_LIMIT,
+ offset: ((qParams.page ?? 1) - 1) * RESULTS_PER_PAGE_LIMIT,
+ },
+ pathParams: {
+ facilityId,
+ id: deviceId,
+ },
+ }),
+ });
+
+ return (
+
+
+ {isLoading ? (
+
+ ) : (
+
+ {locationsData?.results?.length === 0 ? (
+
+
+
+
+
+ {t("no_locations_found")}
+
+
+
+
+
+ ) : (
+
+ {locationsData?.results?.map((locationData) => (
+ -
+
+
+ ))}
+
+
RESULTS_PER_PAGE_LIMIT
+ ? "visible"
+ : "invisible",
+ )}
+ >
+
setQueryParams({ page })}
+ />
+
+
+
+ )}
+
+ )}
+
+
+ );
+};
+
+export default DeviceLocationHistory;
diff --git a/src/pages/Facility/settings/devices/components/AssociateLocationSheet.tsx b/src/pages/Facility/settings/devices/components/AssociateLocationSheet.tsx
index 86b1c8c0761..046f4a47015 100644
--- a/src/pages/Facility/settings/devices/components/AssociateLocationSheet.tsx
+++ b/src/pages/Facility/settings/devices/components/AssociateLocationSheet.tsx
@@ -46,6 +46,9 @@ export default function AssociateLocationSheet({
queryClient.invalidateQueries({
queryKey: ["device", facilityId, deviceId],
});
+ queryClient.invalidateQueries({
+ queryKey: ["deviceLocationHistory", facilityId, deviceId],
+ });
toast.success(t("location_associated_successfully"));
onOpenChange(false);
setSelectedLocation(null);
diff --git a/src/pages/Facility/settings/devices/components/DeviceLocationCard.tsx b/src/pages/Facility/settings/devices/components/DeviceLocationCard.tsx
new file mode 100644
index 00000000000..b7b1abecbd6
--- /dev/null
+++ b/src/pages/Facility/settings/devices/components/DeviceLocationCard.tsx
@@ -0,0 +1,81 @@
+import { t } from "i18next";
+import { Link } from "raviger";
+
+import CareIcon from "@/CAREUI/icons/CareIcon";
+
+import { Badge } from "@/components/ui/badge";
+import { Card, CardContent } from "@/components/ui/card";
+
+import { formatDateTime } from "@/Utils/utils";
+import { DeviceLocationHistory } from "@/types/device/device";
+
+interface LocationCardProps {
+ locationData: DeviceLocationHistory;
+}
+
+export const DeviceLocationCard = ({ locationData }: LocationCardProps) => {
+ const { start, end, location, created_by } = locationData;
+
+ return (
+
+
+
+
+
+ {location.name}
+
+
+
+
+
+
+
{t("locations")}
+
+ {t(`location_form__${location?.form}`)}
+
+
+ {location?.status}
+
+
+
+
+
+
{t("associated_by")}
+
+ {`${created_by.first_name} ${created_by.last_name}`}
+
+
+
+
+
+ {t("association_start_date")}
+
+
+ {start ? formatDateTime(start) : t("not_started")}
+
+
+
+ {
+
+
+ {t("association_end_date")}
+
+
+ {end ? formatDateTime(end) : "-"}
+
+
+ }
+
+
+
+ );
+};
diff --git a/src/pages/Facility/settings/layout.tsx b/src/pages/Facility/settings/layout.tsx
index 6d256ec4cff..c92dec3537d 100644
--- a/src/pages/Facility/settings/layout.tsx
+++ b/src/pages/Facility/settings/layout.tsx
@@ -8,6 +8,7 @@ import ErrorPage from "@/components/ErrorPages/DefaultErrorPage";
import CreateDevice from "@/pages/Facility/settings/devices/CreateDevice";
import DeviceDetail from "@/pages/Facility/settings/devices/DeviceDetail";
+import DeviceLocationHistory from "@/pages/Facility/settings/devices/DeviceLocationHistory";
import DevicesList from "@/pages/Facility/settings/devices/DevicesList";
import UpdateDevice from "@/pages/Facility/settings/devices/UpdateDevice";
@@ -43,6 +44,9 @@ const getRoutes = (facilityId: string) => ({
"/devices/:id/edit": ({ id }: { id: string }) => (
),
+ "/devices/:id/locationHistory": ({ id }: { id: string }) => (
+
+ ),
"*": () =>
,
});
diff --git a/src/types/device/device.ts b/src/types/device/device.ts
index 60ec9aa9ff8..6c24e9a7e39 100644
--- a/src/types/device/device.ts
+++ b/src/types/device/device.ts
@@ -50,4 +50,12 @@ export interface DeviceList extends DeviceBase {
id: string;
}
+export interface DeviceLocationHistory {
+ id: string;
+ created_by: UserBase;
+ location: LocationList;
+ start: string;
+ end: string;
+}
+
export type DeviceWrite = DeviceBase;
diff --git a/src/types/device/deviceApi.ts b/src/types/device/deviceApi.ts
index 929c13a25a6..330460bf923 100644
--- a/src/types/device/deviceApi.ts
+++ b/src/types/device/deviceApi.ts
@@ -1,7 +1,12 @@
import { HttpMethod, Type } from "@/Utils/request/api";
import { PaginatedResponse } from "@/Utils/request/types";
-import { DeviceDetail, DeviceList, DeviceWrite } from "./device";
+import {
+ DeviceDetail,
+ DeviceList,
+ DeviceLocationHistory,
+ DeviceWrite,
+} from "./device";
export default {
list: {
@@ -44,4 +49,9 @@ export default {
TRes: Type
(),
TBody: Type<{ location: string }>(),
},
+ locationHistory: {
+ path: "/api/v1/facility/{facilityId}/device/{id}/location_history/",
+ method: HttpMethod.GET,
+ TRes: Type>(),
+ },
};