diff --git a/designer_v2/lib/domain/study_monitoring.dart b/designer_v2/lib/domain/study_monitoring.dart index e80d27c7c..1f8bd6e41 100644 --- a/designer_v2/lib/domain/study_monitoring.dart +++ b/designer_v2/lib/domain/study_monitoring.dart @@ -20,6 +20,8 @@ class StudyMonitorItem extends Equatable { final bool droppedOut; final List> missedTasksPerDay; final List> completedTasksPerDay; + final int totalInterventionTasks; + final int totalSurveyTasks; const StudyMonitorItem({ required this.studySubject, @@ -36,6 +38,8 @@ class StudyMonitorItem extends Equatable { required this.droppedOut, required this.missedTasksPerDay, required this.completedTasksPerDay, + required this.totalInterventionTasks, + required this.totalSurveyTasks, }) : assert(missedTasksPerDay.length == currentDayOfStudy), assert(completedTasksPerDay.length == currentDayOfStudy); @@ -130,6 +134,20 @@ extension StudyMonitoringX on Study { final missedInterventions = totalInterventions - completedInterventions; final missedSurveys = totalSurveys - completedSurveys; + // Calculate total number of tasks for all interventions for this participant + final totalInterventionTasks = interventions + .where((i) => participant.selectedInterventionIds.contains(i.id)) + .map((i) => i.tasks.length) + .fold(0, (prev, element) => prev + element) * + schedule.phaseDuration * + schedule.numberOfCycles; + + //calculate the total number of surveys for this participant + final totalSurveyTasks = observations + .where((o) => requiredSurveyTaskIds.contains(o.id)) + .length * + schedule.length; + items.add( StudyMonitorItem( studySubject: participant, @@ -146,6 +164,8 @@ extension StudyMonitoringX on Study { droppedOut: participant.isDeleted, missedTasksPerDay: missedTasksPerDay, completedTasksPerDay: completedTasksPerDay, + totalInterventionTasks: totalInterventionTasks, + totalSurveyTasks: totalSurveyTasks, ), ); } diff --git a/designer_v2/lib/features/monitor/participant/participant_info.dart b/designer_v2/lib/features/monitor/participant/participant_info.dart index 3b67ad17e..6c65b20d3 100644 --- a/designer_v2/lib/features/monitor/participant/participant_info.dart +++ b/designer_v2/lib/features/monitor/participant/participant_info.dart @@ -44,11 +44,11 @@ class ParticipantInfo extends ConsumerWidget { ), _buildInfoRow( tr.monitoring_table_column_completed_interventions, - '${monitorItem.completedInterventions}/${monitorItem.completedInterventions + monitorItem.missedInterventions}', + '${monitorItem.completedInterventions}/${monitorItem.totalInterventionTasks}', ), _buildInfoRow( tr.monitoring_table_column_completed_surveys, - '${monitorItem.completedSurveys}/${monitorItem.completedSurveys + monitorItem.missedSurveys}', + '${monitorItem.completedSurveys}/${monitorItem.totalSurveyTasks}', ), ], ), diff --git a/designer_v2/lib/features/monitor/participant/participant_legend.dart b/designer_v2/lib/features/monitor/participant/participant_legend.dart index 190aad98a..cd2c8fcb4 100644 --- a/designer_v2/lib/features/monitor/participant/participant_legend.dart +++ b/designer_v2/lib/features/monitor/participant/participant_legend.dart @@ -16,27 +16,23 @@ class ParticipantLegend extends StatelessWidget { style: const TextStyle(fontWeight: FontWeight.bold), ), const SizedBox(height: 8.0), - Row( - children: [ - _buildLegendItem( - color: completeColor, - tr.participant_details_color_legend_completed, - tr.participant_details_completed_legend_tooltip, - ), - const SizedBox(width: 16.0), - _buildLegendItem( - color: partiallyCompleteColor, - tr.participant_details_color_legend_partially_completed, - tr.participant_details_partially_completed_legend_tooltip, - gradient: true, - ), - const SizedBox(width: 16.0), - _buildLegendItem( - color: incompleteColor, - tr.participant_details_color_legend_missed, - tr.participant_details_incomplete_legend_tooltip, - ), - ], + _buildLegendItem( + color: completeColor, + tr.participant_details_color_legend_completed, + tr.participant_details_completed_legend_tooltip, + ), + const SizedBox(height: 18.0), + _buildLegendItem( + color: partiallyCompleteColor, + tr.participant_details_color_legend_partially_completed, + tr.participant_details_partially_completed_legend_tooltip, + gradient: true, + ), + const SizedBox(height: 16.0), + _buildLegendItem( + color: incompleteColor, + tr.participant_details_color_legend_missed, + tr.participant_details_incomplete_legend_tooltip, ), const SizedBox(height: 16.0), Text( diff --git a/designer_v2/lib/features/monitor/study_monitor_page.dart b/designer_v2/lib/features/monitor/study_monitor_page.dart index cf0524ad5..b52d17208 100644 --- a/designer_v2/lib/features/monitor/study_monitor_page.dart +++ b/designer_v2/lib/features/monitor/study_monitor_page.dart @@ -26,9 +26,9 @@ class StudyMonitorScreen extends StudyPageWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _monitorSectionHeader(context, studyMonitorData), - const SizedBox(height: 32.0), if (studyMonitorData.isNotEmpty) ...[ + _monitorSectionHeader(context, studyMonitorData), + const SizedBox(height: 32.0), SelectableText( tr.monitoring_participants_title, style: Theme.of(context).textTheme.headlineSmall, @@ -58,7 +58,8 @@ class StudyMonitorScreen extends StudyPageWidget { ) { final theme = Theme.of(context); final int total = monitorData.length; - const double minPercentage = 0.01; // Minimum percentage for visibility + const double minPercentage = + 0; // Minimum percentage for visibility, change to 0.01 if min visibility is required. double activePercentage = monitorData.activeParticipants.length / total; double inactivePercentage = monitorData.inactiveParticipants.length / total; @@ -101,7 +102,7 @@ class StudyMonitorScreen extends StudyPageWidget { children: [ const Spacer(), SizedBox( - width: 400, + width: 450, child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ @@ -113,25 +114,25 @@ class StudyMonitorScreen extends StudyPageWidget { percentage: activePercentage, color: activeColor, tooltip: - '${tr.monitoring_active}: ${monitorData.activeParticipants.map((e) => e.participantId)}', + '${tr.monitoring_active}: ${monitorData.activeParticipants.map((e) => e.participantId).length}', ), _buildStat( percentage: inactivePercentage, color: inactiveColor, tooltip: - '${tr.monitoring_inactive}: ${monitorData.inactiveParticipants.map((e) => e.participantId)}', + '${tr.monitoring_inactive}: ${monitorData.inactiveParticipants.map((e) => e.participantId).length}', ), _buildStat( percentage: dropoutPercentage, color: dropoutColor, tooltip: - '${tr.monitoring_dropout}: ${monitorData.dropoutParticipants.map((e) => e.participantId)}', + '${tr.monitoring_dropout}: ${monitorData.dropoutParticipants.map((e) => e.participantId).length}', ), _buildStat( percentage: completedPercentage, color: completedColor, tooltip: - '${tr.monitoring_completed}: ${monitorData.completedParticipants.map((e) => e.participantId)}', + '${tr.monitoring_completed}: ${monitorData.completedParticipants.map((e) => e.participantId).length}', ), ], ), @@ -222,6 +223,7 @@ class StudyMonitorScreen extends StudyPageWidget { showModalSideSheet( context: context, title: tr.participant_details_title, + width: 550, body: ParticipantDetailsView( monitorItem: item, study: study, diff --git a/designer_v2/lib/features/monitor/study_monitor_table.dart b/designer_v2/lib/features/monitor/study_monitor_table.dart index 70fce141f..8c88c031d 100644 --- a/designer_v2/lib/features/monitor/study_monitor_table.dart +++ b/designer_v2/lib/features/monitor/study_monitor_table.dart @@ -28,8 +28,8 @@ class StudyMonitorTable extends ConsumerWidget { (a, b) => a.participantId.compareTo(b.participantId), (a, b) => a.inviteCode != null ? a.inviteCode!.compareTo(b.inviteCode!) : 0, - (a, b) => a.startedAt.compareTo(b.startedAt), - (a, b) => a.lastActivityAt.compareTo(b.lastActivityAt), + (a, b) => b.startedAt.compareTo(a.startedAt), + (a, b) => b.lastActivityAt.compareTo(a.lastActivityAt), (a, b) => a.currentDayOfStudy.compareTo(b.currentDayOfStudy), (a, b) => a.completedInterventions.compareTo(b.completedInterventions), (a, b) => a.completedSurveys.compareTo(b.completedSurveys), @@ -142,12 +142,12 @@ class StudyMonitorTable extends ConsumerWidget { _buildProgressCell( context, item.completedInterventions, - item.completedInterventions + item.missedInterventions, + item.totalInterventionTasks, ), _buildProgressCell( context, item.completedSurveys, - item.completedSurveys + item.missedSurveys, + item.totalSurveyTasks, ), ]; } diff --git a/designer_v2/lib/localization/app_de.arb b/designer_v2/lib/localization/app_de.arb index 2ecfbb00c..1638e2115 100644 --- a/designer_v2/lib/localization/app_de.arb +++ b/designer_v2/lib/localization/app_de.arb @@ -546,10 +546,10 @@ "participant_details_study_days_description": "Dieser Abschnitt bietet einen Überblick über die täglichen Aktivitäten des Teilnehmers in der Studie. Die Farblegende zeigt den Status der täglichen Aufgaben an. Bewege den Mauszeiger über die Studientage, um mehr Details über die tägliche Aktivität des Teilnehmers zu erfahren.", "participant_details_color_legend_title": "Legende", "participant_details_color_tooltip_legend_title": "Aktivitätsdetail Legende", - "participant_details_color_legend_completed_task": "Completed task", - "participant_details_color_legend_completed_task_tooltip": "The participant has completed this task", - "participant_details_color_legend_missed_task": "Missed task", - "participant_details_color_legend_missed_task_tooltip": "The participant has missed this task", + "participant_details_color_legend_completed_task": "Abgeschlossene Aufgabe", + "participant_details_color_legend_completed_task_tooltip": "Der Teilnehmer hat diese Aufgabe erledigt", + "participant_details_color_legend_missed_task": "Verpasste Aufgabe", + "participant_details_color_legend_missed_task_tooltip": "Der Teilnehmer hat diese Aufgabe verpasst", "participant_details_color_legend_completed": "Alle Aufgaben abgeschlossen", "participant_details_color_legend_partially_completed": "Einige Aufgaben unvollständig", "participant_details_color_legend_missed": "Alle Aufgaben verpasst", @@ -566,7 +566,7 @@ "monitoring_active_tooltip": "Anzahl der Teilnehmer, die derzeit in der Studie sind", "monitoring_inactive": "Inaktiv", "monitoring_inactive_tooltip": "Anzahl der Teilnehmer, die 3 Tage hintereinander keine Aktivität in der Studie gezeigt haben", - "monitoring_dropout": "Dropout", + "monitoring_dropout": "Abgebrochen", "monitoring_dropout_tooltip": "Anzahl der Teilnehmer, die die Studie vorzeitig abgebrochen haben oder für 5 Tage hintereinander keine Aktivität in der Studie gezeigt haben", "monitoring_completed": "Abgeschlossen", "monitoring_completed_tooltip": "Anzahl der Teilnehmer, die das Ende der Studie erreicht haben",