From b64817520573aec7023933f7cc4bfd59eaffee1c Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 2 Feb 2026 07:48:53 +0100 Subject: [PATCH] Refactor trigger creation logic: Update the created_at and updated_at fields to use the election date instead of the current timestamp, ensuring accurate term end calculations. Enhance socket event handling in StatusBar component by implementing setup and teardown methods for improved event management and user notifications. --- backend/models/trigger.js | 7 +- backend/services/falukantService.js | 5 +- .../src/components/falukant/StatusBar.vue | 66 ++++++++++++++----- 3 files changed, 57 insertions(+), 21 deletions(-) diff --git a/backend/models/trigger.js b/backend/models/trigger.js index 295ec73..cd87394 100644 --- a/backend/models/trigger.js +++ b/backend/models/trigger.js @@ -350,15 +350,16 @@ export async function createTriggers() { SELECT * FROM random_fill ), - -- 8) Neue Ämter anlegen und sofort zurückliefern + -- 8) Neue Ämter anlegen – created_at = Wahldatum (Amtsbeginn), nicht NOW() + -- damit termEnds = Amtsbeginn + termLength korrekt berechnet werden kann created_offices AS ( INSERT INTO falukant_data.political_office (office_type_id, character_id, created_at, updated_at, region_id) SELECT tp.tp_office_type_id, fw.character_id, - NOW() AS created_at, - NOW() AS updated_at, + tp.tp_election_date AS created_at, + tp.tp_election_date AS updated_at, tp.tp_region_id FROM final_winners fw JOIN to_process tp diff --git a/backend/services/falukantService.js b/backend/services/falukantService.js index 6ff6623..a790f17 100644 --- a/backend/services/falukantService.js +++ b/backend/services/falukantService.js @@ -3535,8 +3535,9 @@ class FalukantService extends BaseService { firstName: firstNameObject.id, }); updateFalukantUserMoney(falukantUser.id, -50, 'Baptism', falukantUser.id); - // Trigger status bar refresh for the user after baptism - notifyUser(hashedUserId, 'falukantUpdateStatus', {}); + // Trigger status bar refresh (children count) and family view update + await notifyUser(hashedUserId, 'falukantUpdateStatus', {}); + await notifyUser(hashedUserId, 'familychanged', {}); return { success: true }; } catch (error) { throw new Error(error.message); diff --git a/frontend/src/components/falukant/StatusBar.vue b/frontend/src/components/falukant/StatusBar.vue index e3bb0be..73b2a67 100644 --- a/frontend/src/components/falukant/StatusBar.vue +++ b/frontend/src/components/falukant/StatusBar.vue @@ -64,6 +64,17 @@ export default { this.preloadQuickAccessImages(); }, deep: true + }, + socket(newVal, oldVal) { + if (oldVal) this.teardownSocketListeners(); + if (newVal) this.setupSocketListeners(); + }, + daemonSocket(newVal, oldVal) { + if (oldVal && this._daemonHandler) { + oldVal.removeEventListener('message', this._daemonHandler); + this._daemonHandler = null; + } + if (newVal) this.setupDaemonListeners(); } }, async mounted() { @@ -72,24 +83,13 @@ export default { // Bilder für Schnellzugriff vorladen und cachen this.preloadQuickAccessImages(); - // Live-Socket-Events - ["falukantUpdateStatus", "stock_change", "familychanged"].forEach(eventName => { - if (this.daemonSocket) { - this.daemonSocket.addEventListener('message', (event) => { - try { - const data = JSON.parse(event.data); - if (data.event === eventName) { - this.handleEvent(data); - } - } catch (error) { - // Ignore non-JSON messages like ping/pong - } - }); - } - }); + // Socket.IO (Backend notifyUser) – Hauptkanal für Falukant-Events + this.setupSocketListeners(); + this.setupDaemonListeners(); }, beforeUnmount() { - // Daemon WebSocket wird automatisch beim Logout geschlossen + this.teardownSocketListeners(); + this.teardownDaemonListeners(); }, methods: { preloadQuickAccessImages() { @@ -155,6 +155,40 @@ export default { // Error fetching status } }, + setupSocketListeners() { + this.teardownSocketListeners(); + if (!this.socket) return; + this.socket.on('falukantUpdateStatus', (data) => this.handleEvent({ event: 'falukantUpdateStatus', ...data })); + this.socket.on('stock_change', (data) => this.handleEvent({ event: 'stock_change', ...data })); + this.socket.on('familychanged', (data) => this.handleEvent({ event: 'familychanged', ...data })); + }, + teardownSocketListeners() { + if (this.socket) { + this.socket.off('falukantUpdateStatus'); + this.socket.off('stock_change'); + this.socket.off('familychanged'); + } + }, + setupDaemonListeners() { + this.teardownDaemonListeners(); + if (!this.daemonSocket) return; + this._daemonHandler = (event) => { + try { + const data = JSON.parse(event.data); + if (['falukantUpdateStatus', 'stock_change', 'familychanged'].includes(data.event)) { + this.handleEvent(data); + } + } catch (_) {} + }; + this.daemonSocket.addEventListener('message', this._daemonHandler); + }, + teardownDaemonListeners() { + const sock = this.daemonSocket; + if (sock && this._daemonHandler) { + sock.removeEventListener('message', this._daemonHandler); + this._daemonHandler = null; + } + }, handleEvent(eventData) { switch (eventData.event) { case 'falukantUpdateStatus':