Skip to content

Commit

Permalink
(feat) O3-4002 Add implementation for configuring dashboard Encounter…
Browse files Browse the repository at this point in the history
… List Table component
  • Loading branch information
CynthiaKamau committed Sep 30, 2024
1 parent 3a47f77 commit 765c1ae
Show file tree
Hide file tree
Showing 18 changed files with 815 additions and 9 deletions.
165 changes: 165 additions & 0 deletions src/components/interactive-builder/add-columns-modal.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import React, { useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import {
Button,
Form,
FormGroup,
ModalBody,
ModalFooter,
ModalHeader,
Stack,
TextInput,
Dropdown,
RadioButton,
RadioButtonGroup,
} from '@carbon/react';
import { isDesktop, useLayoutType } from '@openmrs/esm-framework';
import { type Schema, type Form as FormType } from '../../types';
import styles from './modals.scss';
import { useForms } from '../../hooks/useForm';
import { useFormConcepts } from '../../hooks/useFormConcepts';

interface ConfigureDashboardModalProps {
schema: Schema;
onSchemaChange: (schema: Schema) => void;
closeModal: () => void;
slotName: string;
}

const ConfigureDashboardModal: React.FC<ConfigureDashboardModalProps> = ({
schema,
onSchemaChange,
closeModal,
slotName,
}) => {
const { t } = useTranslation();
const desktopLayout = isDesktop(useLayoutType());
const [columnTitle, setColumnTitle] = useState('');
const [columnConcept, setColumnConcept] = useState('');
const [isColumnDate, setIsColumnDate] = useState(false);
const [isColumnLink, setIsColumnLink] = useState(false);
const [selectedForm, setSelectedForm] = useState<FormType>();
const [selectedFormForConcepts, setSelectedFormForConcepts] = useState<FormType>();
const { isLoadingForm, forms, formsError } = useForms();
const { isLoadingFormConcepts, formConcepts, formConceptsError } = useFormConcepts(selectedFormForConcepts);

const newColumns = {
id: columnTitle,
title: columnTitle,
concept: columnConcept,
isDate: isColumnDate,
isLink: isColumnLink,
};
const updateSchema = () => {};

const handleCreateColumn = () => {
updateSchema();
closeModal();
};

const handleConceptChange = useCallback(({ selectedItem }) => setColumnConcept(selectedItem.concept), []);
const handleFormChange = useCallback(({ selectedItem }) => {
setSelectedForm(selectedItem.uuid);
setSelectedFormForConcepts(selectedItem);
}, []);

return (
<>
<ModalHeader
className={styles.modalHeader}
closeModal={closeModal}
title={t('createNewSubMenu', 'Create a new submenu')}
/>
<Form onSubmit={(event: React.SyntheticEvent) => event.preventDefault()}>
<ModalBody>
<Stack gap={5}>
<FormGroup legendText={t('configureColumns', 'Configure columns')}>
<Dropdown
id="form"
initialSelectedItem={forms[0]}
label={t('selectform', 'Select form')}
titleText={t('form', 'Form') + ':'}
items={[...forms]}
itemToString={(item) => item.display}
onChange={handleFormChange}
size={desktopLayout ? 'sm' : 'lg'}
className={styles.label}
/>
<Dropdown
id="form"
initialSelectedItem={formConcepts[0]}
label={t('selectConcept', 'Select concept')}
titleText={t('concept', 'Concept') + ':'}
items={[...formConcepts]}
itemToString={(item) => item.label}
onChange={handleConceptChange}
size={desktopLayout ? 'sm' : 'lg'}
className={styles.label}
/>
<TextInput
required
id="columnTitle"
labelText={t('columnTitle', 'Column Title')}
placeholder={t('columnTitlePlaceholder', 'e.g. Visit title')}
value={columnTitle}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => setColumnTitle(event.target.value)}
className={styles.label}
/>
<RadioButtonGroup
name="isDate"
orientation="horizontal"
legendText={t('isDate', 'Is date')}
className={styles.label}
onChange={(event) => setIsColumnDate(event.toString())}
>
<RadioButton
className={styles.radioButton}
id="isDateTrue"
labelText={t('true', 'True')}
value="true"
/>
<RadioButton
className={styles.radioButton}
id="isDateFalse"
labelText={t('false', 'False')}
value="false"
/>
</RadioButtonGroup>

<RadioButtonGroup
name="isLink"
orientation="horizontal"
legendText={t('isLink', 'Is link')}
className={styles.label}
onChange={(event) => setIsColumnLink(event.toString())}
>
<RadioButton
className={styles.radioButton}
id="isLinkTrue"
labelText={t('true', 'True')}
value="true"
/>
<RadioButton
className={styles.radioButton}
id="isLinkFalse"
labelText={t('false', 'False')}
value="false"
/>
</RadioButtonGroup>
</FormGroup>
</Stack>
</ModalBody>
</Form>
<ModalFooter>
<Button kind="secondary" onClick={closeModal}>
{t('cancel', 'Cancel')}
</Button>
<Button onClick={handleCreateColumn}>
<span>{t('createSubMenu', 'Create Submenu')}</span>
</Button>
</ModalFooter>
</>
);
};

export default ConfigureDashboardModal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import React, { useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import {
Button,
Form,
FormGroup,
ModalBody,
ModalFooter,
ModalHeader,
Stack,
TextInput,
Dropdown,
} from '@carbon/react';
import { isDesktop, showSnackbar, useLayoutType } from '@openmrs/esm-framework';
import { type Schema, type Form as FormType } from '../../types';
import styles from './modals.scss';
import { useEncounterTypes } from '../../hooks/useEncounter';

interface ConfigureDashboardModalProps {
schema: Schema;
onSchemaChange: (schema: Schema) => void;
closeModal: () => void;
slotName: string;
}

const ConfigureDashboardModal: React.FC<ConfigureDashboardModalProps> = ({
schema,
onSchemaChange,
closeModal,
slotName,
}) => {
const { t } = useTranslation();
const [selectedWidget, setSelectedWidget] = useState('');
const [tabName, setTabName] = useState('');
const [displayTitle, setDisplayTitle] = useState('');
const [encounterType, setEncounterType] = useState('');
const desktopLayout = isDesktop(useLayoutType());
const [selectedFormForConcepts, setSelectedFormForConcepts] = useState<FormType>();
const { isLoading, encounterTypes, encounterTypesError } = useEncounterTypes();

const availableWidgets = [
{ uuid: 'encounter-list-table-tabs', value: 'Encounter list table' },
{ uuid: 'program-summary', value: 'Encounter tile' },
];

const newExtensionSlot = {
[slotName]: {
add: [slotName],
configure: {
[slotName]: {
title: tabName,
slotName: slotName,
isExpanded: true,
tabDefinitions: [
{
tabName: tabName,
headerTitle: tabName,
displayText: displayTitle,
encounterType: encounterType,
columns: [],
},
],
},
},
},
};
const updateSchema = () => {
try {
const updatedSchema = {
...schema,
'@openmrs/esm-patient-chart-app': {
...schema['@openmrs/esm-patient-chart-app'],
extensionSlots: {
...schema['@openmrs/esm-patient-chart-app'].extensionSlots,
...newExtensionSlot,
},
},
};

onSchemaChange(updatedSchema);

// Show success notification
showSnackbar({
title: t('success', 'Success!'),
kind: 'success',
isLowContrast: true,
subtitle: t('submenuCreated', 'New submenu created'),
});
} catch (error) {
if (error instanceof Error) {
showSnackbar({
title: t('errorCreatingSubmenu', 'Error creating submenu'),
kind: 'error',
subtitle: error.message,
});
}
}
};

const handleCreateWidget = () => {
updateSchema();
closeModal();
};

const handleEncounterTypeChange = useCallback(({ selectedItem }) => setEncounterType(selectedItem.uuid), []);

return (
<>
<ModalHeader
className={styles.modalHeader}
closeModal={closeModal}
title={t('createNewSubMenu', 'Create a new submenu')}
/>
<Form onSubmit={(event: React.SyntheticEvent) => event.preventDefault()}>
<ModalBody>
<Stack gap={5}>
<FormGroup legendText={''}>
<TextInput required readOnly id="slotName" labelText={t('slotName', 'Slot name')} value={slotName} />
<Dropdown
id="widget"
items={[...availableWidgets]}
initialSelectedItem={availableWidgets[0]}
itemToString={(item) => (item ? item.value : 'Not Set')}
titleText={t('selectWidget', 'Select Widget')}
onChange={({ selectedItem }) => setSelectedWidget(selectedItem?.uuid)}
size={desktopLayout ? 'sm' : 'lg'}
className={styles.label}
/>
</FormGroup>

{selectedWidget === 'encounter-list-table-tabs' && (
<FormGroup legendText={t('configureColumns', 'Configure columns')}>
<TextInput
required
id="tabName"
labelText={t('tabName', 'Tab name')}
placeholder={t('tabNamePlaceholder', 'e.g. Clinical Visit')}
value={tabName}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => setTabName(event.target.value)}
className={styles.label}
/>
<TextInput
required
id="displayTitle"
labelText={t('displayTitle', 'Display title')}
placeholder={t('displayTitlePlaceholder', 'e.g. Clinical Visit Encounters')}
value={displayTitle}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => setDisplayTitle(event.target.value)}
className={styles.label}
/>
<Dropdown
id="encounterType"
initialSelectedItem={encounterTypes[0]}
label={t('selectEncounterType', 'select encounter type')}
titleText={t('encounterType', 'Encounter type') + ':'}
items={[...encounterTypes]}
itemToString={(item) => item.display}
onChange={handleEncounterTypeChange}
size={desktopLayout ? 'sm' : 'lg'}
className={styles.label}
/>
</FormGroup>
)}
</Stack>
</ModalBody>
</Form>
<ModalFooter>
<Button kind="secondary" onClick={closeModal}>
{t('cancel', 'Cancel')}
</Button>
<Button disabled={!selectedWidget} onClick={handleCreateWidget}>
<span>{t('createSubMenu', 'Create Submenu')}</span>
</Button>
</ModalFooter>
</>
);
};

export default ConfigureDashboardModal;
Loading

0 comments on commit 765c1ae

Please sign in to comment.