Refactor backend CORS settings to include default origins and improve error handling in chat services: Introduce dynamic CORS origin handling, enhance RabbitMQ message sending with fallback mechanisms, and update WebSocket service to manage pending messages. Update UI components for better accessibility and responsiveness, including adjustments to dialog and navigation elements. Enhance styling for improved user experience across various components.

This commit is contained in:
Torsten Schulz (local)
2026-03-19 14:44:04 +01:00
parent 4442937ebd
commit 9d44a265ca
67 changed files with 5426 additions and 1099 deletions

View File

@@ -1,9 +1,14 @@
<template>
<div class="home-logged-in">
<header class="dashboard-header">
<h1>Willkommen zurück!</h1>
<p class="dashboard-subtitle">Schön, dass du wieder da bist.</p>
<div class="dashboard-toolbar">
<section class="dashboard-hero surface-card">
<div class="dashboard-hero__copy">
<span class="dashboard-kicker">Dein Bereich</span>
<h1>Willkommen zurück!</h1>
<p class="dashboard-subtitle">
Dein persönlicher Einstieg in Community, Termine, Falukant und laufende Aktivitäten.
</p>
</div>
<div class="dashboard-toolbar surface-card">
<button
v-if="!editMode"
type="button"
@@ -42,7 +47,25 @@
</button>
</template>
</div>
</header>
</section>
<section class="dashboard-overview">
<article class="overview-card surface-card">
<span class="overview-card__label">Aktive Widgets</span>
<strong>{{ widgets.length }}</strong>
<p>Dein Dashboard ist modular aufgebaut und kann jederzeit umsortiert werden.</p>
</article>
<article class="overview-card surface-card">
<span class="overview-card__label">Verfügbare Module</span>
<strong>{{ widgetTypeOptions.length }}</strong>
<p>Du kannst Community-, Kalender-, News- und Falukant-Module kombinieren.</p>
</article>
<article class="overview-card surface-card">
<span class="overview-card__label">Bearbeitungsmodus</span>
<strong>{{ editMode ? 'Aktiv' : 'Aus' }}</strong>
<p>{{ editMode ? 'Widgets können gerade ergänzt und angepasst werden.' : 'Inhalte bleiben fokussiert und ruhig lesbar.' }}</p>
</article>
</section>
<div
v-if="loadError"
@@ -58,11 +81,20 @@
</div>
<div
v-else
ref="dashboardGridRef"
class="dashboard-grid"
@dragover.prevent
@drop.prevent="onAnyDrop($event)"
class="dashboard-shell"
>
<div class="dashboard-shell__header">
<div>
<h2>Deine Übersicht</h2>
<p>Widgets lassen sich verschieben und im Bearbeitungsmodus anpassen.</p>
</div>
</div>
<div
ref="dashboardGridRef"
class="dashboard-grid"
@dragover.prevent
@drop.prevent="onAnyDrop($event)"
>
<template v-for="(w, index) in widgets" :key="w.id">
<div
class="dashboard-grid-cell"
@@ -103,6 +135,7 @@
</div>
</div>
</template>
</div>
</div>
<div v-if="widgets.length === 0 && !loading" class="dashboard-empty">
@@ -306,98 +339,170 @@ export default {
<style scoped>
.home-logged-in {
max-width: 1200px;
max-width: var(--content-max-width);
margin: 0 auto;
padding: 20px;
padding: 8px 0 24px;
}
.dashboard-header {
margin-bottom: 24px;
.dashboard-hero {
display: flex;
align-items: stretch;
justify-content: space-between;
gap: 20px;
padding: 26px;
margin-bottom: 18px;
background:
radial-gradient(circle at top right, rgba(248, 162, 43, 0.18), transparent 28%),
linear-gradient(180deg, rgba(255, 251, 246, 0.96) 0%, rgba(250, 243, 233, 0.98) 100%);
}
.dashboard-header h1 {
color: #333;
margin: 0 0 4px 0;
.dashboard-hero__copy {
max-width: 640px;
}
.dashboard-kicker {
display: inline-block;
margin-bottom: 10px;
padding: 4px 10px;
border-radius: 999px;
background: rgba(248, 162, 43, 0.14);
color: #8a5411;
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
}
.dashboard-hero h1 {
margin: 0 0 8px;
}
.dashboard-subtitle {
color: #666;
margin: 0 0 16px 0;
color: var(--color-text-secondary);
margin: 0;
max-width: 58ch;
}
.dashboard-overview {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
margin-bottom: 18px;
}
.overview-card {
padding: 18px 20px;
}
.overview-card__label {
display: inline-block;
margin-bottom: 12px;
color: var(--color-text-muted);
font-size: 0.78rem;
font-weight: 700;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.overview-card strong {
display: block;
margin-bottom: 8px;
font-size: 1.9rem;
line-height: 1;
color: var(--color-text-primary);
}
.overview-card p {
margin: 0;
color: var(--color-text-secondary);
}
.dashboard-toolbar {
display: flex;
flex-wrap: wrap;
align-items: center;
align-self: flex-start;
flex-wrap: wrap;
gap: 10px;
padding: 14px;
min-width: 300px;
background: rgba(255, 255, 255, 0.72);
}
.btn-edit,
.btn-done {
padding: 8px 14px;
border-radius: 4px;
border: 1px solid transparent;
background: var(--color-primary-orange);
color: var(--color-text-on-orange);
cursor: pointer;
font-size: 0.9rem;
min-height: 40px;
}
.btn-edit:hover,
.btn-done:hover {
background: var(--color-primary-orange-light);
color: var(--color-text-secondary);
border-color: var(--color-text-secondary);
color: #2b1f14;
}
.widget-add-row {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 10px;
}
.btn-add-again {
padding: 8px 14px;
border-radius: 4px;
border: 1px solid var(--color-text-secondary);
background: #fff;
color: var(--color-text-primary);
font-size: 0.9rem;
cursor: pointer;
min-height: 40px;
background: rgba(255, 255, 255, 0.78);
border-color: var(--color-border-strong);
box-shadow: none;
}
.btn-add-again:hover {
background: var(--color-primary-orange-light);
border-color: var(--color-primary-orange);
background: rgba(255, 255, 255, 0.96);
}
.widget-type-select {
padding: 8px 12px;
border-radius: 4px;
border: 1px solid var(--color-text-secondary);
background: #fff;
color: var(--color-text-primary);
font-size: 0.9rem;
min-width: 180px;
}
.dashboard-message {
padding: 16px;
border-radius: 8px;
padding: 16px 18px;
border-radius: var(--radius-md);
margin-bottom: 16px;
}
.dashboard-error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
background: rgba(177, 59, 53, 0.12);
color: #7a241f;
border: 1px solid rgba(177, 59, 53, 0.18);
}
.dashboard-shell {
padding: 20px;
border-radius: var(--radius-lg);
border: 1px solid var(--color-border);
background:
linear-gradient(180deg, rgba(255, 252, 247, 0.94) 0%, rgba(248, 241, 231, 0.96) 100%);
box-shadow: var(--shadow-soft);
}
.dashboard-shell__header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16px;
}
.dashboard-shell__header h2 {
margin: 0 0 4px;
font-size: 1.4rem;
}
.dashboard-shell__header p {
margin: 0;
color: var(--color-text-secondary);
}
.dashboard-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
grid-auto-rows: 200px;
gap: 20px;
grid-auto-rows: 220px;
gap: 18px;
}
.dashboard-grid-cell {
@@ -415,9 +520,9 @@ export default {
}
.dashboard-grid-cell.drop-target {
outline: 2px dashed #0d6efd;
outline: 2px dashed rgba(248, 162, 43, 0.82);
outline-offset: 4px;
border-radius: 8px;
border-radius: var(--radius-md);
}
.dashboard-grid-cell.drag-source {
@@ -426,13 +531,14 @@ export default {
.dashboard-widget-edit {
min-height: 200px;
padding: 12px;
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 16px;
background: rgba(255, 255, 255, 0.82);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
display: flex;
flex-direction: column;
gap: 12px;
box-shadow: var(--shadow-soft);
}
.widget-edit-fields {
@@ -441,40 +547,58 @@ export default {
gap: 8px;
}
.widget-edit-input {
padding: 8px 10px;
border: 1px solid #ced4da;
border-radius: 4px;
font-size: 0.9rem;
}
.btn-remove {
align-self: flex-start;
padding: 6px 12px;
border: 1px solid transparent;
background: var(--color-primary-orange);
color: var(--color-text-on-orange);
border-radius: 4px;
cursor: pointer;
font-size: 0.85rem;
min-height: 36px;
background: rgba(177, 59, 53, 0.12);
color: #7a241f;
border-color: rgba(177, 59, 53, 0.18);
box-shadow: none;
}
.btn-remove:hover {
background: var(--color-primary-orange-light);
color: var(--color-text-secondary);
border-color: var(--color-text-secondary);
background: rgba(177, 59, 53, 0.18);
}
.dashboard-empty {
padding: 32px;
text-align: center;
color: #666;
background: #f8f9fa;
border-radius: 8px;
border: 1px dashed #dee2e6;
color: var(--color-text-secondary);
background: rgba(255, 255, 255, 0.72);
border-radius: var(--radius-lg);
border: 1px dashed var(--color-border-strong);
box-shadow: var(--shadow-soft);
}
.actions {
margin-top: 30px;
}
@media (max-width: 960px) {
.home-logged-in {
padding-bottom: 18px;
}
.dashboard-hero {
flex-direction: column;
padding: 20px;
}
.dashboard-toolbar {
width: 100%;
min-width: 0;
}
.dashboard-overview {
grid-template-columns: 1fr;
}
.dashboard-shell {
padding: 16px;
}
.dashboard-grid {
grid-template-columns: 1fr;
}
}
</style>