Files
Kol-Manager/resources/views/settings/notifications.blade.php
I-Fun 22f03ccca7 Add contract management and invoice settings pages
- Created a new Blade view for managing brand contracts with forms for adding and editing contracts, including client and category selection.
- Implemented success message notifications for contract actions.
- Added a new Blade view for invoice settings, allowing customization of invoice number format, header branding, and default values for new invoices.
- Introduced a new PDF view for generating rate cards with customizable styles based on user profile settings.
- Developed a profile management page for rate cards, enabling users to update their identity, appearance, and visibility settings.
2026-04-01 21:47:34 +07:00

284 lines
18 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@extends('layouts.app')
@section('title', 'Notification Settings')
@section('page-title', '🔔 Notifications')
@section('page-subtitle', 'Configure Email, Telegram & WhatsApp alerts')
@section('content')
<div class="max-w-3xl mx-auto space-y-6">
{{-- ── How it works ─────────────────────────────────────── --}}
<div class="cat-card p-4 flex gap-3 items-start bg-blue-50/50 border-blue-100">
<span class="text-2xl shrink-0">💡</span>
<div class="text-sm text-gray-600 space-y-1">
<p class="font-semibold text-gray-700">How notifications work</p>
<p>Add one or more channels below. Notifications fire automatically every hour via the scheduler.</p>
<p class="text-xs text-gray-400">To enable the scheduler on your server: add <code class="bg-white px-1 rounded text-xs">* * * * * php /path/to/artisan schedule:run</code> to crontab.</p>
</div>
</div>
{{-- ── Existing channels ────────────────────────────────── --}}
@if($settings->isNotEmpty())
<div class="space-y-3">
@foreach($settings as $setting)
<div class="cat-card p-4" x-data="{ editing: false }">
<div class="flex items-center gap-3">
<span class="text-2xl shrink-0">{{ $setting->channelIcon }}</span>
<div class="flex-1 min-w-0">
<div class="flex items-center gap-2 flex-wrap">
<span class="font-semibold text-gray-800 text-sm">{{ $setting->name }}</span>
<span class="badge badge-ghost text-xs">{{ $setting->channelLabel }}</span>
@if(! $setting->is_enabled)
<span class="badge badge-error text-xs">Disabled</span>
@endif
</div>
<div class="text-xs text-gray-400 mt-0.5 flex flex-wrap gap-2">
@foreach($setting->triggers ?? [] as $trigger)
<span>{{ \App\Models\NotificationSetting::$triggerMeta[$trigger]['icon'] ?? '🔔' }}
{{ \App\Models\NotificationSetting::$triggerMeta[$trigger]['label'] ?? $trigger }}</span>
@endforeach
<span>⏰ {{ $setting->notify_before_hours }}h before</span>
</div>
</div>
<div class="flex items-center gap-1 shrink-0 flex-wrap justify-end">
{{-- Test --}}
<form action="{{ route('settings.notifications.test', $setting) }}" method="POST">
@csrf
<button type="submit" class="text-xs px-3 py-1.5 rounded-full border border-blue-200 text-blue-500 hover:bg-blue-50">
Test
</button>
</form>
{{-- Toggle --}}
<form action="{{ route('settings.notifications.toggle', $setting) }}" method="POST">
@csrf
<button type="submit"
class="text-xs px-3 py-1.5 rounded-full border {{ $setting->is_enabled ? 'border-amber-200 text-amber-500 hover:bg-amber-50' : 'border-green-200 text-green-500 hover:bg-green-50' }}">
{{ $setting->is_enabled ? 'Disable' : 'Enable' }}
</button>
</form>
{{-- Edit --}}
<button @click="editing = !editing"
class="text-xs px-3 py-1.5 rounded-full border border-pink-200 text-pink-500 hover:bg-pink-50">
Edit
</button>
{{-- Delete --}}
<form action="{{ route('settings.notifications.destroy', $setting) }}" method="POST"
onsubmit="return confirm('Remove this channel?')">
@csrf @method('DELETE')
<button type="submit"
class="text-xs px-3 py-1.5 rounded-full border border-red-100 text-red-400 hover:bg-red-50">
Del
</button>
</form>
</div>
</div>
{{-- Inline edit form --}}
<div x-show="editing" x-transition class="mt-4 pt-4 border-t border-pink-50">
<form action="{{ route('settings.notifications.update', $setting) }}" method="POST"
class="space-y-3">
@csrf @method('PUT')
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">Name</label>
<input type="text" name="name" value="{{ $setting->name }}"
class="input-soft text-sm" required>
</div>
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">Notify before (hours)</label>
<input type="number" name="notify_before_hours"
value="{{ $setting->notify_before_hours }}"
min="1" max="720" class="input-soft text-sm">
</div>
</div>
{{-- Triggers --}}
<div>
<label class="text-xs font-semibold text-gray-600 block mb-2">Triggers</label>
<div class="flex flex-wrap gap-3">
@foreach(\App\Models\NotificationSetting::$triggerMeta as $key => $meta)
<label class="flex items-center gap-1.5 cursor-pointer text-sm">
<input type="checkbox" name="triggers[]" value="{{ $key }}"
class="accent-pink-400"
{{ in_array($key, $setting->triggers ?? []) ? 'checked' : '' }}>
{{ $meta['icon'] }} {{ $meta['label'] }}
</label>
@endforeach
</div>
</div>
{{-- Channel-specific config --}}
@if($setting->channel === 'email')
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">To Email</label>
<input type="email" name="config[to_email]"
value="{{ $setting->config['to_email'] ?? '' }}"
class="input-soft text-sm" placeholder="you@example.com">
</div>
@elseif($setting->channel === 'telegram')
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">Bot Token</label>
<input type="text" name="config[bot_token]"
value="{{ $setting->config['bot_token'] ?? '' }}"
class="input-soft text-sm" placeholder="123456:ABC-DEF...">
</div>
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">Chat ID</label>
<input type="text" name="config[chat_id]"
value="{{ $setting->config['chat_id'] ?? '' }}"
class="input-soft text-sm" placeholder="-100123456789">
</div>
</div>
@elseif($setting->channel === 'whatsapp')
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
<div class="sm:col-span-2">
<label class="text-xs font-semibold text-gray-600 block mb-1">WAHA Endpoint</label>
<input type="url" name="config[waha_endpoint]"
value="{{ $setting->config['waha_endpoint'] ?? '' }}"
class="input-soft text-sm" placeholder="http://localhost:3000/api/sendText">
<p class="text-xs text-gray-400 mt-1">Full URL to the sendText endpoint</p>
</div>
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">Session Name</label>
<input type="text" name="config[waha_session]"
value="{{ $setting->config['waha_session'] ?? 'default' }}"
class="input-soft text-sm" placeholder="default">
</div>
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">API Key
<span class="font-normal text-gray-400">(if required)</span>
</label>
<input type="text" name="config[api_key]"
value="{{ $setting->config['api_key'] ?? '' }}"
class="input-soft text-sm" placeholder="your-waha-api-key">
<p class="text-xs text-gray-400 mt-1">Sent as <code>X-Api-Key</code> header. Leave blank if WAHA has no auth.</p>
</div>
<div class="sm:col-span-2">
<label class="text-xs font-semibold text-gray-600 block mb-1">Chat ID</label>
<input type="text" name="config[chat_id]"
value="{{ $setting->config['chat_id'] ?? '' }}"
class="input-soft text-sm" placeholder="628123456789@c.us or 120363xxx@g.us">
<p class="text-xs text-gray-400 mt-1">Individual: <code>628xxx@c.us</code> · Group: <code>120363xxx@g.us</code></p>
</div>
</div>
@endif
<button type="submit" class="btn-sakura text-sm px-6 py-2">💾 Save</button>
</form>
</div>
</div>
@endforeach
</div>
@else
<div class="cat-card p-8 text-center text-gray-400">
<span class="text-4xl block mb-2">🔕</span>
<p class="text-sm font-medium">No notification channels yet</p>
<p class="text-xs mt-1">Add one below to get started</p>
</div>
@endif
{{-- ── Add new channel ─────────────────────────────────── --}}
<div class="cat-card p-5" x-data="{ channel: 'email' }">
<h2 class="font-bold text-gray-700 mb-4 flex items-center gap-2">
<span>➕</span> Add Notification Channel
</h2>
<form action="{{ route('settings.notifications.store') }}" method="POST" class="space-y-4">
@csrf
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">Name <span class="text-pink-400">*</span></label>
<input type="text" name="name" class="input-soft text-sm"
placeholder="My Telegram Bot" required>
</div>
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">Channel <span class="text-pink-400">*</span></label>
<select name="channel" class="input-soft text-sm" x-model="channel">
<option value="email">✉️ Email</option>
<option value="telegram">✈️ Telegram</option>
<option value="whatsapp">💬 WhatsApp (WAHA)</option>
</select>
</div>
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">Notify before (hours)</label>
<input type="number" name="notify_before_hours" value="24"
min="1" max="720" class="input-soft text-sm">
</div>
</div>
{{-- Triggers --}}
<div>
<label class="text-xs font-semibold text-gray-600 block mb-2">Send when…</label>
<div class="flex flex-wrap gap-4">
@foreach(\App\Models\NotificationSetting::$triggerMeta as $key => $meta)
<label class="flex items-center gap-1.5 cursor-pointer text-sm">
<input type="checkbox" name="triggers[]" value="{{ $key }}"
class="accent-pink-400" checked>
{{ $meta['icon'] }} {{ $meta['label'] }}
</label>
@endforeach
</div>
</div>
{{-- Email --}}
<div x-show="channel === 'email'" x-transition>
<label class="text-xs font-semibold text-gray-600 block mb-1">To Email <span class="text-pink-400">*</span></label>
<input type="email" name="config[to_email]" class="input-soft text-sm"
placeholder="you@example.com">
</div>
{{-- Telegram --}}
<div x-show="channel === 'telegram'" x-transition class="grid grid-cols-1 sm:grid-cols-2 gap-3">
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">Bot Token <span class="text-pink-400">*</span></label>
<input type="text" name="config[bot_token]" class="input-soft text-sm"
placeholder="123456:ABC-DEF...">
<p class="text-xs text-gray-400 mt-1">Get from <a href="https://t.me/BotFather" target="_blank" class="text-pink-500">@BotFather</a></p>
</div>
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">Chat ID <span class="text-pink-400">*</span></label>
<input type="text" name="config[chat_id]" class="input-soft text-sm"
placeholder="-100123456789 or @username">
<p class="text-xs text-gray-400 mt-1">Use <a href="https://t.me/userinfobot" target="_blank" class="text-pink-500">@userinfobot</a> to find your ID</p>
</div>
</div>
{{-- WhatsApp / WAHA --}}
<div x-show="channel === 'whatsapp'" x-transition class="grid grid-cols-1 sm:grid-cols-2 gap-3">
<div class="sm:col-span-2">
<label class="text-xs font-semibold text-gray-600 block mb-1">WAHA Endpoint <span class="text-pink-400">*</span></label>
<input type="url" name="config[waha_endpoint]" class="input-soft text-sm"
placeholder="http://localhost:3000/api/sendText">
<p class="text-xs text-gray-400 mt-1">Full URL to the sendText endpoint of your WAHA instance</p>
</div>
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">Session Name</label>
<input type="text" name="config[waha_session]" value="default" class="input-soft text-sm">
</div>
<div>
<label class="text-xs font-semibold text-gray-600 block mb-1">API Key
<span class="font-normal text-gray-400">(if required)</span>
</label>
<input type="text" name="config[api_key]" class="input-soft text-sm"
placeholder="your-waha-api-key">
<p class="text-xs text-gray-400 mt-1">Sent as <code class="bg-gray-100 px-1 rounded">X-Api-Key</code> header. Leave blank if WAHA has no auth.</p>
</div>
<div class="sm:col-span-2">
<label class="text-xs font-semibold text-gray-600 block mb-1">Chat ID <span class="text-pink-400">*</span></label>
<input type="text" name="config[chat_id]" class="input-soft text-sm"
placeholder="628123456789@c.us or 120363xxx@g.us">
<p class="text-xs text-gray-400 mt-1">Individual: <code class="bg-gray-100 px-1 rounded">628xxx@c.us</code> · Group: <code class="bg-gray-100 px-1 rounded">120363xxx@g.us</code></p>
</div>
</div>
<button type="submit" class="btn-sakura">🔔 Add Channel</button>
</form>
</div>
</div>
@endsection