178 lines
5.4 KiB
Vue
178 lines
5.4 KiB
Vue
<template>
|
|
<dl v-if="falukantData" class="dashboard-widget__falukant">
|
|
<dt>{{ $t('falukant.overview.metadata.name') }}</dt>
|
|
<dd>{{ falukantDisplayName }}</dd>
|
|
<dt>{{ $t('falukant.create.gender') }}</dt>
|
|
<dd class="falukant-gender">{{ falukantGenderLabel }}</dd>
|
|
<dt>{{ $t('falukant.overview.metadata.age') }}</dt>
|
|
<dd class="falukant-age">{{ falukantAgeLabel }}</dd>
|
|
<dt>{{ $t('falukant.overview.metadata.money') }}</dt>
|
|
<dd>{{ formatMoney(falukantData.money) }}</dd>
|
|
<dt>{{ $t('falukant.messages.title') }}</dt>
|
|
<dd>{{ falukantData.unreadNotificationsCount }}</dd>
|
|
<dt>{{ $t('falukant.statusbar.children') }}</dt>
|
|
<dd>{{ falukantData.childrenCount }}</dd>
|
|
</dl>
|
|
<span v-else>—</span>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
name: 'FalukantWidget',
|
|
props: {
|
|
data: { type: Object, default: null }
|
|
},
|
|
computed: {
|
|
falukantData() {
|
|
const d = this.data;
|
|
if (d && typeof d === 'object' && 'characterName' in d && 'money' in d) return d;
|
|
return null;
|
|
},
|
|
falukantDisplayName() {
|
|
const d = this.falukantData;
|
|
if (!d) return '—';
|
|
const titleKey = d.titleLabelTr;
|
|
const gender = d.gender;
|
|
const nameWithoutTitle = d.nameWithoutTitle ?? d.characterName;
|
|
if (titleKey && gender) {
|
|
const key = `falukant.titles.${gender}.${titleKey}`;
|
|
const translatedTitle = this.$t(key);
|
|
if (translatedTitle !== key) return `${translatedTitle} ${nameWithoutTitle}`.trim();
|
|
}
|
|
return d.characterName || nameWithoutTitle || '—';
|
|
},
|
|
falukantGenderLabel() {
|
|
const g = this.falukantData?.gender;
|
|
if (g == null || g === '') return '—';
|
|
|
|
// Altersabhängige, (auf Wunsch) altertümlichere Bezeichnungen
|
|
const years = this._ageYearsFromWidgetValue(this.falukantData?.age);
|
|
const group = years == null ? null : this._getAgeGroupKey(years);
|
|
|
|
// Debug: Zeige, ob age->years->group korrekt ist und ob i18n keys aufgelöst werden
|
|
try {
|
|
const cfg = this.$t('falukant.genderAge.ageGroups');
|
|
// eslint-disable-next-line no-console
|
|
console.log('[FalukantWidget] genderAge', {
|
|
locale: this?.$i18n?.locale,
|
|
rawAge: this.falukantData?.age,
|
|
years,
|
|
group,
|
|
gender: g,
|
|
ageGroups: cfg
|
|
});
|
|
} catch (_) {}
|
|
|
|
if (group && (g === 'female' || g === 'male')) {
|
|
const key = `falukant.genderAge.${g}.${group}`;
|
|
const t = this.$t(key);
|
|
|
|
// eslint-disable-next-line no-console
|
|
console.log('[FalukantWidget] gender label lookup', { key, resolved: t });
|
|
|
|
if (t !== key) return t;
|
|
}
|
|
|
|
// Fallback auf vorhandene Übersetzungen
|
|
const key = `falukant.create.${g}`;
|
|
const t = this.$t(key);
|
|
return t === key ? this.$t(`general.gender.${g}`) || g : t;
|
|
},
|
|
falukantAgeLabel() {
|
|
const ageValue = this.falukantData?.age;
|
|
if (ageValue == null) return '—';
|
|
const years = this._ageYearsFromWidgetValue(ageValue);
|
|
if (years == null) return '—';
|
|
|
|
// eslint-disable-next-line no-console
|
|
console.log('[FalukantWidget] age label', {
|
|
locale: this?.$i18n?.locale,
|
|
rawAge: ageValue,
|
|
years,
|
|
yearsLabel: this.$t('falukant.overview.metadata.years')
|
|
});
|
|
|
|
return `${years} ${this.$t('falukant.overview.metadata.years')}`;
|
|
}
|
|
},
|
|
methods: {
|
|
/**
|
|
* Backend liefert für Falukant das Alter als (Spiel-)Tage.
|
|
* In diesem Spiel entspricht 1 (Spiel-)Tag einem Jahr, damit die Alterung spielbar schnell ist.
|
|
*
|
|
* Daher ist der übergebene Tageswert direkt das Alter in (Spiel-)Jahren.
|
|
*/
|
|
_ageYearsFromWidgetValue(ageValue) {
|
|
const n = Number(ageValue);
|
|
if (Number.isNaN(n)) return null;
|
|
|
|
// Spiel-Zeit: 1 Tag = 1 Jahr
|
|
const years = Math.floor(n);
|
|
return Number.isFinite(years) ? years : null;
|
|
},
|
|
_getAgeGroupKey(age) {
|
|
const a = Number(age);
|
|
if (Number.isNaN(a)) return null;
|
|
|
|
// Pro Sprache konfigurierbare Schwellenwerte aus i18n.
|
|
// Format: "key:maxAge|key2:maxAge2|..." (maxAge exklusiv, letzte Gruppe sollte hoch gesetzt sein)
|
|
const raw = this.$t('falukant.genderAge.ageGroups');
|
|
const parsed = typeof raw === 'string' ? raw : '';
|
|
const rules = parsed.split('|')
|
|
.map(part => part.trim())
|
|
.filter(Boolean)
|
|
.map(part => {
|
|
const [key, num] = part.split(':').map(s => (s ?? '').trim());
|
|
return { key, max: Number(num) };
|
|
})
|
|
.filter(r => r.key && !Number.isNaN(r.max))
|
|
.sort((x, y) => x.max - y.max);
|
|
|
|
for (const r of rules) {
|
|
if (a < r.max) return r.key;
|
|
}
|
|
|
|
// Fallback, falls Konfig kaputt ist
|
|
return 'adult';
|
|
},
|
|
formatMoney(value) {
|
|
const n = Number(value);
|
|
if (Number.isNaN(n)) return '—';
|
|
return n.toLocaleString('de-DE');
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.dashboard-widget__falukant {
|
|
margin: 0;
|
|
display: grid;
|
|
grid-template-columns: auto 1fr;
|
|
gap: 4px 16px;
|
|
align-items: baseline;
|
|
}
|
|
|
|
.dashboard-widget__falukant dt {
|
|
margin: 0;
|
|
font-weight: 600;
|
|
color: #555;
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
.dashboard-widget__falukant dd {
|
|
margin: 0;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.dashboard-widget__falukant dd.falukant-gender {
|
|
color: var(--color-text-secondary);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.dashboard-widget__falukant dd.falukant-age {
|
|
color: #198754;
|
|
font-weight: 600;
|
|
}
|
|
</style>
|