From d0b6e6f0acd0d07fad9a0fdf5e8c518d3c1316ba Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Tue, 17 Mar 2026 00:28:36 +0100 Subject: [PATCH] feat(DiaryView, i18n): improve diary overview with new readiness indicators and localization updates - Refactored the DiaryView to implement a tabbed overview for training day, details, and groups, enhancing user navigation. - Added a readiness panel to display the status of training day elements, including training window, participants, and open plan items. - Expanded the German localization file with new keys for readiness indicators and checklist items, improving the experience for German-speaking users. --- frontend/src/i18n/locales/de.json | 8 + frontend/src/views/DiaryView.vue | 380 +++++++++++++++++++++++++----- 2 files changed, 334 insertions(+), 54 deletions(-) diff --git a/frontend/src/i18n/locales/de.json b/frontend/src/i18n/locales/de.json index 685c559f..40940ab0 100644 --- a/frontend/src/i18n/locales/de.json +++ b/frontend/src/i18n/locales/de.json @@ -402,6 +402,7 @@ "createNewDate": "Neues Datum anlegen", "activeTrainingDay": "Aktiver Trainingstag", "trainingDaySection": "Trainingstag", + "trainingDayChecklist": "Abschlusscheck", "trainingStart": "Trainingsbeginn", "trainingEnd": "Trainingsende", "trainingWindow": "Trainingsfenster", @@ -446,6 +447,13 @@ "selectGroup": "Gruppe auswählen...", "activityPlaceholder": "Aktivität", "assignShort": "Zuordnen", + "statusReadyShort": "Bereit", + "statusOpenShort": "Offen", + "openPlanItemsLabel": "Plan-Status", + "openPlanItems": "{count} offen", + "unassignedPlanItems": "{count} offen", + "durationExampleLong": "z.B. 2x7 oder 3*5", + "durationExampleShort": "z.B. 2x7", "showImage": "Bild/Zeichnung anzeigen", "participants": "Teilnehmer", "searchParticipants": "Teilnehmer suchen", diff --git a/frontend/src/views/DiaryView.vue b/frontend/src/views/DiaryView.vue index 3af3ea87..840053ca 100644 --- a/frontend/src/views/DiaryView.vue +++ b/frontend/src/views/DiaryView.vue @@ -78,15 +78,34 @@
-
- -
+ + +
+
+
{{ $t('diary.activeTrainingDay') }}
@@ -114,15 +133,8 @@
-
- -
+
+
@@ -136,15 +148,8 @@
-
- -
+
+

{{ $t('diary.existingGroups') }}

@@ -249,6 +254,33 @@
{{ $t('diary.planEmptyState') }}
+
+
+ {{ $t('diary.trainingDayChecklist') }} +
+
+
+ {{ $t('diary.trainingWindow') }} + {{ Boolean(trainingStart || trainingEnd) ? $t('diary.statusReadyShort') : $t('diary.statusOpenShort') }} +
+
+ {{ $t('diary.participants') }} + {{ participants.length > 0 ? $t('diary.statusReadyShort') : $t('diary.statusOpenShort') }} +
+
+ {{ $t('diary.trainingPlan') }} + {{ trainingPlan.length > 0 ? $t('diary.statusReadyShort') : $t('diary.statusOpenShort') }} +
+
+ {{ $t('diary.openPlanItemsLabel') }} + + {{ openPlanItems.length === 0 + ? $t('diary.statusReadyShort') + : $t('diary.openPlanItems', { count: openPlanItems.length }) }} + +
+
+
@@ -296,7 +328,7 @@
- +
@@ -343,7 +375,7 @@
- +
@@ -449,20 +481,25 @@ ☰ {{ formatDisplayTime(item.startTime) }} - {{ $t('diary.timeblock') }} - - - 🖼️ - {{ (item.predefinedActivity && item.predefinedActivity.code && - item.predefinedActivity.code.trim() !== '') - ? item.predefinedActivity.code - : (item.predefinedActivity ? item.predefinedActivity.name : - item.activity) }} - +
+ {{ $t('diary.timeblock') }} + + + 🖼️ + {{ (item.predefinedActivity && item.predefinedActivity.code && + item.predefinedActivity.code.trim() !== '') + ? item.predefinedActivity.code + : (item.predefinedActivity ? item.predefinedActivity.name : + item.activity) }} + + + {{ getPlanItemStatus(item).label }} + +
@@ -540,6 +577,9 @@ ? groupItem.groupPredefinedActivity.code : groupItem.groupPredefinedActivity.name }} + + {{ getPlanItemStatus(groupItem).label }} +
{{ groupItem.groupsGroupActivity.name }} @@ -860,9 +900,7 @@ export default { addNewItem: false, addNewGroupActivity: false, addNewTimeblock: false, - showTrainingDayPanel: true, - showDetailsPanel: false, - showGroupsPanel: false, + activeOverviewPanel: 'trainingDay', editingGroupId: null, doMemberTagUpdates: true, showTagHistoryModal: false, @@ -1005,6 +1043,20 @@ export default { } return null; }, + openPlanItems() { + const result = []; + for (const item of this.trainingPlan || []) { + if (!item?.isTimeblock && this.getPlanItemStatus(item).key === 'open') { + result.push(item); + } + for (const groupItem of item.groupActivities || []) { + if (this.getPlanItemStatus(groupItem).key === 'open') { + result.push(groupItem); + } + } + } + return result; + }, filteredDiaryMembers() { const search = (this.participantSearchQuery || '').trim().toLowerCase(); @@ -1077,7 +1129,7 @@ export default { const hasPlan = this.trainingPlan.length > 0; const hasActivities = this.activities.length > 0; - if (hasTimes && hasParticipants && hasPlan) { + if (hasTimes && hasParticipants && hasPlan && this.openPlanItems.length === 0) { return this.$t('diary.statusReady'); } @@ -1095,6 +1147,9 @@ export default { const hasPlan = Array.isArray(this.trainingPlan) && this.trainingPlan.length > 0; return hasTimes && hasParticipants && hasPlan; }, + toggleOverviewPanel(panel) { + this.activeOverviewPanel = this.activeOverviewPanel === panel ? null : panel; + }, // Dialog Helper Methods async showInfo(title, message, details = '', type = 'info') { this.infoDialog = { @@ -1357,9 +1412,7 @@ export default { this.calculateIntermediateTimes(); this.initializeSortable(); await this.loadGroups(); - this.showTrainingDayPanel = !this.isDiaryDayConfigured(); - this.showDetailsPanel = false; - this.showGroupsPanel = false; + this.activeOverviewPanel = this.isDiaryDayConfigured() ? null : 'trainingDay'; this.startCheckingTime(); } else { this.newDate = ''; @@ -2965,6 +3018,32 @@ export default { const map = this.participantMapByMemberId || {}; return map[memberId]; }, + getPlanItemStatus(item) { + if (!item) { + return { key: 'open', label: this.$t('diary.statusOpenShort'), tone: 'open' }; + } + + if (item.isTimeblock) { + const groupActivities = item.groupActivities || []; + if (groupActivities.length === 0) { + return { key: 'open', label: this.$t('diary.statusOpenShort'), tone: 'open' }; + } + const allReady = groupActivities.every(groupItem => this.getPlanItemStatus(groupItem).key === 'ready'); + return allReady + ? { key: 'ready', label: this.$t('diary.statusReadyShort'), tone: 'ready' } + : { key: 'open', label: this.$t('diary.statusOpenShort'), tone: 'open' }; + } + + const assignedCount = item.groupPredefinedActivity + ? this.presentMembers.filter(member => this.isAssignedToGroupActivity(item.id, member.id)).length + : this.presentMembers.filter(member => this.isAssignedToActivity(item.id, member.id)).length; + + if (assignedCount > 0) { + return { key: 'ready', label: this.$t('diary.statusReadyShort'), tone: 'ready' }; + } + + return { key: 'open', label: this.$t('diary.statusOpenShort'), tone: 'open' }; + }, async toggleMemberForActivity(activityId, memberId, checked) { let participantId = this.participantIdForMember(memberId); @@ -3610,6 +3689,28 @@ form div { margin-bottom: 1rem; } +.diary-overview-switcher { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; +} + +.diary-overview-switch { + padding: 0.5rem 0.8rem; + border: 1px solid #cfdbe3; + border-radius: 999px; + background: #fff; + color: #315066; + font-weight: 600; + cursor: pointer; +} + +.diary-overview-switch.active { + background: #e6f0f6; + border-color: #9bb9cb; + color: #173042; +} + .diary-toggle-card { border: 1px solid #d9e4ec; border-radius: 12px; @@ -3622,22 +3723,38 @@ form div { display: flex; justify-content: space-between; align-items: center; - gap: 1rem; - padding: 0.95rem 1.15rem; + gap: 0.75rem; + padding: 0.65rem 0.9rem; background: transparent; border: none; cursor: pointer; text-align: left; } +.diary-toggle-head > div { + min-width: 0; + line-height: 1.2; +} + +.diary-toggle-head strong { + display: block; + margin-top: 0.1rem; + font-size: 0.98rem; + line-height: 1.2; +} + .diary-toggle-symbol { - font-size: 1.4rem; + font-size: 1.15rem; line-height: 1; color: #315066; } .diary-toggle-body { - padding: 0 1.15rem 1.1rem; + padding: 0 0.9rem 0.9rem; +} + +.diary-toggle-body-open { + padding-top: 0.9rem; } .diary-groups-grid { @@ -4380,7 +4497,8 @@ img { } .diary-workspace-copy h3 { - margin: 0.2rem 0 0.35rem; + margin: 0.1rem 0 0.25rem; + font-size: 1.15rem; } .diary-workspace-label { @@ -4393,6 +4511,7 @@ img { .diary-workspace-status { margin: 0; + font-size: 0.92rem; color: #45606f; } @@ -4426,6 +4545,91 @@ img { color: #173042; } +@media (min-width: 769px) and (max-width: 1100px) { + .diary-overview-panels { + display: grid; + grid-template-columns: 1fr; + gap: 0.65rem; + margin-bottom: 0.8rem; + } + + .diary-overview-switcher { + gap: 0.4rem; + } + + .diary-overview-switch { + padding: 0.42rem 0.68rem; + font-size: 0.9rem; + } + + .diary-toggle-card { + border-radius: 10px; + } + + .diary-toggle-head { + gap: 0.7rem; + padding: 0.7rem 0.85rem; + } + + .diary-toggle-body { + padding: 0 0.85rem 0.8rem; + } + + .diary-general-label { + font-size: 0.72rem; + } + + .diary-toggle-head strong { + display: block; + font-size: 0.95rem; + line-height: 1.25; + } + + .diary-toggle-symbol { + font-size: 1.1rem; + } + + .diary-workspace-header { + gap: 0.75rem; + margin-bottom: 0; + padding: 0.75rem 0.85rem; + border-radius: 10px; + } + + .diary-workspace-copy h3 { + font-size: 1rem; + } + + .diary-workspace-status { + font-size: 0.88rem; + } + + .diary-workspace-stats { + grid-template-columns: repeat(2, minmax(92px, 1fr)); + gap: 0.5rem; + width: 100%; + } + + .diary-stat-card { + padding: 0.6rem 0.7rem; + border-radius: 8px; + } + + .diary-stat-label { + font-size: 0.68rem; + } + + .diary-stat-value { + margin-top: 0.15rem; + font-size: 0.92rem; + } + + .diary-groups-grid { + grid-template-columns: 1fr; + gap: 0.75rem; + } +} + .participant-toolbar { display: flex; flex-direction: column; @@ -4612,6 +4816,13 @@ img { padding-left: 0.75rem; } +.plan-activity-main { + display: flex; + align-items: center; + gap: 0.45rem; + flex-wrap: wrap; +} + .plan-type-badge { display: inline-flex; align-items: center; @@ -4638,6 +4849,63 @@ img { font-size: 0.84rem; } +.plan-status-badge { + display: inline-flex; + align-items: center; + border-radius: 999px; + padding: 0.1rem 0.45rem; + font-size: 0.72rem; + font-weight: 700; +} + +.plan-status-badge-ready { + background: #e9f3e6; + color: #245037; +} + +.plan-status-badge-open { + background: #fff2d9; + color: #7a5a12; +} + +.diary-readiness-panel { + margin-bottom: 1rem; + padding: 0.9rem 1rem; + border: 1px solid #d9e4ec; + border-radius: 10px; + background: #f8fbfd; +} + +.diary-readiness-header { + margin-bottom: 0.75rem; +} + +.diary-readiness-grid { + display: grid; + grid-template-columns: repeat(4, minmax(120px, 1fr)); + gap: 0.75rem; +} + +.diary-readiness-item { + padding: 0.7rem 0.8rem; + border-radius: 8px; + background: #fff2d9; + color: #7a5a12; +} + +.diary-readiness-item.ready { + background: #e9f3e6; + color: #245037; +} + +.diary-readiness-item span { + display: block; + font-size: 0.76rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.03em; +} + .plan-editor { margin-bottom: 1rem; padding: 0.95rem 1rem; @@ -4795,6 +5063,10 @@ img { grid-template-columns: 1fr; } + .diary-readiness-grid { + grid-template-columns: 1fr 1fr; + } + .plan-assignment-list { grid-template-columns: 1fr; }