Enhance DiaryView with mobile and desktop tab navigation improvements

This commit refines the DiaryView component by implementing a responsive tab navigation system for both mobile and desktop views. It introduces new CSS styles for better layout management and user interaction, ensuring a seamless experience when switching between 'Teilnehmer' and 'Aktivitäten' sections. The active tab state is now visually indicated, improving usability across devices.
This commit is contained in:
Torsten Schulz (local)
2025-11-13 17:39:38 +01:00
parent 8d17cad299
commit 58e773e51e

View File

@@ -54,7 +54,7 @@
<button type="submit">Zeiten aktualisieren</button>
</form>
</div>
<div v-if="date !== 'new' && date !== null" style="overflow: visible">
<div v-if="date !== 'new' && date !== null" class="diary-content">
<!-- Tab-Navigation für Mobile -->
<div class="mobile-tabs">
<button
@@ -385,14 +385,16 @@
</tr>
</tbody>
</table>
<button v-if="trainingPlan && trainingPlan.length && trainingPlan.length > 0"
@click="generatePDF">Als PDF
herunterladen</button>
<div style="margin-top: 1rem; margin-bottom: 2rem; padding-bottom: 1rem;">
<button v-if="trainingPlan && trainingPlan.length && trainingPlan.length > 0"
@click="generatePDF">Als PDF
herunterladen</button>
</div>
</div>
</div>
<div class="column mobile-sidebar" :class="{ 'mobile-tab-content': true, 'active': activeTab === 'members' || activeTab === 'activities' }" style="padding-bottom:4em">
<!-- Mobile: Nur Mitglieder-Tab -->
<div class="mobile-tab-section" v-show="activeTab === 'members'">
<div class="mobile-tab-section" :class="{ 'active': activeTab === 'members' }" v-show="activeTab === 'members'">
<div>
<button @click="addAccident">Unfall buchen</button>
<div v-if="accidents.length > 0">
@@ -446,6 +448,96 @@
<div class="add-participant">
<button @click="openQuickAddDialog" class="quick-add-btn">+ Schnell hinzufügen</button>
</div>
</div>
<!-- Mobile: Nur Aktivitäten-Tab -->
<div class="mobile-tab-section" :class="{ 'active': activeTab === 'activities' }" v-show="activeTab === 'activities'">
<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>
<ul>
<li v-for="activity in activities" :key="activity.id">
{{ 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" />
</div>
</div>
<!-- Desktop: Beide Bereiche immer sichtbar -->
<div class="desktop-sidebar">
<div>
<button @click="addAccident">Unfall buchen</button>
<div v-if="accidents.length > 0">
</div>
</div>
<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>
<ul>
<li v-for="activity in activities" :key="activity.id">
{{ 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" />
</div>
<h3>Teilnehmer ({{ participants.length }})</h3>
<ul>
<li v-for="member in sortedMembers()" :key="member.id" class="checkbox-item participant-row"
:class="{
'row-inactive': !member.active,
'row-test': member.testMembership && !member.memberFormHandedOver,
'row-test-form': member.testMembership && member.memberFormHandedOver
}">
<label class="checkbox-label">
<input type="checkbox" :value="member.id" @change="toggleParticipant(member.id)"
:checked="isParticipant(member.id)">
</label>
<span class="clickable participant-name" @click.stop="openNotesModal(member)">
<span v-if="member && member.testMembership && member.trainingParticipations >= 6" class="warning-icon warning-icon-severe" title="6 oder mehr Trainingsteilnahmen">🛑</span>
<span v-else-if="member && member.testMembership && member.trainingParticipations >= 3" class="warning-icon" title="3 oder mehr Trainingsteilnahmen"></span>
{{
member ? member.firstName : ''
}} {{
member ? member.lastName : ''
}}
</span>
<div class="participant-actions">
<!-- Gruppenzuordnung für aktive Teilnehmer -->
<select v-if="isParticipant(member.id) && groups.length > 0"
:value="getMemberGroup(member.id)"
@change="updateMemberGroup(member.id, $event.target.value)"
@input="updateMemberGroup(member.id, $event.target.value)"
style="margin-left: 10px; font-size: 8px; width: 5em;">
<option value="">-</option>
<option v-for="group in groups" :key="group.id" :value="String(group.id)">
{{ group.name }}
</option>
</select>
<span v-if="false" @click="openNotesModal(member)" class="clickable">📝</span>
<span @click="showPic(member)" class="img-icon" v-if="member.hasImage">&#x1F5BC;</span>
<span v-if="member.testMembership === true && member.memberFormHandedOver !== true"
@click.stop="markFormHandedOver(member)"
class="pointer form-handover-icon"
title="Mitgliedsformular ausgehändigt">
📄
</span>
<span class="pointer" @click="openTagInfos(member)"></span>
</div>
</li>
</ul>
<div class="add-participant">
<button @click="openQuickAddDialog" class="quick-add-btn">+ Schnell hinzufügen</button>
</div>
</div>
</div>
</div>
</div>
@@ -3427,7 +3519,157 @@ img {
flex: 1;
}
/* Tab-Navigation für Mobile */
.mobile-tabs {
display: none;
width: 100%;
border-bottom: 2px solid #ddd;
margin-bottom: 1rem;
background: #f5f5f5;
position: sticky;
top: 0;
z-index: 100;
}
.tab-button {
flex: 1;
padding: 0.75rem 1rem;
border: none;
background: transparent;
cursor: pointer;
font-size: 1rem;
border-bottom: 3px solid transparent;
transition: all 0.3s ease;
color: #666;
}
.tab-button:hover {
background: #e9e9e9;
color: #333;
}
.tab-button.active {
border-bottom-color: #007bff;
color: #007bff;
font-weight: 600;
background: white;
}
/* Mobile Tab Content */
.mobile-tab-content {
display: block;
}
.mobile-tab-section {
display: block;
}
.desktop-sidebar {
display: block;
}
/* Diary Content Container */
.diary-content {
overflow: visible;
}
/* Responsive Design */
@media (max-width: 768px) {
.mobile-tabs {
display: flex;
}
.diary-content {
overflow: visible;
padding-bottom: 2rem;
}
/* Sicherstellen, dass Tab-Content genug Platz am Ende hat */
.column.mobile-tab-content.active {
padding-bottom: 3rem;
}
.columns {
flex-direction: column;
width: 100%;
overflow: visible;
}
.column {
width: 100%;
max-width: 100%;
overflow: visible;
}
.column.mobile-tab-content {
display: none;
}
.column.mobile-tab-content.active {
display: block;
}
.mobile-sidebar .desktop-sidebar {
display: none !important;
}
.mobile-sidebar .mobile-tab-section {
display: block;
}
/* Besseres Scrollen - nur eine Haupt-Scrollbar */
.diary {
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
height: 100vh;
}
.columns {
overflow: visible;
}
.column:first-child {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
overflow-y: visible;
}
.column:last-child {
overflow: visible;
}
/* Tabelle horizontal scrollbar nur wenn nötig */
table {
display: block;
overflow-x: auto;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
overflow-y: visible;
}
table thead,
table tbody,
table tr {
display: table;
width: 100%;
table-layout: fixed;
}
/* Teilnehmerliste ohne eigene Scrollbar - nutzt Haupt-Scroll */
.mobile-tab-section ul {
overflow: visible;
}
/* Tab-Content ohne eigene Scrollbar */
.mobile-tab-content {
overflow: visible;
}
.mobile-tab-section {
overflow: visible;
}
.notes-body {
flex-direction: column;
}
@@ -3437,6 +3679,43 @@ img {
height: auto;
max-height: 300px;
}
/* Header Row anpassen */
.diary-header-row {
flex-direction: column;
align-items: stretch;
}
.diary-header-row label {
width: 100%;
}
.diary-header-row button {
width: 100%;
margin-top: 0.5rem;
}
}
@media (min-width: 769px) {
.mobile-tabs {
display: none !important;
}
.mobile-tab-section {
display: none !important;
}
.desktop-sidebar {
display: block !important;
}
.column.mobile-tab-content {
display: block !important;
}
.mobile-sidebar .desktop-sidebar {
display: block !important;
}
}
/* Render Container */