diff --git a/cypress/e2e/assets_spec/asset_homepage.cy.ts b/cypress/e2e/assets_spec/asset_homepage.cy.ts index e1fcf278442..61f7d8a52c0 100644 --- a/cypress/e2e/assets_spec/asset_homepage.cy.ts +++ b/cypress/e2e/assets_spec/asset_homepage.cy.ts @@ -90,7 +90,7 @@ describe("Asset Tab", () => { assetPage.selectImportOption(); assetPage.selectImportFacility("Dummy Facility 1"); assetPage.importAssetFile(); - assetPage.selectImportLocation("Camera Loc"); + assetPage.selectImportLocation("Camera Locations"); assetPage.clickImportAsset(); }); diff --git a/src/Components/Assets/AssetFilter.tsx b/src/Components/Assets/AssetFilter.tsx index 4dca7dfecdb..8b250088d1a 100644 --- a/src/Components/Assets/AssetFilter.tsx +++ b/src/Components/Assets/AssetFilter.tsx @@ -1,19 +1,14 @@ import { useState, useEffect, useCallback } from "react"; -import { useAbortableEffect, statusType } from "../../Common/utils"; import { navigate, useQueryParams } from "raviger"; import { FacilitySelect } from "../Common/FacilitySelect"; import { FacilityModel } from "../Facility/models"; -import { useDispatch } from "react-redux"; -import { - getFacilityAssetLocation, - getPermittedFacility, -} from "../../Redux/actions"; -import * as Notification from "../../Utils/Notifications.js"; import { LocationSelect } from "../Common/LocationSelect"; import { AssetClass, AssetLocationObject } from "./AssetTypes"; import { FieldLabel } from "../Form/FormFields/FormField"; import { SelectFormField } from "../Form/FormFields/SelectFormField"; import FiltersSlideover from "../../CAREUI/interactive/FiltersSlideover"; +import routes from "../../Redux/api"; +import useQuery from "../../Utils/request/useQuery"; import DateRangeFormField from "../Form/FormFields/DateRangeFormField"; import dayjs from "dayjs"; import { FieldChangeEvent } from "../Form/FormFields/Utils"; @@ -35,7 +30,6 @@ const getDate = (value: any) => function AssetFilter(props: any) { const { filter, onChange, closeFilter } = props; - const dispatch: any = useDispatch(); const [facility, setFacility] = useState({ name: "" }); const [location, setLocation] = useState(initialLocation); @@ -46,7 +40,7 @@ function AssetFilter(props: any) { const [asset_class, setAssetClass] = useState( filter.asset_class || "" ); - const [facilityId, setFacilityId] = useState(filter.facility); + const [facilityId, setFacilityId] = useState(filter.facility); const [locationId, setLocationId] = useState(filter.location); const [warrantyExpiry, setWarrantyExpiry] = useState({ before: filter.warranty_amc_end_of_validity_before || null, @@ -54,8 +48,31 @@ function AssetFilter(props: any) { }); const [qParams, _] = useQueryParams(); + useQuery(routes.getPermittedFacility, { + pathParams: { id: facilityId }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data) { + setFacility(data); + } + }, + prefetch: !!facilityId, + }); + + useQuery(routes.getFacilityAssetLocation, { + pathParams: { + facilityId: String(facilityId), + locationId: String(locationId), + }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data) { + setLocation(data); + } + }, + prefetch: !!(facilityId && locationId), + }); + useEffect(() => { - setFacilityId(facility?.id ? facility?.id : ""); + setFacilityId(facility?.id ? `${facility?.id}` : ""); setLocationId( facility?.id === qParams.facility ? qParams.location ?? "" : "" ); @@ -75,48 +92,6 @@ function AssetFilter(props: any) { else navigate("/assets"); }, [qParams]); - const fetchFacility = useCallback( - async (status: statusType) => { - if (facilityId) { - const facilityData: any = await dispatch( - getPermittedFacility(facilityId) - ); - if (!status.aborted) { - setFacility(facilityData?.data); - } - } - }, - [filter.facility] - ); - - const fetchLocation = useCallback( - async (status: statusType) => { - if (locationId && facilityId) { - const [locationData]: any = await Promise.all([ - dispatch( - getFacilityAssetLocation(String(facilityId), String(locationId)) - ), - ]); - if (!status.aborted && locationData !== undefined) { - if (!locationData.data) - Notification.Error({ - msg: "Something went wrong..!", - }); - else { - setLocation(locationData.data); - } - } - } else { - setLocation(initialLocation); - } - }, - [filter.location] - ); - - useAbortableEffect((status: statusType) => { - filter.facility && fetchFacility(status); - filter.location && fetchLocation(status); - }, []); const applyFilter = () => { const data = { facility: facilityId, diff --git a/src/Components/Assets/AssetImportModal.tsx b/src/Components/Assets/AssetImportModal.tsx index 54ac25e2ac8..f8ab7cbc65f 100644 --- a/src/Components/Assets/AssetImportModal.tsx +++ b/src/Components/Assets/AssetImportModal.tsx @@ -5,8 +5,6 @@ import { FacilityModel } from "../Facility/models"; import { AssetData } from "./AssetTypes"; import * as Notification from "../../Utils/Notifications.js"; import { Cancel, Submit } from "../Common/components/ButtonV2"; -import { listFacilityAssetLocation } from "../../Redux/actions"; -import { useDispatch } from "react-redux"; import { Link } from "raviger"; import readXlsxFile from "read-excel-file"; import { @@ -16,6 +14,8 @@ import { import { parseCsvFile } from "../../Utils/utils"; import useConfig from "../../Common/hooks/useConfig"; import DialogModal from "../Common/Dialog"; +import useQuery from "../../Utils/request/useQuery"; +import routes from "../../Redux/api"; import { SelectFormField } from "../Form/FormFields/SelectFormField"; interface Props { @@ -34,7 +34,6 @@ const AssetImportModal = ({ open, onClose, facility }: Props) => { location: "", }); const [locations, setLocations] = useState([]); - const dispatchAction: any = useDispatch(); const { sample_format_asset_import } = useConfig(); const [locationsLoading, setLocationsLoading] = useState(false); @@ -43,18 +42,14 @@ const AssetImportModal = ({ open, onClose, facility }: Props) => { setSelectedFile(undefined); onClose && onClose(); }; - - useEffect(() => { - setLocationsLoading(true); - dispatchAction( - listFacilityAssetLocation({}, { facility_external_id: facility.id }) - ).then(({ data }: any) => { - setLocationsLoading(false); - if (data.count > 0) { + useQuery(routes.listFacilityAssetLocation, { + pathParams: { facility_external_id: `${facility.id}` }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data) { setLocations(data.results); } - }); - }, []); + }, + }); useEffect(() => { const readFile = async () => { @@ -362,6 +357,7 @@ const AssetImportModal = ({ open, onClose, facility }: Props) => { {isImporting ? ( diff --git a/src/Components/Assets/AssetManage.tsx b/src/Components/Assets/AssetManage.tsx index e6d1836e27b..23098bff22f 100644 --- a/src/Components/Assets/AssetManage.tsx +++ b/src/Components/Assets/AssetManage.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback, useEffect, ReactElement, lazy } from "react"; +import { useState, useEffect, ReactElement, lazy } from "react"; import { AssetClass, assetClassProps, @@ -6,14 +6,6 @@ import { AssetService, AssetTransaction, } from "./AssetTypes"; -import { statusType, useAbortableEffect } from "../../Common/utils"; -import { useDispatch } from "react-redux"; -import { - deleteAsset, - getAsset, - listAssetService, - listAssetTransaction, -} from "../../Redux/actions"; import Pagination from "../Common/Pagination"; import { navigate } from "raviger"; import QRCode from "qrcode.react"; @@ -36,6 +28,9 @@ import RelativeDateUserMention from "../Common/RelativeDateUserMention"; import { AssetServiceEditModal } from "./AssetServiceEditModal"; import { warrantyAmcValidityChip } from "./AssetsList"; import Page from "../Common/components/Page"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; +import useQuery from "../../Utils/request/useQuery"; interface AssetManageProps { assetId: string; @@ -51,80 +46,60 @@ const checkAuthority = (type: string, cutoff: string) => { const AssetManage = (props: AssetManageProps) => { const { t } = useTranslation(); const { assetId, facilityId } = props; - const [asset, setAsset] = useState(); const [isPrintMode, setIsPrintMode] = useState(false); const [currentPage, setCurrentPage] = useState(1); const [offset, setOffset] = useState(0); const [totalCount, setTotalCount] = useState(0); - const [transactions, setTransactions] = useState([]); const [transactionDetails, setTransactionDetails] = useState< ReactElement | ReactElement[] >(); - const [services, setServices] = useState([]); const [servicesDetails, setServiceDetails] = useState< ReactElement | ReactElement[] >(); - const [isLoading, setIsLoading] = useState(false); - const dispatch = useDispatch(); const limit = 14; const authUser = useAuthUser(); const [showDeleteDialog, setShowDeleteDialog] = useState(false); const [serviceEditData, setServiceEditData] = useState< AssetService & { open: boolean; viewOnly?: boolean } >(); + const [transactionFilter, setTransactionFilter] = useState({}); - const fetchData = useCallback( - async (status: statusType) => { - setIsLoading(true); - const assetData = await dispatch(getAsset(assetId)); - if (!status.aborted) { - setIsLoading(false); - if (assetData?.data) { - setAsset(assetData.data); - - const transactionFilter = assetData.qr_code_id - ? { qr_code_id: assetData.qr_code_id } - : { external_id: assetId }; - - const [transactionsData, servicesData] = await Promise.all([ - dispatch( - listAssetTransaction({ - ...transactionFilter, - limit, - offset, - }) - ), - dispatch(listAssetService({}, assetId)), - ]); - - if (transactionsData?.data) { - setTransactions(transactionsData.data.results); - setTotalCount(transactionsData.data.count); - } else { - Notification.Error({ - msg: "Error fetching transactions", - }); - } - if (servicesData?.data) { - setServices(servicesData.data.results); - } else { - Notification.Error({ - msg: "Error fetching service logs", - }); - } - } else { - navigate("/not-found"); - } + const { data: asset, loading } = useQuery(routes.getAsset, { + pathParams: { + external_id: assetId, + }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data) { + setTransactionFilter( + data.qr_code_id + ? { qr_code_id: data.qr_code_id } + : { external_id: assetId } + ); } }, - [dispatch, assetId, offset] - ); + }); - useAbortableEffect( - (status: statusType) => { - fetchData(status); + const { data: transactions } = useQuery(routes.listAssetTransaction, { + prefetch: !!asset, + query: { + ...transactionFilter, + limit, + offset, }, - [dispatch, fetchData] + onResponse: ({ res, data }) => { + if (res?.status === 200 && data) { + setTotalCount(data.count); + } + }, + }); + + const { data: services, refetch: serviceRefetch } = useQuery( + routes.listAssetService, + { + pathParams: { + asset_external_id: assetId, + }, + } ); const handlePagination = (page: number, limit: number) => { @@ -158,7 +133,7 @@ const AssetManage = (props: AssetManageProps) => { const populateTableRows = (txns: AssetTransaction[]) => { if (txns.length > 0) { setTransactionDetails( - transactions.map((transaction: AssetTransaction) => ( + transactions?.results.map((transaction: AssetTransaction) => ( @@ -201,7 +176,7 @@ const AssetManage = (props: AssetManageProps) => { const populateServiceTableRows = (txns: AssetService[]) => { if (txns.length > 0) { setServiceDetails( - services.map((service: AssetService) => ( + services?.results.map((service: AssetService) => ( @@ -276,14 +251,14 @@ const AssetManage = (props: AssetManageProps) => { }; useEffect(() => { - populateTableRows(transactions); + if (transactions) populateTableRows(transactions.results); }, [transactions]); useEffect(() => { - populateServiceTableRows(services); + if (services) populateServiceTableRows(services?.results); }, [services]); - if (isLoading) return ; + if (loading) return ; if (isPrintMode) return ; const assetClassProp = @@ -324,13 +299,17 @@ const AssetManage = (props: AssetManageProps) => { const handleDelete = async () => { if (asset) { - const response = await dispatch(deleteAsset(asset.id)); - if (response && response.status === 204) { - Notification.Success({ - msg: "Asset deleted successfully", - }); - navigate("/assets"); - } + await request(routes.deleteAsset, { + pathParams: { + external_id: asset.id, + }, + onResponse: () => { + Notification.Success({ + msg: "Asset deleted successfully", + }); + navigate("/assets"); + }, + }); } }; @@ -595,7 +574,7 @@ const AssetManage = (props: AssetManageProps) => { handleClose={() => setServiceEditData({ ...serviceEditData, open: false }) } - handleUpdate={() => fetchData({ aborted: false })} + handleUpdate={() => serviceRefetch()} show={serviceEditData.open} viewOnly={serviceEditData.viewOnly} /> diff --git a/src/Components/Assets/AssetServiceEditModal.tsx b/src/Components/Assets/AssetServiceEditModal.tsx index 690524e471b..3964dfe0770 100644 --- a/src/Components/Assets/AssetServiceEditModal.tsx +++ b/src/Components/Assets/AssetServiceEditModal.tsx @@ -1,6 +1,4 @@ import { useEffect, useState } from "react"; -import { useDispatch } from "react-redux"; -import { updateAssetService } from "../../Redux/actions"; import * as Notification from "../../Utils/Notifications.js"; import ButtonV2, { Cancel, Submit } from "../Common/components/ButtonV2"; import DialogModal from "../Common/Dialog"; @@ -9,6 +7,8 @@ import dayjs from "dayjs"; import TextAreaFormField from "../Form/FormFields/TextAreaFormField"; import { formatDate, formatDateTime } from "../../Utils/utils"; import CareIcon from "../../CAREUI/icons/CareIcon"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; import DateFormField from "../Form/FormFields/DateFormField"; import { t } from "i18next"; @@ -24,23 +24,25 @@ export const AssetServiceEditModal = (props: { serviced_on: props.service_record?.serviced_on, note: props.service_record?.note, }); - const dispatchAction: any = useDispatch(); const [isLoading, setIsLoading] = useState(false); const [editRecord, setEditRecord] = useState(); const handleSubmit = async (e: any) => { e.preventDefault(); setIsLoading(true); - const data = { + const body = { serviced_on: form.serviced_on, note: form.note, }; - - const res = await dispatchAction( - updateAssetService(props.asset?.id ?? "", props.service_record.id, data) - ); + const { data } = await request(routes.updateAssetService, { + pathParams: { + asset_external_id: props.asset?.id ?? "", + external_id: props.service_record.id, + }, + body: body, + }); setIsLoading(false); - if (res?.data) { + if (data) { Notification.Success({ msg: "Asset service record updated successfully", }); diff --git a/src/Components/Assets/AssetType/HL7Monitor.tsx b/src/Components/Assets/AssetType/HL7Monitor.tsx index 6f896ac343f..b4fefbc90b2 100644 --- a/src/Components/Assets/AssetType/HL7Monitor.tsx +++ b/src/Components/Assets/AssetType/HL7Monitor.tsx @@ -1,10 +1,5 @@ import { SyntheticEvent, useEffect, useState } from "react"; import { AssetData } from "../AssetTypes"; -import { useDispatch } from "react-redux"; -import { - partialUpdateAsset, - getPermittedFacility, -} from "../../../Redux/actions"; import * as Notification from "../../../Utils/Notifications.js"; import MonitorConfigure from "../configure/MonitorConfigure"; import Loading from "../../Common/Loading"; @@ -16,6 +11,9 @@ import TextFormField from "../../Form/FormFields/TextFormField"; import HL7PatientVitalsMonitor from "../../VitalsMonitor/HL7PatientVitalsMonitor"; import VentilatorPatientVitalsMonitor from "../../VitalsMonitor/VentilatorPatientVitalsMonitor"; import useAuthUser from "../../../Common/hooks/useAuthUser"; +import request from "../../../Utils/request/request"; +import routes from "../../../Redux/api"; +import useQuery from "../../../Utils/request/useQuery"; interface HL7MonitorProps { assetId: string; @@ -33,19 +31,14 @@ const HL7Monitor = (props: HL7MonitorProps) => { const [localipAddress, setLocalIPAddress] = useState(""); const [ipadrdress_error, setIpAddress_error] = useState(""); const authUser = useAuthUser(); - const dispatch = useDispatch(); - - useEffect(() => { - const fetchFacility = async () => { - const res = await dispatch(getPermittedFacility(facilityId)); - - if (res.status === 200 && res.data) { - setFacilityMiddlewareHostname(res.data.middleware_address); + const { data: facility, loading } = useQuery(routes.getPermittedFacility, { + pathParams: { id: facilityId }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data && data.middleware_address) { + setFacilityMiddlewareHostname(data.middleware_address); } - }; - - if (facilityId) fetchFacility(); - }, [dispatch, facilityId]); + }, + }); useEffect(() => { setAssetType(asset?.asset_class); @@ -65,9 +58,10 @@ const HL7Monitor = (props: HL7MonitorProps) => { local_ip_address: localipAddress, }, }; - const res: any = await Promise.resolve( - dispatch(partialUpdateAsset(assetId, data)) - ); + const { res } = await request(routes.partialUpdateAsset, { + pathParams: { external_id: assetId }, + body: data, + }); if (res?.status === 200) { Notification.Success({ msg: "Asset Configured Successfully", @@ -85,7 +79,7 @@ const HL7Monitor = (props: HL7MonitorProps) => { const fallbackMiddleware = asset?.location_object?.middleware_address || facilityMiddlewareHostname; - if (isLoading) return ; + if (isLoading || loading || !facility) return ; return (
diff --git a/src/Components/Assets/AssetType/ONVIFCamera.tsx b/src/Components/Assets/AssetType/ONVIFCamera.tsx index cb9cc1cc497..eb6ebb9abfd 100644 --- a/src/Components/Assets/AssetType/ONVIFCamera.tsx +++ b/src/Components/Assets/AssetType/ONVIFCamera.tsx @@ -1,11 +1,5 @@ import { useEffect, useState } from "react"; import { AssetData } from "../AssetTypes"; -import { useDispatch } from "react-redux"; -import { - partialUpdateAsset, - createAssetBed, - getPermittedFacility, -} from "../../../Redux/actions"; import * as Notification from "../../../Utils/Notifications.js"; import { BedModel } from "../../Facility/models"; import axios from "axios"; @@ -17,8 +11,14 @@ import TextFormField from "../../Form/FormFields/TextFormField"; import { Submit } from "../../Common/components/ButtonV2"; import { SyntheticEvent } from "react"; import useAuthUser from "../../../Common/hooks/useAuthUser"; + +import request from "../../../Utils/request/request"; +import routes from "../../../Redux/api"; +import useQuery from "../../../Utils/request/useQuery"; + import CareIcon from "../../../CAREUI/icons/CareIcon"; + interface Props { assetId: string; facilityId: string; @@ -44,19 +44,15 @@ const ONVIFCamera = ({ assetId, facilityId, asset, onUpdated }: Props) => { const [refreshPresetsHash, setRefreshPresetsHash] = useState( Number(new Date()) ); - const dispatch = useDispatch(); + const { data: facility, loading } = useQuery(routes.getPermittedFacility, { + pathParams: { id: facilityId }, + }); const authUser = useAuthUser(); useEffect(() => { - const fetchFacility = async () => { - const res = await dispatch(getPermittedFacility(facilityId)); - - if (res.status === 200 && res.data) { - setFacilityMiddlewareHostname(res.data.middleware_address); - } - }; - - if (facilityId) fetchFacility(); - }, [dispatch, facilityId]); + if (facility?.middleware_address) { + setFacilityMiddlewareHostname(facility.middleware_address); + } + }, [facility, facilityId]); useEffect(() => { if (asset) { @@ -84,9 +80,10 @@ const ONVIFCamera = ({ assetId, facilityId, asset, onUpdated }: Props) => { camera_access_key: `${username}:${password}:${streamUuid}`, }, }; - const res: any = await Promise.resolve( - dispatch(partialUpdateAsset(assetId, data)) - ); + const { res } = await request(routes.partialUpdateAsset, { + pathParams: { external_id: assetId }, + body: data, + }); if (res?.status === 200) { Notification.Success({ msg: "Asset Configured Successfully" }); onUpdated?.(); @@ -111,15 +108,14 @@ const ONVIFCamera = ({ assetId, facilityId, asset, onUpdated }: Props) => { const presetData = await axios.get( `https://${facilityMiddlewareHostname}/status?hostname=${config.hostname}&port=${config.port}&username=${config.username}&password=${config.password}` ); - const res: any = await Promise.resolve( - dispatch( - createAssetBed( - { meta: { ...data, ...presetData.data } }, - assetId, - bed?.id as string - ) - ) - ); + + const { res } = await request(routes.createAssetBed, { + body: { + meta: { ...data, ...presetData.data }, + asset: assetId, + bed: bed?.id as string, + }, + }); if (res?.status === 201) { Notification.Success({ msg: "Preset Added Successfully", @@ -139,12 +135,12 @@ const ONVIFCamera = ({ assetId, facilityId, asset, onUpdated }: Props) => { } setLoadingAddPreset(false); }; + + if (isLoading || loading || !facility) return ; const fallbackMiddleware = asset?.location_object?.middleware_address || facilityMiddlewareHostname; - if (isLoading) return ; - return (
{["DistrictAdmin", "StateAdmin"].includes(authUser.user_type) && ( diff --git a/src/Components/Assets/AssetTypes.tsx b/src/Components/Assets/AssetTypes.tsx index 52c7e45003c..8b96b6beeb7 100644 --- a/src/Components/Assets/AssetTypes.tsx +++ b/src/Components/Assets/AssetTypes.tsx @@ -91,6 +91,8 @@ export interface AssetData { }; } +export type AssetUpdate = Partial; + export interface AssetsResponse { count: number; next?: string; @@ -137,8 +139,12 @@ export interface AssetBedModel { created_date: string; modified_date: string; meta: Record; + asset?: string; + bed?: string; } +export type AssetBedBody = Partial; + export interface AssetServiceEdit { id: string; asset_service: AssetService; @@ -166,3 +172,9 @@ export interface PatientAssetBed { patient?: PatientModel; meta?: Record; } + +export interface AssetServiceUpdate { + external_id: string; + serviced_on: string; + note: string; +} diff --git a/src/Components/Assets/AssetsList.tsx b/src/Components/Assets/AssetsList.tsx index 1c366a23e7e..4bcb2698a9a 100644 --- a/src/Components/Assets/AssetsList.tsx +++ b/src/Components/Assets/AssetsList.tsx @@ -1,15 +1,8 @@ -import { useDispatch } from "react-redux"; import QrReader from "react-qr-reader"; -import { statusType, useAbortableEffect } from "../../Common/utils"; import * as Notification from "../../Utils/Notifications.js"; -import { - getAnyFacility, - listAssets, - getFacilityAssetLocation, - getAsset, -} from "../../Redux/actions"; +import { listAssets } from "../../Redux/actions"; import { assetClassProps, AssetData } from "./AssetTypes"; -import { useState, useCallback, useEffect, lazy } from "react"; +import { useState, useEffect, lazy } from "react"; import { Link, navigate } from "raviger"; import AssetFilter from "./AssetFilter"; import { parseQueryParams } from "../../Utils/primitives"; @@ -28,6 +21,9 @@ import AssetImportModal from "./AssetImportModal"; import Page from "../Common/components/Page"; import { AdvancedFilterButton } from "../../CAREUI/interactive/FiltersSlideover"; import { useTranslation } from "react-i18next"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; +import useQuery from "../../Utils/request/useQuery"; const Loading = lazy(() => import("../Common/Loading")); @@ -52,66 +48,45 @@ const AssetsList = () => { const [status, setStatus] = useState(); const [facilityName, setFacilityName] = useState(); const [asset_class, setAssetClass] = useState(); - const [locationName, setLocationName] = useState(); const [importAssetModalOpen, setImportAssetModalOpen] = useState(false); - const dispatch: any = useDispatch(); const assetsExist = assets.length > 0 && Object.keys(assets[0]).length > 0; const [showFacilityDialog, setShowFacilityDialog] = useState(false); const [selectedFacility, setSelectedFacility] = useState({ name: "", }); + const params = { + limit: resultsPerPage, + page: qParams.page, + offset: (qParams.page ? qParams.page - 1 : 0) * resultsPerPage, + search_text: qParams.search || "", + facility: qParams.facility || "", + asset_type: qParams.asset_type || "", + asset_class: qParams.asset_class || "", + location: qParams.facility ? qParams.location || "" : "", + status: qParams.status || "", + }; - const fetchData = useCallback( - async (status: statusType) => { - setIsLoading(true); - const params = { - limit: resultsPerPage, - page: qParams.page, - offset: (qParams.page ? qParams.page - 1 : 0) * resultsPerPage, - search_text: qParams.search || "", - facility: qParams.facility || "", - asset_type: qParams.asset_type || "", - asset_class: qParams.asset_class || "", - location: qParams.facility ? qParams.location || "" : "", - status: qParams.status || "", - warranty_amc_end_of_validity_before: - qParams.warranty_amc_end_of_validity_before || "", - warranty_amc_end_of_validity_after: - qParams.warranty_amc_end_of_validity_after || "", - }; - const { data } = await dispatch(listAssets(params)); - if (!status.aborted) { - setIsLoading(false); - if (!data) - Notification.Error({ - msg: "Something went wrong..!", - }); - else { - setAssets(data.results); - setTotalCount(data.count); - if (qParams.facility) { - const fetchFacility = await dispatch( - getAnyFacility(qParams.facility) - ); - setSelectedFacility(fetchFacility.data as FacilityModel); - } - } + useQuery(routes.listAssets, { + query: params, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data) { + setAssets(data.results); + setTotalCount(data.count); } }, - [ - resultsPerPage, - qParams.page, - qParams.search, - qParams.facility, - qParams.asset_type, - qParams.asset_class, - qParams.location, - qParams.status, - qParams.warranty_amc_end_of_validity_before, - qParams.warranty_amc_end_of_validity_after, - dispatch, - ] - ); + }); + + useQuery(routes.getAnyFacility, { + pathParams: { id: qParams.facility }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data) { + setFacility(data); + setSelectedFacility(data); + setFacilityName(data.name); + } + }, + prefetch: !!qParams.facility, + }); useEffect(() => { setAssetType(qParams.asset_type); @@ -125,56 +100,13 @@ const AssetsList = () => { setAssetClass(qParams.asset_class); }, [qParams.asset_class]); - useAbortableEffect( - (status: statusType) => { - fetchData(status); + const { data: location } = useQuery(routes.getFacilityAssetLocation, { + pathParams: { + facility_external_id: String(qParams.facility), + external_id: String(qParams.location), }, - [dispatch, fetchData] - ); - useEffect(() => { - async function fetchFacilityName() { - if (!qParams.facility) return setFacilityName(""); - const res = await dispatch(getAnyFacility(qParams.facility, "facility")); - setFacilityName(res?.data?.name); - } - fetchFacilityName(); - }, [dispatch, qParams.facility]); - - const fetchFacility = useCallback( - async (status: statusType) => { - if (!qParams.facility) return setFacility(undefined); - setIsLoading(true); - const res = await dispatch(getAnyFacility(qParams.facility)); - if (!status.aborted) { - setFacility(res?.data); - setIsLoading(false); - } - }, - [dispatch, qParams.facility] - ); - const fetchLocationName = useCallback( - async (status: statusType) => { - if (!qParams.location || !qParams.facility) - return setLocationName(undefined); - setIsLoading(true); - const res = await dispatch( - getFacilityAssetLocation(qParams.facility, qParams.location) - ); - if (!status.aborted) { - setLocationName(res?.data?.name); - setIsLoading(false); - } - }, - [dispatch, qParams.facility, qParams.location] - ); - - useAbortableEffect( - (status: statusType) => { - fetchFacility(status); - fetchLocationName(status); - }, - [fetchFacility, fetchLocationName] - ); + prefetch: !!(qParams.facility && qParams.location), + }); const getAssetIdFromQR = async (assetUrl: string) => { try { @@ -184,8 +116,10 @@ const AssetsList = () => { // QR Maybe searchParams "asset" or "assetQR" const assetId = params.asset || params.assetQR; if (assetId) { - const { data } = await dispatch(listAssets({ qr_code_id: assetId })); - return data.results[0].id; + const { data } = await request(routes.listAssets, { + query: { qr_code_id: assetId }, + }); + return data?.results[0].id; } } catch (err) { console.log(err); @@ -193,11 +127,13 @@ const AssetsList = () => { }; const checkValidAssetId = async (assetId: string) => { - const assetData = await dispatch(getAsset(assetId)); + const { data: assetData } = await request(routes.getAsset, { + pathParams: { id: assetId }, + }); try { - if (assetData.data) { + if (assetData) { navigate( - `/facility/${assetData.data.location_object.facility.id}/assets/${assetId}` + `/facility/${assetData.location_object.facility.id}/assets/${assetId}` ); } } catch (err) { @@ -434,7 +370,7 @@ const AssetsList = () => { value("Asset Type", "asset_type", asset_type ?? ""), value("Asset Class", "asset_class", asset_class ?? ""), value("Status", "status", status?.replace(/_/g, " ") ?? ""), - value("Location", "location", locationName ?? ""), + value("Location", "location", location?.name ?? ""), value( "Warranty AMC End Of Validity Before", "warranty_amc_end_of_validity_before", diff --git a/src/Components/Assets/configure/MonitorConfigure.tsx b/src/Components/Assets/configure/MonitorConfigure.tsx index 1d469335ce2..d1b24b24959 100644 --- a/src/Components/Assets/configure/MonitorConfigure.tsx +++ b/src/Components/Assets/configure/MonitorConfigure.tsx @@ -1,62 +1,50 @@ -import { Dispatch, useEffect, useState } from "react"; +import { useState } from "react"; import { BedSelect } from "../../Common/BedSelect"; import { BedModel } from "../../Facility/models"; import { AssetData } from "../AssetTypes"; -import { - createAssetBed, - listAssetBeds, - partialUpdateAssetBed, -} from "../../../Redux/actions"; import * as Notification from "../../../Utils/Notifications.js"; -import { useDispatch } from "react-redux"; import { Submit } from "../../Common/components/ButtonV2"; import { FieldLabel } from "../../Form/FormFields/FormField"; +import request from "../../../Utils/request/request"; +import routes from "../../../Redux/api"; +import useQuery from "../../../Utils/request/useQuery"; -const saveLink = (assetId: string, bedId: string, dispatch: Dispatch) => { - dispatch(createAssetBed({}, assetId, bedId)); +const saveLink = async (assetId: string, bedId: string) => { + await request(routes.createAssetBed, { + body: { + asset: assetId, + bed: bedId, + }, + }); Notification.Success({ msg: "AssetBed Link created successfully" }); }; -const update_Link = ( +const update_Link = async ( assetbedId: string, assetId: string, - bed: BedModel, - assetBed: any, - dispatch: Dispatch + bed: BedModel ) => { - dispatch( - partialUpdateAssetBed( - { - asset: assetId, - bed: bed.id, - }, - assetbedId - ) - ); + await request(routes.partialUpdateAssetBed, { + pathParams: { external_id: assetbedId }, + body: { + asset: assetId, + bed: bed.id ?? "", + }, + }); Notification.Success({ msg: "AssetBed Link updated successfully" }); }; export default function MonitorConfigure({ asset }: { asset: AssetData }) { const [bed, setBed] = useState({}); const [updateLink, setUpdateLink] = useState(false); - const [assetBed, setAssetBed] = useState(); - const dispatch: any = useDispatch(); - - const getAssetBeds = async (id: string) => { - const assetBeds = await dispatch(listAssetBeds({ asset: id })); - if (assetBeds.data?.results?.length > 0) { - setUpdateLink(true); - setAssetBed(assetBeds.data.results[0]); - setBed(assetBeds.data.results[0].bed_object); - } else { - setUpdateLink(false); - } - }; - - useEffect(() => { - if (asset.id) { - getAssetBeds(asset.id); - } - }, [asset]); + const { data: assetBed } = useQuery(routes.listAssetBeds, { + query: { asset: asset.id }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data && data.results.length > 0) { + setBed(data.results[0].bed_object); + setUpdateLink(true); + } + }, + }); return (
diff --git a/src/Redux/actions.tsx b/src/Redux/actions.tsx index 06a12796737..7a92b1a7658 100644 --- a/src/Redux/actions.tsx +++ b/src/Redux/actions.tsx @@ -834,47 +834,15 @@ export const listAssets = (params: object) => fireRequest("listAssets", [], params); export const createAsset = (params: object) => fireRequest("createAsset", [], params); -export const getAssetUserLocation = (params: object) => - fireRequest("getAssetUserLocation", [], params); -export const createAssetUserLocation = (params: object) => - fireRequest("createAssetUserLocation", [], params); export const getAsset = (id: string) => fireRequest("getAsset", [], {}, { external_id: id }); export const deleteAsset = (id: string) => fireRequest("deleteAsset", [], {}, { external_id: id }); export const updateAsset = (id: string, params: object) => fireRequest("updateAsset", [], params, { external_id: id }); -export const partialUpdateAsset = (id: string, params: object) => - fireRequest("partialUpdateAsset", [], params, { external_id: id }); export const operateAsset = (id: string, params: object) => fireRequest("operateAsset", [], params, { external_id: id }); -export const listAssetTransaction = (params: object) => - fireRequest("listAssetTransaction", [], params); -export const getAssetTransaction = (id: string) => - fireRequest("getAssetTransaction", [], {}, { id }); - -export const listAssetService = (params: object, asset_external_id: string) => - fireRequest("listAssetService", [], params, { asset_external_id }); -export const getAssetService = ( - params: object, - asset_external_id: string, - external_id: string -) => - fireRequest("getAssetService", [], params, { - asset_external_id, - external_id, - }); -export const updateAssetService = ( - asset_external_id: string, - external_id: string, - params: object -) => - fireRequest("updateAssetService", [], params, { - asset_external_id, - external_id, - }); - // ABDM related export const generateAadhaarOtp = (aadhaar: string) => fireRequest("generateAadhaarOtp", [], { aadhaar }); diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index 02c38afcc5a..a05d461c98d 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -1,5 +1,17 @@ import { IConfig } from "../Common/hooks/useConfig"; -import { AssetData } from "../Components/Assets/AssetTypes"; + +import { + AssetBedBody, + AssetBedModel, + AssetData, + AssetLocationObject, + AssetService, + AssetServiceUpdate, + AssetTransaction, + AssetUpdate, +} from "../Components/Assets/AssetTypes"; +import { FacilityModel, LocationModel, WardModel } from "../Components/Facility/models"; + import { IDeleteExternalResult, IExternalResult, @@ -8,7 +20,6 @@ import { ILocalBodyByDistrict, IPartialUpdateExternalResult, } from "../Components/ExternalResult/models"; -import { LocationModel, WardModel } from "../Components/Facility/models"; import { Prescription } from "../Components/Medicine/models"; import { UserModel } from "../Components/Users/models"; import { PaginatedResponse } from "../Utils/request/types"; @@ -197,10 +208,14 @@ const routes = { getPermittedFacility: { path: "/api/v1/facility/{id}/", + method: "GET", + TRes: Type(), }, getAnyFacility: { path: "/api/v1/getallfacilities/{id}/", + method: "GET", + TRes: Type(), }, updateFacility: { @@ -234,6 +249,7 @@ const routes = { getFacilityAssetLocation: { path: "/api/v1/facility/{facility_external_id}/asset_location/{external_id}/", method: "GET", + TRes: Type(), }, updateFacilityAssetLocation: { path: "/api/v1/facility/{facility_external_id}/asset_location/{external_id}/", @@ -248,10 +264,13 @@ const routes = { listAssetBeds: { path: "/api/v1/assetbed/", method: "GET", + TRes: Type>(), }, createAssetBed: { path: "/api/v1/assetbed/", method: "POST", + TRes: Type(), + TBody: Type(), }, getAssetBed: { path: "/api/v1/assetbed/{external_id}/", @@ -264,6 +283,8 @@ const routes = { partialUpdateAssetBed: { path: "/api/v1/assetbed/{external_id}/", method: "PATCH", + TRes: Type(), + TBody: Type(), }, deleteAssetBed: { path: "/api/v1/assetbed/{external_id}/", @@ -830,6 +851,7 @@ const routes = { listAssets: { path: "/api/v1/asset", method: "GET", + TRes: Type>(), }, createAsset: { path: "/api/v1/asset/", @@ -851,6 +873,7 @@ const routes = { deleteAsset: { path: "/api/v1/asset/{external_id}/", method: "DELETE", + TRes: Type(), }, updateAsset: { path: "/api/v1/asset/{external_id}/", @@ -859,6 +882,8 @@ const routes = { partialUpdateAsset: { path: "/api/v1/asset/{external_id}/", method: "PATCH", + TRes: Type(), + TBody: Type(), }, // Asset transaction endpoints @@ -866,6 +891,7 @@ const routes = { listAssetTransaction: { path: "/api/v1/asset_transaction/", method: "GET", + TRes: Type>(), }, getAssetTransaction: { path: "/api/v1/asset_transaction/{id}", @@ -877,6 +903,7 @@ const routes = { listAssetService: { path: "/api/v1/asset/{asset_external_id}/service_records/", method: "GET", + TRes: Type>(), }, getAssetService: { path: "/api/v1/asset/{asset_external_id}/service_records/{external_id}", @@ -885,6 +912,8 @@ const routes = { updateAssetService: { path: "/api/v1/asset/{asset_external_id}/service_records/{external_id}", method: "PUT", + TRes: Type(), + TBody: Type(), }, // ABDM HealthID endpoints