diff --git a/src/Components/Facility/FacilityCreate.tsx b/src/Components/Facility/FacilityCreate.tsx index e742caefb82..24d91d25a5d 100644 --- a/src/Components/Facility/FacilityCreate.tsx +++ b/src/Components/Facility/FacilityCreate.tsx @@ -1,7 +1,7 @@ import * as Notification from "../../Utils/Notifications.js"; import ButtonV2, { Cancel, Submit } from "../Common/components/ButtonV2"; -import { CapacityModal, DoctorModal } from "./models"; +import { CapacityModal, DoctorModal, FacilityModel } from "./models"; import { DraftSection, useAutoSaveReducer } from "../../Utils/AutoSave.js"; import { FACILITY_FEATURE_TYPES, @@ -13,19 +13,8 @@ import { SelectFormField, } from "../Form/FormFields/SelectFormField"; import { Popover, Transition } from "@headlessui/react"; -import { Fragment, lazy, useCallback, useState } from "react"; +import { Fragment, lazy, useEffect, useState } from "react"; import Steps, { Step } from "../Common/Steps"; -import { - createFacility, - getDistrictByState, - getLocalbodyByDistrict, - getPermittedFacility, - getStates, - getWardByLocalBody, - listCapacity, - listDoctor, - updateFacility, -} from "../../Redux/actions"; import { getPincodeDetails, includesIgnoreCase, @@ -37,7 +26,6 @@ import { validateLongitude, validatePincode, } from "../../Common/validation"; -import { statusType, useAbortableEffect } from "../../Common/utils"; import { BedCapacity } from "./BedCapacity"; import BedTypeCard from "./BedTypeCard"; @@ -57,9 +45,11 @@ import TextFormField from "../Form/FormFields/TextFormField"; import { navigate } from "raviger"; import useAppHistory from "../../Common/hooks/useAppHistory"; import useConfig from "../../Common/hooks/useConfig"; -import { useDispatch } from "react-redux"; import { useTranslation } from "react-i18next"; import { PhoneNumberValidator } from "../Form/FieldValidators.js"; +import request from "../../Utils/request/request.js"; +import routes from "../../Redux/api.js"; +import useQuery from "../../Utils/request/useQuery.js"; const Loading = lazy(() => import("../Common/Loading")); @@ -150,7 +140,6 @@ const facilityCreateReducer = (state = initialState, action: FormAction) => { export const FacilityCreate = (props: FacilityProps) => { const { t } = useTranslation(); const { gov_data_api_key, kasp_string, kasp_enabled } = useConfig(); - const dispatchAction: any = useDispatch(); const { facilityId } = props; const [state, dispatch] = useAutoSaveReducer( @@ -177,36 +166,36 @@ export const FacilityCreate = (props: FacilityProps) => { const headerText = !facilityId ? "Create Facility" : "Update Facility"; const buttonText = !facilityId ? "Save Facility" : "Update Facility"; - const fetchDistricts = useCallback( - async (id: number) => { - if (id > 0) { - setIsDistrictLoading(true); - const districtList = await dispatchAction(getDistrictByState({ id })); - if (districtList) { - setDistricts([...districtList.data]); - } - setIsDistrictLoading(false); - return districtList ? [...districtList.data] : []; + const fetchDistricts = async (id: number) => { + if (id > 0) { + setIsDistrictLoading(true); + const { res, data } = await request(routes.getDistrictByState, { + pathParams: { + id: String(id), + }, + }); + if (res?.ok && data) { + setDistricts([data]); } - }, - [dispatchAction] - ); + setIsDistrictLoading(false); + return res ? [data] : []; + } + }; - const fetchLocalBody = useCallback( - async (id: number) => { - if (id > 0) { - setIsLocalbodyLoading(true); - const localBodyList = await dispatchAction( - getLocalbodyByDistrict({ id }) - ); - setIsLocalbodyLoading(false); - if (localBodyList) { - setLocalBodies([...localBodyList.data]); - } + const fetchLocalBody = async (id: number) => { + if (id > 0) { + setIsLocalbodyLoading(true); + const { res, data } = await request(routes.getLocalbodyByDistrict, { + pathParams: { + id: String(id), + }, + }); + setIsLocalbodyLoading(false); + if (res?.ok && data) { + setLocalBodies(data); } - }, - [dispatchAction] - ); + } + }; const getSteps = (): Step[] => { return [ @@ -245,59 +234,64 @@ export const FacilityCreate = (props: FacilityProps) => { ]; }; - const fetchWards = useCallback( - async (id: number) => { - if (id > 0) { - setIsWardLoading(true); - const wardList = await dispatchAction(getWardByLocalBody({ id })); - setIsWardLoading(false); - if (wardList) { - setWard([...wardList.data.results]); - } + const fetchWards = async (id: number) => { + if (id > 0) { + setIsWardLoading(true); + const { res, data } = await request(routes.getWardByLocalBody, { + pathParams: { + id: String(id), + }, + }); + setIsWardLoading(false); + if (res?.ok && data) { + setWard([data.results[0]]); } - }, - [dispatchAction] - ); + } + }; - const fetchData = useCallback( - async (status: statusType) => { + const { refetch: facilityFetch } = useQuery(routes.getPermittedFacility, { + pathParams: { + id: facilityId || "", + }, + prefetch: facilityId !== undefined, + onResponse: ({ res, data }) => { if (facilityId) { setIsLoading(true); - const res = await dispatchAction(getPermittedFacility(facilityId)); - if (!status.aborted && res.data) { + if (res?.ok && data) { const formData = { - facility_type: res.data.facility_type, - name: res.data.name, - state: res.data.state ? res.data.state : 0, - district: res.data.district ? res.data.district : 0, - local_body: res.data.local_body ? res.data.local_body : 0, - features: res.data.features || [], - ward: res.data.ward_object ? res.data.ward_object.id : 0, - kasp_empanelled: res.data.kasp_empanelled - ? String(res.data.kasp_empanelled) - : "false", - address: res.data.address, - pincode: res.data.pincode, - phone_number: - res.data.phone_number.length == 10 - ? "+91" + res.data.phone_number - : res.data.phone_number, - latitude: res.data.latitude || "", - longitude: res.data.longitude || "", - type_b_cylinders: res.data.type_b_cylinders, - type_c_cylinders: res.data.type_c_cylinders, - type_d_cylinders: res.data.type_d_cylinders, - expected_type_b_cylinders: res.data.expected_type_b_cylinders, - expected_type_c_cylinders: res.data.expected_type_c_cylinders, - expected_type_d_cylinders: res.data.expected_type_d_cylinders, - expected_oxygen_requirement: res.data.expected_oxygen_requirement, - oxygen_capacity: res.data.oxygen_capacity, + facility_type: String(data.facility_type), + name: data.name ? data.name : "", + state: data.state ? data.state : 0, + district: data.district ? data.district : 0, + local_body: data.local_body ? data.local_body : 0, + features: data.features || [], + ward: data.ward_object ? data.ward_object.id : 0, + kasp_empanelled: "", + address: data.address ? data.address : "", + pincode: "", + phone_number: data.phone_number + ? data.phone_number.length == 10 + ? "+91" + data.phone_number + : data.phone_number + : "", + latitude: data.location ? String(data.location.latitude) : "", + longitude: data.location + ? String(data.location.latitude) + : "" || "", + type_b_cylinders: data.type_b_cylinders, + type_c_cylinders: data.type_c_cylinders, + type_d_cylinders: data.type_d_cylinders, + expected_type_b_cylinders: data.expected_type_b_cylinders, + expected_type_c_cylinders: data.expected_type_c_cylinders, + expected_type_d_cylinders: data.expected_type_d_cylinders, + expected_oxygen_requirement: data.expected_oxygen_requirement, + oxygen_capacity: data.oxygen_capacity, }; dispatch({ type: "set_form", form: formData }); Promise.all([ - fetchDistricts(res.data.state), - fetchLocalBody(res.data.district), - fetchWards(res.data.local_body), + fetchDistricts(data.state || 0), + fetchLocalBody(data.district || 0), + fetchWards(data.local_body || 0), ]); } else { navigate(`/facility/${facilityId}`); @@ -305,30 +299,24 @@ export const FacilityCreate = (props: FacilityProps) => { setIsLoading(false); } }, - [dispatchAction, facilityId, fetchDistricts, fetchLocalBody, fetchWards] - ); + }); - const fetchStates = useCallback( - async (status: statusType) => { + const { refetch: fetchStates } = useQuery(routes.statesList, { + onResponse: ({ res, data }) => { setIsStateLoading(true); - const statesRes = await dispatchAction(getStates()); - if (!status.aborted && statesRes.data.results) { - setStates([...statesRes.data.results]); + if (res && data) { + setStates([...data.results]); } setIsStateLoading(false); }, - [dispatchAction] - ); + }); - useAbortableEffect( - (status: statusType) => { - if (facilityId) { - fetchData(status); - } - fetchStates(status); - }, - [dispatch, fetchData] - ); + useEffect(() => { + if (facilityId) { + facilityFetch(); + } + fetchStates(); + }, [dispatch]); const handleChange = (e: FieldChangeEvent) => { dispatch({ @@ -362,12 +350,13 @@ export const FacilityCreate = (props: FacilityProps) => { return includesIgnoreCase(state.name, pincodeDetails.statename); }); if (!matchedState) return; - const fetchedDistricts = await fetchDistricts(matchedState.id); if (!fetchedDistricts) return; const matchedDistrict = fetchedDistricts.find((district) => { - return includesIgnoreCase(district.name, pincodeDetails.district); + return ( + district && includesIgnoreCase(district.name, pincodeDetails.district) + ); }); if (!matchedDistrict) return; @@ -479,19 +468,19 @@ export const FacilityCreate = (props: FacilityProps) => { console.log(state.form); if (validated) { setIsLoading(true); - const data = { + const data: FacilityModel = { facility_type: state.form.facility_type, name: state.form.name, district: state.form.district, state: state.form.state, address: state.form.address, - pincode: state.form.pincode, local_body: state.form.local_body, features: state.form.features, ward: state.form.ward, - kasp_empanelled: JSON.parse(state.form.kasp_empanelled), - latitude: state.form.latitude || null, - longitude: state.form.longitude || null, + location: { + latitude: Number(state.form.latitude), + longitude: Number(state.form.longitude), + }, phone_number: parsePhoneNumber(state.form.phone_number), oxygen_capacity: state.form.oxygen_capacity ? state.form.oxygen_capacity @@ -520,18 +509,26 @@ export const FacilityCreate = (props: FacilityProps) => { ? state.form.expected_type_d_cylinders : 0, }; - const res = await dispatchAction( - facilityId ? updateFacility(facilityId, data) : createFacility(data) - ); - if (res && (res.status === 200 || res.status === 201) && res.data) { - const id = res.data.id; + const { res, data: requestData } = facilityId + ? await request(routes.updateFacility, { + body: data, + pathParams: { + id: facilityId, + }, + }) + : await request(routes.createFacility, { + body: data, + }); + + if (res?.ok && requestData) { + const id = requestData.id; dispatch({ type: "set_form", form: initForm }); if (!facilityId) { Notification.Success({ msg: "Facility added successfully", }); - setCreatedFacilityId(id); + setCreatedFacilityId(String(id)); setCurrentStep(2); } else { Notification.Success({ @@ -539,11 +536,6 @@ export const FacilityCreate = (props: FacilityProps) => { }); navigate(`/facility/${facilityId}`); } - } else { - if (res?.data) - Notification.Error({ - msg: "Something went wrong: " + (res.data.detail || ""), - }); } setIsLoading(false); } @@ -603,11 +595,11 @@ export const FacilityCreate = (props: FacilityProps) => { lastUpdated={res.modified_date} removeBedType={removeCurrentBedType} handleUpdate={async () => { - const capacityRes = await dispatchAction( - listCapacity({}, { facilityId: createdFacilityId }) - ); - if (capacityRes && capacityRes.data) { - setCapacityData(capacityRes.data.results); + const { res, data } = await request(routes.getCapacity, { + pathParams: { facilityId: createdFacilityId }, + }); + if (res?.ok && data) { + setCapacityData(data.results); } }} /> @@ -640,11 +632,11 @@ export const FacilityCreate = (props: FacilityProps) => { facilityId={createdFacilityId || ""} key={`bed_${data.id}`} handleUpdate={async () => { - const doctorRes = await dispatchAction( - listDoctor({}, { facilityId: createdFacilityId }) - ); - if (doctorRes && doctorRes.data) { - setDoctorData(doctorRes.data.results); + const { res, data } = await request(routes.listDoctor, { + pathParams: { facilityId: createdFacilityId }, + }); + if (res?.ok && data) { + setDoctorData(data.results); } }} {...data} @@ -686,11 +678,11 @@ export const FacilityCreate = (props: FacilityProps) => { navigate(`/facility/${createdFacilityId}`); }} handleUpdate={async () => { - const doctorRes = await dispatchAction( - listDoctor({}, { facilityId: createdFacilityId }) - ); - if (doctorRes && doctorRes.data) { - setDoctorData(doctorRes.data.results); + const { res, data } = await request(routes.listDoctor, { + pathParams: { facilityId: createdFacilityId }, + }); + if (res?.ok && data) { + setDoctorData(data.results); } }} /> @@ -721,11 +713,11 @@ export const FacilityCreate = (props: FacilityProps) => { setCurrentStep(3); }} handleUpdate={async () => { - const capacityRes = await dispatchAction( - listCapacity({}, { facilityId: createdFacilityId }) - ); - if (capacityRes && capacityRes.data) { - setCapacityData(capacityRes.data.results); + const { res, data } = await request(routes.getCapacity, { + pathParams: { facilityId: createdFacilityId }, + }); + if (res?.ok && data) { + setCapacityData(data.results); } }} /> diff --git a/src/Components/Facility/HospitalList.tsx b/src/Components/Facility/HospitalList.tsx index ffdc1f4ed12..90eec8d8d9b 100644 --- a/src/Components/Facility/HospitalList.tsx +++ b/src/Components/Facility/HospitalList.tsx @@ -3,14 +3,8 @@ import { downloadFacilityCapacity, downloadFacilityDoctors, downloadFacilityTriage, - getDistrict, - getLocalBody, - getPermittedFacilities, - getState, } from "../../Redux/actions"; -import { statusType, useAbortableEffect } from "../../Common/utils"; -import { lazy, useCallback, useState } from "react"; -import { useDispatch } from "react-redux"; +import { lazy } from "react"; import { AdvancedFilterButton } from "../../CAREUI/interactive/FiltersSlideover"; import CountBlock from "../../CAREUI/display/Count"; import ExportMenu from "../Common/Export"; @@ -25,6 +19,8 @@ import { navigate } from "raviger"; import useFilters from "../../Common/hooks/useFilters"; import { useTranslation } from "react-i18next"; import useAuthUser from "../../Common/hooks/useAuthUser"; +import useQuery from "../../Utils/request/useQuery"; +import routes from "../../Redux/api"; const Loading = lazy(() => import("../Common/Loading")); @@ -39,21 +35,14 @@ export const HospitalList = () => { } = useFilters({ limit: 14, }); - const dispatchAction: any = useDispatch(); - const [data, setData] = useState>([]); let manageFacilities: any = null; - const [isLoading, setIsLoading] = useState(false); - const [totalCount, setTotalCount] = useState(0); - const [stateName, setStateName] = useState(""); - const [districtName, setDistrictName] = useState(""); - const [localbodyName, setLocalbodyName] = useState(""); const { user_type } = useAuthUser(); const { t } = useTranslation(); - const fetchData = useCallback( - async (status: statusType) => { - setIsLoading(true); - const params = { + const { data: permittedData, loading: isLoading } = useQuery( + routes.getPermittedFacilities, + { + query: { limit: resultsPerPage, page: qParams.page || 1, offset: (qParams.page ? qParams.page - 1 : 0) * resultsPerPage, @@ -63,92 +52,30 @@ export const HospitalList = () => { local_body: qParams.local_body, facility_type: qParams.facility_type, kasp_empanelled: qParams.kasp_empanelled, - }; - - const res = await dispatchAction(getPermittedFacilities(params)); - if (!status.aborted) { - if (res && res.data) { - setData(res.data.results); - setTotalCount(res.data.count); - } - setIsLoading(false); - } - }, - [ - qParams.page, - qParams.search, - qParams.state, - qParams.district, - qParams.local_body, - qParams.facility_type, - qParams.kasp_empanelled, - dispatchAction, - ] - ); - - useAbortableEffect( - (status: statusType) => { - fetchData(status); - }, - [fetchData] - ); - - const fetchStateName = useCallback( - async (status: statusType) => { - const res = - Number(qParams.state) && - (await dispatchAction(getState(qParams.state))); - if (!status.aborted) { - setStateName(res?.data?.name); - } - }, - [dispatchAction, qParams.state] - ); - - useAbortableEffect( - (status: statusType) => { - fetchStateName(status); - }, - [fetchStateName] + }, + } ); - const fetchDistrictName = useCallback( - async (status: statusType) => { - const res = - Number(qParams.district) && - (await dispatchAction(getDistrict(qParams.district))); - if (!status.aborted) { - setDistrictName(res?.data?.name); - } - }, - [dispatchAction, qParams.district] - ); - - useAbortableEffect( - (status: statusType) => { - fetchDistrictName(status); + const { data: stateData } = useQuery(routes.getState, { + pathParams: { + id: qParams.state, }, - [fetchDistrictName] - ); + prefetch: qParams.state !== undefined, + }); - const fetchLocalbodyName = useCallback( - async (status: statusType) => { - const res = - Number(qParams.local_body) && - (await dispatchAction(getLocalBody({ id: qParams.local_body }))); - if (!status.aborted) { - setLocalbodyName(res?.data?.name); - } + const { data: districtData } = useQuery(routes.getDistrict, { + pathParams: { + id: qParams.district, }, - [dispatchAction, qParams.local_body] - ); + prefetch: qParams.district !== undefined, + }); - useAbortableEffect( - (status: statusType) => { - fetchLocalbodyName(status); + const { data: localBodyData } = useQuery(routes.getLocalBody, { + pathParams: { + id: qParams.local_body, }, - [fetchLocalbodyName] - ); + prefetch: qParams.local_body !== undefined, + }); const findFacilityTypeById = (id: number) => { const facility_type = FACILITY_TYPES.find((type) => type.id == id); @@ -167,8 +94,8 @@ export const HospitalList = () => { }; let facilityList: JSX.Element[] = []; - if (data && data.length) { - facilityList = data.map((facility: FacilityModel) => ( + if (permittedData && permittedData.results.length) { + facilityList = permittedData.results.map((facility: FacilityModel) => ( { )); } - if (isLoading || !data) { + if (isLoading || !permittedData) { manageFacilities = ; - } else if (data && data.length) { + } else if (permittedData.results && permittedData.results.length) { manageFacilities = ( <>
{facilityList}
- + ); - } else if (data && data.length === 0) { + } else if (permittedData.results && permittedData.results.length === 0) { manageFacilities = hasFiltersApplied(qParams) ? (
@@ -244,13 +171,15 @@ export const HospitalList = () => { } >
- + {permittedData && ( + + )}
{ [ badge("Facility/District Name", "search"), - value("State", "state", stateName), - value("District", "district", districtName), - value("Local Body", "local_body", localbodyName), + value("State", "state", stateData?.name ?? ""), + value("District", "district", districtData?.name ?? ""), + value("Local Body", "local_body", localBodyData?.name ?? ""), value( "Facility type", "facility_type", diff --git a/src/Components/Facility/models.tsx b/src/Components/Facility/models.tsx index f5ddde19d2d..a995ac84d8e 100644 --- a/src/Components/Facility/models.tsx +++ b/src/Components/Facility/models.tsx @@ -3,6 +3,7 @@ import { ProcedureType } from "../Common/prescription-builder/ProcedureBuilder"; import { NormalPrescription, PRNPrescription } from "../Medicine/models"; import { AssetData } from "../Assets/AssetTypes"; import { UserBareMinimum } from "../Users/models"; +import { PaginatedResponse } from "../../Utils/request/types"; export interface LocalBodyModel { name: string; @@ -229,3 +230,8 @@ export type ICD11DiagnosisModel = { id: string; label: string; }; + +export type IStateListResponse = PaginatedResponse<{ + id: number; + name: string; +}>; diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index 7194aba5278..5f9eea1920f 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -28,9 +28,15 @@ import { AssetUpdate, } from "../Components/Assets/AssetTypes"; import { + CapacityModal, ConsultationModel, + DistrictModel, + DoctorModal, FacilityModel, + IStateListResponse, + LocalBodyModel, LocationModel, + StateModel, WardModel, } from "../Components/Facility/models"; import { @@ -229,6 +235,7 @@ const routes = { createFacility: { path: "/api/v1/facility/", method: "POST", + TRes: Type(), }, getPermittedFacility: { @@ -246,6 +253,7 @@ const routes = { updateFacility: { path: "/api/v1/facility", method: "PUT", + TRes: Type(), }, partialUpdateFacility: { @@ -458,6 +466,7 @@ const routes = { getCapacity: { path: "/api/v1/facility/{facilityId}/capacity/", + TRes: Type>(), }, getCapacityBed: { @@ -471,6 +480,7 @@ const routes = { listDoctor: { path: "/api/v1/facility/{facilityId}/hospital_doctor/", + TRes: Type>(), }, getDoctor: { path: "/api/v1/facility/{facilityId}/hospital_doctor/{id}/", @@ -596,19 +606,23 @@ const routes = { // States statesList: { path: "/api/v1/state/", + TRes: Type(), }, getState: { path: "/api/v1/state/{id}/", + TRes: Type(), }, // Districts getDistrict: { path: "/api/v1/district/{id}/", + TRes: Type(), }, getDistrictByState: { path: "/api/v1/state/{id}/districts/", + TRes: Type(), }, getDistrictByName: { path: "/api/v1/district/", @@ -627,6 +641,7 @@ const routes = { // Local Body getLocalBody: { path: "/api/v1/local_body/{id}/", + TRes: Type(), }, getAllLocalBody: { path: "/api/v1/local_body/",