Verbessert die Lesbarkeit und Struktur des Codes in DiaryView.vue durch Anpassungen der Einrückungen und Formatierungen. Optimiert die Anzeige von Aktivitätsvisualisierungen und aktualisiert die Logik für die Eingabefelder, um die Benutzerfreundlichkeit zu erhöhen. Diese Änderungen tragen zur allgemeinen Verbesserung der Benutzeroberfläche und der Codequalität bei.
This commit is contained in:
@@ -8,7 +8,8 @@
|
||||
<option v-for="entry in dates" :key="entry.id" :value="entry">{{ getFormattedDate(entry.date) }}
|
||||
</option>
|
||||
</select>
|
||||
<button v-if="date && date !== 'new' && canDeleteCurrentDate" class="btn-secondary" @click="deleteCurrentDate">Datum löschen</button>
|
||||
<button v-if="date && date !== 'new' && canDeleteCurrentDate" class="btn-secondary"
|
||||
@click="deleteCurrentDate">Datum löschen</button>
|
||||
</label>
|
||||
</div>
|
||||
<div v-if="showForm && date === 'new'">
|
||||
@@ -55,7 +56,7 @@
|
||||
<ul>
|
||||
<li v-for="group in groups" :key="group.id">
|
||||
<span v-if="editingGroupId !== group.id" @click="editGroup(group.id)">{{ group.name
|
||||
}}</span>
|
||||
}}</span>
|
||||
<input v-else type="text" v-model="group.name" @blur="saveGroup(group)"
|
||||
@keyup.enter="saveGroup(group)" @keyup.esc="cancelEditGroup"
|
||||
style="display: inline;width:10em" />
|
||||
@@ -105,51 +106,61 @@
|
||||
<td>
|
||||
<span v-if="item.isTimeblock"><i>Zeitblock</i></span>
|
||||
<span v-else-if="editingActivityId === item.id">
|
||||
<div style="display: flex; gap: 5px; align-items: center; position: relative;">
|
||||
<input
|
||||
type="text"
|
||||
v-model="editingActivityText"
|
||||
<div
|
||||
style="display: flex; gap: 5px; align-items: center; position: relative;">
|
||||
<input type="text" v-model="editingActivityText"
|
||||
@input="onEditInputChangeText(item)"
|
||||
@keyup.enter="saveActivityEdit(item)"
|
||||
@keyup.esc="cancelActivityEdit"
|
||||
ref="activityInput"
|
||||
style="flex: 1;"
|
||||
/>
|
||||
<button @click="saveActivityEdit(item)" class="btn-primary" style="padding: 2px 8px; font-size: 12px;">✓</button>
|
||||
<button @click="cancelActivityEdit" class="btn-secondary" style="padding: 2px 8px; font-size: 12px;">✗</button>
|
||||
<div v-if="editShowDropdown && editSearchForId === item.id && editSearchResults.length" class="dropdown" style="max-height: 9.5em;">
|
||||
<div v-for="s in editSearchResults" :key="s.id" @click="chooseEditSuggestion(s, item)">
|
||||
<span v-if="s.code && s.code.trim() !== ''"><strong>[{{ s.name }}]</strong> </span>
|
||||
@keyup.esc="cancelActivityEdit" ref="activityInput"
|
||||
style="flex: 1;" />
|
||||
<button @click="saveActivityEdit(item)" class="btn-primary"
|
||||
style="padding: 2px 8px; font-size: 12px;">✓</button>
|
||||
<button @click="cancelActivityEdit" class="btn-secondary"
|
||||
style="padding: 2px 8px; font-size: 12px;">✗</button>
|
||||
<div v-if="editShowDropdown && editSearchForId === item.id && editSearchResults.length"
|
||||
class="dropdown" style="max-height: 9.5em;">
|
||||
<div v-for="s in editSearchResults" :key="s.id"
|
||||
@click="chooseEditSuggestion(s, item)">
|
||||
<span v-if="s.code && s.code.trim() !== ''"><strong>[{{
|
||||
s.name }}]</strong> </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<span v-else @click="startActivityEdit(item)" class="clickable activity-label"
|
||||
:title="item.predefinedActivity && item.predefinedActivity.name ? item.predefinedActivity.name : ''">
|
||||
<!-- Icon öffnet Rendering (falls vorhanden) oder Bild im Modal -->
|
||||
<span v-if="hasActivityVisual(item.predefinedActivity)"
|
||||
@click.stop="openActivityVisual(item.predefinedActivity)"
|
||||
class="image-icon"
|
||||
title="Bild/Zeichnung anzeigen">🖼️</span>
|
||||
{{ (item.predefinedActivity && item.predefinedActivity.code && item.predefinedActivity.code.trim() !== '')
|
||||
<span v-else @click="startActivityEdit(item)"
|
||||
class="clickable activity-label"
|
||||
:title="item.predefinedActivity && item.predefinedActivity.name ? item.predefinedActivity.name : ''">
|
||||
<!-- Icon öffnet Rendering (falls vorhanden) oder Bild im Modal -->
|
||||
<span v-if="hasActivityVisual(item.predefinedActivity)"
|
||||
@click.stop="openActivityVisual(item.predefinedActivity)"
|
||||
class="image-icon" title="Bild/Zeichnung anzeigen">🖼️</span>
|
||||
{{ (item.predefinedActivity && item.predefinedActivity.code &&
|
||||
item.predefinedActivity.code.trim() !== '')
|
||||
? item.predefinedActivity.code
|
||||
: (item.predefinedActivity ? item.predefinedActivity.name : item.activity) }}
|
||||
: (item.predefinedActivity ? item.predefinedActivity.name :
|
||||
item.activity) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ item.groupActivity ? item.groupActivity.name : '' }}</td>
|
||||
<td>
|
||||
{{ item.duration }}<span
|
||||
v-if="item.durationText && item.durationText.trim() !== ''"> ({{
|
||||
item.durationText }})</span>
|
||||
item.durationText }})</span>
|
||||
</td>
|
||||
<td>
|
||||
<button @click="toggleActivityMembers(item)" title="Teilnehmer zuordnen" class="person-btn">👤</button>
|
||||
<button @click="toggleActivityMembers(item)" title="Teilnehmer zuordnen"
|
||||
class="person-btn">👤</button>
|
||||
<button @click="removePlanItem(item.id)" class="trash-btn">🗑️</button>
|
||||
<div v-if="activityMembersOpenId === item.id" class="dropdown" style="max-height: 12em; padding: 0.25rem;">
|
||||
<div style="margin-bottom: 0.25rem; font-weight: 600;">Teilnehmer zuordnen</div>
|
||||
<div v-if="activityMembersOpenId === item.id" class="dropdown"
|
||||
style="max-height: 12em; padding: 0.25rem;">
|
||||
<div style="margin-bottom: 0.25rem; font-weight: 600;">Teilnehmer
|
||||
zuordnen</div>
|
||||
<div style="max-height: 9.5em; overflow-y: auto;">
|
||||
<label v-for="m in presentMembers" :key="m.id" style="display:flex; align-items:center; gap:0.5rem;">
|
||||
<input type="checkbox" :checked="isAssignedToActivity(item.id, m.id)" @change="toggleMemberForActivity(item.id, m.id, $event.target.checked)">
|
||||
<label v-for="m in presentMembers" :key="m.id"
|
||||
style="display:flex; align-items:center; gap:0.5rem;">
|
||||
<input type="checkbox"
|
||||
:checked="isAssignedToActivity(item.id, m.id)"
|
||||
@change="toggleMemberForActivity(item.id, m.id, $event.target.checked)">
|
||||
<span>{{ m.firstName }} {{ m.lastName }}</span>
|
||||
</label>
|
||||
</div>
|
||||
@@ -161,16 +172,18 @@
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<span class="activity-label" :title="(groupItem.groupPredefinedActivity && groupItem.groupPredefinedActivity.name) ? groupItem.groupPredefinedActivity.name : ''">
|
||||
<!-- Icon öffnet Rendering (falls vorhanden) oder Bild im Modal -->
|
||||
<span v-if="hasActivityVisual(groupItem.groupPredefinedActivity)"
|
||||
@click.stop="openActivityVisual(groupItem.groupPredefinedActivity)"
|
||||
class="image-icon"
|
||||
title="Bild/Zeichnung anzeigen">🖼️</span>
|
||||
|
||||
{{ (groupItem.groupPredefinedActivity && groupItem.groupPredefinedActivity.code && groupItem.groupPredefinedActivity.code.trim() !== '')
|
||||
<span class="activity-label"
|
||||
:title="(groupItem.groupPredefinedActivity && groupItem.groupPredefinedActivity.name) ? groupItem.groupPredefinedActivity.name : ''">
|
||||
<!-- Icon öffnet Rendering (falls vorhanden) oder Bild im Modal -->
|
||||
<span v-if="hasActivityVisual(groupItem.groupPredefinedActivity)"
|
||||
@click.stop="openActivityVisual(groupItem.groupPredefinedActivity)"
|
||||
class="image-icon" title="Bild/Zeichnung anzeigen">🖼️</span>
|
||||
|
||||
{{ (groupItem.groupPredefinedActivity &&
|
||||
groupItem.groupPredefinedActivity.code &&
|
||||
groupItem.groupPredefinedActivity.code.trim() !== '')
|
||||
? groupItem.groupPredefinedActivity.code
|
||||
: groupItem.groupPredefinedActivity.name }}
|
||||
: groupItem.groupPredefinedActivity.name }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ groupItem.groupsGroupActivity.name }}</td>
|
||||
@@ -193,11 +206,13 @@
|
||||
<div v-if="addtype === 'activity'" style="position: relative;">
|
||||
<input type="text" v-model="newPlanItem.activity"
|
||||
placeholder="Aktivität / Zeitblock" required
|
||||
@input="onNewItemInputChange"
|
||||
/>
|
||||
<div v-if="newItemShowDropdown && newItemSearchResults.length" class="dropdown" style="max-height: 9.5em;">
|
||||
<div v-for="s in newItemSearchResults" :key="s.id" @click="chooseNewItemSuggestion(s)">
|
||||
<span v-if="s.code && s.code.trim() !== ''"><strong>[{{ s.code }}]</strong> </span>{{ s.name }}
|
||||
@input="onNewItemInputChange" />
|
||||
<div v-if="newItemShowDropdown && newItemSearchResults.length"
|
||||
class="dropdown" style="max-height: 9.5em;">
|
||||
<div v-for="s in newItemSearchResults" :key="s.id"
|
||||
@click="chooseNewItemSuggestion(s)">
|
||||
<span v-if="s.code && s.code.trim() !== ''"><strong>[{{ s.code
|
||||
}}]</strong> </span>{{ s.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -211,9 +226,8 @@
|
||||
</td>
|
||||
<td v-else-if="addNewItem || addNewTimeblock"></td>
|
||||
<td v-if="(addNewItem || addNewTimeblock) && !addNewGroupActivity">
|
||||
<input type="text" v-model="newPlanItem.durationText"
|
||||
@input="calculateDuration" placeholder="z.B. 2x7 oder 3*5"
|
||||
style="width:10em" />
|
||||
<input type="text" v-model="newPlanItem.durationText" @input="calculateDuration"
|
||||
placeholder="z.B. 2x7 oder 3*5" style="width:10em" />
|
||||
<input type="number" v-model="newPlanItem.duration" placeholder="Minuten" />
|
||||
</td>
|
||||
<td v-else-if="addNewGroupActivity"></td>
|
||||
@@ -235,7 +249,8 @@
|
||||
<div v-if="accidents.length > 0">
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="clickable" @click="toggleActivitiesBox">Aktivitäten <span>{{ showActivitiesBox ? '-' : '+' }}</span></h3>
|
||||
<h3 class="clickable" @click="toggleActivitiesBox">Aktivitäten <span>{{ showActivitiesBox ? '-' :
|
||||
'+' }}</span></h3>
|
||||
<div v-if="showActivitiesBox" class="collapsible-box">
|
||||
<textarea v-model="newActivity"></textarea>
|
||||
<button @click="addActivity">Aktivität hinzufügen</button>
|
||||
@@ -244,9 +259,10 @@
|
||||
{{ activity.description }}
|
||||
</li>
|
||||
</ul>
|
||||
<multiselect v-model="selectedActivityTags" :options="availableTags" placeholder="Tags auswählen"
|
||||
label="name" track-by="id" multiple :close-on-select="true" @tag="addNewTag"
|
||||
@remove="removeActivityTag" :allow-empty="false" @keydown.enter.prevent="addNewTagFromInput" />
|
||||
<multiselect v-model="selectedActivityTags" :options="availableTags"
|
||||
placeholder="Tags auswählen" label="name" track-by="id" multiple :close-on-select="true"
|
||||
@tag="addNewTag" @remove="removeActivityTag" :allow-empty="false"
|
||||
@keydown.enter.prevent="addNewTagFromInput" />
|
||||
</div>
|
||||
<h3>Teilnehmer ({{ participants.length }})</h3>
|
||||
<ul>
|
||||
@@ -336,7 +352,8 @@
|
||||
<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 + ' '
|
||||
<option v-if="participants.indexOf(member.id) >= 0" :value="member.id">{{ member.firstName +
|
||||
' '
|
||||
+ member.lastName }}</option>
|
||||
</template>
|
||||
</select>
|
||||
@@ -348,12 +365,13 @@
|
||||
<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 +
|
||||
<li v-for="accident in accidents" :key="accident.id">{{ accident.firstName + ' ' + accident.lastName
|
||||
+
|
||||
': '
|
||||
+ accident.accident}}</li>
|
||||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Schnell hinzufügen Dialog -->
|
||||
<div v-if="showQuickAddDialog" class="modal-overlay" @click.self="closeQuickAddDialog">
|
||||
@@ -531,20 +549,20 @@ export default {
|
||||
},
|
||||
|
||||
isNewMemberValid() {
|
||||
return this.newMember.firstName.trim() !== '' &&
|
||||
(this.newMember.gender === 'male' || this.newMember.gender === 'female' || this.newMember.gender === 'diverse');
|
||||
return this.newMember.firstName.trim() !== '' &&
|
||||
(this.newMember.gender === 'male' || this.newMember.gender === 'female' || this.newMember.gender === 'diverse');
|
||||
},
|
||||
|
||||
canDeleteCurrentDate() {
|
||||
if (!this.date || this.date === 'new') return false;
|
||||
|
||||
|
||||
// Prüfe ob keine Inhalte vorhanden sind
|
||||
const hasTrainingPlan = this.trainingPlan && this.trainingPlan.length > 0;
|
||||
const hasParticipants = this.participants && this.participants.length > 0;
|
||||
const hasActivities = this.activities && this.activities.length > 0;
|
||||
const hasAccidents = this.accidents && this.accidents.length > 0;
|
||||
const hasNotes = this.notes && this.notes.length > 0;
|
||||
|
||||
|
||||
// Kann gelöscht werden wenn alle Listen leer sind
|
||||
return !hasTrainingPlan && !hasParticipants && !hasActivities && !hasAccidents && !hasNotes;
|
||||
},
|
||||
@@ -560,7 +578,7 @@ export default {
|
||||
// gerenderter Code / renderSpec
|
||||
if (pa.renderCode && pa.renderCode.trim() !== '') return true;
|
||||
if (pa.renderSpec && Object.keys(pa.renderSpec).length) return true;
|
||||
} catch (e) {}
|
||||
} catch (e) { }
|
||||
return false;
|
||||
},
|
||||
drawingDataFor(pa) {
|
||||
@@ -597,10 +615,10 @@ export default {
|
||||
if (this.isAuthenticated && this.currentClub) {
|
||||
const response = await apiClient.get(`/diary/${this.currentClub}`);
|
||||
this.dates = response.data.map(entry => ({ id: entry.id, date: entry.date }));
|
||||
|
||||
|
||||
// Automatisch das Datum mit den meisten Einträgen auswählen
|
||||
await this.autoSelectDateWithEntries();
|
||||
|
||||
|
||||
await this.loadTags();
|
||||
await this.loadPredefinedActivities();
|
||||
}
|
||||
@@ -613,7 +631,7 @@ export default {
|
||||
}
|
||||
|
||||
const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD Format
|
||||
|
||||
|
||||
// 1. Zuerst prüfe das heutige Datum
|
||||
const todayEntry = this.dates.find(date => date.date === today);
|
||||
if (todayEntry) {
|
||||
@@ -1411,7 +1429,7 @@ export default {
|
||||
this.playBellSound();
|
||||
} else {
|
||||
// Nach letzter Aktivität (Ende) nochmal Glocke
|
||||
try { this.calculateAllItemTimes(); } catch (e) {}
|
||||
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;
|
||||
@@ -1423,7 +1441,7 @@ export default {
|
||||
}
|
||||
}
|
||||
// Aktivitätszeiten (Startzeiten) aus Trainingsplan prüfen
|
||||
try { this.calculateAllItemTimes(); } catch (e) {}
|
||||
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))
|
||||
@@ -1457,7 +1475,7 @@ export default {
|
||||
|
||||
calculateIntermediateTimes() {
|
||||
// Stelle sicher, dass alle startTime-Werte aktuell sind
|
||||
try { this.calculateAllItemTimes(); } catch(e) {}
|
||||
try { this.calculateAllItemTimes(); } catch (e) { }
|
||||
if (!this.trainingPlan || this.trainingPlan.length === 0) {
|
||||
this.intermediateTimes = [];
|
||||
return;
|
||||
@@ -1480,7 +1498,7 @@ export default {
|
||||
const filtered = unique.filter(t => t !== normalizedStart);
|
||||
filtered.sort();
|
||||
this.intermediateTimes = filtered;
|
||||
|
||||
|
||||
},
|
||||
|
||||
async addAccident() {
|
||||
@@ -1522,10 +1540,10 @@ export default {
|
||||
durationText: item.durationText,
|
||||
groupId: item.groupId,
|
||||
});
|
||||
|
||||
|
||||
// Lade die Daten neu, um die Änderungen anzuzeigen
|
||||
await this.loadTrainingPlan();
|
||||
|
||||
|
||||
this.editingActivityId = null;
|
||||
this.editingActivityText = '';
|
||||
} catch (error) {
|
||||
@@ -1667,12 +1685,12 @@ export default {
|
||||
// Schnell hinzufügen Dialog Methoden
|
||||
openQuickAddDialog() {
|
||||
this.showQuickAddDialog = true;
|
||||
|
||||
|
||||
// Standard-Geburtsdatum: 01.01.(aktuelles Jahr - 10)
|
||||
const currentYear = new Date().getFullYear();
|
||||
const defaultBirthYear = currentYear - 10;
|
||||
const defaultBirthDate = `${defaultBirthYear}-01-01`;
|
||||
|
||||
|
||||
this.newMember = {
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
@@ -1702,7 +1720,7 @@ export default {
|
||||
const defaultBirthYear = currentYear - 10;
|
||||
birthDate = `${defaultBirthYear}-01-01`;
|
||||
}
|
||||
|
||||
|
||||
// Erstelle neues Mitglied
|
||||
const memberData = {
|
||||
firstName: this.newMember.firstName.trim(),
|
||||
@@ -1730,7 +1748,7 @@ export default {
|
||||
// Lade die aktualisierte Mitgliederliste
|
||||
const membersResponse = await apiClient.get(`/clubmembers/get/${this.currentClub}/false`);
|
||||
this.members = membersResponse.data;
|
||||
|
||||
|
||||
// Finde das neu erstellte Mitglied (das letzte in der Liste)
|
||||
const newMember = this.members[this.members.length - 1];
|
||||
|
||||
@@ -1904,7 +1922,11 @@ table {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
thead, tbody, tr, td, th {
|
||||
thead,
|
||||
tbody,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
@@ -1913,7 +1935,8 @@ td {
|
||||
}
|
||||
|
||||
/* Bearbeitungszelle soll relativer Kontext sein */
|
||||
.clickable, td > div[style*="position: relative"] {
|
||||
.clickable,
|
||||
td>div[style*="position: relative"] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -2070,7 +2093,8 @@ img {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.memberImage > div, .memberImage canvas {
|
||||
.memberImage>div,
|
||||
.memberImage canvas {
|
||||
/* falls Komponenten-Inhalt (Renderer) da ist, mittig zeigen */
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
|
||||
Reference in New Issue
Block a user