@extends('layouts.app') @section('title', 'Settings') @section('content') @php $tabs = [ 'branding' => ['label' => 'Branding', 'icon' => 'sparkles'], 'notifications' => ['label' => 'Notifications', 'icon' => 'alerts'], 'sms' => ['label' => 'SMS Gateway', 'icon' => 'messages'], 'email' => ['label' => 'Email Gateway', 'icon' => 'mail'], 'payments' => ['label' => 'Payments', 'icon' => 'bolt'], 'integrations' => ['label' => 'Integrations', 'icon' => 'bolt'], 'sounds' => ['label' => 'Sounds', 'icon' => 'signal'], 'departments' => ['label' => 'Departments', 'icon' => 'users'], 'roles' => ['label' => 'Roles', 'icon' => 'shield'], 'backup' => ['label' => 'Backup', 'icon' => 'database'], 'audit' => ['label' => 'Audit', 'icon' => 'clipboard'], 'theme' => ['label' => 'Theme', 'icon' => 'sun'], 'maintenance' => ['label' => 'Maintenance', 'icon' => 'wrench'], 'security' => ['label' => 'Security', 'icon' => 'shield'], ]; @endphp @if (!empty($company?->company_number))
@include('partials.company-number', ['company' => $company])
@endif
{{-- Tab navigation --}}
@if ($tab === 'branding')

Branding

@if (!empty($isPlatformBranding)) Platform name, logo, and favicon shown when companies have not unlocked custom branding. @else Customize your company name, logo, and favicon on the web portal and mobile apps. @endif

@if (empty($brandingUnlocked) && empty($isPlatformBranding))

Custom branding is a one-time add-on ({{ \App\Support\Currency::format((float) ($brandingAddonPrice ?? 1), $brandingAddonCurrency ?? 'USD') }}). After payment, your logo and app name appear on the dashboard and registered devices.

@if (auth()->user()?->isAdmin())
@csrf @include('partials.payment-gateway-picker', [ 'paymentGateways' => $availablePaymentGateways ?? [], 'selectedPaymentProvider' => old('payment_provider', ($availablePaymentGateways[0]['id'] ?? '')), 'style' => 'app', ])
@else

Ask a company admin to unlock this add-on.

@endif
@else
@csrf @method('PUT')
@if (!empty($settings['logo_path']))
Current logo
@endif

PNG, JPG, SVG. Max 2 MB. Recommended 256×256.

@if (!empty($settings['favicon_path']))
Current favicon
@endif

ICO, PNG, or SVG. Max 512 KB.

@endif
@elseif ($tab === 'notifications')

Notifications

Control which events generate dashboard alerts, and whether this company keeps SMS history.

@csrf @method('PUT') @php $platformSaveOn = $platformSaveNotificationLogs ?? true; @endphp @if (! $platformSaveOn)
Platform saving is disabled by Super Admin. This company can only keep a live feed until the end of today.
@endif
@foreach ([ 'notify_otp_alerts' => 'OTP message alerts', 'notify_large_payment_alerts' => 'Large payment alerts', 'notify_sync_failure_alerts' => 'Sync failure alerts', 'notify_telegram_enabled' => 'Telegram alerts for critical events', 'notify_email_enabled' => 'Email alerts for critical events', 'notify_sms_alerts' => 'SMS alerts for critical events', 'notify_sound_enabled' => 'Play sound on new SMS (live feed)', 'notify_sound_announce_device' => 'Announce device name when a message arrives', 'message_poll_enabled' => 'Poll for new messages when live feed is open', 'allow_device_code_reuse' => 'Allow device name + code re-registration on the same device', ] as $key => $label) @endforeach

How often the dashboard checks for new messages when polling is enabled.

@include('partials.log-deletion-request-form')
@elseif ($tab === 'sms')

SMS Gateway

Configure outbound SMS for alerts and test messages. Arkesel is supported.

@csrf @method('PUT')

Comma-separated phone numbers in international format.

@csrf

Send test SMS

@elseif ($tab === 'email')

Email Gateway

Override SMTP settings used for alerts and verification emails. Leave disabled to use server `.env` mail config.

@csrf @method('PUT')
@csrf

Send test email

@elseif ($tab === 'payments')

Payment Gateway

@if (!empty($canManagePayments))

Enable any combination of payment methods for company registration and trial conversion. Credentials are stored at platform level.

@csrf @method('PUT')

Turn on any combination. Payers choose among the enabled methods. Auto-renew with a saved card remains Paystack-only (Paystack must stay enabled).

@foreach (($paymentGatewayLabels ?? \App\Services\Payments\PaymentGatewayManager::labels()) as $id => $label) @endforeach

Trial conversion and renewals use the platform subscription price ({{ app(\App\Services\SubscriptionService::class)->formatSubscriptionPrice() }}/mo) with prepaid discounts on 3–12 month terms. Fields below are legacy offline/pending registration only.

Paystack

Webhook URL: {{ $paystackWebhookUrl }}

Hubtel

Webhook URL: {{ $hubtelWebhookUrl }}

Stripe

Webhook URL: {{ $stripeWebhookUrl }}

PayPal

Webhook URL: {{ $paypalWebhookUrl }}

Offline MoMo

Bank transfer

@else

Payment methods are enabled by the platform Super Admin.

@if (!empty($availablePaymentGateways))

Currently available: {{ collect($availablePaymentGateways)->pluck('label')->join(', ') }}.

@else

No payment methods are available right now.

@endif

Gateway credentials and webhook secrets are not available to company admins.

@endif
@elseif ($tab === 'integrations')

Integrations

Outbound webhooks and device request signing.

@csrf @method('PUT')
@elseif ($tab === 'sounds')

Notification Sounds

Upload custom sounds, set the active alert, preview, rename, or delete.

@csrf

MP3, WAV, OGG, or M4A — max 5 MB.

@foreach ($sounds as $sound)

{{ $sound->name }}

@if ($sound->is_active) Active @endif @if ($sound->is_builtin) Built-in @endif

@if ($sound->is_builtin) Synthetic two-tone chime (no file) @elseif ($sound->fileSize()) {{ number_format($sound->fileSize() / 1024, 1) }} KB @else File missing @endif

@if (! $sound->is_active)
@csrf @method('PATCH')
@endif
@if (! $sound->is_builtin)
@csrf @method('PUT')
@csrf @method('DELETE')
@endif
@endforeach
@elseif ($tab === 'departments')

Departments

Create departments, assign devices to them, and assign users so they only see their department's messages on the dashboard.

@csrf
@if ($departments->isEmpty())

No departments yet. Create one above, then assign it when adding or editing users.

@else
@foreach ($departments as $department)

{{ $department->name }}

{{ $department->users_count }} {{ Str::plural('user', $department->users_count) }} · {{ $department->devices_count }} {{ Str::plural('device', $department->devices_count) }}

@csrf @method('DELETE')
@csrf @method('PUT')
@csrf @method('PUT') @if ($allDevices->isEmpty())

No devices registered yet.

@else
@foreach ($allDevices as $device) @endforeach
@endif
@endforeach
@endif
@elseif ($tab === 'roles')

Role Management

Create roles and control which pages they can access and which actions they can perform. Assign roles when adding or editing users.

@if (auth()->user()->hasAction('roles.manage'))
@csrf

Create new role

@include('settings.partials.role-permissions', [ 'permissionPages' => $permissionPages, 'permissionActions' => $permissionActions, 'selectedPages' => old('pages', []), 'selectedActions' => old('actions', []), 'inputPrefix' => 'create', ])
@endif @if ($roles->isEmpty())

No roles yet.

@else
@foreach ($roles as $role) @php $rolePages = $role->permissions['pages'] ?? []; $roleActions = $role->permissions['actions'] ?? []; @endphp

{{ $role->name }}

@if ($role->is_system) System @endif
@if ($role->description)

{{ $role->description }}

@endif

{{ $role->users_count }} {{ Str::plural('user', $role->users_count) }} · {{ count($rolePages) }} pages · {{ count($roleActions) }} actions

@if (auth()->user()->hasAction('roles.manage') && ! $role->is_system && $role->users_count === 0)
@csrf @method('DELETE')
@endif
@if (auth()->user()->hasAction('roles.manage'))
@csrf @method('PUT')
@include('settings.partials.role-permissions', [ 'permissionPages' => $permissionPages, 'permissionActions' => $permissionActions, 'selectedPages' => $rolePages, 'selectedActions' => $roleActions, 'inputPrefix' => 'role-'.$role->id, ])
@else

Pages

    @foreach ($permissionPages as $key => $label) @if (in_array($key, $rolePages, true))
  • {{ $label }}
  • @endif @endforeach

Actions

    @foreach ($permissionActions as $key => $meta) @if (in_array($key, $roleActions, true))
  • {{ $meta['label'] }}
  • @endif @endforeach
@endif
@endforeach
@endif
@elseif ($tab === 'backup')

Database Backup

Create and download SQL backups of your {{ $appName }} data.

@csrf
@if (count($backups) === 0)

No backups yet. Create your first backup above.

@else
@foreach ($backups as $backup)

{{ $backup['name'] }}

{{ number_format($backup['size'] / 1024, 1) }} KB · {{ date('M d, Y H:i', $backup['created_at']) }}

Download
@csrf @method('DELETE')
@endforeach
@endif
@elseif ($tab === 'audit')

Audit Log

Recent administrative actions and system changes.

@forelse ($auditLogs as $log) @empty @endforelse
Time User Action Category Description
{{ $log->created_at->format('M d, H:i') }} {{ $log->user?->name ?? 'System' }} {{ $log->action }} {{ $log->category }} {{ $log->description }}
No audit entries yet.
@elseif ($tab === 'theme')

Theme

Set the default appearance for all users. Users can override with the theme toggle.

@csrf @method('PUT')
@foreach (['dark' => ['Dark', 'moon'], 'light' => ['Light', 'sun'], 'system' => ['System', 'devices']] as $value => [$label, $icon]) @endforeach

Preview — your personal preference

@elseif ($tab === 'security')

Security

Protect logins, two-factor authentication, and device/API hardening.

@csrf @method('PUT')

When required, every user must enroll in an authenticator app before using the dashboard.

@foreach ([ 'security_headers_enabled' => 'Send security headers (HSTS on HTTPS, X-Frame-Options, nosniff)', 'require_device_hmac' => 'Require HMAC signatures on device API requests', ] as $key => $label) @endforeach
@elseif ($tab === 'maintenance')

Maintenance Mode

When enabled, non-admin users see a maintenance page. Admins can still access the dashboard.

@if ($settings['maintenance_mode'])
Maintenance mode is currently active.
@endif
@csrf @method('PUT')
@endif
@endsection