diff --git a/src/add-group-modal/AddGroupModal.tsx b/src/add-group-modal/AddGroupModal.tsx index c12b550..f06d3e0 100644 --- a/src/add-group-modal/AddGroupModal.tsx +++ b/src/add-group-modal/AddGroupModal.tsx @@ -16,10 +16,13 @@ import { } from "@carbon/react"; import { TrashCan } from "@carbon/react/icons"; import { useTranslation } from "react-i18next"; -import { ExtensionSlot, showToast } from "@openmrs/esm-framework"; +import { ExtensionSlot, showToast, useConfig } from "@openmrs/esm-framework"; import styles from "./styles.scss"; import GroupFormWorkflowContext from "../context/GroupFormWorkflowContext"; import { usePostCohort } from "../hooks"; +import GroupAttributeComponent, { + CohortAttribute, +} from "./cohort-attribute-component/GroupAttributeComponent"; const MemExtension = React.memo(ExtensionSlot); @@ -79,6 +82,8 @@ const NewGroupForm = (props) => { errors, validate, removePatient, + groupAttributes, + onCohortAttributeValueChange, } = props; const { t } = useTranslation(); @@ -103,6 +108,10 @@ const NewGroupForm = (props) => { : errors.name}

)} + {patientList.length} {t("patientsInGroup", "Patients in group")} @@ -147,6 +156,7 @@ const AddGroupModal = ({ isOpen, handleCancel, onPostSubmit, + attributes = undefined, }) => { const { setGroup } = useContext(GroupFormWorkflowContext); const { t } = useTranslation(); @@ -154,6 +164,11 @@ const AddGroupModal = ({ const [name, setName] = useState(groupName); const [patientList, setPatientList] = useState(patients || []); const { post, result, error } = usePostCohort(); + const { groupAttributesConfig } = useConfig(); + const [groupAttributes, setGroupAttributes] = useState([]); + + console.log("result", result); + console.log("groupName", groupName); const removePatient = useCallback( (patientUuid: string) => @@ -205,11 +220,52 @@ const AddGroupModal = ({ [setPatientList] ); + useMemo(() => { + setGroupAttributes( + groupAttributesConfig?.map((config) => { + const attribute = attributes?.find( + (a) => a.attributeType.uuid == config.uuid + ); + return { + uuid: attribute?.uuid, + labelCode: config.labelCode, + value: attribute?.value, + attributeType: { + name: config.name, + type: config.type, + uuid: config.uuid, + }, + }; + }) + ); + }, [groupAttributesConfig, attributes]); + + const onCohortAttributeValueChange = (attributeId: string, value: any) => { + const updatedAttributes = [...groupAttributes]; + updatedAttributes.find( + (a: CohortAttribute) => a.attributeType.uuid == attributeId + ).value = value; + setGroupAttributes(updatedAttributes); + }; + + const getAttributesPayload = () => { + return groupAttributes.map((a: CohortAttribute) => { + return { + uuid: a.uuid, + value: a.value, + attributeType: { + uuid: a.attributeType.uuid, + }, + }; + }); + }; + const handleSubmit = () => { if (validate()) { post({ uuid: cohortUuid, name: name, + attributes: getAttributesPayload(), cohortMembers: patientList.map((p) => ({ patient: p.uuid })), }); if (onPostSubmit) { @@ -269,6 +325,8 @@ const AddGroupModal = ({ errors, validate, removePatient, + groupAttributes, + onCohortAttributeValueChange, }} /> diff --git a/src/add-group-modal/cohort-attribute-component/GroupAttributeComponent.tsx b/src/add-group-modal/cohort-attribute-component/GroupAttributeComponent.tsx new file mode 100644 index 0000000..50d0641 --- /dev/null +++ b/src/add-group-modal/cohort-attribute-component/GroupAttributeComponent.tsx @@ -0,0 +1,61 @@ +import React from "react"; +import { TextInput, Checkbox } from "@carbon/react"; +import { useTranslation } from "react-i18next"; +import styles from "./styles.scss"; + +interface GroupAttributeComponentProps { + cohortAttributeTypes: CohortAttribute[]; + onChange: any; +} +const GroupAttributeComponent: React.FC = ( + props +) => { + const { cohortAttributeTypes, onChange } = props; + const { t } = useTranslation(); + + return ( + <> + {cohortAttributeTypes.map((attribute) => { + switch (attribute.attributeType.type) { + case "org.openmrs.customdatatype.datatype.FreeTextDatatype": + return ( + { + onChange(event.target.id, event.target.value); + }} + /> + ); + case "org.openmrs.customdatatype.datatype.BooleanDatatype": + return ( + { + onChange(event.target.id, event.target.checked); + }} + /> + ); + default: + break; + } + })} + + ); +}; +export default GroupAttributeComponent; + +export type CohortAttribute = { + uuid?: string; + labelCode?: string; + value?: any; + attributeType: { + uuid: string; + name: string; + type: string; + }; +}; diff --git a/src/add-group-modal/cohort-attribute-component/styles.scss b/src/add-group-modal/cohort-attribute-component/styles.scss new file mode 100644 index 0000000..ff98b1a --- /dev/null +++ b/src/add-group-modal/cohort-attribute-component/styles.scss @@ -0,0 +1,3 @@ +@use '@carbon/styles/scss/spacing'; +@use '@carbon/colors'; + diff --git a/src/config-schema.ts b/src/config-schema.ts index b50f1b9..4fda3f9 100644 --- a/src/config-schema.ts +++ b/src/config-schema.ts @@ -82,6 +82,48 @@ export const configSchema = { _default: "fa8fedc0-c066-4da3-8dc1-2ad8621fc480", }, }, + groupAttributesConfig: { + _type: Type.Array, + _description: + "List of group attributes, must correspond to an Cohort Attribute Type on the database", + _elements: { + uuid: { + _type: Type.String, + _description: "UUID of the Cohort Attribute Type", + }, + name: { + _type: Type.String, + _description: "Name of the Cohort Attribute Type", + }, + id: { + _type: Type.String, + _description: "ID of the attribute.", + }, + labelCode: { + _type: Type.String, + _description: "Code to be use in translation.", + }, + type: { + _type: Type.String, + _description: + "Datatype of the Cohort Attribute Type, acceptable values are 'FreeTextDatatype' | 'BooleanDatatype'", + }, + }, + _default: [ + { + uuid: "09790099-9190-429d-811a-aac9edb8d98a", + name: "Test 01", + labelCode: "test01", + type: "org.openmrs.customdatatype.datatype.FreeTextDatatype", + }, + { + uuid: "09790099-9190-429d-811a-aac9edb8d98d", + name: "Close Group", + labelCode: "closeGroup", + type: "org.openmrs.customdatatype.datatype.BooleanDatatype", + }, + ], + }, }; export type Form = { @@ -94,7 +136,17 @@ export type Category = { forms: Array
; }; +export type CohortAttributeTypeConfig = { + uuid: string; + name: string; + labelCode: string; + type: + | "org.openmrs.customdatatype.datatype.FreeTextDatatype" + | "org.openmrs.customdatatype.datatype.BooleanDatatype"; +}; + export type Config = { formCategories: Array; formCategoriesToShow: Array; + groupAttributesConfig: Array; }; diff --git a/src/context/GroupFormWorkflowContext.tsx b/src/context/GroupFormWorkflowContext.tsx index 3e97972..4c59d60 100644 --- a/src/context/GroupFormWorkflowContext.tsx +++ b/src/context/GroupFormWorkflowContext.tsx @@ -11,6 +11,7 @@ export interface GroupType { id: string; name: string; members: Array; + attributes: Array; } export interface MetaType { sessionName: string; @@ -56,6 +57,7 @@ export const initialWorkflowState = { activeGroupUuid: null, // pseudo field from state[activeFormUuid].groupUuid activeGroupName: null, // pseudo field from state[activeFormUuid].groupName activeGroupMembers: [], // pseudo field from state[activeFormUuid].groupMembers + activeGroupAttributes: [], // pseudo field from state[activeFormUuid].groupAttributes activeSessionMeta: { sessionName: null, practitionerName: null, @@ -162,6 +164,9 @@ const GroupFormWorkflowProvider = ({ children }) => { activeGroupMembers: state.forms?.[state.activeFormUuid]?.groupMembers ?? initialWorkflowState.activeGroupMembers, + activeGroupAttributes: + state.forms?.[state.activeFormUuid]?.groupAttributes ?? + initialWorkflowState.activeGroupAttributes, activeSessionMeta: state.forms?.[state.activeFormUuid]?.sessionMeta ?? initialWorkflowState.activeSessionMeta, diff --git a/src/group-form-entry-workflow/attendance-table/AttendanceTable.tsx b/src/group-form-entry-workflow/attendance-table/AttendanceTable.tsx index 3f8042d..a943149 100644 --- a/src/group-form-entry-workflow/attendance-table/AttendanceTable.tsx +++ b/src/group-form-entry-workflow/attendance-table/AttendanceTable.tsx @@ -71,9 +71,12 @@ const PatientRow = ({ patient }) => { const AttendanceTable = ({ patients }) => { const { t } = useTranslation(); - const { activeGroupUuid, activeGroupName, activeGroupMembers } = useContext( - GroupFormWorkflowContext - ); + const { + activeGroupUuid, + activeGroupName, + activeGroupAttributes, + activeGroupMembers, + } = useContext(GroupFormWorkflowContext); const [isOpen, setOpen] = useState(false); @@ -118,6 +121,7 @@ const AttendanceTable = ({ patients }) => { isOpen: isOpen, handleCancel: handleCancel, onPostSubmit: onPostSubmit, + attributes: activeGroupAttributes, }} /> diff --git a/src/group-form-entry-workflow/group-search/GroupSearch.tsx b/src/group-form-entry-workflow/group-search/GroupSearch.tsx index 63980fd..e4f7714 100644 --- a/src/group-form-entry-workflow/group-search/GroupSearch.tsx +++ b/src/group-form-entry-workflow/group-search/GroupSearch.tsx @@ -35,6 +35,8 @@ const GroupSearch: React.FC = ({ }, }); + console.log("results", results); + const lastItem = useRef(null); const observer = useRef(null); const loadingRef = useCallback(