diff --git a/src/Components/Facility/FacilityCreate.tsx b/src/Components/Facility/FacilityCreate.tsx index 4440b920f50..66d80c1089b 100644 --- a/src/Components/Facility/FacilityCreate.tsx +++ b/src/Components/Facility/FacilityCreate.tsx @@ -1,68 +1,68 @@ -import * as Notification from '../../Utils/Notifications.js'; -import ButtonV2, { Cancel, Submit } from '../Common/components/ButtonV2'; +import * as Notification from "../../Utils/Notifications.js"; +import ButtonV2, { Cancel, Submit } from "../Common/components/ButtonV2"; import { CapacityModal, DistrictModel, DoctorModal, FacilityRequest, -} from './models'; -import { DraftSection, useAutoSaveReducer } from '../../Utils/AutoSave.js'; +} from "./models"; +import { DraftSection, useAutoSaveReducer } from "../../Utils/AutoSave.js"; import { BED_TYPES, FACILITY_FEATURE_TYPES, FACILITY_TYPES, -} from '../../Common/constants'; +} from "../../Common/constants"; import { MultiSelectFormField, SelectFormField, -} from '../Form/FormFields/SelectFormField'; +} from "../Form/FormFields/SelectFormField"; import { Popover, PopoverButton, PopoverPanel, Transition, -} from '@headlessui/react'; -import {useEffect, useState } from 'react'; -import Steps, { Step } from '../Common/Steps'; +} from "@headlessui/react"; +import { useEffect, useState } from "react"; +import Steps, { Step } from "../Common/Steps"; import { getPincodeDetails, includesIgnoreCase, parsePhoneNumber, compareBy, -} from '../../Utils/utils'; +} from "../../Utils/utils"; import { phonePreg, validateLatitude, validateLongitude, validatePincode, -} from '../../Common/validation'; +} from "../../Common/validation"; -import { BedCapacity } from './BedCapacity'; -import BedTypeCard from './BedTypeCard'; -import Card from '../../CAREUI/display/Card.js'; -import CareIcon from '../../CAREUI/icons/CareIcon'; -import { StaffCapacity } from './StaffCapacity.js'; -import StaffCountCard from './StaffCountCard.js'; -import { FieldChangeEvent } from '../Form/FormFields/Utils'; -import { FormAction } from '../Form/Utils.js'; -import GLocationPicker from '../Common/GLocationPicker'; -import Page from '../Common/components/Page.js'; -import PhoneNumberFormField from '../Form/FormFields/PhoneNumberFormField'; -import RadioFormField from '../Form/FormFields/RadioFormField'; -import TextAreaFormField from '../Form/FormFields/TextAreaFormField'; -import TextFormField from '../Form/FormFields/TextFormField'; -import { navigate } from 'raviger'; -import useAppHistory from '../../Common/hooks/useAppHistory'; -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'; -import { RequestResult } from '../../Utils/request/types.js'; -import useAuthUser from '../../Common/hooks/useAuthUser'; -import SpokeFacilityEditor from './SpokeFacilityEditor.js'; -import careConfig from '@careConfig'; -import CoverImageEditModal from './CoverImageEditModal'; +import { BedCapacity } from "./BedCapacity"; +import BedTypeCard from "./BedTypeCard"; +import Card from "../../CAREUI/display/Card.js"; +import CareIcon from "../../CAREUI/icons/CareIcon"; +import { StaffCapacity } from "./StaffCapacity.js"; +import StaffCountCard from "./StaffCountCard.js"; +import { FieldChangeEvent } from "../Form/FormFields/Utils"; +import { FormAction } from "../Form/Utils.js"; +import GLocationPicker from "../Common/GLocationPicker"; +import Page from "../Common/components/Page.js"; +import PhoneNumberFormField from "../Form/FormFields/PhoneNumberFormField"; +import RadioFormField from "../Form/FormFields/RadioFormField"; +import TextAreaFormField from "../Form/FormFields/TextAreaFormField"; +import TextFormField from "../Form/FormFields/TextFormField"; +import { navigate } from "raviger"; +import useAppHistory from "../../Common/hooks/useAppHistory"; +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"; +import { RequestResult } from "../../Utils/request/types.js"; +import useAuthUser from "../../Common/hooks/useAuthUser"; +import SpokeFacilityEditor from "./SpokeFacilityEditor.js"; +import careConfig from "@careConfig"; +import CoverImageEditModal from "./CoverImageEditModal"; import Loading from "../Common/Loading"; interface FacilityProps { @@ -95,18 +95,18 @@ type FacilityForm = { const initForm: FacilityForm = { facility_type: undefined, - name: '', + name: "", state: 0, district: 0, local_body: 0, ward: 0, - kasp_empanelled: 'false', + kasp_empanelled: "false", features: [], - address: '', - phone_number: '', - latitude: '', - longitude: '', - pincode: '', + address: "", + phone_number: "", + latitude: "", + longitude: "", + pincode: "", oxygen_capacity: undefined, type_b_cylinders: undefined, type_c_cylinders: undefined, @@ -119,7 +119,7 @@ const initForm: FacilityForm = { const initError: Record = Object.assign( {}, - ...Object.keys(initForm).map((k) => ({ [k]: '' })) + ...Object.keys(initForm).map((k) => ({ [k]: "" })), ); const initialState = { @@ -129,11 +129,11 @@ const initialState = { const facilityCreateReducer = (state = initialState, action: FormAction) => { switch (action.type) { - case 'set_form': + case "set_form": return { ...state, form: action.form }; - case 'set_errors': + case "set_errors": return { ...state, errors: action.errors }; - case 'set_state': { + case "set_state": { if (action.state) return action.state; return state; } @@ -146,11 +146,11 @@ export const FacilityCreate = (props: FacilityProps) => { const [state, dispatch] = useAutoSaveReducer( facilityCreateReducer, - initialState + initialState, ); const [isLoading, setIsLoading] = useState(false); const [currentStep, setCurrentStep] = useState(1); - const [createdFacilityId, setCreatedFacilityId] = useState(''); + const [createdFacilityId, setCreatedFacilityId] = useState(""); const [showAutoFilledPincode, setShowAutoFilledPincode] = useState(false); const [capacityData, setCapacityData] = useState>([]); const [doctorData, setDoctorData] = useState>([]); @@ -160,20 +160,19 @@ export const FacilityCreate = (props: FacilityProps) => { const [districtId, setDistrictId] = useState(); const [localBodyId, setLocalBodyId] = useState(); const { goBack } = useAppHistory(); - const headerText = !facilityId ? 'Create Facility' : 'Update Facility'; - const buttonText = !facilityId ? 'Save Facility' : 'Update Facility'; - const [isImageUploadChecked, setIsImageUploadChecked] = useState(false); // Track if the user wants to upload a cover image - + const headerText = !facilityId ? "Create Facility" : "Update Facility"; + const buttonText = !facilityId ? "Save Facility" : "Update Facility"; + const [isImageUploadChecked] = useState(false); const authUser = useAuthUser(); useEffect(() => { if ( authUser && - authUser.user_type !== 'StateAdmin' && - authUser.user_type !== 'DistrictAdmin' && - authUser.user_type !== 'DistrictLabAdmin' + authUser.user_type !== "StateAdmin" && + authUser.user_type !== "DistrictAdmin" && + authUser.user_type !== "DistrictLabAdmin" ) { - navigate('/facility'); + navigate("/facility"); Notification.Error({ msg: "You don't have permission to perform this action. Contact the admin", }); @@ -198,42 +197,61 @@ export const FacilityCreate = (props: FacilityProps) => { id: String(districtId), }, prefetch: !!districtId, - } + }, ); const getSteps = (): Step[] => { return [ { id: 1, - name: 'Facility details', + name: "Facility details", onClick: () => { setCurrentStep(1); }, - status: currentStep === 1 ? 'current' : 'complete', + status: currentStep === 1 ? "current" : "complete", disabled: currentStep > 1, }, { id: 2, - name: 'Bed Capacity', + name: "Bed Capacity", onClick: () => { setCurrentStep(2); }, status: currentStep === 2 - ? 'current' + ? "current" : currentStep > 2 - ? 'complete' - : 'upcoming', - disabled: createdFacilityId == '', + ? "complete" + : "upcoming", + disabled: createdFacilityId === "", }, { id: 3, - name: 'Staff Capacity', + name: "Staff Capacity", onClick: () => { setCurrentStep(3); }, - disabled: createdFacilityId == '', - status: currentStep === 3 ? 'current' : 'upcoming', + status: + currentStep === 3 + ? "current" + : currentStep > 3 + ? "complete" + : "upcoming", + disabled: createdFacilityId === "", + }, + { + id: 4, + name: "Cover Image", + onClick: () => { + setCurrentStep(4); + }, + status: + currentStep === 4 + ? "current" + : currentStep > 4 + ? "complete" + : "upcoming", + disabled: createdFacilityId === "", }, ]; }; @@ -245,7 +263,7 @@ export const FacilityCreate = (props: FacilityProps) => { id: String(localBodyId), }, prefetch: !!localBodyId, - } + }, ); const facilityQuery = useQuery(routes.getPermittedFacility, { @@ -258,25 +276,25 @@ export const FacilityCreate = (props: FacilityProps) => { setIsLoading(true); if (res?.ok && data) { const formData = { - facility_type: data.facility_type ? data.facility_type : '', - name: data.name ? data.name : '', + facility_type: data.facility_type ? 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: data.pincode ? data.pincode : '', + kasp_empanelled: "", + address: data.address ? data.address : "", + pincode: data.pincode ? data.pincode : "", phone_number: data.phone_number ? data.phone_number.length == 10 - ? '+91' + data.phone_number + ? "+91" + data.phone_number : data.phone_number - : '', - latitude: data.latitude ? parseFloat(data.latitude).toFixed(7) : '', + : "", + latitude: data.latitude ? parseFloat(data.latitude).toFixed(7) : "", longitude: data.longitude ? parseFloat(data.longitude).toFixed(7) - : '', + : "", type_b_cylinders: data.type_b_cylinders, type_c_cylinders: data.type_c_cylinders, type_d_cylinders: data.type_d_cylinders, @@ -286,7 +304,7 @@ export const FacilityCreate = (props: FacilityProps) => { expected_oxygen_requirement: data.expected_oxygen_requirement, oxygen_capacity: data.oxygen_capacity, }; - dispatch({ type: 'set_form', form: formData }); + dispatch({ type: "set_form", form: formData }); setStateId(data.state); setDistrictId(data.district); setLocalBodyId(data.local_body); @@ -299,12 +317,12 @@ export const FacilityCreate = (props: FacilityProps) => { }); const { data: stateData, loading: isStateLoading } = useQuery( - routes.statesList + routes.statesList, ); const handleChange = (e: FieldChangeEvent) => { dispatch({ - type: 'set_form', + type: "set_form", form: { ...state.form, [e.name]: e.value }, }); }; @@ -312,7 +330,7 @@ export const FacilityCreate = (props: FacilityProps) => { const handleLocationChange = (location: google.maps.LatLng | undefined) => { if (location) { dispatch({ - type: 'set_form', + type: "set_form", form: { ...state.form, latitude: location.lat().toFixed(7), @@ -329,7 +347,7 @@ export const FacilityCreate = (props: FacilityProps) => { const pincodeDetails = await getPincodeDetails( e.value, - careConfig.govDataApiKey + careConfig.govDataApiKey, ); if (!pincodeDetails) return; @@ -350,7 +368,7 @@ export const FacilityCreate = (props: FacilityProps) => { if (!matchedDistrict) return; dispatch({ - type: 'set_form', + type: "set_form", form: { ...state.form, state: matchedState.id, @@ -367,12 +385,12 @@ export const FacilityCreate = (props: FacilityProps) => { }; const handleSelectCurrentLocation = ( - setCenter: (lat: number, lng: number) => void + setCenter: (lat: number, lng: number) => void, ) => { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition((position) => { dispatch({ - type: 'set_form', + type: "set_form", form: { ...state.form, latitude: String(position.coords.latitude), @@ -390,52 +408,47 @@ export const FacilityCreate = (props: FacilityProps) => { let invalidForm = false; Object.keys(state.form).forEach((field) => { switch (field) { - case 'facility_type': - case 'name': - case 'address': + case "facility_type": + case "name": + case "address": if (!state.form[field]) { - errors[field] = t('required'); + errors[field] = t("required"); invalidForm = true; } return; - case 'district': - case 'state': - case 'local_body': - case 'ward': + case "district": + case "state": + case "local_body": + case "ward": if (!Number(state.form[field])) { - errors[field] = t('required'); + errors[field] = t("required"); invalidForm = true; } return; - case 'pincode': - if (!validatePincode(state.form[field])) { - errors[field] = t('invalid_pincode'); - invalidForm = true; - } - return; - case 'phone_number': - // eslint-disable-next-line no-case-declarations + case "phone_number": { const phoneNumber = state.form[field]; if ( !phoneNumber || - !PhoneNumberValidator()(phoneNumber) === undefined || + PhoneNumberValidator()(phoneNumber) === undefined || !phonePreg(phoneNumber) ) { - errors[field] = t('invalid_phone_number'); + errors[field] = t("invalid_phone_number"); invalidForm = true; } return; - case 'latitude': + } + + case "latitude": if (!!state.form.latitude && !validateLatitude(state.form[field])) { - errors[field] = t('latitude_invalid'); + errors[field] = t("latitude_invalid"); invalidForm = true; } return; - case 'longitude': + case "longitude": if (!!state.form.longitude && !validateLongitude(state.form[field])) { - errors[field] = t('longitude_invalid'); + errors[field] = t("longitude_invalid"); invalidForm = true; } return; @@ -445,10 +458,10 @@ export const FacilityCreate = (props: FacilityProps) => { } }); if (invalidForm) { - dispatch({ type: 'set_errors', errors }); + dispatch({ type: "set_errors", errors }); return false; } - dispatch({ type: 'set_errors', errors }); + dispatch({ type: "set_errors", errors }); return true; }; const [isCoverImageModalOpen, setIsCoverImageModalOpen] = useState(false); @@ -501,8 +514,8 @@ export const FacilityCreate = (props: FacilityProps) => { if (res?.ok && requestData) { const id = requestData.id; - dispatch({ type: 'set_form', form: initForm }); - Notification.Success({ msg: 'Facility added successfully' }); + dispatch({ type: "set_form", form: initForm }); + Notification.Success({ msg: "Facility added successfully" }); setCreatedFacilityId(String(id)); setCurrentStep(2); if (isImageUploadChecked) { @@ -524,7 +537,7 @@ export const FacilityCreate = (props: FacilityProps) => { if (!capacityData || !capacityData.length) { capacityList = (
- {t('no_bed_types_found')} + {t("no_bed_types_found")}
); } else { @@ -539,7 +552,7 @@ export const FacilityCreate = (props: FacilityProps) => { id="total-bed-capacity" > { if (res) { const removeCurrentBedType = (bedTypeId: number | undefined) => { setCapacityData((state) => - state.filter((i) => i.id !== bedTypeId) + state.filter((i) => i.id !== bedTypeId), ); setBedCapacityKey((bedCapacityKey) => bedCapacityKey + 1); }; @@ -588,7 +601,7 @@ export const FacilityCreate = (props: FacilityProps) => { if (!doctorData || !doctorData.length) { doctorList = (
- {t('no_staff')} + {t("no_staff")}
); } else { @@ -597,14 +610,14 @@ export const FacilityCreate = (props: FacilityProps) => { {doctorData.map((data: DoctorModal) => { const removeCurrentDoctorData = (doctorId: number | undefined) => { setDoctorData((state) => - state.filter((i: DoctorModal) => i.id !== doctorId) + state.filter((i: DoctorModal) => i.id !== doctorId), ); setDocCapacityKey((docCapacityKey) => docCapacityKey + 1); }; return ( { const { res, data } = await request(routes.listDoctor, { @@ -635,53 +648,65 @@ export const FacilityCreate = (props: FacilityProps) => { }; switch (currentStep) { - case 3: + case 4: return ( -
- -
- +
setIsCoverImageModalOpen(true)} className="mt-4" - disabled={!isImageUploadChecked} > - {t('Upload Facility Image')} + {t("Upload Facility Image")} - + setIsCoverImageModalOpen(false)} - onSave={() => setIsCoverImageModalOpen(false)} + onSave={() => setIsCoverImageModalOpen(false)} facility={{ id: createdFacilityId, - name: state.form.name, - read_cover_image_url: '', + name: state.form.name, + read_cover_image_url: "", }} />
+ +
+ { + navigate(`/facility/${createdFacilityId}`); + }} + className="mt-4" + > + {t("Save Facility")} + +
+
+ ); + + case 3: + return ( + +
{ - navigate(`/facility/${createdFacilityId}`); + setCurrentStep(4); }} handleUpdate={async () => { const { res, data } = await request(routes.listDoctor, { @@ -695,7 +720,7 @@ export const FacilityCreate = (props: FacilityProps) => {
-
{t('staff_list')}
+
{t("staff_list")}
{doctorList} @@ -708,7 +733,7 @@ export const FacilityCreate = (props: FacilityProps) => { @@ -716,7 +741,7 @@ export const FacilityCreate = (props: FacilityProps) => { { setCurrentStep(3); }} @@ -733,12 +758,11 @@ export const FacilityCreate = (props: FacilityProps) => {
- {t('bed_capacity')} + {t("bed_capacity")}
{capacityList}
-
); case 1: @@ -747,7 +771,7 @@ export const FacilityCreate = (props: FacilityProps) => { {!facilityId && } @@ -756,7 +780,7 @@ export const FacilityCreate = (props: FacilityProps) => {
handleSubmit(e)}> { - dispatch({ type: 'set_state', state: newState }); + dispatch({ type: "set_state", state: newState }); setStateId(newState.form.state); setDistrictId(newState.form.district); setLocalBodyId(newState.form.local_body); @@ -765,28 +789,28 @@ export const FacilityCreate = (props: FacilityProps) => { />
o.text} optionValue={(o) => o.text} /> o.name} optionValue={(o) => o.id} />
@@ -794,16 +818,16 @@ export const FacilityCreate = (props: FacilityProps) => {
- {t('State and district auto-filled from pincode')} + {t("State and district auto-filled from pincode")}
)}
o.name} @@ -815,10 +839,10 @@ export const FacilityCreate = (props: FacilityProps) => { }} /> o.name} @@ -830,11 +854,11 @@ export const FacilityCreate = (props: FacilityProps) => { }} /> o.name} optionValue={(o) => o.id} @@ -845,32 +869,32 @@ export const FacilityCreate = (props: FacilityProps) => { }} /> { return { id: e.id, - name: e.number + ': ' + e.name, + name: e.number + ": " + e.name, }; })} optionLabel={(o) => o.name} optionValue={(o) => o.id} /> - + {facilityId && (
-

{t('spokes')}

+

{t("spokes")}

@@ -878,83 +902,83 @@ export const FacilityCreate = (props: FacilityProps) => { )}
} + trailing={} min={0} /> } - label={t('expected_burn_rate')} + trailing={} + label={t("expected_burn_rate")} min={0} /> } + trailing={} min={0} /> } + trailing={} min={0} /> } + trailing={} min={0} /> } - label={t('expected_burn_rate')} + trailing={} + label={t("expected_burn_rate")} min={0} /> } + trailing={} min={0} /> } + trailing={} min={0} />
{careConfig.kasp.enabled && ( (o ? 'Yes' : 'No')} + optionLabel={(o) => (o ? "Yes" : "No")} optionValue={(o) => String(o)} /> )} @@ -963,8 +987,8 @@ export const FacilityCreate = (props: FacilityProps) => {
@@ -980,7 +1004,7 @@ export const FacilityCreate = (props: FacilityProps) => { > - {t('Select location from map')} + {t("Select location from map")} @@ -1010,7 +1034,7 @@ export const FacilityCreate = (props: FacilityProps) => {
} placeholder="Longitude" />