From ad0ccd0281ebb260738746b725598b2d0fb00cef Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Thu, 21 May 2026 09:55:11 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20F=C3=BCge=20Debug-Overlay=20und=20Alter?= =?UTF-8?q?s-/Geschlechtsanpassungen=20f=C3=BCr=203D-Charaktere=20hinzu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/services/falukantService.js | 22 ++- frontend/src/components/Character3D.vue | 176 ++++++++++++++++-- .../dialogues/falukant/ChildDetailsDialog.vue | 2 + frontend/src/i18n/locales/ceb/falukant.json | 17 ++ frontend/src/i18n/locales/de/falukant.json | 17 ++ frontend/src/i18n/locales/en/falukant.json | 17 ++ frontend/src/i18n/locales/es/falukant.json | 17 ++ frontend/src/i18n/locales/fr/falukant.json | 17 ++ frontend/src/router/falukantRoutes.js | 7 + .../src/views/falukant/AllCharactersTest.vue | 58 ++++++ frontend/src/views/falukant/FamilyView.vue | 38 +++- 11 files changed, 364 insertions(+), 24 deletions(-) create mode 100644 frontend/src/views/falukant/AllCharactersTest.vue diff --git a/backend/services/falukantService.js b/backend/services/falukantService.js index 55640f6..fbbdec4 100644 --- a/backend/services/falukantService.js +++ b/backend/services/falukantService.js @@ -4601,16 +4601,26 @@ class FalukantService extends BaseService { if (!marriedType) { throw new Error('Relationship type "married" not found'); } - await Relationship.create({ + const newRel = await Relationship.create({ character1Id: proposal.requesterCharacterId, character2Id: proposal.proposedCharacterId, relationshipTypeId: marriedType.id, }); - await MarriageProposal.destroy({ - where: { requesterCharacterId: character.id }, - }) - ; - return { success: true, message: 'Marriage proposal accepted' }; + + await MarriageProposal.destroy({ where: { requesterCharacterId: character.id } }); + + // Ensure both households are marked as unburdened upon marriage creation + try { + const otherChar = await FalukantCharacter.findByPk(proposal.proposedCharacterId, { attributes: ['userId'] }); + const otherFUserId = otherChar ? otherChar.userId : null; + const affectedUserIds = [user.id]; + if (otherFUserId) affectedUserIds.push(otherFUserId); + await UserHouse.update({ householdTensionScore: 0, householdTensionReasonsJson: [] }, { where: { userId: affectedUserIds } }); + } catch (err) { + console.error('Failed to reset household tension on marriage:', err); + } + + return { success: true, message: 'Marriage proposal accepted', relationshipId: newRel.id }; } async cancelWooing(hashedUserId) { diff --git a/frontend/src/components/Character3D.vue b/frontend/src/components/Character3D.vue index 47fc904..7456415 100644 --- a/frontend/src/components/Character3D.vue +++ b/frontend/src/components/Character3D.vue @@ -7,6 +7,16 @@ :src="fallbackImageSrc" :alt="`Character ${actualGender}`" /> +
+
3D Debug
+
model: {{ debugInfo.modelType || '—' }}
+
path: {{ debugInfo.modelPath || '—' }}
+
age: {{ debugInfo.actualAge || '—' }} ({{ debugInfo.ageGroup || '—' }})
+
camera: {{ debugInfo.camera.x.toFixed(2) }}, {{ debugInfo.camera.y.toFixed(2) }}, {{ debugInfo.camera.z.toFixed(2) }}
+
camDist: {{ debugInfo.cameraDistance || '—' }}
+
lightweight: {{ debugInfo.lightweight }}
+
lazy: {{ debugInfo.lazy }}
+
@@ -16,6 +26,46 @@ import { getApiBaseURL } from '@/utils/axios.js'; /** Backend-Route: GET /api/models/3d/falukant/characters/:filename (Proxy mit Draco-Optimierung) */ const MODELS_API_PATH = '/api/models/3d/falukant/characters'; +// Optional: zusätzliche Namenskonventionen, die vor dem Standardpfad ausprobiert werden. +// Hier werden mögliche Alternativ-Dateinamen aufgeführt, die für bestimmte Altersstufen +// (z.B. weibliche Modelle für 1-4 Jahre) existieren könnten. Trage hier die tatsächlichen +// Dateinamen ein, falls dein Backend solche Varianten enthält. +const AGE_ALTERNATIVE_SUFFIXES = [ + '_alt.glb', + '_special.glb', + '_v2.glb' +]; + +// Per-age camera offsets applied after auto-fit. Values are additive (meters). +// Set `y` to raise/lower the camera, `z` to move it closer/further. +// The mapping supports per-age overrides; if an exact age key is missing the +// gender `default` entry will be used. Tune these numbers visually. +const AGE_CAMERA_OVERRIDES = { + female: { + default: { y: 0.35, z: 0.35 }, + '1': { y: 0.0, z: 0.0 }, + '2': { y: 0.0, z: 0.0 }, + '5': { y: 0.0, z: 0.0 } + }, + male: { + default: { y: 0.25, z: 0.25 } + } +}; + +// Per-age model position overrides (y in meters). Positive raises the model, +// negative moves it down. Defaults move most characters slightly down to match +// the visual baseline; specific ages (e.g. female 1/2/5) keep no offset. +const AGE_MODEL_POSITION_OVERRIDES = { + female: { + default: { y: -1 }, + '1': { y: 0 }, + '2': { y: 0 }, + '5': { y: 0 } + }, + male: { + default: { y: -1 } + } +}; let threeRuntimePromise = null; let threeLoadersPromise = null; let threeModelRuntimePromise = null; @@ -89,8 +139,23 @@ export default { ,resizeObserver: null ,intersectionObserver: null ,isVisible: false + ,debugInfo: { + modelPath: null, + modelType: null, + camera: null, + cameraDistance: null, + ageGroup: null, + actualAge: null, + lightweight: false, + lazy: false + } }; }, + computed: { + isDev() { + return !import.meta.env.PROD; + } + }, computed: { actualGender() { if (this.gender) { @@ -157,6 +222,9 @@ export default { }, async mounted() { const container = this.$refs.container; + // expose runtime props for debug overlay + this.debugInfo.lightweight = !!this.lightweight; + this.debugInfo.lazy = !!this.lazy; if (this.lazy && typeof window !== 'undefined' && 'IntersectionObserver' in window && container) { // Defer initialization until the element is in viewport this.intersectionObserver = new window.IntersectionObserver((entries) => { @@ -375,25 +443,49 @@ export default { const ageGroupPath = this.modelPath; const fallbackPath = `${prefix}/${this.actualGender}.glb`; + // Build a list of candidate paths. For every age and gender we first try + // possible alternate filenames for the exact-age model (e.g. female_1y_alt.glb), + // then the exact-age file, then the age-group file, and finally the base gender + // fallback. This makes the age-specific model the primary source and the + // age-group only a later fallback. + const candidates = []; + const modelAge = this.actualAge; + + // Try exact-age variants with configured suffixes first (works for any gender/age) + for (const sfx of AGE_ALTERNATIVE_SUFFIXES) { + candidates.push(`${prefix}/${this.actualGender}_${modelAge}y${sfx}`); + } + + // Standard preference order: exact age, age group, fallback + candidates.push(exactAgePath); + candidates.push(ageGroupPath); + candidates.push(fallbackPath); + let gltf; try { - if (this.lightweight) { - try { - gltf = await loader.loadAsync(ageGroupPath); - } catch (ageGroupError) { - gltf = await loader.loadAsync(fallbackPath); - } - } else { - try { - gltf = await loader.loadAsync(exactAgePath); - } catch (exactAgeError) { + let chosenPath = null; + // Try candidates in order until one loads + for (const candidate of candidates) { try { - gltf = await loader.loadAsync(ageGroupPath); - } catch (ageGroupError) { - gltf = await loader.loadAsync(fallbackPath); + chosenPath = candidate; + gltf = await loader.loadAsync(candidate); + // loaded successfully + break; + } catch (err) { + // try next candidate } } - } + if (!gltf) { + throw new Error('No model candidate could be loaded'); + } + + // store for debug overlay + this.debugInfo.modelPath = chosenPath; + // determine modelType + if (chosenPath === exactAgePath) this.debugInfo.modelType = 'exactAge'; + else if (chosenPath === ageGroupPath) this.debugInfo.modelType = 'ageGroup'; + else if (chosenPath === fallbackPath) this.debugInfo.modelType = 'fallback'; + else this.debugInfo.modelType = 'alternate'; } finally { dracoLoader.dispose(); } @@ -435,7 +527,20 @@ export default { const baseY = -scaledBox.min.y; // Auf Boden setzen (y=0 entspricht dem unteren Rand) this.model.position.set(-scaledCenter.x, baseY, -scaledCenter.z); this.baseYPosition = baseY; // Basisposition für Animation speichern - + // Apply per-age/gender model position overrides (vertical shift) + try { + const genderMap = AGE_MODEL_POSITION_OVERRIDES[this.actualGender] || {}; + const specific = genderMap[String(this.actualAge)]; + const def = genderMap.default; + const used = specific || def; + if (used && typeof used.y === 'number') { + this.model.position.y += used.y; + this.debugInfo.modelOffset = { y: used.y }; + } + } catch (e) { + // ignore position override errors + } + this.scene.add(this.model); // Auto-Kamera-Anpassung: Abstand so setzen, dass die modell-Höhe gut ins Bild passt @@ -446,11 +551,33 @@ export default { const desiredHeight = Math.max(scaledSize.y, scaledSize.z) * 1.15; // etwas Margin let distance = desiredHeight / (2 * Math.tan(fovRad / 2)); if (!isFinite(distance) || distance <= 0) distance = 3; - const camY = scaledCenter.y + Math.max(0.5, scaledSize.y * 0.15); - const camZ = distance + 0.6; // kleiner Offset, damit etwas Raum vor dem Modell ist + let camY = scaledCenter.y + Math.max(0.5, scaledSize.y * 0.15); + let camZ = distance + 0.6; // kleiner Offset, damit etwas Raum vor dem Modell ist + + // Apply per-age/gender camera overrides if configured + try { + const genderMap = AGE_CAMERA_OVERRIDES[this.actualGender] || {}; + const specific = genderMap[String(this.actualAge)]; + const def = genderMap.default; + const used = specific || def; + if (used) { + camY += (used.y || 0); + camZ += (used.z || 0); + // expose applied offsets for easier debugging + this.debugInfo.cameraOffset = { y: (used.y || 0), z: (used.z || 0) }; + } + } catch (e) { + // ignore override errors + } + this.camera.position.set(0, camY, camZ); this.camera.lookAt(scaledCenter.x, scaledCenter.y, scaledCenter.z); this.onWindowResize(); + // debug info + this.debugInfo.camera = { x: this.camera.position.x, y: this.camera.position.y, z: this.camera.position.z }; + this.debugInfo.cameraDistance = camZ; + this.debugInfo.ageGroup = this.ageGroup; + this.debugInfo.actualAge = this.actualAge; } } catch (e) { // ignore camera auto-fit errors @@ -582,4 +709,19 @@ export default { object-fit: contain; object-position: center bottom; } + +.character-debug-overlay { + position: absolute; + right: 6px; + top: 6px; + background: rgba(0,0,0,0.6); + color: #fff; + font-size: 11px; + padding: 6px 8px; + border-radius: 6px; + line-height: 1.2; + z-index: 1000; + pointer-events: none; +} +.character-debug-overlay div { opacity: 0.95 } diff --git a/frontend/src/dialogues/falukant/ChildDetailsDialog.vue b/frontend/src/dialogues/falukant/ChildDetailsDialog.vue index 82a4db3..feaee01 100644 --- a/frontend/src/dialogues/falukant/ChildDetailsDialog.vue +++ b/frontend/src/dialogues/falukant/ChildDetailsDialog.vue @@ -12,6 +12,7 @@ >
+ +
{{ $t('falukant.family.children.name') }} @@ -42,6 +43,7 @@ {{ $t('falukant.family.children.notHeir') }}

{{ $t('falukant.family.children.baptismNotice') }}

diff --git a/frontend/src/i18n/locales/ceb/falukant.json b/frontend/src/i18n/locales/ceb/falukant.json index 6c532f6..3f14ed8 100644 --- a/frontend/src/i18n/locales/ceb/falukant.json +++ b/frontend/src/i18n/locales/ceb/falukant.json @@ -910,6 +910,10 @@ "maintenance": "Suporta bulanan", "scandalExtraDailyPct": "Dugang risgo sa iskandalo/adlaw", "monthlyCost": "Gasto kada bulan", + "titleEffects": { + "label": "Epekto sa titulo", + "help": "Giunsa pag-usab sa usa ka titulo sa nobility sa pamatasan o visibility sa usa ka uyab." + }, "politicalFreeSlotsHint": "Ang mga politikal nga opisina naghatag og {count} ka affair slot nga walay bulan nga suporta (ang barato nga relasyon una).", "politicalFreeMaintenance": "Opisina (libre)", "statusFit": "Angay sa kahimtang", @@ -1036,6 +1040,7 @@ }, "householdTension": { "label": "Balayhold Kakulba", + "noReasons": "Walay espesipikong hinungdan nga gi-report.", "score": "Kakulba score", "reasonsLabel": "Current causes", "low": "Calm", @@ -1052,6 +1057,18 @@ "tooFewServants": "Too few sulugoons", "marriageCrisis": "Ubos nga kasal satisfaction (makapasakit sa kalinaw sa balay)" } + , + "reasonsDetail": { + "visibleLover": "Ang usa ka hayag nga relasyon makapahugno sa dungog sa balay.", + "noticeableLover": "Ang relasyon mabantayan ug mosangpot ug tsismis o panagbangi.", + "underfundedLover": "Kulang ang suporta sa relasyon, mosangpot sa kalagot ug risgo sa iskandalo.", + "acknowledgedAffair": "Ang relasyon giila sa publiko ug naghimo ug adlaw-adlaw nga tensiyon.", + "statusMismatch": "Nagkalain-lain nga sosyal nga ranggo nagdala ug panagbangi ug selos.", + "loverChild": "Ang bata gikan sa relasyon magdala ug komplikasyon ug rivalidad sa pamilya.", + "disorder": "Ang kagubot sa balay makadaut sa adlaw-adlaw nga kinabuhi.", + "tooFewServants": "Kulang ang mga sulugoon, nagdugang trabaho ug kasuko sa balay.", + "marriageCrisis": "Kahimtang sa kasal nga dili maayo nagapaubos sa kalinaw sa balay ug makapahimo ug kasuko." + } }, "marriageActions": { "title": "Support ang kasal", diff --git a/frontend/src/i18n/locales/de/falukant.json b/frontend/src/i18n/locales/de/falukant.json index 0e9b8c0..0ef4300 100644 --- a/frontend/src/i18n/locales/de/falukant.json +++ b/frontend/src/i18n/locales/de/falukant.json @@ -687,6 +687,7 @@ }, "householdTension": { "label": "Hausfrieden", + "noReasons": "Keine spezifischen Spannungsgründe.", "score": "Spannungswert", "reasonsLabel": "Aktuelle Ursachen", "low": "Ruhig", @@ -703,6 +704,18 @@ "tooFewServants": "Zu wenig Diener", "marriageCrisis": "Niedrige Ehezufriedenheit (belastet den Hausfrieden)" } + , + "reasonsDetail": { + "visibleLover": "Ein öffentlich sichtbares Verhältnis belastet das Ansehen im Haushalt.", + "noticeableLover": "Die Beziehung ist auffällig und führt zu Gerede oder Konflikten.", + "underfundedLover": "Die Beziehung erhält zu wenig Unterhalt, was Unzufriedenheit und Skandalisierung fördert.", + "acknowledgedAffair": "Die Beziehung ist öffentlich anerkannt und erzeugt Spannungen im Alltag.", + "statusMismatch": "Unterschiedliche soziale Stände führen zu Konflikten und Eifersucht.", + "loverChild": "Ein Kind aus einer Liebschaft verursacht familiäre Komplikationen und Rivalität.", + "disorder": "Unordnung im Haushalt verschlechtert das Zusammenleben.", + "tooFewServants": "Zu wenige Diener erhöhen Arbeitsbelastung und Unzufriedenheit im Haus.", + "marriageCrisis": "Allgemeine Unzufriedenheit in der Ehe verringert den Hausfrieden und kann Verstimmungen auslösen." + } }, "marriageActions": { "title": "Ehe pflegen", @@ -774,6 +787,10 @@ "maintenance": "Unterhalt", "scandalExtraDailyPct": "Zusatz-Skandalrisiko/Tag", "monthlyCost": "Monatskosten", + "titleEffects": { + "label": "Titel-Auswirkungen", + "help": "Wie ein Adelstitel das Verhalten oder die Sichtbarkeit eines Liebhabers beeinflussen kann." + }, "politicalFreeSlotsHint": "Politische Ämter gewähren dir {count} Liebschaftsplatz/-plätze ohne monatlichen Unterhalt (die günstigsten Beziehungen zählen zuerst).", "politicalFreeMaintenance": "Amt (frei)", "statusFit": "Standespassung", diff --git a/frontend/src/i18n/locales/en/falukant.json b/frontend/src/i18n/locales/en/falukant.json index cb4c042..e6438d6 100644 --- a/frontend/src/i18n/locales/en/falukant.json +++ b/frontend/src/i18n/locales/en/falukant.json @@ -927,6 +927,7 @@ }, "householdTension": { "label": "Household Tension", + "noReasons": "No specific causes reported.", "score": "Tension score", "reasonsLabel": "Current causes", "low": "Calm", @@ -943,6 +944,18 @@ "tooFewServants": "Too few servants", "marriageCrisis": "Low marriage satisfaction (strains household peace)" } + , + "reasonsDetail": { + "visibleLover": "A publicly visible affair affects the household's reputation.", + "noticeableLover": "The relationship is noticeable and leads to gossip or conflicts.", + "underfundedLover": "The affair receives too little maintenance, causing dissatisfaction and scandal risk.", + "acknowledgedAffair": "The relationship is acknowledged publicly and creates daily tensions.", + "statusMismatch": "Different social ranks cause conflicts and jealousy.", + "loverChild": "A child from an affair causes family complications and rivalry.", + "disorder": "Disorder in the household worsens daily life.", + "tooFewServants": "Too few servants increase workload and household dissatisfaction.", + "marriageCrisis": "General marital unhappiness reduces household peace and can cause resentments." + } }, "marriageActions": { "title": "Support the marriage", @@ -973,6 +986,10 @@ "maintenance": "Maintenance", "scandalExtraDailyPct": "Extra scandal risk/day", "monthlyCost": "Monthly Cost", + "titleEffects": { + "label": "Title effects", + "help": "How a noble title affects a lover's behavior or visibility." + }, "politicalFreeSlotsHint": "Political offices grant you {count} affair slot(s) with no monthly upkeep (cheapest relationships count first).", "politicalFreeMaintenance": "Office (free)", "statusFit": "Status Fit", diff --git a/frontend/src/i18n/locales/es/falukant.json b/frontend/src/i18n/locales/es/falukant.json index 18cb2b7..2829a3e 100644 --- a/frontend/src/i18n/locales/es/falukant.json +++ b/frontend/src/i18n/locales/es/falukant.json @@ -687,6 +687,7 @@ }, "householdTension": { "label": "Tensión del hogar", + "noReasons": "No hay causas específicas.", "score": "Valor de tensión", "reasonsLabel": "Causas actuales", "low": "Calmo", @@ -703,6 +704,18 @@ "tooFewServants": "Muy pocos sirvientes", "marriageCrisis": "Baja satisfacción conyugal (tensa el ambiente en casa)" } + , + "reasonsDetail": { + "visibleLover": "Una relación visible afecta la reputación del hogar.", + "noticeableLover": "La relación es llamativa y provoca habladurías o conflictos.", + "underfundedLover": "La relación recibe poco mantenimiento, causando descontento y riesgo de escándalo.", + "acknowledgedAffair": "La relación está reconocida públicamente y genera tensiones diarias.", + "statusMismatch": "Diferentes rangos sociales causan conflictos y celos.", + "loverChild": "Un hijo de una relación provoca complicaciones familiares y rivalidades.", + "disorder": "El desorden en la casa empeora la convivencia.", + "tooFewServants": "Muy pocos sirvientes aumentan la carga de trabajo y el descontento.", + "marriageCrisis": "Insatisfacción marital general reduce la paz del hogar y puede causar resentimientos." + } }, "marriageActions": { "title": "Cuidar el matrimonio", @@ -774,6 +787,10 @@ "maintenance": "Mantenimiento", "scandalExtraDailyPct": "Riesgo extra de escándalo/día", "monthlyCost": "Coste mensual", + "titleEffects": { + "label": "Efectos del título", + "help": "Cómo un título nobiliario afecta el comportamiento o la visibilidad de un amante." + }, "politicalFreeSlotsHint": "Los cargos políticos te conceden {count} plaza(s) de relación sin mantenimiento mensual (primero cuentan las relaciones más baratas).", "politicalFreeMaintenance": "Cargo (gratis)", "statusFit": "Adecuación social", diff --git a/frontend/src/i18n/locales/fr/falukant.json b/frontend/src/i18n/locales/fr/falukant.json index 76633ed..17c9d3e 100644 --- a/frontend/src/i18n/locales/fr/falukant.json +++ b/frontend/src/i18n/locales/fr/falukant.json @@ -685,6 +685,7 @@ }, "householdTension": { "label": "Paix dans la maison", + "noReasons": "Aucune cause spécifique signalée.", "score": "Valeur de tension", "reasonsLabel": "Causes actuelles", "low": "Calme", @@ -701,6 +702,18 @@ "tooFewServants": "Trop peu de serviteurs", "marriageCrisis": "Faible satisfaction du couple (tension au foyer)" } + , + "reasonsDetail": { + "visibleLover": "Une relation visible porte atteinte à la réputation du foyer.", + "noticeableLover": "La relation est remarquée et provoque des commérages ou des conflits.", + "underfundedLover": "La relation reçoit trop peu d'entretien, entraînant mécontentement et risque de scandale.", + "acknowledgedAffair": "La relation est reconnue publiquement et crée des tensions quotidiennes.", + "statusMismatch": "Des rangs sociaux différents provoquent des conflits et de la jalousie.", + "loverChild": "Un enfant issu d'une relation cause des complications familiales et des rivalités.", + "disorder": "Le désordre dans le foyer dégrade la vie quotidienne.", + "tooFewServants": "Trop peu de domestiques augmentent la charge de travail et le mécontentement.", + "marriageCrisis": "Un malheur conjugal général réduit la paix du foyer et peut provoquer des ressentiments." + } }, "marriageActions": { "title": "Maintenir le mariage", @@ -772,6 +785,10 @@ "maintenance": "Entretien", "scandalExtraDailyPct": "Risque de scandale supplémentaire/jour", "monthlyCost": "Coûts mensuels", + "titleEffects": { + "label": "Effets du titre", + "help": "Comment un titre de noblesse influence le comportement ou la visibilité d'un amant." + }, "politicalFreeSlotsHint": "Les bureaux politiques vous accordent {count} intérêts amoureux sans entretien mensuel (les relations les moins chères comptent en premier).", "politicalFreeMaintenance": "Bureau (vacant)", "statusFit": "Ajustement de classe", diff --git a/frontend/src/router/falukantRoutes.js b/frontend/src/router/falukantRoutes.js index 156ff31..5e8a18d 100644 --- a/frontend/src/router/falukantRoutes.js +++ b/frontend/src/router/falukantRoutes.js @@ -3,6 +3,7 @@ const Createview = () => import('../views/falukant/CreateView.vue'); const FalukantOverviewView = () => import('../views/falukant/OverviewView.vue'); const MoneyHistoryView = () => import('../views/falukant/MoneyHistoryView.vue'); const FamilyView = () => import('../views/falukant/FamilyView.vue'); +const AllCharactersTest = () => import('../views/falukant/AllCharactersTest.vue'); const HouseView = () => import('../views/falukant/HouseView.vue'); const NobilityView = () => import('../views/falukant/NobilityView.vue'); const ReputationView = () => import('../views/falukant/ReputationView.vue'); @@ -45,6 +46,12 @@ const falukantRoutes = [ component: FamilyView, meta: { requiresAuth: true } }, + { + path: '/falukant/dev-all-characters', + name: 'FalukantAllCharactersTest', + component: AllCharactersTest, + meta: { requiresAuth: true } + }, { path: '/falukant/house', name: 'HouseView', diff --git a/frontend/src/views/falukant/AllCharactersTest.vue b/frontend/src/views/falukant/AllCharactersTest.vue new file mode 100644 index 0000000..4012c83 --- /dev/null +++ b/frontend/src/views/falukant/AllCharactersTest.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/frontend/src/views/falukant/FamilyView.vue b/frontend/src/views/falukant/FamilyView.vue index 4ab4af1..3741f37 100644 --- a/frontend/src/views/falukant/FamilyView.vue +++ b/frontend/src/views/falukant/FamilyView.vue @@ -275,6 +275,23 @@ {{ $t('falukant.family.householdTension.reasons.' + reason) }}
+
+
    +
  • + {{ $t('falukant.family.householdTension.reasons.' + reason) }}: + + {{ $t('falukant.family.householdTension.reasonsDetail.' + reason) || $t('falukant.family.householdTension.reasons.' + reason) }} + +
  • +
+
+
+
+

{{ $t('falukant.family.householdTension.noReasons') || 'Keine spezifischen Spannungsgründe angegeben.' }}

+
+

Dev: rohdaten

+
{{ JSON.stringify({ householdTension, householdTensionScore, householdTensionReasons, relationships: relationships && relationships[0] ? { marriageState: relationships[0].marriageState, marriageSatisfaction: relationships[0].marriageSatisfaction, marriageFlags: relationships[0].marriageFlags } : null }, null, 2) }}
+
@@ -449,7 +466,7 @@
{{ lover.statusFit }}
-
+
{{ $t('falukant.family.lovers.underfunded', { count: lover.monthsUnderfunded }) }} + +
+ {{ $t('falukant.family.lovers.titleEffects.label') || 'Titel-Auswirkungen' }} +
    +
  • + {{ te.title || te.name || te.key }}: {{ te.effect || te.impact || JSON.stringify(te) }} +
  • +
  • + {{ key }}: {{ val }} +
  • +
+
+
+
+ Dev: Lover raw +
{{ JSON.stringify(lover, null, 2) }}
+
+