Skip to content

Commit

Permalink
(feat) (O3-2573): Implement the new snackbar patient management (pati…
Browse files Browse the repository at this point in the history
…ent-registration-app) (#892)

* feat: use snackbar and replace toast in patient registration app

* refactor: fix missing propery dateOfBirtt on fieldConfiguration test

* refactor: fix lowcontrast on error snackbars, and subtitle for translation keys

* refactor: extract translations
  • Loading branch information
usamaidrsk authored Dec 5, 2023
1 parent 30d0cc5 commit d9d83d0
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 74 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FetchResponse, openmrsFetch, showToast } from '@openmrs/esm-framework';
import { FetchResponse, openmrsFetch, showSnackbar } from '@openmrs/esm-framework';
import useSWRImmutable from 'swr/immutable';
import { ConceptAnswers, ConceptResponse } from '../patient-registration.types';

Expand All @@ -9,9 +9,9 @@ export function useConcept(conceptUuid: string): { data: ConceptResponse; isLoad
openmrsFetch,
);
if (error) {
showToast({
showSnackbar({
title: error.name,
description: error.message,
subtitle: error.message,
kind: 'error',
});
}
Expand All @@ -25,9 +25,9 @@ export function useConceptAnswers(conceptUuid: string): { data: Array<ConceptAns
openmrsFetch,
);
if (error) {
showToast({
showSnackbar({
title: error.name,
description: error.message,
subtitle: error.message,
kind: 'error',
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FetchResponse, openmrsFetch, showToast } from '@openmrs/esm-framework';
import { FetchResponse, openmrsFetch } from '@openmrs/esm-framework';
import useSWRImmutable from 'swr/immutable';
import { PersonAttributeTypeResponse } from '../../patient-registration.types';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { XAxis } from '@carbon/react/icons';
import { useLocation, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Formik, Form, FormikHelpers } from 'formik';
import { createErrorHandler, showToast, useConfig, interpolateUrl, usePatient } from '@openmrs/esm-framework';
import { createErrorHandler, showSnackbar, useConfig, interpolateUrl, usePatient } from '@openmrs/esm-framework';
import { validationSchema as initialSchema } from './validation/patient-registration-validation';
import { FormValues, CapturePhotoProps } from './patient-registration.types';
import { PatientRegistrationContext } from './patient-registration-context';
Expand Down Expand Up @@ -81,17 +81,18 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
abortController,
);

showToast({
description: inEditMode
? t('updationSuccessToastDescription', "The patient's information has been successfully updated")
showSnackbar({
subtitle: inEditMode
? t('updatePatientSuccessSnackbarSubtitle', "The patient's information has been successfully updated")
: t(
'registrationSuccessToastDescription',
'registerPatientSuccessSnackbarSubtitle',
'The patient can now be found by searching for them using their name or ID number',
),
title: inEditMode
? t('updationSuccessToastTitle', 'Patient Details Updated')
: t('registrationSuccessToastTitle', 'New Patient Created'),
? t('updatePatientSuccessSnackbarTitle', 'Patient Details Updated')
: t('registerPatientSuccessSnackbarTitle', 'New Patient Created'),
kind: 'success',
isLowContrast: true,
});

const afterUrl = new URLSearchParams(search).get('afterUrl');
Expand All @@ -101,10 +102,22 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
} catch (error) {
if (error.responseBody?.error?.globalErrors) {
error.responseBody.error.globalErrors.forEach((error) => {
showToast({ description: error.message });
showSnackbar({
title: inEditMode
? t('updatePatientErrorSnackbarTitle', 'Patient Details Update Failed')
: t('registrationErrorSnackbarTitle', 'Patient Registration Failed'),
subtitle: error.message,
kind: 'error',
});
});
} else if (error.responseBody?.error?.message) {
showToast({ description: error.responseBody.error.message });
showSnackbar({
title: inEditMode
? t('updatePatientErrorSnackbarTitle', 'Patient Details Update Failed')
: t('registrationErrorSnackbarTitle', 'Patient Registration Failed'),
subtitle: error.responseBody.error.message,
kind: 'error',
});
} else {
createErrorHandler()(error);
}
Expand All @@ -113,25 +126,15 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
}
};

const getDescription = (errors) => {
return (
<div>
<p>{t('fieldErrorTitleMessage', 'The following fields have errors:')}</p>
<ul style={{ listStyle: 'inside' }}>
{Object.keys(errors).map((error, index) => (
<li key={index}>{t(`${error}LabelText`, error)}</li>
))}
</ul>
</div>
);
};

const displayErrors = (errors) => {
if (errors && typeof errors === 'object' && !!Object.keys(errors).length) {
showToast({
description: getDescription(errors),
title: t('incompleteForm', 'Incomplete form'),
kind: 'warning',
Object.keys(errors).forEach((error) => {
showSnackbar({
subtitle: t(`${error}LabelText`, error),
title: t('incompleteForm', 'The following field has errors:'),
kind: 'warning',
isLowContrast: true,
});
});
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { BrowserRouter as Router, useParams } from 'react-router-dom';
import { render, screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { showToast, useConfig, usePatient } from '@openmrs/esm-framework';
import { showSnackbar, useConfig, usePatient } from '@openmrs/esm-framework';
import { FormManager } from './form-manager';
import { saveEncounter, savePatient } from './patient-registration.resource';
import type { Encounter } from './patient-registration.types';
Expand All @@ -16,7 +16,7 @@ const mockedUseConfig = useConfig as jest.Mock;
const mockedUsePatient = usePatient as jest.Mock;
const mockedSaveEncounter = saveEncounter as jest.Mock;
const mockedSavePatient = savePatient as jest.Mock;
const mockedShowToast = showToast as jest.Mock;
const mockedShowSnackbar = showSnackbar as jest.Mock;

jest.setTimeout(10000);

Expand Down Expand Up @@ -81,6 +81,14 @@ let mockOpenmrsConfig: RegistrationConfig = {
],
fieldDefinitions: [],
fieldConfigurations: {
dateOfBirth: {
allowEstimatedDateOfBirth: true,
useEstimatedDateOfBirth: {
enabled: true,
dayOfMonth: new Date().getDay(),
month: new Date().getMonth(),
},
},
name: {
displayMiddleName: true,
allowUnidentifiedPatients: true,
Expand Down Expand Up @@ -180,7 +188,7 @@ describe('patient registration component', () => {
mockedUseConfig.mockReturnValue(mockOpenmrsConfig);
mockedSavePatient.mockReturnValue({ data: { uuid: 'new-pt-uuid' }, ok: true });
mockedSaveEncounter.mockClear();
mockedShowToast.mockClear();
mockedShowSnackbar.mockClear();
jest.clearAllMocks();
});

Expand Down Expand Up @@ -327,15 +335,17 @@ describe('patient registration component', () => {
await waitFor(() => expect(mockedSavePatient).toHaveBeenCalledTimes(1));
await waitFor(() => expect(mockedSaveEncounter).toHaveBeenCalledTimes(1));
await waitFor(() =>
expect(mockedShowToast).toHaveBeenCalledWith(expect.objectContaining({ description: 'an error message' })),
expect(mockedShowSnackbar).toHaveBeenCalledWith(expect.objectContaining({ subtitle: 'an error message' })),
);

mockedSaveEncounter.mockResolvedValue({});

await user.click(screen.getByText('Register Patient'));
await waitFor(() => expect(mockedSavePatient).toHaveBeenCalledTimes(2));
await waitFor(() => expect(mockedSaveEncounter).toHaveBeenCalledTimes(2));
await waitFor(() => expect(mockedShowToast).toHaveBeenCalledWith(expect.objectContaining({ kind: 'success' })));
await waitFor(() =>
expect(mockedShowSnackbar).toHaveBeenCalledWith(expect.objectContaining({ kind: 'success' })),
);
});
});

Expand All @@ -344,7 +354,7 @@ describe('patient registration component', () => {
mockedUseConfig.mockReturnValue(mockOpenmrsConfig);
mockedSavePatient.mockReturnValue({ data: { uuid: 'new-pt-uuid' }, ok: true });
mockedSaveEncounter.mockClear();
mockedShowToast.mockClear();
mockedShowSnackbar.mockClear();
jest.clearAllMocks();
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FetchResponse, openmrsFetch, showToast } from '@openmrs/esm-framework';
import { FetchResponse, openmrsFetch } from '@openmrs/esm-framework';
import { RelationshipValue } from '../../patient-registration.types';
import useSWR from 'swr';
import { useMemo } from 'react';
Expand Down
11 changes: 6 additions & 5 deletions packages/esm-patient-registration-app/translations/am.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
"familyNameLabelText": "Family Name",
"familyNameRequired": "",
"female": "Female",
"fieldErrorTitleMessage": "The following fields have errors:",
"fullNameLabelText": "Full Name",
"genderLabelText": "Sex",
"genderRequired": "",
Expand Down Expand Up @@ -64,8 +63,9 @@
"patientNameKnown": "Patient's Name is Known?",
"patientRegistrationBreadcrumb": "Patient Registration",
"registerPatient": "Register Patient",
"registrationSuccessToastDescription": "The patient can now be found by searching for them using their name or ID number",
"registrationSuccessToastTitle": "New Patient Created",
"registerPatientSuccessSnackbarSubtitle": "The patient can now be found by searching for them using their name or ID number",
"registerPatientSuccessSnackbarTitle": "New Patient Created",
"registrationErrorSnackbarTitle": "Patient Registration Failed",
"relationship": "Relationship",
"relationshipPersonMustExist": "Related person must be an existing person",
"relationshipPlaceholder": "Relationship",
Expand All @@ -86,8 +86,9 @@
"unknown": "Unknown",
"unknownPatientAttributeType": "Patient attribute type has unknown format {{personAttributeTypeFormat}}",
"updatePatient": "Update Patient",
"updationSuccessToastDescription": "The patient's information has been successfully updated",
"updationSuccessToastTitle": "Patient Details Updated",
"updatePatientErrorSnackbarTitle": "Patient Details Update Failed",
"updatePatientSuccessSnackbarSubtitle": "The patient's information has been successfully updated",
"updatePatientSuccessSnackbarTitle": "Patient Details Updated",
"yearsEstimateRequired": "",
"yes": "Yes"
}
11 changes: 6 additions & 5 deletions packages/esm-patient-registration-app/translations/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
"familyNameLabelText": "اسم العائلة",
"familyNameRequired": "",
"female": "أنثى",
"fieldErrorTitleMessage": "الحقول التالية بها أخطاء:",
"fullNameLabelText": "الاسم الكامل",
"genderLabelText": "الجنس",
"genderRequired": "",
Expand Down Expand Up @@ -64,8 +63,9 @@
"patientNameKnown": "هل اسم المريض معروف؟",
"patientRegistrationBreadcrumb": "Patient Registration",
"registerPatient": "تسجيل المريض",
"registrationSuccessToastDescription": "يمكن الآن العثور على المريض عن طريق البحث عنه باستخدام اسمه أو رقم هويته",
"registrationSuccessToastTitle": "تم إنشاء مريض جديد",
"registerPatientSuccessSnackbarSubtitle": "The patient can now be found by searching for them using their name or ID number",
"registerPatientSuccessSnackbarTitle": "New Patient Created",
"registrationErrorSnackbarTitle": "Patient Registration Failed",
"relationship": "العلاقة",
"relationshipPersonMustExist": "Related person must be an existing person",
"relationshipPlaceholder": "العلاقة",
Expand All @@ -86,8 +86,9 @@
"unknown": "غير معروف",
"unknownPatientAttributeType": "Patient attribute type has unknown format {{personAttributeTypeFormat}}",
"updatePatient": "تحديث المريض",
"updationSuccessToastDescription": "تم تحديث معلومات المريض بنجاح",
"updationSuccessToastTitle": "تم تحديث تفاصيل المريض",
"updatePatientErrorSnackbarTitle": "Patient Details Update Failed",
"updatePatientSuccessSnackbarSubtitle": "The patient's information has been successfully updated",
"updatePatientSuccessSnackbarTitle": "Patient Details Updated",
"yearsEstimateRequired": "",
"yes": "نعم"
}
11 changes: 6 additions & 5 deletions packages/esm-patient-registration-app/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
"familyNameLabelText": "Family Name",
"familyNameRequired": "Family name is required",
"female": "Female",
"fieldErrorTitleMessage": "The following fields have errors:",
"fullNameLabelText": "Full Name",
"genderLabelText": "Sex",
"genderRequired": "Gender is required",
Expand Down Expand Up @@ -64,8 +63,9 @@
"patientNameKnown": "Patient's Name is Known?",
"patientRegistrationBreadcrumb": "Patient Registration",
"registerPatient": "Register Patient",
"registrationSuccessToastDescription": "The patient can now be found by searching for them using their name or ID number",
"registrationSuccessToastTitle": "New Patient Created",
"registerPatientSuccessSnackbarSubtitle": "The patient can now be found by searching for them using their name or ID number",
"registerPatientSuccessSnackbarTitle": "New Patient Created",
"registrationErrorSnackbarTitle": "Patient Registration Failed",
"relationship": "Relationship",
"relationshipPersonMustExist": "Related person must be an existing person",
"relationshipPlaceholder": "Relationship",
Expand All @@ -86,8 +86,9 @@
"unknown": "Unknown",
"unknownPatientAttributeType": "Patient attribute type has unknown format {{personAttributeTypeFormat}}",
"updatePatient": "Update Patient",
"updationSuccessToastDescription": "The patient's information has been successfully updated",
"updationSuccessToastTitle": "Patient Details Updated",
"updatePatientErrorSnackbarTitle": "Patient Details Update Failed",
"updatePatientSuccessSnackbarSubtitle": "The patient's information has been successfully updated",
"updatePatientSuccessSnackbarTitle": "Patient Details Updated",
"yearsEstimateRequired": "Years estimate required",
"yes": "Yes"
}
11 changes: 6 additions & 5 deletions packages/esm-patient-registration-app/translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
"familyNameLabelText": "Apellidos",
"familyNameRequired": "Apellidos es obligatorio",
"female": "Femenino",
"fieldErrorTitleMessage": "Los siguientes campos tienen errores:",
"fullNameLabelText": "Nombre y Apellidos",
"genderLabelText": "Sexo",
"genderRequired": "El sexo es obligatorio",
Expand Down Expand Up @@ -64,8 +63,9 @@
"patientNameKnown": "¿Se sabe el nombre del paciente?",
"patientRegistrationBreadcrumb": "Patient Registration",
"registerPatient": "Registrar paciente",
"registrationSuccessToastDescription": "Ahora se puede encontrar al paciente buscándolo por su nombre o número de identificación",
"registrationSuccessToastTitle": "Nuevo paciente creado",
"registerPatientSuccessSnackbarSubtitle": "The patient can now be found by searching for them using their name or ID number",
"registerPatientSuccessSnackbarTitle": "New Patient Created",
"registrationErrorSnackbarTitle": "Patient Registration Failed",
"relationship": "Relación",
"relationshipPersonMustExist": "Related person must be an existing person",
"relationshipPlaceholder": "Relación",
Expand All @@ -86,8 +86,9 @@
"unknown": "Desconocido",
"unknownPatientAttributeType": "Patient attribute type has unknown format {{personAttributeTypeFormat}}",
"updatePatient": "Paciente Actualizado",
"updationSuccessToastDescription": "La información del paciente se ha actualizado correctamente",
"updationSuccessToastTitle": "Datos del paciente actualizados",
"updatePatientErrorSnackbarTitle": "Patient Details Update Failed",
"updatePatientSuccessSnackbarSubtitle": "The patient's information has been successfully updated",
"updatePatientSuccessSnackbarTitle": "Patient Details Updated",
"yearsEstimateRequired": "Estimación de años obligatoria",
"yes": ""
}
11 changes: 6 additions & 5 deletions packages/esm-patient-registration-app/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
"familyNameLabelText": "Nom de famille",
"familyNameRequired": "Le nom de famille est requis",
"female": "Femme",
"fieldErrorTitleMessage": "Les champs suivants contiennent des erreurs:",
"fullNameLabelText": "Nom et Prénom",
"genderLabelText": "Sexe",
"genderRequired": "Le genre est requis",
Expand Down Expand Up @@ -64,8 +63,9 @@
"patientNameKnown": "Le nom du patient est connu?",
"patientRegistrationBreadcrumb": "Patient Registration",
"registerPatient": "Enregistrer un patient",
"registrationSuccessToastDescription": "Le patient peut maintenant être trouvé en faisant une recherche par son nom ou son numéro d'identification",
"registrationSuccessToastTitle": "Nouveau patient créé",
"registerPatientSuccessSnackbarSubtitle": "The patient can now be found by searching for them using their name or ID number",
"registerPatientSuccessSnackbarTitle": "New Patient Created",
"registrationErrorSnackbarTitle": "Patient Registration Failed",
"relationship": "Relation",
"relationshipPersonMustExist": "La personne liée doit être une personne existante",
"relationshipPlaceholder": "Relation",
Expand All @@ -86,8 +86,9 @@
"unknown": "Inconnu",
"unknownPatientAttributeType": "Patient attribute type has unknown format {{personAttributeTypeFormat}}",
"updatePatient": "Mettre à jour le patient",
"updationSuccessToastDescription": "Les informations du patient ont été mises à jour avec succès",
"updationSuccessToastTitle": "Les informations du patients ont été mises à jour",
"updatePatientErrorSnackbarTitle": "Patient Details Update Failed",
"updatePatientSuccessSnackbarSubtitle": "The patient's information has been successfully updated",
"updatePatientSuccessSnackbarTitle": "Patient Details Updated",
"yearsEstimateRequired": "Estimation du nombre d'années requise",
"yes": "Oui"
}
11 changes: 6 additions & 5 deletions packages/esm-patient-registration-app/translations/he.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
"familyNameLabelText": "שם משפחה",
"familyNameRequired": "שם משפחה נדרש",
"female": "נקבה",
"fieldErrorTitleMessage": "יש שגיאות בשדות הבאים:",
"fullNameLabelText": "שם מלא",
"genderLabelText": "מין",
"genderRequired": "מין נדרש",
Expand Down Expand Up @@ -64,8 +63,9 @@
"patientNameKnown": "שם המטופל ידוע?",
"patientRegistrationBreadcrumb": "רישום מטופל",
"registerPatient": "רשום מטופל",
"registrationSuccessToastDescription": "המטופל נרשם בהצלחה וניתן למצוא אותו באמצעות חיפוש לפי שם או מספר תעודת זהות",
"registrationSuccessToastTitle": "נרשם מטופל חדש",
"registerPatientSuccessSnackbarSubtitle": "The patient can now be found by searching for them using their name or ID number",
"registerPatientSuccessSnackbarTitle": "New Patient Created",
"registrationErrorSnackbarTitle": "Patient Registration Failed",
"relationship": "קשר",
"relationshipPersonMustExist": "האדם הקשור חייב להיות אדם קיים",
"relationshipPlaceholder": "קשר",
Expand All @@ -86,8 +86,9 @@
"unknown": "לא ידוע",
"unknownPatientAttributeType": "סוג המאפיין של המטופל לא ידוע {{personAttributeTypeFormat}}",
"updatePatient": "עדכון פרטי מטופל",
"updationSuccessToastDescription": "פרטי המטופל עודכנו בהצלחה",
"updationSuccessToastTitle": "פרטי המטופל עודכנו",
"updatePatientErrorSnackbarTitle": "Patient Details Update Failed",
"updatePatientSuccessSnackbarSubtitle": "The patient's information has been successfully updated",
"updatePatientSuccessSnackbarTitle": "Patient Details Updated",
"yearsEstimateRequired": "נדרש חיזוי שנים",
"yes": "כן"
}
Loading

0 comments on commit d9d83d0

Please sign in to comment.