diff --git a/assets/controllers/notifications_controller.js b/assets/controllers/notifications_controller.js new file mode 100644 index 0000000..cfb31a3 --- /dev/null +++ b/assets/controllers/notifications_controller.js @@ -0,0 +1,77 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + static targets = ['badge', 'list']; + + connect() { + this._poll(); + this._interval = setInterval(() => this._poll(), 30000); + } + + disconnect() { + clearInterval(this._interval); + } + + async _poll() { + try { + const response = await fetch('/api/notifications'); + if (!response.ok) return; + + const data = await response.json(); + this._updateBadge(data.unreadCount); + this._updateTitle(data.unreadCount); + this._updateList(data.notifications); + } catch (e) { + // silently ignore polling errors + } + } + + _updateBadge(count) { + if (count > 0) { + this.badgeTarget.textContent = count; + this.badgeTarget.hidden = false; + } else { + this.badgeTarget.hidden = true; + } + } + + _updateTitle(count) { + const base = 'Actorle'; + document.title = count > 0 ? `(${count}) ${base}` : base; + } + + _updateList(notifications) { + if (notifications.length === 0) { + this.listTarget.innerHTML = '
Aucune notification
'; + return; + } + + this.listTarget.innerHTML = notifications.map(n => ` +${this._escapeHtml(n.message)}
+ +