From 9f852af8e0cbdc64a55513a390749e74f659d7a6 Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Wed, 31 Jan 2024 13:12:02 +0530 Subject: [PATCH] Replace `useDispatch` with `useQuery` in Asset Management, Location Management, Facility Cover Image Popup, Doctor Capacity and Triage (#7004) * Replace `useDispatch` with `useQuery` in Asset Create page * Replace `useDispatch` with `useQuery` in Add Location Form * Replace `useDispatch` with `useQuery` in Delete Cover Image Edit Modal * Replace `useDispatch` with `useQuery` in Doctor Capacity and Counts * Replace `useDispatch` with `useQuery` in Triage Form * Replace `useDispatch` with `useQuery` in Doctor Capacity form * fix bugs and cypress tests --------- Co-authored-by: Mohammed Nihal <57055998+nihal467@users.noreply.github.com> --- cypress/pageobject/Asset/AssetCreation.ts | 2 +- src/Components/Assets/AssetTypes.tsx | 6 +- src/Components/Facility/AddLocationForm.tsx | 118 +++++++------- src/Components/Facility/AssetCreate.tsx | 90 +++++------ .../Facility/CoverImageEditModal.tsx | 16 +- src/Components/Facility/DoctorCapacity.tsx | 139 ++++++----------- src/Components/Facility/DoctorsCountCard.tsx | 32 ++-- src/Components/Facility/TriageForm.tsx | 146 +++++------------- src/Components/Facility/models.tsx | 6 +- src/Redux/actions.tsx | 84 ---------- src/Redux/api.tsx | 28 +++- src/Utils/request/utils.ts | 9 +- 12 files changed, 238 insertions(+), 438 deletions(-) diff --git a/cypress/pageobject/Asset/AssetCreation.ts b/cypress/pageobject/Asset/AssetCreation.ts index 60e3f3ece2d..6932b5ed15e 100644 --- a/cypress/pageobject/Asset/AssetCreation.ts +++ b/cypress/pageobject/Asset/AssetCreation.ts @@ -129,7 +129,7 @@ export class AssetPage { cy.get( "[data-testid=asset-last-serviced-on-input] input[type='text']" ).click(); - cy.get("#date-input").click().type(lastServicedOn); + cy.get("#date-input").click().clear().type(lastServicedOn); cy.get("[data-testid=asset-notes-input] textarea").clear().type(notes); } diff --git a/src/Components/Assets/AssetTypes.tsx b/src/Components/Assets/AssetTypes.tsx index 436c9370dd8..dc70d246e0b 100644 --- a/src/Components/Assets/AssetTypes.tsx +++ b/src/Components/Assets/AssetTypes.tsx @@ -9,14 +9,14 @@ export enum AssetLocationType { } export interface AssetLocationObject { - id: string; + id?: string; name: string; description: string; created_date?: string; modified_date?: string; location_type: AssetLocationType; middleware_address?: string; - facility: { + facility?: { id: string; name: string; }; @@ -105,8 +105,6 @@ export interface AssetData { }; } -export type AssetUpdate = Partial; - export interface AssetsResponse { count: number; next?: string; diff --git a/src/Components/Facility/AddLocationForm.tsx b/src/Components/Facility/AddLocationForm.tsx index 8f756f91781..b9300708781 100644 --- a/src/Components/Facility/AddLocationForm.tsx +++ b/src/Components/Facility/AddLocationForm.tsx @@ -1,11 +1,4 @@ -import { useState, useEffect, lazy, SyntheticEvent } from "react"; -import { useDispatch } from "react-redux"; -import { - createFacilityAssetLocation, - getAnyFacility, - getFacilityAssetLocation, - updateFacilityAssetLocation, -} from "../../Redux/actions"; +import { useState, lazy, SyntheticEvent } from "react"; import * as Notification from "../../Utils/Notifications.js"; import { navigate } from "raviger"; import { Submit, Cancel } from "../Common/components/ButtonV2"; @@ -14,17 +7,18 @@ import TextAreaFormField from "../Form/FormFields/TextAreaFormField"; import Page from "../Common/components/Page"; import { SelectFormField } from "../Form/FormFields/SelectFormField"; import { AssetLocationType } from "../Assets/AssetTypes"; +import useQuery from "../../Utils/request/useQuery"; +import routes from "../../Redux/api"; +import request from "../../Utils/request/request"; const Loading = lazy(() => import("../Common/Loading")); -interface LocationFormProps { +interface Props { facilityId: string; locationId?: string; } -export const AddLocationForm = (props: LocationFormProps) => { - const { facilityId, locationId } = props; - const dispatchAction: any = useDispatch(); +export const AddLocationForm = ({ facilityId, locationId }: Props) => { const [isLoading, setIsLoading] = useState(false); const [name, setName] = useState(""); const [middlewareAddress, setMiddlewareAddress] = useState(""); @@ -41,29 +35,30 @@ export const AddLocationForm = (props: LocationFormProps) => { const headerText = !locationId ? "Add Location" : "Update Location"; const buttonText = !locationId ? "Add Location" : "Update Location"; - useEffect(() => { - async function fetchFacilityName() { - setIsLoading(true); - if (facilityId) { - const res = await dispatchAction(getAnyFacility(facilityId)); - - setFacilityName(res?.data?.name || ""); - } - if (locationId) { - const res = await dispatchAction( - getFacilityAssetLocation(facilityId, locationId) - ); - - setName(res?.data?.name || ""); - setLocationName(res?.data?.name || ""); - setDescription(res?.data?.description || ""); - setLocationType(res?.data?.location_type || ""); - setMiddlewareAddress(res?.data?.middleware_address || ""); - } - setIsLoading(false); - } - fetchFacilityName(); - }, [dispatchAction, facilityId, locationId]); + const facilityQuery = useQuery(routes.getAnyFacility, { + pathParams: { id: facilityId }, + prefetch: !locationId, + onResponse: ({ data }) => { + data?.name && setFacilityName(data.name); + }, + }); + + const locationQuery = useQuery(routes.getFacilityAssetLocation, { + pathParams: { + facility_external_id: facilityId, + external_id: locationId!, + }, + prefetch: !!locationId, + onResponse: ({ data }) => { + if (!data) return; + setFacilityName(data.facility?.name ?? ""); + setName(data.name); + setLocationName(data.name); + setDescription(data.description); + setLocationType(data.location_type); + setMiddlewareAddress(data.middleware_address ?? ""); + }, + }); const validateForm = () => { let formValid = true; @@ -109,39 +104,40 @@ export const AddLocationForm = (props: LocationFormProps) => { name, description, middleware_address: middlewareAddress, - location_type: locationType, + location_type: locationType as AssetLocationType, }; - const res = await dispatchAction( - locationId - ? updateFacilityAssetLocation(data, facilityId, locationId) - : createFacilityAssetLocation(data, facilityId) - ); + const { res, error } = await (locationId + ? request(routes.updateFacilityAssetLocation, { + body: data, + pathParams: { + facility_external_id: facilityId, + external_id: locationId, + }, + }) + : request(routes.createFacilityAssetLocation, { + body: data, + pathParams: { facility_external_id: facilityId }, + })); + setIsLoading(false); - if (res) { - if (res.status === 201 || res.status === 200) { - const notificationMessage = locationId + + if (res?.ok) { + navigate(`/facility/${facilityId}/location`, { replace: true }); + Notification.Success({ + msg: locationId ? "Location updated successfully" - : "Location created successfully"; - - navigate(`/facility/${facilityId}/location`, { - replace: true, - }); - Notification.Success({ - msg: notificationMessage, - }); - } else if (res.status === 400) { - Object.keys(res.data).forEach((key) => { - setErrors((prevState: any) => ({ - ...prevState, - [key]: res.data[key], - })); - }); - } + : "Location created successfully", + }); + return; + } + + if (error) { + setErrors(error); } }; - if (isLoading) { + if (isLoading || locationQuery.loading || facilityQuery.loading) { return ; } diff --git a/src/Components/Facility/AssetCreate.tsx b/src/Components/Facility/AssetCreate.tsx index 35f71a746fd..784174cd2f7 100644 --- a/src/Components/Facility/AssetCreate.tsx +++ b/src/Components/Facility/AssetCreate.tsx @@ -1,6 +1,6 @@ import * as Notification from "../../Utils/Notifications.js"; -import { AssetClass, AssetData, AssetType } from "../Assets/AssetTypes"; +import { AssetClass, AssetType } from "../Assets/AssetTypes"; import { Cancel, Submit } from "../Common/components/ButtonV2"; import { LegacyRef, @@ -11,12 +11,6 @@ import { useReducer, useState, } from "react"; -import { - createAsset, - getAsset, - listFacilityAssetLocation, - updateAsset, -} from "../../Redux/actions"; import CareIcon from "../../CAREUI/icons/CareIcon"; import { FieldErrorText, FieldLabel } from "../Form/FormFields/FormField"; @@ -32,13 +26,15 @@ import TextFormField from "../Form/FormFields/TextFormField"; import { navigate } from "raviger"; import { parseQueryParams } from "../../Utils/primitives"; import useAppHistory from "../../Common/hooks/useAppHistory"; -import { useDispatch } from "react-redux"; import useVisibility from "../../Utils/useVisibility"; import { validateEmailAddress } from "../../Common/validation"; import { dateQueryString, parsePhoneNumber } from "../../Utils/utils.js"; import dayjs from "../../Utils/dayjs"; import DateFormField from "../Form/FormFields/DateFormField.js"; import { t } from "i18next"; +import useQuery from "../../Utils/request/useQuery.js"; +import routes from "../../Redux/api.js"; +import request from "../../Utils/request/request.js"; const Loading = lazy(() => import("../Common/Loading")); @@ -124,18 +120,12 @@ const AssetCreate = (props: AssetProps) => { const [support_email, setSupportEmail] = useState(""); const [location, setLocation] = useState(""); const [isLoading, setIsLoading] = useState(false); - const [locations, setLocations] = useState<{ name: string; id: string }[]>( - [] - ); - const [asset, setAsset] = useState(); - const [facilityName, setFacilityName] = useState(""); const [qrCodeId, setQrCodeId] = useState(""); const [manufacturer, setManufacturer] = useState(""); const [warranty_amc_end_of_validity, setWarrantyAmcEndOfValidity] = useState(null); const [last_serviced_on, setLastServicedOn] = useState(null); const [notes, setNotes] = useState(""); - const dispatchAction: any = useDispatch(); const [isScannerActive, setIsScannerActive] = useState(false); const [currentSection, setCurrentSection] = @@ -173,32 +163,20 @@ const AssetCreate = (props: AssetProps) => { }); }, [generalDetailsVisible, warrantyDetailsVisible, serviceDetailsVisible]); - useEffect(() => { - setIsLoading(true); - dispatchAction( - listFacilityAssetLocation({}, { facility_external_id: facilityId }) - ).then(({ data }: any) => { - if (data.count > 0) { - setFacilityName(data.results[0].facility?.name); - setLocations(data.results); - } - setIsLoading(false); - }); + const locationsQuery = useQuery(routes.listFacilityAssetLocation, { + pathParams: { facility_external_id: facilityId }, + query: { limit: 1 }, + }); - if (assetId) { - setIsLoading(true); - dispatchAction(getAsset(assetId)).then(({ data }: any) => { - setAsset(data); - setIsLoading(false); - }); - } - }, [assetId, dispatchAction, facilityId]); + const assetQuery = useQuery(routes.getAsset, { + pathParams: { external_id: assetId! }, + prefetch: !!assetId, + onResponse: ({ data: asset }) => { + if (!asset) return; - useEffect(() => { - if (asset) { setName(asset.name); setDescription(asset.description); - setLocation(asset.location_object.id); + setLocation(asset.location_object.id!); setAssetType(asset.asset_type); setAssetClass(asset.asset_class); setIsWorking(String(asset.is_working)); @@ -215,8 +193,8 @@ const AssetCreate = (props: AssetProps) => { asset.last_service?.serviced_on && setLastServicedOn(asset.last_service?.serviced_on); asset.last_service?.note && setNotes(asset.last_service?.note); - } - }, [asset]); + }, + }); const validateForm = () => { const errors = { ...initError }; @@ -355,26 +333,25 @@ const AssetCreate = (props: AssetProps) => { } if (!assetId) { - const res = await dispatchAction(createAsset(data)); - if (res && res.data && res.status === 201) { - Notification.Success({ - msg: "Asset created successfully", - }); - if (!addMore) { - goBack(); - } else { + const { res } = await request(routes.createAsset, { body: data }); + if (res?.ok) { + Notification.Success({ msg: "Asset created successfully" }); + if (addMore) { resetFilters(); const pageContainer = window.document.getElementById("pages"); pageContainer?.scroll(0, 0); + } else { + goBack(); } } setIsLoading(false); } else { - const res = await dispatchAction(updateAsset(assetId, data)); - if (res && res.data && res.status === 200) { - Notification.Success({ - msg: "Asset updated successfully", - }); + const { res } = await request(routes.updateAsset, { + pathParams: { external_id: assetId }, + body: data, + }); + if (res?.ok) { + Notification.Success({ msg: "Asset updated successfully" }); goBack(); } setIsLoading(false); @@ -400,14 +377,15 @@ const AssetCreate = (props: AssetProps) => { setIsScannerActive(false); }; - if (isLoading) return ; + if (isLoading || locationsQuery.loading || assetQuery.loading) { + return ; + } - if (locations.length === 0) { + if (locationsQuery.data?.count === 0) { return ( { title={`${assetId ? t("update") : t("create")} Asset`} className="grow-0 pl-6" crumbsReplacements={{ - [facilityId]: { name: facilityName }, + [facilityId]: { + name: locationsQuery.data?.results[0].facility?.name, + }, assets: { style: "text-gray-200 pointer-events-none" }, [assetId || "????"]: { name }, }} diff --git a/src/Components/Facility/CoverImageEditModal.tsx b/src/Components/Facility/CoverImageEditModal.tsx index 4b3519ca745..8de463ad9b5 100644 --- a/src/Components/Facility/CoverImageEditModal.tsx +++ b/src/Components/Facility/CoverImageEditModal.tsx @@ -6,8 +6,6 @@ import { useRef, useState, } from "react"; -import { useDispatch } from "react-redux"; -import { deleteFacilityCoverImage } from "../../Redux/actions"; import { Success } from "../../Utils/Notifications"; import useDragAndDrop from "../../Utils/useDragAndDrop"; import { sleep } from "../../Utils/utils"; @@ -20,6 +18,8 @@ import * as Notification from "../../Utils/Notifications.js"; import { useTranslation } from "react-i18next"; import { LocalStorageKeys } from "../../Common/constants"; import DialogModal from "../Common/Dialog"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; interface Props { open: boolean; onClose: (() => void) | undefined; @@ -35,7 +35,6 @@ const CoverImageEditModal = ({ onDelete, facility, }: Props) => { - const dispatch = useDispatch(); const [isUploading, setIsUploading] = useState(false); const [selectedFile, setSelectedFile] = useState(); const [preview, setPreview] = useState(); @@ -143,13 +142,14 @@ const CoverImageEditModal = ({ }; const handleDelete = async () => { - const res = await dispatch(deleteFacilityCoverImage(facility.id as any)); - if (res.statusCode === 204) { + const { res } = await request(routes.deleteFacilityCoverImage, { + pathParams: { id: facility.id! }, + }); + if (res?.ok) { Success({ msg: "Cover image deleted" }); + onDelete?.(); + closeModal(); } - - onDelete && onDelete(); - closeModal(); }; const hasImage = !!(preview || facility.read_cover_image_url); diff --git a/src/Components/Facility/DoctorCapacity.tsx b/src/Components/Facility/DoctorCapacity.tsx index 6c7baafaad8..34acb7567c1 100644 --- a/src/Components/Facility/DoctorCapacity.tsx +++ b/src/Components/Facility/DoctorCapacity.tsx @@ -1,15 +1,15 @@ -import { useCallback, useEffect, useReducer, useState } from "react"; -import { useDispatch } from "react-redux"; +import { useReducer, useState } from "react"; import { DOCTOR_SPECIALIZATION } from "../../Common/constants"; -import { statusType, useAbortableEffect } from "../../Common/utils"; -import { createDoctor, getDoctor, listDoctor } from "../../Redux/actions"; import * as Notification from "../../Utils/Notifications.js"; import ButtonV2, { Cancel } from "../Common/components/ButtonV2"; import { FieldErrorText, FieldLabel } from "../Form/FormFields/FormField"; import TextFormField from "../Form/FormFields/TextFormField"; import { FieldChangeEventHandler } from "../Form/FormFields/Utils"; import SelectMenuV2 from "../Form/SelectMenuV2"; -import { DoctorModal, OptionsType } from "./models"; +import { DoctorModal } from "./models"; +import useQuery from "../../Utils/request/useQuery"; +import routes from "../../Redux/api"; +import request from "../../Utils/request/request"; interface DoctorCapacityProps extends DoctorModal { facilityId: string; @@ -19,8 +19,6 @@ interface DoctorCapacityProps extends DoctorModal { id?: number; } -const initDoctorTypes: Array = [...DOCTOR_SPECIALIZATION]; - const initForm: any = { area: "", count: "", @@ -50,78 +48,46 @@ const doctorCapacityReducer = (state = initialState, action: any) => { } }; +const getAllowedDoctorTypes = (existing?: DoctorModal[]) => { + if (!existing) return [...DOCTOR_SPECIALIZATION]; + + return DOCTOR_SPECIALIZATION.map((specialization) => { + const disabled = existing.some((i) => i.area === specialization.id); + return { ...specialization, disabled }; + }); +}; + export const DoctorCapacity = (props: DoctorCapacityProps) => { - const dispatchAction: any = useDispatch(); const { facilityId, handleClose, handleUpdate, className, id } = props; const [state, dispatch] = useReducer(doctorCapacityReducer, initialState); const [isLoading, setIsLoading] = useState(false); - const [isLastOptionType, setIsLastOptionType] = useState(false); - const [doctorTypes, setDoctorTypes] = - useState>(initDoctorTypes); - const headerText = !id ? "Add Doctor Capacity" : "Edit Doctor Capacity"; - const buttonText = !id - ? `Save ${!isLastOptionType ? "& Add More" : "Doctor Capacity"}` - : "Update Doctor Capacity"; + const specializationsQuery = useQuery(routes.listDoctor, { + pathParams: { facilityId }, + }); - const fetchData = useCallback( - async (status: statusType) => { - setIsLoading(true); - if (!id) { - // Add Form functionality - const doctorRes = await dispatchAction(listDoctor({}, { facilityId })); - if (!status.aborted) { - if (doctorRes && doctorRes.data) { - const existingData = doctorRes.data.results; - // if all options are diabled - if (existingData.length === DOCTOR_SPECIALIZATION.length) { - return; - } - // disable existing doctor types - const updatedDoctorTypes = initDoctorTypes.map( - (type: OptionsType) => { - const isExisting = existingData.find( - (i: DoctorModal) => i.area === type.id - ); - return { - ...type, - disabled: !!isExisting, - }; - } - ); - setDoctorTypes(updatedDoctorTypes); - } - } - } else { - // Edit Form functionality - const res = await dispatchAction( - getDoctor({ facilityId: facilityId, id: id }) - ); - if (res && res.data) { - dispatch({ - type: "set_form", - form: { area: res.data.area, count: res.data.count }, - }); - } - } - setIsLoading(false); + const { loading } = useQuery(routes.getDoctor, { + pathParams: { facilityId, id: `${id}` }, + prefetch: !!id, + onResponse: ({ data }) => { + if (!data) return; + dispatch({ + type: "set_form", + form: { area: data.area, count: data.count }, + }); }, - [dispatchAction, facilityId, id] - ); + }); - useAbortableEffect( - (status: statusType) => { - fetchData(status); - }, - [dispatch, fetchData, id] - ); + const doctorTypes = getAllowedDoctorTypes(specializationsQuery.data?.results); - useEffect(() => { - const lastDoctorType = - doctorTypes.filter((i: OptionsType) => i.disabled).length === - DOCTOR_SPECIALIZATION.length - 1; - setIsLastOptionType(lastDoctorType); - }, [doctorTypes]); + const isLastOptionType = + doctorTypes.filter((i) => i.disabled).length === + DOCTOR_SPECIALIZATION.length - 1; + + const headerText = !id ? "Add Doctor Capacity" : "Edit Doctor Capacity"; + const buttonText = !id + ? `Save ${!isLastOptionType ? "& Add More" : "Doctor Capacity"}` + : "Update Doctor Capacity"; const validateData = () => { const errors = { ...initForm }; @@ -159,28 +125,23 @@ export const DoctorCapacity = (props: DoctorCapacityProps) => { area: Number(state.form.area), count: Number(state.form.count), }; - const res = await dispatchAction(createDoctor(id, data, { facilityId })); + const { res } = await (id + ? request(routes.updateDoctor, { + pathParams: { facilityId, id: `${id}` }, + body: data, + }) + : request(routes.createDoctor, { + pathParams: { facilityId }, + body: data, + })); setIsLoading(false); - if (res && res.data) { - // disable last added bed type - const updatedDoctorTypes = doctorTypes.map((type: OptionsType) => { - return { - ...type, - disabled: res.data.area !== type.id ? type.disabled : true, - }; - }); - setDoctorTypes(updatedDoctorTypes); - // reset form + if (res?.ok) { + specializationsQuery.refetch(); dispatch({ type: "set_form", form: initForm }); - // show success message if (!id) { - Notification.Success({ - msg: "Doctor count added successfully", - }); + Notification.Success({ msg: "Doctor count added successfully" }); } else { - Notification.Success({ - msg: "Doctor count updated successfully", - }); + Notification.Success({ msg: "Doctor count updated successfully" }); } } handleUpdate(); @@ -191,7 +152,7 @@ export const DoctorCapacity = (props: DoctorCapacityProps) => { return (
- {isLoading ? ( + {isLoading || loading || specializationsQuery.loading ? (
{ const specialization = DOCTOR_SPECIALIZATION.find((i) => i.id === props.area); - const dispatchAction: any = useDispatch(); const [openDeleteDialog, setOpenDeleteDialog] = useState(false); const [open, setOpen] = useState(false); const [selectedId, setSelectedId] = useState(-1); const handleDeleteSubmit = async () => { - if (props.area) { - const res = await dispatchAction( - deleteDoctor(props.area, { facilityId: props.facilityId }) - ); - if (res?.status === 204) { - Notification.Success({ - msg: "Doctor specialization type deleted successfully", - }); - props.removeDoctor(props.id); - } else { - Notification.Error({ - msg: - "Error while deleting Doctor specialization: " + - (res?.data?.detail || ""), - }); - } + if (!props.area) return; + + const { res } = await request(routes.deleteDoctor, { + pathParams: { facilityId: props.facilityId, area: `${props.area}` }, + }); + + if (res?.ok) { + props.removeDoctor(props.id); + Notification.Success({ + msg: "Doctor specialization type deleted successfully", + }); } }; diff --git a/src/Components/Facility/TriageForm.tsx b/src/Components/Facility/TriageForm.tsx index 9264661fc45..32971f1d302 100644 --- a/src/Components/Facility/TriageForm.tsx +++ b/src/Components/Facility/TriageForm.tsx @@ -2,15 +2,7 @@ import ConfirmDialog from "../Common/ConfirmDialog"; import Card from "../../CAREUI/display/Card"; import CareIcon from "../../CAREUI/icons/CareIcon"; -import { useCallback, useReducer, useState, useEffect, lazy } from "react"; -import { useDispatch } from "react-redux"; -import { statusType, useAbortableEffect } from "../../Common/utils"; -import { - createTriageForm, - getTriageDetails, - getAnyFacility, - getTriageInfo, -} from "../../Redux/actions"; +import { useReducer, useState, lazy } from "react"; import * as Notification from "../../Utils/Notifications.js"; import TextFormField from "../Form/FormFields/TextFormField"; import { PatientStatsModel } from "./models"; @@ -22,10 +14,13 @@ const Loading = lazy(() => import("../Common/Loading")); import Page from "../Common/components/Page"; import dayjs from "dayjs"; import { dateQueryString, scrollTo } from "../../Utils/utils"; +import useQuery from "../../Utils/request/useQuery"; +import routes from "../../Redux/api"; +import request from "../../Utils/request/request"; -interface triageFormProps extends PatientStatsModel { - facilityId: number; - id?: number; +interface Props extends PatientStatsModel { + facilityId: string; + id?: string; } const initForm: any = { @@ -61,99 +56,40 @@ const triageFormReducer = (state = initialState, action: any) => { } }; -export const TriageForm = (props: triageFormProps) => { +export const TriageForm = ({ facilityId, id }: Props) => { const { goBack } = useAppHistory(); - const dispatchTriageData: any = useDispatch(); - const dispatchAction: any = useDispatch(); - const { facilityId, id } = props; const [state, dispatch] = useReducer(triageFormReducer, initialState); const [isLoading, setIsLoading] = useState(false); - const [facilityName, setFacilityName] = useState(""); - const [patientStatsData, setPatientStatsData] = useState< - Array - >([]); const [openModalForExistingTriage, setOpenModalForExistingTriage] = useState(false); const headerText = !id ? "Add Triage" : "Edit Triage"; const buttonText = !id ? "Save Triage" : "Update Triage"; - const fetchData = useCallback( - async (status: statusType) => { - setIsLoading(true); - if (id) { - // Edit Form functionality - const res = await dispatchAction( - getTriageDetails({ facilityId: facilityId, id: id }) - ); - if (!status.aborted && res && res.data) { - dispatch({ - type: "set_form", - form: { - entry_date: res.data.entry_date - ? dayjs(res.data.entry_date).toDate() - : null, - num_patients_visited: res.data.num_patients_visited, - num_patients_home_quarantine: - res.data.num_patients_home_quarantine, - num_patients_isolation: res.data.num_patients_isolation, - num_patient_referred: res.data.num_patient_referred, - num_patient_confirmed_positive: - res.data.num_patient_confirmed_positive, - }, - }); - } - } - setIsLoading(false); - }, - [dispatchAction, facilityId, id] - ); - - useAbortableEffect( - (status: statusType) => { - fetchData(status); - }, - [dispatch, fetchData, id] - ); - - // this will fetch all triage data of the facility - const fetchTriageData = useCallback( - async (status: statusType) => { - const [triageRes] = await Promise.all([ - dispatchTriageData(getTriageInfo({ facilityId })), - ]); - if (!status.aborted) { - if ( - triageRes && - triageRes.data && - triageRes.data.results && - triageRes.data.results.length - ) { - setPatientStatsData(triageRes.data.results); - } - } + const triageDetailsQuery = useQuery(routes.getTriageDetails, { + pathParams: { facilityId, id: id! }, + prefetch: !!id, + onResponse: ({ data }) => { + if (!data) return; + dispatch({ + type: "set_form", + form: { + ...data, + entry_date: data.entry_date ? dayjs(data.entry_date).toDate() : null, + }, + }); }, - [dispatchTriageData, facilityId] - ); + }); - useAbortableEffect( - (status: statusType) => { - fetchTriageData(status); - }, - [dispatch, fetchTriageData] - ); + const patientStatsQuery = useQuery(routes.getTriage, { + pathParams: { facilityId }, + }); - useEffect(() => { - async function fetchFacilityName() { - if (facilityId) { - const res = await dispatchAction(getAnyFacility(facilityId)); + const patientStatsData = patientStatsQuery.data?.results ?? []; - setFacilityName(res?.data?.name || ""); - } else { - setFacilityName(""); - } - } - fetchFacilityName(); - }, [dispatchAction, facilityId]); + const facilityQuery = useQuery(routes.getAnyFacility, { + pathParams: { id: facilityId }, + }); + const facilityName = facilityQuery.data?.name ?? ""; const validateForm = () => { const errors = { ...initForm }; @@ -216,20 +152,17 @@ export const TriageForm = (props: triageFormProps) => { ) { setOpenModalForExistingTriage(false); setIsLoading(true); - const res = await dispatchAction( - createTriageForm(data, { facilityId }) - ); + const { res } = await request(routes.createTriage, { + pathParams: { facilityId }, + body: data, + }); setIsLoading(false); - if (res && res.data) { + if (res?.ok) { dispatch({ type: "set_form", form: initForm }); if (id) { - Notification.Success({ - msg: "Triage updated successfully", - }); + Notification.Success({ msg: "Triage updated successfully" }); } else { - Notification.Success({ - msg: "Triage created successfully", - }); + Notification.Success({ msg: "Triage created successfully" }); } goBack(); } @@ -246,7 +179,12 @@ export const TriageForm = (props: triageFormProps) => { }); }; - if (isLoading) { + if ( + isLoading || + facilityQuery.loading || + triageDetailsQuery.loading || + patientStatsQuery.loading + ) { return ; } diff --git a/src/Components/Facility/models.tsx b/src/Components/Facility/models.tsx index 99d91c6cbae..979e1c49056 100644 --- a/src/Components/Facility/models.tsx +++ b/src/Components/Facility/models.tsx @@ -35,7 +35,7 @@ export interface WardModel { } export interface FacilityModel { - id?: number; + id?: string; name?: string; read_cover_image_url?: string; facility_type?: string; @@ -165,13 +165,13 @@ export interface ConsultationModel { } export interface PatientStatsModel { - id?: number; + id?: string; entryDate?: string; num_patients_visited?: number; num_patients_home_quarantine?: number; num_patients_isolation?: number; num_patient_referred?: number; - entry_date?: number; + entry_date?: string; num_patient_confirmed_positive?: number; } diff --git a/src/Redux/actions.tsx b/src/Redux/actions.tsx index d6de3c3b960..1fadd678f73 100644 --- a/src/Redux/actions.tsx +++ b/src/Redux/actions.tsx @@ -3,23 +3,10 @@ import { MedibaseMedicine } from "../Components/Medicine/models"; import { fireRequest } from "./fireRequest"; // Facility -export const createFacility = (params: object) => { - return fireRequest("createFacility", [], params); -}; -export const updateFacility = (id: string, params: object) => { - return fireRequest("updateFacility", [id], params); -}; -export const deleteFacilityCoverImage = (id: string) => { - return fireRequest("deleteFacilityCoverImage", [], {}, { id }); -}; export const getUserList = (params: object, key?: string) => { return fireRequest("userList", [], params, null, key); }; -export const getPermittedFacilities = (params: object) => { - return fireRequest("getPermittedFacilities", [], params); -}; - export const getAnyFacility = (id: number | string, key?: string) => { return fireRequest("getAnyFacility", [], {}, { id: id }, key); }; @@ -33,15 +20,6 @@ export const getFacilityUsers = (id: string, params?: object) => { ); }; -export const listFacilityAssetLocation = (params: object, pathParam: object) => - fireRequest("listFacilityAssetLocation", [], params, pathParam); -export const createFacilityAssetLocation = ( - params: object, - facility_id: string -) => - fireRequest("createFacilityAssetLocation", [], params, { - facility_external_id: facility_id, - }); export const getFacilityAssetLocation = ( facility_external_id: string, external_id: string @@ -52,15 +30,6 @@ export const getFacilityAssetLocation = ( {}, { facility_external_id, external_id } ); -export const updateFacilityAssetLocation = ( - params: object, - facility_external_id: string, - external_id: string -) => - fireRequest("updateFacilityAssetLocation", [], params, { - facility_external_id, - external_id, - }); // asset bed export const listAssetBeds = (params: object, altKey?: string) => @@ -97,21 +66,6 @@ export const deleteAssetBed = (asset_id: string) => } ); -// Facility Beds -export const listFacilityBeds = (params: object) => - fireRequest("listFacilityBeds", [], params, {}); -export const createFacilityBed = ( - params: object, - facility_id: string, - location_id: string -) => - fireRequest( - "createFacilityBed", - [], - { ...params, facility: facility_id, location: location_id }, - {} - ); - // Download Actions export const downloadFacility = () => { return fireRequest("downloadFacility"); @@ -129,35 +83,6 @@ export const downloadFacilityTriage = () => { return fireRequest("downloadFacilityTriage"); }; -// Capacity/Triage/Doctor -export const createDoctor = ( - id: number | undefined, - params: object, - pathParam: object -) => { - return id - ? fireRequest("updateDoctor", [id], params, pathParam) - : fireRequest("createDoctor", [], params, pathParam); -}; -export const deleteDoctor = (id: number, pathParam: object) => { - return fireRequest("deleteDoctor", [id], {}, pathParam); -}; -export const createTriageForm = (params: object, pathParam: object) => { - return fireRequest("createTriage", [], params, pathParam); -}; -export const getTriageInfo = (pathParam: object) => { - return fireRequest("getTriage", [], {}, pathParam); -}; -export const getTriageDetails = (pathParam: object) => { - return fireRequest("getTriageDetails", [], {}, pathParam); -}; -export const listDoctor = (params: object, pathParam: object) => { - return fireRequest("listDoctor", [], params, pathParam); -}; -export const getDoctor = (pathParam: object) => { - return fireRequest("getDoctor", [], {}, pathParam); -}; - //Patient export const searchPatient = (params: object) => { return fireRequest("searchPatient", [], params); @@ -183,9 +108,6 @@ export const transferPatient = (params: object, pathParam: object) => { export const getStates = () => { return fireRequest("statesList", []); }; -export const getState = (id: number) => { - return fireRequest("getState", [], {}, { id: id }); -}; // District/State/Local body/ward export const getDistrictByState = (pathParam: object) => { @@ -460,12 +382,6 @@ export const downloadResourceRequests = (params: object) => { export const listAssets = (params: object) => fireRequest("listAssets", [], params); -export const createAsset = (params: object) => - fireRequest("createAsset", [], params); -export const getAsset = (id: string) => - fireRequest("getAsset", [], {}, { external_id: id }); -export const updateAsset = (id: string, params: object) => - fireRequest("updateAsset", [], params, { external_id: id }); export const operateAsset = (id: string, params: object) => fireRequest("operateAsset", [], params, { external_id: id }); diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index 94b61fa339e..a94efeb7ea1 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -27,7 +27,6 @@ import { AssetService, AssetServiceUpdate, AssetTransaction, - AssetUpdate, AssetUptimeRecord, PatientAssetBed, } from "../Components/Assets/AssetTypes"; @@ -332,6 +331,7 @@ const routes = { deleteFacilityCoverImage: { path: "/api/v1/facility/{id}/cover_image/", method: "DELETE", + TRes: Type>(), }, getFacilityUsers: { @@ -347,6 +347,8 @@ const routes = { createFacilityAssetLocation: { path: "/api/v1/facility/{facility_external_id}/asset_location/", method: "POST", + TBody: Type(), + TRes: Type(), }, getFacilityAssetLocation: { path: "/api/v1/facility/{facility_external_id}/asset_location/{external_id}/", @@ -356,6 +358,8 @@ const routes = { updateFacilityAssetLocation: { path: "/api/v1/facility/{facility_external_id}/asset_location/{external_id}/", method: "PUT", + TBody: Type(), + TRes: Type(), }, partialUpdateFacilityAssetLocation: { path: "/api/v1/facility/{facility_external_id}/asset_location/{external_id}/", @@ -551,6 +555,8 @@ const routes = { createDoctor: { path: "/api/v1/facility/{facilityId}/hospital_doctor/", method: "POST", + TRes: Type(), + TBody: Type(), }, getCapacity: { @@ -575,6 +581,7 @@ const routes = { }, getDoctor: { path: "/api/v1/facility/{facilityId}/hospital_doctor/{id}/", + TRes: Type(), }, updateCapacity: { @@ -584,19 +591,23 @@ const routes = { }, updateDoctor: { - path: "/api/v1/facility/{facilityId}/hospital_doctor", + path: "/api/v1/facility/{facilityId}/hospital_doctor/{id}/", method: "PUT", + TRes: Type(), }, deleteDoctor: { - path: "/api/v1/facility/{facilityId}/hospital_doctor", + path: "/api/v1/facility/{facilityId}/hospital_doctor/{area}/", method: "DELETE", + TRes: Type>(), }, //Triage createTriage: { path: "/api/v1/facility/{facilityId}/patient_stats/", method: "POST", + TBody: Type(), + TRes: Type(), }, getTriage: { path: "/api/v1/facility/{facilityId}/patient_stats/", @@ -605,6 +616,7 @@ const routes = { getTriageDetails: { path: "/api/v1/facility/{facilityId}/patient_stats/{id}/", + TRes: Type(), }, // //Care Center @@ -1045,9 +1057,11 @@ const routes = { createAsset: { path: "/api/v1/asset/", method: "POST", + TBody: Type(), + TRes: Type(), }, getAssetUserLocation: { - path: "​/api/v1/asset​/get_default_user_location​/", + path: "/api/v1/asset/get_default_user_location/", method: "GET", }, createAssetUserLocation: { @@ -1062,17 +1076,19 @@ const routes = { deleteAsset: { path: "/api/v1/asset/{external_id}/", method: "DELETE", - TRes: Type(), + TRes: Type>(), }, updateAsset: { path: "/api/v1/asset/{external_id}/", method: "PUT", + TBody: Type(), + TRes: Type(), }, partialUpdateAsset: { path: "/api/v1/asset/{external_id}/", method: "PATCH", TRes: Type(), - TBody: Type(), + TBody: Type>(), }, // Asset transaction endpoints diff --git a/src/Utils/request/utils.ts b/src/Utils/request/utils.ts index 166355812bb..9b98e1ae3bf 100644 --- a/src/Utils/request/utils.ts +++ b/src/Utils/request/utils.ts @@ -39,10 +39,11 @@ const ensurePathNotMissingReplacements = (path: string) => { const missingParams = path.match(/\{.*\}/g); if (missingParams) { - Notification.Error({ - msg: `Missing path params: ${missingParams.join(", ")}`, - }); - throw new Error(`Missing path params: ${missingParams.join(", ")}`); + const msg = `Missing path params: ${missingParams.join( + ", " + )}. Path: ${path}`; + Notification.Error({ msg }); + throw new Error(msg); } };