Enhance notification display and localization in MessagesDialog component
- Updated the MessagesDialog component to display notifications with titles and descriptions, improving clarity and user experience. - Enhanced the formatBody method to support new notification structures, including extraction and formatting of parameters for better message presentation. - Added a new formatParams method to handle various parameter types, ensuring accurate representation of values in notifications. - Updated localization files in both German and English to include structured titles and descriptions for random events, enriching the user experience with detailed information.
This commit is contained in:
@@ -11,7 +11,10 @@
|
||||
>
|
||||
<ul class="messages">
|
||||
<li v-for="n in messages" :key="n.id" :class="{ unread: !n.shown }">
|
||||
<div class="body">{{ formatBody(n) }}</div>
|
||||
<div class="body">
|
||||
<div v-if="formatBody(n).title" class="notification-title">{{ formatBody(n).title }}</div>
|
||||
<div class="notification-description">{{ formatBody(n).description || formatBody(n) }}</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<span>{{ formatDate(n.createdAt) }}</span>
|
||||
</div>
|
||||
@@ -118,11 +121,21 @@ export default {
|
||||
} catch { return dt; }
|
||||
},
|
||||
formatBody(n) {
|
||||
// Wenn die Notification bereits title und description hat (z.B. von WebSocket Events)
|
||||
if (n.title && n.description) {
|
||||
// Parameter aus effects oder anderen Feldern extrahieren
|
||||
const params = this.extractParams(n);
|
||||
return {
|
||||
title: this.interpolateString(n.title, params),
|
||||
description: this.interpolateString(n.description, params)
|
||||
};
|
||||
}
|
||||
|
||||
let raw = n.tr || '';
|
||||
let key = raw;
|
||||
let params = {};
|
||||
|
||||
// 1) JSON-Format unterstützen: {"tr":"production.overproduction","value":21}
|
||||
// 1) JSON-Format unterstützen: {"tr":"random_event.windfall","amount":1000,"characterName":"Max"}
|
||||
if (typeof raw === 'string') {
|
||||
const trimmed = raw.trim();
|
||||
if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
|
||||
@@ -131,7 +144,8 @@ export default {
|
||||
if (parsed && parsed.tr) {
|
||||
raw = parsed.tr;
|
||||
key = parsed.tr;
|
||||
params = { ...parsed };
|
||||
// Alle anderen Felder als Parameter verwenden und formatieren
|
||||
params = this.formatParams({ ...parsed });
|
||||
delete params.tr;
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -153,7 +167,137 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Prüfe, ob es sich um ein random_event handelt mit title/description Struktur
|
||||
if (key.startsWith('falukant.notifications.random_event.')) {
|
||||
const eventId = key.replace('falukant.notifications.random_event.', '');
|
||||
const eventKey = `falukant.notifications.random_event.${eventId}`;
|
||||
try {
|
||||
const titleKey = `${eventKey}.title`;
|
||||
const descKey = `${eventKey}.description`;
|
||||
|
||||
if (this.$te(titleKey) && this.$te(descKey)) {
|
||||
const title = this.$t(titleKey, params);
|
||||
const description = this.$t(descKey, params);
|
||||
return { title, description };
|
||||
}
|
||||
} catch (e) {
|
||||
// Fallback zur alten Methode
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: Alte Methode für andere Notification-Typen
|
||||
return this.$t(key, params);
|
||||
},
|
||||
|
||||
formatParams(params) {
|
||||
const formatted = {};
|
||||
|
||||
// Geldbeträge formatieren
|
||||
if (params.amount !== undefined) {
|
||||
formatted.amount = this.formatMoney(params.amount);
|
||||
}
|
||||
if (params.absolute !== undefined) {
|
||||
formatted.amount = this.formatMoney(params.absolute);
|
||||
}
|
||||
if (params.percent !== undefined) {
|
||||
formatted.amount = `${params.percent > 0 ? '+' : ''}${params.percent.toFixed(1)}%`;
|
||||
}
|
||||
|
||||
// Gesundheit formatieren
|
||||
if (params.change !== undefined) {
|
||||
formatted.healthChange = params.change > 0 ? `+${params.change}` : `${params.change}`;
|
||||
}
|
||||
if (params.healthChange !== undefined) {
|
||||
formatted.healthChange = params.healthChange > 0 ? `+${params.healthChange}` : `${params.healthChange}`;
|
||||
}
|
||||
|
||||
// Schaden formatieren
|
||||
if (params.inventory_damage_percent !== undefined) {
|
||||
formatted.damagePercent = ` Lagerbestand beschädigt: ${params.inventory_damage_percent.toFixed(1)}%.`;
|
||||
}
|
||||
if (params.storage_destruction_percent !== undefined) {
|
||||
formatted.destructionPercent = ` Lager zerstört: ${params.storage_destruction_percent.toFixed(1)}%.`;
|
||||
}
|
||||
|
||||
// Alle anderen Parameter übernehmen
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
if (!formatted.hasOwnProperty(key) && key !== 'tr') {
|
||||
formatted[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return formatted;
|
||||
},
|
||||
|
||||
extractParams(n) {
|
||||
const params = {};
|
||||
|
||||
// Parameter aus effects extrahieren
|
||||
if (n.effects && Array.isArray(n.effects)) {
|
||||
for (const effect of n.effects) {
|
||||
if (effect.type === 'money_change') {
|
||||
if (effect.absolute !== undefined) {
|
||||
params.amount = effect.absolute;
|
||||
} else if (effect.percent !== undefined) {
|
||||
params.percent = effect.percent;
|
||||
}
|
||||
} else if (effect.type === 'character_health_change') {
|
||||
if (effect.character_id && n.character_id === effect.character_id) {
|
||||
params.characterName = n.characterName || '';
|
||||
}
|
||||
if (effect.change !== undefined) {
|
||||
params.change = effect.change;
|
||||
}
|
||||
} else if (effect.type === 'character_death') {
|
||||
if (effect.character_id && n.character_id === effect.character_id) {
|
||||
params.characterName = n.characterName || '';
|
||||
}
|
||||
} else if (effect.type === 'storage_damage') {
|
||||
if (effect.inventory_damage_percent !== undefined) {
|
||||
params.inventory_damage_percent = effect.inventory_damage_percent;
|
||||
}
|
||||
if (effect.storage_destruction_percent !== undefined) {
|
||||
params.storage_destruction_percent = effect.storage_destruction_percent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Weitere Parameter aus der Notification selbst
|
||||
if (n.region_id && n.regionName) {
|
||||
params.regionName = n.regionName;
|
||||
}
|
||||
if (n.character_id && n.characterName) {
|
||||
params.characterName = n.characterName;
|
||||
}
|
||||
if (n.amount !== undefined) {
|
||||
params.amount = n.amount;
|
||||
}
|
||||
|
||||
return this.formatParams(params);
|
||||
},
|
||||
|
||||
interpolateString(str, params) {
|
||||
if (!str || typeof str !== 'string') return str;
|
||||
let result = str;
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
if (value !== undefined && value !== null && value !== '') {
|
||||
result = result.replace(new RegExp(`\\{${key}\\}`, 'g'), String(value));
|
||||
} else {
|
||||
// Entferne Platzhalter, wenn kein Wert vorhanden ist
|
||||
result = result.replace(new RegExp(`\\s*\\{${key}\\}\\s*`, 'g'), '');
|
||||
}
|
||||
}
|
||||
// Entferne doppelte Leerzeichen und trimme
|
||||
result = result.replace(/\s+/g, ' ').trim();
|
||||
return result;
|
||||
},
|
||||
|
||||
formatMoney(amount) {
|
||||
return new Intl.NumberFormat(navigator.language, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
}).format(amount);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -174,6 +318,9 @@ export default {
|
||||
}
|
||||
.messages > li { border: 1px solid #7BBE55; margin-bottom: .25em; padding: .5em; }
|
||||
.messages > li.unread { font-weight: bold; }
|
||||
.messages > li .body { display: flex; flex-direction: column; gap: 0.25em; }
|
||||
.messages > li .notification-title { font-weight: bold; font-size: 1.05em; }
|
||||
.messages > li .notification-description { color: #555; }
|
||||
.messages > li .footer { color: #f9a22c; font-size: .8em; margin-top: .3em; display: flex; }
|
||||
.messages > li .footer span:first-child { flex: 1; }
|
||||
.empty { text-align: center; color: #777; padding: 1em; }
|
||||
|
||||
Reference in New Issue
Block a user