Entfernt die PDF-Datei 9_code_list_1759357969975.pdf und implementiert eine Sidebar-Toggle-Funktionalität in App.vue. Die Sidebar kann nun auf mobilen Geräten ein- und ausgeklappt werden, um die Benutzeroberfläche zu optimieren. Zudem wurden Titelattribute zu Navigationslinks hinzugefügt, um die Benutzerfreundlichkeit zu verbessern. Der Vuex-Store wurde aktualisiert, um den Zustand der Sidebar zu speichern und zu verwalten.
This commit is contained in:
@@ -10,7 +10,11 @@
|
||||
</header>
|
||||
|
||||
<div class="app-container">
|
||||
<aside v-if="isAuthenticated" class="sidebar">
|
||||
<aside v-if="isAuthenticated" class="sidebar" :class="{ 'sidebar-collapsed': sidebarCollapsed }">
|
||||
<button class="sidebar-toggle" @click="toggleSidebar">
|
||||
<span v-if="sidebarCollapsed">→</span>
|
||||
<span v-else>←</span>
|
||||
</button>
|
||||
<div class="sidebar-content">
|
||||
<div class="club-selector card">
|
||||
<h3 class="card-title">Verein auswählen</h3>
|
||||
@@ -29,19 +33,19 @@
|
||||
<nav v-if="selectedClub" class="nav-menu">
|
||||
<div class="nav-section">
|
||||
<h4 class="nav-title">Verwaltung</h4>
|
||||
<a href="/members" class="nav-link">
|
||||
<a href="/members" class="nav-link" title="Mitglieder">
|
||||
<span class="nav-icon">👥</span>
|
||||
Mitglieder
|
||||
</a>
|
||||
<a href="/diary" class="nav-link">
|
||||
<a href="/diary" class="nav-link" title="Tagebuch">
|
||||
<span class="nav-icon">📝</span>
|
||||
Tagebuch
|
||||
</a>
|
||||
<a href="/pending-approvals" class="nav-link">
|
||||
<a href="/pending-approvals" class="nav-link" title="Freigaben">
|
||||
<span class="nav-icon">⏳</span>
|
||||
Freigaben
|
||||
</a>
|
||||
<a href="/training-stats" class="nav-link">
|
||||
<a href="/training-stats" class="nav-link" title="Trainings-Statistik">
|
||||
<span class="nav-icon">📊</span>
|
||||
Trainings-Statistik
|
||||
</a>
|
||||
@@ -49,23 +53,23 @@
|
||||
|
||||
<div class="nav-section">
|
||||
<h4 class="nav-title">Organisation</h4>
|
||||
<a href="/schedule" class="nav-link">
|
||||
<a href="/schedule" class="nav-link" title="Spielpläne">
|
||||
<span class="nav-icon">📅</span>
|
||||
Spielpläne
|
||||
</a>
|
||||
<a href="/tournaments" class="nav-link">
|
||||
<a href="/tournaments" class="nav-link" title="Interne Turniere">
|
||||
<span class="nav-icon">🏆</span>
|
||||
Interne Turniere
|
||||
</a>
|
||||
<a href="/official-tournaments" class="nav-link">
|
||||
<a href="/official-tournaments" class="nav-link" title="Offizielle Turniere">
|
||||
<span class="nav-icon">📄</span>
|
||||
Offizielle Turniere
|
||||
</a>
|
||||
<a href="/predefined-activities" class="nav-link">
|
||||
<a href="/predefined-activities" class="nav-link" title="Vordefinierte Aktivitäten">
|
||||
<span class="nav-icon">⚙️</span>
|
||||
Vordefinierte Aktivitäten
|
||||
</a>
|
||||
<a href="/team-management" class="nav-link">
|
||||
<a href="/team-management" class="nav-link" title="Team-Verwaltung">
|
||||
<span class="nav-icon">👥</span>
|
||||
Team-Verwaltung
|
||||
</a>
|
||||
@@ -76,7 +80,7 @@
|
||||
<nav class="sidebar-footer">
|
||||
<div class="nav-section">
|
||||
<h4 class="nav-title">Einstellungen</h4>
|
||||
<a href="/mytischtennis-account" class="nav-link">
|
||||
<a href="/mytischtennis-account" class="nav-link" title="myTischtennis-Account">
|
||||
<span class="nav-icon">🔗</span>
|
||||
myTischtennis-Account
|
||||
</a>
|
||||
@@ -84,7 +88,7 @@
|
||||
</nav>
|
||||
|
||||
<div class="sidebar-footer">
|
||||
<button @click="logout()" class="btn-secondary logout-btn">
|
||||
<button @click="logout()" class="btn-secondary logout-btn" title="Ausloggen">
|
||||
<span class="nav-icon">🚪</span>
|
||||
Ausloggen
|
||||
</button>
|
||||
@@ -137,7 +141,7 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['isAuthenticated', 'currentClub', 'clubs']),
|
||||
...mapGetters(['isAuthenticated', 'currentClub', 'clubs', 'sidebarCollapsed']),
|
||||
},
|
||||
watch: {
|
||||
selectedClub(newVal) {
|
||||
@@ -166,7 +170,7 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['setCurrentClub', 'setClubs', 'logout']),
|
||||
...mapActions(['setCurrentClub', 'setClubs', 'logout', 'toggleSidebar']),
|
||||
|
||||
async loadUserData() {
|
||||
try {
|
||||
@@ -530,14 +534,83 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
/* Toggle-Button für Sidebar (nur auf mobil sichtbar) */
|
||||
.sidebar-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.sidebar {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
top: 3rem;
|
||||
left: 0;
|
||||
height: calc(100vh - 3rem);
|
||||
z-index: 999;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.sidebar.sidebar-collapsed {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.sidebar:not(.sidebar-collapsed) {
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
border: none;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
z-index: 1000;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.sidebar-toggle:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
/* Im kollabierten Zustand: nur Icons zeigen */
|
||||
.sidebar-collapsed .nav-link span:not(.nav-icon),
|
||||
.sidebar-collapsed .nav-link text,
|
||||
.sidebar-collapsed .nav-title,
|
||||
.sidebar-collapsed .card-title,
|
||||
.sidebar-collapsed .logout-btn span:not(.nav-icon),
|
||||
.sidebar-collapsed .club-selector,
|
||||
.sidebar-collapsed .select-group,
|
||||
.sidebar-collapsed .btn-primary {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Alle Text-Inhalte in nav-links verstecken */
|
||||
.sidebar-collapsed .nav-link {
|
||||
justify-content: center;
|
||||
padding: 0.75rem 0.5rem;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.sidebar-collapsed .nav-icon {
|
||||
font-size: 1.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sidebar-collapsed .logout-btn {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sidebar-collapsed .sidebar-footer {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.content {
|
||||
@@ -557,8 +630,13 @@ export default {
|
||||
}
|
||||
|
||||
.main-content {
|
||||
margin-left: 0;
|
||||
margin-left: 60px;
|
||||
overflow-y: auto;
|
||||
transition: margin-left 0.3s ease;
|
||||
}
|
||||
|
||||
.sidebar:not(.sidebar-collapsed) ~ .main-content {
|
||||
margin-left: 240px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,14 @@ const store = createStore({
|
||||
})(),
|
||||
dialogs: [], // Array von offenen Dialogen
|
||||
dialogCounter: 0, // Zähler für eindeutige Dialog-IDs
|
||||
sidebarCollapsed: (() => {
|
||||
const savedState = localStorage.getItem('sidebarCollapsed');
|
||||
if (savedState !== null) {
|
||||
return savedState === 'true';
|
||||
}
|
||||
// Standardmäßig kollabiert auf mobilen Geräten
|
||||
return window.innerWidth <= 480;
|
||||
})(),
|
||||
},
|
||||
mutations: {
|
||||
setToken(state, token) {
|
||||
@@ -36,6 +44,10 @@ const store = createStore({
|
||||
state.clubs = clubs;
|
||||
localStorage.setItem('clubs', JSON.stringify(clubs));
|
||||
},
|
||||
setSidebarCollapsed(state, collapsed) {
|
||||
state.sidebarCollapsed = collapsed;
|
||||
localStorage.setItem('sidebarCollapsed', collapsed.toString());
|
||||
},
|
||||
clearToken(state) {
|
||||
state.token = null;
|
||||
localStorage.removeItem('token');
|
||||
@@ -103,6 +115,9 @@ const store = createStore({
|
||||
setClubs({ commit }, clubs) {
|
||||
commit('setClubsMutation', clubs);
|
||||
},
|
||||
toggleSidebar({ commit, state }) {
|
||||
commit('setSidebarCollapsed', !state.sidebarCollapsed);
|
||||
},
|
||||
// Dialog-Actions
|
||||
openDialog({ commit }, dialog) {
|
||||
commit('openDialog', dialog);
|
||||
@@ -126,6 +141,7 @@ const store = createStore({
|
||||
username: state => state.username,
|
||||
currentClub: state => state.currentClub,
|
||||
clubs: state => state.clubs,
|
||||
sidebarCollapsed: state => state.sidebarCollapsed,
|
||||
currentClubName: state => {
|
||||
const club = state.clubs.find(club => club.id === parseInt(state.currentClub));
|
||||
return club ? club.name : '';
|
||||
|
||||
Reference in New Issue
Block a user