import { ref } from 'vue' export const useNotificationLogs = () => { // Use Nuxt's useFetch instead of $fetch const config = useRuntimeConfig() // Logs data state const logs = ref([]) const loading = ref(false) const error = ref(null) const pagination = ref({ page: 1, limit: 10, total: 0, pages: 1 }) const summaryStats = ref({ totalLogs: 0, failedDeliveries: 0, successfulDeliveries: 0, successRate: 0 }) // Filters state const filters = ref({ startDate: null, endDate: null, action: null, channel: null, status: null, actor: '', keyword: '' }) // Analytics state const analyticsData = ref(null) const analyticsLoading = ref(false) const analyticsError = ref(null) // Monitoring state const monitoringData = ref(null) const monitoringLoading = ref(false) const monitoringError = ref(null) // Fetch logs with filters and pagination const fetchLogs = async () => { try { loading.value = true error.value = null // Build query parameters const queryParams = new URLSearchParams() queryParams.append('page', pagination.value.page) queryParams.append('limit', pagination.value.limit) // Add filters if they exist if (filters.value.startDate) queryParams.append('startDate', filters.value.startDate) if (filters.value.endDate) queryParams.append('endDate', filters.value.endDate) if (filters.value.action) queryParams.append('action', filters.value.action) if (filters.value.channel) queryParams.append('channel', filters.value.channel) if (filters.value.status) queryParams.append('status', filters.value.status) if (filters.value.actor) queryParams.append('actor', filters.value.actor) if (filters.value.keyword) queryParams.append('keyword', filters.value.keyword) // Make API call with useFetch const { data, error: fetchError } = await useFetch(`/api/notifications/logs`, { method: 'GET', params: { page: pagination.value.page, limit: pagination.value.limit, ...filters.value } }) if (fetchError.value) { throw new Error(fetchError.value.message || 'Failed to fetch logs'); } if (data.value && data.value.body && data.value.body.success) { logs.value = data.value.body.data.logs || []; pagination.value = data.value.body.data.pagination || pagination.value; // Ensure summary stats are properly assigned if (data.value.body.data.summary) { summaryStats.value = { totalLogs: data.value.body.data.summary.totalLogs || 0, failedDeliveries: data.value.body.data.summary.failedDeliveries || 0, successfulDeliveries: data.value.body.data.summary.successfulDeliveries || 0, successRate: data.value.body.data.summary.successRate || 0 }; } console.log('Logs fetched successfully:', { logsCount: logs.value.length, pagination: pagination.value, summaryStats: summaryStats.value }); } else { throw new Error('Failed to fetch logs: ' + (data.value?.body?.message || 'Unknown error')) } } catch (err) { error.value = err.message || 'An error occurred' console.error('Error fetching logs:', err) } finally { loading.value = false } } // Get a specific log by ID const getLogById = async (id) => { try { loading.value = true error.value = null // Make API call const { data } = await useFetch(`/api/notifications/logs/${id}`, { method: 'GET' }) if (data.value && data.value.body && data.value.body.success) { return data.value.body.data } else { throw new Error('Failed to fetch log details') } } catch (err) { error.value = err.message || 'An error occurred' console.error('Error fetching log details:', err) return null } finally { loading.value = false } } // Update filters and fetch logs const applyFilters = async (newFilters) => { filters.value = { ...filters.value, ...newFilters } pagination.value.page = 1 // Reset to first page when filters change await fetchLogs() } // Clear all filters const clearFilters = async () => { filters.value = { startDate: null, endDate: null, action: null, channel: null, status: null, actor: '', keyword: '' } pagination.value.page = 1 await fetchLogs() } // Change page const changePage = async (page) => { pagination.value.page = page await fetchLogs() } // Fetch analytics data const fetchAnalytics = async (period = '7d', channel = 'all') => { try { analyticsLoading.value = true analyticsError.value = null // Make API call const { data } = await useFetch(`/api/notifications/logs/analytics`, { method: 'GET', params: { period, channel } }) if (data.value && data.value.body && data.value.body.success) { analyticsData.value = data.value.body.data } else { throw new Error('Failed to fetch analytics data') } } catch (err) { analyticsError.value = err.message || 'An error occurred' console.error('Error fetching analytics data:', err) } finally { analyticsLoading.value = false } } // Fetch monitoring data const fetchMonitoringData = async () => { try { monitoringLoading.value = true monitoringError.value = null // Make API call const { data } = await useFetch('/api/notifications/logs/monitoring', { method: 'GET' }) if (data.value && data.value.body && data.value.body.success) { monitoringData.value = data.value.body.data } else { throw new Error('Failed to fetch monitoring data') } } catch (err) { monitoringError.value = err.message || 'An error occurred' console.error('Error fetching monitoring data:', err) } finally { monitoringLoading.value = false } } // Format date for display const formatDate = (date, includeTime = false) => { if (!date) return '' const options = { year: 'numeric', month: 'short', day: 'numeric' } if (includeTime) { options.hour = '2-digit' options.minute = '2-digit' } return new Date(date).toLocaleDateString(undefined, options) } // Format time ago (e.g., "2 minutes ago") const formatTimeAgo = (timestamp) => { const now = new Date() const time = new Date(timestamp) const diffInMinutes = Math.floor((now - time) / (1000 * 60)) if (diffInMinutes < 1) return "Just now" if (diffInMinutes < 60) return `${diffInMinutes} minutes ago` if (diffInMinutes < 1440) return `${Math.floor(diffInMinutes / 60)} hours ago` return `${Math.floor(diffInMinutes / 1440)} days ago` } // Get available actions for filters const availableActions = [ { label: 'All Actions', value: null }, { label: 'Notification Created', value: 'Notification Created' }, { label: 'Notification Sent', value: 'Notification Sent' }, { label: 'Delivery Attempted', value: 'Delivery Attempted' }, { label: 'Delivery Failed', value: 'Delivery Failed' }, { label: 'Notification Opened', value: 'Notification Opened' }, { label: 'Template Updated', value: 'Template Updated' }, { label: 'Notification Queued', value: 'Notification Queued' }, ] // Get available channels for filters const availableChannels = [ { label: 'All Channels', value: null }, { label: 'Email', value: 'Email' }, { label: 'SMS', value: 'SMS' }, { label: 'Push Notification', value: 'Push Notification' }, { label: 'Webhook', value: 'Webhook' } ] // Get available statuses for filters const availableStatuses = [ { label: 'All Statuses', value: null }, { label: 'Sent', value: 'Sent' }, { label: 'Failed', value: 'Failed' }, { label: 'Bounced', value: 'Bounced' }, { label: 'Opened', value: 'Opened' }, { label: 'Queued', value: 'Queued' }, { label: 'Created', value: 'Created' }, { label: 'Updated', value: 'Updated' } ] return { // State logs, loading, error, pagination, summaryStats, filters, analyticsData, analyticsLoading, analyticsError, monitoringData, monitoringLoading, monitoringError, // Methods fetchLogs, getLogById, applyFilters, clearFilters, changePage, fetchAnalytics, fetchMonitoringData, formatDate, formatTimeAgo, // Filter options availableActions, availableChannels, availableStatuses } }