From 38ba77e37f6ebd404f68e42644437edbcb3b9cb2 Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Wed, 11 Dec 2024 15:26:03 +0300 Subject: [PATCH 01/17] (refactor) updating the uuids --- packages/esm-morgue-app/src/config-schema.ts | 28 ++++++-------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/packages/esm-morgue-app/src/config-schema.ts b/packages/esm-morgue-app/src/config-schema.ts index 1c27d03c5..8c2bb40b0 100644 --- a/packages/esm-morgue-app/src/config-schema.ts +++ b/packages/esm-morgue-app/src/config-schema.ts @@ -1,27 +1,15 @@ import { Type } from '@openmrs/esm-framework'; export const configSchema = { - autopsyEncounterUuid: { - _type: Type.String, - _description: 'Encounter UUID for autopsy', - _default: '', - }, - formsList: { - _type: Type.Object, - _description: 'List of form UUIDs', - _default: { - autopsyFormUuid: '', - }, - }, morgueVisitTypeUuid: { _type: Type.String, _description: ' UUID for morgue visit', - _default: '6307dbe2-f336-4c11-a393-50c2769f455a', + _default: '02b67c47-6071-4091-953d-ad21452e830c', }, morgueDepartmentServiceTypeUuid: { _type: Type.String, _description: ' UUID for morgue department service type', - _default: '4a4a5b10-5740-48ff-929d-9f29c77125e9', + _default: '5b9e6cd1-f836-4144-91e4-401c58dd62af', }, insurancepaymentModeUuid: { _type: Type.String, @@ -36,7 +24,7 @@ export const configSchema = { tagNumberUuid: { _type: Type.String, _description: 'UUID for tag number concept', - _default: '4e4456fc-314a-4729-aa24-62e2b0637544', + _default: 'f2b35679-7ba9-4619-92cb-6872b0c6bf57', }, morgueAdmissionEncounterType: { _type: Type.String, @@ -56,22 +44,22 @@ export const configSchema = { obNumberUuid: { _type: Type.String, _description: 'UUID for ob number concept', - _default: '188ffac9-af2f-4a83-be58-f914f8bae08a', + _default: '0dffecb3-2dc4-4d56-8cd4-56ba38579c69', }, policeNameUuid: { _type: Type.String, _description: 'UUID for police name concept', - _default: '8c9922b3-37a8-4473-b81b-221a82c1c3cf', + _default: 'd889f05b-0d9b-462f-ae8e-2e9be79fd954', }, burialPermitNumberUuid: { _type: Type.String, _description: 'UUID for burial permit number concept', - _default: '63f961a7-1614-45ce-8cd1-7d5e98aa23c4', + _default: 'da524812-5600-4677-ba26-eb61eb925eef', }, policeIDNumber: { _type: Type.String, _description: 'UUID for police id number concept', - _default: '8a960c91-fc0e-4143-a9db-6c9fa57b51e2', + _default: '163084AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', }, encounterProviderRoleUuid: { _type: Type.UUID, @@ -81,7 +69,7 @@ export const configSchema = { dischargeAreaUuid: { _type: Type.String, _description: 'UUID for discharge area concept', - _default: 'a458fd00-199e-4d08-ad5c-1be322a6ccbe', + _default: '89ebccf1-4cca-4195-aeff-3e75fdf976b4', }, adminUuid: { _type: Type.String, From e926ff3f538e385c4e0a2657e225a939f07a8c01 Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Tue, 17 Dec 2024 14:45:09 +0300 Subject: [PATCH 02/17] (feat) added end relationship functionality --- .../case-management-header.component.tsx | 16 +++-- .../case-management-list-active-component.tsx | 58 +++++++++++++++++-- ...ase-management-list-inactive-component.tsx | 36 +++++++----- .../tabs/case-management-tabs.component.tsx | 11 +++- .../workspace/case-management.scss | 4 +- .../workspace/case-management.workspace.tsx | 28 ++------- .../case-management/wrap/wrap.component.tsx | 8 ++- 7 files changed, 106 insertions(+), 55 deletions(-) diff --git a/packages/esm-patient-clinical-view-app/src/case-management/metrics/case-management-header.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/metrics/case-management-header.component.tsx index ab029abd7..075e5c9bc 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/metrics/case-management-header.component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/metrics/case-management-header.component.tsx @@ -1,11 +1,15 @@ -import React, { useState } from 'react'; +import React from 'react'; import { useTranslation } from 'react-i18next'; import { WatsonHealthStressBreathEditor } from '@carbon/react/icons'; import { Button } from '@carbon/react'; import styles from './case-management-header.scss'; -import { launchWorkspace, navigate, useSession } from '@openmrs/esm-framework'; +import { launchWorkspace, useSession } from '@openmrs/esm-framework'; -const MetricsHeader = () => { +interface MetricsHeaderProps { + activeTabIndex: number; +} + +const MetricsHeader: React.FC = ({ activeTabIndex }) => { const { t } = useTranslation(); const { user } = useSession(); const metricsTitle = t(' ', 'Case Manager'); @@ -14,6 +18,9 @@ const MetricsHeader = () => { workspaceTitle: 'Case Management Form', }); }; + + const isDiscontinuationTab = activeTabIndex === 1; + return (
@@ -21,7 +28,8 @@ const MetricsHeader = () => { kind="tertiary" renderIcon={(props) => } iconDescription={t('addCase', 'Add case')} - onClick={handleAddCase}> + onClick={handleAddCase} + disabled={isDiscontinuationTab}> {t('addCase', 'Add case')}
diff --git a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx index b959e9b54..a47e61e1f 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx @@ -14,18 +14,29 @@ import { Layer, Tile, OverflowMenu, + Tag, + OverflowMenuItem, } from '@carbon/react'; import { CardHeader, EmptyDataIllustration } from '@openmrs/esm-patient-common-lib'; -import { ConfigurableLink, isDesktop, useLayoutType, useSession } from '@openmrs/esm-framework'; +import { + ConfigurableLink, + isDesktop, + launchWorkspace, + showSnackbar, + useLayoutType, + useSession, +} from '@openmrs/esm-framework'; import styles from './case-management-list.scss'; import { useActivecases } from '../workspace/case-management.resource'; import { extractNameString, uppercaseText } from '../../utils/expression-helper'; +import { updateRelationship } from '../../relationships/relationship.resources'; interface CaseManagementListActiveProps { setActiveCasesCount: (count: number) => void; + activeTabIndex: number; } -const CaseManagementListActive: React.FC = ({ setActiveCasesCount }) => { +const CaseManagementListActive: React.FC = ({ setActiveCasesCount, activeTabIndex }) => { const { t } = useTranslation(); const layout = useLayoutType(); const [pageSize, setPageSize] = useState(10); @@ -35,7 +46,7 @@ const CaseManagementListActive: React.FC = ({ set const { user } = useSession(); const caseManagerPersonUuid = user?.person.uuid; - const { data: activeCasesData, error: activeCasesError } = useActivecases(caseManagerPersonUuid); + const { data: activeCasesData, error: activeCasesError, mutate: fetchCases } = useActivecases(caseManagerPersonUuid); const patientChartUrl = '${openmrsSpaBase}/patient/${patientUuid}/chart/case-management-encounters'; @@ -43,6 +54,7 @@ const CaseManagementListActive: React.FC = ({ set { key: 'names', header: t('names', 'Names') }, { key: 'dateofstart', header: t('dateofstart', 'Start Date') }, { key: 'dateofend', header: t('dateofend', 'End Date') }, + { key: 'actions', header: t('actions', 'Actions') }, ]; const filteredCases = activeCasesData?.data.results.filter( @@ -51,6 +63,28 @@ const CaseManagementListActive: React.FC = ({ set (extractNameString(caseData.personB.display).toLowerCase().includes(searchTerm.toLowerCase()) || caseData.personB.display.toLowerCase().includes(searchTerm.toLowerCase())), ); + const handleDiscontinueACase = async (relationshipUuid: string) => { + try { + await updateRelationship(relationshipUuid, { endDate: new Date() }); + await fetchCases(); + + showSnackbar({ + kind: 'success', + title: t('endRlship', 'End relationship'), + subtitle: t('savedRlship', 'Relationship ended successfully'), + timeoutInMs: 3000, + isLowContrast: true, + }); + } catch (error) { + showSnackbar({ + kind: 'error', + title: t('RlshipError', 'Relationship Error'), + subtitle: t('RlshipError', 'Request Failed.......'), + timeoutInMs: 2500, + isLowContrast: true, + }); + } + }; const tableRows = filteredCases ?.slice((currentPage - 1) * pageSize, currentPage * pageSize) @@ -65,7 +99,23 @@ const CaseManagementListActive: React.FC = ({ set ), dateofstart: new Date(caseData.startDate).toLocaleDateString(), - dateofend: caseData.endDate ? new Date(caseData.endDate).toLocaleDateString() : '-', + dateofend: caseData.endDate ? ( + new Date(caseData.endDate).toLocaleDateString() + ) : ( + + {t('enrolled', 'Enrolled')} + + ), + actions: ( + + handleDiscontinueACase(caseData.uuid)} + /> + + ), })); useEffect(() => { diff --git a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-inactive-component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-inactive-component.tsx index cd35822c8..d06245b33 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-inactive-component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-inactive-component.tsx @@ -13,7 +13,7 @@ import { Search, Layer, Tile, - OverflowMenu, + Tag, } from '@carbon/react'; import { CardHeader, EmptyDataIllustration } from '@openmrs/esm-patient-common-lib'; import { ConfigurableLink, isDesktop, useLayoutType, useSession } from '@openmrs/esm-framework'; @@ -43,6 +43,7 @@ const CaseManagementListInActive: React.FC = ({ { key: 'names', header: t('names', 'Names') }, { key: 'dateofstart', header: t('dateofstart', 'Start Date') }, { key: 'dateofend', header: t('dateofend', 'End Date') }, + { key: 'status', header: t('status', 'Status') }, ]; const filteredCases = inactiveCasesData?.data.results.filter( @@ -52,21 +53,24 @@ const CaseManagementListInActive: React.FC = ({ caseData.personB.display.toLowerCase().includes(searchTerm.toLowerCase())), ); - const tableRows = filteredCases - ?.slice((currentPage - 1) * pageSize, currentPage * pageSize) - .map((caseData, index) => ({ - id: caseData.uuid, - names: ( - - {uppercaseText(extractNameString(caseData.personB.display))} - - ), - dateofstart: new Date(caseData.startDate).toLocaleDateString(), - dateofend: new Date(caseData.endDate).toLocaleDateString(), - })); + const tableRows = filteredCases?.slice((currentPage - 1) * pageSize, currentPage * pageSize).map((caseData) => ({ + id: caseData.uuid, + names: ( + + {uppercaseText(extractNameString(caseData.personB.display))} + + ), + dateofstart: new Date(caseData.startDate).toLocaleDateString(), + dateofend: new Date(caseData.endDate).toLocaleDateString(), + status: caseData.endDate ? ( + + {t('discontinued', 'Discontinued')} + + ) : null, + })); useEffect(() => { const count = filteredCases?.length || 0; diff --git a/packages/esm-patient-clinical-view-app/src/case-management/tabs/case-management-tabs.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/tabs/case-management-tabs.component.tsx index e57c5d0d6..238c0dafd 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/tabs/case-management-tabs.component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/tabs/case-management-tabs.component.tsx @@ -5,13 +5,18 @@ import styles from './case-management-tabs.scss'; import CaseManagementListActive from '../table/case-management-list-active-component'; import CaseManagementListInActive from '../table/case-management-list-inactive-component'; -const CaseManagementTabs: React.FC = () => { +interface CaseManagementTabsProps { + setActiveTabIndex: (index: number) => void; +} + +const CaseManagementTabs: React.FC = ({ setActiveTabIndex }) => { const { t } = useTranslation(); - const [activeTabIndex, setActiveTabIndex] = useState(0); + const [activeTabIndex, setLocalActiveTabIndex] = useState(0); const [activeCasesCount, setActiveCasesCount] = useState(0); const [inactiveCasesCount, setInactiveCasesCount] = useState(0); const handleTabChange = ({ selectedIndex }: { selectedIndex: number }) => { + setLocalActiveTabIndex(selectedIndex); setActiveTabIndex(selectedIndex); }; @@ -30,7 +35,7 @@ const CaseManagementTabs: React.FC = () => {
- + diff --git a/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.scss b/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.scss index 2a6cd0378..fb2388311 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.scss +++ b/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.scss @@ -19,8 +19,8 @@ color: $ui-05; } } -.datePickerInput { - width: 23rem; +.formDatePicker input { + min-width: 24rem; } .form { display: flex; diff --git a/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.workspace.tsx b/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.workspace.tsx index c5c6dc123..beb89d557 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.workspace.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.workspace.tsx @@ -15,7 +15,6 @@ const schema = z.object({ caseManager: z.string().nonempty({ message: 'Case Manager is required' }), relationship: z.string().nonempty({ message: 'Relationship is required' }), startDate: z.date({ required_error: 'Start Date is required' }), - endDate: z.date().optional(), notes: z.string().optional(), }); @@ -65,7 +64,6 @@ const CaseManagementForm: React.FC = ({ closeWorkspace }) => relationshipType: data.relationship, personB: patientUuid, startDate: data.startDate.toISOString(), - endDate: data.endDate ? data.endDate.toISOString() : null, }; try { @@ -167,13 +165,16 @@ const CaseManagementForm: React.FC = ({ closeWorkspace }) => name="startDate" control={control} render={({ field, fieldState }) => ( - field.onChange(e[0])}> + field.onChange(e[0])} + className={styles.formDatePicker}> @@ -181,25 +182,6 @@ const CaseManagementForm: React.FC = ({ closeWorkspace }) => )} /> - - - ( - field.onChange(e[0])}> - - - )} - /> - - { + const [activeTabIndex, setActiveTabIndex] = useState(0); + return (
- - + +
); }; From 3b6270156a0164d91828e499a726dc271001f095 Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Tue, 17 Dec 2024 20:40:55 +0300 Subject: [PATCH 03/17] (feat) added a ability to end relationship on case management --- .../test-order-action.component.tsx | 2 +- .../test-order/test-order-action.test.tsx | 117 ++++++------------ .../modal/case-management-modal.component.tsx | 92 ++++++++++++++ .../modal/end-date.component.tsx | 34 +++++ .../src/case-management/modal/end-date.scss | 20 +++ .../case-management-list-active-component.tsx | 25 +--- .../src/index.ts | 4 + .../src/routes.json | 4 + 8 files changed, 198 insertions(+), 100 deletions(-) create mode 100644 packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx create mode 100644 packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx create mode 100644 packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.scss diff --git a/packages/esm-billing-app/src/billable-services/billiable-item/test-order/test-order-action.component.tsx b/packages/esm-billing-app/src/billable-services/billiable-item/test-order/test-order-action.component.tsx index 0899004b9..08a1c0174 100644 --- a/packages/esm-billing-app/src/billable-services/billiable-item/test-order/test-order-action.component.tsx +++ b/packages/esm-billing-app/src/billable-services/billiable-item/test-order/test-order-action.component.tsx @@ -56,7 +56,7 @@ const TestOrderAction: React.FC = (props) => { order, ...(additionalProps && { additionalProps }), }); - }, [order, additionalProps, modalName, handleModalClose]); + }, [isDispenseOrder, modalName, order, additionalProps, dispenseFormProps, handleModalClose]); if (isLoading) { return ( diff --git a/packages/esm-billing-app/src/billable-services/billiable-item/test-order/test-order-action.test.tsx b/packages/esm-billing-app/src/billable-services/billiable-item/test-order/test-order-action.test.tsx index aebf42b93..4a4fa1c0c 100644 --- a/packages/esm-billing-app/src/billable-services/billiable-item/test-order/test-order-action.test.tsx +++ b/packages/esm-billing-app/src/billable-services/billiable-item/test-order/test-order-action.test.tsx @@ -8,116 +8,75 @@ import { launchWorkspace, showModal } from '@openmrs/esm-framework'; import { createMedicationDispenseProps } from './dispense.resource'; jest.mock('./test-order-action.resource'); - -const mockTestProps = { - order: { uuid: '123', patient: { uuid: '456' } } as Order, - patientUuid: 'patient-uuid-123', - encounterUuid: 'encounter-uuid-456', - medicationRequestBundle: { - request: { - id: 'med-request-789', - medicationReference: { reference: 'Medication/med-123' }, - medicationCodeableConcept: { coding: [{ code: 'med-code-123' }] }, - subject: { reference: 'Patient/patient-uuid-123' }, - dispenseRequest: { - quantity: { - value: 30, - code: 'TAB', - unit: 'tablets', - system: 'http://terminology.hl7.org/CodeSystem/v3-orderableDrugForm', +jest.mock('./dispense.resource', () => ({ + createMedicationDispenseProps: jest.fn(() => ({ + whenHandedOver: '2024-12-17T11:52:35+00:00', + medicationRequestBundle: { + request: { + dispenseRequest: { + quantity: { value: 30, code: 'TAB', unit: 'tablets' }, }, }, - dosageInstruction: [ - { - text: 'Take 1 tablet daily', - timing: { code: 'daily' }, - route: { coding: [{ code: 'PO' }] }, - doseAndRate: [ - { - doseQuantity: { - value: 1, - code: 'TAB', - unit: 'tablet', - }, - }, - ], - additionalInstruction: [{ text: 'with food' }], - }, - ], - }, - }, - quantityRemaining: 30, - session: { - currentProvider: { - uuid: 'provider-uuid-123', }, - sessionLocation: { - uuid: 'location-uuid-456', - }, - }, - providers: [ - { - uuid: 'provider-uuid-123', - display: 'Dr. Test Provider', - }, - ], - closeable: true, -} as Record; + otherProp: 'test-value', + })), +})); + +jest.mock('@openmrs/esm-framework', () => ({ + launchWorkspace: jest.fn(), + showModal: jest.fn(), +})); const testProps = { order: { uuid: '123', patient: { uuid: '456' } } as Order, + modalName: 'test-modal', + actionText: 'Test Action', }; describe('TestOrderAction', () => { beforeEach(() => { jest.resetAllMocks(); jest.clearAllMocks(); + jest.useFakeTimers().setSystemTime(new Date('2024-12-17T11:52:35Z')); }); - test('should render loading when isLoading is true', () => { + afterEach(() => { + jest.useRealTimers(); + }); + + test('should render loading state when isLoading is true', () => { jest.spyOn(resource, 'useTestOrderBillStatus').mockReturnValueOnce({ isLoading: true, hasPendingPayment: false }); render(); + expect(screen.getByText('Verifying bill status...')).toBeInTheDocument(); + expect(screen.getByRole('button')).toBeDisabled(); }); - test("should display `Unsettled bill for test` when there's a pending payment", () => { + test('should display "Unsettled bill" when hasPendingPayment is true', () => { jest.spyOn(resource, 'useTestOrderBillStatus').mockReturnValueOnce({ isLoading: false, hasPendingPayment: true }); render(); + expect(screen.getByText('Unsettled bill')).toBeInTheDocument(); + expect(screen.getByRole('button')).toBeDisabled(); }); - test("should display `Pick Lab Request` when there's no pending payment", async () => { - const user = userEvent.setup(); + test('should render the button with correct action text', () => { jest.spyOn(resource, 'useTestOrderBillStatus').mockReturnValueOnce({ isLoading: false, hasPendingPayment: false }); render(); - const pickLabRequestMenuItem = screen.getByText('Pick Lab Request'); - await user.click(pickLabRequestMenuItem); - expect(screen.queryByText('Unsettled bill.')).not.toBeInTheDocument(); - expect(showModal).toBeCalledWith('pickup-lab-request-modal', { - closeModal: expect.any(Function), - order: { patient: { uuid: '456' }, uuid: '123' }, - }); + expect(screen.getByText('Test Action')).toBeInTheDocument(); + expect(screen.getByRole('button')).toBeEnabled(); }); - test('should not render the dispense form if closeable is false', () => { - jest.spyOn(resource, 'useTestOrderBillStatus').mockReturnValueOnce({ isLoading: false, hasPendingPayment: false }); - render(); - expect(screen.queryByText('Dispense')).not.toBeInTheDocument(); - }); + test('should not render button if order is in progress', () => { + const inProgressProps = { + ...testProps, + order: { ...testProps.order, fulfillerStatus: 'IN_PROGRESS' } as Order, + }; - test('should launch the dispense form when dispense order is part of props', async () => { - const user = userEvent.setup(); jest.spyOn(resource, 'useTestOrderBillStatus').mockReturnValueOnce({ isLoading: false, hasPendingPayment: false }); - render(); - const dispenseButton = screen.getByRole('button', { name: 'Dispense' }); - expect(dispenseButton).toBeInTheDocument(); - - await user.click(dispenseButton); - const dispenseFormProps = createMedicationDispenseProps(mockTestProps); + render(); - expect(launchWorkspace).toHaveBeenCalledWith('dispense-workspace', { - ...dispenseFormProps, - }); + expect(screen.queryByRole('button')).not.toBeInTheDocument(); }); }); diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx new file mode 100644 index 000000000..5c0d0944d --- /dev/null +++ b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx @@ -0,0 +1,92 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, ModalBody, ModalFooter, ModalHeader, Column } from '@carbon/react'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { mutate } from 'swr'; +import { updateRelationship } from '../../relationships/relationship.resources'; +import { showSnackbar } from '@openmrs/esm-framework'; +import EndDatePicker from './end-date.component'; +import styles from './end-date.scss'; + +const EndRelationshipSchema = z.object({ + endDate: z.date({ + required_error: 'End date is required', + invalid_type_error: 'Please select a valid date', + }), +}); + +type FormData = z.infer; + +interface EndRelationshipModalProps { + closeModal: () => void; + relationshipUuid: string; +} + +const EndRelationshipModal: React.FC = ({ closeModal, relationshipUuid }) => { + const { t } = useTranslation(); + const [isSubmitting, setIsSubmitting] = useState(false); + + const { + handleSubmit, + control, + formState: { errors }, + } = useForm({ + resolver: zodResolver(EndRelationshipSchema), + defaultValues: { endDate: null }, + }); + + const handleEndRelationship = async (data: FormData) => { + try { + setIsSubmitting(true); + await updateRelationship(relationshipUuid, { endDate: data.endDate }); + mutate((key) => typeof key === 'string' && key.startsWith('/ws/rest/v1/relationship'), undefined, { + revalidate: true, + }); + showSnackbar({ + kind: 'success', + title: t('endRlship', 'End relationship'), + subtitle: t('savedRlship', 'Relationship ended successfully'), + timeoutInMs: 3000, + isLowContrast: true, + }); + closeModal(); + } catch (error) { + showSnackbar({ + kind: 'error', + title: t('RlshipError', 'Relationship Error'), + subtitle: t('RlshipErrorMessage', 'Request Failed'), + timeoutInMs: 2500, + isLowContrast: true, + }); + } finally { + setIsSubmitting(false); + } + }; + + return ( +
+
+

{t('endRelationship', 'End Relationship')}

+
+
+

{t('rlshipConfirmationText', 'This will end the relationship. Are you sure you want to proceed?')}

+ +
+ +
+
+ + + + +
+ ); +}; + +export default EndRelationshipModal; diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx new file mode 100644 index 000000000..50af7dd4c --- /dev/null +++ b/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { Controller, Control } from 'react-hook-form'; +import { DatePicker, DatePickerInput } from '@carbon/react'; +import styles from './end-date.scss'; + +interface EndDatePickerProps { + name: string; + control: Control; + label?: string; +} + +const EndDatePicker: React.FC = ({ name, control, label }) => { + return ( + ( + field.onChange(e[0])} className={styles.formDatePicker}> + + + )} + /> + ); +}; + +export default EndDatePicker; diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.scss b/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.scss new file mode 100644 index 000000000..be9cccded --- /dev/null +++ b/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.scss @@ -0,0 +1,20 @@ +@use '@carbon/colors'; +@use '@carbon/layout'; +@use '@carbon/type'; + +.formDatePicker input { + min-width: 50rem; + display: flex; + align-items: center; + justify-content: space-between; + border: 1px solid colors.$gray-50; + padding: layout.$spacing-04 layout.$spacing-05; + background-color: colors.$white; +} + +.centeredContainer { + display: flex; + justify-content: center; + align-items: center; + margin: layout.$spacing-06 layout.$spacing-07; +} diff --git a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx index a47e61e1f..83e634fa3 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx @@ -22,6 +22,7 @@ import { ConfigurableLink, isDesktop, launchWorkspace, + showModal, showSnackbar, useLayoutType, useSession, @@ -64,26 +65,10 @@ const CaseManagementListActive: React.FC = ({ set caseData.personB.display.toLowerCase().includes(searchTerm.toLowerCase())), ); const handleDiscontinueACase = async (relationshipUuid: string) => { - try { - await updateRelationship(relationshipUuid, { endDate: new Date() }); - await fetchCases(); - - showSnackbar({ - kind: 'success', - title: t('endRlship', 'End relationship'), - subtitle: t('savedRlship', 'Relationship ended successfully'), - timeoutInMs: 3000, - isLowContrast: true, - }); - } catch (error) { - showSnackbar({ - kind: 'error', - title: t('RlshipError', 'Relationship Error'), - subtitle: t('RlshipError', 'Request Failed.......'), - timeoutInMs: 2500, - isLowContrast: true, - }); - } + const dispose = showModal('end-relationship-dialog', { + relationshipUuid, + closeModal: () => dispose(), + }); }; const tableRows = filteredCases diff --git a/packages/esm-patient-clinical-view-app/src/index.ts b/packages/esm-patient-clinical-view-app/src/index.ts index 4e7a6b350..ee202cf30 100644 --- a/packages/esm-patient-clinical-view-app/src/index.ts +++ b/packages/esm-patient-clinical-view-app/src/index.ts @@ -55,6 +55,7 @@ import RelationshipUpdateForm from './relationships/forms/relationships-update-f import DeleteRelationshipConfirmDialog from './relationships/modals/delete-relationship-dialog.modal'; import DeceasedDetailsView from './deceased-panel/tabs/tabs.component'; import DeceasedPanelDashboardLink from './deceased-panel/dashboard-link/dashboard-link.component'; +import EndRelationshipModal from './case-management/modal/case-management-modal.component'; const moduleName = '@kenyaemr/esm-patient-clinical-view-app'; @@ -154,6 +155,9 @@ export const inPatientChartDashboard = getSyncLifecycle(InPatient, options); export const peerCalendarFormEntry = getSyncLifecycle(FormEntryWorkspace, options); +// Case management modal +export const endRelationshipModal = getSyncLifecycle(EndRelationshipModal, options); + export function startupApp() { defineConfigSchema(moduleName, configSchema); } diff --git a/packages/esm-patient-clinical-view-app/src/routes.json b/packages/esm-patient-clinical-view-app/src/routes.json index 6a20a39dc..d529f1bae 100644 --- a/packages/esm-patient-clinical-view-app/src/routes.json +++ b/packages/esm-patient-clinical-view-app/src/routes.json @@ -305,6 +305,10 @@ { "name": "relationship-delete-confirm-dialog", "component": "relationshipDeleteConfirmialog" + }, + { + "name": "end-relationship-dialog", + "component": "endRelationshipModal" } ], "workspaces": [ From 84e29438847e45654905cad6cc7525ee1eb34d5d Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Thu, 19 Dec 2024 12:43:58 +0300 Subject: [PATCH 04/17] (refactor) updated PR per suggestion --- .../modal/case-management-modal.component.tsx | 41 +++++++++++++------ ...d-date.scss => case-management-modal.scss} | 0 .../modal/end-date.component.tsx | 34 --------------- .../case-management-list-active-component.tsx | 6 +-- .../translations/en.json | 11 ++++- 5 files changed, 41 insertions(+), 51 deletions(-) rename packages/esm-patient-clinical-view-app/src/case-management/modal/{end-date.scss => case-management-modal.scss} (100%) delete mode 100644 packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx index 5c0d0944d..dca8de6b1 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx @@ -1,14 +1,13 @@ -import React, { useState } from 'react'; +import React from 'react'; import { useTranslation } from 'react-i18next'; -import { Button, ModalBody, ModalFooter, ModalHeader, Column } from '@carbon/react'; -import { useForm } from 'react-hook-form'; +import { Button, DatePicker, DatePickerInput, ModalFooter } from '@carbon/react'; +import { useForm, Controller } from 'react-hook-form'; import { z } from 'zod'; import { zodResolver } from '@hookform/resolvers/zod'; import { mutate } from 'swr'; import { updateRelationship } from '../../relationships/relationship.resources'; import { showSnackbar } from '@openmrs/esm-framework'; -import EndDatePicker from './end-date.component'; -import styles from './end-date.scss'; +import styles from './case-management-modal.scss'; const EndRelationshipSchema = z.object({ endDate: z.date({ @@ -26,12 +25,11 @@ interface EndRelationshipModalProps { const EndRelationshipModal: React.FC = ({ closeModal, relationshipUuid }) => { const { t } = useTranslation(); - const [isSubmitting, setIsSubmitting] = useState(false); const { handleSubmit, control, - formState: { errors }, + formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(EndRelationshipSchema), defaultValues: { endDate: null }, @@ -39,14 +37,13 @@ const EndRelationshipModal: React.FC = ({ closeModal, const handleEndRelationship = async (data: FormData) => { try { - setIsSubmitting(true); await updateRelationship(relationshipUuid, { endDate: data.endDate }); mutate((key) => typeof key === 'string' && key.startsWith('/ws/rest/v1/relationship'), undefined, { revalidate: true, }); showSnackbar({ kind: 'success', - title: t('endRlship', 'End relationship'), + title: t('endRelationship', 'End relationship'), subtitle: t('savedRlship', 'Relationship ended successfully'), timeoutInMs: 3000, isLowContrast: true, @@ -55,13 +52,11 @@ const EndRelationshipModal: React.FC = ({ closeModal, } catch (error) { showSnackbar({ kind: 'error', - title: t('RlshipError', 'Relationship Error'), + title: t('relationshipError', 'Relationship Error'), subtitle: t('RlshipErrorMessage', 'Request Failed'), timeoutInMs: 2500, isLowContrast: true, }); - } finally { - setIsSubmitting(false); } }; @@ -74,7 +69,27 @@ const EndRelationshipModal: React.FC = ({ closeModal,

{t('rlshipConfirmationText', 'This will end the relationship. Are you sure you want to proceed?')}

- + ( + field.onChange(e[0])} + className={styles.formDatePicker}> + + + )} + /> + {errors.endDate &&
{errors.endDate.message}
}
diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.scss b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.scss similarity index 100% rename from packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.scss rename to packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.scss diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx deleted file mode 100644 index 50af7dd4c..000000000 --- a/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { Controller, Control } from 'react-hook-form'; -import { DatePicker, DatePickerInput } from '@carbon/react'; -import styles from './end-date.scss'; - -interface EndDatePickerProps { - name: string; - control: Control; - label?: string; -} - -const EndDatePicker: React.FC = ({ name, control, label }) => { - return ( - ( - field.onChange(e[0])} className={styles.formDatePicker}> - - - )} - /> - ); -}; - -export default EndDatePicker; diff --git a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx index 83e634fa3..523d87ffd 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx @@ -47,7 +47,7 @@ const CaseManagementListActive: React.FC = ({ set const { user } = useSession(); const caseManagerPersonUuid = user?.person.uuid; - const { data: activeCasesData, error: activeCasesError, mutate: fetchCases } = useActivecases(caseManagerPersonUuid); + const { data: activeCasesData, error: activeCasesError } = useActivecases(caseManagerPersonUuid); const patientChartUrl = '${openmrsSpaBase}/patient/${patientUuid}/chart/case-management-encounters'; @@ -87,12 +87,12 @@ const CaseManagementListActive: React.FC = ({ set dateofend: caseData.endDate ? ( new Date(caseData.endDate).toLocaleDateString() ) : ( - + {t('enrolled', 'Enrolled')} ), actions: ( - + Date: Thu, 19 Dec 2024 12:44:53 +0300 Subject: [PATCH 05/17] (feat) updated translation --- packages/esm-patient-clinical-view-app/translations/en.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/esm-patient-clinical-view-app/translations/en.json b/packages/esm-patient-clinical-view-app/translations/en.json index 1ffe5294d..ac5cf2ac5 100644 --- a/packages/esm-patient-clinical-view-app/translations/en.json +++ b/packages/esm-patient-clinical-view-app/translations/en.json @@ -79,7 +79,6 @@ "encounterType": "Encounter Type", "endDate": "End Date", "endRelationship": "End Relationship", - "endRlship": "End relationship", "enterForm": "Enter form", "error": "Error", "errorFetchingbedInformation": "Error fetching bed information", @@ -160,11 +159,11 @@ "recordLabourDetails": "Record labour details", "referrals": "Referrals", "relation": "Relation", + "relationshipError": "Relationship Error", "releaseBody": "Release Body", "reportingMonth": "Month", "reportingYear": "Year", "rlshipConfirmationText": "This will end the relationship. Are you sure you want to proceed?", - "RlshipError": "Relationship Error", "RlshipErrorMessage": "Request Failed", "savedRlship": "Relationship ended successfully", "sex": "Sex", From b0fe70fb282216fd50f916713bed307ff6f23a04 Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Thu, 19 Dec 2024 18:28:56 +0300 Subject: [PATCH 06/17] (feat) added the unit test --- .../modal/case-management-modal.component.tsx | 1 - .../modal/case-management-modal.test.tsx | 43 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.test.tsx diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx index dca8de6b1..9d17b066e 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx @@ -89,7 +89,6 @@ const EndRelationshipModal: React.FC = ({ closeModal,
)} /> - {errors.endDate &&
{errors.endDate.message}
} diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.test.tsx b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.test.tsx new file mode 100644 index 000000000..8f9940372 --- /dev/null +++ b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.test.tsx @@ -0,0 +1,43 @@ +import React from 'react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; +import { updateRelationship } from '../../relationships/relationship.resources'; +import { showSnackbar } from '@openmrs/esm-framework'; +import EndRelationshipModal from './case-management-modal.component'; +import { SWRConfig } from 'swr'; + +jest.mock('../../relationships/relationship.resources', () => ({ + updateRelationship: jest.fn(), +})); + +jest.mock('@openmrs/esm-framework', () => ({ + showSnackbar: jest.fn(), +})); + +describe('EndRelationshipModal', () => { + const mockCloseModal = jest.fn(); + const mockRelationshipUuid = 'test-uuid'; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders the modal with the correct content', () => { + render(); + + expect(screen.getByText(/end relationship/i)).toBeInTheDocument(); + expect(screen.getByText(/this will end the relationship. are you sure you want to proceed\?/i)).toBeInTheDocument(); + expect(screen.getByLabelText(/end date/i)).toBeInTheDocument(); + }); + + it('closes the modal when the No button is clicked', () => { + render(); + + const noButton = screen.getByRole('button', { name: /no/i }); + fireEvent.click(noButton); + + expect(mockCloseModal).toHaveBeenCalledTimes(1); + }); +}); From 6af8746c2e360551b0fcb5ec6de785c3b67bca41 Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Fri, 10 Jan 2025 03:46:48 +0300 Subject: [PATCH 07/17] Revert commits 38ba77e and e926ff3: Undo changes from Dec 16 and Dec 17 --- packages/esm-morgue-app/src/config-schema.ts | 26 +++++----------- .../case-management-list-active-component.tsx | 31 ++++++++++++++----- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/packages/esm-morgue-app/src/config-schema.ts b/packages/esm-morgue-app/src/config-schema.ts index 1c8bf4a2e..ecceb105b 100644 --- a/packages/esm-morgue-app/src/config-schema.ts +++ b/packages/esm-morgue-app/src/config-schema.ts @@ -1,18 +1,6 @@ import { Type } from '@openmrs/esm-framework'; export const configSchema = { - autopsyEncounterUuid: { - _type: Type.String, - _description: 'Encounter UUID for autopsy', - _default: '', - }, - formsList: { - _type: Type.Object, - _description: 'List of form UUIDs', - _default: { - autopsyFormUuid: '', - }, - }, morgueVisitTypeUuid: { _type: Type.String, _description: ' UUID for morgue visit', @@ -21,7 +9,7 @@ export const configSchema = { morgueDepartmentServiceTypeUuid: { _type: Type.String, _description: ' UUID for morgue department service type', - _default: 'd7bd4cc0-90b1-4f22-90f2-ab7fde936727', + _default: '5b9e6cd1-f836-4144-91e4-401c58dd62af', }, insurancepaymentModeUuid: { _type: Type.String, @@ -36,7 +24,7 @@ export const configSchema = { tagNumberUuid: { _type: Type.String, _description: 'UUID for tag number concept', - _default: '13ba9c45-c540-4f10-b915-fa3d7baeb3d1', + _default: 'f2b35679-7ba9-4619-92cb-6872b0c6bf57', }, morgueAdmissionEncounterType: { _type: Type.String, @@ -56,22 +44,22 @@ export const configSchema = { obNumberUuid: { _type: Type.String, _description: 'UUID for ob number concept', - _default: 'c756d06a-22a5-4b66-933e-3d44667b72a0', + _default: '0dffecb3-2dc4-4d56-8cd4-56ba38579c69', }, policeNameUuid: { _type: Type.String, _description: 'UUID for police name concept', - _default: '6d58d9b5-6f84-4e77-941e-f5cc86d18a60', + _default: 'd889f05b-0d9b-462f-ae8e-2e9be79fd954', }, burialPermitNumberUuid: { _type: Type.String, _description: 'UUID for burial permit number concept', - _default: '29ef3df3-9845-49b0-96f2-5fb6d6240039', + _default: 'da524812-5600-4677-ba26-eb61eb925eef', }, policeIDNumber: { _type: Type.String, _description: 'UUID for police id number concept', - _default: '8d488d02-d1d8-41a5-8219-61f4fc5dbeb0', + _default: '163084AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', }, encounterProviderRoleUuid: { _type: Type.UUID, @@ -133,4 +121,4 @@ export type ConfigObject = { dischargeAreaUuid: string; morgueDischargeEncounterTypeUuid: string; adminUuid: string; -}; \ No newline at end of file +}; diff --git a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx index 523d87ffd..a47e61e1f 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx @@ -22,7 +22,6 @@ import { ConfigurableLink, isDesktop, launchWorkspace, - showModal, showSnackbar, useLayoutType, useSession, @@ -47,7 +46,7 @@ const CaseManagementListActive: React.FC = ({ set const { user } = useSession(); const caseManagerPersonUuid = user?.person.uuid; - const { data: activeCasesData, error: activeCasesError } = useActivecases(caseManagerPersonUuid); + const { data: activeCasesData, error: activeCasesError, mutate: fetchCases } = useActivecases(caseManagerPersonUuid); const patientChartUrl = '${openmrsSpaBase}/patient/${patientUuid}/chart/case-management-encounters'; @@ -65,10 +64,26 @@ const CaseManagementListActive: React.FC = ({ set caseData.personB.display.toLowerCase().includes(searchTerm.toLowerCase())), ); const handleDiscontinueACase = async (relationshipUuid: string) => { - const dispose = showModal('end-relationship-dialog', { - relationshipUuid, - closeModal: () => dispose(), - }); + try { + await updateRelationship(relationshipUuid, { endDate: new Date() }); + await fetchCases(); + + showSnackbar({ + kind: 'success', + title: t('endRlship', 'End relationship'), + subtitle: t('savedRlship', 'Relationship ended successfully'), + timeoutInMs: 3000, + isLowContrast: true, + }); + } catch (error) { + showSnackbar({ + kind: 'error', + title: t('RlshipError', 'Relationship Error'), + subtitle: t('RlshipError', 'Request Failed.......'), + timeoutInMs: 2500, + isLowContrast: true, + }); + } }; const tableRows = filteredCases @@ -87,12 +102,12 @@ const CaseManagementListActive: React.FC = ({ set dateofend: caseData.endDate ? ( new Date(caseData.endDate).toLocaleDateString() ) : ( - + {t('enrolled', 'Enrolled')} ), actions: ( - + Date: Wed, 11 Dec 2024 15:26:03 +0300 Subject: [PATCH 08/17] (refactor) updating the uuids --- packages/esm-morgue-app/src/config-schema.ts | 25 ++++++-------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/packages/esm-morgue-app/src/config-schema.ts b/packages/esm-morgue-app/src/config-schema.ts index a5b50b0b4..7494f2abe 100644 --- a/packages/esm-morgue-app/src/config-schema.ts +++ b/packages/esm-morgue-app/src/config-schema.ts @@ -1,27 +1,16 @@ import { Type } from '@openmrs/esm-framework'; export const configSchema = { - autopsyEncounterUuid: { - _type: Type.String, - _description: 'Encounter UUID for autopsy', - _default: '', - }, - formsList: { - _type: Type.Object, - _description: 'List of form UUIDs', - _default: { - autopsyFormUuid: '', - }, - }, morgueVisitTypeUuid: { _type: Type.String, _description: ' UUID for morgue visit', _default: '02b67c47-6071-4091-953d-ad21452e830c', + _default: '02b67c47-6071-4091-953d-ad21452e830c', }, morgueDepartmentServiceTypeUuid: { _type: Type.String, _description: ' UUID for morgue department service type', - _default: 'd7bd4cc0-90b1-4f22-90f2-ab7fde936727', + _default: '5b9e6cd1-f836-4144-91e4-401c58dd62af', }, insurancepaymentModeUuid: { _type: Type.String, @@ -36,7 +25,7 @@ export const configSchema = { tagNumberUuid: { _type: Type.String, _description: 'UUID for tag number concept', - _default: '13ba9c45-c540-4f10-b915-fa3d7baeb3d1', + _default: 'f2b35679-7ba9-4619-92cb-6872b0c6bf57', }, morgueAdmissionEncounterType: { _type: Type.String, @@ -56,22 +45,22 @@ export const configSchema = { obNumberUuid: { _type: Type.String, _description: 'UUID for ob number concept', - _default: 'c756d06a-22a5-4b66-933e-3d44667b72a0', + _default: '0dffecb3-2dc4-4d56-8cd4-56ba38579c69', }, policeNameUuid: { _type: Type.String, _description: 'UUID for police name concept', - _default: '6d58d9b5-6f84-4e77-941e-f5cc86d18a60', + _default: 'd889f05b-0d9b-462f-ae8e-2e9be79fd954', }, burialPermitNumberUuid: { _type: Type.String, _description: 'UUID for burial permit number concept', - _default: '29ef3df3-9845-49b0-96f2-5fb6d6240039', + _default: 'da524812-5600-4677-ba26-eb61eb925eef', }, policeIDNumber: { _type: Type.String, _description: 'UUID for police id number concept', - _default: '8d488d02-d1d8-41a5-8219-61f4fc5dbeb0', + _default: '163084AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', }, encounterProviderRoleUuid: { _type: Type.UUID, From 632b3f30a847df0c4790464455bb5b4c351b86a1 Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Tue, 17 Dec 2024 14:45:09 +0300 Subject: [PATCH 09/17] (feat) added end relationship functionality --- .../case-management-header.component.tsx | 16 +++-- .../case-management-list-active-component.tsx | 58 +++++++++++++++++-- ...ase-management-list-inactive-component.tsx | 36 +++++++----- .../tabs/case-management-tabs.component.tsx | 11 +++- .../workspace/case-management.scss | 4 +- .../workspace/case-management.workspace.tsx | 28 ++------- .../case-management/wrap/wrap.component.tsx | 8 ++- 7 files changed, 106 insertions(+), 55 deletions(-) diff --git a/packages/esm-patient-clinical-view-app/src/case-management/metrics/case-management-header.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/metrics/case-management-header.component.tsx index ab029abd7..075e5c9bc 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/metrics/case-management-header.component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/metrics/case-management-header.component.tsx @@ -1,11 +1,15 @@ -import React, { useState } from 'react'; +import React from 'react'; import { useTranslation } from 'react-i18next'; import { WatsonHealthStressBreathEditor } from '@carbon/react/icons'; import { Button } from '@carbon/react'; import styles from './case-management-header.scss'; -import { launchWorkspace, navigate, useSession } from '@openmrs/esm-framework'; +import { launchWorkspace, useSession } from '@openmrs/esm-framework'; -const MetricsHeader = () => { +interface MetricsHeaderProps { + activeTabIndex: number; +} + +const MetricsHeader: React.FC = ({ activeTabIndex }) => { const { t } = useTranslation(); const { user } = useSession(); const metricsTitle = t(' ', 'Case Manager'); @@ -14,6 +18,9 @@ const MetricsHeader = () => { workspaceTitle: 'Case Management Form', }); }; + + const isDiscontinuationTab = activeTabIndex === 1; + return (
@@ -21,7 +28,8 @@ const MetricsHeader = () => { kind="tertiary" renderIcon={(props) => } iconDescription={t('addCase', 'Add case')} - onClick={handleAddCase}> + onClick={handleAddCase} + disabled={isDiscontinuationTab}> {t('addCase', 'Add case')}
diff --git a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx index b959e9b54..a47e61e1f 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx @@ -14,18 +14,29 @@ import { Layer, Tile, OverflowMenu, + Tag, + OverflowMenuItem, } from '@carbon/react'; import { CardHeader, EmptyDataIllustration } from '@openmrs/esm-patient-common-lib'; -import { ConfigurableLink, isDesktop, useLayoutType, useSession } from '@openmrs/esm-framework'; +import { + ConfigurableLink, + isDesktop, + launchWorkspace, + showSnackbar, + useLayoutType, + useSession, +} from '@openmrs/esm-framework'; import styles from './case-management-list.scss'; import { useActivecases } from '../workspace/case-management.resource'; import { extractNameString, uppercaseText } from '../../utils/expression-helper'; +import { updateRelationship } from '../../relationships/relationship.resources'; interface CaseManagementListActiveProps { setActiveCasesCount: (count: number) => void; + activeTabIndex: number; } -const CaseManagementListActive: React.FC = ({ setActiveCasesCount }) => { +const CaseManagementListActive: React.FC = ({ setActiveCasesCount, activeTabIndex }) => { const { t } = useTranslation(); const layout = useLayoutType(); const [pageSize, setPageSize] = useState(10); @@ -35,7 +46,7 @@ const CaseManagementListActive: React.FC = ({ set const { user } = useSession(); const caseManagerPersonUuid = user?.person.uuid; - const { data: activeCasesData, error: activeCasesError } = useActivecases(caseManagerPersonUuid); + const { data: activeCasesData, error: activeCasesError, mutate: fetchCases } = useActivecases(caseManagerPersonUuid); const patientChartUrl = '${openmrsSpaBase}/patient/${patientUuid}/chart/case-management-encounters'; @@ -43,6 +54,7 @@ const CaseManagementListActive: React.FC = ({ set { key: 'names', header: t('names', 'Names') }, { key: 'dateofstart', header: t('dateofstart', 'Start Date') }, { key: 'dateofend', header: t('dateofend', 'End Date') }, + { key: 'actions', header: t('actions', 'Actions') }, ]; const filteredCases = activeCasesData?.data.results.filter( @@ -51,6 +63,28 @@ const CaseManagementListActive: React.FC = ({ set (extractNameString(caseData.personB.display).toLowerCase().includes(searchTerm.toLowerCase()) || caseData.personB.display.toLowerCase().includes(searchTerm.toLowerCase())), ); + const handleDiscontinueACase = async (relationshipUuid: string) => { + try { + await updateRelationship(relationshipUuid, { endDate: new Date() }); + await fetchCases(); + + showSnackbar({ + kind: 'success', + title: t('endRlship', 'End relationship'), + subtitle: t('savedRlship', 'Relationship ended successfully'), + timeoutInMs: 3000, + isLowContrast: true, + }); + } catch (error) { + showSnackbar({ + kind: 'error', + title: t('RlshipError', 'Relationship Error'), + subtitle: t('RlshipError', 'Request Failed.......'), + timeoutInMs: 2500, + isLowContrast: true, + }); + } + }; const tableRows = filteredCases ?.slice((currentPage - 1) * pageSize, currentPage * pageSize) @@ -65,7 +99,23 @@ const CaseManagementListActive: React.FC = ({ set ), dateofstart: new Date(caseData.startDate).toLocaleDateString(), - dateofend: caseData.endDate ? new Date(caseData.endDate).toLocaleDateString() : '-', + dateofend: caseData.endDate ? ( + new Date(caseData.endDate).toLocaleDateString() + ) : ( + + {t('enrolled', 'Enrolled')} + + ), + actions: ( + + handleDiscontinueACase(caseData.uuid)} + /> + + ), })); useEffect(() => { diff --git a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-inactive-component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-inactive-component.tsx index cd35822c8..d06245b33 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-inactive-component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-inactive-component.tsx @@ -13,7 +13,7 @@ import { Search, Layer, Tile, - OverflowMenu, + Tag, } from '@carbon/react'; import { CardHeader, EmptyDataIllustration } from '@openmrs/esm-patient-common-lib'; import { ConfigurableLink, isDesktop, useLayoutType, useSession } from '@openmrs/esm-framework'; @@ -43,6 +43,7 @@ const CaseManagementListInActive: React.FC = ({ { key: 'names', header: t('names', 'Names') }, { key: 'dateofstart', header: t('dateofstart', 'Start Date') }, { key: 'dateofend', header: t('dateofend', 'End Date') }, + { key: 'status', header: t('status', 'Status') }, ]; const filteredCases = inactiveCasesData?.data.results.filter( @@ -52,21 +53,24 @@ const CaseManagementListInActive: React.FC = ({ caseData.personB.display.toLowerCase().includes(searchTerm.toLowerCase())), ); - const tableRows = filteredCases - ?.slice((currentPage - 1) * pageSize, currentPage * pageSize) - .map((caseData, index) => ({ - id: caseData.uuid, - names: ( - - {uppercaseText(extractNameString(caseData.personB.display))} - - ), - dateofstart: new Date(caseData.startDate).toLocaleDateString(), - dateofend: new Date(caseData.endDate).toLocaleDateString(), - })); + const tableRows = filteredCases?.slice((currentPage - 1) * pageSize, currentPage * pageSize).map((caseData) => ({ + id: caseData.uuid, + names: ( + + {uppercaseText(extractNameString(caseData.personB.display))} + + ), + dateofstart: new Date(caseData.startDate).toLocaleDateString(), + dateofend: new Date(caseData.endDate).toLocaleDateString(), + status: caseData.endDate ? ( + + {t('discontinued', 'Discontinued')} + + ) : null, + })); useEffect(() => { const count = filteredCases?.length || 0; diff --git a/packages/esm-patient-clinical-view-app/src/case-management/tabs/case-management-tabs.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/tabs/case-management-tabs.component.tsx index e57c5d0d6..238c0dafd 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/tabs/case-management-tabs.component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/tabs/case-management-tabs.component.tsx @@ -5,13 +5,18 @@ import styles from './case-management-tabs.scss'; import CaseManagementListActive from '../table/case-management-list-active-component'; import CaseManagementListInActive from '../table/case-management-list-inactive-component'; -const CaseManagementTabs: React.FC = () => { +interface CaseManagementTabsProps { + setActiveTabIndex: (index: number) => void; +} + +const CaseManagementTabs: React.FC = ({ setActiveTabIndex }) => { const { t } = useTranslation(); - const [activeTabIndex, setActiveTabIndex] = useState(0); + const [activeTabIndex, setLocalActiveTabIndex] = useState(0); const [activeCasesCount, setActiveCasesCount] = useState(0); const [inactiveCasesCount, setInactiveCasesCount] = useState(0); const handleTabChange = ({ selectedIndex }: { selectedIndex: number }) => { + setLocalActiveTabIndex(selectedIndex); setActiveTabIndex(selectedIndex); }; @@ -30,7 +35,7 @@ const CaseManagementTabs: React.FC = () => {
- + diff --git a/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.scss b/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.scss index 2a6cd0378..fb2388311 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.scss +++ b/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.scss @@ -19,8 +19,8 @@ color: $ui-05; } } -.datePickerInput { - width: 23rem; +.formDatePicker input { + min-width: 24rem; } .form { display: flex; diff --git a/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.workspace.tsx b/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.workspace.tsx index c5c6dc123..beb89d557 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.workspace.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.workspace.tsx @@ -15,7 +15,6 @@ const schema = z.object({ caseManager: z.string().nonempty({ message: 'Case Manager is required' }), relationship: z.string().nonempty({ message: 'Relationship is required' }), startDate: z.date({ required_error: 'Start Date is required' }), - endDate: z.date().optional(), notes: z.string().optional(), }); @@ -65,7 +64,6 @@ const CaseManagementForm: React.FC = ({ closeWorkspace }) => relationshipType: data.relationship, personB: patientUuid, startDate: data.startDate.toISOString(), - endDate: data.endDate ? data.endDate.toISOString() : null, }; try { @@ -167,13 +165,16 @@ const CaseManagementForm: React.FC = ({ closeWorkspace }) => name="startDate" control={control} render={({ field, fieldState }) => ( - field.onChange(e[0])}> + field.onChange(e[0])} + className={styles.formDatePicker}> @@ -181,25 +182,6 @@ const CaseManagementForm: React.FC = ({ closeWorkspace }) => )} /> - - - ( - field.onChange(e[0])}> - - - )} - /> - - { + const [activeTabIndex, setActiveTabIndex] = useState(0); + return (
- - + +
); }; From 53a27f5133eb09b815357d9a06d17024f6425015 Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Tue, 17 Dec 2024 20:40:55 +0300 Subject: [PATCH 10/17] (feat) added a ability to end relationship on case management --- .../test-order/test-order-action.test.tsx | 117 ++++++------------ .../modal/case-management-modal.component.tsx | 92 ++++++++++++++ .../modal/end-date.component.tsx | 34 +++++ .../src/case-management/modal/end-date.scss | 20 +++ .../case-management-list-active-component.tsx | 25 +--- .../src/index.ts | 4 + .../src/routes.json | 4 + 7 files changed, 197 insertions(+), 99 deletions(-) create mode 100644 packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx create mode 100644 packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx create mode 100644 packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.scss diff --git a/packages/esm-billing-app/src/billable-services/billiable-item/test-order/test-order-action.test.tsx b/packages/esm-billing-app/src/billable-services/billiable-item/test-order/test-order-action.test.tsx index aebf42b93..4a4fa1c0c 100644 --- a/packages/esm-billing-app/src/billable-services/billiable-item/test-order/test-order-action.test.tsx +++ b/packages/esm-billing-app/src/billable-services/billiable-item/test-order/test-order-action.test.tsx @@ -8,116 +8,75 @@ import { launchWorkspace, showModal } from '@openmrs/esm-framework'; import { createMedicationDispenseProps } from './dispense.resource'; jest.mock('./test-order-action.resource'); - -const mockTestProps = { - order: { uuid: '123', patient: { uuid: '456' } } as Order, - patientUuid: 'patient-uuid-123', - encounterUuid: 'encounter-uuid-456', - medicationRequestBundle: { - request: { - id: 'med-request-789', - medicationReference: { reference: 'Medication/med-123' }, - medicationCodeableConcept: { coding: [{ code: 'med-code-123' }] }, - subject: { reference: 'Patient/patient-uuid-123' }, - dispenseRequest: { - quantity: { - value: 30, - code: 'TAB', - unit: 'tablets', - system: 'http://terminology.hl7.org/CodeSystem/v3-orderableDrugForm', +jest.mock('./dispense.resource', () => ({ + createMedicationDispenseProps: jest.fn(() => ({ + whenHandedOver: '2024-12-17T11:52:35+00:00', + medicationRequestBundle: { + request: { + dispenseRequest: { + quantity: { value: 30, code: 'TAB', unit: 'tablets' }, }, }, - dosageInstruction: [ - { - text: 'Take 1 tablet daily', - timing: { code: 'daily' }, - route: { coding: [{ code: 'PO' }] }, - doseAndRate: [ - { - doseQuantity: { - value: 1, - code: 'TAB', - unit: 'tablet', - }, - }, - ], - additionalInstruction: [{ text: 'with food' }], - }, - ], - }, - }, - quantityRemaining: 30, - session: { - currentProvider: { - uuid: 'provider-uuid-123', }, - sessionLocation: { - uuid: 'location-uuid-456', - }, - }, - providers: [ - { - uuid: 'provider-uuid-123', - display: 'Dr. Test Provider', - }, - ], - closeable: true, -} as Record; + otherProp: 'test-value', + })), +})); + +jest.mock('@openmrs/esm-framework', () => ({ + launchWorkspace: jest.fn(), + showModal: jest.fn(), +})); const testProps = { order: { uuid: '123', patient: { uuid: '456' } } as Order, + modalName: 'test-modal', + actionText: 'Test Action', }; describe('TestOrderAction', () => { beforeEach(() => { jest.resetAllMocks(); jest.clearAllMocks(); + jest.useFakeTimers().setSystemTime(new Date('2024-12-17T11:52:35Z')); }); - test('should render loading when isLoading is true', () => { + afterEach(() => { + jest.useRealTimers(); + }); + + test('should render loading state when isLoading is true', () => { jest.spyOn(resource, 'useTestOrderBillStatus').mockReturnValueOnce({ isLoading: true, hasPendingPayment: false }); render(); + expect(screen.getByText('Verifying bill status...')).toBeInTheDocument(); + expect(screen.getByRole('button')).toBeDisabled(); }); - test("should display `Unsettled bill for test` when there's a pending payment", () => { + test('should display "Unsettled bill" when hasPendingPayment is true', () => { jest.spyOn(resource, 'useTestOrderBillStatus').mockReturnValueOnce({ isLoading: false, hasPendingPayment: true }); render(); + expect(screen.getByText('Unsettled bill')).toBeInTheDocument(); + expect(screen.getByRole('button')).toBeDisabled(); }); - test("should display `Pick Lab Request` when there's no pending payment", async () => { - const user = userEvent.setup(); + test('should render the button with correct action text', () => { jest.spyOn(resource, 'useTestOrderBillStatus').mockReturnValueOnce({ isLoading: false, hasPendingPayment: false }); render(); - const pickLabRequestMenuItem = screen.getByText('Pick Lab Request'); - await user.click(pickLabRequestMenuItem); - expect(screen.queryByText('Unsettled bill.')).not.toBeInTheDocument(); - expect(showModal).toBeCalledWith('pickup-lab-request-modal', { - closeModal: expect.any(Function), - order: { patient: { uuid: '456' }, uuid: '123' }, - }); + expect(screen.getByText('Test Action')).toBeInTheDocument(); + expect(screen.getByRole('button')).toBeEnabled(); }); - test('should not render the dispense form if closeable is false', () => { - jest.spyOn(resource, 'useTestOrderBillStatus').mockReturnValueOnce({ isLoading: false, hasPendingPayment: false }); - render(); - expect(screen.queryByText('Dispense')).not.toBeInTheDocument(); - }); + test('should not render button if order is in progress', () => { + const inProgressProps = { + ...testProps, + order: { ...testProps.order, fulfillerStatus: 'IN_PROGRESS' } as Order, + }; - test('should launch the dispense form when dispense order is part of props', async () => { - const user = userEvent.setup(); jest.spyOn(resource, 'useTestOrderBillStatus').mockReturnValueOnce({ isLoading: false, hasPendingPayment: false }); - render(); - const dispenseButton = screen.getByRole('button', { name: 'Dispense' }); - expect(dispenseButton).toBeInTheDocument(); - - await user.click(dispenseButton); - const dispenseFormProps = createMedicationDispenseProps(mockTestProps); + render(); - expect(launchWorkspace).toHaveBeenCalledWith('dispense-workspace', { - ...dispenseFormProps, - }); + expect(screen.queryByRole('button')).not.toBeInTheDocument(); }); }); diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx new file mode 100644 index 000000000..5c0d0944d --- /dev/null +++ b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx @@ -0,0 +1,92 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, ModalBody, ModalFooter, ModalHeader, Column } from '@carbon/react'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { mutate } from 'swr'; +import { updateRelationship } from '../../relationships/relationship.resources'; +import { showSnackbar } from '@openmrs/esm-framework'; +import EndDatePicker from './end-date.component'; +import styles from './end-date.scss'; + +const EndRelationshipSchema = z.object({ + endDate: z.date({ + required_error: 'End date is required', + invalid_type_error: 'Please select a valid date', + }), +}); + +type FormData = z.infer; + +interface EndRelationshipModalProps { + closeModal: () => void; + relationshipUuid: string; +} + +const EndRelationshipModal: React.FC = ({ closeModal, relationshipUuid }) => { + const { t } = useTranslation(); + const [isSubmitting, setIsSubmitting] = useState(false); + + const { + handleSubmit, + control, + formState: { errors }, + } = useForm({ + resolver: zodResolver(EndRelationshipSchema), + defaultValues: { endDate: null }, + }); + + const handleEndRelationship = async (data: FormData) => { + try { + setIsSubmitting(true); + await updateRelationship(relationshipUuid, { endDate: data.endDate }); + mutate((key) => typeof key === 'string' && key.startsWith('/ws/rest/v1/relationship'), undefined, { + revalidate: true, + }); + showSnackbar({ + kind: 'success', + title: t('endRlship', 'End relationship'), + subtitle: t('savedRlship', 'Relationship ended successfully'), + timeoutInMs: 3000, + isLowContrast: true, + }); + closeModal(); + } catch (error) { + showSnackbar({ + kind: 'error', + title: t('RlshipError', 'Relationship Error'), + subtitle: t('RlshipErrorMessage', 'Request Failed'), + timeoutInMs: 2500, + isLowContrast: true, + }); + } finally { + setIsSubmitting(false); + } + }; + + return ( +
+
+

{t('endRelationship', 'End Relationship')}

+
+
+

{t('rlshipConfirmationText', 'This will end the relationship. Are you sure you want to proceed?')}

+ +
+ +
+
+ + + + +
+ ); +}; + +export default EndRelationshipModal; diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx new file mode 100644 index 000000000..50af7dd4c --- /dev/null +++ b/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { Controller, Control } from 'react-hook-form'; +import { DatePicker, DatePickerInput } from '@carbon/react'; +import styles from './end-date.scss'; + +interface EndDatePickerProps { + name: string; + control: Control; + label?: string; +} + +const EndDatePicker: React.FC = ({ name, control, label }) => { + return ( + ( + field.onChange(e[0])} className={styles.formDatePicker}> + + + )} + /> + ); +}; + +export default EndDatePicker; diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.scss b/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.scss new file mode 100644 index 000000000..be9cccded --- /dev/null +++ b/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.scss @@ -0,0 +1,20 @@ +@use '@carbon/colors'; +@use '@carbon/layout'; +@use '@carbon/type'; + +.formDatePicker input { + min-width: 50rem; + display: flex; + align-items: center; + justify-content: space-between; + border: 1px solid colors.$gray-50; + padding: layout.$spacing-04 layout.$spacing-05; + background-color: colors.$white; +} + +.centeredContainer { + display: flex; + justify-content: center; + align-items: center; + margin: layout.$spacing-06 layout.$spacing-07; +} diff --git a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx index a47e61e1f..83e634fa3 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx @@ -22,6 +22,7 @@ import { ConfigurableLink, isDesktop, launchWorkspace, + showModal, showSnackbar, useLayoutType, useSession, @@ -64,26 +65,10 @@ const CaseManagementListActive: React.FC = ({ set caseData.personB.display.toLowerCase().includes(searchTerm.toLowerCase())), ); const handleDiscontinueACase = async (relationshipUuid: string) => { - try { - await updateRelationship(relationshipUuid, { endDate: new Date() }); - await fetchCases(); - - showSnackbar({ - kind: 'success', - title: t('endRlship', 'End relationship'), - subtitle: t('savedRlship', 'Relationship ended successfully'), - timeoutInMs: 3000, - isLowContrast: true, - }); - } catch (error) { - showSnackbar({ - kind: 'error', - title: t('RlshipError', 'Relationship Error'), - subtitle: t('RlshipError', 'Request Failed.......'), - timeoutInMs: 2500, - isLowContrast: true, - }); - } + const dispose = showModal('end-relationship-dialog', { + relationshipUuid, + closeModal: () => dispose(), + }); }; const tableRows = filteredCases diff --git a/packages/esm-patient-clinical-view-app/src/index.ts b/packages/esm-patient-clinical-view-app/src/index.ts index 4e7a6b350..ee202cf30 100644 --- a/packages/esm-patient-clinical-view-app/src/index.ts +++ b/packages/esm-patient-clinical-view-app/src/index.ts @@ -55,6 +55,7 @@ import RelationshipUpdateForm from './relationships/forms/relationships-update-f import DeleteRelationshipConfirmDialog from './relationships/modals/delete-relationship-dialog.modal'; import DeceasedDetailsView from './deceased-panel/tabs/tabs.component'; import DeceasedPanelDashboardLink from './deceased-panel/dashboard-link/dashboard-link.component'; +import EndRelationshipModal from './case-management/modal/case-management-modal.component'; const moduleName = '@kenyaemr/esm-patient-clinical-view-app'; @@ -154,6 +155,9 @@ export const inPatientChartDashboard = getSyncLifecycle(InPatient, options); export const peerCalendarFormEntry = getSyncLifecycle(FormEntryWorkspace, options); +// Case management modal +export const endRelationshipModal = getSyncLifecycle(EndRelationshipModal, options); + export function startupApp() { defineConfigSchema(moduleName, configSchema); } diff --git a/packages/esm-patient-clinical-view-app/src/routes.json b/packages/esm-patient-clinical-view-app/src/routes.json index 6a20a39dc..d529f1bae 100644 --- a/packages/esm-patient-clinical-view-app/src/routes.json +++ b/packages/esm-patient-clinical-view-app/src/routes.json @@ -305,6 +305,10 @@ { "name": "relationship-delete-confirm-dialog", "component": "relationshipDeleteConfirmialog" + }, + { + "name": "end-relationship-dialog", + "component": "endRelationshipModal" } ], "workspaces": [ From 29e5d488bebe824f4aa8882a865449f1b7011bf9 Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Thu, 19 Dec 2024 12:43:58 +0300 Subject: [PATCH 11/17] (refactor) updated PR per suggestion --- .../modal/case-management-modal.component.tsx | 41 +++++++++++++------ ...d-date.scss => case-management-modal.scss} | 0 .../modal/end-date.component.tsx | 34 --------------- .../case-management-list-active-component.tsx | 6 +-- .../translations/en.json | 11 ++++- 5 files changed, 41 insertions(+), 51 deletions(-) rename packages/esm-patient-clinical-view-app/src/case-management/modal/{end-date.scss => case-management-modal.scss} (100%) delete mode 100644 packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx index 5c0d0944d..dca8de6b1 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx @@ -1,14 +1,13 @@ -import React, { useState } from 'react'; +import React from 'react'; import { useTranslation } from 'react-i18next'; -import { Button, ModalBody, ModalFooter, ModalHeader, Column } from '@carbon/react'; -import { useForm } from 'react-hook-form'; +import { Button, DatePicker, DatePickerInput, ModalFooter } from '@carbon/react'; +import { useForm, Controller } from 'react-hook-form'; import { z } from 'zod'; import { zodResolver } from '@hookform/resolvers/zod'; import { mutate } from 'swr'; import { updateRelationship } from '../../relationships/relationship.resources'; import { showSnackbar } from '@openmrs/esm-framework'; -import EndDatePicker from './end-date.component'; -import styles from './end-date.scss'; +import styles from './case-management-modal.scss'; const EndRelationshipSchema = z.object({ endDate: z.date({ @@ -26,12 +25,11 @@ interface EndRelationshipModalProps { const EndRelationshipModal: React.FC = ({ closeModal, relationshipUuid }) => { const { t } = useTranslation(); - const [isSubmitting, setIsSubmitting] = useState(false); const { handleSubmit, control, - formState: { errors }, + formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(EndRelationshipSchema), defaultValues: { endDate: null }, @@ -39,14 +37,13 @@ const EndRelationshipModal: React.FC = ({ closeModal, const handleEndRelationship = async (data: FormData) => { try { - setIsSubmitting(true); await updateRelationship(relationshipUuid, { endDate: data.endDate }); mutate((key) => typeof key === 'string' && key.startsWith('/ws/rest/v1/relationship'), undefined, { revalidate: true, }); showSnackbar({ kind: 'success', - title: t('endRlship', 'End relationship'), + title: t('endRelationship', 'End relationship'), subtitle: t('savedRlship', 'Relationship ended successfully'), timeoutInMs: 3000, isLowContrast: true, @@ -55,13 +52,11 @@ const EndRelationshipModal: React.FC = ({ closeModal, } catch (error) { showSnackbar({ kind: 'error', - title: t('RlshipError', 'Relationship Error'), + title: t('relationshipError', 'Relationship Error'), subtitle: t('RlshipErrorMessage', 'Request Failed'), timeoutInMs: 2500, isLowContrast: true, }); - } finally { - setIsSubmitting(false); } }; @@ -74,7 +69,27 @@ const EndRelationshipModal: React.FC = ({ closeModal,

{t('rlshipConfirmationText', 'This will end the relationship. Are you sure you want to proceed?')}

- + ( + field.onChange(e[0])} + className={styles.formDatePicker}> + + + )} + /> + {errors.endDate &&
{errors.endDate.message}
}
diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.scss b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.scss similarity index 100% rename from packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.scss rename to packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.scss diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx deleted file mode 100644 index 50af7dd4c..000000000 --- a/packages/esm-patient-clinical-view-app/src/case-management/modal/end-date.component.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { Controller, Control } from 'react-hook-form'; -import { DatePicker, DatePickerInput } from '@carbon/react'; -import styles from './end-date.scss'; - -interface EndDatePickerProps { - name: string; - control: Control; - label?: string; -} - -const EndDatePicker: React.FC = ({ name, control, label }) => { - return ( - ( - field.onChange(e[0])} className={styles.formDatePicker}> - - - )} - /> - ); -}; - -export default EndDatePicker; diff --git a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx index 83e634fa3..523d87ffd 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx @@ -47,7 +47,7 @@ const CaseManagementListActive: React.FC = ({ set const { user } = useSession(); const caseManagerPersonUuid = user?.person.uuid; - const { data: activeCasesData, error: activeCasesError, mutate: fetchCases } = useActivecases(caseManagerPersonUuid); + const { data: activeCasesData, error: activeCasesError } = useActivecases(caseManagerPersonUuid); const patientChartUrl = '${openmrsSpaBase}/patient/${patientUuid}/chart/case-management-encounters'; @@ -87,12 +87,12 @@ const CaseManagementListActive: React.FC = ({ set dateofend: caseData.endDate ? ( new Date(caseData.endDate).toLocaleDateString() ) : ( - + {t('enrolled', 'Enrolled')} ), actions: ( - + Date: Thu, 19 Dec 2024 12:44:53 +0300 Subject: [PATCH 12/17] (feat) updated translation --- packages/esm-patient-clinical-view-app/translations/en.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/esm-patient-clinical-view-app/translations/en.json b/packages/esm-patient-clinical-view-app/translations/en.json index 1ffe5294d..ac5cf2ac5 100644 --- a/packages/esm-patient-clinical-view-app/translations/en.json +++ b/packages/esm-patient-clinical-view-app/translations/en.json @@ -79,7 +79,6 @@ "encounterType": "Encounter Type", "endDate": "End Date", "endRelationship": "End Relationship", - "endRlship": "End relationship", "enterForm": "Enter form", "error": "Error", "errorFetchingbedInformation": "Error fetching bed information", @@ -160,11 +159,11 @@ "recordLabourDetails": "Record labour details", "referrals": "Referrals", "relation": "Relation", + "relationshipError": "Relationship Error", "releaseBody": "Release Body", "reportingMonth": "Month", "reportingYear": "Year", "rlshipConfirmationText": "This will end the relationship. Are you sure you want to proceed?", - "RlshipError": "Relationship Error", "RlshipErrorMessage": "Request Failed", "savedRlship": "Relationship ended successfully", "sex": "Sex", From eb37f0a9480b6f76394b3ae66db1e75d5f2b84a5 Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Thu, 19 Dec 2024 18:28:56 +0300 Subject: [PATCH 13/17] (feat) added the unit test --- .../modal/case-management-modal.component.tsx | 1 - .../modal/case-management-modal.test.tsx | 43 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.test.tsx diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx index dca8de6b1..9d17b066e 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.component.tsx @@ -89,7 +89,6 @@ const EndRelationshipModal: React.FC = ({ closeModal,
)} /> - {errors.endDate &&
{errors.endDate.message}
} diff --git a/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.test.tsx b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.test.tsx new file mode 100644 index 000000000..8f9940372 --- /dev/null +++ b/packages/esm-patient-clinical-view-app/src/case-management/modal/case-management-modal.test.tsx @@ -0,0 +1,43 @@ +import React from 'react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; +import { updateRelationship } from '../../relationships/relationship.resources'; +import { showSnackbar } from '@openmrs/esm-framework'; +import EndRelationshipModal from './case-management-modal.component'; +import { SWRConfig } from 'swr'; + +jest.mock('../../relationships/relationship.resources', () => ({ + updateRelationship: jest.fn(), +})); + +jest.mock('@openmrs/esm-framework', () => ({ + showSnackbar: jest.fn(), +})); + +describe('EndRelationshipModal', () => { + const mockCloseModal = jest.fn(); + const mockRelationshipUuid = 'test-uuid'; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders the modal with the correct content', () => { + render(); + + expect(screen.getByText(/end relationship/i)).toBeInTheDocument(); + expect(screen.getByText(/this will end the relationship. are you sure you want to proceed\?/i)).toBeInTheDocument(); + expect(screen.getByLabelText(/end date/i)).toBeInTheDocument(); + }); + + it('closes the modal when the No button is clicked', () => { + render(); + + const noButton = screen.getByRole('button', { name: /no/i }); + fireEvent.click(noButton); + + expect(mockCloseModal).toHaveBeenCalledTimes(1); + }); +}); From c5e2a06f9a5da7f7b340c07cfef055e43ed52fc5 Mon Sep 17 00:00:00 2001 From: Fredrick Kioko <67967749+its-kios09@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:12:08 +0300 Subject: [PATCH 14/17] (refactor) updated the config schema uuids (#535) --- packages/esm-morgue-app/src/config-schema.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/esm-morgue-app/src/config-schema.ts b/packages/esm-morgue-app/src/config-schema.ts index 7494f2abe..1f12ff971 100644 --- a/packages/esm-morgue-app/src/config-schema.ts +++ b/packages/esm-morgue-app/src/config-schema.ts @@ -10,7 +10,7 @@ export const configSchema = { morgueDepartmentServiceTypeUuid: { _type: Type.String, _description: ' UUID for morgue department service type', - _default: '5b9e6cd1-f836-4144-91e4-401c58dd62af', + _default: 'd7bd4cc0-90b1-4f22-90f2-ab7fde936727', }, insurancepaymentModeUuid: { _type: Type.String, @@ -25,7 +25,7 @@ export const configSchema = { tagNumberUuid: { _type: Type.String, _description: 'UUID for tag number concept', - _default: 'f2b35679-7ba9-4619-92cb-6872b0c6bf57', + _default: '13ba9c45-c540-4f10-b915-fa3d7baeb3d1', }, morgueAdmissionEncounterType: { _type: Type.String, @@ -45,22 +45,22 @@ export const configSchema = { obNumberUuid: { _type: Type.String, _description: 'UUID for ob number concept', - _default: '0dffecb3-2dc4-4d56-8cd4-56ba38579c69', + _default: 'c756d06a-22a5-4b66-933e-3d44667b72a0', }, policeNameUuid: { _type: Type.String, _description: 'UUID for police name concept', - _default: 'd889f05b-0d9b-462f-ae8e-2e9be79fd954', + _default: '6d58d9b5-6f84-4e77-941e-f5cc86d18a60', }, burialPermitNumberUuid: { _type: Type.String, _description: 'UUID for burial permit number concept', - _default: 'da524812-5600-4677-ba26-eb61eb925eef', + _default: '29ef3df3-9845-49b0-96f2-5fb6d6240039', }, policeIDNumber: { _type: Type.String, _description: 'UUID for police id number concept', - _default: '163084AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + _default: '8d488d02-d1d8-41a5-8219-61f4fc5dbeb0', }, encounterProviderRoleUuid: { _type: Type.UUID, @@ -71,6 +71,7 @@ export const configSchema = { _type: Type.String, _description: 'UUID for discharge area concept', _default: '89ebccf1-4cca-4195-aeff-3e75fdf976b4', + _default: '89ebccf1-4cca-4195-aeff-3e75fdf976b4', }, adminUuid: { _type: Type.String, From 86c22cafe9177ab7abca22957f7d80f48a9984a9 Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Fri, 10 Jan 2025 03:46:48 +0300 Subject: [PATCH 15/17] Revert commits 38ba77e and e926ff3: Undo changes from Dec 16 and Dec 17 --- packages/esm-morgue-app/src/config-schema.ts | 12 +++---- .../case-management-list-active-component.tsx | 31 ++++++++++++++----- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/packages/esm-morgue-app/src/config-schema.ts b/packages/esm-morgue-app/src/config-schema.ts index 1f12ff971..c7262ff44 100644 --- a/packages/esm-morgue-app/src/config-schema.ts +++ b/packages/esm-morgue-app/src/config-schema.ts @@ -10,7 +10,7 @@ export const configSchema = { morgueDepartmentServiceTypeUuid: { _type: Type.String, _description: ' UUID for morgue department service type', - _default: 'd7bd4cc0-90b1-4f22-90f2-ab7fde936727', + _default: '5b9e6cd1-f836-4144-91e4-401c58dd62af', }, insurancepaymentModeUuid: { _type: Type.String, @@ -25,7 +25,7 @@ export const configSchema = { tagNumberUuid: { _type: Type.String, _description: 'UUID for tag number concept', - _default: '13ba9c45-c540-4f10-b915-fa3d7baeb3d1', + _default: 'f2b35679-7ba9-4619-92cb-6872b0c6bf57', }, morgueAdmissionEncounterType: { _type: Type.String, @@ -45,22 +45,22 @@ export const configSchema = { obNumberUuid: { _type: Type.String, _description: 'UUID for ob number concept', - _default: 'c756d06a-22a5-4b66-933e-3d44667b72a0', + _default: '0dffecb3-2dc4-4d56-8cd4-56ba38579c69', }, policeNameUuid: { _type: Type.String, _description: 'UUID for police name concept', - _default: '6d58d9b5-6f84-4e77-941e-f5cc86d18a60', + _default: 'd889f05b-0d9b-462f-ae8e-2e9be79fd954', }, burialPermitNumberUuid: { _type: Type.String, _description: 'UUID for burial permit number concept', - _default: '29ef3df3-9845-49b0-96f2-5fb6d6240039', + _default: 'da524812-5600-4677-ba26-eb61eb925eef', }, policeIDNumber: { _type: Type.String, _description: 'UUID for police id number concept', - _default: '8d488d02-d1d8-41a5-8219-61f4fc5dbeb0', + _default: '163084AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', }, encounterProviderRoleUuid: { _type: Type.UUID, diff --git a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx index 523d87ffd..a47e61e1f 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx @@ -22,7 +22,6 @@ import { ConfigurableLink, isDesktop, launchWorkspace, - showModal, showSnackbar, useLayoutType, useSession, @@ -47,7 +46,7 @@ const CaseManagementListActive: React.FC = ({ set const { user } = useSession(); const caseManagerPersonUuid = user?.person.uuid; - const { data: activeCasesData, error: activeCasesError } = useActivecases(caseManagerPersonUuid); + const { data: activeCasesData, error: activeCasesError, mutate: fetchCases } = useActivecases(caseManagerPersonUuid); const patientChartUrl = '${openmrsSpaBase}/patient/${patientUuid}/chart/case-management-encounters'; @@ -65,10 +64,26 @@ const CaseManagementListActive: React.FC = ({ set caseData.personB.display.toLowerCase().includes(searchTerm.toLowerCase())), ); const handleDiscontinueACase = async (relationshipUuid: string) => { - const dispose = showModal('end-relationship-dialog', { - relationshipUuid, - closeModal: () => dispose(), - }); + try { + await updateRelationship(relationshipUuid, { endDate: new Date() }); + await fetchCases(); + + showSnackbar({ + kind: 'success', + title: t('endRlship', 'End relationship'), + subtitle: t('savedRlship', 'Relationship ended successfully'), + timeoutInMs: 3000, + isLowContrast: true, + }); + } catch (error) { + showSnackbar({ + kind: 'error', + title: t('RlshipError', 'Relationship Error'), + subtitle: t('RlshipError', 'Request Failed.......'), + timeoutInMs: 2500, + isLowContrast: true, + }); + } }; const tableRows = filteredCases @@ -87,12 +102,12 @@ const CaseManagementListActive: React.FC = ({ set dateofend: caseData.endDate ? ( new Date(caseData.endDate).toLocaleDateString() ) : ( - + {t('enrolled', 'Enrolled')} ), actions: ( - + Date: Fri, 10 Jan 2025 03:49:39 +0300 Subject: [PATCH 16/17] Revert "(feat) added end relationship functionality" This reverts commit e926ff3f538e385c4e0a2657e225a939f07a8c01. --- .../case-management-header.component.tsx | 16 ++--- .../case-management-list-active-component.tsx | 58 ++----------------- ...ase-management-list-inactive-component.tsx | 36 +++++------- .../tabs/case-management-tabs.component.tsx | 11 +--- .../workspace/case-management.scss | 4 +- .../workspace/case-management.workspace.tsx | 28 +++++++-- .../case-management/wrap/wrap.component.tsx | 8 +-- 7 files changed, 55 insertions(+), 106 deletions(-) diff --git a/packages/esm-patient-clinical-view-app/src/case-management/metrics/case-management-header.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/metrics/case-management-header.component.tsx index 075e5c9bc..ab029abd7 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/metrics/case-management-header.component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/metrics/case-management-header.component.tsx @@ -1,15 +1,11 @@ -import React from 'react'; +import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { WatsonHealthStressBreathEditor } from '@carbon/react/icons'; import { Button } from '@carbon/react'; import styles from './case-management-header.scss'; -import { launchWorkspace, useSession } from '@openmrs/esm-framework'; +import { launchWorkspace, navigate, useSession } from '@openmrs/esm-framework'; -interface MetricsHeaderProps { - activeTabIndex: number; -} - -const MetricsHeader: React.FC = ({ activeTabIndex }) => { +const MetricsHeader = () => { const { t } = useTranslation(); const { user } = useSession(); const metricsTitle = t(' ', 'Case Manager'); @@ -18,9 +14,6 @@ const MetricsHeader: React.FC = ({ activeTabIndex }) => { workspaceTitle: 'Case Management Form', }); }; - - const isDiscontinuationTab = activeTabIndex === 1; - return (
@@ -28,8 +21,7 @@ const MetricsHeader: React.FC = ({ activeTabIndex }) => { kind="tertiary" renderIcon={(props) => } iconDescription={t('addCase', 'Add case')} - onClick={handleAddCase} - disabled={isDiscontinuationTab}> + onClick={handleAddCase}> {t('addCase', 'Add case')}
diff --git a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx index a47e61e1f..b959e9b54 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-active-component.tsx @@ -14,29 +14,18 @@ import { Layer, Tile, OverflowMenu, - Tag, - OverflowMenuItem, } from '@carbon/react'; import { CardHeader, EmptyDataIllustration } from '@openmrs/esm-patient-common-lib'; -import { - ConfigurableLink, - isDesktop, - launchWorkspace, - showSnackbar, - useLayoutType, - useSession, -} from '@openmrs/esm-framework'; +import { ConfigurableLink, isDesktop, useLayoutType, useSession } from '@openmrs/esm-framework'; import styles from './case-management-list.scss'; import { useActivecases } from '../workspace/case-management.resource'; import { extractNameString, uppercaseText } from '../../utils/expression-helper'; -import { updateRelationship } from '../../relationships/relationship.resources'; interface CaseManagementListActiveProps { setActiveCasesCount: (count: number) => void; - activeTabIndex: number; } -const CaseManagementListActive: React.FC = ({ setActiveCasesCount, activeTabIndex }) => { +const CaseManagementListActive: React.FC = ({ setActiveCasesCount }) => { const { t } = useTranslation(); const layout = useLayoutType(); const [pageSize, setPageSize] = useState(10); @@ -46,7 +35,7 @@ const CaseManagementListActive: React.FC = ({ set const { user } = useSession(); const caseManagerPersonUuid = user?.person.uuid; - const { data: activeCasesData, error: activeCasesError, mutate: fetchCases } = useActivecases(caseManagerPersonUuid); + const { data: activeCasesData, error: activeCasesError } = useActivecases(caseManagerPersonUuid); const patientChartUrl = '${openmrsSpaBase}/patient/${patientUuid}/chart/case-management-encounters'; @@ -54,7 +43,6 @@ const CaseManagementListActive: React.FC = ({ set { key: 'names', header: t('names', 'Names') }, { key: 'dateofstart', header: t('dateofstart', 'Start Date') }, { key: 'dateofend', header: t('dateofend', 'End Date') }, - { key: 'actions', header: t('actions', 'Actions') }, ]; const filteredCases = activeCasesData?.data.results.filter( @@ -63,28 +51,6 @@ const CaseManagementListActive: React.FC = ({ set (extractNameString(caseData.personB.display).toLowerCase().includes(searchTerm.toLowerCase()) || caseData.personB.display.toLowerCase().includes(searchTerm.toLowerCase())), ); - const handleDiscontinueACase = async (relationshipUuid: string) => { - try { - await updateRelationship(relationshipUuid, { endDate: new Date() }); - await fetchCases(); - - showSnackbar({ - kind: 'success', - title: t('endRlship', 'End relationship'), - subtitle: t('savedRlship', 'Relationship ended successfully'), - timeoutInMs: 3000, - isLowContrast: true, - }); - } catch (error) { - showSnackbar({ - kind: 'error', - title: t('RlshipError', 'Relationship Error'), - subtitle: t('RlshipError', 'Request Failed.......'), - timeoutInMs: 2500, - isLowContrast: true, - }); - } - }; const tableRows = filteredCases ?.slice((currentPage - 1) * pageSize, currentPage * pageSize) @@ -99,23 +65,7 @@ const CaseManagementListActive: React.FC = ({ set ), dateofstart: new Date(caseData.startDate).toLocaleDateString(), - dateofend: caseData.endDate ? ( - new Date(caseData.endDate).toLocaleDateString() - ) : ( - - {t('enrolled', 'Enrolled')} - - ), - actions: ( - - handleDiscontinueACase(caseData.uuid)} - /> - - ), + dateofend: caseData.endDate ? new Date(caseData.endDate).toLocaleDateString() : '-', })); useEffect(() => { diff --git a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-inactive-component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-inactive-component.tsx index d06245b33..cd35822c8 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-inactive-component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/table/case-management-list-inactive-component.tsx @@ -13,7 +13,7 @@ import { Search, Layer, Tile, - Tag, + OverflowMenu, } from '@carbon/react'; import { CardHeader, EmptyDataIllustration } from '@openmrs/esm-patient-common-lib'; import { ConfigurableLink, isDesktop, useLayoutType, useSession } from '@openmrs/esm-framework'; @@ -43,7 +43,6 @@ const CaseManagementListInActive: React.FC = ({ { key: 'names', header: t('names', 'Names') }, { key: 'dateofstart', header: t('dateofstart', 'Start Date') }, { key: 'dateofend', header: t('dateofend', 'End Date') }, - { key: 'status', header: t('status', 'Status') }, ]; const filteredCases = inactiveCasesData?.data.results.filter( @@ -53,24 +52,21 @@ const CaseManagementListInActive: React.FC = ({ caseData.personB.display.toLowerCase().includes(searchTerm.toLowerCase())), ); - const tableRows = filteredCases?.slice((currentPage - 1) * pageSize, currentPage * pageSize).map((caseData) => ({ - id: caseData.uuid, - names: ( - - {uppercaseText(extractNameString(caseData.personB.display))} - - ), - dateofstart: new Date(caseData.startDate).toLocaleDateString(), - dateofend: new Date(caseData.endDate).toLocaleDateString(), - status: caseData.endDate ? ( - - {t('discontinued', 'Discontinued')} - - ) : null, - })); + const tableRows = filteredCases + ?.slice((currentPage - 1) * pageSize, currentPage * pageSize) + .map((caseData, index) => ({ + id: caseData.uuid, + names: ( + + {uppercaseText(extractNameString(caseData.personB.display))} + + ), + dateofstart: new Date(caseData.startDate).toLocaleDateString(), + dateofend: new Date(caseData.endDate).toLocaleDateString(), + })); useEffect(() => { const count = filteredCases?.length || 0; diff --git a/packages/esm-patient-clinical-view-app/src/case-management/tabs/case-management-tabs.component.tsx b/packages/esm-patient-clinical-view-app/src/case-management/tabs/case-management-tabs.component.tsx index 238c0dafd..e57c5d0d6 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/tabs/case-management-tabs.component.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/tabs/case-management-tabs.component.tsx @@ -5,18 +5,13 @@ import styles from './case-management-tabs.scss'; import CaseManagementListActive from '../table/case-management-list-active-component'; import CaseManagementListInActive from '../table/case-management-list-inactive-component'; -interface CaseManagementTabsProps { - setActiveTabIndex: (index: number) => void; -} - -const CaseManagementTabs: React.FC = ({ setActiveTabIndex }) => { +const CaseManagementTabs: React.FC = () => { const { t } = useTranslation(); - const [activeTabIndex, setLocalActiveTabIndex] = useState(0); + const [activeTabIndex, setActiveTabIndex] = useState(0); const [activeCasesCount, setActiveCasesCount] = useState(0); const [inactiveCasesCount, setInactiveCasesCount] = useState(0); const handleTabChange = ({ selectedIndex }: { selectedIndex: number }) => { - setLocalActiveTabIndex(selectedIndex); setActiveTabIndex(selectedIndex); }; @@ -35,7 +30,7 @@ const CaseManagementTabs: React.FC = ({ setActiveTabInd
- + diff --git a/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.scss b/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.scss index fb2388311..2a6cd0378 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.scss +++ b/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.scss @@ -19,8 +19,8 @@ color: $ui-05; } } -.formDatePicker input { - min-width: 24rem; +.datePickerInput { + width: 23rem; } .form { display: flex; diff --git a/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.workspace.tsx b/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.workspace.tsx index beb89d557..c5c6dc123 100644 --- a/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.workspace.tsx +++ b/packages/esm-patient-clinical-view-app/src/case-management/workspace/case-management.workspace.tsx @@ -15,6 +15,7 @@ const schema = z.object({ caseManager: z.string().nonempty({ message: 'Case Manager is required' }), relationship: z.string().nonempty({ message: 'Relationship is required' }), startDate: z.date({ required_error: 'Start Date is required' }), + endDate: z.date().optional(), notes: z.string().optional(), }); @@ -64,6 +65,7 @@ const CaseManagementForm: React.FC = ({ closeWorkspace }) => relationshipType: data.relationship, personB: patientUuid, startDate: data.startDate.toISOString(), + endDate: data.endDate ? data.endDate.toISOString() : null, }; try { @@ -165,16 +167,13 @@ const CaseManagementForm: React.FC = ({ closeWorkspace }) => name="startDate" control={control} render={({ field, fieldState }) => ( - field.onChange(e[0])} - className={styles.formDatePicker}> + field.onChange(e[0])}> @@ -182,6 +181,25 @@ const CaseManagementForm: React.FC = ({ closeWorkspace }) => )} /> + + + ( + field.onChange(e[0])}> + + + )} + /> + + { - const [activeTabIndex, setActiveTabIndex] = useState(0); - return (
- - + +
); }; From 5f064521ec875d5c299a6343cc31ed647d1a373e Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Fri, 10 Jan 2025 12:39:12 +0300 Subject: [PATCH 17/17] (fix) duplicate type --- packages/esm-morgue-app/src/config-schema.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/esm-morgue-app/src/config-schema.ts b/packages/esm-morgue-app/src/config-schema.ts index c7262ff44..ecceb105b 100644 --- a/packages/esm-morgue-app/src/config-schema.ts +++ b/packages/esm-morgue-app/src/config-schema.ts @@ -5,7 +5,6 @@ export const configSchema = { _type: Type.String, _description: ' UUID for morgue visit', _default: '02b67c47-6071-4091-953d-ad21452e830c', - _default: '02b67c47-6071-4091-953d-ad21452e830c', }, morgueDepartmentServiceTypeUuid: { _type: Type.String, @@ -71,7 +70,6 @@ export const configSchema = { _type: Type.String, _description: 'UUID for discharge area concept', _default: '89ebccf1-4cca-4195-aeff-3e75fdf976b4', - _default: '89ebccf1-4cca-4195-aeff-3e75fdf976b4', }, adminUuid: { _type: Type.String,