From 36690980b7643738004fff863b1702f3de4327a9 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Fri, 20 Mar 2026 10:20:48 +0100 Subject: [PATCH] feat(ViteConfig, App, Router, DialogManager, MembersView, ScheduleView, ClubView, Home, TournamentsView, TrainingStatsView): enhance performance and responsiveness - Updated Vite configuration to improve chunking strategy and set a chunk size warning limit. - Refactored App.vue and DialogManager.vue to utilize async component loading for better performance. - Modified router.js to implement lazy loading for various views, optimizing initial load times. - Enhanced MembersView, ScheduleView, ClubView, and TournamentsView with responsive design adjustments for improved mobile usability. - Improved styling and layout in Home.vue and TrainingStatsView to enhance user experience across different screen sizes. --- frontend/src/App.vue | 4 +- frontend/src/components/DialogManager.vue | 16 +-- .../members/MembersOverviewSection.vue | 86 +++++++++++++ .../schedule/ScheduleLayoutShell.vue | 38 ++++++ frontend/src/router.js | 55 +++++---- frontend/src/views/ClubView.vue | 115 +++++++++++++++--- frontend/src/views/Home.vue | 47 ++++++- frontend/src/views/MembersView.vue | 84 +++++++++++++ frontend/src/views/ScheduleView.vue | 45 +++++++ frontend/src/views/TournamentsView.vue | 30 +++++ frontend/src/views/TrainingStatsView.vue | 68 +++++++++++ frontend/vite.config.js | 24 ++++ 12 files changed, 557 insertions(+), 55 deletions(-) diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 0e0db17c..eef53820 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -209,14 +209,16 @@ diff --git a/frontend/src/views/Home.vue b/frontend/src/views/Home.vue index fda2d2f6..d907e951 100644 --- a/frontend/src/views/Home.vue +++ b/frontend/src/views/Home.vue @@ -701,12 +701,30 @@ export default { } .welcome-card { - margin: 0 0.375rem; + margin: 0; } .card-title { font-size: 1.5rem; } + + .marketing { + gap: 1.5rem; + } + + .hero { + align-items: stretch; + text-align: left; + } + + .hero-title, + .hero-subtitle { + text-align: left; + } + + .hero-bullets { + grid-template-columns: 1fr; + } .features-grid { grid-template-columns: 1fr; @@ -717,6 +735,10 @@ export default { .search-topic-grid { grid-template-columns: 1fr; } + + .seo-intro { + padding: 1.15rem; + } .feature-card { padding: 1.25rem 1rem; @@ -725,7 +747,7 @@ export default { .auth-actions, .user-actions { flex-direction: column; width: 100%; - max-width: 280px; + max-width: none; } .btn-primary, .btn-secondary { @@ -738,6 +760,27 @@ export default { .card-title { font-size: 1.375rem; } + + .hero-title { + font-size: 1.55rem; + line-height: 1.25; + } + + .hero-subtitle, + .seo-intro-copy p, + .search-topic p, + .seo-copy .long-text { + font-size: 0.95rem; + line-height: 1.6; + } + + .seo-point, + .search-topic, + .feature-card, + .faq details { + padding-left: 0.95rem; + padding-right: 0.95rem; + } .section-title { font-size: 1.375rem; diff --git a/frontend/src/views/MembersView.vue b/frontend/src/views/MembersView.vue index c5f67ab1..bd6a6e73 100644 --- a/frontend/src/views/MembersView.vue +++ b/frontend/src/views/MembersView.vue @@ -3655,5 +3655,89 @@ table td { flex-direction: column; align-items: stretch; } + + .member-preview-header, + .member-preview-actions, + .member-actions-primary, + .member-actions-secondary { + width: 100%; + } + + .member-preview-actions > button, + .member-actions-primary > *, + .member-actions-secondary > * { + flex: 1 1 12rem; + } + + .new-member-form > label { + padding: 0.45rem 0; + } + + .new-member-form > label > span { + width: 100%; + display: block; + margin-bottom: 0.35rem; + } + + .member-editor-field-hint { + margin-left: 0; + } + + .contact-item { + align-items: stretch; + } + + .contact-input, + .parent-name-input, + .group-select { + width: 100%; + min-width: 0; + flex: 1 1 100%; + } + + .checkbox-inline { + width: 100%; + } + + .members-table-wrap { + padding: 0.35rem 0.5rem 0.75rem; + } +} + +@media (max-width: 640px) { + .member-preview-panel, + .newmember, + .contact-section { + padding-left: 0.75rem; + padding-right: 0.75rem; + } + + .member-preview-grid { + grid-template-columns: 1fr; + } + + .member-preview-actions > button, + .member-actions-primary > *, + .member-actions-secondary > *, + .btn-add-contact, + .toggle-new-member > button { + width: 100%; + flex: 1 1 100%; + } + + .member-actions-cell { + min-width: 12rem; + } + + .action-icons-row { + flex-wrap: wrap; + white-space: normal; + } + + .member-image-thumb-small, + .member-image-thumb__placeholder { + width: 42px; + height: 42px; + } } diff --git a/frontend/src/views/ScheduleView.vue b/frontend/src/views/ScheduleView.vue index 642f0a0c..7c4970e3 100644 --- a/frontend/src/views/ScheduleView.vue +++ b/frontend/src/views/ScheduleView.vue @@ -2244,4 +2244,49 @@ li { grid-template-columns: 1fr; } } + +@media (max-width: 640px) { + .schedule-view { + gap: 12px; + } + + .league-match-scope-card { + padding: 12px; + } + + .league-match-scope-controls { + flex-direction: column; + align-items: stretch; + } + + .team-filter-chip, + .league-match-scope-select { + width: 100%; + min-width: 0; + } + + .tab-button { + padding: 10px 14px; + font-size: 0.95rem; + } + + .location-info-button { + width: 38px; + height: 38px; + } + + .table-header { + flex-direction: column; + align-items: flex-start; + gap: 10px; + } + + .dialog-actions { + flex-direction: column; + } + + .dialog-actions > button { + width: 100%; + } +} diff --git a/frontend/src/views/TournamentsView.vue b/frontend/src/views/TournamentsView.vue index 8aebf047..5b77b3b0 100644 --- a/frontend/src/views/TournamentsView.vue +++ b/frontend/src/views/TournamentsView.vue @@ -139,6 +139,36 @@ export default { align-items: flex-start; flex-direction: column; } + + .mode-switcher { + width: 100%; + } +} + +@media (max-width: 640px) { + .tournaments-container { + padding: 14px; + } + + .workspace-title { + font-size: 1.35rem; + } + + .workspace-summary { + margin-bottom: 14px; + line-height: 1.4; + } + + .mode-switcher { + flex-direction: column; + align-items: stretch; + } + + .mode-button { + width: 100%; + text-align: left; + justify-content: flex-start; + } } diff --git a/frontend/src/views/TrainingStatsView.vue b/frontend/src/views/TrainingStatsView.vue index 857a9b57..4a89e62a 100644 --- a/frontend/src/views/TrainingStatsView.vue +++ b/frontend/src/views/TrainingStatsView.vue @@ -656,6 +656,30 @@ export default { margin-bottom: 2rem; } +.stats-filters { + display: flex; + gap: 0.9rem; + flex-wrap: wrap; + margin-bottom: 1.25rem; +} + +.stats-filter { + display: flex; + flex-direction: column; + gap: 0.35rem; + flex: 1 1 220px; +} + +.stats-filter span { + font-size: 0.88rem; + font-weight: 600; + color: var(--text-secondary); +} + +.stats-filter select { + width: 100%; +} + .stats-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); @@ -1097,6 +1121,15 @@ export default { .training-stats { padding: 1rem; } + + .stats-filters { + flex-direction: column; + gap: 0.75rem; + } + + .stats-filter { + flex-basis: auto; + } .stats-summary { grid-template-columns: 1fr; @@ -1112,6 +1145,15 @@ export default { grid-template-columns: 1fr; } + .panel-header { + flex-direction: column; + align-items: flex-start; + } + + .section-header { + padding: 1rem; + } + .trend-value { text-align: left; } @@ -1124,6 +1166,11 @@ export default { .members-table td { padding: 0.75rem 0.5rem; } + + .training-days-container, + .members-table-container { + margin: 0 -0.25rem; + } .modal-content { margin: 1rem; @@ -1140,4 +1187,25 @@ export default { text-align: center; } } + +@media (max-width: 480px) { + .training-stats { + padding: 0.85rem; + } + + .stats-panel { + padding: 0.95rem; + } + + .highlight-number { + font-size: 1.9rem; + } + + .training-days-table th, + .training-days-table td, + .members-table th, + .members-table td { + padding: 0.65rem 0.45rem; + } +} diff --git a/frontend/vite.config.js b/frontend/vite.config.js index f24d931b..1c1ac73c 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -4,6 +4,30 @@ import vue from '@vitejs/plugin-vue'; export default defineConfig({ plugins: [vue()], mode: 'development', + build: { + chunkSizeWarningLimit: 700, + rollupOptions: { + output: { + manualChunks(id) { + if (!id.includes('node_modules')) { + return; + } + + if (id.includes('vue-router')) return 'router'; + if (id.includes('vue-i18n')) return 'i18n'; + if (id.includes('vuex')) return 'store'; + if (id.includes('socket.io-client')) return 'socket'; + if (id.includes('html2canvas')) return 'html2canvas'; + if (id.includes('jspdf')) return 'jspdf'; + if (id.includes('sortablejs')) return 'sortable'; + if (id.includes('crypto-js')) return 'crypto'; + if (id.includes('axios')) return 'http'; + + return 'vendor'; + } + } + } + }, resolve: { alias: { '@': '/src'