feat : save encounter#12
Merged
solemabrothers merged 30 commits intoMETS-Programme:mainfrom Jul 8, 2025
Merged
Conversation
This commit introduces Firebase Crashlytics for enhanced crash reporting and analysis. The following changes were made: - Added Firebase Crashlytics dependencies to all relevant modules (`app`, `auth`, `core`, `form`, `main`, `settings`, `sync`, `worklist`). - Updated the `libs.versions.toml` file to include the Crashlytics library. - Enabled Crashlytics logging in `AppLogger.kt` to send crash reports and logs to Firebase.
This commit refactors the form mapping logic to enhance the mapping of OpenMRS concepts for both questions and answers.
Key changes:
- **Questionnaire Item Link ID Prefixing:** `linkId` for pages, sections, and questions are now prefixed (e.g., `page-`, `section-`, `q-`) for better organization and clarity.
- **Concept Mapping for Questions:**
- Questions now store the concept UUID in the `definition` field of the FHIR Questionnaire item.
- The concept is also added as a `code` and an `extension` to the Questionnaire item.
- Logging has been added to track successful concept mapping and instances where questions lack a concept UUID.
- **Concept Mapping for Answers:**
- Answer options now correctly map their `concept` to the `code` within the FHIR `Coding` object, along with the `system` URL.
- Logging added for answers missing concepts.
- **Improved Observation Extraction:**
- The `extractObsFromResponse` function now takes `questionnaireItems` as a parameter to resolve concepts directly from the Questionnaire definition.
- It prioritizes concept resolution in the following order: `code` field, custom concept `extension`, or `definition` field.
- Enhanced logging and warnings for missing matching Questionnaire items or concepts during observation extraction.
- For coded answers, it now uses the answer's `concept` as the observation concept.
- For non-coded answers, it uses the question's resolved concept as the observation concept.
- **Helper Function:** Added `findQuestionnaireItemByLinkId` to recursively search for Questionnaire items by their `linkId`.
- **Encounter Building:** The `buildOpenmrsEncounter` and `toOpenmrsEncounter` functions now require `questionnaireItems` to facilitate the improved concept mapping during observation extraction.
- **Boolean Conversion:** The `toBooleanStrict()` extension function was removed as `toBooleanStrictOrNull()` provides a safer alternative for handling potentially nullable boolean strings.
Refactors encounter processing in `QuestionnaireViewModel` to use `EncounterExtensions.toOpenmrsEncounter`. Adds `Questionnaire` object to `QuestionnaireState` for easier access. Improves error handling and logging for questionnaire submission.
This commit introduces the ability to save encounters locally. Key changes include: - Updated `QuestionnaireViewModel` to map `QuestionnaireResponse` to an `OpenmrsEncounter`, convert it to an `EncounterEntity`, and save it locally using `FormsUseCase`. - Moved `OpenmrsEncounter` and `OpenmrsObs` data classes from the `form` module to the `core` module. - Added `saveEncounterLocally` method to `FormRepository` and its implementation in `FormRepositoryImpl`. - Updated `EncounterEntity` with new fields and relationships. - Added `EncounterDao` for database operations related to encounters. - Updated `AppDatabase` and `DatabaseModule` to include `EncounterDao`. - Added `EncounterExtensions` for mapping between `OpenmrsEncounter` and `EncounterEntity`.
This commit updates the Kotlin JVM target configuration across multiple modules and introduces new dependencies.
Key changes:
- **Kotlin JVM Toolchain:** Replaced `kotlinOptions { jvmTarget = "11" }` with `kotlin { jvmToolchain(11) }` in `app`, `auth`, `core`, `core-navigation`, `form`, `settings`, `sync`, and `worklist` modules for standardized JVM target configuration.
- **Guava Version Override:** Forced Guava version to `32.1.3-android` in `app`, `main`, and `sync` modules to resolve potential version conflicts.
- **New Dependencies in `sync` module:**
- Added Android FHIR Engine and SDC libraries (`libs.android.fhir.engine`, `libs.android.fhir.sdc`).
- Added Core Library Desugaring (`libs.desugar.jdk.libs`).
- Added Hilt WorkManager integration libraries (`libs.hilt.work`, `libs.hilt.work.compiler`, `libs.work.runtime.ktx`).
- **New Dependencies in `app` module:**
- Added Hilt WorkManager integration libraries (`libs.hilt.work`, `libs.hilt.work.compiler`, `libs.work.runtime.ktx`).
This commit relocates the patient mapping logic from `PatientMapper.kt` in the `form` module to `PatientExtensions.kt` in the `form/utils` package.
Key changes:
- Moved and refactored patient mapping functions (`toQuestionnaireAnswers`, `toPatient`, `toPatientEntity`, `toFhirPatient`) to `PatientExtensions.kt`.
- Updated `PatientEntity` to auto-generate a UUID for `id` if not provided and renamed `isSynced` to `synced`. Removed `visitHistory` and `encounters` fields.
- Enhanced `EncounterDao` and `PatientDao` `update` methods to return the number of rows affected.
- Added `getUnsyncedPatients` method to `PatientDao`.
- Implemented methods in `SyncRepository` and `SyncRepositoryImpl` for:
- Retrieving unsynced encounters and patients.
- Marking encounters and patients as synced.
- Updated `SyncUseCase` to expose the new sync functionalities.
- Adjusted `SyncModule` to provide necessary DAO dependencies to `SyncRepositoryImpl`.
This commit introduces background synchronization for encounters and patients using WorkManager.
Key changes:
- **`EncounterSyncWorker`**:
- Fetches unsynced `EncounterEntity` records from the local database.
- Builds an `EncounterPayload` for each unsynced encounter.
- Sends the payload to the `saveEncounter` API endpoint.
- On successful API response, marks the encounter as synced in the local database.
- Implements retry logic for failed API calls or database operations.
- Logs sync progress and errors.
- **`PatientsSyncWorker`**:
- Fetches unsynced `PatientEntity` records from the local database.
- Converts each `PatientEntity` to a FHIR Patient resource (JSON).
- Sends the FHIR Patient JSON to the `/fhir/Patient` API endpoint.
- On successful API response, marks the patient as synced in the local database.
- Implements retry logic and logging similar to `EncounterSyncWorker`.
- **`EncounterPayload`**: Added a new data class to represent the structure for saving encounters via the API.
- **`FormApi`**:
- Added `saveEncounter` endpoint for posting encounter data.
- Added `savePatient` endpoint for posting FHIR Patient resources.
- **`FormTypeConverters`**: Added a `TypeConverter` for `List<OpenmrsObs>` to support storing observations within `EncounterEntity`.
- **Dependency Injection**:
- Updated `FormModule` to provide `EncounterDao` to `FormRepository`.
- `UgandaEMRMobile` (Application class) now implements `Configuration.Provider` and injects `HiltWorkerFactory` to enable Hilt dependency injection in Workers.
This commit updates the following dependencies: - Firebase Bill of Materials (BoM) from version 33.15.0 to 33.16.0. - Google Services plugin from version 4.4.2 to 4.4.3. - Kotlin Symbol Processing (KSP) from version 2.1.21-2.0.1 to 2.2.0-2.0.2. - Adds Hilt WorkManager integration with version 1.2.0 for Hilt and 2.10.2 for WorkManager.
Moved mapper functions `toPatient`, `toPatientEntity`, and `toQuestionnaireAnswers` from the `domain.mapper` package to the `utils` package within the `form` module. The `toPatientEntity` function in `RegisterPatientViewModel` now directly converts a `Patient` object to a `PatientEntity` without requiring `visitHistory` and `encounters` parameters, as these can be handled with default values or populated later.
This commit significantly refactors the local data models for Encounters and Visits to better align with the OpenMRS data structure. This improves consistency and prepares for more robust synchronization with the server.
Key changes include:
- **Encounter Model:**
- Renamed fields in `EncounterEntity` and `Encounter` (domain model) to match OpenMRS conventions (e.g., `id` to `uuid`, `visitId` to `visitUuid`, `type` to `encounterTypeUuid`).
- Added new fields to `EncounterEntity` and `Encounter` to store more comprehensive OpenMRS encounter data: `providerUuid`, `orders`, `formUuid`, `voided`, and `createdAt`.
- Updated `EncounterPayload` to reflect these changes for server communication.
- Adjusted `EncounterExtensions.toEncounterEntity` and `EncounterMapper.toDomain/toEntity` to handle the new fields and naming.
- **Visit Model:**
- Renamed `visitId` to `visitUuid` in `VitalsEntity` and updated foreign key relationships in `EncounterEntity` and `VitalsEntity` to use `visitUuid`.
- Updated `VisitMapper` to align `Encounter.toEntity` and `Vitals.toEntity` with the new `visitUuid` field.
- Automatically generate `id` for `VisitEntity` using `UUID.randomUUID().toString()`.
- **Data Converters:**
- Added `FormTypeConverters` for `Order` and `List<Order>` to enable Room to store these new complex types.
- **UI & Logic Updates:**
- Updated `EncounterCard` to display `encounterTypeUuid` and `encounterDatetime`.
- Updated `QuestionnaireViewModel` to use `visitUuid` when creating `EncounterEntity`.
- Commented out encounter insertion in `VisitRepositoryImpl` as it's now handled by the form submission flow.
- Updated `EncounterSyncWorker` to build the `EncounterPayload` using the new field names and structure.
These changes ensure that the local data representation is closer to the OpenMRS API, facilitating smoother data exchange and future development.
The `EncounterCard` composable was updated to display observations from the `obs` field of the `Encounter` object, instead of the previously used `observations` field. This aligns the UI with the data model.
This commit introduces support for repeating groups within forms.
Key changes:
- Added a `questions` field to the `Questions` data class in `o3Form.kt` to allow nesting of questions, which is essential for defining repeating groups.
- Modified `FormMapper.kt` to handle questions with `FieldType.REPEATING`.
- When a repeating question is encountered, it's mapped to a FHIR `QuestionnaireItemComponent` of type `GROUP` with `repeats = true`.
- Child questions within the repeating group are processed and added to this group item using a new extension function `addChildQuestionItem`.
- Link IDs for child questions within repeating groups are now prefixed with the parent group's `linkId` to ensure uniqueness (e.g., `parent-group-link-id.q-1`).
- Added an extension function `Questionnaire.QuestionnaireItemComponent.addChildQuestionItem` to encapsulate the logic for creating and adding child question items to a parent group item. This function handles `linkId` generation, type mapping, concept mapping, and answer option creation for child questions.
- Updated `FhirExtensions.kt` to map `FieldType.REPEATING` to `Questionnaire.QuestionnaireItemType.GROUP`.
- Added `FieldType.FILE` mapping to `Questionnaire.QuestionnaireItemType.ATTACHMENT`.
- Improved logging throughout the form mapping process, especially for repeating groups and their child questions, to aid in debugging and understanding the mapping flow.
This commit introduces the following changes: - **Navigation after save:** After successfully saving an encounter locally, the user is now navigated to the "worklist_main" screen. - **Improved logging:** Enhanced logging for form parsing errors in `QuestionnaireViewModel`. - **Corrected payload mapping:** Fixed the mapping of `providerUuid` in `EncounterSyncWorker` to use `entity.providerUuid` instead of `entity.locationUuid`.
This commit refactors the `SyncViewModel` to use a single `SyncUiState` data class to manage its state and a sealed `SyncEvent` class to handle user interactions and asynchronous events. This improves state management and makes the ViewModel more testable and easier to reason about.
Key changes:
- **Introduced `SyncUiState`:**
- Created `SyncUiState.kt` to consolidate all UI-related state for the sync screen, including loading status, error messages, form lists, selections, search queries, cohort data, indicator selections, date ranges, and parameter lists.
- **Introduced `SyncEvent`:**
- Created `SyncEvent.kt` to define all possible events that can occur in the sync screen, such as filtering forms, toggling form selections, downloading forms, changing cohort/indicator selections, applying filters, and managing dual list box interactions.
- **Refactored `SyncViewModel`:**
- Replaced individual `MutableStateFlow` and `mutableStateOf` properties with a single `_uiState` of type `MutableStateFlow<SyncUiState>`.
- Implemented an `onEvent(event: SyncEvent)` function to handle all incoming events and update the `_uiState` accordingly.
- Updated methods like `loadForms`, `filterForms`, `toggleFormSelection`, `onDownloadClick`, `onIndicatorSelected`, `onApplyFilters`, `toggleHighlightAvailable`, `toggleHighlightSelected`, `moveRight`, and `moveLeft` to interact with `_uiState` and `SyncEvent`.
- Removed `DownloadFormsUiEvent` as its functionality is now covered by `SyncEvent` and `SyncUiState`.
- Updated `collectResult` to modify `_uiState.isLoading` and `_uiState.error`.
- The `formCount` is now updated directly in `_uiState`.
- **Updated `SyncScreen.kt`:**
- Now collects `uiState` from `SyncViewModel`.
- Calls `viewModel.onEvent()` to dispatch events instead of directly calling ViewModel methods.
- Uses `uiState` properties for displaying data (e.g., `uiState.formItems`, `uiState.searchQuery`, `uiState.selectedFormIds`).
- Removed `LaunchedEffect` for `viewModel.uiEvent` as UI updates are driven by `uiState` collection.
- **Updated `DownloadFormsScreen.kt`:**
- Now collects `uiState` from `SyncViewModel`.
- Calls `viewModel.onEvent()` for actions like filtering and toggling form selection.
- Uses `uiState` properties for displaying data.
- **Removed `DownloadFormsUiEvent.kt`:** This event class is no longer needed.
- **Added mapping for `FieldType.UI_SELECT_EXTENDED`:**
- In `FhirExtensions.kt`, `FieldType.UI_SELECT_EXTENDED` is now mapped to `Questionnaire.QuestionnaireItemType.STRING`.
This refactoring centralizes state and event handling, leading to a more predictable and maintainable codebase for the sync feature.
… local data counts
This commit introduces several enhancements to the Sync and Settings screens, refactors data fetching logic, and adds functionality to display local data counts.
**Key Changes:**
**Sync Screen (`SyncScreen.kt`, `SyncViewModel.kt`, `SyncUiState.kt`):**
- **Enhanced UI:**
- Improved layout and styling for better readability and visual appeal.
- Added icons to various sections (Sync Status, Data Summary, Auto Sync, Manual Download).
- Introduced `StatusRow` and `SummaryRow` composables for consistent display of status and summary information.
- Implemented `AnimatedCount` for a smoother visual update of data counts.
- Used `HorizontalDivider` to visually separate sections within cards.
- Updated card shapes to `RoundedCornerShape(12.dp)`.
- **Data Summary:**
- Display counts for "Forms Saved", "Patients Saved", "Visits Saved" (currently 0), "Patients Synced", "Visits Synced" (currently 0), and "Encounters Synced".
- `SyncViewModel` now fetches and updates `patientCount` and `encounterCount` in `SyncUiState`.
- **Error Handling:**
- Improved error messages for fetching order types, encounter types, and patient identifiers.
- Refactored result handling in `SyncViewModel` using a new `handleResult` (though the implementation diff for `handleResult` itself is not provided, the calls to it are updated).
- **Patient Download:**
- Removed `selectedDateRange` and related date picker logic from the patient filter section as it's not currently used.
- `SyncEvent.DateRangeSelected` has been removed.
**Settings Screen (`SettingsScreen.kt`):**
- **Enhanced UI:**
- Replaced generic `SettingsItem` with more specific `SettingsItem` (with icon and optional trailing icon) and `SettingsItemSwitch` composables.
- Added icons to all settings items (Username, Facility, Language, Dark Mode, Server URL, Sync Interval, Logout).
- Improved styling of the Logout button.
- Grouped settings items within visually distinct surfaced sections.
**Data Layer (`SyncRepository.kt`, `SyncRepositoryImpl.kt`, DAOs):**
- **Local Data Counts:**
- Added `getPatientsCount()` and `getEncountersCount()` to `SyncRepository` and `SyncRepositoryImpl`.
- Implemented these count methods in `PatientDao`, `EncounterDao`, and `FormDao` to return a `Flow<Int>`.
- `getFormCount` in `SyncRepositoryImpl` now directly maps the Flow from DAO to `Result.Success` and handles errors more concisely.
- **Repository Method Reordering:**
- Moved sync-related methods (getUnsynced, markSynced, etc.) in `SyncRepository` to be grouped together.
- **OrderType Model:**
- Made `display` and `name` fields in `OrderType` nullable to handle potential null values from the API.
**Core UI Components:**
- **`IndicatorAttributesScreen.kt`:**
- Improved TopAppBar title display.
- Enhanced visual distinction of available and selected parameter lists.
- Updated transfer button content descriptions for better accessibility.
- **`ParameterList.kt`:**
- Improved empty state display with an icon and more informative text.
- Enhanced styling for highlighted items using `Surface` with tonal elevation and border.
**Use Cases (`SyncUseCase.kt`):**
- Added `getPatientCount()` and `getEncounterCount()` methods to expose the new repository functionalities.
…mponents
This commit replaces the `VisitSummary` domain model and related entities/DAOs with the existing `VisitEntity` and its corresponding DAO and mappers. This streamlines the visit data handling and aligns it with the core data model.
Key changes:
- **Removed `VisitSummary` related files:**
- `worklist/domain/model/VisitSummary.kt`
- `worklist/domain/model/PatientDetails.kt` (as it used `VisitSummary`)
- `core/data/local/dao/VisitSummaryDao.kt`
- `core/data/local/entity/VisitSummaryEntity.kt`
- `worklist/domain/usecase/VisitSummaryUseCases.kt`
- **Updated `AppDatabase`:** Removed `VisitSummaryEntity` from the database schema and `visitSummaryDao()` abstract function.
- **Updated `VisitMapper.kt`:** Removed mapping functions related to `VisitSummary` and `VisitSummaryEntity`.
- **Updated `VisitEntity.kt`:** Added `type`, `date`, and `notes` fields to match the information previously in `VisitSummaryEntity`. Made `scheduledTime` nullable.
- **Updated `WorklistViewModel.kt`:**
- Replaced `VisitSummaryUseCase` with `VisitUseCases`.
- Commented out `loadVisitSummary` logic.
- Added `WorklistEvent.StartVisit` and a placeholder `startPatientVisit()` function.
- Updated navigation to use `UiEvent.Navigate`.
- **Updated `VisitRepositoryImpl.kt`:**
- Changed `VisitRepository` interface and `VisitRepositoryImpl` to use `VisitEntity` instead of `VisitSummary`.
- Commented out and added TODOs for `getVisitSummariesForPatient` and `saveVisitSummary` implementations to reflect the change to `VisitEntity`.
- **Updated `VitalsEntity.kt`:** Changed foreign key to reference `VisitEntity` instead of `VisitSummaryEntity`.
- **Updated `WorklistUiState.kt`:** Changed `visits` from `List<VisitSummary>` to `List<VisitEntity>` and `encounters` from `List<Encounter>` to `List<EncounterEntity>`.
- **Updated `VisitDao.kt`:**
- Added functions to insert vitals and encounters (`insertVitals`, `insertEncounters`).
- Added a transaction query `getVisitDetailsForPatient` to fetch `VisitWithDetails`.
- **Updated UI Components:**
- `VisitCard.kt`, `VisitDetailsDialog.kt`: Changed to accept `VisitEntity` instead of `VisitSummary`.
- `EncounterCard.kt`, `EncounterSection.kt`: Changed to accept `EncounterEntity` instead of `Encounter`.
- `PatientDetailsScreen.kt`: Updated `selectedVisit` state to `VisitEntity?`.
- **Updated `EncounterEntity.kt`:** Changed foreign key to reference `VisitEntity` and made `id` auto-generate UUID by default.
- **Updated `FormEntity.kt`:** Made `uuid` auto-generate UUID by default.
- **Updated `PatientEntity.kt`:** Ensured `id` auto-generates UUID.
- **Updated `DatabaseModule.kt`:** Removed `provideVisitSummaryDao`.
- **Updated `WorklistModule.kt`:** Injected `VisitDao` instead of `VisitSummaryDao` into `VisitRepositoryImpl`.
- **Updated `SettingsScreen.kt`:** Minor UI improvements to the server settings dialog (styling, placeholder).
- **Added `VisitUseCases.kt`:** New use case class (currently with commented-out methods) to replace `VisitSummaryUseCases`.
This commit introduces the "Start Visit" feature, allowing users to initiate new patient visits directly from the worklist and patient details screens.
**Key Changes:**
- **`StartVisitDialog.kt`:**
- Added a new composable dialog (`StartVisitDialog`) to host the `StartVisitScreen`.
- This dialog is displayed when the "New Visit" action is triggered.
- **`WorklistScreen.kt`:**
- Integrated `StartVisitDialog` to appear when a patient's "Start Visit" action is initiated from the patient card.
- Removed the direct `onStartVisit` callback from `WorklistScreen` as the action is now handled within the dialog.
- **`PatientDetailsScreen.kt`:**
- Integrated `StartVisitDialog` to appear when the "New Visit" floating action button is clicked.
- Removed the direct `onStartVisit` parameter.
- **`StartVisitScreen.kt`:**
- Refactored to be a composable function that takes a `WorklistViewModel`.
- UI state (visit type, location, status, dates, times) is now managed by `WorklistViewModel`.
- User interactions (e.g., selecting visit type, date, time) now trigger events in `WorklistViewModel`.
- The "Start Visit" button now triggers the `WorklistEvent.StartVisit` event.
- **`WorklistViewModel.kt`:**
- Added new state properties in `WorklistUiState` to manage the "Start Visit" form data (e.g., `visitType`, `visitLocation`, `startDate`, `startTime`, `amPm`, `locationMenuExpanded`, `amPmMenuExpanded`).
- Implemented new `WorklistEvent` handlers for updating these state properties (e.g., `OnVisitTypeChanged`, `OnVisitLocationChanged`, `OnStartDateChanged`).
- Implemented the `startPatientVisit()` function:
- Retrieves form data from `_uiState`.
- Creates a `VisitEntity` with a generated UUID and selected patient ID.
- Saves the new `VisitEntity` using `visitUseCases.saveVisit()`.
- Reloads the patient list upon successful visit creation.
- **`WorklistUiState.kt`:**
- Added new fields to manage the state of the "Start Visit" form, including default values for date and time.
- **`WorklistEvent.kt`:**
- Added new events to handle changes in the "Start Visit" form fields and to trigger the start visit action.
- **`VisitRepository.kt` & `VisitRepositoryImpl.kt`:**
- Updated `getVisitSummariesForPatient` to return `Flow<Result<List<VisitWithDetails>>>`.
- Implemented `saveVisit(visit: VisitEntity): Flow<Result<Boolean>>` to persist new visit entities, including error handling for database operations.
- **`VisitUseCases.kt`:**
- Updated `getVisitSummariesForPatient` to align with repository changes.
- Added `saveVisit(visit: VisitEntity)` function to call the repository's save method.
- **`worklistGraph.kt`:**
- Removed the direct `onStartVisit` navigation from `WorklistScreen`.
- Removed the separate `startVisit` composable route as it's now handled by the dialog.
The "Start Visit" flow now involves:
1. User clicks "New Visit" (either from Patient Card or Patient Details FAB).
2. `StartVisitDialog` appears with the `StartVisitScreen`.
3. User fills in visit details (type, location, date, time, etc.).
4. Changes are reflected in `WorklistViewModel`'s state via `WorklistEvent`s.
5. User clicks "Start Visit" button.
6. `WorklistEvent.StartVisit` is dispatched.
7. `WorklistViewModel.startPatientVisit()` creates and saves the `VisitEntity`.
8. The dialog closes, and relevant lists are updated.
This commit introduces the following changes:
- **Refactored `StartVisitDialog`:**
- The dialog now uses `AlertDialog` for a more standard look and feel.
- The "Start Visit" and "Cancel" buttons are now part of the `AlertDialog`'s `confirmButton` and `dismissButton` respectively.
- The `onStartVisit` callback was removed from `StartVisitDialog` and `WorklistScreen`/`PatientDetailsScreen` as the action is now handled internally by the dialog and `WorklistViewModel`. The dialog now dismisses itself upon starting a visit.
- The `StartVisitScreen` composable no longer accepts `onStartVisit` and `onDiscard` parameters, as these actions are now handled by the parent `StartVisitDialog`. The "Start Visit" and "Discard" buttons have been removed from `StartVisitScreen`.
- **Display Server Version in Settings:**
- Added a `serverVersion` field to `SettingsUiState`.
- The Settings screen now displays the server version under the "Server Configuration" section.
This commit introduces several UI improvements to the `PatientCard` and relocates the filtering functionality to the `MainScreen`.
**PatientCard Changes (`PatientCard.kt`):**
- **Avatar:** Added a circular avatar displaying the patient's initial.
- **Status Badge:** The status badge is now displayed next to the patient's name.
- **Actions Dropdown:** Replaced the "Start Visit" and "View Details" buttons with a three-dot menu (MoreVert icon) that reveals these actions in a `DropdownMenu`.
- **Visit Information:**
- The `PatientCard` now accepts an optional `visitInfo: VisitEntity?` parameter.
- If `visitInfo` is provided, it displays the visit type (e.g., "Community") and visit date, each preceded by an icon (Place and Event icons, respectively).
- If `visitInfo` is null, it displays "No visit details available".
- **Visual Styling:**
- Added a `Divider` to visually separate the main patient information from the visit details.
- Improved spacing and alignment for better readability.
- Used `MaterialTheme.colorScheme` for consistent theming.
- Added `@OptIn(ExperimentalMaterial3Api::class)` for Material 3 components.
**WorklistScreen Changes (`WorklistScreen.kt`):**
- **Removed Filter Section:** The `FilterSection` composable has been removed from `WorklistScreen`.
- **Passing Visit Info:** The `PatientCard` is now provided with `visitInfo` by finding the corresponding visit from `uiState.visits` based on `patient.id`.
- **Removed Local Filter State:** The local `filters` state and the `LaunchedEffect` that observed it have been removed. Filter logic is now handled globally.
- Added `@OptIn(ExperimentalMaterial3Api::class)` for Material 3 components.
**MainScreen Changes (`MainScreen.kt`):**
- **Global Filter Integration:**
- The `FilterSection` is now displayed within an `AlertDialog` in `MainScreen`.
- A "FilterList" icon button is added to the `TopAppBar` when the current route is the worklist. Clicking this button opens the filter dialog.
- The filter state (`filters`) is managed using `rememberSaveable` within `MainScreen`.
- `LaunchedEffect` is used to send filter changes to the `WorklistViewModel`.
- The filter dialog includes "Apply" and "Clear" buttons.
- **ViewModel Injection:** `WorklistViewModel` is now injected into `MainScreen` using `hiltViewModel()`.
- **TopAppBar Actions:** The logic for displaying actions in the `TopAppBar` (filter icon or general menu) is now based on the current route.
This commit introduces functionality to fetch and display the most recent visit for a patient and updates UI components to use `VisitWithDetails` for richer visit information.
Key changes:
- **`VisitDao`:** Added `getMostRecentVisitForPatient` query to retrieve the latest visit by `scheduledTime`.
- **`VisitRepository` & `VisitRepositoryImpl`:** Implemented `getMostRecentForVisitPatient` to expose the new DAO function.
- **`VisitUseCases`:** Added `getMostRecentVisitForPatient` use case.
- **`WorklistViewModel`:**
- Loads the most recent visit for a patient in `init` using `loadPatientMostRecentVisit`.
- Added `loadPatientVisits` to fetch all visits for a patient.
- **`WorklistUiState`:** Added `mostRecentVisit` of type `VisitWithDetails?`.
- **UI Updates:**
- `WorklistScreen`: Passes `uiState.mostRecentVisit` to `PatientCard`.
- `PatientCard`: Now accepts `VisitWithDetails?` and displays `visit.visit.type` and `visit.visit.date`.
- `PatientDetailsScreen`:
- Displays `state.mostRecentVisit` as the "Current Visit".
- Updates logic for `pastVisits` to correctly handle `VisitWithDetails`.
- `VisitCard` now correctly uses `visit.visit.id` as key.
- `VisitCard`: Updated to accept `VisitWithDetails?` and display details from `visit.visit.*`. Now also displays visit notes if available.
- `VisitDetailsDialog`: Updated to accept `VisitWithDetails` and displays details from `visit.visit.*`. Now also displays encounters associated with the visit.
- **Error Handling:** Improved error handling in `VisitRepositoryImpl` for database operations.
This commit introduces functionality to retrieve encounters associated with a specific patient and visit.
Key changes:
- **`VisitDao`**: Added `getEncountersByPatientIdAndVisitId` to query for encounters based on `patientId` and `visitId`.
- **`VisitRepository` & `VisitRepositoryImpl`**:
- Added `getEncountersByPatientIdAndVisitId` to the repository interface and its implementation.
- The implementation in `VisitRepositoryImpl` calls the new DAO method and wraps the result in a `Flow<Result<List<EncounterEntity>>>`, including error handling for database exceptions.
- **`VisitUseCases`**: Added `getEncountersByPatientIdAndVisitId` use case to expose the repository functionality.
- **`WorklistViewModel`**:
- Calls `getEncountersByPatientIdAndVisitId` after loading patient details and most recent visit information.
- Updates the UI state with the fetched encounters or any error messages.
- **`WorklistScreen`**: Modified to find the correct `visitInfo` for each `PatientCard` from the `uiState.visits` list based on `patient.id`.
- **`PatientCard`**: Changed the "Open Details" menu item text to "View Details".
This commit introduces several improvements to visit and encounter management, primarily focusing on form submission and display in the worklist.
Key changes:
- **Automatic Visit Creation/Association:**
- When submitting a form, the system now checks for an existing recent visit for the patient.
- If a recent visit exists, the new encounter is associated with it.
- If no recent visit is found, a new default "Community Visit" is created, and the encounter is linked to this new visit.
- `FormsUseCase` now includes `getMostRecentForVisitPatient` and `createADefault` (for visits).
- `FormRepository` and `FormRepositoryImpl` were updated to support these new visit-related operations.
- `QuestionnaireViewModel` now fetches the most recent visit on initialization and uses its ID or creates a new visit when submitting a form.
- **Form Name Display in EncounterCard:**
- `EncounterCard` now attempts to display the actual form name instead of just the form UUID.
- `WorklistViewModel` fetches all available forms and stores them in `WorklistUiState`.
- `EncounterCard` uses this list to look up the form name based on `encounter.encounterTypeUuid` (which is the form UUID).
- If the form name is not found, it falls back to displaying the UUID.
- **EncounterCard UI Enhancements:**
- `EncounterCard` is now expandable to show observation details.
- Added styling for better readability, including formatted dates for encounter and observation datetimes.
- **Improved Data Loading in WorklistViewModel:**
- `WorklistViewModel` now loads forms on initialization.
- When loading visits, it also updates the `encounters` in the UI state with the encounters from the first visit (if any).
- Removed redundant `showLoading()` call when loading a specific patient.
- **Type Safety and Navigation:**
- Ensured `formId` is non-null in `QuestionnaireViewModel` and `patientId` is passed correctly during navigation to `QuestionnaireScreen`.
- Made `formUuid` non-nullable in `EncounterEntity` and the domain `Encounter` model, as it's a required field.
- **Repository and UseCase Updates:**
- Added `getForms` to `VisitRepository`, `VisitRepositoryImpl`, and `VisitUseCases` to allow the worklist to fetch form metadata.
- Updated DI modules (`FormModule`, `WorklistModule`) to provide necessary DAO dependencies for the new repository methods.
- **Minor Fixes:**
- Added `FieldType.GROUP` mapping to `Questionnaire.QuestionnaireItemType.GROUP` in `FhirExtensions.kt`.
These changes streamline the form submission process by ensuring encounters are always associated with a visit and improve the user experience in the worklist by providing more context (form names) and details (expandable observations) for encounters.
This commit introduces significant improvements to the handling and display of patient vitals.
Key changes:
- **Expanded Vitals Model:**
- `VitalsEntity` (core module) and `Vitals` (domain model in worklist module) now include fields for:
- `bloodPressureSystolic` (Int)
- `bloodPressureDiastolic` (Int)
- `heartRate` (Int)
- `respirationRate` (Int)
- `spo2` (Int)
- `notes` (String)
- `weight` (Double)
- `height` (Double)
- `bmi` (Double)
- `muac` (Double)
- The `Vitals` domain model now uses `String` types for all fields to better align with UI input and allow for empty/null initial states, with appropriate default empty string values.
- **Improved Vitals Mapping:**
- `VisitMapper.kt` updated:
- `VitalsEntity.toDomain()`: Converts nullable numeric entity fields to non-null strings (empty if null) for the domain model.
- `Vitals.toEntity()`: Converts string domain fields to nullable numeric types for the entity, handling potential parsing errors (e.g., `toDoubleOrNull`, `toIntOrNull`). Empty strings are mapped to null.
- **Enhanced RecordVitalsScreen:**
- UI now uses the expanded `Vitals` model fields.
- Added input fields for all new vital signs.
- Integrated with `WorklistViewModel` to manage vitals state (`state.vitals`).
- Implemented `viewModel.updateVitals()` to update the state as users input data.
- BMI is now automatically calculated and updated in the ViewModel when weight or height changes.
- Added icons to input fields for better visual distinction (e.g., Thermostat for temperature, Heart for BP/HR).
- `RowPair` and `RowPairTwoFields` composables now accept an optional `icon` parameter.
- **Refined PatientDetailsScreen:**
- `VitalsInfo` composable now uses `FlowRow` to display vitals, allowing them to wrap if space is limited.
- Displays all the new vital signs if they are present (not blank).
- Improved formatting for BP (e.g., "BP: 120/80 mmHg").
- **EncounterCard Update:**
- `EncounterCard.kt` now correctly uses `encounter.formUuid` instead of `encounter.encounterTypeUuid` to find the form name.
- **Encounter Creation:**
- `QuestionnaireViewModel.kt` now passes `questionnaire.id` as `formUuid` when creating an `EncounterEntity`.
- `EncounterExtensions.toEncounterEntity` now accepts and uses `formUuid`.
- **WorklistViewModel:**
- Added `updateVitals(newVitals: Vitals)` function to update the `vitals` field in `WorklistUiState`.
This commit introduces several changes to improve how visit data is fetched and presented in the worklist and patient details screens.
Key changes:
- **Optimized Visit Data Fetching:**
- Added `getAllVisitsWithDetails()` to `VisitDao`, `VisitRepository`, `VisitRepositoryImpl`, and `VisitUseCases`. This allows fetching all visits with their details (encounters, vitals) in a single query, reducing database calls and improving performance.
- `WorklistViewModel` now calls `getAllVisitsWithDetails()` on initialization to load all visit data upfront. This data is then used to populate `PatientCard` and `PatientDetailsScreen`.
- **Improved `PatientCard`:**
- `PatientCard` now receives `allVisits: List<VisitWithDetails>` instead of a single `visitInfo: VisitWithDetails?`. It then finds the relevant visit for the current patient from this list. This avoids redundant data fetching per card.
- Updated `PatientCard` to safely access `visitInfo.visit.scheduledTime` for displaying the visit date.
- **Enhanced `PatientDetailsScreen`:**
- `PatientDetailsScreen` now displays all visits for a patient under "Visit History" instead of just past visits.
- Removed redundant "Previous Encounters" section as encounters are now displayed within their respective visit cards.
- **Simplified `EncounterCard`:**
- Removed the display of `encounterDatetime` and `obsDatetime` from `EncounterCard` to simplify the UI and reduce clutter.
- **ViewModel Adjustments:**
- `WorklistViewModel.loadPatientVisits()` was updated to reflect the new approach of loading all visits. It now primarily updates the `encounters` in the UI state based on the selected patient's visits.
These changes aim to streamline data loading, improve UI performance, and provide a more consistent display of visit information.
This commit introduces functionality for recording and managing patient vitals.
Key changes:
- **Vitals Data Model & DAO:**
- Created `VitalsEntity` to store vitals data, linked to both `VisitEntity` and `PatientEntity`.
- Added `VitalsDao` with methods to insert, retrieve by visit/patient, and delete vitals.
- Updated `AppDatabase` to include `VitalsDao`.
- **Repository & Use Case:**
- `PatientRepository` and `PatientRepositoryImpl` now include methods for saving and retrieving vitals (`saveVital`, `getVitalsByVisit`, `getVitalsByPatient`).
- `PatientsUseCase` exposes these vitals operations.
- **Vitals Recording UI:**
- Refactored `RecordVitalScreen.kt` into `RecordVitalDialog.kt` to display as a dialog.
- The dialog allows input for temperature, blood pressure, heart rate, respiration rate, SpO₂, notes, weight, height, and MUAC.
- BMI is auto-calculated.
- Basic validation ensures temperature, weight, and height are provided before saving.
- **Integration with Worklist:**
- Removed the dedicated `RecordVitalScreen` navigation from `worklistGraph.kt`. Vitals recording will now be part of a dialog flow.
- Added `OnVitalsChanged` and `SaveVitals` events to `WorklistEvent.kt`.
- `WorklistViewModel` is used to manage vitals state within the dialog.
- **Mapper Updates:**
- `VisitMapper.kt`: `Vitals.toEntity` now accepts `patientId`, generates a UUID for `id`, and sets `dateRecorded`.
- **Dependency Injection:**
- Updated `FormModule.kt` and `DatabaseModule.kt` to provide `VitalsDao` and inject it into `PatientRepositoryImpl`.
…ailsScreen
This commit introduces several improvements to how vitals are managed and displayed:
- **WorklistViewModel:**
- Added `getVitalsByPatient` and `getVitalsByVisit` functions to fetch vitals data.
- Implemented `saveVitals` to persist vitals, now called after `OnVitalsChanged` event.
- Updated `startPatientVisit` to use `orEmpty()` for safer access to nullable IDs.
- Integrated `toDomain` and `toEntity` mappers for `Vitals`.
- Initialized vitals loading for the most recent visit and selected patient in `init`.
- Standardized result handling in various data loading functions.
- **PatientDetailsScreen:**
- Now uses `state.vitalsEntity` (of type `VitalsEntity?`) instead of `state.vitals` (of type `Vitals?`) to display vitals information in `VitalsInfo`.
- Added a `RecordVitalDialog` triggered by the "New Vitals" FAB, which calls `WorklistEvent.OnVitalsChanged` and `WorklistEvent.SaveVitals` on save.
- Used `LaunchedEffect` to trigger `getVitalsByPatient` when the screen is composed.
- Changed `onAddVitals` FAB action to show `RecordVitalDialog`.
- **PatientsUseCase:**
- Ensured `saveVitals` has a return type (Unit).
- **PatientRepositoryImpl:**
- Modified `getVitalsByVisit` to return `Flow<Result<VitalsEntity>>` and use `map/catch` for Flow operations.
- Ensured `saveVital` has a return type (Unit).
- **VitalsDao:**
- Changed `getVitalsByVisit` to return `Flow<VitalsEntity?>`.
- Changed `insertVitals` to be a non-suspend function.
- Added `@Transaction` annotation to `getVitalsByVisit`, `deleteVitals`, and `deleteVitalsForPatient`.
- **WorklistUiState:**
- Added `vitalsEntity: VitalsEntity?` to store vitals data directly as the entity.
These changes streamline vitals data flow, ensure safer data access, and improve the user experience for recording vitals.
This commit streamlines data loading in the worklist and patient details screens. Key changes: - Removed an unnecessary initial call to `getVitalsByVisit` from `WorklistViewModel`'s `init` block. The vitals are now fetched reactively when the `mostRecentVisit` changes. - In `PatientDetailsScreen.kt`, `getVitalsByPatient` has been replaced with `getVitalsByVisit`. Vitals are now fetched using the `visitId` from `state.mostRecentVisit` when it becomes available or changes. This ensures vitals are loaded specifically for the relevant visit. - Removed redundant `showLoading()` and `hideLoading()` calls within the `loadPatients()` and `getPatientDetails()` methods in `WorklistViewModel`, simplifying the loading state management.
This commit addresses a potential crash when parsing the date of birth in `PatientDetailsScreen.kt`. - The `calculateAge` function now catches generic exceptions during date parsing and returns -1 as a fallback. - Corrected a minor typo in a null check for `vitals?.bloodPressureDiastolic` within the `VitalSignsSection`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.