From b7af5250c904f5a445a18990153d21df0f3619eb Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Fri, 15 Dec 2023 12:21:32 +0530 Subject: [PATCH 01/16] hide user conflict notification (#6869) --- src/Components/Users/UserAdd.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Components/Users/UserAdd.tsx b/src/Components/Users/UserAdd.tsx index d26d0832b27..26ba9e44b4b 100644 --- a/src/Components/Users/UserAdd.tsx +++ b/src/Components/Users/UserAdd.tsx @@ -189,6 +189,7 @@ export const UserAdd = (props: UserProps) => { setUsernameExists(userExistsEnums.checking); const { res: usernameCheck } = await request(routes.checkUsername, { pathParams: { username }, + silent: true, }); if (usernameCheck === undefined || usernameCheck.status === 409) setUsernameExists(userExistsEnums.exists); From 1f5ea20a5722f6cfb1d4df4130b8309f257abb60 Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Fri, 15 Dec 2023 18:00:14 +0530 Subject: [PATCH 02/16] daily rounds, clone last default to null (#6872) * daily rounds, clone last default to null * i don't know what this does * skip check for continue form --- src/Components/Patient/DailyRounds.tsx | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/Components/Patient/DailyRounds.tsx b/src/Components/Patient/DailyRounds.tsx index 4105cffb96c..651b278c0de 100644 --- a/src/Components/Patient/DailyRounds.tsx +++ b/src/Components/Patient/DailyRounds.tsx @@ -50,7 +50,7 @@ const initForm: any = { admitted_to: "", taken_at: null, rounds_type: "NORMAL", - clone_last: true, + clone_last: false, systolic: null, diastolic: null, pulse: null, @@ -223,7 +223,7 @@ export const DailyRounds = (props: any) => { RHYTHM_CHOICES.find((i) => i.text === res.data.rhythm)?.id) || "0", temperature: parseFloat(res.data.temperature), - clone_last: res.data.count > 0 ? true : false, + // clone_last: res.data.count > 0 ? true : false, }, }); } @@ -250,12 +250,6 @@ export const DailyRounds = (props: any) => { invalidForm = true; } return; - case "clone_last": - if (state.form.clone_last === null) { - errors[field] = "Please choose a value"; - invalidForm = true; - } - return; default: return; @@ -271,7 +265,7 @@ export const DailyRounds = (props: any) => { if (validForm) { setIsLoading(true); const baseData = { - clone_last: state.form.clone_last, + clone_last: state.form.clone_last ?? false, rounds_type: state.form.rounds_type, patient_category: state.form.patient_category, taken_at: state.form.taken_at @@ -479,7 +473,7 @@ export const DailyRounds = (props: any) => { /> )} - {(state.form.clone_last === false || id) && ( + {(!state.form.clone_last || id) && (
{ goBack()} /> Date: Tue, 19 Dec 2023 18:44:26 +0530 Subject: [PATCH 03/16] thank everyone (#6777) --- .github/workflows/thank-you.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/thank-you.yml b/.github/workflows/thank-you.yml index cd36e64d888..c8104ad73a5 100644 --- a/.github/workflows/thank-you.yml +++ b/.github/workflows/thank-you.yml @@ -1,7 +1,7 @@ name: Say thanks for the contributors on: - pull_request: + pull_request_target: types: - closed From 7d15c037d927d815b7bf2eca0dc5c8b9c78a4517 Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Tue, 19 Dec 2023 18:44:54 +0530 Subject: [PATCH 04/16] Remove Copilot for PR tags (#6725) --- .github/pull_request_template.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 892fea40ab3..b67b01cc863 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,9 +1,6 @@ -### WHAT -copilot:summary - ## Proposed Changes -- Fixes #issue? +- Fixes #issue_number - Change 1 - Change 2 - More? @@ -18,6 +15,3 @@ copilot:summary - [ ] Prep screenshot or demo video for changelog entry, and attach it to issue. - [ ] Request for Peer Reviews - [ ] Completion of QA - -### HOW -copilot:walkthrough From 7c21b80c87f00eb50c81dda5cbf58537ea226ca8 Mon Sep 17 00:00:00 2001 From: Pranshu Aggarwal <70687348+Pranshu1902@users.noreply.github.com> Date: Wed, 20 Dec 2023 13:58:42 +0530 Subject: [PATCH 05/16] Disable critical care submit if onle basic editor is filled (#6860) Co-authored-by: Mohammed Nihal <57055998+nihal467@users.noreply.github.com> --- .../Recording/CriticalCare__Recording.res | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Components/CriticalCareRecording/Recording/CriticalCare__Recording.res b/src/Components/CriticalCareRecording/Recording/CriticalCare__Recording.res index 0316430dcd3..b0ff4fd04cc 100644 --- a/src/Components/CriticalCareRecording/Recording/CriticalCare__Recording.res +++ b/src/Components/CriticalCareRecording/Recording/CriticalCare__Recording.res @@ -237,7 +237,9 @@ let make = (~id, ~facilityId, ~patientId, ~consultationId, ~dailyRound) => { From b4a7fbdc3ce37ba1d69727a0ae6e654e7c7f6026 Mon Sep 17 00:00:00 2001 From: Ashesh <3626859+Ashesh3@users.noreply.github.com> Date: Wed, 20 Dec 2023 19:49:15 +0530 Subject: [PATCH 06/16] Add Telemedicine as a rounds type option (#6831) * Add Telemedicine round type * Refactor DailyRoundsList and DailyRounds to handle TELEMEDICINE rounds type * merge conflict fixes --- .../DailyRounds/DefaultLogUpdateCard.tsx | 4 ++++ .../Consultations/DailyRoundsList.tsx | 9 +++++---- src/Components/Patient/DailyRounds.tsx | 20 ++++++++++++------- src/Components/Patient/models.tsx | 7 ++++++- src/Locale/en/Consultation.json | 3 ++- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/Components/Facility/Consultations/DailyRounds/DefaultLogUpdateCard.tsx b/src/Components/Facility/Consultations/DailyRounds/DefaultLogUpdateCard.tsx index ff738f4acb6..a0a4f2280cf 100644 --- a/src/Components/Facility/Consultations/DailyRounds/DefaultLogUpdateCard.tsx +++ b/src/Components/Facility/Consultations/DailyRounds/DefaultLogUpdateCard.tsx @@ -53,6 +53,10 @@ const DefaultLogUpdateCard = ({ round, ...props }: Props) => { attributeValue={getName(round.last_edited_by)} /> )} + { const [isLoading, setIsLoading] = useState(false); const [facilityName, setFacilityName] = useState(""); const [patientName, setPatientName] = useState(""); + const [consultationSuggestion, setConsultationSuggestion] = useState(""); const [prevReviewInterval, setPreviousReviewInterval] = useState(-1); const [prevAction, setPreviousAction] = useState("NO_ACTION"); const [hasPreviousLog, setHasPreviousLog] = useState(false); @@ -137,6 +138,7 @@ export const DailyRounds = (props: any) => { if (res.data) { setPatientName(res.data.name); setFacilityName(res.data.facility_object.name); + setConsultationSuggestion(res.data.last_consultation?.suggestion); setPreviousReviewInterval( Number(res.data.last_consultation.review_interval) ); @@ -250,7 +252,6 @@ export const DailyRounds = (props: any) => { invalidForm = true; } return; - default: return; } @@ -292,7 +293,7 @@ export const DailyRounds = (props: any) => { action: prevAction, review_interval: Number(prevReviewInterval), }; - if (state.form.rounds_type === "NORMAL") { + if (["NORMAL", "TELEMEDICINE"].includes(state.form.rounds_type)) { data = { ...data, bp: @@ -334,7 +335,7 @@ export const DailyRounds = (props: any) => { Notification.Success({ msg: "Consultation Updates details updated successfully", }); - if (state.form.rounds_type === "NORMAL") { + if (["NORMAL", "TELEMEDICINE"].includes(state.form.rounds_type)) { navigate( `/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}` ); @@ -347,7 +348,7 @@ export const DailyRounds = (props: any) => { Notification.Success({ msg: "Consultation Updates details created successfully", }); - if (state.form.rounds_type === "NORMAL") { + if (["NORMAL", "TELEMEDICINE"].includes(state.form.rounds_type)) { if (data.clone_last) { navigate( `/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/daily-rounds/${res.data.external_id}/update` @@ -450,8 +451,13 @@ export const DailyRounds = (props: any) => { className="w-full" label="Round Type" options={[ - { id: "NORMAL", text: "Normal" }, - { id: "VENTILATOR", text: "Critical Care" }, + ...[ + { id: "NORMAL", text: "Normal" }, + { id: "VENTILATOR", text: "Critical Care" }, + ], + ...(consultationSuggestion == "DC" + ? [{ id: "TELEMEDICINE", text: "Telemedicine" }] + : []), ]} optionLabel={(option) => option.text} optionValue={(option) => option.id} @@ -529,7 +535,7 @@ export const DailyRounds = (props: any) => { }} /> - {state.form.rounds_type === "NORMAL" && ( + {["NORMAL", "TELEMEDICINE"].includes(state.form.rounds_type) && ( <>

Vitals

diff --git a/src/Components/Patient/models.tsx b/src/Components/Patient/models.tsx index 3a856a04765..e1ce5d53050 100644 --- a/src/Components/Patient/models.tsx +++ b/src/Components/Patient/models.tsx @@ -269,7 +269,12 @@ export interface DailyRoundsOutput { quantity: number; } -export const DailyRoundTypes = ["NORMAL", "VENTILATOR", "AUTOMATED"] as const; +export const DailyRoundTypes = [ + "NORMAL", + "VENTILATOR", + "AUTOMATED", + "TELEMEDICINE", +] as const; export interface DailyRoundsModel { ventilator_spo2?: number; diff --git a/src/Locale/en/Consultation.json b/src/Locale/en/Consultation.json index 54b587eb81e..c633f7aaab3 100644 --- a/src/Locale/en/Consultation.json +++ b/src/Locale/en/Consultation.json @@ -15,5 +15,6 @@ "generated_summary_caution": "This is a computer generated summary using the information captured in the CARE system.", "NORMAL": "Normal", "VENTILATOR": "Critical Care", - "AUTOMATED": "Automated" + "AUTOMATED": "Automated", + "TELEMEDICINE": "Telemedicine" } From d5e342c4921797d70cd72eac034b1b4e945c438a Mon Sep 17 00:00:00 2001 From: Ashesh <3626859+Ashesh3@users.noreply.github.com> Date: Wed, 20 Dec 2023 20:25:18 +0530 Subject: [PATCH 07/16] Fix pincode api (#6884) --- src/Components/Facility/FacilityCreate.tsx | 2 +- src/Utils/utils.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Components/Facility/FacilityCreate.tsx b/src/Components/Facility/FacilityCreate.tsx index 584d577dcb1..e9547d5dddd 100644 --- a/src/Components/Facility/FacilityCreate.tsx +++ b/src/Components/Facility/FacilityCreate.tsx @@ -366,7 +366,7 @@ export const FacilityCreate = (props: FacilityProps) => { if (!fetchedDistricts) return; const matchedDistrict = fetchedDistricts.find((district) => { - return includesIgnoreCase(district.name, pincodeDetails.district); + return includesIgnoreCase(district.name, pincodeDetails.districtname); }); if (!matchedDistrict) return; diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts index 90e6b323db7..df6bd46d131 100644 --- a/src/Utils/utils.ts +++ b/src/Utils/utils.ts @@ -214,13 +214,14 @@ export const parseCsvFile = async ( export const getPincodeDetails = async (pincode: string, apiKey: string) => { const response = await fetch( - `https://api.data.gov.in/resource/5c2f62fe-5afa-4119-a499-fec9d604d5bd?api-key=${apiKey}&format=json&filters[pincode]=${pincode}&limit=1` + `https://api.data.gov.in/resource/6176ee09-3d56-4a3b-8115-21841576b2f6?api-key=${apiKey}&format=json&filters[pincode]=${pincode}&limit=1` ); const data = await response.json(); return data.records[0]; }; export const includesIgnoreCase = (str1: string, str2: string) => { + if (!str1 || !str2) return false; const lowerCaseStr1 = str1.toLowerCase(); const lowerCaseStr2 = str2.toLowerCase(); return ( From 4c08326c152b52bc02d2a8e456808879bf9f738b Mon Sep 17 00:00:00 2001 From: Ashraf Mohammed <98876115+AshrafMd-1@users.noreply.github.com> Date: Wed, 20 Dec 2023 20:26:28 +0530 Subject: [PATCH 08/16] remove irrelevant columns (#6878) --- src/Components/Facility/TreatmentSummary.tsx | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/Components/Facility/TreatmentSummary.tsx b/src/Components/Facility/TreatmentSummary.tsx index 3ff5d47d5e0..7adb4dcfbe2 100644 --- a/src/Components/Facility/TreatmentSummary.tsx +++ b/src/Components/Facility/TreatmentSummary.tsx @@ -11,6 +11,7 @@ import { PatientModel } from "../Patient/models"; import { GENDER_TYPES } from "../../Common/constants"; import { formatAge, formatDate, formatDateTime } from "../../Utils/utils"; + const Loading = lazy(() => import("../Common/Loading")); const TreatmentSummary = (props: any) => { @@ -135,7 +136,7 @@ const TreatmentSummary = (props: any) => { Age :{" "} {formatAge(patientData.age, patientData.date_of_birth, true)}
-
+
Date of admission : {consultationData.admitted @@ -143,12 +144,6 @@ const TreatmentSummary = (props: any) => { : " --/--/----"}
-
- Date of positive : - {patientData.date_of_result - ? formatDate(patientData.date_of_result) - : " --/--/----"} -
@@ -157,7 +152,7 @@ const TreatmentSummary = (props: any) => { {GENDER_TYPES.find((i) => i.id === patientData.gender)?.text}
-
+
Contact person : {" "} @@ -166,15 +161,6 @@ const TreatmentSummary = (props: any) => { : " -"}
- -
- Date of negative : - - {patientData.disease_status == "NEGATIVE" - ? formatDate(patientData.modified_date) - : " --/--/----"} - -
From dc6d0493aff3a2d19d1b5ec437b22feedf9c47e4 Mon Sep 17 00:00:00 2001 From: Vedant Jain <129421822+jainvedant392@users.noreply.github.com> Date: Wed, 20 Dec 2023 20:27:26 +0530 Subject: [PATCH 09/16] feat: show correct error message for interval server errors (#6873) * feat: show correct error message for interval server errors * modify handleResponse.ts --- src/Redux/fireRequest.tsx | 30 +++-------------------------- src/Utils/request/handleResponse.ts | 11 ++--------- 2 files changed, 5 insertions(+), 36 deletions(-) diff --git a/src/Redux/fireRequest.tsx b/src/Redux/fireRequest.tsx index 892e6bd2ee9..876877799d8 100644 --- a/src/Redux/fireRequest.tsx +++ b/src/Redux/fireRequest.tsx @@ -149,7 +149,7 @@ export const fireRequest = ( } // 4xx Errors - if (error.response.status > 400 && error.response.status < 500) { + if (error.response.status > 400 && error.response.status < 600) { if (error.response.data && error.response.data.detail) { if (error.response.data.code === "token_not_valid") { window.location.href = `/session-expired?redirect=${window.location.href}`; @@ -167,14 +167,6 @@ export const fireRequest = ( } return; } - - // 5xx Errors - if (error.response.status >= 500 && error.response.status <= 599) { - Notification.Error({ - msg: "Something went wrong...!", - }); - return; - } } else { return error.response; } @@ -264,7 +256,7 @@ export const fireRequestV2 = ( } // 4xx Errors - if (error.response.status > 400 && error.response.status < 500) { + if (error.response.status > 400 && error.response.status < 600) { if (error.response.data && error.response.data.detail) { Notification.Error({ msg: error.response.data.detail, @@ -279,14 +271,6 @@ export const fireRequestV2 = ( } return; } - - // 5xx Errors - if (error.response.status >= 500 && error.response.status <= 599) { - Notification.Error({ - msg: "Something went wrong...!", - }); - return; - } } }); }; @@ -374,7 +358,7 @@ export const fireRequestForFiles = ( } // 4xx Errors - if (error.response.status > 400 && error.response.status < 500) { + if (error.response.status > 400 && error.response.status < 600) { if (error.response.status === 429) { return error.response; } else if (error.response.data && error.response.data.detail) { @@ -388,14 +372,6 @@ export const fireRequestForFiles = ( } return; } - - // 5xx Errors - if (error.response.status >= 500 && error.response.status <= 599) { - Notification.Error({ - msg: "Something went wrong...!", - }); - return; - } } }); }; diff --git a/src/Utils/request/handleResponse.ts b/src/Utils/request/handleResponse.ts index 8698919c869..c1139af141d 100644 --- a/src/Utils/request/handleResponse.ts +++ b/src/Utils/request/handleResponse.ts @@ -12,21 +12,14 @@ export default function handleResponse( return; } - // 5xx errors - if (res.status >= 500 && res.status < 600) { - console.error("Server error", res); - notify?.Error({ msg: "Something went wrong...!" }); - return; - } - // 400/406 Bad Request if (res.status === 400 || res.status === 406) { notify?.BadRequest({ errs: error }); return; } - // Other 400 Errors - if (res.status >= 400) { + // Other Errors between 400-599 (inclusive) + if (res.status >= 400 && res.status < 600) { // Invalid token if (!silent && error?.code === "token_not_valid") { navigate(`/session-expired?redirect=${window.location.href}`); From 541f9b2af02299f64189224bee17de577e14b867 Mon Sep 17 00:00:00 2001 From: Ashesh <3626859+Ashesh3@users.noreply.github.com> Date: Wed, 20 Dec 2023 20:28:33 +0530 Subject: [PATCH 10/16] Update GitHub action versions (#6863) * Update action versions * Update ossar-analysis.yml --- .github/workflows/deploy.yaml | 69 ++++++++++++++++++---------- .github/workflows/linter.yml | 6 +-- .github/workflows/ossar-analysis.yml | 4 +- 3 files changed, 50 insertions(+), 29 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 3c9d6aa28cb..b90adb20138 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -35,7 +35,7 @@ jobs: uses: docker/setup-buildx-action@v2 - name: Cache Docker layers - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ hashFiles('package-lock.json', 'Dockerfile') }} @@ -87,7 +87,7 @@ jobs: uses: docker/setup-buildx-action@v2 - name: Cache Docker layers - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ hashFiles('package-lock.json', 'Dockerfile') }} @@ -149,7 +149,7 @@ jobs: uses: docker/setup-buildx-action@v2 - name: Cache Docker layers - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ hashFiles('package-lock.json', 'Dockerfile') }} @@ -188,6 +188,9 @@ jobs: needs: build-staging name: Deploy to staging GCP cluster runs-on: ubuntu-latest + - uses: actions/setup-node@v3 + with: + node-version: '20' environment: name: Staging-GCP url: https://care-staging.ohc.network/ @@ -201,20 +204,20 @@ jobs: ref: main # Setup gcloud CLI - - uses: google-github-actions/setup-gcloud@94337306dda8180d967a56932ceb4ddcf01edae7 + - uses: google-github-actions/setup-gcloud@v2 with: service_account_key: ${{ secrets.GKE_SA_KEY }} project_id: ${{ secrets.GKE_PROJECT }} # Get the GKE credentials so we can deploy to the cluster - - uses: google-github-actions/get-gke-credentials@fb08709ba27618c31c09e014e1d8364b02e5042e + - uses: google-github-actions/get-gke-credentials@v2 with: cluster_name: ${{ secrets.GKE_CLUSTER }} location: ${{ secrets.GKE_ZONE }} credentials: ${{ secrets.GKE_SA_KEY }} - name: install kubectl - uses: azure/setup-kubectl@v3.0 + uses: azure/setup-kubectl@v3 with: version: "v1.23.6" id: install @@ -230,6 +233,9 @@ jobs: needs: build-production name: Deploy to GKE Manipur runs-on: ubuntu-latest + - uses: actions/setup-node@v3 + with: + node-version: '20' environment: name: Production-Manipur url: https://care.mn.gov.in @@ -243,20 +249,20 @@ jobs: ref: main # Setup gcloud CLI - - uses: google-github-actions/setup-gcloud@94337306dda8180d967a56932ceb4ddcf01edae7 + - uses: google-github-actions/setup-gcloud@v2 with: service_account_key: ${{ secrets.GKE_SA_KEY }} project_id: ${{ secrets.GKE_PROJECT }} # Get the GKE credentials so we can deploy to the cluster - - uses: google-github-actions/get-gke-credentials@fb08709ba27618c31c09e014e1d8364b02e5042e + - uses: google-github-actions/get-gke-credentials@v2 with: cluster_name: ${{ secrets.GKE_CLUSTER }} location: ${{ secrets.GKE_ZONE }} credentials: ${{ secrets.GKE_SA_KEY }} - name: install kubectl - uses: azure/setup-kubectl@v3.0 + uses: azure/setup-kubectl@v3 with: version: "v1.23.6" id: install @@ -272,6 +278,9 @@ jobs: needs: build-production name: Deploy to GKE Karnataka runs-on: ubuntu-latest + - uses: actions/setup-node@v3 + with: + node-version: '20' environment: name: Production-Karnataka url: https://karnataka.care @@ -285,20 +294,20 @@ jobs: ref: main # Setup gcloud CLI - - uses: google-github-actions/setup-gcloud@94337306dda8180d967a56932ceb4ddcf01edae7 + - uses: google-github-actions/setup-gcloud@v2 with: service_account_key: ${{ secrets.GKE_SA_KEY }} project_id: ${{ secrets.GKE_PROJECT }} # Get the GKE credentials so we can deploy to the cluster - - uses: google-github-actions/get-gke-credentials@fb08709ba27618c31c09e014e1d8364b02e5042e + - uses: google-github-actions/get-gke-credentials@v2 with: cluster_name: ${{ secrets.GKE_CLUSTER }} location: ${{ secrets.GKE_ZONE }} credentials: ${{ secrets.GKE_SA_KEY }} - name: install kubectl - uses: azure/setup-kubectl@v3.0 + uses: azure/setup-kubectl@v3 with: version: "v1.23.6" id: install @@ -314,6 +323,9 @@ jobs: needs: build-production name: Deploy to GKE Sikkim runs-on: ubuntu-latest + - uses: actions/setup-node@v3 + with: + node-version: '20' environment: name: Production-Sikkim url: https://care.sikkim.gov.in @@ -327,20 +339,20 @@ jobs: ref: main # Setup gcloud CLI - - uses: google-github-actions/setup-gcloud@94337306dda8180d967a56932ceb4ddcf01edae7 + - uses: google-github-actions/setup-gcloud@v2 with: service_account_key: ${{ secrets.GKE_SA_KEY }} project_id: ${{ secrets.GKE_PROJECT }} # Get the GKE credentials so we can deploy to the cluster - - uses: google-github-actions/get-gke-credentials@fb08709ba27618c31c09e014e1d8364b02e5042e + - uses: google-github-actions/get-gke-credentials@v2 with: cluster_name: ${{ secrets.GKE_CLUSTER }} location: ${{ secrets.GKE_ZONE }} credentials: ${{ secrets.GKE_SA_KEY }} - name: install kubectl - uses: azure/setup-kubectl@v3.0 + uses: azure/setup-kubectl@v3 with: version: "v1.23.6" id: install @@ -356,6 +368,9 @@ jobs: needs: build-production name: Deploy to GKE Assam runs-on: ubuntu-latest + - uses: actions/setup-node@v3 + with: + node-version: '20' environment: name: Production-Assam url: https://care.assam.gov.in @@ -369,20 +384,20 @@ jobs: ref: main # Setup gcloud CLI - - uses: google-github-actions/setup-gcloud@94337306dda8180d967a56932ceb4ddcf01edae7 + - uses: google-github-actions/setup-gcloud@v2 with: service_account_key: ${{ secrets.GKE_SA_KEY }} project_id: ${{ secrets.GKE_PROJECT }} # Get the GKE credentials so we can deploy to the cluster - - uses: google-github-actions/get-gke-credentials@fb08709ba27618c31c09e014e1d8364b02e5042e + - uses: google-github-actions/get-gke-credentials@v2 with: cluster_name: ${{ secrets.GKE_CLUSTER }} location: ${{ secrets.GKE_ZONE }} credentials: ${{ secrets.GKE_SA_KEY }} - name: install kubectl - uses: azure/setup-kubectl@v3.0 + uses: azure/setup-kubectl@v3 with: version: "v1.23.6" id: install @@ -398,6 +413,9 @@ jobs: needs: build-production name: Deploy to GKE Nagaland runs-on: ubuntu-latest + - uses: actions/setup-node@v3 + with: + node-version: '20' environment: name: Production - Nagaland url: https://care.nagaland.gov.in @@ -411,20 +429,20 @@ jobs: ref: main # Setup gcloud CLI - - uses: google-github-actions/setup-gcloud@94337306dda8180d967a56932ceb4ddcf01edae7 + - uses: google-github-actions/setup-gcloud@v2 with: service_account_key: ${{ secrets.GKE_SA_KEY }} project_id: ${{ secrets.GKE_PROJECT }} # Get the GKE credentials, so we can deploy to the cluster - - uses: google-github-actions/get-gke-credentials@fb08709ba27618c31c09e014e1d8364b02e5042e + - uses: google-github-actions/get-gke-credentials@v2 with: cluster_name: ${{ secrets.GKE_CLUSTER }} location: ${{ secrets.GKE_ZONE }} credentials: ${{ secrets.GKE_SA_KEY }} - name: install kubectl - uses: azure/setup-kubectl@v3.0 + uses: azure/setup-kubectl@v3 with: version: "v1.23.6" id: install @@ -440,6 +458,9 @@ jobs: needs: build-production name: Deploy to GKE Meghalaya runs-on: ubuntu-latest + - uses: actions/setup-node@v3 + with: + node-version: '20' environment: name: Production-Meghalaya url: https://care.meghealth.gov.in @@ -453,20 +474,20 @@ jobs: ref: main # Setup gcloud CLI - - uses: google-github-actions/setup-gcloud@94337306dda8180d967a56932ceb4ddcf01edae7 + - uses: google-github-actions/setup-gcloud@v2 with: service_account_key: ${{ secrets.GKE_SA_KEY }} project_id: ${{ secrets.GKE_PROJECT }} # Get the GKE credentials, so we can deploy to the cluster - - uses: google-github-actions/get-gke-credentials@fb08709ba27618c31c09e014e1d8364b02e5042e + - uses: google-github-actions/get-gke-credentials@v2 with: cluster_name: ${{ secrets.GKE_CLUSTER }} location: ${{ secrets.GKE_ZONE }} credentials: ${{ secrets.GKE_SA_KEY }} - name: install kubectl - uses: azure/setup-kubectl@v3.0 + uses: azure/setup-kubectl@v3 with: version: "v1.23.6" id: install diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index ce4bd271cf7..2bf60f375fc 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -17,12 +17,12 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: - node-version: "18" + node-version: '20' - name: Install dependencies run: npm ci diff --git a/.github/workflows/ossar-analysis.yml b/.github/workflows/ossar-analysis.yml index c213148091f..4e806124e77 100644 --- a/.github/workflows/ossar-analysis.yml +++ b/.github/workflows/ossar-analysis.yml @@ -17,7 +17,7 @@ jobs: steps: # Checkout your code repository to scan - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. @@ -30,7 +30,7 @@ jobs: # Run open source static analysis tools - name: Run OSSAR - uses: github/ossar-action@v1 + uses: github/ossar-action@fae13e456b9973657a670eef6bccc3a4c2b5153d id: ossar # Upload results to the Security tab From 83c452408a9a0f275a8131b0bd044b2691924daf Mon Sep 17 00:00:00 2001 From: Gokulram A Date: Wed, 20 Dec 2023 20:29:15 +0530 Subject: [PATCH 11/16] Redesign location card UI (#6853) * redesign location card * used RecordMeta component for created and modified date --- src/Components/Assets/AssetTypes.tsx | 1 - .../Facility/LocationManagement.tsx | 87 +++++++++++-------- src/Components/Facility/models.tsx | 5 +- 3 files changed, 55 insertions(+), 38 deletions(-) diff --git a/src/Components/Assets/AssetTypes.tsx b/src/Components/Assets/AssetTypes.tsx index 041d3d0a81e..97334f6af49 100644 --- a/src/Components/Assets/AssetTypes.tsx +++ b/src/Components/Assets/AssetTypes.tsx @@ -20,7 +20,6 @@ export interface AssetLocationObject { id: string; name: string; }; - middleware_address?: string; } export enum AssetType { diff --git a/src/Components/Facility/LocationManagement.tsx b/src/Components/Facility/LocationManagement.tsx index c018a7c222b..d378dbf9953 100644 --- a/src/Components/Facility/LocationManagement.tsx +++ b/src/Components/Facility/LocationManagement.tsx @@ -6,6 +6,7 @@ import Page from "../Common/components/Page"; import routes from "../../Redux/api"; import PaginatedList from "../../CAREUI/misc/PaginatedList"; import { LocationModel } from "./models"; +import RecordMeta from "../../CAREUI/display/RecordMeta"; const Loading = lazy(() => import("../Common/Loading")); @@ -51,10 +52,11 @@ export default function LocationManagement({ facilityId }: Props) { - - className="my-8 flex grow flex-col gap-3 lg:mx-8"> - {(item) => } - +
+ className="my-8 grid gap-3 @4xl:grid-cols-2 @6xl:grid-cols-3 @[100rem]:grid-cols-4 lg:mx-8"> + {(item) => } + +
@@ -69,43 +71,56 @@ const Location = ({ name, description, middleware_address, + location_type, + created_date, + modified_date, id, }: LocationModel) => ( -
-
-
-

- {name} -

- {description || "-"} -

-

-

- {middleware_address} -

+
+
+
+
+

{name}

+
+

+ {location_type} +

+
+
+ + + Edit +
+

+ {description || "-"} +

+

+ Middleware Address: +

+

+ {middleware_address || "-"} +

-
- - - Edit - - - - Manage Beds - + + + Manage Beds + + +
+ +
); diff --git a/src/Components/Facility/models.tsx b/src/Components/Facility/models.tsx index 92daaf4ca5b..bfb5750504a 100644 --- a/src/Components/Facility/models.tsx +++ b/src/Components/Facility/models.tsx @@ -1,7 +1,7 @@ import { AssignedToObjectModel, DailyRoundsModel } from "../Patient/models"; import { ProcedureType } from "../Common/prescription-builder/ProcedureBuilder"; import { NormalPrescription, PRNPrescription } from "../Medicine/models"; -import { AssetData } from "../Assets/AssetTypes"; +import { AssetData, AssetLocationType } from "../Assets/AssetTypes"; import { UserBareMinimum } from "../Users/models"; import { RouteToFacility } from "../Common/RouteToFacilitySelect"; import { ConsultationDiagnosis, CreateDiagnosis } from "../Diagnosis/types"; @@ -205,9 +205,12 @@ export interface LocationModel { name?: string; description?: string; middleware_address?: string; + location_type?: AssetLocationType; facility?: { name: string; }; + created_date?: string; + modified_date?: string; } export interface BedModel { From 23af9e05f50490412f630443c42aa6c3c7148d6f Mon Sep 17 00:00:00 2001 From: Pranshu Aggarwal <70687348+Pranshu1902@users.noreply.github.com> Date: Wed, 20 Dec 2023 20:34:28 +0530 Subject: [PATCH 12/16] Add Consultation Specific route for Doctor Notes (#6851) * add new route * refactor * show consultation specific notes by passing consultation param in api * use useQuery * refactor * fix offset calls * refactor props * use common component * separate files for notes * auto fetch on adding new note * refactor * remove dispatch * remove dispatch on patient notes * use request instead of usequery on consultation notes page * replace useQuery with request on patient notes * remove dispatch * useQuery and change model name --- .../Facility/ConsultationDetails/index.tsx | 1 + .../ConsultationDoctorNotes/index.tsx | 135 ++++++++++++++++++ src/Components/Facility/DoctorNote.tsx | 45 ++++++ .../Facility/PatientConsultationNotesList.tsx | 87 +++++++++++ src/Components/Facility/PatientNotesList.tsx | 125 +++++----------- .../Facility/PatientNotesSlideover.tsx | 48 +++++-- src/Components/Facility/models.tsx | 6 + src/Components/Patient/PatientNotes.tsx | 40 ++++-- src/Redux/api.tsx | 5 + src/Routers/routes/ConsultationRoutes.tsx | 9 ++ 10 files changed, 388 insertions(+), 113 deletions(-) create mode 100644 src/Components/Facility/ConsultationDoctorNotes/index.tsx create mode 100644 src/Components/Facility/DoctorNote.tsx create mode 100644 src/Components/Facility/PatientConsultationNotesList.tsx diff --git a/src/Components/Facility/ConsultationDetails/index.tsx b/src/Components/Facility/ConsultationDetails/index.tsx index 54eee52878e..c1086a67221 100644 --- a/src/Components/Facility/ConsultationDetails/index.tsx +++ b/src/Components/Facility/ConsultationDetails/index.tsx @@ -475,6 +475,7 @@ export const ConsultationDetails = (props: any) => { )} diff --git a/src/Components/Facility/ConsultationDoctorNotes/index.tsx b/src/Components/Facility/ConsultationDoctorNotes/index.tsx new file mode 100644 index 00000000000..dd96ef9af1e --- /dev/null +++ b/src/Components/Facility/ConsultationDoctorNotes/index.tsx @@ -0,0 +1,135 @@ +import { useState } from "react"; +import * as Notification from "../../../Utils/Notifications.js"; +import Page from "../../Common/components/Page"; +import TextFormField from "../../Form/FormFields/TextFormField"; +import ButtonV2 from "../../Common/components/ButtonV2"; +import CareIcon from "../../../CAREUI/icons/CareIcon"; +import { NonReadOnlyUsers } from "../../../Utils/AuthorizeFor"; +import { useMessageListener } from "../../../Common/hooks/useMessageListener"; +import PatientConsultationNotesList from "../PatientConsultationNotesList.js"; +import { PatientNoteStateType } from "../models.js"; +import routes from "../../../Redux/api.js"; +import request from "../../../Utils/request/request.js"; +import useQuery from "../../../Utils/request/useQuery.js"; + +interface ConsultationDoctorNotesProps { + patientId: string; + facilityId: string; + consultationId: string; +} + +const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { + const { patientId, facilityId, consultationId } = props; + + const [patientActive, setPatientActive] = useState(true); + const [noteField, setNoteField] = useState(""); + const [reload, setReload] = useState(false); + const [facilityName, setFacilityName] = useState(""); + const [patientName, setPatientName] = useState(""); + + const initialData: PatientNoteStateType = { + notes: [], + cPage: 1, + totalPages: 1, + }; + const [state, setState] = useState(initialData); + + const onAddNote = async () => { + const payload = { + note: noteField, + consultation: consultationId, + }; + if (!/\S+/.test(noteField)) { + Notification.Error({ + msg: "Note Should Contain At Least 1 Character", + }); + return; + } + + const { res } = await request(routes.addPatientNote, { + pathParams: { + patientId: patientId, + }, + body: payload, + }); + + if (res?.status === 201) { + Notification.Success({ msg: "Note added successfully" }); + setState({ ...state, cPage: 1 }); + setNoteField(""); + setReload(true); + } + }; + + useQuery(routes.getPatient, { + pathParams: { id: patientId }, + onResponse: ({ data }) => { + if (data) { + setPatientActive(data.is_active ?? true); + setPatientName(data.name ?? ""); + setFacilityName(data.facility_object?.name ?? ""); + } + }, + }); + + useMessageListener((data) => { + const message = data?.message; + if ( + (message?.from == "patient/doctor_notes/create" || + message?.from == "patient/doctor_notes/edit") && + message?.facility_id == facilityId && + message?.patient_id == patientId + ) { + setReload(true); + } + }); + + return ( + +
+ + +
+ setNoteField(e.value)} + className="grow" + type="text" + errorClassName="hidden" + placeholder="Type your Note" + disabled={!patientActive} + /> + + + +
+
+
+ ); +}; + +export default ConsultationDoctorNotes; diff --git a/src/Components/Facility/DoctorNote.tsx b/src/Components/Facility/DoctorNote.tsx new file mode 100644 index 00000000000..85703a1e3d8 --- /dev/null +++ b/src/Components/Facility/DoctorNote.tsx @@ -0,0 +1,45 @@ +import InfiniteScroll from "react-infinite-scroll-component"; +import CircularProgress from "../Common/components/CircularProgress"; +import PatientNoteCard from "./PatientNoteCard"; +import { PatientNoteStateType } from "./models"; + +interface DoctorNoteProps { + state: PatientNoteStateType; + handleNext: () => void; +} + +const DoctorNote = (props: DoctorNoteProps) => { + const { state, handleNext } = props; + return ( +
+ {state.notes.length ? ( + + +
+ } + className="flex h-full flex-col-reverse p-2" + inverse={true} + dataLength={state.notes.length} + scrollableTarget="patient-notes-list" + > + {state.notes.map((note: any) => ( + + ))} + + ) : ( +
+ No Notes Found +
+ )} +
+ ); +}; + +export default DoctorNote; diff --git a/src/Components/Facility/PatientConsultationNotesList.tsx b/src/Components/Facility/PatientConsultationNotesList.tsx new file mode 100644 index 00000000000..f38de51110b --- /dev/null +++ b/src/Components/Facility/PatientConsultationNotesList.tsx @@ -0,0 +1,87 @@ +import { useEffect, useState } from "react"; +import { RESULTS_PER_PAGE_LIMIT } from "../../Common/constants"; +import CircularProgress from "../Common/components/CircularProgress"; +import routes from "../../Redux/api"; +import { PatientNoteStateType } from "./models"; +import useSlug from "../../Common/hooks/useSlug"; +import DoctorNote from "./DoctorNote"; +import request from "../../Utils/request/request"; + +interface PatientNotesProps { + state: PatientNoteStateType; + setState: any; + patientId: string; + facilityId: string; + reload?: boolean; + setReload?: any; +} + +const pageSize = RESULTS_PER_PAGE_LIMIT; + +const PatientConsultationNotesList = (props: PatientNotesProps) => { + const { state, setState, reload, setReload } = props; + const consultationId = useSlug("consultation") ?? ""; + + const [isLoading, setIsLoading] = useState(true); + + const fetchNotes = async () => { + setIsLoading(true); + const { data }: any = await request(routes.getPatientNotes, { + pathParams: { + patientId: props.patientId, + }, + query: { + consultation: consultationId, + offset: (state.cPage - 1) * RESULTS_PER_PAGE_LIMIT, + }, + }); + + if (state.cPage === 1) { + setState((prevState: any) => ({ + ...prevState, + notes: data.results, + totalPages: Math.ceil(data.count / pageSize), + })); + } else { + setState((prevState: any) => ({ + ...prevState, + notes: [...prevState.notes, ...data.results], + totalPages: Math.ceil(data.count / pageSize), + })); + } + setIsLoading(false); + setReload(false); + }; + + useEffect(() => { + if (reload) { + fetchNotes(); + } + }, [reload]); + + useEffect(() => { + setReload(true); + }, []); + + const handleNext = () => { + if (state.cPage < state.totalPages) { + setState((prevState: any) => ({ + ...prevState, + cPage: prevState.cPage + 1, + })); + setReload(true); + } + }; + + if (isLoading && !state.notes.length) { + return ( +
+ +
+ ); + } + + return ; +}; + +export default PatientConsultationNotesList; diff --git a/src/Components/Facility/PatientNotesList.tsx b/src/Components/Facility/PatientNotesList.tsx index 330bca4b06d..96f9dcad871 100644 --- a/src/Components/Facility/PatientNotesList.tsx +++ b/src/Components/Facility/PatientNotesList.tsx @@ -1,86 +1,68 @@ -import { useCallback, useState, useEffect } from "react"; -import { useDispatch } from "react-redux"; -import { statusType, useAbortableEffect } from "../../Common/utils"; -import { getPatientNotes } from "../../Redux/actions"; +import { useState, useEffect } from "react"; import { RESULTS_PER_PAGE_LIMIT } from "../../Common/constants"; import CircularProgress from "../Common/components/CircularProgress"; -import PatientNoteCard from "./PatientNoteCard"; -import InfiniteScroll from "react-infinite-scroll-component"; -import { NoteType } from "./PatientNoteCard"; +import DoctorNote from "./DoctorNote"; +import { PatientNoteStateType } from "./models"; +import routes from "../../Redux/api"; +import request from "../../Utils/request/request"; interface PatientNotesProps { - patientId: any; - facilityId: any; + state: PatientNoteStateType; + setState: any; + patientId: string; + facilityId: string; reload?: boolean; setReload?: any; } -interface StateType { - notes: NoteType[]; - cPage: number; - totalPages: number; -} - const pageSize = RESULTS_PER_PAGE_LIMIT; const PatientNotesList = (props: PatientNotesProps) => { - const { reload, setReload } = props; + const { state, setState, reload, setReload } = props; - const dispatch: any = useDispatch(); - const initialData: StateType = { notes: [], cPage: 1, totalPages: 1 }; - const [state, setState] = useState(initialData); const [isLoading, setIsLoading] = useState(true); - const fetchData = useCallback( - async (page = 1, status: statusType = { aborted: false }) => { - setIsLoading(true); - const res = await dispatch( - getPatientNotes(props.patientId, pageSize, (page - 1) * pageSize) - ); - if (!status.aborted) { - if (res && res.data) { - if (page === 1) { - setState({ - notes: res.data?.results, - cPage: page, - totalPages: Math.ceil(res.data.count / pageSize), - }); - } else { - setState((prevState: any) => ({ - ...prevState, - notes: [...prevState.notes, ...res.data.results], - cPage: page, - totalPages: Math.ceil(res.data.count / pageSize), - })); - } - } - setIsLoading(false); - } - }, - [props.patientId, dispatch] - ); + const fetchNotes = async () => { + setIsLoading(true); + const { data }: any = await request(routes.getPatientNotes, { + pathParams: { patientId: props.patientId }, + query: { offset: (state.cPage - 1) * RESULTS_PER_PAGE_LIMIT }, + }); + + if (state.cPage === 1) { + setState((prevState: any) => ({ + ...prevState, + notes: data.results, + totalPages: Math.ceil(data.count / pageSize), + })); + } else { + setState((prevState: any) => ({ + ...prevState, + notes: [...prevState.notes, ...data.results], + totalPages: Math.ceil(data.count / pageSize), + })); + } + setIsLoading(false); + setReload(false); + }; useEffect(() => { if (reload) { - fetchData(1); - setReload(false); + fetchNotes(); } }, [reload]); - useAbortableEffect( - (status: statusType) => { - fetchData(1, status); - }, - [fetchData] - ); + useEffect(() => { + setReload(true); + }, []); const handleNext = () => { if (state.cPage < state.totalPages) { - fetchData(state.cPage + 1); setState((prevState: any) => ({ ...prevState, cPage: prevState.cPage + 1, })); + setReload(true); } }; @@ -92,36 +74,7 @@ const PatientNotesList = (props: PatientNotesProps) => { ); } - return ( -
- {state.notes.length ? ( - - -
- } - className="flex h-full flex-col-reverse p-2" - inverse={true} - dataLength={state.notes.length} - scrollableTarget="patient-notes-list" - > - {state.notes.map((note: any) => ( - - ))} - - ) : ( -
- No Notes Found -
- )} -
- ); + return ; }; export default PatientNotesList; diff --git a/src/Components/Facility/PatientNotesSlideover.tsx b/src/Components/Facility/PatientNotesSlideover.tsx index b268500f6cf..8b08d9767db 100644 --- a/src/Components/Facility/PatientNotesSlideover.tsx +++ b/src/Components/Facility/PatientNotesSlideover.tsx @@ -1,8 +1,5 @@ import { useState, useEffect, Dispatch, SetStateAction } from "react"; -import { getPatient, addPatientNote } from "../../Redux/actions"; import * as Notification from "../../Utils/Notifications.js"; -import { useDispatch } from "react-redux"; -import PatientNotesList from "./PatientNotesList"; import { NonReadOnlyUsers } from "../../Utils/AuthorizeFor"; import CareIcon from "../../CAREUI/icons/CareIcon"; import { classNames } from "../../Utils/utils"; @@ -10,10 +7,15 @@ import TextFormField from "../Form/FormFields/TextFormField"; import ButtonV2 from "../Common/components/ButtonV2"; import { make as Link } from "../Common/components/Link.bs"; import { useMessageListener } from "../../Common/hooks/useMessageListener"; +import PatientConsultationNotesList from "./PatientConsultationNotesList"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; +import { PatientNoteStateType } from "./models"; interface PatientNotesProps { patientId: string; facilityId: string; + consultationId: string; setShowPatientNotesPopup: Dispatch>; } @@ -23,13 +25,20 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { const [noteField, setNoteField] = useState(""); const [reload, setReload] = useState(false); - const dispatch = useDispatch(); + const initialData: PatientNoteStateType = { + notes: [], + cPage: 1, + totalPages: 1, + }; + const [state, setState] = useState(initialData); - const { facilityId, patientId, setShowPatientNotesPopup } = props; + const { facilityId, patientId, consultationId, setShowPatientNotesPopup } = + props; - const onAddNote = () => { + const onAddNote = async () => { const payload = { note: noteField, + consultation: consultationId, }; if (!/\S+/.test(noteField)) { Notification.Error({ @@ -37,11 +46,16 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { }); return; } - dispatch(addPatientNote(patientId, payload)).then(() => { + const { res } = await request(routes.addPatientNote, { + pathParams: { patientId: patientId }, + body: payload, + }); + if (res?.status === 201) { Notification.Success({ msg: "Note added successfully" }); setNoteField(""); - setReload(!reload); - }); + setState({ ...state, cPage: 1 }); + setReload(true); + } }; useMessageListener((data) => { @@ -59,21 +73,23 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { useEffect(() => { async function fetchPatientName() { if (patientId) { - const res = await dispatch(getPatient({ id: patientId })); - if (res.data) { - setPatientActive(res.data.is_active); + const { data } = await request(routes.getPatient, { + pathParams: { id: patientId }, + }); + if (data) { + setPatientActive(data.is_active ?? true); } } } fetchPatientName(); - }, [dispatch, patientId]); + }, [patientId]); const notesActionIcons = (
{show && ( @@ -122,7 +138,9 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { {notesActionIcons}
{/* Doctor Notes Body */} - { const [facilityName, setFacilityName] = useState(""); const [patientName, setPatientName] = useState(""); - const dispatch = useDispatch(); + const initialData: PatientNoteStateType = { + notes: [], + cPage: 1, + totalPages: 1, + }; + const [state, setState] = useState(initialData); - const onAddNote = () => { + const onAddNote = async () => { const payload = { note: noteField, }; @@ -36,26 +42,34 @@ const PatientNotes = (props: PatientNotesProps) => { }); return; } - dispatch(addPatientNote(patientId, payload)).then(() => { + + const { res } = await request(routes.addPatientNote, { + pathParams: { patientId: patientId }, + body: payload, + }); + if (res?.status === 201) { Notification.Success({ msg: "Note added successfully" }); setNoteField(""); setReload(!reload); - }); + setState({ ...state, cPage: 1 }); + } }; useEffect(() => { async function fetchPatientName() { if (patientId) { - const res = await dispatch(getPatient({ id: patientId })); - if (res.data) { - setPatientActive(res.data.is_active); - setPatientName(res.data.name); - setFacilityName(res.data.facility_object.name); + const { data } = await request(routes.getPatient, { + pathParams: { id: patientId }, + }); + if (data) { + setPatientActive(data.is_active ?? true); + setPatientName(data.name ?? ""); + setFacilityName(data.facility_object?.name ?? ""); } } } fetchPatientName(); - }, [dispatch, patientId]); + }, [patientId]); useMessageListener((data) => { const message = data?.message; @@ -81,6 +95,8 @@ const PatientNotes = (props: PatientNotesProps) => { >
(), TRes: Type(), }, updatePatient: { @@ -614,10 +616,13 @@ const routes = { getPatientNotes: { path: "/api/v1/patient/{patientId}/notes/", method: "GET", + TBody: Type(), + TRes: Type>(), }, addPatientNote: { path: "/api/v1/patient/{patientId}/notes/", method: "POST", + TRes: Type(), }, sampleTestList: { path: "/api/v1/patient/{patientId}/test_sample/", diff --git a/src/Routers/routes/ConsultationRoutes.tsx b/src/Routers/routes/ConsultationRoutes.tsx index 4f1d6e7d75d..401358717eb 100644 --- a/src/Routers/routes/ConsultationRoutes.tsx +++ b/src/Routers/routes/ConsultationRoutes.tsx @@ -8,6 +8,7 @@ import { FileUpload } from "../../Components/Patient/FileUpload"; import { make as CriticalCareRecording } from "../../Components/CriticalCareRecording/CriticalCareRecording.bs"; import { ConsultationDetails } from "../../Components/Facility/ConsultationDetails"; import TreatmentSummary from "../../Components/Facility/TreatmentSummary"; +import ConsultationDoctorNotes from "../../Components/Facility/ConsultationDoctorNotes"; export default { "/facility/:facilityId/patient/:patientId/consultation": ({ @@ -129,6 +130,14 @@ export default { dailyRoundsListData={[]} /> ), + "/facility/:facilityId/patient/:patientId/consultation/:consultationId/notes": + ({ facilityId, patientId, consultationId }: any) => ( + + ), "/facility/:facilityId/patient/:patientId/consultation/:consultationId/:tab": ({ facilityId, patientId, consultationId, tab }: any) => ( Date: Thu, 21 Dec 2023 11:02:23 +0530 Subject: [PATCH 13/16] Rename "Admission Date" to encounter specific labels (#6719) * Rename `admission_date` to `encounter_date` * Whitelabel fields * fix colaescing issue * fix minor bug * minor fix --- src/Common/constants.tsx | 5 +- src/Components/DeathReport/DeathReport.tsx | 4 +- src/Components/Facility/ConsultationCard.tsx | 4 +- .../Facility/ConsultationDetails/index.tsx | 12 +-- src/Components/Facility/ConsultationForm.tsx | 75 ++++++++++--------- src/Components/Facility/DischargeModal.tsx | 6 +- src/Components/Facility/TreatmentSummary.tsx | 2 +- src/Components/Facility/models.tsx | 5 +- src/Components/Patient/ManagePatients.tsx | 18 ++--- src/Components/Patient/PatientFilter.tsx | 30 ++++---- src/Components/Patient/PatientInfoCard.tsx | 8 +- src/Components/Shifting/ShiftDetails.tsx | 5 +- 12 files changed, 87 insertions(+), 87 deletions(-) diff --git a/src/Common/constants.tsx b/src/Common/constants.tsx index 069a39e1539..23c02e389f3 100644 --- a/src/Common/constants.tsx +++ b/src/Common/constants.tsx @@ -330,7 +330,10 @@ export const CONSULTATION_SUGGESTION = [ { id: "OP", text: "OP Consultation" }, { id: "DC", text: "Domiciliary Care" }, { id: "DD", text: "Declare Death" }, -]; +] as const; + +export type ConsultationSuggestionValue = + (typeof CONSULTATION_SUGGESTION)[number]["id"]; export const ADMITTED_TO = [ { id: "1", text: "Isolation" }, diff --git a/src/Components/DeathReport/DeathReport.tsx b/src/Components/DeathReport/DeathReport.tsx index 9908b4fa852..3901996e119 100644 --- a/src/Components/DeathReport/DeathReport.tsx +++ b/src/Components/DeathReport/DeathReport.tsx @@ -115,8 +115,8 @@ export default function PrintDeathReport(props: { id: string }) { date_declared_positive: res.data?.date_declared_positive ? dayjs(res.data?.date_declared_positive).toDate() : "", - date_of_admission: res.data?.last_consultation?.admission_date - ? dayjs(res.data?.last_consultation?.admission_date).toDate() + date_of_admission: res.data?.last_consultation?.encounter_date + ? dayjs(res.data?.last_consultation?.encounter_date).toDate() : "", date_of_test: res.data?.date_of_test ? dayjs(res.data?.date_of_test).toDate() diff --git a/src/Components/Facility/ConsultationCard.tsx b/src/Components/Facility/ConsultationCard.tsx index 2c0fa54db21..c402853f366 100644 --- a/src/Components/Facility/ConsultationCard.tsx +++ b/src/Components/Facility/ConsultationCard.tsx @@ -63,14 +63,14 @@ export const ConsultationCard = (props: ConsultationProps) => {
)} - {itemData.admitted && itemData.admission_date && ( + {itemData.admitted && itemData.encounter_date && (
Admitted on
- {formatDateTime(itemData.admission_date)} + {formatDateTime(itemData.encounter_date)} {itemData.is_readmission && ( { name: consultationData.suggestion === "A" ? `Admitted on ${formatDateTime( - consultationData.admission_date! + consultationData.encounter_date! )}` : consultationData.suggestion_text, }, @@ -345,19 +345,19 @@ export const ConsultationDetails = (props: any) => { {consultationData.admitted_to}
- {(consultationData.admission_date ?? - consultationData.discharge_date) && ( + {(consultationData.discharge_date ?? + consultationData.encounter_date) && (
{relativeTime( consultationData.discharge_date ? consultationData.discharge_date - : consultationData.admission_date + : consultationData.encounter_date )}
)}
- {consultationData.admission_date && - formatDateTime(consultationData.admission_date)} + {consultationData.encounter_date && + formatDateTime(consultationData.encounter_date)} {consultationData.discharge_date && ` - ${formatDateTime(consultationData.discharge_date)}`}
diff --git a/src/Components/Facility/ConsultationForm.tsx b/src/Components/Facility/ConsultationForm.tsx index 3207787a27d..72944389235 100644 --- a/src/Components/Facility/ConsultationForm.tsx +++ b/src/Components/Facility/ConsultationForm.tsx @@ -3,6 +3,7 @@ import * as Notification from "../../Utils/Notifications.js"; import { BedModel, FacilityModel } from "./models"; import { CONSULTATION_SUGGESTION, + ConsultationSuggestionValue, PATIENT_CATEGORIES, REVIEW_AT_CHOICES, TELEMEDICINE_ACTIONS, @@ -82,14 +83,14 @@ type FormDetails = { symptoms: number[]; other_symptoms: string; symptoms_onset_date?: Date; - suggestion: string; + suggestion: ConsultationSuggestionValue; route_to_facility?: RouteToFacility; patient: string; facility: string; admitted: BooleanStrings; admitted_to: string; category: string; - admission_date?: Date; + encounter_date?: Date; icu_admission_date?: Date; discharge_date: null; referred_to?: string; @@ -139,7 +140,7 @@ const initForm: FormDetails = { admitted: "false", admitted_to: "", category: "", - admission_date: new Date(), + encounter_date: new Date(), icu_admission_date: undefined, discharge_date: null, referred_to: "", @@ -375,7 +376,7 @@ export const ConsultationForm = (props: any) => { const formData = { ...res.data, symptoms_onset_date: isoStringToDate(res.data.symptoms_onset_date), - admission_date: isoStringToDate(res.data.admission_date), + encounter_date: isoStringToDate(res.data.encounter_date), icu_admission_date: isoStringToDate(res.data.icu_admission_date), admitted: res.data.admitted ? String(res.data.admitted) : "false", admitted_to: res.data.admitted_to ? res.data.admitted_to : "", @@ -485,15 +486,12 @@ export const ConsultationForm = (props: any) => { invalidForm = true; } return; - case "admission_date": - if ( - ["A", "DC"].includes(state.form.suggestion) && - !state.form[field] - ) { + case "encounter_date": + if (!state.form[field]) { errors[field] = "Field is required"; invalidForm = true; } - if (dayjs(state.form.admission_date).isBefore(dayjs("2000-01-01"))) { + if (dayjs(state.form.encounter_date).isBefore(dayjs("2000-01-01"))) { errors[field] = "Admission date cannot be before 01/01/2000"; invalidForm = true; } @@ -685,9 +683,7 @@ export const ConsultationForm = (props: any) => { suggestion: state.form.suggestion, route_to_facility: state.form.route_to_facility, admitted: state.form.suggestion === "A", - admission_date: ["A", "DC"].includes(state.form.suggestion) - ? state.form.admission_date - : undefined, + encounter_date: state.form.encounter_date, category: state.form.category, is_kasp: state.form.is_kasp, kasp_enabled_date: JSON.parse(state.form.is_kasp) ? new Date() : null, @@ -1134,7 +1130,7 @@ export const ConsultationForm = (props: any) => { label="Decision after consultation" {...selectField("suggestion")} options={CONSULTATION_SUGGESTION.filter( - ({ deprecated }) => !deprecated + (option) => !("deprecated" in option) )} />
@@ -1200,30 +1196,35 @@ export const ConsultationForm = (props: any) => { )} - {["A", "DC"].includes(state.form.suggestion) && ( -
+ - -
- )} + label={ + { + A: "Date & Time of Admission to the Facility", + DC: "Date & Time of Domiciliary Care commencement", + OP: "Date & Time of Out-patient visit", + DD: "Date & Time of Encounter", + HI: "Date & Time of Encounter", + R: "Date & Time of Encounter", + }[state.form.suggestion] + } + type="datetime-local" + value={dayjs(state.form.encounter_date).format( + "YYYY-MM-DDTHH:mm" + )} + max={dayjs().format("YYYY-MM-DDTHH:mm")} + /> +
{state.form.route_to_facility === 30 && (
({ ...form, ...updates })); }} required - min={dayjs( - consultationData?.admission_date ?? consultationData?.created_date - ).format("YYYY-MM-DDTHH:mm")} + min={dayjs(consultationData?.encounter_date).format( + "YYYY-MM-DDTHH:mm" + )} max={dayjs().format("YYYY-MM-DDTHH:mm")} error={ preDischargeForm.discharge_reason === "EXP" diff --git a/src/Components/Facility/TreatmentSummary.tsx b/src/Components/Facility/TreatmentSummary.tsx index 7adb4dcfbe2..8291e0e8ba4 100644 --- a/src/Components/Facility/TreatmentSummary.tsx +++ b/src/Components/Facility/TreatmentSummary.tsx @@ -140,7 +140,7 @@ const TreatmentSummary = (props: any) => { Date of admission : {consultationData.admitted - ? formatDateTime(consultationData.admission_date) + ? formatDateTime(consultationData.encounter_date) : " --/--/----"}
diff --git a/src/Components/Facility/models.tsx b/src/Components/Facility/models.tsx index 0cf0a4da986..c4a5196511d 100644 --- a/src/Components/Facility/models.tsx +++ b/src/Components/Facility/models.tsx @@ -5,6 +5,7 @@ import { AssetData, AssetLocationType } from "../Assets/AssetTypes"; import { UserBareMinimum } from "../Users/models"; import { RouteToFacility } from "../Common/RouteToFacilitySelect"; import { ConsultationDiagnosis, CreateDiagnosis } from "../Diagnosis/types"; +import { ConsultationSuggestionValue } from "../../Common/constants"; export interface LocalBodyModel { id: number; @@ -93,7 +94,7 @@ export type PatientCategory = | "Critical"; export interface ConsultationModel { - admission_date?: string; + encounter_date: string; icu_admission_date?: string; admitted?: boolean; test_id?: string; @@ -123,7 +124,7 @@ export interface ConsultationModel { referred_by_external?: string; transferred_from_location?: LocationModel["id"]; transferred_from_location_object?: LocationModel; - suggestion?: string; + suggestion?: ConsultationSuggestionValue; patient_no?: string; route_to_facility?: RouteToFacility; is_kasp?: boolean; diff --git a/src/Components/Patient/ManagePatients.tsx b/src/Components/Patient/ManagePatients.tsx index 9113e8654bf..e1d982148f1 100644 --- a/src/Components/Patient/ManagePatients.tsx +++ b/src/Components/Patient/ManagePatients.tsx @@ -194,10 +194,10 @@ export const PatientManager = () => { date_of_result_after: qParams.date_of_result_after || undefined, last_consultation_medico_legal_case: qParams.last_consultation_medico_legal_case || undefined, - last_consultation_admission_date_before: - qParams.last_consultation_admission_date_before || undefined, - last_consultation_admission_date_after: - qParams.last_consultation_admission_date_after || undefined, + last_consultation_encounter_date_before: + qParams.last_consultation_encounter_date_before || undefined, + last_consultation_encounter_date_after: + qParams.last_consultation_encounter_date_after || undefined, last_consultation_discharge_date_before: qParams.last_consultation_discharge_date_before || undefined, last_consultation_discharge_date_after: @@ -239,8 +239,8 @@ export const PatientManager = () => { [params.date_of_result_before, params.date_of_result_after], [params.last_vaccinated_date_before, params.last_vaccinated_date_after], [ - params.last_consultation_admission_date_before, - params.last_consultation_admission_date_after, + params.last_consultation_encounter_date_before, + params.last_consultation_encounter_date_after, ], [ params.last_consultation_discharge_date_before, @@ -345,8 +345,8 @@ export const PatientManager = () => { }, [ dispatch, qParams.last_consultation_medico_legal_case, - qParams.last_consultation_admission_date_before, - qParams.last_consultation_admission_date_after, + qParams.last_consultation_encounter_date_before, + qParams.last_consultation_encounter_date_after, qParams.last_consultation_discharge_date_before, qParams.last_consultation_discharge_date_after, qParams.age_max, @@ -967,7 +967,7 @@ export const PatientManager = () => { badge("IP/OP number", "patient_no"), ...dateRange("Modified", "modified_date"), ...dateRange("Created", "created_date"), - ...dateRange("Admitted", "last_consultation_admission_date"), + ...dateRange("Admitted", "last_consultation_encounter_date"), ...dateRange("Discharged", "last_consultation_discharge_date"), // Admitted to type badges badge("No. of vaccination doses", "number_of_doses"), diff --git a/src/Components/Patient/PatientFilter.tsx b/src/Components/Patient/PatientFilter.tsx index 0599cb2625b..481d2dcc67b 100644 --- a/src/Components/Patient/PatientFilter.tsx +++ b/src/Components/Patient/PatientFilter.tsx @@ -67,10 +67,10 @@ export default function PatientFilter(props: any) { date_declared_positive: filter.date_declared_positive || null, last_consultation_medico_legal_case: filter.last_consultation_medico_legal_case || null, - last_consultation_admission_date_before: - filter.last_consultation_admission_date_before || null, - last_consultation_admission_date_after: - filter.last_consultation_admission_date_after || null, + last_consultation_encounter_date_before: + filter.last_consultation_encounter_date_before || null, + last_consultation_encounter_date_after: + filter.last_consultation_encounter_date_after || null, last_consultation_discharge_date_before: filter.last_consultation_discharge_date_before || null, last_consultation_discharge_date_after: @@ -125,8 +125,8 @@ export default function PatientFilter(props: any) { date_of_result: null, date_declared_positive: null, last_consultation_medico_legal_case: null, - last_consultation_admission_date_before: "", - last_consultation_admission_date_after: "", + last_consultation_encounter_date_before: "", + last_consultation_encounter_date_after: "", last_consultation_discharge_date_before: "", last_consultation_discharge_date_after: "", last_consultation_admitted_to_list: [], @@ -236,8 +236,8 @@ export default function PatientFilter(props: any) { age_max, date_of_result, last_consultation_medico_legal_case, - last_consultation_admission_date_before, - last_consultation_admission_date_after, + last_consultation_encounter_date_before, + last_consultation_encounter_date_after, last_consultation_discharge_date_before, last_consultation_discharge_date_after, last_consultation_admitted_bed_type_list, @@ -278,11 +278,11 @@ export default function PatientFilter(props: any) { date_of_result: dateQueryString(date_of_result), last_consultation_medico_legal_case: last_consultation_medico_legal_case || "", - last_consultation_admission_date_before: dateQueryString( - last_consultation_admission_date_before + last_consultation_encounter_date_before: dateQueryString( + last_consultation_encounter_date_before ), - last_consultation_admission_date_after: dateQueryString( - last_consultation_admission_date_after + last_consultation_encounter_date_after: dateQueryString( + last_consultation_encounter_date_after ), last_consultation_discharge_date_before: dateQueryString( last_consultation_discharge_date_before @@ -537,13 +537,13 @@ export default function PatientFilter(props: any) { /> {" "} diff --git a/src/Components/Shifting/ShiftDetails.tsx b/src/Components/Shifting/ShiftDetails.tsx index a898b0cde15..493c56e71c0 100644 --- a/src/Components/Shifting/ShiftDetails.tsx +++ b/src/Components/Shifting/ShiftDetails.tsx @@ -22,6 +22,7 @@ import { useTranslation } from "react-i18next"; import useQuery from "../../Utils/request/useQuery.js"; import routes from "../../Redux/api.js"; import request from "../../Utils/request/request.js"; +import { ConsultationModel } from "../Facility/models.js"; const Loading = lazy(() => import("../Common/Loading")); @@ -316,7 +317,7 @@ export default function ShiftDetails(props: { id: string }) { const printData = (data: any) => { const patientData = data.patient_object; - const consultation = data.patient.last_consultation; + const consultation = data.patient.last_consultation as ConsultationModel; const patientGender = GENDER_TYPES.find( (i) => i.id === patientData?.gender )?.text; @@ -409,7 +410,7 @@ export default function ShiftDetails(props: { id: string }) { {t("date_of_admission")}:{" "} {formatDateTime( - consultation.admission_date || consultation.created_date + consultation.encounter_date || consultation.created_date ) || "-"}
From 9fc041c5ecf7f48172286b8c4b9f3752e82934b9 Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Thu, 21 Dec 2023 11:05:25 +0530 Subject: [PATCH 14/16] =?UTF-8?q?=F0=9F=A7=B9=20Remove=20unused=20redux=20?= =?UTF-8?q?actions,=20fireRequest=20for=20file=20utility=20method,=20hooks?= =?UTF-8?q?=20and=20components=20(#6887)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove unused redux actions * Remove unused `fireRequestForFiles` method * remove unused `useIsInitialRender` hook * remove unused components --- src/Common/hooks/useIsInitialRender.ts | 9 - src/Components/Common/NavTabs.tsx | 52 ---- .../Common/WardAutocompleteFormField.tsx | 52 ---- src/Redux/actions.tsx | 260 +----------------- src/Redux/fireRequest.tsx | 102 ------- 5 files changed, 1 insertion(+), 474 deletions(-) delete mode 100644 src/Common/hooks/useIsInitialRender.ts delete mode 100644 src/Components/Common/NavTabs.tsx delete mode 100644 src/Components/Common/WardAutocompleteFormField.tsx diff --git a/src/Common/hooks/useIsInitialRender.ts b/src/Common/hooks/useIsInitialRender.ts deleted file mode 100644 index cfbfe71734d..00000000000 --- a/src/Common/hooks/useIsInitialRender.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { useEffect, useRef } from "react"; - -export default function useIsInitialRender() { - const isInitialRender = useRef(true); - useEffect(() => { - isInitialRender.current = false; - }, []); - return isInitialRender.current; -} diff --git a/src/Components/Common/NavTabs.tsx b/src/Components/Common/NavTabs.tsx deleted file mode 100644 index 1b913d888ce..00000000000 --- a/src/Components/Common/NavTabs.tsx +++ /dev/null @@ -1,52 +0,0 @@ -interface TabValue { - value: number; - label: string; -} -interface TabChange { - (value: number): void; -} -interface NavTabsProps { - active?: number; - options?: TabValue[]; - onChange: TabChange; -} - -export default function NavTabs(props: NavTabsProps) { - const { active, options, onChange } = props; - return ( -
-
- -
-
-
- -
-
-
- ); -} diff --git a/src/Components/Common/WardAutocompleteFormField.tsx b/src/Components/Common/WardAutocompleteFormField.tsx deleted file mode 100644 index 47298dd27b2..00000000000 --- a/src/Components/Common/WardAutocompleteFormField.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { useDispatch } from "react-redux"; -import { FormFieldBaseProps } from "../Form/FormFields/Utils"; -import AutocompleteFormField from "../Form/FormFields/Autocomplete"; -import { statusType, useAbortableEffect } from "../../Common/utils"; -import { useCallback, useState } from "react"; -import { getWardByLocalBody } from "../../Redux/actions"; -import { ILocalBody } from "./LocalBodyAutocompleteFormField"; - -export type IWard = { - id: number; - name: string; -}; - -type Props = FormFieldBaseProps & { - placeholder?: string; - local_body?: ILocalBody["id"]; -}; - -export default function WardAutocompleteFormField(props: Props) { - const dispatch = useDispatch(); - const [Ward, setWard] = useState(); - - const fetchWard = useCallback( - async (status: any) => { - setWard(undefined); - if (!props.local_body) { - return; - } - const res = await dispatch(getWardByLocalBody({ id: props.local_body })); - if (!status.aborted && res.data) { - setWard(res.data); - } - }, - [dispatch, props.local_body] - ); - - useAbortableEffect( - (status: statusType) => fetchWard(status), - [props.local_body] - ); - - return ( - option.name} - optionValue={(option) => option.id} - isLoading={!!(props.local_body && Ward === undefined)} - disabled={!props.local_body} - /> - ); -} diff --git a/src/Redux/actions.tsx b/src/Redux/actions.tsx index 2395c9ad163..32af9609263 100644 --- a/src/Redux/actions.tsx +++ b/src/Redux/actions.tsx @@ -1,43 +1,6 @@ import { HCXClaimModel, HCXPolicyModel } from "../Components/HCX/models"; import { MedibaseMedicine } from "../Components/Medicine/models"; -import { fireRequest, fireRequestForFiles } from "./fireRequest"; - -export const getConfig = () => { - return fireRequestForFiles("config"); -}; -// User -export const postLogin = (params: object) => { - return fireRequest("login", [], params); -}; -export const getCurrentUser = () => { - return fireRequest("currentUser"); -}; -export const signupUser = (params: object) => { - return fireRequest("createUser", [], params); -}; -export const deleteUser = (username: string) => { - return fireRequest("deleteUser", [], {}, { username }); -}; - -export const checkResetToken = (params: object) => { - return fireRequest("checkResetToken", [], params); -}; - -export const postResetPassword = (form: object) => { - return fireRequest("resetPassword", [], form); -}; - -export const postForgotPassword = (form: object) => { - return fireRequest("forgotPassword", [], form); -}; - -export const getUserPnconfig = (pathParams: object) => { - return fireRequest("getUserPnconfig", [], {}, pathParams); -}; - -export const updateUserPnconfig = (params: object, pathParams: object) => { - return fireRequest("updateUserPnconfig", [], params, pathParams); -}; +import { fireRequest } from "./fireRequest"; // Facility export const createFacility = (params: object) => { @@ -46,39 +9,12 @@ export const createFacility = (params: object) => { export const updateFacility = (id: string, params: object) => { return fireRequest("updateFacility", [id], params); }; -export const partialUpdateFacility = (id: string, params: object) => { - return fireRequest("partialUpdateFacility", [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 getUserListFacility = (pathParam: object) => { - return fireRequest("userListFacility", [], {}, pathParam); -}; - -export const addUserSkill = (username: string, skill: string) => { - return fireRequest("addUserSkill", [], { skill }, { username }); -}; - -export const addUserFacility = (username: string, facility: string) => { - return fireRequest("addUserFacility", [], { facility }, { username }); -}; - -export const deleteUserSkill = (username: string, id: string) => { - return fireRequest("deleteUserSkill", [], {}, { username, id }); -}; - -export const deleteUserFacility = (username: string, facility: string) => { - return fireRequest( - "deleteUserFacility", - [], - { data: { facility } }, - { username } - ); -}; export const getPermittedFacilities = (params: object) => { return fireRequest("getPermittedFacilities", [], params); @@ -108,9 +44,6 @@ export const getFacilityUsers = (id: string, params?: object) => { { facility_id: id } ); }; -export const getOnlineDoctors = () => { - return fireRequest("getOnlineDoctors", [], {}, {}); -}; export const listFacilityAssetLocation = (params: object, pathParam: object) => fireRequest("listFacilityAssetLocation", [], params, pathParam); @@ -140,15 +73,6 @@ export const updateFacilityAssetLocation = ( facility_external_id, external_id, }); -export const partialUpdateFacilityAssetLocation = ( - params: object, - facility_external_id: string, - external_id: string -) => - fireRequest("partialUpdateFacilityAssetLocation", [], params, { - facility_external_id, - external_id, - }); // asset bed export const listAssetBeds = (params: object, altKey?: string) => @@ -165,17 +89,6 @@ export const createAssetBed = ( {} ); -export const getAssetBed = ( - asset_external_id: string, - bed_id: string, - external_id: string -) => - fireRequest( - "getAssetBed", - [], - { asset: asset_external_id, bed: bed_id }, - { external_id } - ); export const partialUpdateAssetBed = (params: object, asset_id: string) => fireRequest( "partialUpdateAssetBed", @@ -186,21 +99,6 @@ export const partialUpdateAssetBed = (params: object, asset_id: string) => } ); -export const updateAssetBed = ( - params: object, - asset_external_id: string, - external_id: string, - bed_id: string -) => - fireRequest( - "updateAssetBed", - [], - { ...params, asset: asset_external_id, bed: bed_id }, - { - external_id, - } - ); - export const deleteAssetBed = (asset_id: string) => fireRequest( "deleteAssetBed", @@ -260,47 +158,6 @@ export const deleteFacilityBed = (external_id: string) => { return fireRequest("deleteFacilityBed", [], {}, { external_id }); }; -// Consultation Beds -export const listConsultationBeds = (params: object) => - fireRequest("listConsultationBeds", [], params, {}); -export const createConsultationBed = ( - params: object, - consultation_id: string, - bed_id: string -) => - fireRequest( - "createConsultationBed", - [], - { ...params, consultation: consultation_id, bed: bed_id }, - {} - ); - -export const getConsultationBed = ( - consultation_external_id: string, - bed_id: string, - external_id: string -) => - fireRequest( - "getConsultationBed", - [], - { consultation: consultation_external_id, bed: bed_id }, - { external_id } - ); -export const updateConsultationBed = ( - params: object, - consultation_external_id: string, - external_id: string, - bed_id: string -) => - fireRequest( - "updateConsultationBed", - [], - { ...params, consultation: consultation_external_id, bed: bed_id }, - { - external_id, - } - ); - // Download Actions export const downloadFacility = () => { return fireRequest("downloadFacility"); @@ -318,9 +175,6 @@ export const downloadFacilityTriage = () => { return fireRequest("downloadFacilityTriage"); }; -export const downloadPatients = () => { - return fireRequest("downloadPatients"); -}; // Capacity/Triage/Doctor export const createCapacity = ( id: number | undefined, @@ -377,9 +231,6 @@ export const deleteCapacity = (pathParam: object) => { export const searchPatient = (params: object) => { return fireRequest("searchPatient", [], params); }; -export const searchUser = (params: object) => { - return fireRequest("searchUser", [], params); -}; export const getAllPatient = (params: object, altKey: string) => { return fireRequest("patientList", [], params, null, altKey); }; @@ -398,23 +249,9 @@ export const patchPatient = (params: object, pathParam: object) => { export const transferPatient = (params: object, pathParam: object) => { return fireRequest("transferPatient", [], params, pathParam); }; -export const getPatientNotes = ( - patientId: string, - limit: number, - offset: number -) => { - return fireRequest("getPatientNotes", [], { limit, offset }, { patientId }); -}; -export const addPatientNote = (patientId: string, params: object) => { - return fireRequest("addPatientNote", [], params, { patientId }); -}; - export const getStates = () => { return fireRequest("statesList", []); }; -export const getStatesByText = (params: object) => { - return fireRequest("statesList", [], params); -}; export const getState = (id: number) => { return fireRequest("getState", [], {}, { id: id }); }; @@ -433,20 +270,10 @@ export const getDistrict = (id: number, key?: string) => { export const getLocalbodyByDistrict = (pathParam: object) => { return fireRequest("getLocalbodyByDistrict", [], {}, pathParam); }; -export const getLocalbodyByName = (params: object) => { - return fireRequest("getLocalbodyByName", [], params, null); -}; export const getWardByLocalBody = (pathParam: object) => { return fireRequest("getWardByLocalBody", [], {}, pathParam); }; -export const getWards = (params: object) => { - return fireRequest("getWards", [], params); -}; - -export const getAllLocalBodyByDistrict = (pathParam: object) => { - return fireRequest("getAllLocalBodyByDistrict", [], {}, pathParam); -}; // Local Body export const getLocalBody = (pathParam: object) => { @@ -460,10 +287,6 @@ export const getAllLocalBody = (params: object) => { export const getSampleTestList = (params: object, pathParam: object) => { return fireRequest("sampleTestList", [], params, pathParam); }; - -export const sampleSearch = (params: object) => { - return fireRequest("getTestSampleList", [], params); -}; export const createSampleTest = (params: object, pathParam: object) => { return fireRequest("createSampleTest", [], params, pathParam); }; @@ -497,9 +320,6 @@ export const getDailyReport = (params: object, pathParam: object) => { export const getConsultationDailyRoundsDetails = (pathParam: object) => { return fireRequest("getDailyReport", [], {}, pathParam); }; -export const dailyRoundsAnalyse = (params: object, pathParam: object) => { - return fireRequest("dailyRoundsAnalyse", [], params, pathParam); -}; // Consultation export const createConsultation = (params: object) => { @@ -552,10 +372,6 @@ export const getInventorySummary = (facilityId: number, params: object) => { params ); }; -export const getItemName = (id: number) => { - return fireRequest("getItemName", [id], {}); -}; - export const flagInventoryItem = (params: object) => { return fireRequest("flagInventoryItem", [], {}, params); }; @@ -584,12 +400,6 @@ export const dischargePatient = (params: object, pathParams: object) => { return fireRequest("dischargePatient", [], params, pathParams); }; -//Profile - -export const updateUserDetails = (username: string, data: object) => { - return fireRequest("updateUserDetails", [username], data); -}; - //Shift export const createShift = (params: object) => { return fireRequest("createShift", [], params); @@ -615,36 +425,6 @@ export const externalResult = (pathParam: object) => { return fireRequest("externalResult", [], {}, pathParam); }; -export const updateExternalResult = (id: number, params: object) => { - return fireRequest("updateExternalResult", [], params, { id }); -}; - -export const partialUpdateExternalResult = (id: number, params: object) => { - return fireRequest("partialUpdateExternalResult", [], params, { id }); -}; - -// Notifications -export const getNotifications = (params: object, altKey?: string) => { - return fireRequest("getNotifications", [], params, {}, altKey); -}; - -export const getNotificationData = (pathParam: object) => { - return fireRequest("getNotificationData", [], {}, pathParam); -}; - -export const markNotificationAsRead = (id: string) => { - return fireRequest( - "markNotificationAsRead", - [], - { read_at: new Date() }, - { id } - ); -}; - -export const getPublicKey = () => { - return fireRequest("getPublicKey", [], {}, {}); -}; - // FileUpload export const createUpload = (params: object) => { @@ -659,10 +439,6 @@ export const retrieveUpload = (params: object, fileId: string) => { return fireRequest("retrieveUpload", [], params, { fileId: fileId }); }; -export const retrieveUploadFilesURL = (params: object, fileId: string) => { - return fireRequestForFiles("retrieveUpload", [], params, { fileId: fileId }); -}; - export const editUpload = ( params: object, fileId: string, @@ -757,47 +533,13 @@ export const createAsset = (params: object) => fireRequest("createAsset", [], 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 operateAsset = (id: string, params: object) => fireRequest("operateAsset", [], params, { external_id: id }); -// ABDM related - -export const resentAadhaarOtp = (txnId: string) => - fireRequest("resendAadhaarOtp", [], { txnId }); - -export const generateMobileOtp = (txnId: string, mobile: string) => - fireRequest("generateMobileOtp", [], { txnId, mobile }); - -export const linkCareContext = ( - consultationId: string, - data: { name?: string; gender?: "M" | "F" | "O"; dob?: string } -) => { - return fireRequest("linkCareContext", [], { - consultation: consultationId, - ...data, - }); -}; - -export const healthFacilityActions = { - list: (params: object) => { - return fireRequest("listHealthFacilities", [], params); - }, - - update: (id: string, data: object) => { - return fireRequest("updateHealthFacility", [], data, { - facility_id: id, - }); - }, -}; - export const listAssetAvailability = (params: object) => fireRequest("listAssetAvailability", [], params); -export const getAssetAvailability = (id: string) => - fireRequest("getAssetAvailability", [], {}, { id }); export const listPMJYPackages = (query?: string) => fireRequest("listPMJYPackages", [], { query }); diff --git a/src/Redux/fireRequest.tsx b/src/Redux/fireRequest.tsx index 876877799d8..6c3aee7c12a 100644 --- a/src/Redux/fireRequest.tsx +++ b/src/Redux/fireRequest.tsx @@ -274,105 +274,3 @@ export const fireRequestV2 = ( } }); }; - -export const fireRequestForFiles = ( - key: string, - path: any = [], - params: any = {}, - pathParam?: any, - altKey?: string -) => { - return (dispatch: any) => { - // cancel previous api call - if (isRunning[altKey ? altKey : key]) { - isRunning[altKey ? altKey : key].cancel(); - } - isRunning[altKey ? altKey : key] = axios.CancelToken.source(); - // get api url / method - const request = Object.assign({}, requestMap[key]); - if (path.length > 0) { - request.path += "/" + path.join("/"); - } - if (request.method === undefined || request.method === "GET") { - request.method = "GET"; - const qs = new URLSearchParams(omitBy(params, isEmpty)).toString(); - if (qs !== "") { - request.path += `?${qs}`; - } - } - // set dynamic params in the URL - if (pathParam) { - Object.keys(pathParam).forEach((param: any) => { - request.path = request.path.replace(`{${param}}`, pathParam[param]); - }); - } - - // set authorization header in the request header - const config: any = { - headers: { - "Content-type": "application/pdf", - "Content-disposition": "inline", - }, - }; - // Content-Type: application/pdf - // Content-Disposition: inline; filename="filename.pdf" - if (!request.noAuth && localStorage.getItem(LocalStorageKeys.accessToken)) { - config.headers["Authorization"] = - "Bearer " + localStorage.getItem(LocalStorageKeys.accessToken); - } - const axiosApiCall: any = axios.create(config); - - dispatch(fetchDataRequest(key)); - return axiosApiCall[request.method.toLowerCase()](request.path, { - ...params, - cancelToken: isRunning[altKey ? altKey : key].token, - }) - .then((response: any) => { - dispatch(fetchResponseSuccess(key, response.data)); - return response; - }) - .catch((error: any) => { - dispatch(fetchDataRequestError(key, error)); - - if (error.response) { - // temporarily don't show invalid phone number error on duplicate patient check - if (error.response.status === 400 && key === "searchPatient") { - return; - } - - // currentUser is ignored because on the first page load - // 403 error is displayed for invalid credential. - if (error.response.status === 403 && key === "currentUser") { - if (localStorage.getItem(LocalStorageKeys.accessToken)) { - localStorage.removeItem(LocalStorageKeys.accessToken); - } - return; - } - - // 400 Bad Request Error - if (error.response.status === 400 || error.response.status === 406) { - Notification.BadRequest({ - errs: error.response.data, - }); - return error.response; - } - - // 4xx Errors - if (error.response.status > 400 && error.response.status < 600) { - if (error.response.status === 429) { - return error.response; - } else if (error.response.data && error.response.data.detail) { - Notification.Error({ - msg: error.response.data.detail, - }); - } else { - Notification.Error({ - msg: "Something went wrong...!", - }); - } - return; - } - } - }); - }; -}; From 89c6382d4cf140cbdd8bac37216baa48550d76df Mon Sep 17 00:00:00 2001 From: Ashesh <3626859+Ashesh3@users.noreply.github.com> Date: Fri, 22 Dec 2023 18:38:44 +0530 Subject: [PATCH 15/16] Fix pincode district name comparison (#6894) --- src/Components/Patient/PatientRegister.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Patient/PatientRegister.tsx b/src/Components/Patient/PatientRegister.tsx index f2683f2f775..77088ef57e7 100644 --- a/src/Components/Patient/PatientRegister.tsx +++ b/src/Components/Patient/PatientRegister.tsx @@ -707,7 +707,7 @@ export const PatientRegister = (props: PatientRegisterProps) => { if (!fetchedDistricts) return; const matchedDistrict = fetchedDistricts.find((district) => { - return includesIgnoreCase(district.name, pincodeDetails.district); + return includesIgnoreCase(district.name, pincodeDetails.districtname); }); if (!matchedDistrict) return; From d906c6ad9a1744bcca76629223ef8644ed239942 Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Sat, 23 Dec 2023 18:14:35 +0530 Subject: [PATCH 16/16] Adds support for units for `max_dosage` (#6897) --- .../Form/FormFields/NumericWithUnitsFormField.tsx | 2 +- .../Medicine/CreatePrescriptionForm.tsx | 13 +++++++++---- src/Components/Medicine/EditPrescriptionForm.tsx | 9 +++++---- src/Components/Medicine/models.ts | 15 +++++++++++++-- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/Components/Form/FormFields/NumericWithUnitsFormField.tsx b/src/Components/Form/FormFields/NumericWithUnitsFormField.tsx index 02f98a7ba17..d0dae7ddff5 100644 --- a/src/Components/Form/FormFields/NumericWithUnitsFormField.tsx +++ b/src/Components/Form/FormFields/NumericWithUnitsFormField.tsx @@ -9,7 +9,7 @@ type Props = FormFieldBaseProps & { className?: string | undefined; min?: string | number; max?: string | number; - units: string[]; + units: readonly string[]; }; export default function NumericWithUnitsFormField(props: Props) { diff --git a/src/Components/Medicine/CreatePrescriptionForm.tsx b/src/Components/Medicine/CreatePrescriptionForm.tsx index d6691ebbc03..2725ab4e728 100644 --- a/src/Components/Medicine/CreatePrescriptionForm.tsx +++ b/src/Components/Medicine/CreatePrescriptionForm.tsx @@ -3,7 +3,11 @@ import Form from "../Form/Form"; import { SelectFormField } from "../Form/FormFields/SelectFormField"; import TextAreaFormField from "../Form/FormFields/TextAreaFormField"; import TextFormField from "../Form/FormFields/TextFormField"; -import { MedicineAdministrationRecord, Prescription } from "./models"; +import { + DOSAGE_UNITS, + MedicineAdministrationRecord, + Prescription, +} from "./models"; import { useState } from "react"; import NumericWithUnitsFormField from "../Form/FormFields/NumericWithUnitsFormField"; import { useTranslation } from "react-i18next"; @@ -74,7 +78,7 @@ export default function CreatePrescriptionForm(props: { label={t("dosage")} {...field("dosage", RequiredFieldValidator())} required - units={["mg", "g", "ml", "drop(s)", "ampule(s)", "tsp"]} + units={DOSAGE_UNITS} min={0} />
@@ -86,9 +90,10 @@ export default function CreatePrescriptionForm(props: { {...field("indicator", RequiredFieldValidator())} required /> - diff --git a/src/Components/Medicine/EditPrescriptionForm.tsx b/src/Components/Medicine/EditPrescriptionForm.tsx index 42a9b39f7ea..2bd3805af73 100644 --- a/src/Components/Medicine/EditPrescriptionForm.tsx +++ b/src/Components/Medicine/EditPrescriptionForm.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; import Form from "../Form/Form"; -import { Prescription } from "./models"; +import { DOSAGE_UNITS, Prescription } from "./models"; import request from "../../Utils/request/request"; import * as Notification from "../../Utils/Notifications"; import useSlug from "../../Common/hooks/useSlug"; @@ -102,7 +102,7 @@ export default function EditPrescriptionForm(props: Props) { label={t("dosage")} {...field("dosage", RequiredFieldValidator())} required - units={["mg", "g", "ml", "drop(s)", "ampule(s)", "tsp"]} + units={DOSAGE_UNITS} min={0} />
@@ -114,9 +114,10 @@ export default function EditPrescriptionForm(props: Props) { {...field("indicator", RequiredFieldValidator())} required /> - diff --git a/src/Components/Medicine/models.ts b/src/Components/Medicine/models.ts index ee42b03eca2..4fca9b6f972 100644 --- a/src/Components/Medicine/models.ts +++ b/src/Components/Medicine/models.ts @@ -1,12 +1,23 @@ import { PerformedByModel } from "../HCX/misc"; +export const DOSAGE_UNITS = [ + "mg", + "g", + "ml", + "drop(s)", + "ampule(s)", + "tsp", +] as const; + +export type DosageValue = `${number} ${(typeof DOSAGE_UNITS)[number]}`; + interface BasePrescription { readonly id: string; medicine?: string; medicine_object?: MedibaseMedicine; medicine_old?: string; route?: "ORAL" | "IV" | "IM" | "SC"; - dosage: string; + dosage: DosageValue; notes?: string; meta?: object; readonly prescription_type?: "DISCHARGE" | "REGULAR"; @@ -40,7 +51,7 @@ export interface NormalPrescription extends BasePrescription { export interface PRNPrescription extends BasePrescription { indicator: string; - max_dosage?: string; + max_dosage?: DosageValue; min_hours_between_doses?: number; is_prn: true; frequency?: undefined;