NotificationStore
A NotificationStore egy globális Svelte 5 store, amely kezeli az értesítések állapotát és a Socket.IO kapcsolatot. Automatikusan fallback-el REST API polling-ra, ha a WebSocket nem elérhető.
Automatikus Fallback
Szekció neve “Automatikus Fallback”A store intelligensen kezeli a kapcsolati problémákat:
- Socket.IO kapcsolódás sikeres → Valós idejű értesítések WebSocket-en
- Socket.IO kapcsolódás sikertelen → Automatikus polling 30 másodpercenként
- Socket.IO kapcsolat megszakad → Automatikus átváltás polling-ra
- Socket.IO újrakapcsolódik → Automatikus visszaváltás WebSocket-re
// Automatikus inicializálásconst notificationStore = getNotificationStore();await notificationStore.connect(userId);
// A store automatikusan:// 1. Megpróbál Socket.IO-val kapcsolódni// 2. Ha sikertelen, elindítja a polling-ot// 3. Betölti az értesítéseket REST API-n keresztül// 4. 30 másodpercenként frissít, ha nincs WebSocket kapcsolatHasználat
Szekció neve “Használat”Store Lekérése
Szekció neve “Store Lekérése”import { getNotificationStore } from '$lib/stores/notificationStore.svelte';
const notificationStore = getNotificationStore();Reaktív Állapot
Szekció neve “Reaktív Állapot”// Értesítések listájaconst notifications = $derived(notificationStore.notifications);
// Olvasatlan értesítések számaconst unreadCount = $derived(notificationStore.unreadCount);
// Socket.IO kapcsolat állapotaconst isConnected = $derived(notificationStore.isConnected);
// Aktuális kritikus értesítés (ha van)const currentCritical = $derived(notificationStore.currentCritical);
// Van-e olvasatlan kritikus értesítésconst hasUnreadCritical = $derived(notificationStore.hasUnreadCritical);Svelte Komponensben
Szekció neve “Svelte Komponensben”<script> import { getNotificationStore } from '$lib/stores/notificationStore.svelte';
const notificationStore = getNotificationStore();
const notifications = $derived(notificationStore.notifications); const unreadCount = $derived(notificationStore.unreadCount);</script>
<div> <p>Olvasatlan értesítések: {unreadCount}</p>
{#each notifications as notification} <div> <h3>{notification.title}</h3> <p>{notification.message}</p> </div> {/each}</div>API Metódusok
Szekció neve “API Metódusok”connect(userId)
Szekció neve “connect(userId)”Socket.IO kapcsolat inicializálása és értesítések betöltése.
await notificationStore.connect(123);Automatikusan megtörténik: A hooks.client.ts automatikusan meghívja bejelentkezéskor.
disconnect()
Szekció neve “disconnect()”Socket.IO kapcsolat bontása.
notificationStore.disconnect();loadNotifications(showToast?)
Szekció neve “loadNotifications(showToast?)”Értesítések betöltése REST API-n keresztül.
await notificationStore.loadNotifications();
// Toast megjelenítéssel (dev módban)await notificationStore.loadNotifications(true);Automatikusan megtörténik:
- Inicializáláskor
- 30 másodpercenként, ha Socket.IO nem elérhető
reload()
Szekció neve “reload()”Értesítések újratöltése toast megjelenítéssel (hasznos dev módban).
await notificationStore.reload();markAsRead(notificationId)
Szekció neve “markAsRead(notificationId)”Értesítés olvasottnak jelölése.
await notificationStore.markAsRead(123);Hatás:
- Lokális állapot frissítése
- REST API hívás
- Socket.IO emit (ha elérhető)
markAllAsRead()
Szekció neve “markAllAsRead()”Összes értesítés olvasottnak jelölése.
await notificationStore.markAllAsRead();deleteNotification(notificationId)
Szekció neve “deleteNotification(notificationId)”Értesítés törlése.
await notificationStore.deleteNotification(123);deleteAllNotifications()
Szekció neve “deleteAllNotifications()”Összes értesítés törlése.
await notificationStore.deleteAllNotifications();sendNotification(payload)
Szekció neve “sendNotification(payload)”Új értesítés küldése.
await notificationStore.sendNotification({ userId: 123, title: { hu: 'Teszt', en: 'Test' }, message: { hu: 'Teszt üzenet', en: 'Test message' }, type: 'info'});Megjegyzés: Inkább használd a sendNotification függvényt a notificationService-ből.
getAppNotifications(appName)
Szekció neve “getAppNotifications(appName)”Egy adott app értesítéseinek lekérése.
const userNotifications = notificationStore.getAppNotifications('users');getAppUnreadCount(appName)
Szekció neve “getAppUnreadCount(appName)”Egy adott app olvasatlan értesítéseinek száma.
const unreadCount = notificationStore.getAppUnreadCount('users');acknowledgeCritical()
Szekció neve “acknowledgeCritical()”Aktuális kritikus értesítés elismerése (eltávolítás a sorból).
notificationStore.acknowledgeCritical();Automatikusan megtörténik: A CriticalNotificationDialog komponens meghívja az OK gomb kattintásakor.
Állapot Tulajdonságok
Szekció neve “Állapot Tulajdonságok”notifications
Szekció neve “notifications”Értesítések tömbje, időrendben csökkenő sorrendben.
const notifications: Notification[] = notificationStore.notifications;unreadCount
Szekció neve “unreadCount”Olvasatlan értesítések száma.
const unreadCount: number = notificationStore.unreadCount;isConnected
Szekció neve “isConnected”Socket.IO kapcsolat állapota.
const isConnected: boolean = notificationStore.isConnected;currentCritical
Szekció neve “currentCritical”Aktuális kritikus értesítés (első a sorban).
const currentCritical: Notification | null = notificationStore.currentCritical;hasUnreadCritical
Szekció neve “hasUnreadCritical”Van-e olvasatlan kritikus értesítés.
const hasUnreadCritical: boolean = notificationStore.hasUnreadCritical;Inicializálás
Szekció neve “Inicializálás”A store automatikusan inicializálódik a hooks.client.ts-ben:
import { getNotificationStore } from '$lib/stores/notificationStore.svelte';
export async function handleSession({ data }) { if (data.user?.id) { const notificationStore = getNotificationStore(); await notificationStore.connect(parseInt(data.user.id)); }}Belső Működés
Szekció neve “Belső Működés”Socket.IO Események Kezelése
Szekció neve “Socket.IO Események Kezelése”// Új értesítés érkezettsocket.on('notification:new', (notification: Notification) => { // Hozzáadás a listához this.state.notifications = [notification, ...this.state.notifications]; this.state.unreadCount++;
// Toast megjelenítése (kivéve critical) this.showToastNotification(notification);
// Browser értesítés this.showBrowserNotification(notification);});
// Olvasatlan számláló frissítésesocket.on('notification:unread-count', (count: number) => { this.state.unreadCount = count;});Automatikus Polling
Szekció neve “Automatikus Polling”// 30 másodpercenként polling, ha Socket.IO nem elérhetősetInterval(() => { if (browser && !this.state.isConnected) { console.log('[NotificationStore] WebSocket disconnected, polling for notifications'); this.loadNotifications(); }}, 30000);Toast Megjelenítés
Szekció neve “Toast Megjelenítés”private showToastNotification(notification: Notification) { // Critical értesítések a dialog-ba kerülnek if (notification.type === 'critical') { this._criticalQueue = [...this._criticalQueue, notification]; return; }
// Toast megjelenítése import('svelte-sonner').then(({ toast }) => { const toastFn = toast[notification.type] || toast.info; toastFn(title, { description: message, duration: 5000, action: { label: 'Megnyitás', onClick: () => this.openNotificationInApp(notification.id) } }); });}Példák
Szekció neve “Példák”Értesítések Megjelenítése Listában
Szekció neve “Értesítések Megjelenítése Listában”<script> import { getNotificationStore } from '$lib/stores/notificationStore.svelte';
const notificationStore = getNotificationStore(); const notifications = $derived(notificationStore.notifications);
async function handleMarkAsRead(id: number) { await notificationStore.markAsRead(id); }
async function handleDelete(id: number) { await notificationStore.deleteNotification(id); }</script>
<div> {#each notifications as notification} <div class:unread={!notification.isRead}> <h3>{notification.title}</h3> <p>{notification.message}</p> <p>{new Date(notification.createdAt).toLocaleString()}</p>
{#if !notification.isRead} <button onclick={() => handleMarkAsRead(notification.id)}> Olvasottnak jelölés </button> {/if}
<button onclick={() => handleDelete(notification.id)}> Törlés </button> </div> {/each}</div>Olvasatlan Számláló Badge
Szekció neve “Olvasatlan Számláló Badge”<script> import { getNotificationStore } from '$lib/stores/notificationStore.svelte';
const notificationStore = getNotificationStore(); const unreadCount = $derived(notificationStore.unreadCount);</script>
<button> Értesítések {#if unreadCount > 0} <span class="badge">{unreadCount}</span> {/if}</button>App-Specifikus Értesítések
Szekció neve “App-Specifikus Értesítések”<script> import { getNotificationStore } from '$lib/stores/notificationStore.svelte';
const notificationStore = getNotificationStore(); const appNotifications = $derived(notificationStore.getAppNotifications('users')); const appUnreadCount = $derived(notificationStore.getAppUnreadCount('users'));</script>
<div> <h2>Users App Értesítések ({appUnreadCount} olvasatlan)</h2>
{#each appNotifications as notification} <div>{notification.message}</div> {/each}</div>Kapcsolat Állapot Megjelenítése
Szekció neve “Kapcsolat Állapot Megjelenítése”<script> import { getNotificationStore } from '$lib/stores/notificationStore.svelte';
const notificationStore = getNotificationStore(); const isConnected = $derived(notificationStore.isConnected);</script>
<div class="status"> {#if isConnected} <span class="online">● Online (WebSocket)</span> {:else} <span class="offline">● Offline (Polling)</span> {/if}</div>