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:
@@ -1,7 +1,46 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="falukant-overview">
|
||||
<StatusBar />
|
||||
<h2>{{ $t('falukant.overview.title') }}</h2>
|
||||
<section class="falukant-hero surface-card">
|
||||
<div>
|
||||
<span class="falukant-kicker">Falukant</span>
|
||||
<h2>{{ $t('falukant.overview.title') }}</h2>
|
||||
<p>Dein Stand in Wirtschaft, Familie und Besitz in einer verdichteten Uebersicht.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-if="falukantUser?.character" class="falukant-summary-grid">
|
||||
<article class="summary-card surface-card">
|
||||
<span class="summary-card__label">Niederlassungen</span>
|
||||
<strong>{{ branchCount }}</strong>
|
||||
<p>Direkter Zugriff auf deine wichtigsten Geschaeftsstandorte.</p>
|
||||
</article>
|
||||
<article class="summary-card surface-card">
|
||||
<span class="summary-card__label">Produktionen aktiv</span>
|
||||
<strong>{{ productionCount }}</strong>
|
||||
<p>Laufende Produktionen, die zeitnah Abschluss oder Kontrolle brauchen.</p>
|
||||
</article>
|
||||
<article class="summary-card surface-card">
|
||||
<span class="summary-card__label">Lagerpositionen</span>
|
||||
<strong>{{ stockEntryCount }}</strong>
|
||||
<p>Verdichteter Blick auf Warenbestand ueber alle Regionen.</p>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section v-if="falukantUser?.character" class="falukant-routine-grid">
|
||||
<article
|
||||
v-for="action in routineActions"
|
||||
:key="action.title"
|
||||
class="routine-card surface-card"
|
||||
>
|
||||
<span class="routine-card__eyebrow">{{ action.kicker }}</span>
|
||||
<h3>{{ action.title }}</h3>
|
||||
<p>{{ action.description }}</p>
|
||||
<button type="button" :class="action.secondary ? 'button-secondary' : ''" @click="openRoute(action.route)">
|
||||
{{ action.cta }}
|
||||
</button>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<!-- Erben-Auswahl wenn kein Charakter vorhanden -->
|
||||
<div v-if="!falukantUser?.character" class="heir-selection-container">
|
||||
@@ -136,6 +175,7 @@
|
||||
import StatusBar from '@/components/falukant/StatusBar.vue';
|
||||
import Character3D from '@/components/Character3D.vue';
|
||||
import apiClient from '@/utils/axios.js';
|
||||
import { showError, showSuccess } from '@/utils/feedback.js';
|
||||
import { mapState } from 'vuex';
|
||||
|
||||
const AVATAR_POSITIONS = {
|
||||
@@ -233,6 +273,50 @@ export default {
|
||||
const m = this.falukantUser?.money;
|
||||
return typeof m === 'string' ? parseFloat(m) : m;
|
||||
},
|
||||
branchCount() {
|
||||
return this.falukantUser?.branches?.length || 0;
|
||||
},
|
||||
productionCount() {
|
||||
return this.productions.length;
|
||||
},
|
||||
stockEntryCount() {
|
||||
return this.allStock.length;
|
||||
},
|
||||
routineActions() {
|
||||
return [
|
||||
{
|
||||
kicker: 'Routine',
|
||||
title: 'Niederlassung oeffnen',
|
||||
description: 'Die schnellste Route zu Produktion, Lager, Verkauf und Transport.',
|
||||
cta: 'Zu den Betrieben',
|
||||
route: 'BranchView',
|
||||
},
|
||||
{
|
||||
kicker: 'Ueberblick',
|
||||
title: 'Finanzen pruefen',
|
||||
description: 'Kontostand, Verlauf und wirtschaftliche Entwicklung ohne lange Suche.',
|
||||
cta: 'Geldhistorie',
|
||||
route: 'MoneyHistoryView',
|
||||
secondary: true,
|
||||
},
|
||||
{
|
||||
kicker: 'Charakter',
|
||||
title: 'Familie und Nachfolge',
|
||||
description: 'Wichtige persoenliche Entscheidungen und Haushaltsstatus gesammelt.',
|
||||
cta: 'Familie oeffnen',
|
||||
route: 'FalukantFamily',
|
||||
secondary: true,
|
||||
},
|
||||
{
|
||||
kicker: 'Besitz',
|
||||
title: 'Haus und Umfeld',
|
||||
description: 'Wohnsitz und alltaeglicher Status als eigener Arbeitsbereich.',
|
||||
cta: 'Zum Haus',
|
||||
route: 'HouseView',
|
||||
secondary: true,
|
||||
},
|
||||
];
|
||||
},
|
||||
locale() {
|
||||
return window.navigator.language || 'en-US';
|
||||
},
|
||||
@@ -369,6 +453,16 @@ export default {
|
||||
openBranch(branchId) {
|
||||
this.$router.push({ name: 'BranchView', params: { branchId } });
|
||||
},
|
||||
openRoute(routeName) {
|
||||
if (routeName === 'BranchView') {
|
||||
const firstBranch = this.falukantUser?.branches?.[0];
|
||||
if (firstBranch?.id) {
|
||||
this.openBranch(firstBranch.id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.$router.push({ name: routeName });
|
||||
},
|
||||
async fetchProductions() {
|
||||
try {
|
||||
const response = await apiClient.get('/api/falukant/productions');
|
||||
@@ -399,15 +493,15 @@ export default {
|
||||
async selectHeir(heirId) {
|
||||
try {
|
||||
await apiClient.post('/api/falukant/heirs/select', { heirId });
|
||||
// Lade User-Daten neu
|
||||
await this.fetchFalukantUser();
|
||||
if (this.falukantUser?.character) {
|
||||
await this.fetchAllStock();
|
||||
await this.fetchProductions();
|
||||
}
|
||||
showSuccess(this, 'Erbe wurde uebernommen.');
|
||||
} catch (error) {
|
||||
console.error('Error selecting heir:', error);
|
||||
alert(this.$t('falukant.overview.heirSelection.error'));
|
||||
showError(this, this.$t('falukant.overview.heirSelection.error'));
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -415,16 +509,99 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.falukant-overview {
|
||||
max-width: var(--content-max-width);
|
||||
margin: 0 auto;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
.falukant-hero {
|
||||
padding: 24px 26px;
|
||||
margin-bottom: 16px;
|
||||
background:
|
||||
radial-gradient(circle at top right, rgba(248, 162, 43, 0.16), transparent 28%),
|
||||
linear-gradient(180deg, rgba(255, 250, 243, 0.98) 0%, rgba(247, 238, 224, 0.98) 100%);
|
||||
}
|
||||
|
||||
.falukant-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.06em;
|
||||
}
|
||||
|
||||
.falukant-hero p {
|
||||
margin: 0;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.falukant-summary-grid,
|
||||
.falukant-routine-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 14px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.falukant-routine-grid {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.summary-card,
|
||||
.routine-card {
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
.summary-card strong {
|
||||
display: block;
|
||||
margin: 6px 0 8px;
|
||||
font-size: 1.8rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.summary-card p,
|
||||
.routine-card p {
|
||||
margin: 0;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.summary-card__label,
|
||||
.routine-card__eyebrow {
|
||||
display: inline-flex;
|
||||
margin-bottom: 4px;
|
||||
color: var(--color-text-muted);
|
||||
font-size: 0.76rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.routine-card h3 {
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
|
||||
.routine-card button {
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.overviewcontainer {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
grid-gap: 5px;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.overviewcontainer>div {
|
||||
border: 1px solid #ccc;
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--color-border);
|
||||
padding: 16px;
|
||||
border-radius: var(--radius-lg);
|
||||
background: rgba(255, 253, 249, 0.82);
|
||||
box-shadow: var(--shadow-soft);
|
||||
}
|
||||
|
||||
.imagecontainer {
|
||||
@@ -438,10 +615,12 @@ export default {
|
||||
}
|
||||
|
||||
.avatar {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
background-color: rgba(255,255,255,0.72);
|
||||
background-repeat: no-repeat;
|
||||
image-rendering: crisp-edges;
|
||||
box-shadow: var(--shadow-soft);
|
||||
}
|
||||
|
||||
.house-with-character {
|
||||
@@ -453,8 +632,8 @@ export default {
|
||||
.house {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
background-repeat: no-repeat;
|
||||
image-rendering: crisp-edges;
|
||||
z-index: 1;
|
||||
@@ -470,16 +649,13 @@ export default {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.heir-selection-container {
|
||||
border: 2px solid #dc3545;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(177, 59, 53, 0.18);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
background-color: #fff3cd;
|
||||
background-color: rgba(255, 243, 205, 0.92);
|
||||
box-shadow: var(--shadow-soft);
|
||||
}
|
||||
|
||||
.heir-selection-container h3 {
|
||||
@@ -495,10 +671,10 @@ h2 {
|
||||
}
|
||||
|
||||
.heir-card {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 15px;
|
||||
background-color: white;
|
||||
background-color: rgba(255,255,255,0.86);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
@@ -518,6 +694,20 @@ h2 {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.falukant-routine-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.falukant-summary-grid,
|
||||
.falukant-routine-grid,
|
||||
.overviewcontainer {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.select-heir-button {
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
@@ -535,6 +725,16 @@ h2 {
|
||||
.loading, .no-heirs {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
color: #666;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.overviewcontainer {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.imagecontainer {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user