@kenyaemr/esm-patient-clinical-view-app 5.4.2-pre.2758 → 5.4.2-pre.2764

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/dist/127.js +1 -1
  3. package/dist/{805.js → 189.js} +1 -1
  4. package/dist/189.js.map +1 -0
  5. package/dist/40.js +1 -1
  6. package/dist/916.js +1 -1
  7. package/dist/kenyaemr-esm-patient-clinical-view-app.js +2 -2
  8. package/dist/kenyaemr-esm-patient-clinical-view-app.js.buildmanifest.json +36 -36
  9. package/dist/main.js +3 -3
  10. package/dist/main.js.map +1 -1
  11. package/dist/routes.json +1 -1
  12. package/package.json +1 -1
  13. package/src/config-schema.ts +58 -36
  14. package/src/maternal-and-child-health/partography/components/temperature-graph.component.tsx +0 -4
  15. package/src/maternal-and-child-health/partography/components/uterine-contractions-graph.component.tsx +33 -11
  16. package/src/maternal-and-child-health/partography/forms/cervical-contractions-form.component.tsx +124 -136
  17. package/src/maternal-and-child-health/partography/forms/cervix-form.component.tsx +23 -14
  18. package/src/maternal-and-child-health/partography/forms/drugs-iv-fluids-form.component.tsx +6 -10
  19. package/src/maternal-and-child-health/partography/forms/fetal-heart-rate-form.component.tsx +36 -13
  20. package/src/maternal-and-child-health/partography/forms/time-picker-dropdown.component.tsx +27 -46
  21. package/src/maternal-and-child-health/partography/forms/useCervixData.ts +2 -2
  22. package/src/maternal-and-child-health/partography/graphs/cervix-graph.component.tsx +56 -18
  23. package/src/maternal-and-child-health/partography/graphs/fetal-heart-rate-graph.component.tsx +36 -23
  24. package/src/maternal-and-child-health/partography/graphs/pulse-bp-graph.component.tsx +10 -5
  25. package/src/maternal-and-child-health/partography/partograph.component.tsx +315 -371
  26. package/src/maternal-and-child-health/partography/partography.resource.ts +788 -230
  27. package/src/maternal-and-child-health/partography/partography.scss +68 -40
  28. package/src/maternal-and-child-health/partography/resources/cervix.resource.ts +79 -76
  29. package/src/maternal-and-child-health/partography/resources/uterine-contractions.resource.ts +33 -12
  30. package/src/maternal-and-child-health/partography/types/index.ts +94 -0
  31. package/translations/am.json +0 -8
  32. package/translations/en.json +0 -8
  33. package/translations/sw.json +0 -8
  34. package/dist/805.js.map +0 -1
package/dist/routes.json CHANGED
@@ -1 +1 @@
1
- {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[{"component":"wrapComponent","route":"case-management"}],"extensions":[{"name":"hiv-care-and-treatment-dashboard-link","component":"hivCareAndTreatmentLink","slot":"patient-chart-dashboard-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-hiv-care-and-treatment-dashboard-slot","path":"hiv-care-and-treatment-dashboard","layoutMode":"anchored"}},{"name":"hiv-care-and-treatment-dashboard","slot":"patient-chart-hiv-care-and-treatment-dashboard-slot","component":"hivCareAndTreatment","order":0,"online":true,"offline":false},{"name":"relationship-dashboard-link","component":"relationshipsLink","order":24,"online":true,"offline":false,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-relationship-slot","path":"relationships","layoutMode":"anchored"}},{"name":"relationship-dashboard","slot":"patient-chart-relationship-slot","component":"relationships","order":0,"online":true,"offline":false},{"name":"clinical-encounter-dashboard-link","component":"clinicalEncounterLink","order":25,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-clinical-encounter-slot","path":"clinical-encounter","layoutMode":"anchored"}},{"name":"clinical-encounter-dashboard","slot":"patient-chart-clinical-encounter-slot","component":"clinicalEncounter","order":0,"online":true,"offline":false},{"name":"maternal-and-child-health-dashboard-link","component":"maternalAndChildHealthDashboardLink","order":26,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-maternal-and-child-health-slot","path":"maternal-and-child-health","layoutMode":"anchored"}},{"name":"maternal-and-child-health-dashboard","slot":"patient-chart-maternal-and-child-health-slot","component":"maternalAndChildHealthDashboard","order":0,"online":true,"offline":false},{"name":"maternal-and-child-health-partograph","slot":"maternal-and-child-health-partograph-slot","component":"partograph","order":0,"online":true,"offline":false},{"name":"contact-list-dashboard-link","component":"contactListLink","order":27,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-contact-list-slot","path":"contact-list","layoutMode":"anchored"}},{"name":"contact-list-dashboard","slot":"patient-chart-contact-list-slot","component":"contactList","order":0,"online":true,"offline":false},{"component":"caseManagementDashboardLink","name":"case-management-dashboard-link","meta":{"name":"case-management","title":"Case Management","slot":"case-management-dashboard-slot","path":"/case-management"}},{"name":"wrap-component-view","slot":"case-management-dashboard-slot","component":"wrapComponent","order":2,"online":true,"offline":false},{"name":"case-encounter-link","component":"caseEncounterDashboardLink","order":14,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-case-encounter-slot","path":"case-management-encounters","layoutMode":"anchored"}},{"name":"case-encounter-table","slot":"patient-chart-case-encounter-slot","component":"caseEncounterTable","order":0,"online":true,"offline":false},{"component":"peerCalendarDashboardLink","name":"peer-calendar-dashboard-link","meta":{"name":"peer-calendar","title":"Peer Calendar","slot":"peer-calendar-dashboard-slot","path":"peer-management"}},{"name":"peer-calendar","slot":"peer-calendar-dashboard-slot","component":"peerCalendar","order":0,"online":true,"offline":false},{"name":"special-clinics-dashboard-link","component":"specialClinicsDashboardLink","order":15,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-special-clinics-slot","path":"special-clinics","layoutMode":"anchored"}},{"name":"special-clinics-dashboard","slot":"patient-chart-special-clinics-slot","component":"specialClinicsDashboard","order":0,"online":true,"offline":false},{"name":"patient-complaints","slot":"ewf-patient-summary-slot","component":"patientComplaints","order":0,"online":true,"offline":false}],"modals":[{"name":"birth-date-calculator","component":"birthDateCalculator"},{"name":"relationship-delete-confirm-dialog","component":"relationshipDeleteConfirmialog"},{"name":"end-relationship-dialog","component":"endRelationshipModal"}],"workspaces":[{"name":"contact-list-form","component":"contactListForm","title":"Contact List Form","type":"form"},{"name":"case-management-form","component":"caseManagementForm","title":"Case Management Form","type":"form"},{"name":"add-patient-case-form","component":"addPatientCaseForm","title":"Add patient case Form","type":"form"},{"name":"family-relationship-form","component":"familyRelationshipForm","title":"Family Relationship Form","type":"form"},{"name":"peers-form","component":"peersForm","title":"Add New Peer","type":"form"},{"name":"kenyaemr-cusom-form-entry-workspace","component":"peerCalendarFormEntry","title":"KVP Peer Educator Outreach Calendar","type":"form","width":"extra-wide","canMaximize":true,"canHide":true},{"name":"contact-list-update-form","component":"contactListUpdateForm","title":"Contact List Update Form","type":"form"},{"name":"other-relationship-form","component":"otherRelationshipsForm","title":"Other Relationships Form","type":"form"},{"name":"end-relationship-form","component":"endRelationshipWorkspace","title":"Discontinue relationship form","type":"form"}],"version":"5.4.2-pre.2758"}
1
+ {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[{"component":"wrapComponent","route":"case-management"}],"extensions":[{"name":"hiv-care-and-treatment-dashboard-link","component":"hivCareAndTreatmentLink","slot":"patient-chart-dashboard-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-hiv-care-and-treatment-dashboard-slot","path":"hiv-care-and-treatment-dashboard","layoutMode":"anchored"}},{"name":"hiv-care-and-treatment-dashboard","slot":"patient-chart-hiv-care-and-treatment-dashboard-slot","component":"hivCareAndTreatment","order":0,"online":true,"offline":false},{"name":"relationship-dashboard-link","component":"relationshipsLink","order":24,"online":true,"offline":false,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-relationship-slot","path":"relationships","layoutMode":"anchored"}},{"name":"relationship-dashboard","slot":"patient-chart-relationship-slot","component":"relationships","order":0,"online":true,"offline":false},{"name":"clinical-encounter-dashboard-link","component":"clinicalEncounterLink","order":25,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-clinical-encounter-slot","path":"clinical-encounter","layoutMode":"anchored"}},{"name":"clinical-encounter-dashboard","slot":"patient-chart-clinical-encounter-slot","component":"clinicalEncounter","order":0,"online":true,"offline":false},{"name":"maternal-and-child-health-dashboard-link","component":"maternalAndChildHealthDashboardLink","order":26,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-maternal-and-child-health-slot","path":"maternal-and-child-health","layoutMode":"anchored"}},{"name":"maternal-and-child-health-dashboard","slot":"patient-chart-maternal-and-child-health-slot","component":"maternalAndChildHealthDashboard","order":0,"online":true,"offline":false},{"name":"maternal-and-child-health-partograph","slot":"maternal-and-child-health-partograph-slot","component":"partograph","order":0,"online":true,"offline":false},{"name":"contact-list-dashboard-link","component":"contactListLink","order":27,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-contact-list-slot","path":"contact-list","layoutMode":"anchored"}},{"name":"contact-list-dashboard","slot":"patient-chart-contact-list-slot","component":"contactList","order":0,"online":true,"offline":false},{"component":"caseManagementDashboardLink","name":"case-management-dashboard-link","meta":{"name":"case-management","title":"Case Management","slot":"case-management-dashboard-slot","path":"/case-management"}},{"name":"wrap-component-view","slot":"case-management-dashboard-slot","component":"wrapComponent","order":2,"online":true,"offline":false},{"name":"case-encounter-link","component":"caseEncounterDashboardLink","order":14,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-case-encounter-slot","path":"case-management-encounters","layoutMode":"anchored"}},{"name":"case-encounter-table","slot":"patient-chart-case-encounter-slot","component":"caseEncounterTable","order":0,"online":true,"offline":false},{"component":"peerCalendarDashboardLink","name":"peer-calendar-dashboard-link","meta":{"name":"peer-calendar","title":"Peer Calendar","slot":"peer-calendar-dashboard-slot","path":"peer-management"}},{"name":"peer-calendar","slot":"peer-calendar-dashboard-slot","component":"peerCalendar","order":0,"online":true,"offline":false},{"name":"special-clinics-dashboard-link","component":"specialClinicsDashboardLink","order":15,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-special-clinics-slot","path":"special-clinics","layoutMode":"anchored"}},{"name":"special-clinics-dashboard","slot":"patient-chart-special-clinics-slot","component":"specialClinicsDashboard","order":0,"online":true,"offline":false},{"name":"patient-complaints","slot":"ewf-patient-summary-slot","component":"patientComplaints","order":0,"online":true,"offline":false}],"modals":[{"name":"birth-date-calculator","component":"birthDateCalculator"},{"name":"relationship-delete-confirm-dialog","component":"relationshipDeleteConfirmialog"},{"name":"end-relationship-dialog","component":"endRelationshipModal"}],"workspaces":[{"name":"contact-list-form","component":"contactListForm","title":"Contact List Form","type":"form"},{"name":"case-management-form","component":"caseManagementForm","title":"Case Management Form","type":"form"},{"name":"add-patient-case-form","component":"addPatientCaseForm","title":"Add patient case Form","type":"form"},{"name":"family-relationship-form","component":"familyRelationshipForm","title":"Family Relationship Form","type":"form"},{"name":"peers-form","component":"peersForm","title":"Add New Peer","type":"form"},{"name":"kenyaemr-cusom-form-entry-workspace","component":"peerCalendarFormEntry","title":"KVP Peer Educator Outreach Calendar","type":"form","width":"extra-wide","canMaximize":true,"canHide":true},{"name":"contact-list-update-form","component":"contactListUpdateForm","title":"Contact List Update Form","type":"form"},{"name":"other-relationship-form","component":"otherRelationshipsForm","title":"Other Relationships Form","type":"form"},{"name":"end-relationship-form","component":"endRelationshipWorkspace","title":"Discontinue relationship form","type":"form"}],"version":"5.4.2-pre.2764"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kenyaemr/esm-patient-clinical-view-app",
3
- "version": "5.4.2-pre.2758",
3
+ "version": "5.4.2-pre.2764",
4
4
  "description": "Patient clinical view microfrontend for the OpenMRS SPA",
5
5
  "keywords": [
6
6
  "openmrs"
@@ -1,3 +1,8 @@
1
+ export const FETAL_HEART_RATE_GRAPH_UUIDS = {
2
+ fetalHeartRate: 'FETAL_HEART_RATE_CONCEPT',
3
+ fetalHeartRateHour: 'FETAL_HEART_RATE_HOUR_CONCEPT',
4
+ fetalHeartRateTime: 'FETAL_HEART_RATE_TIME_CONCEPT',
5
+ };
1
6
  import { Type } from '@openmrs/esm-framework';
2
7
  import _default from 'react-hook-form/dist/logic/appendErrors';
3
8
 
@@ -427,66 +432,83 @@ export const configSchema = {
427
432
  _default: '9065e3c6-b2f5-4f99-9cbf-f67fd9f82ec5',
428
433
  },
429
434
  };
430
- export const DRUG_ORDER_TYPE_UUID = '131168f4-15f5-102d-96e4-000c29c2a5d7';
431
- export const ENCOUNTER_ROLE = '240b26f9-dd88-4172-823d-4a8bfeb7841f';
432
- export const MOULDING_NONE_CONCEPT = '1107AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
433
- export const MOULDING_SLIGHT_CONCEPT = '1362AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
434
- export const MOULDING_MODERATE_CONCEPT = '1363AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
435
- export const MOULDING_SEVERE_CONCEPT = '1364AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
436
- export const CONTRACTION_LEVEL_MILD_CONCEPT = '1498AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
437
- export const CONTRACTION_LEVEL_MODERATE_CONCEPT = '1499AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
438
- export const CONTRACTION_LEVEL_STRONG_CONCEPT = '166788AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
439
- export const CERVIX_CONCEPT = '162261AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
435
+
436
+ // Fetal Heart Rate Graph
440
437
  export const FETAL_HEART_RATE_CONCEPT = '1440AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
438
+ export const FETAL_HEART_RATE_TIME_CONCEPT = 'bb3724c9-fbcc-49c5-9702-6cde0be325ca';
441
439
  export const FETAL_HEART_RATE_HOUR_CONCEPT = '160632AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
442
- export const FETAL_HEART_RATE_TIME_CONCEPT = '160632AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
443
- export const DESCENT_OF_HEAD_CONCEPT = '1810AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
440
+
441
+ // Membrane Amniotic Fluid Graph
442
+ export const AMNIOTIC_FLUID_CONCEPT = '162653AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
443
+ export const RUPTURED_MEMBRANES_CONCEPT = '164900AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
444
+ export const AMNIOTIC_CLEAR_LIQUOR_CONCEPT = '159484AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
445
+ export const AMNIOTIC_MECONIUM_STAINED_CONCEPT = '134488AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
446
+ export const AMNIOTIC_ABSENT_CONCEPT = '163747AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
447
+ export const AMNIOTIC_BLOOD_STAINED_CONCEPT = '1077AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
448
+ export const AMNIOTIC_MEMBRANE_INTACT_CONCEPT = 'd1787a76-7310-4223-a645-9fd410d418c1';
449
+
450
+ // Cervical Contractions Graph
444
451
  export const UTERINE_CONTRACTIONS_CONCEPT = '163750AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
452
+ export const CONTRACTION_LEVEL_MILD_CONCEPT = '1498AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
453
+ export const CONTRACTION_LEVEL_MODERATE_CONCEPT = '1499AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
454
+ export const CONTRACTION_LEVEL_STRONG_CONCEPT = '166788AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
445
455
  export const UTERINE_CONTRACTION_FREQUENCY_CONCEPT = '166529AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
446
456
  export const UTERINE_CONTRACTION_DURATION_CONCEPT = '159368AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
457
+
458
+ // Oxytocin Graph
459
+ export const OXYTOCIN_DOSE_CONCEPT = '81369AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
460
+ export const ROUTE_CONCEPT = '8878f9c0-a1ce-47ec-a88f-69ef0f6576ba';
461
+ export const FREQUENCY_CONCEPT = 'fd9f82fd-f327-4502-ac8e-5d9144dbd504';
462
+
463
+ // Drugs IV Fluids Graph
464
+ export const MEDICATION_CONCEPT = '1282AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
465
+ export const IV_FLUIDS_CONCEPT = '161911AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
466
+ export const DOSAGE_CONCEPT = 'b71ddb80-2d7f-4bde-a44b-236e62d4c1b6';
467
+ export const DRUG_DOSE_CONCEPT = '162384AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
468
+
469
+ // Pulse BP Graph
447
470
  export const MATERNAL_PULSE_CONCEPT = '5087AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
448
471
  export const SYSTOLIC_BP_CONCEPT = '5085AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
449
472
  export const DIASTOLIC_BP_CONCEPT = '5086AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
450
- export const TEMPERATURE_CONCEPT = '5088AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
451
- export const GLUCOSE_LEVEL_CONCEPT = '887AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
473
+ export const PULSE_BP_TIME_CONCEPT = 'bb3724c9-fbcc-49c5-9702-6cde0be325ca';
474
+
475
+ // Urine Test Graph
452
476
  export const PROTEIN_LEVEL_CONCEPT = '161442AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
477
+ export const GLUCOSE_LEVEL_CONCEPT = '887AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
453
478
  export const KETONE_LEVEL_CONCEPT = '165438AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
454
479
  export const URINE_VOLUME_CONCEPT = '159660AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
455
- export const CONTRACTION_COUNT_CONCEPT = '159682AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
456
480
  export const URINE_CHARACTERISTICS_CONCEPT = '56AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
457
- export const MEDICATION_CONCEPT = '1282AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
481
+
482
+ // Cervix / Cervical Monitoring During Labor
483
+ export const CERVIX_CONCEPT = '162261AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
484
+ export const DESCENT_OF_HEAD_CONCEPT = '1810AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
485
+ export const STATION_0_CONCEPT = '160769AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
486
+ export const STATION_1_CONCEPT = '162135AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
487
+ export const STATION_2_CONCEPT = '166065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
488
+ export const STATION_3_CONCEPT = '166066AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
489
+ export const STATION_4_CONCEPT = '166067AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
490
+ export const STATION_5_CONCEPT = '163734AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
491
+
492
+ export const DRUG_ORDER_TYPE_UUID = '131168f4-15f5-102d-96e4-000c29c2a5d7';
493
+ export const ENCOUNTER_ROLE = '240b26f9-dd88-4172-823d-4a8bfeb7841f';
494
+ export const MOULDING_NONE_CONCEPT = '1107AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
495
+ export const MOULDING_SLIGHT_CONCEPT = '1362AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
496
+ export const MOULDING_MODERATE_CONCEPT = '1363AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
497
+ export const MOULDING_SEVERE_CONCEPT = '1364AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
498
+ export const TEMPERATURE_CONCEPT = '5088AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
499
+ export const CONTRACTION_COUNT_CONCEPT = '159682AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
458
500
  export const MEDICATION_NAME_CONCEPT = '164231AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
459
- export const OXYTOCIN_DOSE_CONCEPT = '81369AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
460
- export const ROUTE_CONCEPT = '8878f9c0-a1ce-47ec-a88f-69ef0f6576ba';
461
- export const FREQUENCY_CONCEPT = 'fd9f82fd-f327-4502-ac8e-5d9144dbd504';
462
- export const IV_FLUIDS_CONCEPT = '161911AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
463
- export const DOSAGE_CONCEPT = 'b71ddb80-2d7f-4bde-a44b-236e62d4c1b6';
464
- export const DRUG_DOSE_CONCEPT = '162384AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
465
501
  export const EVENT_TYPE_CONCEPT = '162879AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
466
502
  export const EVENT_DESCRIPTION_CONCEPT = '160632AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
467
- export const AMNIOTIC_FLUID_CONCEPT = '162653AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
468
503
  export const MOULDING_CONCEPT = '166527AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
469
504
  export const BLOOD_GROUP_CONCEPT = '300AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
470
505
  export const TIME_SLOT_CONCEPT = '163286AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
471
- export const PULSE_BP_TIME_CONCEPT = 'bb3724c9-fbcc-49c5-9702-6cde0be325ca';
472
506
  export const LABOR_PATTERN_CONCEPT = '164135AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
473
507
  export const HOURS_SINCE_RUPTURE_CONCEPT = '167149AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
474
- export const RUPTURED_MEMBRANES_CONCEPT = '164900AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
475
508
  export const DATE_OF_ADMISSION_CONCEPT = '1640AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
476
509
  export const GESTATION_WEEKS_CONCEPT = '1789AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
477
510
  export const ESTIMATED_DELIVERY_DATE_CONCEPT = '5596AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
478
511
  export const LAST_MENSTRUAL_PERIOD_CONCEPT = '1427AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
479
- export const AMNIOTIC_CLEAR_LIQUOR_CONCEPT = '159484AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
480
- export const AMNIOTIC_MECONIUM_STAINED_CONCEPT = '134488AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
481
- export const AMNIOTIC_ABSENT_CONCEPT = '163747AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
482
- export const AMNIOTIC_BLOOD_STAINED_CONCEPT = '1077AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
483
- export const AMNIOTIC_MEMBRANE_INTACT_CONCEPT = 'd1787a76-7310-4223-a645-9fd410d418c1';
484
- export const STATION_0_CONCEPT = '160769AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
485
- export const STATION_1_CONCEPT = '162135AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
486
- export const STATION_2_CONCEPT = '166065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
487
- export const STATION_3_CONCEPT = '166066AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
488
- export const STATION_4_CONCEPT = '166067AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
489
- export const STATION_5_CONCEPT = '163734AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
490
512
 
491
513
  export interface ConfigObject {
492
514
  requireMaritalStatusOnAgeGreaterThanOrEqualTo: number;
@@ -43,8 +43,6 @@ const TemperatureGraph: React.FC<TemperatureGraphProps> = ({
43
43
  isLoading = false,
44
44
  }) => {
45
45
  const { t } = useTranslation();
46
-
47
- // Only show rows with both date and a time (exactTime or timeSlot)
48
46
  const filteredTableData = tableData.filter((item) => item.date && (item.exactTime || item.timeSlot));
49
47
  const timeColumns = filteredTableData.map((item) => item.exactTime || item.timeSlot || '--');
50
48
 
@@ -60,8 +58,6 @@ const TemperatureGraph: React.FC<TemperatureGraphProps> = ({
60
58
  }
61
59
  return '';
62
60
  };
63
-
64
- // Carbon skeleton for loading state
65
61
  const renderSkeleton = () => (
66
62
  <div className={styles.membraneGrid}>
67
63
  <div className={styles.gridContainer}>
@@ -47,12 +47,10 @@ const UterineContractionsGraph: React.FC<UterineContractionsGraphProps> = ({
47
47
  }) => {
48
48
  const { t } = useTranslation();
49
49
 
50
- // Only show rows with both date and timeSlot
51
50
  const filteredTableData = tableData.filter((item) => item.date && item.timeSlot);
52
51
  const timeColumns = filteredTableData.map((item) => item.timeSlot || '--');
53
52
  const yAxisLabels = ['5', '4', '3', '2', '1'];
54
53
 
55
- // Carbon skeleton for loading state
56
54
  const renderSkeleton = () => (
57
55
  <div className={styles.membraneGrid}>
58
56
  <div className={styles.gridContainer}>
@@ -118,6 +116,7 @@ const UterineContractionsGraph: React.FC<UterineContractionsGraphProps> = ({
118
116
  <h3 className={styles.fetalHeartRateTitle}>Uterine Contractions</h3>
119
117
  <div className={styles.fetalHeartRateControls}>
120
118
  <span className={styles.legendText}>
119
+ {}
121
120
  Contractions per 10 min | Bar Heights: 0=None, 2=Mild, 3=Moderate, 5=Strong
122
121
  </span>
123
122
  </div>
@@ -165,7 +164,6 @@ const UterineContractionsGraph: React.FC<UterineContractionsGraphProps> = ({
165
164
  ) : (
166
165
  <div className={styles.membraneGrid}>
167
166
  <div className={styles.gridContainer}>
168
- {/* Header row with time columns */}
169
167
  <div className={styles.gridHeader}>
170
168
  <div className={styles.gridCell}>{t('time', 'Time')}</div>
171
169
  {timeColumns.map((timeColumn, idx) => (
@@ -174,16 +172,40 @@ const UterineContractionsGraph: React.FC<UterineContractionsGraphProps> = ({
174
172
  </div>
175
173
  ))}
176
174
  </div>
177
- {/* Contractions row */}
178
175
  <div className={styles.gridRow}>
179
176
  <div className={styles.gridRowLabel}>{t('contractions', 'Contractions')}</div>
180
- {filteredTableData.map((item, idx) => (
181
- <div key={`contraction-${idx}`} className={styles.gridCell}>
182
- {item.contractionCount !== undefined && item.contractionCount !== null
183
- ? item.contractionCount
184
- : '--'}
185
- </div>
186
- ))}
177
+ {filteredTableData.map((item, idx) => {
178
+ const rawLevel = (item.contractionLevel || '').toLowerCase();
179
+
180
+ const getContractionLevel = (level) => {
181
+ if (level === '0' || level === 'none') {
182
+ return 'none';
183
+ }
184
+ if (level === '1' || level === 'mild') {
185
+ return 'mild';
186
+ }
187
+ if (level === '2' || level === 'moderate') {
188
+ return 'moderate';
189
+ }
190
+ if (level === '3' || level === '5' || level === 'strong') {
191
+ return 'strong';
192
+ }
193
+ return 'none';
194
+ };
195
+
196
+ const contractionLevel = getContractionLevel(rawLevel);
197
+
198
+ return (
199
+ <div
200
+ key={`contraction-${idx}`}
201
+ className={`${styles.gridCell} contractionsGridCell`}
202
+ data-contraction-level={contractionLevel}>
203
+ {item.contractionCount !== undefined && item.contractionCount !== null
204
+ ? item.contractionCount
205
+ : '--'}
206
+ </div>
207
+ );
208
+ })}
187
209
  </div>
188
210
  </div>
189
211
  </div>
@@ -1,10 +1,9 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useState } from 'react';
2
2
  import { useTranslation } from 'react-i18next';
3
3
  import { useForm, Controller } from 'react-hook-form';
4
- import { Button, Modal, Grid, Column, Dropdown } from '@carbon/react';
4
+ import { contractionLevelOptions as baseContractionLevelOptions } from '../types';
5
+ import { Modal, Dropdown } from '@carbon/react';
5
6
  import styles from '../partography.scss';
6
- import { CONTRACTION_STRONG_UUID } from '../types';
7
- import { MOULDING_NONE_CONCEPT, MOULDING_SLIGHT_CONCEPT, MOULDING_MODERATE_CONCEPT } from '../../../config-schema';
8
7
 
9
8
  type CervicalContractionsFormData = {
10
9
  contractionLevel: string;
@@ -32,7 +31,6 @@ const CervicalContractionsForm: React.FC<CervicalContractionsFormProps> = ({
32
31
  patient,
33
32
  }) => {
34
33
  const { t } = useTranslation();
35
-
36
34
  const {
37
35
  control,
38
36
  handleSubmit,
@@ -47,68 +45,50 @@ const CervicalContractionsForm: React.FC<CervicalContractionsFormProps> = ({
47
45
  },
48
46
  });
49
47
 
50
- const contractionLevelOptions = useMemo(
51
- () => [
52
- {
53
- value: 'none',
54
- label: t('noContractions', 'No Contractions'),
55
- concept: MOULDING_NONE_CONCEPT,
56
- visual: '0',
57
- visualClass: 'none',
58
- title: t('none', 'None'),
59
- },
60
- {
61
- value: 'mild',
62
- label: t('mildContractions', 'Mild Contractions'),
63
- concept: MOULDING_SLIGHT_CONCEPT,
64
- visual: '1',
65
- visualClass: 'mild',
66
- title: t('mild', 'Mild'),
67
- },
68
- {
69
- value: 'moderate',
70
- label: t('moderateContractions', 'Moderate Contractions'),
71
- concept: MOULDING_MODERATE_CONCEPT,
72
- visual: '2',
73
- visualClass: 'moderate',
74
- title: t('moderate', 'Moderate'),
75
- },
76
- {
77
- value: 'strong',
78
- label: t('strongContractions', 'Strong Contractions'),
79
- concept: CONTRACTION_STRONG_UUID,
80
- visual: '3',
81
- visualClass: 'strong',
82
- title: 'Strong',
83
- },
84
- ],
85
- [t],
86
- );
48
+ const contractionLevelOptions = baseContractionLevelOptions.map((opt) => ({
49
+ ...opt,
50
+ label: t(opt.labelKey, opt.defaultLabel),
51
+ title: opt.titleKey ? t(opt.titleKey, opt.defaultTitle) : opt.defaultTitle || opt.title,
52
+ }));
87
53
 
88
- const contractionCountItems = useMemo(
89
- () => [
90
- { id: '1', text: t('oneContraction', '1 contraction') },
91
- { id: '2', text: t('twoContractions', '2 contractions') },
92
- { id: '3', text: t('threeContractions', '3 contractions') },
93
- { id: '4', text: t('fourContractions', '4 contractions') },
94
- { id: '5', text: t('fiveContractions', '5 contractions') },
95
- ],
96
- [t],
97
- );
54
+ const [isSaving, setIsSaving] = useState(false);
98
55
 
99
- const handleFormSubmit = (data: CervicalContractionsFormData) => {
56
+ const handleFormSubmit = async (data: CervicalContractionsFormData) => {
57
+ clearErrors();
58
+ let hasErrors = false;
59
+ if (!data.contractionLevel || data.contractionLevel.trim() === '') {
60
+ setError('contractionLevel', {
61
+ type: 'manual',
62
+ message: t('contractionLevelRequired', 'Please select contraction level'),
63
+ });
64
+ hasErrors = true;
65
+ }
66
+ if (!data.contractionCount || data.contractionCount.trim() === '') {
67
+ setError('contractionCount', {
68
+ type: 'manual',
69
+ message: t('contractionCountRequired', 'Please select number of contractions'),
70
+ });
71
+ hasErrors = true;
72
+ }
73
+ if (hasErrors) {
74
+ alert(t('formValidationError', 'Please select both contraction level and count before submitting.'));
75
+ return;
76
+ }
100
77
  const currentTime = new Date().toLocaleTimeString('en-GB', {
101
78
  hour: '2-digit',
102
79
  minute: '2-digit',
103
80
  });
104
-
105
- onSubmit({
106
- contractionLevel: data.contractionLevel,
107
- contractionCount: data.contractionCount,
108
- timeSlot: currentTime,
109
- });
110
-
111
- reset();
81
+ setIsSaving(true);
82
+ try {
83
+ await onSubmit({
84
+ contractionLevel: data.contractionLevel,
85
+ contractionCount: data.contractionCount,
86
+ timeSlot: currentTime,
87
+ });
88
+ reset();
89
+ } finally {
90
+ setIsSaving(false);
91
+ }
112
92
  };
113
93
 
114
94
  const handleClose = () => {
@@ -121,87 +101,95 @@ const CervicalContractionsForm: React.FC<CervicalContractionsFormProps> = ({
121
101
  <Modal
122
102
  open={isOpen}
123
103
  onRequestClose={handleClose}
124
- primaryButtonText={t('save', 'Save')}
104
+ className={styles.cervixModal}
105
+ size="sm"
106
+ primaryButtonText={isSaving ? t('saving', 'Saving...') : t('save', 'Save')}
125
107
  secondaryButtonText={t('cancel', 'Cancel')}
126
108
  onRequestSubmit={handleSubmit(handleFormSubmit)}
127
109
  onSecondarySubmit={handleClose}
128
- className={styles.cervixModal}
129
- size="lg">
130
- <div className={styles.contractionsFormContainer}>
131
- <div className={styles.formMainSection}>
132
- <div className={styles.formSectionLeft}>
133
- <h3 className={styles.sectionTitle}>{t('cervicalContractionsData', 'Cervical Contractions')}</h3>
134
- <h4 className={styles.sectionTitle}>{t('contractionLevel', 'Select Contraction Level')}</h4>
135
- <p className={styles.sectionDescription}>
136
- {t('contractionLevelDescription', 'Choose the intensity of uterine contractions observed')}
137
- </p>
110
+ primaryButtonDisabled={isSaving}
111
+ preventCloseOnClickOutside={isSaving}>
112
+ <div className={styles.contractionsFormContainer} style={{ maxWidth: 600, margin: 0, padding: '0 8px' }}>
113
+ <h3 className={styles.sectionTitle} style={{ marginBottom: 0 }}>
114
+ {t('cervicalContractionsData', 'Cervical Contractions')}
115
+ </h3>
138
116
 
139
- <Controller
140
- name="contractionLevel"
141
- control={control}
142
- rules={{ required: t('contractionLevelRequired', 'Please select contraction level') }}
143
- render={({ field, fieldState }) => (
144
- <>
145
- <div className={styles.contractionLevelSelector}>
146
- {contractionLevelOptions.map((option) => (
147
- <div
148
- key={option.value}
149
- className={`${styles.contractionLevelOption} ${
150
- field.value === option.value ? styles.contractionLevelSelected : ''
151
- }`}
152
- onClick={() => field.onChange(option.value)}
153
- onKeyDown={(e) => {
154
- if (e.key === 'Enter' || e.key === ' ') {
155
- e.preventDefault();
156
- field.onChange(option.value);
157
- }
158
- }}
159
- role="button"
160
- tabIndex={0}
161
- aria-pressed={field.value === option.value}
162
- title={option.label}>
163
- <div className={styles.contractionLevelTitle}>{option.title}</div>
164
- <div className={`${styles.contractionLevelButton} ${styles[option.visualClass]}`}>
165
- {option.visual}
166
- </div>
167
- </div>
168
- ))}
117
+ <Controller
118
+ name="contractionLevel"
119
+ control={control}
120
+ rules={{ required: t('contractionLevelRequired', 'Please select contraction level') }}
121
+ render={({ field, fieldState }) => (
122
+ <div style={{ display: 'flex', justifyContent: 'center', marginTop: 24, marginBottom: 8 }}>
123
+ {contractionLevelOptions.map((option) => (
124
+ <div key={option.value} style={{ flex: 1, minWidth: 100, margin: '0 12px' }}>
125
+ <div style={{ textAlign: 'center', fontWeight: 600, marginBottom: 8 }}>{option.title}</div>
126
+ <div
127
+ className={`${styles.contractionLevelOption} ${
128
+ field.value === option.value ? styles.contractionLevelSelected : ''
129
+ }`}
130
+ onClick={() => field.onChange(option.value)}
131
+ onKeyDown={(e) => {
132
+ if (e.key === 'Enter' || e.key === ' ') {
133
+ e.preventDefault();
134
+ field.onChange(option.value);
135
+ }
136
+ }}
137
+ role="button"
138
+ tabIndex={0}
139
+ aria-pressed={field.value === option.value}
140
+ title={option.label}
141
+ style={{ minWidth: 80 }}>
142
+ <div className={`${styles.contractionLevelButton} ${styles[option.visualClass]}`}>
143
+ {option.visual}
144
+ </div>
169
145
  </div>
170
- {fieldState.error && <div className={styles.errorMessage}>{fieldState.error.message}</div>}
171
- </>
172
- )}
173
- />
174
- </div>
175
146
 
176
- <div className={styles.formSectionRight}>
177
- <Controller
178
- name="contractionCount"
179
- control={control}
180
- rules={{ required: t('contractionCountRequired', 'Please select number of contractions') }}
181
- render={({ field, fieldState }) => (
182
- <>
183
- <Dropdown
184
- id="contraction-count-dropdown"
185
- titleText={t('chooseCount', 'Number of Contractions')}
186
- label={t('chooseCount', 'Choose count')}
187
- items={contractionCountItems}
188
- itemToString={(item) => (item ? item.text : '')}
189
- selectedItem={
190
- field.value
191
- ? {
192
- id: field.value,
193
- text: `${field.value} contraction${field.value === '1' ? '' : 's'}`,
194
- }
195
- : null
196
- }
197
- onChange={({ selectedItem }) => field.onChange(selectedItem?.id || '')}
198
- className={styles.contractionCountDropdown}
199
- />
200
- {fieldState.error && <div className={styles.errorMessage}>{fieldState.error.message}</div>}
201
- </>
202
- )}
203
- />
204
- </div>
147
+ {option.value === contractionLevelOptions[contractionLevelOptions.length - 1].value &&
148
+ fieldState.error && <div className={styles.errorMessage}>{fieldState.error.message}</div>}
149
+ </div>
150
+ ))}
151
+ </div>
152
+ )}
153
+ />
154
+
155
+ <div style={{ margin: '32px 0 0 0', textAlign: 'left', fontWeight: 500 }}>
156
+ {t('chooseCount', 'Choose count')}
157
+ </div>
158
+ <div style={{ display: 'flex', justifyContent: 'flex-start', marginBottom: 16 }}>
159
+ <Controller
160
+ name="contractionCount"
161
+ control={control}
162
+ rules={{ required: t('contractionCountRequired', 'Please select number of contractions') }}
163
+ render={({ field, fieldState }) => (
164
+ <>
165
+ <Dropdown
166
+ id="contraction-count-dropdown"
167
+ titleText=""
168
+ label={t('chooseCount', 'Choose count')}
169
+ items={[
170
+ { id: '1', text: t('oneContraction', '1 contraction') },
171
+ { id: '2', text: t('twoContractions', '2 contractions') },
172
+ { id: '3', text: t('threeContractions', '3 contractions') },
173
+ { id: '4', text: t('fourContractions', '4 contractions') },
174
+ { id: '5', text: t('fiveContractions', '5 contractions') },
175
+ ]}
176
+ itemToString={(item) => (item ? item.text : '')}
177
+ selectedItem={
178
+ field.value
179
+ ? {
180
+ id: field.value,
181
+ text: `${field.value} contraction${field.value === '1' ? '' : 's'}`,
182
+ }
183
+ : null
184
+ }
185
+ onChange={({ selectedItem }) => field.onChange(selectedItem?.id || '')}
186
+ className={styles.contractionCountDropdown}
187
+ style={{ minWidth: 280, borderRadius: 24, background: '#eee', fontWeight: 600 }}
188
+ />
189
+ {fieldState.error && <div className={styles.errorMessage}>{fieldState.error.message}</div>}
190
+ </>
191
+ )}
192
+ />
205
193
  </div>
206
194
  </div>
207
195
  </Modal>