Merge branch 'main' of ssh://tsschulz.de:/home/git/trainingstagebuch

This commit is contained in:
Torsten Schulz (server)
2025-09-01 09:23:26 +00:00

View File

@@ -311,30 +311,30 @@
<div v-if="showImage" class="memberImage">
<img :src="imageUrl" @click="closeImage" />
</div>
</div>
<div v-if="showAccidentForm" class="accidentForm">
<form @submit.prevent="submitAccident">
<div>
<label for="memberId">Mitglied:</label>
<select id="memberId" v-model="accident.memberId">
<template v-for="member in members" :key="member.id" :value="member.id">
<option v-if="participants.indexOf(member.id) >= 0" :value="member.id">{{ member.firstName + ' '
+ member.lastName }}</option>
</template>
</select>
</div>
<div>
<label for="accident">Unfall:</label>
<textarea id="accident" v-model="accident.accident" required></textarea>
</div>
<button type="button" @click="saveAccident">Eintragen</button>
<button type="button" @click="closeAccidentForm">Schießen</button>
<ul>
<li v-for="accident in accidents" :key="accident.id">{{ accident.firstName + ' ' + accident.lastName +
': '
+ accident.accident}}</li>
</ul>
</form>
<div v-if="showAccidentForm" class="accidentForm">
<form @submit.prevent="submitAccident">
<div>
<label for="memberId">Mitglied:</label>
<select id="memberId" v-model="accident.memberId">
<template v-for="member in members" :key="member.id" :value="member.id">
<option v-if="participants.indexOf(member.id) >= 0" :value="member.id">{{ member.firstName + ' '
+ member.lastName }}</option>
</template>
</select>
</div>
<div>
<label for="accident">Unfall:</label>
<textarea id="accident" v-model="accident.accident" required></textarea>
</div>
<button type="button" @click="saveAccident">Eintragen</button>
<button type="button" @click="closeAccidentForm">Schießen</button>
<ul>
<li v-for="accident in accidents" :key="accident.id">{{ accident.firstName + ' ' + accident.lastName +
': '
+ accident.accident}}</li>
</ul>
</form>
</div>
</div>
</template>
@@ -398,9 +398,12 @@ export default {
tagHistoryMember: null,
tagHistory: null,
intermediateTimes: [],
bellSound: new Audio('/sound/bell-123742.mp3'),
thumbSound: new Audio('/sound/thump-105302.mp3'),
bellSound: null,
thumbSound: null,
soundEnabled: true,
debugSound: true,
timeChecker: null,
playedActivityMarks: [],
showAccidentForm: false,
accident: {
memberId: '',
@@ -465,6 +468,8 @@ export default {
}
},
async refreshDates(selectId) {
const response = await apiClient.get(`/diary/${this.currentClub}`);
this.dates = response.data.map(entry => ({ id: entry.id, date: entry.date }));
@@ -592,7 +597,7 @@ export default {
const response = await apiClient.get(`/group/${this.currentClub}/${this.date.id}`);
this.groups = response.data;
} catch (error) {
console.log(error);
// ignore
}
},
@@ -1168,6 +1173,7 @@ export default {
if (this.timeChecker) clearInterval(this.timeChecker);
this.timeChecker = setInterval(() => {
const currentTime = new Date().toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
// Zeit-Check Tick
if (!this.trainingStart || !this.trainingEnd) {
return;
}
@@ -1183,40 +1189,80 @@ export default {
}
if (startCheckTime && currentTime === startCheckTime) {
this.playBellSound();
}
if (endCheckTime && currentTime === endCheckTime) {
} else if (endCheckTime && currentTime === endCheckTime) {
this.playBellSound();
} else {
// Nach letzter Aktivität (Ende) nochmal Glocke
try { this.calculateAllItemTimes(); } catch (e) {}
const items = Array.isArray(this.trainingPlan) ? this.trainingPlan : [];
const lastItem = items.length ? items[items.length - 1] : null;
const lastEnd = lastItem && lastItem.endTime ? lastItem.endTime : null;
const lastEndSS = lastEnd ? (lastEnd.length === 5 ? lastEnd + ':00' : lastEnd) : null;
const lastEndMM = lastEndSS ? lastEndSS.slice(0, 5) : null;
const currentHHMM = currentTime.slice(0, 5);
if (lastEndSS && (currentTime === lastEndSS || (currentTime.endsWith(':00') && currentHHMM === lastEndMM))) {
this.playBellSound();
}
}
if (this.intermediateTimes.includes(currentTime)) {
// Aktivitätszeiten (Startzeiten) aus Trainingsplan prüfen
try { this.calculateAllItemTimes(); } catch (e) {}
const items = Array.isArray(this.trainingPlan) ? this.trainingPlan : [];
const startTimesSS = items
.map(it => (it && it.startTime ? (it.startTime.length === 5 ? it.startTime + ':00' : it.startTime) : null))
.filter(Boolean);
const startTimesMM = startTimesSS.map(t => t.slice(0, 5));
const currentHHMM = currentTime.slice(0, 5);
const isMatch = startTimesSS.includes(currentTime) || (currentTime.endsWith(':00') && startTimesMM.includes(currentHHMM));
if (isMatch) {
this.playThumbSound();
}
}, 1000);
},
playBellSound() {
this.bellSound.play();
if (!this.soundEnabled) return;
try {
this.bellSound && this.bellSound.play();
} catch (e) {
// ignore
}
},
playThumbSound() {
this.thumbSound.play();
if (!this.soundEnabled) return;
try {
this.thumbSound && this.thumbSound.play();
} catch (e) {
// ignore
}
},
calculateIntermediateTimes() {
// Stelle sicher, dass alle startTime-Werte aktuell sind
try { this.calculateAllItemTimes(); } catch(e) {}
if (!this.trainingPlan || this.trainingPlan.length === 0) {
this.intermediateTimes = [];
return;
}
let times = [];
let currentTime = new Date("2025-01-01 " + this.trainingStart);
this.trainingPlan.forEach(item => {
const rawItem = JSON.parse(JSON.stringify(item));
currentTime.setMinutes(currentTime.getMinutes() + item.duration);
times.push(currentTime.toTimeString({ hours: '2-digit', minutes: '2-digit', seconds: '2-digit' }).slice(0, 8));
});
times = [...new Set(times)].sort();
this.intermediateTimes = times.filter(time =>
time !== this.trainingStart && time !== this.trainingEnd
);
function withSeconds(hhmm) {
if (!hhmm) return null;
const parts = hhmm.split(':');
if (parts.length < 3) return hhmm + ':00';
return hhmm;
}
const times = [];
for (const item of this.trainingPlan) {
if (item && item.startTime) {
const t = withSeconds(item.startTime);
if (t) times.push(t);
}
}
const normalizedStart = withSeconds(this.trainingStart);
const unique = Array.from(new Set(times));
const filtered = unique.filter(t => t !== normalizedStart);
filtered.sort();
this.intermediateTimes = filtered;
},
async addAccident() {
@@ -1402,6 +1448,14 @@ export default {
},
async mounted() {
await this.init();
// Versuche, Audio erst bei Nutzerinteraktion zu initialisieren (Autoplay-Policy)
const tryInit = () => {
if (!this.bellSound) this.bellSound = new Audio('/sound/bell-123742.mp3');
if (!this.thumbSound) this.thumbSound = new Audio('/sound/thump-105302.mp3');
this.soundEnabled = true;
window.removeEventListener('click', tryInit, { once: true });
};
window.addEventListener('click', tryInit, { once: true });
},
beforeUnmount() {
if (this.timeChecker) {