// Notification System Composable // Provides consistent toast, alert, and confirmation patterns import { ref, reactive, readonly } from 'vue'; import { useDesignSystem } from './useDesignSystem'; // Global notification state const notifications = ref([]); const nextId = ref(1); export const useNotifications = () => { const { statusColors, utils } = useDesignSystem(); // Generate unique ID for notifications const generateId = () => nextId.value++; // Notification types const types = { SUCCESS: 'success', ERROR: 'error', WARNING: 'warning', INFO: 'info' }; // Default configuration const defaultConfig = { duration: 5000, persistent: false, position: 'top-right', showIcon: true, showClose: true, allowHtml: false, maxNotifications: 5 }; // Add notification to queue const addNotification = (notification) => { const id = generateId(); const config = { ...defaultConfig, ...notification, id }; // Limit number of notifications if (notifications.value.length >= defaultConfig.maxNotifications) { notifications.value.shift(); } notifications.value.push(config); // Auto-remove if not persistent if (!config.persistent && config.duration > 0) { setTimeout(() => { removeNotification(id); }, config.duration); } return id; }; // Remove notification by ID const removeNotification = (id) => { const index = notifications.value.findIndex(n => n.id === id); if (index > -1) { notifications.value.splice(index, 1); } }; // Clear all notifications const clearAll = () => { notifications.value = []; }; // Success notification const success = (message, options = {}) => { return addNotification({ type: types.SUCCESS, title: options.title || 'Success', message, icon: 'mdi:check-circle', ...options }); }; // Error notification const error = (message, options = {}) => { return addNotification({ type: types.ERROR, title: options.title || 'Error', message, icon: 'mdi:alert-circle', persistent: options.persistent !== undefined ? options.persistent : true, ...options }); }; // Warning notification const warning = (message, options = {}) => { return addNotification({ type: types.WARNING, title: options.title || 'Warning', message, icon: 'mdi:alert', duration: options.duration || 7000, ...options }); }; // Info notification const info = (message, options = {}) => { return addNotification({ type: types.INFO, title: options.title || 'Information', message, icon: 'mdi:information', ...options }); }; // Confirmation dialog const confirm = (options = {}) => { return new Promise((resolve) => { const id = addNotification({ type: 'confirm', title: options.title || 'Confirm Action', message: options.message || 'Are you sure you want to proceed?', icon: options.icon || 'mdi:help-circle', persistent: true, showClose: false, actions: [ { label: options.cancelLabel || 'Cancel', variant: 'secondary-outline', action: () => { removeNotification(id); resolve(false); } }, { label: options.confirmLabel || 'Confirm', variant: options.dangerous ? 'danger' : 'primary', action: () => { removeNotification(id); resolve(true); } } ], ...options }); }); }; // Loading notification with promise const loading = (promise, options = {}) => { const id = addNotification({ type: 'loading', title: options.title || 'Loading...', message: options.message || 'Please wait...', icon: 'mdi:loading', persistent: true, showClose: false, ...options }); return promise .then((result) => { removeNotification(id); if (options.successMessage) { success(options.successMessage); } return result; }) .catch((err) => { removeNotification(id); if (options.errorMessage) { error(options.errorMessage); } else { error(err.message || 'An error occurred'); } throw err; }); }; // DMS-specific notifications const dms = { // Document operations documentUploaded: (filename, count = 1) => { const message = count === 1 ? `Document "${filename}" uploaded successfully` : `${count} documents uploaded successfully`; return success(message, { title: 'Upload Complete' }); }, documentDeleted: (filename) => { return success(`Document "${filename}" deleted successfully`, { title: 'Document Deleted' }); }, documentShared: (filename, users) => { const userCount = Array.isArray(users) ? users.length : 1; const message = `Document "${filename}" shared with ${userCount} user${userCount > 1 ? 's' : ''}`; return success(message, { title: 'Document Shared' }); }, // Permission changes accessGranted: (resource) => { return success(`Access granted to ${resource}`, { title: 'Access Granted' }); }, accessRevoked: (resource) => { return warning(`Access revoked for ${resource}`, { title: 'Access Revoked' }); }, // Sync operations syncStarted: () => { return info('Synchronization started', { title: 'Sync in Progress', duration: 3000 }); }, syncCompleted: (itemCount) => { return success(`Synchronization completed. ${itemCount} items updated.`, { title: 'Sync Complete' }); }, syncFailed: (error) => { return error(`Synchronization failed: ${error}`, { title: 'Sync Error' }); }, // Version control newVersionCreated: (filename, version) => { return success(`Version ${version} created for "${filename}"`, { title: 'New Version' }); }, versionRestored: (filename, version) => { return success(`Document "${filename}" restored to version ${version}`, { title: 'Version Restored' }); }, // Audit & Security unauthorizedAccess: (resource) => { return error(`Unauthorized access attempt to ${resource}`, { title: 'Security Alert', persistent: true }); }, sessionExpiring: (minutes) => { return warning(`Your session will expire in ${minutes} minutes`, { title: 'Session Warning', duration: 10000 }); } }; // Bulk operations helper const bulk = { success: (operations) => { const count = operations.length; const message = `${count} operation${count > 1 ? 's' : ''} completed successfully`; return success(message, { title: 'Bulk Operation Complete' }); }, partialSuccess: (successful, failed) => { const message = `${successful} operation(s) completed, ${failed} failed`; return warning(message, { title: 'Partial Success' }); }, failed: (count, error) => { const message = `${count} operation(s) failed: ${error}`; return error(message, { title: 'Bulk Operation Failed' }); } }; return { // State notifications: readonly(notifications), // Core methods success, error, warning, info, confirm, loading, // Management removeNotification, clearAll, // DMS-specific dms, bulk, // Utilities types, defaultConfig }; }; // Global instance for app-wide usage let globalInstance = null; export const setupNotifications = () => { if (!globalInstance) { globalInstance = useNotifications(); } return globalInstance; }; export const useGlobalNotifications = () => { if (!globalInstance) { throw new Error('Notifications not initialized. Call setupNotifications() first.'); } return globalInstance; };