gps_system/resources/views/livewire/notification-center.blade.php
sackey 6b878bb0a0
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
Initial commit
2025-09-12 16:19:56 +00:00

289 lines
15 KiB
PHP

<div class="space-y-6" wire:key="notification-center">
{{-- Header --}}
<div class="flex items-center justify-between">
<div>
<flux:heading size="lg">Notification Center</flux:heading>
<flux:subheading>Configure and monitor notification settings</flux:subheading>
</div>
<flux:button wire:click="$set('showSettingsModal', true)" variant="primary" size="sm" icon="cog-6-tooth">
Global Settings
</flux:button>
</div>
{{-- Notification Stats --}}
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
<flux:card>
<div class="text-center">
<div class="text-2xl font-bold text-blue-600 dark:text-blue-400">{{ $this->stats['notifications_sent_today'] }}</div>
<div class="text-sm text-gray-600 dark:text-gray-300">Sent Today</div>
</div>
</flux:card>
<flux:card>
<div class="text-center">
<div class="text-2xl font-bold text-green-600 dark:text-green-400">{{ $this->stats['delivery_success_rate'] }}%</div>
<div class="text-sm text-gray-600 dark:text-gray-300">Success Rate</div>
</div>
</flux:card>
<flux:card>
<div class="text-center">
<div class="text-2xl font-bold text-yellow-600 dark:text-yellow-400">{{ $this->stats['pending_notifications'] }}</div>
<div class="text-sm text-gray-600 dark:text-gray-300">Pending</div>
</div>
</flux:card>
<flux:card>
<div class="text-center">
<div class="text-2xl font-bold text-red-600 dark:text-red-400">{{ $this->stats['failed_notifications'] }}</div>
<div class="text-sm text-gray-600 dark:text-gray-300">Failed</div>
</div>
</flux:card>
</div>
{{-- Filters --}}
<flux:card>
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
<flux:input wire:model.live="filters.search" placeholder="Search notifications..." icon="magnifying-glass" />
<flux:select wire:model.live="filters.channel">
<option value="">All Channels</option>
<option value="email">Email</option>
<option value="sms">SMS</option>
<option value="push">Push</option>
<option value="webhook">Webhook</option>
</flux:select>
<flux:select wire:model.live="filters.status">
<option value="">All Status</option>
<option value="sent">Sent</option>
<option value="delivered">Delivered</option>
<option value="failed">Failed</option>
<option value="pending">Pending</option>
</flux:select>
<flux:select wire:model.live="filters.event_type">
<option value="">All Events</option>
<option value="geofence_enter">Geofence Enter</option>
<option value="geofence_exit">Geofence Exit</option>
<option value="speeding">Speeding</option>
<option value="device_offline">Device Offline</option>
<option value="low_battery">Low Battery</option>
<option value="maintenance_due">Maintenance Due</option>
</flux:select>
</div>
</flux:card>
{{-- User Notification Settings --}}
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
{{-- User Settings Table --}}
<flux:card>
<div class="mb-4">
<flux:heading size="base">User Notification Settings</flux:heading>
<flux:subheading>Configure individual user preferences</flux:subheading>
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase">User</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase">Email</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase">SMS</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase">Push</th>
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-300 uppercase">Actions</th>
</tr>
</thead>
<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
@forelse($userSettings as $setting)
<tr>
<td class="px-4 py-4 whitespace-nowrap">
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">{{ $setting->user->name }}</div>
<div class="text-xs text-gray-500 dark:text-gray-400">{{ $setting->user->email }}</div>
</td>
<td class="px-4 py-4 whitespace-nowrap">
<flux:badge variant="{{ $setting->email_enabled ? 'success' : 'outline' }}" size="sm">
{{ $setting->email_enabled ? 'On' : 'Off' }}
</flux:badge>
</td>
<td class="px-4 py-4 whitespace-nowrap">
<flux:badge variant="{{ $setting->sms_enabled ? 'success' : 'outline' }}" size="sm">
{{ $setting->sms_enabled ? 'On' : 'Off' }}
</flux:badge>
</td>
<td class="px-4 py-4 whitespace-nowrap">
<flux:badge variant="{{ $setting->push_enabled ? 'success' : 'outline' }}" size="sm">
{{ $setting->push_enabled ? 'On' : 'Off' }}
</flux:badge>
</td>
<td class="px-4 py-4 whitespace-nowrap text-right">
<flux:button wire:click="editUserSettings({{ $setting->user_id }})" variant="outline" size="xs">
Edit
</flux:button>
</td>
</tr>
@empty
<tr>
<td colspan="5" class="px-4 py-4 text-center text-gray-500">
No user settings found.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</flux:card>
{{-- Notification Log --}}
<flux:card>
<div class="mb-4">
<flux:heading size="base">Recent Notifications</flux:heading>
<flux:subheading>Last 24 hours activity</flux:subheading>
</div>
<div class="space-y-3 max-h-96 overflow-y-auto">
@forelse($recentNotifications as $notification)
<div class="flex items-start space-x-3 p-3 bg-gray-50 rounded-lg">
<div class="flex-shrink-0">
@if($notification->channel === 'email')
<div class="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center">
<flux:icon.envelope class="w-4 h-4 text-blue-600" />
</div>
@elseif($notification->channel === 'sms')
<div class="w-8 h-8 bg-green-100 rounded-full flex items-center justify-center">
<flux:icon.device-phone-mobile class="w-4 h-4 text-green-600" />
</div>
@elseif($notification->channel === 'push')
<div class="w-8 h-8 bg-purple-100 rounded-full flex items-center justify-center">
<flux:icon.bell class="w-4 h-4 text-purple-600" />
</div>
@else
<div class="w-8 h-8 bg-gray-100 rounded-full flex items-center justify-center">
<flux:icon.globe-alt class="w-4 h-4 text-gray-600" />
</div>
@endif
</div>
<div class="flex-1 min-w-0">
<div class="text-sm font-medium text-gray-900">{{ $notification->event_type }}</div>
<div class="text-sm text-gray-500">{{ $notification->recipient }}</div>
<div class="text-xs text-gray-400">
{{ $notification->created_at->diffForHumans() }}
<span class="
@if($notification->status === 'delivered') text-green-600
@elseif($notification->status === 'failed') text-red-600
@else text-yellow-600 @endif
">
{{ ucfirst($notification->status) }}
</span>
</div>
</div>
</div>
@empty
<div class="text-center text-gray-500 py-8">
No recent notifications
</div>
@endforelse
</div>
</flux:card>
</div>
{{-- Global Settings Modal --}}
<flux:modal name="global-settings" x-show="$wire.showSettingsModal" class="md:max-w-lg">
<form wire:submit="updateGlobalSettings">
<div class="space-y-6">
<div>
<flux:heading size="lg">Global Notification Settings</flux:heading>
<flux:subheading>Configure system-wide defaults</flux:subheading>
</div>
<div class="space-y-4">
<div class="grid grid-cols-2 gap-4">
<div>
<flux:switch wire:model="globalSettings.email_enabled" label="Email Notifications" />
</div>
<div>
<flux:switch wire:model="globalSettings.sms_enabled" label="SMS Notifications" />
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<flux:switch wire:model="globalSettings.push_enabled" label="Push Notifications" />
</div>
<div>
<flux:switch wire:model="globalSettings.webhook_enabled" label="Webhook Notifications" />
</div>
</div>
<flux:input wire:model="globalSettings.max_daily_notifications" label="Max Daily Notifications" type="number" />
<div class="grid grid-cols-2 gap-4">
<flux:input wire:model="globalSettings.quiet_hours_start" label="Quiet Hours Start" type="time" />
<flux:input wire:model="globalSettings.quiet_hours_end" label="Quiet Hours End" type="time" />
</div>
<flux:input wire:model="globalSettings.webhook_url" label="Webhook URL" type="url" placeholder="https://your-webhook-url.com" />
</div>
<div class="flex justify-end space-x-2">
<flux:button type="button" variant="ghost" wire:click="closeSettingsModal">Cancel</flux:button>
<flux:button type="submit" variant="primary">Save Settings</flux:button>
</div>
</div>
</form>
</flux:modal>
{{-- User Settings Modal --}}
<flux:modal name="user-settings" x-show="$wire.showUserSettingsModal" class="md:max-w-lg">
@if($editingUserSettings)
<form wire:submit="updateUserSettings">
<div class="space-y-6">
<div>
<flux:heading size="lg">Edit User Settings</flux:heading>
<flux:subheading>{{ $editingUserSettings->user->name }}</flux:subheading>
</div>
<div class="space-y-4">
<div class="grid grid-cols-2 gap-4">
<div>
<flux:switch wire:model="userSettingsForm.email_enabled" label="Email Notifications" />
</div>
<div>
<flux:switch wire:model="userSettingsForm.sms_enabled" label="SMS Notifications" />
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<flux:switch wire:model="userSettingsForm.push_enabled" label="Push Notifications" />
</div>
<div>
<flux:switch wire:model="userSettingsForm.webhook_enabled" label="Webhook Notifications" />
</div>
</div>
<div>
<flux:label>Event Types</flux:label>
<div class="space-y-2">
@foreach(['geofence_enter', 'geofence_exit', 'speeding', 'device_offline', 'low_battery', 'maintenance_due'] as $eventType)
<label class="flex items-center space-x-2">
<flux:checkbox wire:model="userSettingsForm.event_types" value="{{ $eventType }}" />
<span class="text-sm">{{ ucwords(str_replace('_', ' ', $eventType)) }}</span>
</label>
@endforeach
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<flux:input wire:model="userSettingsForm.quiet_hours_start" label="Quiet Hours Start" type="time" />
<flux:input wire:model="userSettingsForm.quiet_hours_end" label="Quiet Hours End" type="time" />
</div>
</div>
<div class="flex justify-end space-x-2">
<flux:button type="button" variant="ghost" wire:click="closeUserSettingsModal">Cancel</flux:button>
<flux:button type="submit" variant="primary">Update Settings</flux:button>
</div>
</div>
</form>
@endif
</flux:modal>
</div>