diff --git a/backend/controllers/trainingGroupController.js b/backend/controllers/trainingGroupController.js index 3a533825..0cdd36ab 100644 --- a/backend/controllers/trainingGroupController.js +++ b/backend/controllers/trainingGroupController.js @@ -32,8 +32,7 @@ export const updateTrainingGroup = async (req, res) => { try { const { authcode: userToken } = req.headers; const { clubId, groupId } = req.params; - const { name, sortOrder } = req.body; - const group = await trainingGroupService.updateTrainingGroup(userToken, clubId, groupId, name, sortOrder); + const group = await trainingGroupService.updateTrainingGroup(userToken, clubId, groupId, req.body); res.status(200).json(group); } catch (error) { console.error('[updateTrainingGroup] - Error:', error); diff --git a/backend/migrations/20260514_add_exclude_from_quick_diary_create_to_training_group.sql b/backend/migrations/20260514_add_exclude_from_quick_diary_create_to_training_group.sql new file mode 100644 index 00000000..ce990095 --- /dev/null +++ b/backend/migrations/20260514_add_exclude_from_quick_diary_create_to_training_group.sql @@ -0,0 +1,4 @@ +-- Trainingsgruppen vom Tagebuch-Schnellanlegen ausnehmen (optional) +ALTER TABLE training_group +ADD COLUMN exclude_from_quick_diary_create TINYINT(1) NOT NULL DEFAULT 0 +COMMENT '1 = Gruppe bei Schnellanlegen-Terminsuche ignorieren'; diff --git a/backend/models/TrainingGroup.js b/backend/models/TrainingGroup.js index 06946f7e..6031df78 100644 --- a/backend/models/TrainingGroup.js +++ b/backend/models/TrainingGroup.js @@ -38,7 +38,13 @@ const TrainingGroup = sequelize.define('TrainingGroup', { allowNull: false, defaultValue: 0, comment: 'Order for displaying groups' - } + }, + excludeFromQuickDiaryCreate: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + comment: 'If true, group is skipped when suggesting/creating diary dates via quick-create' + }, }, { tableName: 'training_group', underscored: true, diff --git a/backend/services/trainingGroupService.js b/backend/services/trainingGroupService.js index cce1d656..700a3241 100644 --- a/backend/services/trainingGroupService.js +++ b/backend/services/trainingGroupService.js @@ -159,9 +159,11 @@ class TrainingGroupService { return group; } - async updateTrainingGroup(userToken, clubId, groupId, name, sortOrder) { + async updateTrainingGroup(userToken, clubId, groupId, body = {}) { await checkAccess(userToken, clubId); - + + const { name, sortOrder, excludeFromQuickDiaryCreate } = body; + const group = await TrainingGroup.findOne({ where: { id: groupId, clubId }, }); @@ -169,25 +171,31 @@ class TrainingGroupService { throw new HttpError('Gruppe nicht gefunden', 404); } - // Preset-Gruppen können nicht umbenannt werden - if (group.isPreset && name !== group.name) { - throw new HttpError('Vorgaben-Gruppen können nicht umbenannt werden', 400); - } - - // Prüfe, ob bereits eine andere Gruppe mit diesem Namen existiert - if (name !== group.name) { - const existing = await TrainingGroup.findOne({ - where: { clubId, name, id: { [Op.ne]: groupId } }, - }); - if (existing) { - throw new HttpError('Eine Gruppe mit diesem Namen existiert bereits', 409); + if (name !== undefined && name !== null) { + // Preset-Gruppen können nicht umbenannt werden + if (group.isPreset && name !== group.name) { + throw new HttpError('Vorgaben-Gruppen können nicht umbenannt werden', 400); } + + if (name !== group.name) { + const existing = await TrainingGroup.findOne({ + where: { clubId, name, id: { [Op.ne]: groupId } }, + }); + if (existing) { + throw new HttpError('Eine Gruppe mit diesem Namen existiert bereits', 409); + } + } + group.name = name; } - group.name = name; - if (sortOrder !== undefined) { + if (sortOrder !== undefined && sortOrder !== null) { group.sortOrder = sortOrder; } + + if (excludeFromQuickDiaryCreate !== undefined) { + group.excludeFromQuickDiaryCreate = Boolean(excludeFromQuickDiaryCreate); + } + await group.save(); return group; } diff --git a/frontend/src/components/TrainingTimesTab.vue b/frontend/src/components/TrainingTimesTab.vue index b246218f..b39a0477 100644 --- a/frontend/src/components/TrainingTimesTab.vue +++ b/frontend/src/components/TrainingTimesTab.vue @@ -10,12 +10,22 @@ >

{{ group.name }}

- +
+ + +
@@ -165,7 +175,12 @@ export default { this.loading = true; try { const response = await apiClient.get(`/training-times/${this.currentClub}`); - this.groups = Array.isArray(response.data) ? response.data : []; + this.groups = Array.isArray(response.data) + ? response.data.map((g) => ({ + ...g, + excludeFromQuickDiaryCreate: Boolean(g.excludeFromQuickDiaryCreate), + })) + : []; } catch (error) { console.error('[loadTrainingTimes] Error:', error); const msg = getSafeErrorMessage(error, 'Fehler beim Laden der Trainingszeiten'); @@ -176,6 +191,23 @@ export default { } }, + async onExcludeQuickChange(group, event) { + const exclude = Boolean(event.target.checked); + try { + await apiClient.put(`/training-groups/${this.currentClub}/${group.id}`, { + name: group.name, + sortOrder: group.sortOrder, + excludeFromQuickDiaryCreate: exclude, + }); + group.excludeFromQuickDiaryCreate = exclude; + } catch (error) { + console.error('[onExcludeQuickChange]', error); + event.target.checked = !exclude; + const msg = getSafeErrorMessage(error, this.$t('trainingTimesTab.excludeFromQuickDiarySaveError')); + alert(msg); + } + }, + showAddTimeForm(groupId) { this.addTimeFormGroupId = groupId; this.newTime = { @@ -267,7 +299,8 @@ export default { getWeekdayName(weekday) { const days = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag']; - return days[weekday] || ''; + const i = Number(weekday); + return days[i] || ''; }, formatTime(time) { @@ -311,11 +344,37 @@ export default { .group-header { display: flex; + flex-wrap: wrap; justify-content: space-between; - align-items: center; + align-items: flex-start; + gap: 12px; margin-bottom: 16px; } +.group-header-actions { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 12px; +} + +.exclude-quick-diary-label { + display: inline-flex; + align-items: flex-start; + gap: 8px; + font-size: 0.85rem; + color: #444; + cursor: pointer; + margin: 0; + max-width: 22rem; + line-height: 1.35; +} + +.exclude-quick-diary-label input { + margin-top: 0.2rem; + flex-shrink: 0; +} + .group-header h3 { margin: 0; font-size: 1.2rem; diff --git a/frontend/src/i18n/locales/de-extended.json b/frontend/src/i18n/locales/de-extended.json index 827e779d..448ad606 100644 --- a/frontend/src/i18n/locales/de-extended.json +++ b/frontend/src/i18n/locales/de-extended.json @@ -2402,7 +2402,9 @@ "noTimes": "Keine Trainingszeiten definiert", "editTime": "Trainingszeit bearbeiten", "save": "Speichern", - "saveError": "Fehler beim Speichern der Trainingszeit" + "saveError": "Fehler beim Speichern der Trainingszeit", + "excludeFromQuickDiaryCreate": "Vom Schnellanlegen (Tagebuch) ausnehmen", + "excludeFromQuickDiarySaveError": "Die Einstellung konnte nicht gespeichert werden." }, "trainingGroupsTab": { "groups": "Gruppen", diff --git a/frontend/src/i18n/locales/de.json b/frontend/src/i18n/locales/de.json index 4723f8fd..15ea6fd7 100644 --- a/frontend/src/i18n/locales/de.json +++ b/frontend/src/i18n/locales/de.json @@ -2464,7 +2464,9 @@ "noTimes": "Keine Trainingszeiten definiert", "editTime": "Trainingszeit bearbeiten", "save": "Speichern", - "saveError": "Fehler beim Speichern der Trainingszeit" + "saveError": "Fehler beim Speichern der Trainingszeit", + "excludeFromQuickDiaryCreate": "Vom Schnellanlegen (Tagebuch) ausnehmen", + "excludeFromQuickDiarySaveError": "Die Einstellung konnte nicht gespeichert werden." }, "trainingGroupsTab": { "groups": "Gruppen", diff --git a/frontend/src/views/DiaryView.vue b/frontend/src/views/DiaryView.vue index 14c3d6e6..909fe116 100644 --- a/frontend/src/views/DiaryView.vue +++ b/frontend/src/views/DiaryView.vue @@ -1640,14 +1640,27 @@ export default { return `${y}-${m}-${day}`; }, + /** Wochentag aus API (0=So … 6=Sa) zuverlässig als Zahl – vermeidet Strict-===-Fehler bei String-Werten. */ + trainingWeekdayNumber(tt) { + if (tt == null || tt.weekday === undefined || tt.weekday === null) return NaN; + const w = Number(tt.weekday); + return Number.isFinite(w) ? w : parseInt(String(tt.weekday), 10); + }, + + trainingStartToMinutes(start) { + const s = String(start || '').trim(); + const base = s.length >= 5 ? s.substring(0, 5) : s; + const parts = base.split(':'); + if (parts.length < 2) return null; + const h = parseInt(parts[0], 10); + const m = parseInt(parts[1], 10); + if (!Number.isFinite(h) || !Number.isFinite(m)) return null; + return h * 60 + m; + }, + findNextQuickSlotAcrossGroups(groups) { if (!Array.isArray(groups) || groups.length === 0) return null; - const sorted = [...groups].sort((a, b) => { - const oa = Number.isFinite(Number(a.sortOrder)) ? Number(a.sortOrder) : 1e9; - const ob = Number.isFinite(Number(b.sortOrder)) ? Number(b.sortOrder) : 1e9; - if (oa !== ob) return oa - ob; - return (Number(a.id) || 0) - (Number(b.id) || 0); - }); + const eligible = groups.filter((g) => !g.excludeFromQuickDiaryCreate); const existing = new Set((this.dates || []).map((d) => this.diaryDateKey(d))); const today = new Date(); for (let dayOffset = 0; dayOffset <= 366; dayOffset++) { @@ -1655,19 +1668,37 @@ export default { const checkWeekday = checkDate.getDay(); const dateStr = this.localYyyyMmDd(checkDate); if (existing.has(dateStr)) continue; - for (const g of sorted) { - const times = (g.trainingTimes || []) - .filter((tt) => tt.weekday === checkWeekday && tt.startTime && String(tt.startTime).trim()); - if (!times.length) continue; - times.sort((a, b) => String(a.startTime).localeCompare(String(b.startTime)) - || (Number(a.id) || 0) - (Number(b.id) || 0)); - const time = times[0]; - return { - date: dateStr, - startTime: this.formatTimeForInput(time.startTime), - endTime: this.formatTimeForInput(time.endTime), - }; + const candidates = []; + for (const g of eligible) { + for (const tt of g.trainingTimes || []) { + if (this.trainingWeekdayNumber(tt) !== checkWeekday) continue; + if (!tt.startTime || !String(tt.startTime).trim()) continue; + const startMin = this.trainingStartToMinutes(tt.startTime); + if (startMin == null) continue; + candidates.push({ + startMin, + dateStr, + sortOrder: Number.isFinite(Number(g.sortOrder)) ? Number(g.sortOrder) : 1e9, + groupId: Number(g.id) || 0, + timeId: Number(tt.id) || 0, + startTime: this.formatTimeForInput(tt.startTime), + endTime: this.formatTimeForInput(tt.endTime), + }); + } } + if (!candidates.length) continue; + candidates.sort((a, b) => { + if (a.startMin !== b.startMin) return a.startMin - b.startMin; + if (a.sortOrder !== b.sortOrder) return a.sortOrder - b.sortOrder; + if (a.groupId !== b.groupId) return a.groupId - b.groupId; + return a.timeId - b.timeId; + }); + const best = candidates[0]; + return { + date: best.dateStr, + startTime: best.startTime, + endTime: best.endTime, + }; } return null; }, @@ -1848,7 +1879,7 @@ export default { const checkWeekday = checkDate.getDay(); // Finde Trainingszeiten für diesen Wochentag - const timesForWeekday = sortedTimes.filter(tt => tt.weekday === checkWeekday); + const timesForWeekday = sortedTimes.filter(tt => this.trainingWeekdayNumber(tt) === checkWeekday); if (timesForWeekday.length > 0) { // Nimm die erste Trainingszeit für diesen Tag diff --git a/mobile-app/composeApp/build.gradle.kts b/mobile-app/composeApp/build.gradle.kts index 6c050da8..b5f73f0c 100644 --- a/mobile-app/composeApp/build.gradle.kts +++ b/mobile-app/composeApp/build.gradle.kts @@ -58,8 +58,8 @@ android { applicationId = "de.tsschulz.tt_tagebuch" minSdk = libs.versions.android.minSdk.get().toInt() targetSdk = libs.versions.android.targetSdk.get().toInt() - versionCode = 2 - versionName = "1.0.1" + versionCode = 3 + versionName = "1.1.0" buildConfigField("String", "BACKEND_BASE_URL", "\"$backendBaseUrl\"") buildConfigField("String", "SOCKET_BASE_URL", "\"$socketBaseUrl\"") } diff --git a/mobile-app/composeApp/src/androidMain/kotlin/de/tsschulz/tt_tagebuch/app/ui/AppRoot.kt b/mobile-app/composeApp/src/androidMain/kotlin/de/tsschulz/tt_tagebuch/app/ui/AppRoot.kt index 329f082e..4ced2bdf 100644 --- a/mobile-app/composeApp/src/androidMain/kotlin/de/tsschulz/tt_tagebuch/app/ui/AppRoot.kt +++ b/mobile-app/composeApp/src/androidMain/kotlin/de/tsschulz/tt_tagebuch/app/ui/AppRoot.kt @@ -6573,29 +6573,63 @@ private fun localDateToJsWeekday(d: java.time.LocalDate): Int = java.time.DayOfWeek.SATURDAY -> 6 } -/** Nächster freier Kalendertag ab heute: erstes Datum ohne Tagebuch-Eintrag, dann erste passende Gruppe (Sortierung) mit Trainingszeit. */ +private fun trainingTimeStartToMinutes(start: String): Int? { + val t = start.trim().take(5) + val parts = t.split(':') + if (parts.size < 2) return null + val h = parts[0].toIntOrNull() ?: return null + val m = parts[1].toIntOrNull() ?: return null + return h * 60 + m +} + +/** Nächster freier Kalendertag: früheste Startzeit über alle nicht ausgeschlossenen Gruppen an diesem Wochentag (0=So … 6=Sa). */ private fun findNextQuickDiarySlotAcrossGroups( groups: List, existingDiaryDatesYyyyMmDd: Set, ): NextDiarySlotSuggestion? { - val sortedGroups = groups.sortedWith(compareBy { it.sortOrder }.thenBy { it.id }) + val eligible = groups.filter { !it.excludeFromQuickDiaryCreate } val today = java.time.LocalDate.now() for (offset in 0..366) { val check = today.plusDays(offset.toLong()) val wd = localDateToJsWeekday(check) val norm = check.toString().take(10) if (norm in existingDiaryDatesYyyyMmDd) continue - for (g in sortedGroups) { - val timesForDay = g.trainingTimes - .filter { it.weekday == wd && it.startTime.isNotBlank() } - .sortedWith(compareBy { it.startTime }.thenBy { it.id }) - val time = timesForDay.firstOrNull() ?: continue - return NextDiarySlotSuggestion( - date = norm, - trainingStart = time.startTime.trim().take(5), - trainingEnd = time.endTime.trim().take(5), - ) + data class SlotCand( + val startMin: Int, + val suggestion: NextDiarySlotSuggestion, + val groupOrder: Int, + val groupId: Int, + val timeId: Int, + ) + val cands = buildList { + for (g in eligible) { + for (time in g.trainingTimes) { + if (time.weekday != wd || time.startTime.isBlank()) continue + val sm = trainingTimeStartToMinutes(time.startTime) ?: continue + add( + SlotCand( + startMin = sm, + suggestion = NextDiarySlotSuggestion( + date = norm, + trainingStart = time.startTime.trim().take(5), + trainingEnd = time.endTime.trim().take(5), + ), + groupOrder = g.sortOrder, + groupId = g.id, + timeId = time.id, + ), + ) + } + } } + if (cands.isEmpty()) continue + val best = cands.minWith( + compareBy { it.startMin } + .thenBy { it.groupOrder } + .thenBy { it.groupId } + .thenBy { it.timeId }, + ) + return best.suggestion } return null } diff --git a/mobile-app/shared/src/commonMain/kotlin/de/tsschulz/tt_tagebuch/shared/api/models/TrainingGroupDtos.kt b/mobile-app/shared/src/commonMain/kotlin/de/tsschulz/tt_tagebuch/shared/api/models/TrainingGroupDtos.kt index c4f6fe30..620b9284 100644 --- a/mobile-app/shared/src/commonMain/kotlin/de/tsschulz/tt_tagebuch/shared/api/models/TrainingGroupDtos.kt +++ b/mobile-app/shared/src/commonMain/kotlin/de/tsschulz/tt_tagebuch/shared/api/models/TrainingGroupDtos.kt @@ -25,6 +25,7 @@ data class TrainingGroupDto( val clubId: Int? = null, val name: String = "", val sortOrder: Int = 0, + val excludeFromQuickDiaryCreate: Boolean = false, val isPreset: Boolean = false, val presetType: String? = null, val trainingTimes: List = emptyList(), diff --git a/mobile-app/shared/src/commonMain/kotlin/de/tsschulz/tt_tagebuch/shared/i18n/MobileStrings.kt b/mobile-app/shared/src/commonMain/kotlin/de/tsschulz/tt_tagebuch/shared/i18n/MobileStrings.kt index 59ddbda2..87540f68 100644 --- a/mobile-app/shared/src/commonMain/kotlin/de/tsschulz/tt_tagebuch/shared/i18n/MobileStrings.kt +++ b/mobile-app/shared/src/commonMain/kotlin/de/tsschulz/tt_tagebuch/shared/i18n/MobileStrings.kt @@ -2480,6 +2480,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -4967,6 +4969,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -7441,6 +7445,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -9915,6 +9921,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -12389,6 +12397,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -14863,6 +14873,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -17337,6 +17349,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -19811,6 +19825,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -22285,6 +22301,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -24759,6 +24777,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -27233,6 +27253,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -29707,6 +29729,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -32181,6 +32205,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -34655,6 +34681,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...", @@ -37129,6 +37157,8 @@ object MobileStrings { "trainingTimesTab.delete" to "Löschen", "trainingTimesTab.edit" to "Bearbeiten", "trainingTimesTab.editTime" to "Trainingszeit bearbeiten", + "trainingTimesTab.excludeFromQuickDiaryCreate" to "Vom Schnellanlegen (Tagebuch) ausnehmen", + "trainingTimesTab.excludeFromQuickDiarySaveError" to "Die Einstellung konnte nicht gespeichert werden.", "trainingTimesTab.friday" to "Freitag", "trainingTimesTab.from" to "Von:", "trainingTimesTab.loading" to "Lade Trainingszeiten...",