ytptube/ui/app/stores/NotificationStore.ts
2026-03-25 22:59:53 +03:00

96 lines
2.8 KiB
TypeScript

import { defineStore } from 'pinia';
import { useStorage } from '@vueuse/core';
import type { notification, notificationType } from '~/composables/useNotification';
const _map: Record<notificationType, { level: number; color: string; icon: string }> = {
error: { level: 3, color: 'error', icon: 'i-lucide-triangle-alert' },
warning: { level: 2, color: 'warning', icon: 'i-lucide-circle-alert' },
success: { level: 1, color: 'success', icon: 'i-lucide-badge-check' },
info: { level: 0, color: 'info', icon: 'i-lucide-info' },
};
export const useNotificationStore = defineStore('notifications', () => {
const notifications = useStorage<notification[]>('notifications', []);
const unreadCount = computed<number>(() => notifications.value.filter((n) => !n.seen).length);
const severityLevel = computed<notificationType | null>(() => {
const unread = notifications.value.filter((n) => !n.seen);
if (0 === unread.length) {
return null;
}
return unread.reduce((h, n) => (_map[n.level].level > _map[h.level].level ? n : h)).level;
});
const severityColor = computed<string>(() => {
const level = severityLevel.value;
return level ? _map[level].color : '';
});
const severityIcon = computed<string>(() => {
const level = severityLevel.value;
return level ? _map[level].icon : '';
});
const sortedNotifications = computed<notification[]>(() => {
return [...notifications.value].sort((a, b) => {
const severityDiff = _map[b.level].level - _map[a.level].level;
if (0 !== severityDiff) {
return severityDiff;
}
return new Date(b.created).getTime() - new Date(a.created).getTime();
});
});
const add = (level: notificationType, message: string, seen: boolean = false): string => {
const id = Array.from(window.crypto.getRandomValues(new Uint8Array(14 / 2)), (dec: any) =>
dec.toString(16).padStart(2, '0'),
).join('');
notifications.value.unshift({
id: id,
message,
level,
seen: seen,
created: new Date(),
});
if (notifications.value.length > 99) {
notifications.value.length = 99;
}
return id;
};
const clear = () => (notifications.value = []);
const markAllRead = () => notifications.value.forEach((n) => (n.seen = true));
const markRead = (id: string) => {
const n = notifications.value.find((n) => n.id === id);
if (!n) {
return;
}
n.seen = true;
};
const get = (id: string): notification | undefined =>
notifications.value.find((n) => n.id === id);
const remove = (id: string) =>
(notifications.value = notifications.value.filter((n) => n.id !== id));
return {
notifications,
unreadCount,
severityLevel,
severityColor,
severityIcon,
sortedNotifications,
add,
get,
markAllRead,
clear,
markRead,
remove,
};
});