From 2a003a69b8114bab7752f1e8103f3355b6d53942 Mon Sep 17 00:00:00 2001 From: Usama Idriss Kakumba Date: Mon, 4 Mar 2024 22:22:40 +0300 Subject: [PATCH 1/5] feat: add end visit data-time on editing existing visit --- .../src/visit/visit-form/visit-form.component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx index 28eb9915b0..69778540f4 100644 --- a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx +++ b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx @@ -121,7 +121,7 @@ const StartVisitForm: React.FC = ({ }); const displayVisitStopDateTimeFields = useMemo( - () => Boolean(visitToEdit?.stopDatetime || showVisitEndDateTimeFields), + () => Boolean(visitToEdit?.uuid || visitToEdit?.stopDatetime || showVisitEndDateTimeFields), [visitToEdit?.stopDatetime, showVisitEndDateTimeFields], ); From ae79819f031b3acbd32d26168627a3b35fe0cab5 Mon Sep 17 00:00:00 2001 From: Usama Idriss Kakumba Date: Tue, 5 Mar 2024 15:26:10 +0300 Subject: [PATCH 2/5] fix: fix validations --- .../visit/visit-form/visit-form.component.tsx | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx index 69778540f4..be3e615449 100644 --- a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx +++ b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx @@ -122,7 +122,7 @@ const StartVisitForm: React.FC = ({ const displayVisitStopDateTimeFields = useMemo( () => Boolean(visitToEdit?.uuid || visitToEdit?.stopDatetime || showVisitEndDateTimeFields), - [visitToEdit?.stopDatetime, showVisitEndDateTimeFields], + [visitToEdit?.uuid, showVisitEndDateTimeFields], ); const visitFormSchema = useMemo(() => { @@ -283,31 +283,33 @@ const StartVisitForm: React.FC = ({ const visitStopTime = getValues('visitStopTime'); const visitStopTimeFormat = getValues('visitStopTimeFormat'); - const [visitStopHours, visitStopMinutes] = convertTime12to24(visitStopTime, visitStopTimeFormat); - - const visitStopDatetime = visitStopDate.setHours(visitStopHours, visitStopMinutes); - - if (minVisitStopDatetime && visitStopDatetime <= minVisitStopDatetime) { - validSubmission = false; - setError('visitStopDate', { - message: t( - 'visitStopDateMustBeAfterMostRecentEncounter', - 'Stop date needs to be on or after {{lastEncounterDatetime}}', - { - lastEncounterDatetime: new Date(minVisitStopDatetime).toLocaleString(), - interpolation: { - escapeValue: false, + if (visitStopDate && visitStopTime && visitStopTimeFormat) { + const [visitStopHours, visitStopMinutes] = convertTime12to24(visitStopTime, visitStopTimeFormat); + + const visitStopDatetime = visitStopDate.setHours(visitStopHours, visitStopMinutes); + + if (minVisitStopDatetime && visitStopDatetime <= minVisitStopDatetime) { + validSubmission = false; + setError('visitStopDate', { + message: t( + 'visitStopDateMustBeAfterMostRecentEncounter', + 'Stop date needs to be on or after {{lastEncounterDatetime}}', + { + lastEncounterDatetime: new Date(minVisitStopDatetime).toLocaleString(), + interpolation: { + escapeValue: false, + }, }, - }, - ), - }); - } + ), + }); + } - if (visitStartDatetime >= visitStopDatetime) { - validSubmission = false; - setError('visitStopDate', { - message: t('invalidVisitStopDate', 'Visit stop date time cannot be on or before visit start date time'), - }); + if (visitStartDatetime >= visitStopDatetime) { + validSubmission = false; + setError('visitStopDate', { + message: t('invalidVisitStopDate', 'Visit stop date time cannot be on or before visit start date time'), + }); + } } return validSubmission; @@ -442,7 +444,7 @@ const StartVisitForm: React.FC = ({ delete payload.patient; } - if (displayVisitStopDateTimeFields) { + if (displayVisitStopDateTimeFields && visitStopDate && visitStopTime && visitStopTimeFormat) { const [visitStopHours, visitStopMinutes] = convertTime12to24(visitStopTime, visitStopTimeFormat); payload.stopDatetime = toDateObjectStrict( From 25ae9db4bdc72429c27b388d103d67f685b50c87 Mon Sep 17 00:00:00 2001 From: Usama Idriss Kakumba Date: Wed, 16 Oct 2024 17:38:54 +0300 Subject: [PATCH 3/5] feat: rebase branch --- .../src/visit/visit-form/visit-form.component.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx index be3e615449..ed710a435f 100644 --- a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx +++ b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx @@ -25,6 +25,7 @@ import { zodResolver } from '@hookform/resolvers/zod'; import { ExtensionSlot, formatDatetime, + type NewVisitPayload, openmrsFetch, restBaseUrl, saveVisit, @@ -39,15 +40,14 @@ import { useSession, useVisit, useVisitTypes, - type NewVisitPayload, type Visit, } from '@openmrs/esm-framework'; import { convertTime12to24, createOfflineVisitForPatient, + type DefaultPatientWorkspaceProps, time12HourFormatRegex, useActivePatientEnrollment, - type DefaultPatientWorkspaceProps, } from '@openmrs/esm-patient-common-lib'; import { type ChartConfig } from '../../config-schema'; import { type VisitFormData } from './visit-form.resource'; @@ -121,7 +121,7 @@ const StartVisitForm: React.FC = ({ }); const displayVisitStopDateTimeFields = useMemo( - () => Boolean(visitToEdit?.uuid || visitToEdit?.stopDatetime || showVisitEndDateTimeFields), + () => Boolean(visitToEdit?.uuid || showVisitEndDateTimeFields), [visitToEdit?.uuid, showVisitEndDateTimeFields], ); From 8617f4c965c3faac129d82e7259d571815ea1246 Mon Sep 17 00:00:00 2001 From: Usama Idriss Kakumba Date: Wed, 23 Oct 2024 02:27:57 +0300 Subject: [PATCH 4/5] fix: fix e2e tests --- e2e/specs/edit-existing-visit.spec.ts | 18 ++++++++++----- .../visit/visit-form/visit-form.component.tsx | 22 ++++++++++++------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/e2e/specs/edit-existing-visit.spec.ts b/e2e/specs/edit-existing-visit.spec.ts index 382e90ae94..637c509fbf 100644 --- a/e2e/specs/edit-existing-visit.spec.ts +++ b/e2e/specs/edit-existing-visit.spec.ts @@ -1,6 +1,6 @@ import { expect } from '@playwright/test'; import { type Visit } from '@openmrs/esm-framework'; -import { type Patient, generateRandomPatient, deletePatient, startVisit } from '../commands'; +import { deletePatient, generateRandomPatient, type Patient, startVisit } from '../commands'; import { test } from '../core'; import { ChartPage, VisitsPage } from '../pages'; @@ -27,18 +27,24 @@ test('Edit an existing visit', async ({ page }) => { await test.step('Then I should see the `Edit Visit` form launch in the workspace', async () => { await expect(chartPage.page.getByText(/visit start date and time/i)).toBeVisible(); - const datePickerInput = chartPage.page.getByPlaceholder(/dd\/mm\/yyyy/i); - await expect(datePickerInput).toBeVisible(); - const dateValue = await datePickerInput.inputValue(); + + const startDateInput = chartPage.page.locator('input#visitStartDateInput'); + const startTimeInput = chartPage.page.locator('input#visitStartTime'); + + await expect(startDateInput).toBeVisible(); + const dateValue = await startDateInput.inputValue(); expect(dateValue).not.toBe(''); expect(dateValue).toMatch(/^\d{2}\/\d{2}\/\d{4}$/); - await expect(chartPage.page.getByPlaceholder(/hh\:mm/i)).toBeVisible(); + await expect(startTimeInput).toBeVisible(); + const timeValue = await startTimeInput.inputValue(); + expect(timeValue).toMatch(/^(1[0-2]|0?[1-9]):([0-5][0-9])$/); + await expect(chartPage.page.getByRole('combobox', { name: /select a location/i })).toBeVisible(); await expect(chartPage.page.getByRole('combobox', { name: /select a location/i })).toHaveValue('Outpatient Clinic'); await expect(chartPage.page.getByText(/visit type/i)).toBeVisible(); await expect(chartPage.page.getByLabel(/facility visit/i)).toBeChecked(); - await expect(chartPage.page.getByRole('search', { name: /search for a visit type/i })).toBeVisible(); + await expect(chartPage.page.getByRole('search', { name: /visit type/i })).toBeVisible(); await expect(chartPage.page.getByLabel(/facility visit/i)).toBeVisible(); await expect(chartPage.page.getByLabel(/home visit/i)).toBeVisible(); await expect(chartPage.page.getByLabel(/opd visit/i)).toBeVisible(); diff --git a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx index ed710a435f..259b8c657d 100644 --- a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx +++ b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx @@ -148,6 +148,8 @@ const StartVisitForm: React.FC = ({ return new Date(visitStartDatetime) <= new Date(); }; + const hadPreviousStopDateTime = Boolean(visitToEdit?.stopDatetime); + return z .object({ visitStartDate: z.date().refine( @@ -167,13 +169,17 @@ const StartVisitForm: React.FC = ({ .string() .refine((value) => value.match(time12HourFormatRegex), t('invalidTimeFormat', 'Invalid time format')), visitStartTimeFormat: z.enum(['PM', 'AM']), - visitStopDate: displayVisitStopDateTimeFields ? z.date() : z.date().optional(), - visitStopTime: displayVisitStopDateTimeFields - ? z - .string() - .refine((value) => value.match(time12HourFormatRegex), t('invalidTimeFormat', 'Invalid time format')) - : z.string().optional(), - visitStopTimeFormat: displayVisitStopDateTimeFields ? z.enum(['PM', 'AM']) : z.enum(['PM', 'AM']).optional(), + visitStopDate: displayVisitStopDateTimeFields && hadPreviousStopDateTime ? z.date() : z.date().optional(), + visitStopTime: + displayVisitStopDateTimeFields && hadPreviousStopDateTime + ? z + .string() + .refine((value) => value.match(time12HourFormatRegex), t('invalidTimeFormat', 'Invalid time format')) + : z.string().optional(), + visitStopTimeFormat: + displayVisitStopDateTimeFields && hadPreviousStopDateTime + ? z.enum(['PM', 'AM']) + : z.enum(['PM', 'AM']).optional(), programType: z.string().optional(), visitType: z.string().refine((value) => !!value, t('visitTypeRequired', 'Visit type is required')), visitLocation: z.object({ @@ -186,7 +192,7 @@ const StartVisitForm: React.FC = ({ message: t('futureStartTime', 'Visit start time cannot be in the future'), path: ['visitStartTime'], }); - }, [t, config, displayVisitStopDateTimeFields]); + }, [config.visitAttributeTypes, visitToEdit?.stopDatetime, t, displayVisitStopDateTimeFields]); const defaultValues = useMemo(() => { const visitStartDate = visitToEdit?.startDatetime ? new Date(visitToEdit?.startDatetime) : new Date(); From 71066304b8655c425a869e8f272db6cb7b586f08 Mon Sep 17 00:00:00 2001 From: Usama Idriss Kakumba Date: Mon, 4 Nov 2024 13:19:44 +0300 Subject: [PATCH 5/5] add validation on optional stopdate --- .../src/visit/visit-form/visit-form.component.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx index 259b8c657d..e29ab38bd0 100644 --- a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx +++ b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx @@ -172,10 +172,11 @@ const StartVisitForm: React.FC = ({ visitStopDate: displayVisitStopDateTimeFields && hadPreviousStopDateTime ? z.date() : z.date().optional(), visitStopTime: displayVisitStopDateTimeFields && hadPreviousStopDateTime - ? z + ? z.string().refine((value) => value.match(time12HourFormatRegex), t('invalidTimeFormat')) + : z .string() - .refine((value) => value.match(time12HourFormatRegex), t('invalidTimeFormat', 'Invalid time format')) - : z.string().optional(), + .refine((value) => !value || value.match(time12HourFormatRegex), t('invalidTimeFormat')) + .optional(), visitStopTimeFormat: displayVisitStopDateTimeFields && hadPreviousStopDateTime ? z.enum(['PM', 'AM'])