Files

3779 lines
282 KiB
PHP

<x-app-layout>
@push('styles')
<link href="https://unpkg.com/filepond/dist/filepond.css" rel="stylesheet" />
<link href="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css"
rel="stylesheet" />
<style>
.ck-editor__editable {
min-height: 200px;
}
/* FilePond Professional Styling */
.filepond--root {
margin-bottom: 1.5rem;
font-family: inherit;
}
.filepond--panel-root {
background-color: #ffffff;
border: 1px solid #ced4da;
border-radius: 12px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.02);
}
.filepond--drop-label {
color: #495057;
font-size: 0.9rem;
cursor: pointer;
}
.filepond--label-action {
text-decoration-color: #0d6efd;
color: #0d6efd;
font-weight: 600;
}
/* Hide Watermark/Credits */
.filepond--credits {
display: none !important;
}
/* Enhance preview look */
.filepond--image-preview-wrapper {
border-radius: 8px;
}
.filepond--item {
width: calc(100% - 1rem);
margin: 0.5rem;
}
/* Ensure original input is hidden */
.filepond--browser {
display: none !important;
}
/* Status Dots Animation */
.status-dot-red {
width: 8px;
height: 8px;
background-color: #dc3545;
border-radius: 50%;
display: inline-block;
animation: pulse-red 2s infinite;
vertical-align: middle;
}
.status-dot-green {
width: 8px;
height: 8px;
background-color: #198754;
border-radius: 50%;
display: inline-block;
animation: pulse-green 2s infinite;
vertical-align: middle;
}
@keyframes pulse-red {
0% {
box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.4);
}
70% {
box-shadow: 0 0 0 6px rgba(220, 53, 69, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(220, 53, 69, 0);
}
}
@keyframes pulse-green {
0% {
box-shadow: 0 0 0 0 rgba(25, 135, 84, 0.4);
}
70% {
box-shadow: 0 0 0 6px rgba(25, 135, 84, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(25, 135, 84, 0);
}
}
/* Majestic Tab Animations */
.tab-pane.active {
animation: fadeInUpCustom 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes fadeInUpCustom {
from {
opacity: 0;
transform: translateY(15px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Floating Footer Styling */
.sticky-bottom-bar {
position: sticky;
bottom: 0;
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(10px);
border-top: 1px solid #e2e8f0;
padding: 1.25rem 2rem;
margin: 0 -1.5rem -1.5rem -1.5rem;
border-bottom-left-radius: 12px;
border-bottom-right-radius: 12px;
z-index: 100;
box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.03);
}
.btn-save-floating {
background: #111827;
color: white;
border-radius: 50rem;
padding: 12px 35px;
font-weight: 600;
border: none;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
transition: all 0.2s ease;
}
.btn-save-floating:hover {
transform: translateY(-2px);
background: #000000;
color: white;
box-shadow: 0 15px 20px -5px rgba(0, 0, 0, 0.15);
}
</style>
@endpush
<div class="container-fluid" id="main-content">
<div class="row gx-3 gx-lg-4">
<div class="col-12">
<div class="card adminuiux-card">
<div class="card-body p-0">
<div class="p-4 pb-0">
<div class="row align-items-center g-3 mb-3">
<div class="col">
<h5 class="mb-0 fw-bold">{{ __('System Configuration') }}</h5>
<small class="text-muted">
{{ __('Manage branding and feature flags with secure, versioned system settings.') }}
</small>
</div>
<div class="col-lg-4">
<div class="input-group input-group-sm bg-light rounded-pill px-3 py-1 border">
<i class="bi bi-search text-muted my-auto me-2"></i>
<input type="text" id="configSearch"
class="form-control border-0 bg-transparent"
placeholder="{{ __('Search settings...') }}">
</div>
</div>
</div>
</div>
<div class="p-4">
<form id="systemConfigForm" action="{{ route('system-config.update') }}" method="POST"
enctype="multipart/form-data" autocomplete="off" class="ajax-form" data-reset="false">
@csrf
@method('PUT')
<input type="text" name="fakeuser" style="display:none">
<input type="password" name="fakepass" style="display:none">
<!-- Nav tabs -->
<!-- Nav tabs -->
<div class="overflow-x-auto mb-4" style="ms-overflow-style: -ms-autohiding-scrollbar;">
<ul class="nav nav-tabs border-bottom-0 flex-nowrap" id="configTabs" role="tablist">
@cantab('global settings', 'general')
<li class="nav-item" role="presentation">
<button class="nav-link px-3 fw-semibold text-nowrap active"
id="general-tab" data-bs-toggle="tab" data-bs-target="#general"
type="button" role="tab" aria-selected="true"><i
class="bi bi-sliders me-2"></i>{{ __('General') }}</button>
</li>
@endcantab
@cantab('global settings', 'login-security')
<li class="nav-item" role="presentation">
<button class="nav-link px-3 fw-semibold text-nowrap"
id="login-security-tab" data-bs-toggle="tab"
data-bs-target="#login-security" type="button" role="tab"
aria-selected="false"><i
class="bi bi-shield-lock me-2"></i>{{ __('Login Security') }}</button>
</li>
@endcantab
@cantab('global settings', 'password-policy')
<li class="nav-item" role="presentation">
<button class="nav-link px-3 fw-semibold text-nowrap"
id="password-policy-tab" data-bs-toggle="tab"
data-bs-target="#password-policy" type="button" role="tab"
aria-selected="false"><i
class="bi bi-key me-2"></i>{{ __('Password Policy') }}</button>
</li>
@endcantab
@cantab('global settings', 'social-login')
<li class="nav-item" role="presentation">
<button class="nav-link px-3 fw-semibold text-nowrap" id="social-login-tab"
data-bs-toggle="tab" data-bs-target="#social-login" type="button"
role="tab" aria-selected="false"><i
class="bi bi-share me-2"></i>{{ __('Social Login / OAuth') }}</button>
</li>
@endcantab
@cantab('global settings', 'ip-access')
<li class="nav-item" role="presentation">
<button class="nav-link px-3 fw-semibold text-nowrap" id="ip-access-tab"
data-bs-toggle="tab" data-bs-target="#ip-access" type="button"
role="tab" aria-selected="false"><i
class="bi bi-globe me-2"></i>{{ __('IP & Access') }}</button>
</li>
@endcantab
@cantab('global settings', 'notifications')
<li class="nav-item" role="presentation">
<button class="nav-link px-3 fw-semibold text-nowrap" id="notification-tab"
data-bs-toggle="tab" data-bs-target="#notification" type="button"
role="tab" aria-selected="false"><i
class="bi bi-bell me-2"></i>{{ __('Notification') }}</button>
</li>
@endcantab
@cantab('global settings', 'content-legal')
<li class="nav-item" role="presentation">
<button class="nav-link px-3 fw-semibold text-nowrap" id="content-legal-tab"
data-bs-toggle="tab" data-bs-target="#content-legal" type="button"
role="tab" aria-selected="false"><i
class="bi bi-file-text me-2"></i>{{ __('Content & Legal') }}</button>
</li>
@endcantab
@cantab('global settings', 'ai-config')
<li class="nav-item" role="presentation">
<button class="nav-link px-3 fw-semibold text-nowrap" id="ai-config-tab"
data-bs-toggle="tab" data-bs-target="#ai-config" type="button"
role="tab" aria-selected="false"><i
class="bi bi-cpu me-2"></i>{{ __('AI Config') }}</button>
</li>
@endcantab
@cantab('global settings', 'sap-integration')
<li class="nav-item" role="presentation">
<button class="nav-link px-3 fw-semibold text-nowrap"
id="sap-integration-tab" data-bs-toggle="tab"
data-bs-target="#sap-integration" type="button" role="tab"
aria-selected="false"><i
class="bi bi-broadcast me-2"></i>{{ __('SAP Integration') }}</button>
</li>
@endcantab
@cantab('global settings', 'monitoring')
<li class="nav-item" role="presentation">
<button class="nav-link px-3 fw-semibold text-nowrap" id="monitoring-tab"
data-bs-toggle="tab" data-bs-target="#monitoring" type="button"
role="tab" aria-selected="false"><i
class="bi bi-speedometer me-2"></i>{{ __('Debug & Monitoring') }}</button>
</li>
@endcantab
</ul>
</div>
<!-- Tab panes -->
<div class="tab-content" id="configTabsContent">
<!-- 1. General Tab -->
@cantab('global settings', 'general')
<div class="tab-pane fade show active " id="general" role="tabpanel">
<div class="row gx-3">
<div class="col-12 col-lg-8 border-end">
<div>
<div class="card-body">
<div class="d-flex align-items-center mb-4">
<div
class="avatar avatar-40 rounded-circle bg-primary-subtle text-primary me-3">
<i class="bi bi-palette fs-5"></i>
</div>
<div>
<h6 class="fw-bold mb-0 text-uppercase tracking-wider">
{{ __('Branding Settings') }}
</h6>
<small
class="text-muted">{{ __('Personalize your application appearance and identity.') }}</small>
</div>
</div>
<label
class="form-label fw-semibold">{{ __('Application Name') }}
<span class="text-danger">*</span></label>
<input type="text" name="app_name" class="form-control mb-3"
value="{{ old('app_name', $settings['app_name'] ?? '') }}"
placeholder="{{ __('Enter application name') }}" required
minlength="3" maxlength="100">
<label
class="form-label fw-semibold">{{ __('Tagline Primary') }}</label>
<input type="text" name="app_tagline" class="form-control mb-3"
value="{{ old('app_tagline', $settings['app_tagline'] ?? '') }}"
maxlength="150"
placeholder="{{ __('Enter primary tagline') }}">
<label
class="form-label fw-semibold">{{ __('Tagline Secondary') }}</label>
<input type="text" name="app_tagline1" class="form-control mb-3"
value="{{ old('app_tagline1', $settings['app_tagline1'] ?? '') }}"
maxlength="150"
placeholder="{{ __('Enter secondary tagline') }}">
<label
class="form-label fw-semibold">{{ __('Tagline Long / Description') }}</label>
<textarea id="app_tagline2" name="app_tagline2"
class="form-control mb-3" rows="5" maxlength="1000"
placeholder="{{ __('Enter description') }}">{{ old('app_tagline2', $settings['app_tagline2'] ?? '') }}</textarea>
<label
class="form-label fw-semibold">{{ __('Footer Text') }}</label>
<input type="text" name="footer_text" class="form-control mb-3"
value="{{ old('footer_text', $settings['footer_text'] ?? '') }}"
maxlength="200"
placeholder="{{ __('© 2025 My Application. All rights reserved.') }}">
<label
class="form-label fw-semibold">{{ __('Default Language') }}</label>
<select name="default_locale" class="form-select mb-3">
<option value="en" @selected(old('default_locale', $settings['default_locale'] ?? 'en') === 'en')>
{{ __('English') }}
</option>
<option value="id" @selected(old('default_locale', $settings['default_locale'] ?? 'en') === 'id')>
{{ __('Indonesian') }}
</option>
</select>
<div class="mb-3">
<label
class="form-label fw-semibold d-block">{{ __('Landing Page Visibility') }}</label>
<div class="form-check form-switch custom-switch-lg">
<input class="form-check-input" type="checkbox"
name="enable_landing_page" id="enable_landing_page"
value="1" @checked(old('enable_landing_page', $settings['enable_landing_page'] ?? '1') == '1')>
<label class="form-check-label text-muted small"
for="enable_landing_page">
{{ __('If disabled, users will be automatically redirected to the login page.') }}
</label>
</div>
</div>
<hr class="my-3">
<h6 class="fw-bold mb-3"><i
class="bi bi-globe2 me-2 text-info"></i>{{ __('Regional Settings') }}
</h6>
<label
class="form-label fw-semibold">{{ __('Timezone Default') }}</label>
<select name="regional_timezone" class="form-select mb-3">
@php
$timezones = [
'Asia/Jakarta' => 'Asia/Jakarta (WIB, UTC+7)',
'Asia/Makassar' => 'Asia/Makassar (WITA, UTC+8)',
'Asia/Jayapura' => 'Asia/Jayapura (WIT, UTC+9)',
'Asia/Singapore' => 'Asia/Singapore (SGT, UTC+8)',
'Asia/Kuala_Lumpur' => 'Asia/Kuala Lumpur (MYT, UTC+8)',
'Asia/Bangkok' => 'Asia/Bangkok (ICT, UTC+7)',
'UTC' => 'UTC',
];
$currentTz = old('regional_timezone', $settings['regional_timezone'] ?? 'Asia/Jakarta');
@endphp
@foreach($timezones as $value => $label)
<option value="{{ $value }}" @selected($currentTz === $value)>
{{ $label }}
</option>
@endforeach
</select>
<label
class="form-label fw-semibold">{{ __('Date Format') }}</label>
<select name="regional_date_format" class="form-select mb-3">
@php
$dateFormats = [
'd/m/Y' => 'DD/MM/YYYY — ' . now()->format('d/m/Y'),
'm/d/Y' => 'MM/DD/YYYY — ' . now()->format('m/d/Y'),
'Y-m-d' => 'YYYY-MM-DD — ' . now()->format('Y-m-d'),
'd-m-Y' => 'DD-MM-YYYY — ' . now()->format('d-m-Y'),
'd M Y' => 'DD Mon YYYY — ' . now()->format('d M Y'),
'D, d M Y' => 'Day, DD Mon YYYY — ' . now()->format('D, d M Y'),
];
$currentDf = old('regional_date_format', $settings['regional_date_format'] ?? 'd/m/Y');
@endphp
@foreach($dateFormats as $value => $label)
<option value="{{ $value }}" @selected($currentDf === $value)>
{{ $label }}
</option>
@endforeach
</select>
<label
class="form-label fw-semibold">{{ __('Time Format') }}</label>
<select name="regional_time_format" class="form-select mb-3">
@php
$timeFormats = [
'H:i' => '24 Hour — ' . now()->format('H:i') . ' (H:i)',
'H:i:s' => '24 Hour + Seconds — ' . now()->format('H:i:s') . ' (H:i:s)',
'h:i A' => '12 Hour — ' . now()->format('h:i A') . ' (h:i A)',
'h:i a' => '12 Hour lowercase — ' . now()->format('h:i a') . ' (h:i a)',
];
$currentTf = old('regional_time_format', $settings['regional_time_format'] ?? 'H:i');
@endphp
@foreach($timeFormats as $value => $label)
<option value="{{ $value }}" @selected($currentTf === $value)>
{{ $label }}
</option>
@endforeach
</select>
<hr class="my-3">
<label
class="form-label fw-semibold d-block">{{ __('Instance Mode') }}</label>
<div class="btn-group w-100" role="group"
aria-label="Instance Mode">
<input type="radio" class="btn-check" name="instance_mode"
id="modeProduction" value="Production"
autocomplete="off" @checked(old('instance_mode', $settings['instance_mode'] ?? 'Production') === 'Production')>
<label class="btn btn-outline-success"
for="modeProduction">{{ __('Production') }}</label>
<input type="radio" class="btn-check" name="instance_mode"
id="modeTrial" value="Trial" autocomplete="off"
@checked(old('instance_mode', $settings['instance_mode'] ?? 'Production') === 'Trial')>
<label class="btn btn-outline-warning"
for="modeTrial">{{ __('Trial') }}</label>
<input type="radio" class="btn-check" name="instance_mode"
id="modeDemo" value="Demo" autocomplete="off"
@checked(old('instance_mode', $settings['instance_mode'] ?? 'Production') === 'Demo')>
<label class="btn btn-outline-info"
for="modeDemo">{{ __('Demo') }}</label>
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-4">
<div>
<div class="card-body">
<h6 class="fw-bold mb-3"><i
class="bi bi-images me-2 text-success"></i>{{ __('Brand Assets') }}
</h6>
<label class="form-label fw-semibold">{{ __('Logo') }}</label>
<div class="mb-2">
<img id="logo-preview"
src="{{ asset('assets/img/logo.png') }}?v={{ file_exists(public_path('assets/img/logo.png')) ? filemtime(public_path('assets/img/logo.png')) : '0' }}"
onerror="this.style.display='none';"
class="img-thumbnail rounded" width="140" alt="logo">
</div>
<input type="file" id="app_logo" name="app_logo"
accept="image/png,image/jpeg,image/webp">
<label
class="form-label fw-semibold mt-3">{{ __('Favicon') }}</label>
<div class="mb-2">
<img id="favicon-preview"
src="{{ asset('assets/img/favicon.png') }}?v={{ file_exists(public_path('assets/img/favicon.png')) ? filemtime(public_path('assets/img/favicon.png')) : '0' }}"
width="40" onerror="this.style.display='none';"
class="rounded" alt="favicon">
</div>
<input type="file" id="app_favicon" name="app_favicon"
accept="image/png,image/x-icon,image/webp">
</div>
</div>
</div>
</div>
</div>
@endcantab
<!-- 3. Login Security Tab -->
@cantab('global settings', 'login-security')
<div class="tab-pane fade" id="login-security" role="tabpanel">
<div class="row">
<div class="col-12 col-lg-12">
<div class="card-body">
<div class="d-flex align-items-center mb-4">
<div
class="avatar avatar-40 rounded-circle bg-primary-subtle text-primary me-3">
<i class="bi bi-person-check fs-5"></i>
</div>
<div>
<h6 class="fw-bold mb-0 text-uppercase tracking-wider">
{{ __('Authentication & Security') }}
</h6>
<small
class="text-muted">{{ __('Manage how users access your system and prevent abuse.') }}</small>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label
class="form-label fw-semibold">{{ __('Max Login Attempts') }}</label>
<input type="number" name="login_max_attempts"
class="form-control"
value="{{ old('login_max_attempts', $settings['login_max_attempts'] ?? 5) }}"
min="1" max="20">
<small
class="text-muted">{{ __('Before account is temporarily locked') }}</small>
</div>
<div class="col-md-6">
<label
class="form-label fw-semibold">{{ __('Lockout Duration (Minutes)') }}</label>
<input type="number" name="login_lockout_duration"
class="form-control"
value="{{ old('login_lockout_duration', $settings['login_lockout_duration'] ?? 15) }}"
min="1" max="1440">
<small
class="text-muted">{{ __('Duration the account remains locked') }}</small>
</div>
</div>
<div class="form-check form-switch mb-4">
<input class="form-check-input" type="checkbox" role="switch"
id="login_lockout_notify" name="login_lockout_notify"
value="1" @checked(old('login_lockout_notify', $settings['login_lockout_notify'] ?? true))>
<label class="form-check-label fw-semibold"
for="login_lockout_notify">
{{ __('Notify on Lockout') }}
</label>
<br><small
class="text-muted">{{ __('Send email when account is locked') }}</small>
</div>
<hr class="my-4">
<h6 class="fw-bold mb-3"><i
class="bi bi-shield-shaded me-2 text-warning"></i>{{ __('Two-Factor Authentication (2FA)') }}
</h6>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch"
id="two_factor_auth" name="two_factor_auth" value="1"
@checked(old('two_factor_auth', $settings['two_factor_auth'] ?? false))>
<label class="form-check-label fw-semibold"
for="two_factor_auth">
{{ __('Enable 2FA') }}
</label>
<br><small
class="text-muted">{{ __('Two-factor authentication') }}</small>
</div>
<label class="form-label fw-semibold">{{ __('2FA Method') }}</label>
<select name="two_factor_method" class="form-select mb-4">
<option value="email" @selected(old('two_factor_method', $settings['two_factor_method'] ?? 'email') === 'email')>
{{ __('Email OTP') }}
</option>
<option value="app" @selected(old('two_factor_method', $settings['two_factor_method'] ?? 'email') === 'app')>
{{ __('OTP App (Google Authenticator)') }}
</option>
</select>
<hr class="my-4">
<h6 class="fw-bold mb-3">{{ __('Google reCAPTCHA') }}</h6>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch"
id="captcha_enabled" name="captcha_enabled" value="1"
@checked(old('captcha_enabled', $settings['captcha_enabled'] ?? false))>
<label class="form-check-label fw-semibold"
for="captcha_enabled">
{{ __('Enable Captcha') }}
</label>
<br><small
class="text-muted">{{ __('Google reCAPTCHA on login page') }}</small>
</div>
<div class="mb-3">
<label
class="form-label fw-semibold">{{ __('reCAPTCHA Version') }}</label>
<select name="captcha_version" class="form-select">
<option value="v2" @selected(old('captcha_version', $settings['captcha_version'] ?? 'v2') === 'v2')>
{{ __('reCAPTCHA v2 (Checkbox)') }}
</option>
<option value="v3" @selected(old('captcha_version', $settings['captcha_version'] ?? 'v2') === 'v3')>
{{ __('reCAPTCHA v3 (Invisible)') }}
</option>
</select>
</div>
<div class="mb-3">
<label
class="form-label fw-semibold">{{ __('reCAPTCHA Site Key') }}</label>
<input type="text" name="captcha_site_key" class="form-control"
value="{{ old('captcha_site_key', $settings['captcha_site_key'] ?? '') }}"
placeholder="6Lc...">
</div>
<div class="mb-4">
<label
class="form-label fw-semibold">{{ __('reCAPTCHA Secret') }}</label>
<div class="input-group">
<input type="password" name="captcha_secret_key"
class="form-control border-end-0"
value="{{ old('captcha_secret_key', $settings['captcha_secret_key'] ?? '') }}"
placeholder="*******">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button" style="border-color: #dee2e6;">
<i class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
<hr class="my-4">
<h6 class="fw-bold mb-3">{{ __('Trust Device & Passkeys') }}</h6>
<div class="mb-3">
<label
class="form-label fw-semibold">{{ __('Trust Device (Days)') }}</label>
<input type="number" name="two_factor_trust_days"
class="form-control"
value="{{ old('two_factor_trust_days', $settings['two_factor_trust_days'] ?? 30) }}"
min="1">
<small
class="text-muted">{{ __('Validity period of 2FA bypass on trusted devices') }}</small>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch"
id="webauthn_enabled" name="webauthn_enabled" value="1"
@checked(old('webauthn_enabled', $settings['webauthn_enabled'] ?? false))>
<label class="form-check-label fw-semibold"
for="webauthn_enabled">
{{ __('Enable Passkeys (Biometric)') }}
</label>
<br><small
class="text-muted">{{ __('Login using Fingerprint/FaceID') }}</small>
</div>
<hr class="my-4">
<h6 class="fw-bold mb-3">{{ __('Logging') }}</h6>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch"
id="login_log_enabled" name="login_log_enabled" value="1"
@checked(old('login_log_enabled', $settings['login_log_enabled'] ?? true))>
<label class="form-check-label fw-semibold"
for="login_log_enabled">
{{ __('Log Login Activity') }}
</label>
<br><small
class="text-muted">{{ __('Record all login attempts and activities') }}</small>
</div>
<hr class="my-4">
<h6 class="fw-semibold mb-3">{{ __('Session Management') }}</h6>
<div class="row mb-4">
<div class="col-md-6 mb-3 mb-md-0">
<div class="form-check form-switch mb-1">
<input class="form-check-input" type="checkbox"
role="switch" id="session_single_session"
name="session_single_session" value="1"
@checked(old('session_single_session', $settings['session_single_session'] ?? false))>
<label class="form-check-label fw-semibold"
for="session_single_session">
{{ __('Single Session') }}
</label>
</div>
<small
class="text-muted d-block">{{ __('Restrict users to one active device at a time') }}</small>
</div>
<div class="col-md-6">
<label
class="form-label fw-semibold">{{ __('Auto Logout Idle (Minutes)') }}</label>
<input type="number" name="session_auto_logout_idle"
class="form-control"
value="{{ old('session_auto_logout_idle', $settings['session_auto_logout_idle'] ?? 30) }}"
min="1">
<small
class="text-muted">{{ __('Automatically log out idle users') }}</small>
</div>
</div>
<hr class="my-4">
<h6 class="fw-semibold mb-3">{{ __('Remember Me Features') }}</h6>
<div class="row">
<div class="col-md-6 mb-3 mb-md-0">
<div class="form-check form-switch mb-1">
<input class="form-check-input" type="checkbox"
role="switch" id="session_allow_remember_me"
name="session_allow_remember_me" value="1"
@checked(old('session_allow_remember_me', $settings['session_allow_remember_me'] ?? true))>
<label class="form-check-label fw-semibold"
for="session_allow_remember_me">
{{ __('Allow Remember Me') }}
</label>
</div>
<small
class="text-muted d-block">{{ __('Enable the "Remember Me" feature on the login page') }}</small>
</div>
<div class="col-md-6">
<label
class="form-label fw-semibold">{{ __('Remember Me Duration (Days)') }}</label>
<input type="number" name="session_remember_me_duration"
class="form-control"
value="{{ old('session_remember_me_duration', $settings['session_remember_me_duration'] ?? 30) }}"
min="1">
<small
class="text-muted">{{ __('How long the remember me token lasts') }}</small>
</div>
</div>
</div>
</div>
</div>
</div>
@endcantab
<!-- 4. Password Policy Tab -->
@cantab('global settings', 'password-policy')
<div class="tab-pane fade" id="password-policy" role="tabpanel">
<div>
<div class="card-body">
<div class="d-flex align-items-center mb-4">
<div
class="avatar avatar-40 rounded-circle bg-primary-subtle text-primary me-3">
<i class="bi bi-key fs-5"></i>
</div>
<div>
<h6 class="fw-bold mb-0 text-uppercase tracking-wider">
{{ __('Password Policy') }}
</h6>
<small
class="text-muted">{{ __('Set requirements for user passwords and rotation cycles.') }}</small>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label
class="form-label fw-semibold">{{ __('Minimum Password Length') }}</label>
<input type="number" name="password_min_length"
class="form-control"
value="{{ old('password_min_length', $settings['password_min_length'] ?? 8) }}"
min="1">
</div>
<div class="col-md-6">
<label
class="form-label fw-semibold">{{ __('Maximum Password Length') }}</label>
<input type="number" name="password_max_length"
class="form-control"
value="{{ old('password_max_length', $settings['password_max_length'] ?? 64) }}"
min="1">
</div>
</div>
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox"
name="password_require_uppercase"
id="password_require_uppercase" value="1"
@checked(old('password_require_uppercase', $settings['password_require_uppercase'] ?? false))>
<label class="form-check-label"
for="password_require_uppercase">{{ __('Require Uppercase Letters') }}</label>
</div>
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox"
name="password_require_lowercase"
id="password_require_lowercase" value="1"
@checked(old('password_require_lowercase', $settings['password_require_lowercase'] ?? false))>
<label class="form-check-label"
for="password_require_lowercase">{{ __('Require Lowercase Letters') }}</label>
</div>
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox"
name="password_require_numeric" id="password_require_numeric"
value="1" @checked(old('password_require_numeric', $settings['password_require_numeric'] ?? false))>
<label class="form-check-label"
for="password_require_numeric">{{ __('Require Numbers') }}</label>
</div>
<div class="form-check form-switch mb-4">
<input class="form-check-input" type="checkbox"
name="password_require_special" id="password_require_special"
value="1" @checked(old('password_require_special', $settings['password_require_special'] ?? false))>
<label class="form-check-label"
for="password_require_special">{{ __('Require Symbols / Special Characters') }}</label>
</div>
<hr class="my-4">
<h6 class="fw-bold mb-3">{{ __('Aging, History & Resets') }}</h6>
<div class="mb-3">
<label
class="form-label fw-semibold">{{ __('Password Expiry (Days)') }}</label>
<input type="number" name="password_expiry_days"
class="form-control"
value="{{ old('password_expiry_days', $settings['password_expiry_days'] ?? 0) }}"
min="0">
<small
class="text-muted">{{ __('0 = Unlimited. Users will be forced to change password after this period.') }}</small>
</div>
<div class="mb-3">
<label
class="form-label fw-semibold">{{ __('Prevent Password Reuse (Count)') }}</label>
<input type="number" name="password_history_count"
class="form-control"
value="{{ old('password_history_count', $settings['password_history_count'] ?? 0) }}"
min="0" max="10">
<small
class="text-muted">{{ __('Check last X passwords when changing password.') }}</small>
</div>
<div class="mb-3">
<label
class="form-label fw-semibold">{{ __('Reset Link Expiry (Minutes)') }}</label>
<input type="number" name="password_reset_link_expiry"
class="form-control"
value="{{ old('password_reset_link_expiry', $settings['password_reset_link_expiry'] ?? 60) }}"
min="1">
<small
class="text-muted">{{ __('How many minutes the password reset link remains valid.') }}</small>
</div>
</div>
</div>
</div>
@endcantab
<!-- 5. Social Login / OAuth Tab -->
@cantab('global settings', 'social-login')
<div class="tab-pane fade" id="social-login" role="tabpanel">
<div>
<div class="card-body">
<div class="d-flex align-items-center mb-4">
<div
class="avatar avatar-40 rounded-circle bg-primary-subtle text-primary me-3">
<i class="bi bi-share fs-5"></i>
</div>
<div>
<h6 class="fw-bold mb-0 text-uppercase tracking-wider">
{{ __('Social Login & OAuth') }}
</h6>
<small
class="text-muted">{{ __('Configure external authentication providers like Google, Facebook, or LinkedIn.') }}</small>
</div>
</div>
<!-- Google -->
<div class="mb-4">
<h6 class="fw-semibold mb-3 border-bottom pb-2">
{{ __('Google OAuth') }}
</h6>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch"
id="feature_google_oauth" name="feature_google_oauth"
value="1" @checked(old('feature_google_oauth', $settings['feature_google_oauth'] ?? false))>
<label class="form-check-label"
for="feature_google_oauth">{{ __('Enable Google Login') }}</label>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label
class="form-label fw-semibold">{{ __('Google Client ID') }}</label>
<input type="text" name="google_client_id"
class="form-control"
value="{{ old('google_client_id', $settings['google_client_id'] ?? '') }}"
placeholder="xxx.apps.googleusercontent.com">
</div>
<div class="col-md-6 mt-3 mt-md-0">
<label
class="form-label fw-semibold">{{ __('Google Secret') }}</label>
<div class="input-group">
<input type="password" name="google_client_secret"
class="form-control border-end-0"
value="{{ old('google_client_secret', $settings['google_client_secret'] ?? '') }}"
placeholder="*******">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button" style="border-color: #dee2e6;">
<i class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
</div>
</div>
<!-- Facebook -->
<div class="mb-4">
<h6 class="fw-semibold mb-3 border-bottom pb-2">
{{ __('Facebook OAuth') }}
</h6>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch"
id="feature_facebook_oauth" name="feature_facebook_oauth"
value="1" @checked(old('feature_facebook_oauth', $settings['feature_facebook_oauth'] ?? false))>
<label class="form-check-label"
for="feature_facebook_oauth">{{ __('Enable Facebook Login') }}</label>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label
class="form-label fw-semibold">{{ __('Facebook App ID') }}</label>
<input type="text" name="facebook_app_id"
class="form-control"
value="{{ old('facebook_app_id', $settings['facebook_app_id'] ?? '') }}"
placeholder="123456789">
</div>
<div class="col-md-6 mt-3 mt-md-0">
<label
class="form-label fw-semibold">{{ __('Facebook Secret') }}</label>
<div class="input-group">
<input type="password" name="facebook_app_secret"
class="form-control border-end-0"
value="{{ old('facebook_app_secret', $settings['facebook_app_secret'] ?? '') }}"
placeholder="*******">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button" style="border-color: #dee2e6;">
<i class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
</div>
</div>
<!-- GitHub -->
<div class="mb-4">
<h6 class="fw-semibold mb-3 border-bottom pb-2">
{{ __('GitHub OAuth') }}
</h6>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch"
id="feature_github_oauth" name="feature_github_oauth"
value="1" @checked(old('feature_github_oauth', $settings['feature_github_oauth'] ?? false))>
<label class="form-check-label"
for="feature_github_oauth">{{ __('Enable GitHub Login') }}</label>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label
class="form-label fw-semibold">{{ __('GitHub Client ID') }}</label>
<input type="text" name="github_client_id"
class="form-control"
value="{{ old('github_client_id', $settings['github_client_id'] ?? '') }}"
placeholder="abc123">
</div>
<div class="col-md-6 mt-3 mt-md-0">
<label
class="form-label fw-semibold">{{ __('GitHub Secret') }}</label>
<div class="input-group">
<input type="password" name="github_client_secret"
class="form-control border-end-0"
value="{{ old('github_client_secret', $settings['github_client_secret'] ?? '') }}"
placeholder="*******">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button" style="border-color: #dee2e6;">
<i class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
</div>
</div>
<!-- Global Callback -->
<div class="mb-3">
<h6 class="fw-semibold mb-3 border-bottom pb-2">
{{ __('Global Settings') }}
</h6>
<label
class="form-label fw-semibold">{{ __('Callback URL') }}</label>
<input type="text" name="social_login_callback_url"
class="form-control"
value="{{ old('social_login_callback_url', $settings['social_login_callback_url'] ?? '/auth/callback') }}"
placeholder="/auth/callback">
<small
class="text-muted d-block mt-1">{{ __('Unified redirect URL after OAuth login for all providers.') }}</small>
</div>
</div>
</div>
</div>
@endcantab
<!-- 7. IP & Access Tab -->
@cantab('global settings', 'ip-access')
<div class="tab-pane fade" id="ip-access" role="tabpanel">
<div>
<div class="card-body">
<div class="d-flex align-items-center mb-4">
<div
class="avatar avatar-40 rounded-circle bg-danger-subtle text-danger me-3">
<i class="bi bi-fire fs-5"></i>
</div>
<div>
<h6 class="fw-bold mb-0 text-uppercase tracking-wider">
{{ __('Firewall & Access') }}
</h6>
<small
class="text-muted">{{ __('Control IP whitelisting and network-level restrictions.') }}</small>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label
class="form-label fw-semibold">{{ __('Admin IP Whitelist') }}</label>
<textarea name="ip_whitelist_admin" class="form-control"
rows="3"
placeholder="192.168.1.1, 10.0.0.1">{{ old('ip_whitelist_admin', $settings['ip_whitelist_admin'] ?? '') }}</textarea>
<small
class="text-muted">{{ __('IP addresses allowed to access the admin area (Comma separated)') }}</small>
</div>
<div class="col-md-6 mb-3">
<label
class="form-label fw-semibold">{{ __('Global IP Blacklist') }}</label>
<textarea name="ip_blacklist" class="form-control" rows="3"
placeholder="185.xxx.xxx.xxx">{{ old('ip_blacklist', $settings['ip_blacklist'] ?? '') }}</textarea>
<small
class="text-muted">{{ __('IP addresses globally blocked from accessing the app (Comma separated)') }}</small>
</div>
</div>
<hr class="my-4">
<h6 class="fw-semibold mb-3">{{ __('Rate Limiting & Mitigation') }}</h6>
<div class="row mb-3">
<div class="col-md-6 mb-3 mb-md-0">
<label
class="form-label fw-semibold">{{ __('Rate Limit per IP') }}</label>
<input type="number" name="rate_limit_per_ip"
class="form-control"
value="{{ old('rate_limit_per_ip', $settings['rate_limit_per_ip'] ?? 60) }}"
min="1">
<small
class="text-muted">{{ __('Max requests per minute per IP') }}</small>
</div>
<div class="col-md-6">
<label
class="form-label fw-semibold">{{ __('Threshold Auto Block') }}</label>
<input type="number" name="threshold_auto_block"
class="form-control"
value="{{ old('threshold_auto_block', $settings['threshold_auto_block'] ?? 100) }}"
min="1">
<small
class="text-muted">{{ __('Number of requests before auto-block') }}</small>
</div>
</div>
<div class="row mb-3">
<div class="col-12">
<div class="form-check form-switch mb-1">
<input class="form-check-input" type="checkbox"
role="switch" id="auto_block_ip" name="auto_block_ip"
value="1" @checked(old('auto_block_ip', $settings['auto_block_ip'] ?? false))>
<label class="form-check-label fw-semibold"
for="auto_block_ip">
{{ __('Auto Block IP') }}
</label>
</div>
<small
class="text-muted d-block">{{ __('Automatically block suspicious IPs exceeding the threshold') }}</small>
</div>
</div>
<hr class="my-4">
<h6 class="fw-semibold mb-3">{{ __('Transport Security') }}</h6>
<div class="row mb-3">
<div class="col-md-6 mb-3 mb-md-0">
<div class="form-check form-switch mb-1">
<input class="form-check-input" type="checkbox"
role="switch" id="force_https" name="force_https"
value="1" @checked(old('force_https', $settings['force_https'] ?? false))>
<label class="form-check-label fw-semibold"
for="force_https">
{{ __('Force HTTPS') }}
</label>
</div>
<small
class="text-muted d-block">{{ __('Redirect all traffic to HTTPS') }}</small>
</div>
<div class="col-md-6 mb-3 mb-md-0">
<div class="form-check form-switch mb-1">
<input class="form-check-input" type="checkbox"
role="switch" id="session_secure_cookie"
name="session_secure_cookie" value="1"
@checked(old('session_secure_cookie', $settings['session_secure_cookie'] ?? config('session.secure', false)))>
<label class="form-check-label fw-semibold"
for="session_secure_cookie">
{{ __('Secure Cookie') }}
</label>
</div>
<small
class="text-muted d-block">{{ __('Cookies are only sent over HTTPS connections') }}</small>
</div>
</div>
<div class="row mb-3 mt-3">
<div class="col-md-6 mb-3 mb-md-0">
<div class="form-check form-switch mb-1">
<input class="form-check-input" type="checkbox"
role="switch" id="hsts_enabled" name="hsts_enabled"
value="1" @checked(old('hsts_enabled', $settings['hsts_enabled'] ?? false))>
<label class="form-check-label fw-semibold"
for="hsts_enabled">
{{ __('Enable HSTS') }}
</label>
</div>
<small
class="text-muted d-block">{{ __('HTTP Strict Transport Security') }}</small>
</div>
<div class="col-md-6">
<div class="form-check form-switch mb-1">
<input class="form-check-input" type="checkbox"
role="switch" id="session_encrypt"
name="session_encrypt" value="1"
@checked(old('session_encrypt', $settings['session_encrypt'] ?? false))>
<label class="form-check-label fw-semibold"
for="session_encrypt">
{{ __('Encrypt Session Data') }}
</label>
</div>
<small
class="text-muted d-block">{{ __('Fully encrypt session payload contents') }}</small>
</div>
</div>
<hr class="my-4">
<h6 class="fw-semibold mb-3">{{ __('CORS Policy') }}</h6>
<div class="row mb-3">
<div class="col-md-12 mb-3">
<label
class="form-label fw-semibold">{{ __('CORS Origins') }}</label>
<textarea name="cors_origins" class="form-control" rows="2"
placeholder="https://app.com, https://api.app.com">{{ old('cors_origins', $settings['cors_origins'] ?? '*') }}</textarea>
<small
class="text-muted">{{ __('Allowed Origins to access the API (Comma separated)') }}</small>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6 mb-3">
<label
class="form-label fw-semibold">{{ __('CORS Methods') }}</label>
<input type="text" name="cors_methods" class="form-control"
value="{{ old('cors_methods', $settings['cors_methods'] ?? '*') }}"
placeholder="GET, POST, PUT, DELETE">
<small
class="text-muted">{{ __('Allowed HTTP Methods (Comma separated)') }}</small>
</div>
<div class="col-md-6 mb-3">
<label
class="form-label fw-semibold">{{ __('CORS Headers') }}</label>
<input type="text" name="cors_headers" class="form-control"
value="{{ old('cors_headers', $settings['cors_headers'] ?? '*') }}"
placeholder="Content-Type, X-Auth-Token, Origin, Authorization">
<small
class="text-muted">{{ __('Allowed Request Headers (Comma separated)') }}</small>
</div>
</div>
</div>
</div>
</div>
@endcantab
<!-- 8. Notification Tab -->
@cantab('global settings', 'notifications')
<div class="tab-pane fade" id="notification" role="tabpanel">
<div class="card p-3 border-0 bg-transparent text-dark">
<div class="card-body">
<div class="d-flex align-items-center mb-4">
<div
class="avatar avatar-40 rounded-circle bg-primary-subtle text-primary me-3">
<i class="bi bi-megaphone fs-5"></i>
</div>
<div>
<h6 class="fw-bold mb-0 text-uppercase tracking-wider">
{{ __('Communication Hub') }}
</h6>
<small
class="text-muted">{{ __('Centralize all system-to-user notification channels.') }}</small>
</div>
</div>
<div class="row align-items-center mb-4">
<div class="col-md-8">
<div class="form-check form-switch mb-1">
<input class="form-check-input" type="checkbox"
role="switch" id="feature_notification_center"
name="feature_notification_center" value="1"
@checked(old('feature_notification_center', $settings['feature_notification_center'] ?? false))>
<label class="form-check-label fw-bold"
for="feature_notification_center">
{{ __('Enable Notification Center') }}
</label>
</div>
<small
class="text-muted">{{ __('Toggle the entire notification infrastructure across the platform.') }}</small>
</div>
</div>
<hr class="my-4">
<h6 class="fw-bold mb-3 d-flex align-items-center">
{{ __('Email Gateway (SMTP)') }}
</h6>
<div class="row">
<div class="col-md-4 mb-3">
<label
class="form-label fw-semibold">{{ __('Mail Driver') }}</label>
<select name="mail_driver" class="form-select">
<option value="smtp" @selected(old('mail_driver', $settings['mail_driver'] ?? 'smtp') === 'smtp')>SMTP
(Recommended)</option>
<option value="mailgun" @selected(old('mail_driver', $settings['mail_driver'] ?? 'smtp') === 'mailgun')>Mailgun
</option>
<option value="ses" @selected(old('mail_driver', $settings['mail_driver'] ?? 'smtp') === 'ses')>Amazon SES
</option>
<option value="mail" @selected(old('mail_driver', $settings['mail_driver'] ?? 'smtp') === 'mail')>PHP Mail
</option>
</select>
</div>
<div class="col-md-5 mb-3">
<label
class="form-label fw-semibold">{{ __('SMTP Host') }}</label>
<input type="text" name="mail_host" class="form-control"
value="{{ old('mail_host', $settings['mail_host'] ?? '') }}"
placeholder="smtp.gmail.com">
</div>
<div class="col-md-3 mb-3">
<label
class="form-label fw-semibold">{{ __('SMTP Port') }}</label>
<input type="number" name="mail_port" class="form-control"
value="{{ old('mail_port', $settings['mail_port'] ?? 587) }}">
</div>
</div>
<div class="row">
<div class="col-md-4 mb-3">
<label
class="form-label fw-semibold">{{ __('SMTP Username') }}</label>
<input type="text" name="mail_username" class="form-control"
value="{{ old('mail_username', $settings['mail_username'] ?? '') }}"
placeholder="user@gmail.com">
</div>
<div class="col-md-4 mb-3">
<label
class="form-label fw-semibold">{{ __('SMTP Password') }}</label>
<div class="input-group">
<input type="password" name="mail_password"
class="form-control border-end-0"
value="{{ old('mail_password', $settings['mail_password'] ?? '') }}"
placeholder="SMTP Password">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button" style="border-color: #dee2e6;">
<i class="bi bi-eye text-secondary"></i>
</button>
</div>
<small
class="text-xs text-muted">{{ __('Password is now hidden by default.') }}</small>
</div>
<div class="col-md-4 mb-3">
<label
class="form-label fw-semibold">{{ __('Encryption') }}</label>
<select name="mail_encryption" class="form-select">
<option value="tls" @selected(old('mail_encryption', $settings['mail_encryption'] ?? 'tls') === 'tls')>TLS
</option>
<option value="ssl" @selected(old('mail_encryption', $settings['mail_encryption'] ?? 'tls') === 'ssl')>SSL
</option>
<option value="null" @selected(old('mail_encryption', $settings['mail_encryption'] ?? 'tls') === 'null')>None
</option>
</select>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3 text-secondary">
<label
class="form-label fw-semibold">{{ __('Sender Email (From Address)') }}</label>
<input type="email" name="mail_from_address"
class="form-control"
value="{{ old('mail_from_address', $settings['mail_from_address'] ?? '') }}"
placeholder="noreply@app.com">
</div>
<div class="col-md-6 mb-3">
<label
class="form-label fw-semibold">{{ __('Sender Name (From Name)') }}</label>
<input type="text" name="mail_from_name" class="form-control"
value="{{ old('mail_from_name', $settings['mail_from_name'] ?? '') }}"
placeholder="My System">
</div>
</div>
<div class="d-flex align-items-center gap-2 mb-3">
<input type="email" id="test-email-recipient"
class="form-control form-control-sm rounded-pill"
placeholder="{{ __('Recipient email (optional)') }}"
style="max-width: 260px;">
<button type="button"
class="btn btn-outline-dark btn-sm rounded-pill px-3"
id="btn-send-test-email">
<i class="bi bi-send-check me-1"></i>
{{ __('Send Test Email') }}
</button>
</div>
<hr class="my-4">
<h6 class="fw-bold mb-3 d-flex align-items-center">
{{ __('Telegram Messenger Bot') }}
</h6>
<div class="row">
<div class="col-md-8 mb-3">
<label
class="form-label fw-semibold">{{ __('Bot API Token') }}</label>
<input type="text" name="telegram_bot_token"
class="form-control"
value="{{ old('telegram_bot_token', $settings['telegram_bot_token'] ?? '') }}"
placeholder="123456789:ABCDefgh-IJKLmn">
<small class="text-muted">{{ __('Generate via @BotFather on
Telegram.') }}</small>
</div>
<div class="col-md-4 mb-3">
<label
class="form-label fw-semibold">{{ __('Default Chat ID') }}</label>
<input type="text" name="telegram_chat_id" class="form-control"
value="{{ old('telegram_chat_id', $settings['telegram_chat_id'] ?? '') }}"
placeholder="-100123456789">
<small
class="text-muted">{{ __('Target group/user ID.') }}</small>
</div>
</div>
<div class="alert alert-secondary py-2 small mb-0 border-0 shadow-none">
<i class="bi bi-info-circle-fill me-2"></i>
{{ __('Telegram integration allows the system to send real-time alerts for security events and system health.') }}
</div>
</div>
</div>
</div>
@endcantab
<!-- 12. Backup & Restore Tab (no tab-guard; accessible via Backup & Restore menu) -->
<div class="tab-pane fade" id="backup-restore" role="tabpanel">
<div class="card-body">
<div class="row g-4">
<!-- Config Side (Concise Accordion) -->
<div class="col-lg-5 col-md-12 border-end">
<div class="d-flex justify-content-between align-items-center mb-4">
<h6 class="fw-bold mb-0">{{ __('Backup Scheduler') }}</h6>
<button type="button"
class="btn btn-sm btn-dark rounded-pill px-3"
id="btn-create-backup">
<i class="bi bi-plus-circle me-1"></i>
{{ __('Create Now') }}
</button>
</div>
<div class="accordion accordion-flush" id="backupConfigAccordion">
<!-- Core Scheduler -->
<div class="accordion-item bg-transparent">
<h2 class="accordion-header">
<button
class="accordion-button px-0 bg-transparent fw-bold"
type="button" data-bs-toggle="collapse"
data-bs-target="#collapseCore">
{{ __('Core Scheduler') }}
</button>
</h2>
<div id="collapseCore"
class="accordion-collapse collapse show"
data-bs-parent="#backupConfigAccordion">
<div class="accordion-body px-0 pt-0">
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox"
role="switch" id="backup_db_enabled"
name="backup_db_enabled" value="1"
@checked(old('backup_db_enabled', $settings['backup_db_enabled'] ?? true))>
<label class="form-check-label fw-semibold"
for="backup_db_enabled">{{ __('Activate Auto Backup') }}</label>
</div>
<div class="mb-3">
<label
class="form-label small text-muted">{{ __('Frequency') }}</label>
<select
class="form-select form-select-sm rounded-pill"
name="backup_db_frequency">
<option value="hourly"
@selected(($settings['backup_db_frequency'] ?? '') == 'hourly')>{{ __('Hourly') }}
</option>
<option value="daily"
@selected(($settings['backup_db_frequency'] ?? 'daily') == 'daily')>{{ __('Daily') }}
</option>
<option value="weekly"
@selected(($settings['backup_db_frequency'] ?? '') == 'weekly')>{{ __('Weekly') }}
</option>
<option value="monthly"
@selected(($settings['backup_db_frequency'] ?? '') == 'monthly')>{{ __('Monthly') }}
</option>
</select>
</div>
<div class="row g-2">
<div class="col-6">
<label
class="form-label small text-muted">{{ __('Execution Time') }}</label>
<input type="time"
class="form-control form-control-sm rounded-pill"
name="backup_db_time"
value="{{ $settings['backup_db_time'] ?? '02:00' }}">
</div>
<div class="col-6">
<label
class="form-label small text-muted">{{ __('Retention (Days)') }}</label>
<input type="number"
class="form-control form-control-sm rounded-pill"
name="backup_db_retention"
value="{{ $settings['backup_db_retention'] ?? 7 }}">
</div>
</div>
</div>
</div>
</div>
<!-- Storage & Security -->
<div class="accordion-item bg-transparent">
<h2 class="accordion-header">
<button
class="accordion-button collapsed px-0 bg-transparent fw-bold"
type="button" data-bs-toggle="collapse"
data-bs-target="#collapseSecurity">
{{ __('Storage & Security') }}
</button>
</h2>
<div id="collapseSecurity"
class="accordion-collapse collapse"
data-bs-parent="#backupConfigAccordion">
<div class="accordion-body px-0 pt-0">
<div class="mb-3">
<label
class="form-label small text-muted">{{ __('Storage Driver') }}</label>
<select
class="form-select form-select-sm rounded-pill"
name="backup_db_driver"
id="backup_db_driver">
<option value="local"
@selected(($settings['backup_db_driver'] ?? 'local') == 'local')>Local Storage
</option>
<option value="s3"
@selected(($settings['backup_db_driver'] ?? '') == 's3')>Amazon S3</option>
<option value="gdrive"
@selected(($settings['backup_db_driver'] ?? '') == 'gdrive')>Google Drive</option>
</select>
</div>
<!-- Unified Cloud Storage Configuration (Dynamic) -->
<div id="cloud_config_wrapper"
style="display: {{ in_array(($settings['backup_db_driver'] ?? ''), ['gdrive', 's3']) ? 'block' : 'none' }}">
<div class="p-3 border rounded-3 bg-light mb-3 shadow-none bg-opacity-50"
style="background-color: rgba(0,0,0,0.02); border-style: dashed !important;">
<!-- Google Drive Fields -->
<div id="gdrive_fields"
style="display: {{ ($settings['backup_db_driver'] ?? '') == 'gdrive' ? 'block' : 'none' }}">
<div
class="mb-3 d-flex align-items-center">
<div class="bg-white rounded-circle p-2 shadow-sm me-2 d-flex align-items-center justify-content-center"
style="width: 32px; height: 32px;">
<i
class="bi bi-google text-primary fs-5"></i>
</div>
<div
class="x-small text-dark op-75">
{{ __('Google Drive Configuration') }}
</div>
</div>
<div class="mb-2">
<label
class="x-small text-muted mb-1">{{ __('Client ID') }}</label>
<input type="text"
class="form-control form-control-sm rounded-pill bg-white"
name="gdrive_client_id"
value="{{ $settings['gdrive_client_id'] ?? '' }}"
placeholder="Paste Client ID">
</div>
<div class="row g-2 mb-2">
<div class="col-6">
<label
class="x-small text-muted mb-1">{{ __('Client Secret') }}</label>
<div
class="input-group input-group-sm">
<input type="password"
class="form-control border-end-0 bg-white"
name="gdrive_client_secret"
value="{{ $settings['gdrive_client_secret'] ?? '' }}"
placeholder="Secret">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button"
style="border-color: #dee2e6;">
<i
class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
<div class="col-6">
<label
class="x-small text-muted mb-1">{{ __('Refresh Token') }}</label>
<div
class="input-group input-group-sm">
<input type="password"
class="form-control border-end-0 bg-white"
name="gdrive_refresh_token"
value="{{ $settings['gdrive_refresh_token'] ?? '' }}"
placeholder="Token">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button"
style="border-color: #dee2e6;">
<i
class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
</div>
<div class="mb-0">
<label
class="x-small text-muted mb-1">{{ __('Folder Name') }}</label>
<input type="text"
class="form-control form-control-sm rounded-pill bg-white"
name="gdrive_folder"
value="{{ $settings['gdrive_folder'] ?? 'LaravelBackups' }}"
placeholder="e.g. MyBackups">
</div>
</div>
<!-- Amazon S3 Fields -->
<div id="s3_fields"
style="display: {{ ($settings['backup_db_driver'] ?? '') == 's3' ? 'block' : 'none' }}">
<div
class="mb-3 d-flex align-items-center">
<div class="bg-white rounded-circle p-2 shadow-sm me-2 d-flex align-items-center justify-content-center"
style="width: 32px; height: 32px;">
<i
class="bi bi-clouds text-warning fs-5"></i>
</div>
<div
class="x-small text-dark op-75">
{{ __('Amazon S3 Configuration') }}
</div>
</div>
<div class="mb-2">
<label
class="x-small text-muted mb-1">{{ __('Access Key ID') }}</label>
<input type="text"
class="form-control form-control-sm rounded-pill bg-white"
name="s3_key"
value="{{ $settings['s3_key'] ?? '' }}"
placeholder="AKIA...">
</div>
<div class="mb-2">
<label
class="x-small text-muted mb-1">{{ __('Secret Access Key') }}</label>
<div
class="input-group input-group-sm">
<input type="password"
class="form-control border-end-0 bg-white"
name="s3_secret"
value="{{ $settings['s3_secret'] ?? '' }}"
placeholder="Secret Key">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button"
style="border-color: #dee2e6;">
<i
class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
<div class="row g-2 mb-2">
<div class="col-6">
<label
class="x-small text-muted mb-1">{{ __('Region') }}</label>
<input type="text"
class="form-control form-control-sm rounded-pill bg-white"
name="s3_region"
value="{{ $settings['s3_region'] ?? 'us-east-1' }}"
placeholder="us-east-1">
</div>
<div class="col-6">
<label
class="x-small text-muted mb-1">{{ __('Bucket') }}</label>
<input type="text"
class="form-control form-control-sm rounded-pill bg-white"
name="s3_bucket"
value="{{ $settings['s3_bucket'] ?? '' }}"
placeholder="my-bucket">
</div>
</div>
<div class="mb-0">
<label
class="x-small text-muted mb-1">{{ __('Endpoint (Optional)') }}</label>
<input type="text"
class="form-control form-control-sm rounded-pill bg-white"
name="s3_endpoint"
value="{{ $settings['s3_endpoint'] ?? '' }}"
placeholder="https://s3.amazonaws.com">
</div>
</div>
</div>
</div>
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox"
role="switch" id="backup_db_compress"
name="backup_db_compress" value="1"
@checked(old('backup_db_compress', $settings['backup_db_compress'] ?? true))>
<label class="form-check-label small"
for="backup_db_compress">{{ __('Compress with Gzip') }}</label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox"
role="switch" id="backup_db_encrypt"
name="backup_db_encrypt" value="1"
@checked(old('backup_db_encrypt', $settings['backup_db_encrypt'] ?? false))>
<label class="form-check-label small"
for="backup_db_encrypt">{{ __('AES-256 Encryption') }}</label>
</div>
<div class="mb-0" id="encryption_key_wrapper"
style="display: {{ ($settings['backup_db_encrypt'] ?? false) ? 'block' : 'none' }}">
<label
class="form-label small text-muted">{{ __('Encryption Key') }}</label>
<div class="input-group input-group-sm">
<input type="password"
class="form-control border-end-0"
name="backup_db_encrypt_key"
placeholder="Min 32 characters"
value="{{ $settings['backup_db_encrypt_key'] ?? '' }}">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button"
style="border-color: #dee2e6;">
<i class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Advanced & Alerts -->
<div class="accordion-item bg-transparent">
<h2 class="accordion-header">
<button
class="accordion-button collapsed px-0 bg-transparent fw-bold"
type="button" data-bs-toggle="collapse"
data-bs-target="#collapseAdvanced">
{{ __('Advanced & Alerts') }}
</button>
</h2>
<div id="collapseAdvanced"
class="accordion-collapse collapse"
data-bs-parent="#backupConfigAccordion">
<div class="accordion-body px-0 pt-0">
<div class="mb-3">
<label
class="form-label small text-muted">{{ __('Exclude Tables (CSV)') }}</label>
<input type="text"
class="form-control form-control-sm rounded-pill"
name="backup_db_exclude"
placeholder="table1, table2..."
value="{{ $settings['backup_db_exclude'] ?? '' }}">
</div>
<div class="mb-3">
<label
class="form-label small text-muted">{{ __('Notify On') }}</label>
<select
class="form-select form-select-sm rounded-pill"
name="backup_db_notify_on">
<option value="failed"
@selected(($settings['backup_db_notify_on'] ?? 'failed') == 'failed')>Failed Only
</option>
<option value="success"
@selected(($settings['backup_db_notify_on'] ?? '') == 'success')>Success Only</option>
<option value="both"
@selected(($settings['backup_db_notify_on'] ?? '') == 'both')>Success & Failed
</option>
<option value="none"
@selected(($settings['backup_db_notify_on'] ?? '') == 'none')>None</option>
</select>
</div>
<div class="mb-0">
<label
class="form-label small text-muted">{{ __('Notify To (Email/Webhook)') }}</label>
<input type="text"
class="form-control form-control-sm rounded-pill"
name="backup_db_notify_to"
placeholder="email@example.com or url"
value="{{ $settings['backup_db_notify_to'] ?? '' }}">
</div>
</div>
</div>
</div>
</div>
</div>
<!-- List Side (Premium Table) -->
<div class="col-lg-7 col-md-12">
<div class="d-flex justify-content-between align-items-center mb-3">
<h6 class="fw-bold mb-0 text-uppercase tracking-wider py-1">
{{ __('Backup Inventory') }}
</h6>
<button type="button"
class="btn btn-sm btn-outline-secondary rounded-pill border-0"
id="btn-refresh-backups">
<i class="bi bi-arrow-clockwise"></i>
</button>
</div>
<div class="table-responsive"
style="max-height: 500px; overflow-y: auto;">
<table class="table table-hover align-middle border-top"
id="backup-list-table">
<thead class="bg-light sticky-top">
<tr>
<th
class="ps-3 py-3 small text-muted text-uppercase">
{{ __('Backup File') }}
</th>
<th class="small text-muted text-uppercase">
{{ __('Status') }}
</th>
<th class="small text-muted text-uppercase">
{{ __('Date') }}
</th>
<th
class="text-end pe-3 small text-muted text-uppercase">
{{ __('Actions') }}
</th>
</tr>
</thead>
<tbody>
<!-- Loaded via AJAX -->
<tr id="backup-loading">
<td colspan="4" class="text-center py-5">
<div
class="spinner-border spinner-border-sm text-primary me-2">
</div>
{{ __('Scanning storage...') }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- 8. Content & Legal Tab -->
@cantab('global settings', 'content-legal')
<div class="tab-pane fade" id="content-legal" role="tabpanel">
<div class="row gx-4">
<div class="col-12 col-lg-8 border-end">
<div class="card-body p-4">
<div class="d-flex align-items-center mb-4">
<h6 class="fw-bold mb-0">
{{ __('Legal Documents & Public Content') }}
</h6>
</div>
<div class="mb-4">
<label
class="form-label fw-semibold">{{ __('Privacy Policy (UU No. 27/2022 Compliance)') }}</label>
<textarea id="page_privacy_content" name="page_privacy_content"
class="form-control rich-editor rounded-3">{{ old('page_privacy_content', $settings['page_privacy_content'] ?? '') }}</textarea>
</div>
<div class="mb-4">
<label
class="form-label fw-semibold">{{ __('Terms of Use') }}</label>
<textarea id="page_tos_content" name="page_tos_content"
class="form-control rich-editor rounded-3">{{ old('page_tos_content', $settings['page_tos_content'] ?? '') }}</textarea>
</div>
<div class="mb-4">
<label
class="form-label fw-semibold">{{ __('Help Center / FAQ') }}</label>
<textarea id="page_help_content" name="page_help_content"
class="form-control rich-editor rounded-3">{{ old('page_help_content', $settings['page_help_content'] ?? '') }}</textarea>
</div>
<div class="mb-4 border-top pt-4">
<h6 class="fw-bold mb-3">{{ __('Other Pages') }}</h6>
<label
class="form-label fw-semibold mt-2">{{ __('About Us') }}</label>
<textarea id="page_about_content" name="page_about_content"
class="form-control rich-editor rounded-3">{{ old('page_about_content', $settings['page_about_content'] ?? '') }}</textarea>
<label
class="form-label fw-semibold mt-3">{{ __('Security Policy') }}</label>
<textarea id="page_security_content"
name="page_security_content"
class="form-control rich-editor rounded-3">{{ old('page_security_content', $settings['page_security_content'] ?? '') }}</textarea>
</div>
</div>
</div>
<div class="col-12 col-lg-4">
<div class="card-body p-4">
<div class="d-flex align-items-center mb-4">
<div
class="avatar avatar-40 rounded-circle bg-primary-subtle text-primary me-3">
<i class="bi bi-file-text fs-5"></i>
</div>
<div>
<h6 class="fw-bold mb-0 text-uppercase tracking-wider">
{{ __('Compliance & Controls') }}
</h6>
<small
class="text-muted">{{ __('Manage legal documents, terms, and regulatory compliance.') }}</small>
</div>
</div>
<div class="mb-4">
<div
class="form-check form-switch mb-3 d-flex align-items-center">
<input class="form-check-input flex-shrink-0"
type="checkbox" name="require_pdp_on_registration"
id="require_pdp_on_registration" value="1"
@checked(old('require_pdp_on_registration', $settings['require_pdp_on_registration'] ?? true))>
<label class="form-check-label small ms-2 fw-semibold"
for="require_pdp_on_registration">{{ __('Enforce PDP agreement during sign-up') }}</label>
</div>
<div
class="form-check form-switch mb-3 d-flex align-items-center">
<input class="form-check-input flex-shrink-0"
type="checkbox" name="feature_cookie_banner"
id="feature_cookie_banner" value="1"
@checked(old('feature_cookie_banner', $settings['feature_cookie_banner'] ?? true))>
<label class="form-check-label small ms-2 fw-semibold"
for="feature_cookie_banner">{{ __('Show Cookie Consent Banner') }}</label>
</div>
</div>
<hr class="my-4 op-75">
<h6 class="fw-bold mb-3">{{ __('Versioning & Audit') }}</h6>
<div class="mb-4">
<label
class="form-label fw-semibold small mb-1">{{ __('Privacy Policy Version') }}</label>
<div class="input-group input-group-sm">
<span
class="input-group-text bg-light border-end-0">v</span>
<input type="number" name="pdp_document_version"
class="form-control"
value="{{ old('pdp_document_version', $settings['pdp_document_version'] ?? 1) }}"
min="1">
</div>
<div class="alert alert-info border-0 rounded-4 mt-2 p-2 px-3 d-flex align-items-center"
style="background: rgba(13, 202, 240, 0.1);">
<i class="bi bi-info-circle-fill me-2 small"></i>
<span
class="x-small fw-medium lh-sm">{{ __('Incrementing this will force ALL users to re-agree upon login.') }}</span>
</div>
</div>
<div class="mb-4">
<label
class="form-label fw-semibold small">{{ __('Terms of Use Version') }}</label>
<div class="input-group input-group-sm">
<span class="input-group-text">v</span>
<input type="number" name="tos_document_version"
class="form-control"
value="{{ old('tos_document_version', $settings['tos_document_version'] ?? 1) }}"
min="1">
</div>
</div>
<hr class="my-4 op-75">
<h6 class="fw-bold mb-3">{{ __('PDP Metadata') }}</h6>
<div class="mb-3">
<label
class="form-label fw-semibold small">{{ __('DPO Contact Email') }}</label>
<input type="email" name="pdp_dpo_email"
class="form-control form-control-sm"
value="{{ old('pdp_dpo_email', $settings['pdp_dpo_email'] ?? '') }}"
placeholder="dpo@company.com">
</div>
<div class="mb-3">
<label
class="form-label fw-semibold small">{{ __('Official Company Address') }}</label>
<textarea name="pdp_company_address"
class="form-control form-control-sm" rows="3"
placeholder="{{ __('Full legal address...') }}">{{ old('pdp_company_address', $settings['pdp_company_address'] ?? '') }}</textarea>
</div>
</div>
</div>
</div>
</div>
@endcantab
<!-- 9. AI Configuration Tab -->
@cantab('global settings', 'ai-config')
<div class="tab-pane fade" id="ai-config" role="tabpanel">
<!-- AI DASHBOARD HEADER (MATCH MONITORING CENTER) -->
<div class="card adminuiux-card bg-dark text-white mb-4 border-0 shadow-lg overflow-hidden animate__animated animate__fadeIn"
style="border-radius: 20px;">
<div class="card-body p-4 position-relative">
<div class="row align-items-center position-relative z-1">
<div class="col">
<h1 class="display-5 fw-bold text-white mb-1 tracking-tight">
{{ __('AI Intelligence Center') }}
</h1>
<p
class="small text-white-50 mb-0 d-flex align-items-center gap-2">
<span class="status-indicator"></span>
{{ __('Neural Engine Gateway operational at node biiproject') }}
</p>
</div>
<div class="col-auto">
<div class="btn-group bg-white bg-opacity-10 rounded-pill p-1 border border-white border-opacity-10 shadow-sm"
role="group">
<input type="radio" class="btn-check period-filter"
name="ai_period" id="all" value="all" checked>
<label
class="btn btn-xs py-1 px-3 border-0 rounded-pill text-white fw-bold extra-small opacity-75 hover-opacity-100 transition-all"
for="all">{{ __('ALL') }}</label>
<input type="radio" class="btn-check period-filter"
name="ai_period" id="day" value="day">
<label
class="btn btn-xs py-1 px-3 border-0 rounded-pill text-white fw-bold extra-small opacity-75 hover-opacity-100 transition-all"
for="day">{{ __('DAY') }}</label>
<input type="radio" class="btn-check period-filter"
name="ai_period" id="week" value="week">
<label
class="btn btn-xs py-1 px-3 border-0 rounded-pill text-white fw-bold extra-small opacity-75 hover-opacity-100 transition-all"
for="week">{{ __('WEEK') }}</label>
<input type="radio" class="btn-check period-filter"
name="ai_period" id="month" value="month">
<label
class="btn btn-xs py-1 px-3 border-0 rounded-pill text-white fw-bold extra-small opacity-75 hover-opacity-100 transition-all"
for="month">{{ __('MONTH') }}</label>
</div>
</div>
</div>
<div class="bg-decoration"></div>
</div>
</div>
<div class="row g-3 mb-4 animate__animated animate__fadeIn">
<div class="col-md-4">
<div class="card adminuiux-card border-0 shadow-sm h-100 hover-lift">
<div class="card-body p-4">
<div class="d-flex justify-content-between mb-2">
<h6 class="fw-bold text-dark extra-small mb-0">
{{ __('TOTAL REQUESTS') }}
</h6>
<i class="bi bi-cpu text-dark opacity-25"></i>
</div>
<h1 class="display-3 fw-black text-dark mb-0 ls-n2"
id="stat-total-requests">0</h1>
<div class="mini-progress mt-3"
style="height: 4px; background: #f1f5f9; border-radius: 2px;">
<div class="bar"
style="width:100%; height: 100%; background: #1e293b; border-radius: 2px;">
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div
class="card adminuiux-card border-0 shadow-sm h-100 hover-lift card-glow-theme">
<div class="card-body p-4">
<div class="d-flex justify-content-between mb-2">
<h6 class="fw-bold text-dark extra-small mb-0">
{{ __('TOKEN DENSITY') }}
</h6>
<i class="bi bi-lightning-charge text-info"></i>
</div>
<h1 class="display-3 fw-black text-info mb-0 ls-n2"
id="stat-total-tokens">0</h1>
<p class="extra-small text-muted mb-0 mt-1">
{{ __('Active Tokenized Data Streams') }}
</p>
</div>
</div>
</div>
<div class="col-md-4">
<div
class="card adminuiux-card border-0 shadow-sm h-100 hover-lift text-warning card-glow-warning">
<div class="card-body p-4">
<div class="d-flex justify-content-between mb-2">
<h6 class="fw-bold text-dark extra-small mb-0">
{{ __('ESTIMATED RUNTIME COST') }}
</h6>
<i class="bi bi-currency-dollar"></i>
</div>
<h1 class="display-3 fw-black mb-0 ls-n2" id="stat-total-cost">
$0.00</h1>
<p class="extra-small text-muted mb-0 mt-1">
{{ __('Projected Neural Compute Cost') }}
</p>
</div>
</div>
</div>
</div>
<div class="row g-4">
<!-- Left Side: Provider Settings -->
<div class="col-lg-7 col-md-12 border-end">
<div class="card-body p-0">
<div class="d-flex align-items-center mb-4">
<div
class="avatar avatar-40 rounded-circle bg-primary-subtle text-primary me-3">
<i class="bi bi-robot fs-5"></i>
</div>
<div>
<h6 class="fw-bold mb-0 text-uppercase tracking-wider">
{{ __('AI Engine Configuration') }}
</h6>
<small
class="text-muted">{{ __('Select and configure your preferred AI provider.') }}</small>
</div>
</div>
<div class="form-check form-switch mb-4">
<input class="form-check-input" type="checkbox" role="switch"
id="ai_enabled" name="ai_enabled" value="1"
@checked(old('ai_enabled', $settings['ai_enabled'] ?? false))>
<label class="form-check-label fw-bold"
for="ai_enabled">{{ __('Enable Global AI Services') }}</label>
<div class="form-text small">
{{ __('Allow the platform to utilize AI for various features.') }}
</div>
</div>
<div class="mb-4">
<label
class="form-label fw-bold">{{ __('Active AI Provider') }}</label>
<div class="row g-2">
@php
$providers = [
'gpt' => ['name' => 'OpenAI GPT', 'img' => 'gpt.png'],
'gemini' => ['name' => 'Google Gemini', 'img' => 'gemini.png'],
'claude' => ['name' => 'Anthropic Claude', 'img' => 'claude.png'],
'deepseek' => ['name' => 'DeepSeek AI', 'img' => 'deepseek.png'],
'grok' => ['name' => 'xAI Grok', 'img' => 'grok.png'],
'mistral' => ['name' => 'Mistral AI', 'img' => 'mistral.png'],
'ollama' => ['name' => 'Ollama (Local)', 'img' => 'ollama.png'],
'openrouter' => ['name' => 'OpenRouter', 'img' => 'openrouter.png'],
];
$activeProvider = old('ai_provider', $settings['ai_provider'] ?? 'gpt');
@endphp
@foreach($providers as $key => $provider)
<div class="col-6 col-md-3">
<input type="radio" class="btn-check" name="ai_provider"
id="provider_{{ $key }}" value="{{ $key }}"
autocomplete="off" @checked($activeProvider === $key)>
<label
class="btn btn-outline-primary w-100 py-3 d-flex flex-column align-items-center gap-2 rounded-4"
for="provider_{{ $key }}">
<img src="{{ asset('assets/img/AI/' . $provider['img']) }}"
alt="{{ $provider['name'] }}"
style="width: 32px; height: 32px; object-fit: contain;">
<span
class="x-small fw-bold">{{ $provider['name'] }}</span>
</label>
</div>
@endforeach
</div>
</div>
<hr class="my-4 opacity-50">
<!-- Provider Specific API Keys -->
<div id="gpt_settings"
class="provider-settings @if($activeProvider !== 'gpt') d-none @endif">
<h6 class="fw-bold mb-3 d-flex align-items-center"><img
src="{{ asset('assets/img/AI/gpt.png') }}" width="20"
class="me-2">{{ __('OpenAI API Settings') }}</h6>
<div class="mb-3">
<label
class="form-label small fw-semibold">{{ __('API Key') }}</label>
<div class="input-group">
<input type="password" name="ai_gpt_key"
class="form-control border-end-0"
value="{{ $settings['ai_gpt_key'] ?? '' }}"
placeholder="sk-...">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button" style="border-color: #dee2e6;">
<i class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
</div>
<div id="gemini_settings"
class="provider-settings @if($activeProvider !== 'gemini') d-none @endif">
<h6 class="fw-bold mb-3 d-flex align-items-center"><img
src="{{ asset('assets/img/AI/gemini.png') }}" width="20"
class="me-2">{{ __('Google Gemini API Settings') }}</h6>
<div class="mb-3">
<label
class="form-label small fw-semibold">{{ __('API Key') }}</label>
<div class="input-group">
<input type="password" name="ai_gemini_key"
class="form-control border-end-0"
value="{{ $settings['ai_gemini_key'] ?? '' }}"
placeholder="AIza...">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button" style="border-color: #dee2e6;">
<i class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
</div>
<div id="claude_settings"
class="provider-settings @if($activeProvider !== 'claude') d-none @endif">
<h6 class="fw-bold mb-3 d-flex align-items-center"><img
src="{{ asset('assets/img/AI/claude.png') }}" width="20"
class="me-2">{{ __('Anthropic Claude API Settings') }}
</h6>
<div class="mb-3">
<label
class="form-label small fw-semibold">{{ __('API Key') }}</label>
<div class="input-group">
<input type="password" name="ai_claude_key"
class="form-control border-end-0"
value="{{ $settings['ai_claude_key'] ?? '' }}"
placeholder="sk-ant-...">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button" style="border-color: #dee2e6;">
<i class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
</div>
<div id="deepseek_settings"
class="provider-settings @if($activeProvider !== 'deepseek') d-none @endif">
<h6 class="fw-bold mb-3 d-flex align-items-center"><img
src="{{ asset('assets/img/AI/deepseek.png') }}"
width="20"
class="me-2">{{ __('DeepSeek API Settings') }}</h6>
<div class="mb-3">
<label
class="form-label small fw-semibold">{{ __('API Key') }}</label>
<div class="input-group">
<input type="password" name="ai_deepseek_key"
class="form-control border-end-0"
value="{{ $settings['ai_deepseek_key'] ?? '' }}"
placeholder="sk-...">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button" style="border-color: #dee2e6;">
<i class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
</div>
<div id="grok_settings"
class="provider-settings @if($activeProvider !== 'grok') d-none @endif">
<h6 class="fw-bold mb-3 d-flex align-items-center"><img
src="{{ asset('assets/img/AI/grok.png') }}" width="20"
class="me-2">{{ __('xAI Grok API Settings') }}</h6>
<div class="mb-3">
<label
class="form-label small fw-semibold">{{ __('API Key') }}</label>
<div class="input-group">
<input type="password" name="ai_grok_key"
class="form-control border-end-0"
value="{{ $settings['ai_grok_key'] ?? '' }}"
placeholder="xai-...">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button" style="border-color: #dee2e6;">
<i class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
</div>
<div id="mistral_settings"
class="provider-settings @if($activeProvider !== 'mistral') d-none @endif">
<h6 class="fw-bold mb-3 d-flex align-items-center"><img
src="{{ asset('assets/img/AI/mistral.png') }}"
width="20"
class="me-2">{{ __('Mistral AI API Settings') }}</h6>
<div class="mb-3">
<label
class="form-label small fw-semibold">{{ __('API Key') }}</label>
<div class="input-group">
<input type="password" name="ai_mistral_key"
class="form-control border-end-0"
value="{{ $settings['ai_mistral_key'] ?? '' }}"
placeholder="sk-...">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button" style="border-color: #dee2e6;">
<i class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
</div>
<div id="openrouter_settings"
class="provider-settings @if($activeProvider !== 'openrouter') d-none @endif">
<h6 class="fw-bold mb-3 d-flex align-items-center"><img
src="{{ asset('assets/img/AI/openrouter.png') }}"
width="20"
class="me-2">{{ __('OpenRouter API Settings') }}</h6>
<div class="mb-3">
<label
class="form-label small fw-semibold">{{ __('API Key') }}</label>
<div class="input-group">
<input type="password" name="ai_openrouter_key"
class="form-control border-end-0"
value="{{ $settings['ai_openrouter_key'] ?? '' }}"
placeholder="sk-or-...">
<button
class="btn btn-outline-secondary bg-white border-start-0 password-toggle"
type="button" style="border-color: #dee2e6;">
<i class="bi bi-eye text-secondary"></i>
</button>
</div>
</div>
</div>
<div id="ollama_settings"
class="provider-settings @if($activeProvider !== 'ollama') d-none @endif">
<h6 class="fw-bold mb-3 d-flex align-items-center"><img
src="{{ asset('assets/img/AI/ollama.png') }}" width="20"
class="me-2">{{ __('Ollama Settings (Local)') }}</h6>
<div class="mb-3">
<label
class="form-label small fw-semibold">{{ __('Base URL') }}</label>
<input type="url" name="ai_ollama_base_url"
class="form-control"
value="{{ $settings['ai_ollama_base_url'] ?? 'http://localhost:11434' }}">
</div>
</div>
<div class="mt-4">
<h6 class="fw-bold mb-3 d-flex align-items-center">
{{ __('Inference Parameters') }}
<i class="bi bi-sliders2 ms-2 text-primary opacity-50"></i>
</h6>
<div class="row">
<div class="col-md-6 mb-3">
<label
class="form-label small fw-semibold">{{ __('Default Model') }}</label>
<div class="input-group">
<span
class="input-group-text bg-light border-end-0"><i
class="bi bi-box-seam"></i></span>
<select name="ai_default_model"
id="ai_default_model"
class="form-select border-start-0"
data-initial-value="{{ $settings['ai_default_model'] ?? 'gpt-4o' }}">
<!-- Dynamically populated by JS based on provider -->
</select>
</div>
</div>
<div class="col-6 col-md-3 mb-3">
<label
class="form-label small fw-semibold">{{ __('Temperature') }}</label>
<input type="number" step="0.1" name="ai_temperature"
class="form-control rounded-pill"
value="{{ $settings['ai_temperature'] ?? 0.7 }}"
min="0" max="2">
</div>
<div class="col-6 col-md-3 mb-3">
<label
class="form-label small fw-semibold">{{ __('Max Tokens') }}</label>
<input type="number" name="ai_max_tokens"
class="form-control rounded-pill"
value="{{ $settings['ai_max_tokens'] ?? 2000 }}">
</div>
</div>
<div class="mb-3">
<label
class="form-label small fw-semibold">{{ __('Global System Instruction') }}</label>
<textarea name="ai_system_instruction"
class="form-control rounded-4" rows="4"
placeholder="You are a helpful assistant specialized in business automation...">{{ $settings['ai_system_instruction'] ?? '' }}</textarea>
<small
class="text-muted">{{ __('This instruction will be appended to every AI request.') }}</small>
</div>
</div>
</div>
</div>
<!-- Right Side: AI Simulation -->
<div class="col-lg-5 col-md-12">
<div class="card adminuiux-card border-0 shadow-sm h-100 hover-lift">
<div
class="card-header bg-transparent border-0 pt-4 px-4 d-flex justify-content-between align-items-center">
<h6 class="fw-bold text-dark mb-0"><i
class="bi bi-terminal me-2"></i>{{ __('Neural Sandbox') }}
</h6>
<span
class="badge text-bg-theme-1 rounded-pill px-3 shadow-sm x-small">{{ __('ACTIVE CONSOLE') }}</span>
</div>
<div class="card-body p-4 d-flex flex-column pt-2">
<div id="ai-simulation-output"
class="flex-grow-1 mb-3 rounded-4 p-3 border overflow-auto"
style="min-height: 250px; background: #0c121e; color: #10b981; font-family: 'Fira Code', 'JetBrains Mono', monospace;">
<div class="text-center mt-5 opacity-50">
<i class="bi bi-robot fs-1 d-block mb-2"></i>
<p class="small">
{{ __('Waiting for neural input sequence...') }}
</p>
</div>
</div>
<div class="simulation-input">
<div
class="d-flex justify-content-between align-items-center mb-2 px-1">
<label
class="extra-small fw-bold text-muted text-uppercase ls-1 mb-0">{{ __('PROMPT_BUFFER') }}</label>
<div id="simulation-metrics"
class="extra-small text-muted d-none">
<span class="me-2 fw-black"><i
class="bi bi-lightning-fill text-warning me-1"></i><span
id="metric-latency">0</span>ms</span>
<span class="fw-black"><i
class="bi bi-coin text-success me-1"></i>$<span
id="metric-cost">0.000</span></span>
</div>
</div>
<div class="input-group">
<textarea id="simulation-prompt"
class="form-control rounded-start-4 border-end-0 bg-light"
rows="2"
placeholder="Enter command or query..."></textarea>
<button type="button" id="btn-run-simulation"
class="btn btn-dark px-3 rounded-end-4 shadow-sm">
<i class="bi bi-play-fill fs-4 text-success"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endcantab
<!-- 9. SAP Integration Tab -->
@cantab('global settings', 'sap-integration')
<div class="tab-pane fade" id="sap-integration" role="tabpanel">
<div class="row">
<div class="col-12 col-lg-12">
<div class="card-body">
<div class="d-flex align-items-center mb-4">
<div
class="avatar avatar-40 rounded-circle bg-primary-subtle text-primary me-3">
<i class="bi bi-diagram-3 fs-5"></i>
</div>
<div>
<h6 class="fw-bold mb-0 text-uppercase tracking-wider">
{{ __('SAP RFC Integration') }}
</h6>
<small
class="text-muted">{{ __('Configure connection settings for SAP Remote Function Call (RFC) services.') }}</small>
</div>
<div class="ms-auto">
<button type="button"
class="btn btn-outline-dark btn-sm rounded-pill px-3 fw-bold"
id="btn-test-sap">
<i class="bi bi-broadcast me-1"></i> TEST CONNECTION
</button>
</div>
</div>
<div class="alert alert-info border-0 shadow-sm rounded-4 mb-4">
<div class="d-flex">
<div class="me-3">
<i class="bi bi-info-circle-fill fs-4"></i>
</div>
<div>
<h6 class="fw-bold mb-1">{{ __('RFC Requirements') }}
</h6>
<p class="mb-0 small text-dark opacity-75">
{{ __('Integration requires the sapnwrfc PHP extension and SAP NW RFC SDK. Ensure these are correctly installed on your production environment node.') }}
</p>
</div>
</div>
</div>
<div class="row mb-4">
<div class="col-md-8">
<label
class="form-label fw-bold small text-uppercase ls-1">{{ __('Application Server (ASHST)') }}</label>
<input type="text" name="sap_rfc_ashost"
class="form-control"
value="{{ old('sap_rfc_ashost', $settings['sap_rfc_ashost'] ?? '') }}"
placeholder="e.g. 192.168.1.10">
</div>
<div class="col-md-4">
<label
class="form-label fw-bold small text-uppercase ls-1">{{ __('Sys Num') }}</label>
<input type="text" name="sap_rfc_sysnr" class="form-control"
value="{{ old('sap_rfc_sysnr', $settings['sap_rfc_sysnr'] ?? '') }}"
placeholder="00">
</div>
</div>
<div class="row mb-4">
<div class="col-md-3">
<label
class="form-label fw-bold small text-uppercase ls-1">{{ __('Client') }}</label>
<input type="text" name="sap_rfc_client"
class="form-control"
value="{{ old('sap_rfc_client', $settings['sap_rfc_client'] ?? '') }}"
placeholder="100">
</div>
<div class="col-md-4">
<label
class="form-label fw-bold small text-uppercase ls-1">{{ __('Username') }}</label>
<input type="text" name="sap_rfc_user" class="form-control"
value="{{ old('sap_rfc_user', $settings['sap_rfc_user'] ?? '') }}"
placeholder="SAP_USER">
</div>
<div class="col-md-5">
<label
class="form-label fw-bold small text-uppercase ls-1">{{ __('Password') }}</label>
<div class="input-group">
<input type="password" name="sap_rfc_passwd"
class="form-control"
value="{{ old('sap_rfc_passwd', $settings['sap_rfc_passwd'] ?? '') }}"
placeholder="*******">
<button
class="btn btn-outline-secondary toggle-password"
type="button">
<i class="bi bi-eye"></i>
</button>
</div>
</div>
</div>
<div class="row mb-4">
<div class="col-md-6">
<label
class="form-label fw-bold small text-uppercase ls-1">{{ __('SAP Router') }}</label>
<input type="text" name="sap_rfc_router"
class="form-control"
value="{{ old('sap_rfc_router', $settings['sap_rfc_router'] ?? '') }}"
placeholder="/H/host/S/port/H/">
</div>
<div class="col-md-6">
<label
class="form-label fw-bold small text-uppercase ls-1">{{ __('Trace Mode') }}</label>
<select name="sap_rfc_trace" class="form-select">
<option value="0" @selected(old('sap_rfc_trace', $settings['sap_rfc_trace'] ?? '0') == '0')>
{{ __('Disabled') }}
</option>
<option value="1" @selected(old('sap_rfc_trace', $settings['sap_rfc_trace'] ?? '0') == '1')>
{{ __('Level 1 (Basic)') }}
</option>
<option value="2" @selected(old('sap_rfc_trace', $settings['sap_rfc_trace'] ?? '0') == '2')>
{{ __('Level 2 (Detailed)') }}
</option>
</select>
</div>
</div>
<div
class="mt-4 pt-3 border-top d-flex align-items-center justify-content-between">
<div>
<h6 class="fw-bold mb-0">{{ __('Connectivity Check') }}</h6>
<p class="text-muted small mb-0">
{{ __('Verify if the system can establish a handshake with the SAP server.') }}
</p>
</div>
<button type="button" id="btn-test-sap"
class="btn btn-outline-primary rounded-pill px-4 shadow-sm">
<i
class="bi bi-broadcast me-2"></i>{{ __('Test SAP Connection') }}
</button>
</div>
</div>
</div>
</div>
</div>
@endcantab
<!-- 10. Debug & Monitoring Tab -->
@cantab('global settings', 'monitoring')
<div class="tab-pane fade" id="monitoring" role="tabpanel">
<div class="row">
<div class="col-12 col-lg-12">
<div class="card-body">
<div class="d-flex align-items-center mb-4">
<div
class="avatar avatar-40 rounded-circle bg-primary-subtle text-primary me-3">
<i class="bi bi-speedometer fs-5"></i>
</div>
<div>
<h6 class="fw-bold mb-0 text-uppercase tracking-wider">
{{ __('Debug & Monitoring') }}
</h6>
<small
class="text-muted">{{ __('Control diagnostic services and system-level monitoring tools.') }}</small>
</div>
</div>
<div class="alert alert-warning border-0 shadow-sm rounded-4 mb-4">
<div class="d-flex">
<div class="me-3">
<i class="bi bi-exclamation-triangle-fill fs-4"></i>
</div>
<div>
<h6 class="fw-bold mb-1">
{{ __('Important Performance Note') }}
</h6>
<p class="mb-0 small text-dark opacity-75">
{{ __('Enabling these tools (especially Pulse and Telescope) will add overhead to every request. It is recommended to disable them in high-traffic production environments unless active debugging is required.') }}
</p>
</div>
</div>
</div>
<div
class="list-group list-group-flush rounded-4 shadow-sm border overflow-hidden mb-4">
{{-- 0. AI Diagnostics --}}
<div class="list-group-item p-4">
<div
class="d-flex justify-content-between align-items-center">
<div>
<h6 class="fw-bold mb-1"><i
class="bi bi-robot me-2 text-danger"></i>{{ __('AI Diagnostics') }}
</h6>
<p class="text-dark opacity-75 small mb-0">
{{ __('Intercept runtime exceptions, diagnose errors via AI, and automatically apply code fixes in real-time. If disabled, the AI agent will not run.') }}
</p>
</div>
<div class="form-check form-switch custom-switch-lg">
<input class="form-check-input" type="checkbox"
id="ai_healing_enabled"
name="ai_healing_enabled" value="1"
@checked(old('ai_healing_enabled', $settings['ai_healing_enabled'] ?? false))>
</div>
</div>
</div>
{{-- 1. Laravel Horizon --}}
<div class="list-group-item p-4">
<div
class="d-flex justify-content-between align-items-center">
<div>
<h6 class="fw-bold mb-1"><i
class="bi bi-speedometer2 me-2 text-primary"></i>{{ __('Laravel Horizon') }}
</h6>
<p class="text-muted small mb-0">
{{ __('A beautiful dashboard and code-driven configuration for your Redis-powered queues.') }}
</p>
</div>
<div class="form-check form-switch custom-switch-lg">
<input class="form-check-input" type="checkbox"
name="engine_horizon_enabled"
id="engine_horizon_enabled" value="1"
@checked(old('engine_horizon_enabled', $settings['engine_horizon_enabled'] ?? true))>
</div>
</div>
</div>
{{-- 2. Laravel Pulse --}}
<div class="list-group-item p-4">
<div
class="d-flex justify-content-between align-items-center">
<div>
<h6 class="fw-bold mb-1"><i
class="bi bi-activity me-2 text-info"></i>{{ __('Laravel Pulse') }}
</h6>
<p class="text-muted small mb-0">
{{ __('A real-time application performance monitoring (APM) tool for your Laravel application.') }}
</p>
</div>
<div class="form-check form-switch custom-switch-lg">
<input class="form-check-input" type="checkbox"
name="engine_pulse_enabled"
id="engine_pulse_enabled" value="1"
@checked(old('engine_pulse_enabled', $settings['engine_pulse_enabled'] ?? true))>
</div>
</div>
</div>
{{-- 3. Laravel Telescope --}}
<div class="list-group-item p-4">
<div
class="d-flex justify-content-between align-items-center">
<div>
<h6 class="fw-bold mb-1"><i
class="bi bi-bug me-2 text-warning"></i>{{ __('Laravel Telescope') }}
</h6>
<p class="text-muted small mb-0">
{{ __('Provides insight into the requests coming into your application, exceptions, log entries, and more.') }}
</p>
</div>
<div class="form-check form-switch custom-switch-lg">
<input class="form-check-input" type="checkbox"
name="engine_telescope_enabled"
id="engine_telescope_enabled" value="1"
@checked(old('engine_telescope_enabled', $settings['engine_telescope_enabled'] ?? true))>
</div>
</div>
</div>
{{-- 4. API Documentation --}}
<div class="list-group-item p-4">
<div
class="d-flex justify-content-between align-items-center">
<div>
<h6 class="fw-bold mb-1"><i
class="bi bi-code-square me-2 text-success"></i>{{ __('API Documentation') }}
</h6>
<p class="text-muted small mb-0">
{{ __('Generates interactive API documentation (Swagger/OpenAPI) based on your route annotations.') }}
</p>
</div>
<div class="form-check form-switch custom-switch-lg">
<input class="form-check-input" type="checkbox"
name="engine_swagger_enabled"
id="engine_swagger_enabled" value="1"
@checked(old('engine_swagger_enabled', $settings['engine_swagger_enabled'] ?? true))>
</div>
</div>
</div>
</div>
<div class="mt-4">
<h6 class="fw-bold mb-3"><i
class="bi bi-tools me-2 text-primary"></i>{{ __("Connectivity Diagnostics") }}
</h6>
<div class="card border-0 bg-light rounded-4 p-4">
<div
class="d-flex justify-content-between align-items-center">
<div>
<h6 class="fw-bold mb-1">
{{ __("Primary Database Connection") }}
</h6>
<p class="text-muted small mb-0">
{{ __("Perform a real-time dry-run to verify connectivity with the primary system database.") }}
</p>
</div>
<button type="button"
class="btn btn-dark btn-sm rounded-pill px-4 fw-bold"
id="btn-test-db">
<i class="bi bi-database-check me-1"></i> TEST
CONNECTION
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endcantab
</div>
@canmanageanytab('global settings')
<div class="sticky-bottom-bar d-flex justify-content-between align-items-center mt-4">
<div class="small text-muted d-none d-md-block">
<i class="bi bi-shield-check me-1 text-primary"></i>
{{ __('Changes are applied globally across the entire application.') }}
</div>
<button type="submit" class="btn btn-save-floating">
<i class="bi bi-cloud-arrow-up me-2"></i> {{ __('Save Configuration') }}
</button>
</div>
@endcanmanageanytab
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@push('scripts')
<script src="https://cdn.ckeditor.com/ckeditor5/41.1.0/classic/ckeditor.js" crossorigin="anonymous"></script>
<script src="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.js"
crossorigin="anonymous"></script>
<script src="https://unpkg.com/filepond/dist/filepond.js" crossorigin="anonymous"></script>
<script>
const Toast = Swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
didOpen: (toast) => {
toast.addEventListener('mouseenter', Swal.stopTimer)
toast.addEventListener('mouseleave', Swal.resumeTimer)
}
});
$(document).ready(function () {
// ===== TAB PERSISTENCE: Remember active tab across page refreshes =====
(function () {
const STORAGE_KEY = 'systemConfigActiveTab';
// Save tab whenever user switches
document.querySelectorAll('[data-bs-toggle="tab"]').forEach(function (tabEl) {
tabEl.addEventListener('shown.bs.tab', function (e) {
localStorage.setItem(STORAGE_KEY, e.target.getAttribute('data-bs-target'));
});
});
// Restore saved tab on page load
const savedTab = localStorage.getItem(STORAGE_KEY);
if (savedTab) {
const tabEl = document.querySelector(`[data-bs-target="${savedTab}"]`);
if (tabEl) {
// Small delay to ensure all components are ready to handle the switch
setTimeout(() => {
bootstrap.Tab.getOrCreateInstance(tabEl).show();
}, 50);
}
}
})();
// Initialize CKEditor 5
ClassicEditor
.create(document.querySelector('#app_tagline2'), {
ckfinder: {
uploadUrl: "{{ route('editor.upload') }}?_token={{ csrf_token() }}"
}
})
.then(newEditor => {
document.querySelector('#app_tagline2').ckeditorInstance = newEditor;
})
.catch(error => {
console.error(error);
});
// Initialize Legal & Content Editors
const legalEditors = [
'#page_privacy_content',
'#page_tos_content',
'#page_help_content',
'#page_about_content',
'#page_security_content'
];
legalEditors.forEach(selector => {
const el = document.querySelector(selector);
if (el) {
ClassicEditor
.create(el, {
ckfinder: {
uploadUrl: "{{ route('editor.upload') }}?_token={{ csrf_token() }}"
}
})
.then(newEditor => {
el.ckeditorInstance = newEditor;
})
.catch(error => {
console.error(error);
});
}
});
// Initialize FilePond
FilePond.registerPlugin(FilePondPluginImagePreview);
const logoPond = FilePond.create(document.querySelector('#app_logo'), {
name: 'app_logo',
labelIdle: 'Drag & Drop your Logo or <span class="filepond--label-action">Browse</span>',
imagePreviewHeight: 170,
stylePanelLayout: 'compact',
styleLoadIndicatorPosition: 'center bottom',
styleProgressIndicatorPosition: 'right bottom',
styleButtonRemoveItemPosition: 'left bottom',
styleButtonProcessItemPosition: 'right bottom',
});
const faviconPond = FilePond.create(document.querySelector('#app_favicon'), {
name: 'app_favicon',
labelIdle: 'Favicon <span class="filepond--label-action">Browse</span>',
imagePreviewHeight: 100,
stylePanelLayout: 'compact',
});
const maintenancePond = FilePond.create(document.querySelector('#maintenance_mode_image'), {
name: 'maintenance_mode_image',
labelIdle: 'Illustration <span class="filepond--label-action">Browse</span>',
imagePreviewHeight: 150,
stylePanelLayout: 'compact',
});
// ===== CRITICAL: Append FilePond files to FormData before AJAX send =====
$('#systemConfigForm').on('ajaxForm:beforeSend', function (e, formData) {
const logoFiles = logoPond.getFiles();
if (logoFiles.length > 0) {
formData.set('app_logo', logoFiles[0].file);
}
const faviconFiles = faviconPond.getFiles();
if (faviconFiles.length > 0) {
formData.set('app_favicon', faviconFiles[0].file);
}
const maintenanceFiles = maintenancePond.getFiles();
if (maintenanceFiles.length > 0) {
formData.set('maintenance_mode_image', maintenanceFiles[0].file);
}
});
// ===== UI updates after successful save =====
$('#systemConfigForm').on('ajaxForm:success', function (e, response) {
StandardSwal.fire({
title: "{{ __('Success!') }}",
text: response.message,
icon: 'success',
showConfirmButton: false,
timer: 2000,
timerProgressBar: true
});
if (!response.settings) return;
// Instance Mode badge
const mode = response.settings.instance_mode || 'Production';
const $container = $('#sidebar-mode-container');
const $badge = $('#sidebar-mode-badge');
const $text = $('#sidebar-mode-text');
if (mode === 'Production') {
$container.addClass('d-none');
} else {
$container.removeClass('d-none');
$text.text(mode.toUpperCase());
$badge.removeClass('bg-success bg-warning bg-info text-white text-dark');
if (mode === 'Trial') $badge.addClass('bg-warning text-dark');
else if (mode === 'Demo') $badge.addClass('bg-info text-dark');
}
// Refresh logo preview + header logo
if (response.settings.app_logo) {
const bust = '?v=' + Date.now();
const logoUrl = '/assets/img/logo.png' + bust;
$('#logo-preview').attr('src', logoUrl).show();
$('#logo-preview').closest('.mb-2').show();
$('#header-logo').attr('src', logoUrl);
$('#header-logo-container').removeClass('d-none');
}
// Refresh favicon preview + browser tab favicon
if (response.settings.app_favicon) {
const bust = '?v=' + Date.now();
const favUrl = '/assets/img/favicon.png' + bust;
$('#favicon-preview').attr('src', favUrl).show();
$('#favicon-preview').closest('.mb-2').show();
$('#dynamic-favicon').attr('href', favUrl);
}
// Global text updates
if (response.settings.app_name) {
$('.app-name-text').text(response.settings.app_name);
document.title = response.settings.app_name;
}
if (response.settings.app_tagline) {
$('.company-tagline').text(response.settings.app_tagline);
}
// Maintenance Status Badge Update
if (response.hasOwnProperty('is_down')) {
const $mntStatus = $('.status-indicator');
if (response.is_down) {
$mntStatus.html(`<span class="badge rounded-pill bg-danger-subtle text-danger px-3 border border-danger-subtle"><span class="status-dot-red me-1"></span>{{ __('Currently DOWN') }}</span>`);
} else {
$mntStatus.html(`<span class="badge rounded-pill bg-success-subtle text-success px-3 border border-success-subtle"><span class="status-dot-green me-1"></span>{{ __('Active') }}</span>`);
}
}
// Clear FilePond after successful upload
window.isSystemConfigSaving = true; // Flag to prevent preview reset during pond clear
logoPond.removeFiles();
faviconPond.removeFiles();
maintenancePond.removeFiles();
// Refresh Maintenance Preview from server
if (response.settings.maintenance_mode_image) {
const bust = '?v=' + Date.now();
const mntUrl = '/assets/img/maintenance.png' + bust;
$('#preview-mnt-image-container').html(`<img src="${mntUrl}" class="img-fluid rounded mb-2" style="max-height: 120px; object-fit: contain;">`);
}
setTimeout(() => { window.isSystemConfigSaving = false; }, 500);
// ===== LIVE SIDEBAR UPDATE for Monitoring Tools =====
const pulseOn = $('#engine_pulse_enabled').is(':checked');
const telescopeOn = $('#engine_telescope_enabled').is(':checked');
const swaggerOn = $('#engine_swagger_enabled').is(':checked');
const horizonOn = $('#engine_horizon_enabled').is(':checked');
$('#menu-pulse').toggleClass('d-none', !pulseOn);
$('#menu-telescope').toggleClass('d-none', !telescopeOn);
$('#menu-swagger').toggleClass('d-none', !swaggerOn);
$('#menu-horizon').toggleClass('d-none', !horizonOn);
// AI Diagnostics visibility
const aiDiagOn = $('#ai_healing_enabled').is(':checked');
$('#menu-ai-diagnostics').toggleClass('d-none', !aiDiagOn);
// Show/Hide the group header based on any item being visible
if (pulseOn || telescopeOn || swaggerOn || horizonOn || aiDiagOn) {
$('#sidebar-dev-group').removeClass('d-none');
} else {
$('#sidebar-dev-group').addClass('d-none');
}
});
$('#systemConfigForm').on('ajaxForm:error', function (e, xhr) {
const msg = xhr.responseJSON?.message || '{{ __("Failed to save configuration.") }}';
StandardSwal.fire({
title: "{{ __('Error') }}",
text: msg,
icon: 'error'
});
});
// ===== SAP CONNECTION TEST =====
$('#btn-test-sap').on('click', function () {
const $btn = $(this);
const originalHtml = $btn.html();
const data = {
_token: "{{ csrf_token() }}",
sap_rfc_ashost: $('input[name="sap_rfc_ashost"]').val(),
sap_rfc_sysnr: $('input[name="sap_rfc_sysnr"]').val(),
sap_rfc_client: $('input[name="sap_rfc_client"]').val(),
sap_rfc_user: $('input[name="sap_rfc_user"]').val(),
sap_rfc_passwd: $('input[name="sap_rfc_passwd"]').val(),
sap_rfc_router: $('input[name="sap_rfc_router"]').val()
};
$btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-2"></span>{{ __("Connecting...") }}');
$.post("{{ route('system-config.test-sap') }}", data, function (response) {
StandardSwal.fire({
title: "{{ __('Connection Successful!') }}",
text: response.message,
icon: 'success'
});
}).fail(function (xhr) {
const msg = xhr.responseJSON?.message || '{{ __("Connection failed.") }}';
StandardSwal.fire({
title: "{{ __('Connection Failed') }}",
text: msg,
icon: 'error'
});
}).always(function () {
$btn.prop('disabled', false).html(originalHtml);
});
});
// ===== LIVE PREVIEW LOGIC: Maintenance Mode =====
$('input[name="maintenance_mode_title"]').on('input', function () {
$('#preview-mnt-title').text($(this).val() || 'Under Maintenance');
});
$('textarea[name="maintenance_mode_message"]').on('input', function () {
let msg = $(this).val() || 'We are currently performing scheduled maintenance...';
if (msg.length > 100) msg = msg.substring(0, 100) + '...';
$('#preview-mnt-message').text(msg);
});
maintenancePond.on('addfile', (error, file) => {
if (error) return;
const url = URL.createObjectURL(file.file);
$('#preview-mnt-image-container').html(`<img src="${url}" class="img-fluid rounded mb-2" style="max-height: 120px; object-fit: contain;">`);
});
maintenancePond.on('removefile', (error, file) => {
if (window.isSystemConfigSaving) return; // Don't reset if we are just clearing after save
$('#preview-mnt-image-container').html(`<i class="bi bi-cone-striped fs-1 text-secondary opacity-25 d-block mb-3"></i>`);
});
// ===== BACKUP & RESTORE LOGIC =====
function renderBackups(backups) {
const $tbody = $('#backup-list-table tbody');
$tbody.empty();
if (!backups || backups.length === 0) {
$tbody.append('<tr><td colspan="4" class="text-center py-5 text-muted">{{ __("No backup archives found.") }}</td></tr>');
return;
}
backups.forEach(function (item) {
let storageIcon = 'bi-hdd text-secondary';
let storageClass = 'bg-secondary-subtle text-secondary';
if (item.storage === 'gdrive') {
storageIcon = 'bi-google text-primary';
storageClass = 'bg-primary-subtle text-primary';
} else if (item.storage === 's3') {
storageIcon = 'bi-clouds text-warning';
storageClass = 'bg-warning-subtle text-warning-emphasis';
}
$tbody.append(`
<tr>
<td class="ps-3">
<div class="d-flex align-items-center">
<div class="avatar avatar-30 bg-light rounded-circle d-flex align-items-center justify-content-center me-2">
<i class="bi ${storageIcon}"></i>
</div>
<div>
<div class="fw-bold small text-truncate" style="max-width: 200px;" title="${item.name}">${item.name.split('/').pop()}</div>
<div class="d-flex align-items-center" style="gap: 5px;">
<span class="text-muted" style="font-size: 0.65rem;">${item.size}</span>
<span class="badge ${storageClass} border-0 rounded-pill uppercase" style="font-size: 0.55rem; padding: 2px 6px;">${item.storage}</span>
</div>
</div>
</div>
</td>
<td>
<span class="badge bg-success-subtle text-success border border-success-subtle rounded-pill px-2" style="font-size: 0.65rem;">
${item.status}
</span>
</td>
<td>
<span class="text-muted small">${item.date}</span>
</td>
<td class="text-end pe-3">
<div class="btn-group btn-group-sm">
<a href="{{ route('backup-restore.download') }}?disk=${item.storage}&path=${item.name}" class="btn btn-outline-dark border-0 rounded-circle me-1" title="Download">
<i class="bi bi-download"></i>
</a>
<button type="button" class="btn btn-outline-primary border-0 rounded-circle me-1 btn-restore-backup" data-disk="${item.storage}" data-path="${item.name}" title="Restore">
<i class="bi bi-arrow-counterclockwise"></i>
</button>
<button type="button" class="btn btn-outline-danger border-0 rounded-circle btn-delete-backup" data-disk="${item.storage}" data-path="${item.name}" title="Delete">
<i class="bi bi-trash"></i>
</button>
</div>
</td>
</tr>
`);
});
}
function loadBackups() {
const $tbody = $('#backup-list-table tbody');
$tbody.html('<tr id="backup-loading"><td colspan="4" class="text-center py-5"><div class="spinner-border spinner-border-sm text-primary me-2"></div>{{ __("Scanning storage...") }}</td></tr>');
$.get("{{ route('backup-restore.index') }}", function (response) {
if (response.success) {
renderBackups(response.backups);
} else {
$tbody.html(`<tr><td colspan="4" class="text-center py-5 text-danger">${response.message || '{{ __("Failed to load inventory.") }}'}</td></tr>`);
}
}).fail(function () {
$tbody.html('<tr><td colspan="4" class="text-center py-5 text-danger">{{ __("Failed to reach server.") }}</td></tr>');
});
}
// Toggle Cloud Config fields based on driver selection
$('#backup_db_driver').on('change', function () {
const driver = $(this).val();
// Outer wrapper toggle
if (driver === 'gdrive' || driver === 's3') {
$('#cloud_config_wrapper').slideDown();
} else {
$('#cloud_config_wrapper').slideUp();
}
// Inner fields toggle
if (driver === 'gdrive') {
$('#s3_fields').hide();
$('#gdrive_fields').fadeIn();
} else if (driver === 's3') {
$('#gdrive_fields').hide();
$('#s3_fields').fadeIn();
}
});
// Toggle encryption key visibility
$('#backup_db_encrypt').on('change', function () {
if ($(this).is(':checked')) {
$('#encryption_key_wrapper').slideDown();
} else {
$('#encryption_key_wrapper').slideUp();
}
});
// ===== SEND TEST EMAIL =====
$('#btn-send-test-email').on('click', function () {
const $btn = $(this);
const recipient = $('#test-email-recipient').val().trim();
$btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-1"></span> {{ __("Sending...") }}');
$.ajax({
url: "{{ route('system-config.test-email') }}",
method: 'POST',
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') },
contentType: 'application/json',
data: JSON.stringify({ to: recipient }),
success: function (res) {
StandardSwal.fire({
title: "Email Sent Successfully!",
text: res.message || "A test email has been dispatched to the recipient.",
icon: 'success',
showConfirmButton: false,
timer: 2000,
timerProgressBar: true
});
},
error: function (xhr) {
const msg = xhr.responseJSON?.message || "Verify your mail server configuration and try again.";
StandardSwal.fire({
title: "Delivery Failed!",
text: msg,
icon: 'error'
});
},
complete: function () {
$btn.prop('disabled', false).html('<i class="bi bi-send-check me-1"></i> {{ __("Send Test Email") }}');
}
});
});
// Load when tab is navigated to
$('#backup-restore-tab').on('shown.bs.tab', loadBackups);
// Also load immediately if this tab was restored from localStorage on page refresh
if ($('#backup-restore').hasClass('active')) {
loadBackups();
}
$('#btn-refresh-backups').on('click', function () {
const $icon = $(this).find('i');
$icon.addClass('spinner-border spinner-border-sm border-0').removeClass('bi-arrow-clockwise');
loadBackups();
setTimeout(() => $icon.removeClass('spinner-border spinner-border-sm border-0').addClass('bi-arrow-clockwise'), 1000);
});
// Create Backup
$('#btn-create-backup').on('click', function () {
const $btn = $(this);
const original = $btn.html();
$btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-1"></span> Tasking...');
$.post("{{ route('backup-restore.create') }}", { _token: "{{ csrf_token() }}" }, function (response) {
if (response.success) {
if (response.backups) {
renderBackups(response.backups);
} else {
loadBackups();
}
StandardSwal.fire({
title: "Backup Created!",
text: response.message || "A new system snapshot has been successfully stored.",
icon: 'success',
showConfirmButton: false,
timer: 2000,
timerProgressBar: true
});
} else {
StandardSwal.fire({
title: 'Creation Failed!',
text: response.message || "The system was unable to generate a backup file.",
icon: 'error'
});
}
}).fail(function (xhr) {
const msg = xhr.responseJSON ? xhr.responseJSON.message : "System error occurred while generating backup.";
StandardSwal.fire({
title: 'System Error!',
text: msg,
icon: 'error'
});
}).always(() => {
$btn.prop('disabled', false).html(original);
});
});
// Delete Backup
$(document).on('click', '.btn-delete-backup', function () {
const $btn = $(this);
const disk = $btn.data('disk');
const path = $btn.data('path');
StandardSwal.fire({
title: "Remove this backup?",
text: "The selected backup file will be permanently deleted from the disk storage.",
icon: 'warning',
showCancelButton: true,
customClass: {
confirmButton: 'btn-pill-danger',
cancelButton: 'btn-pill-cancel'
},
confirmButtonText: "Yes, Delete",
cancelButtonText: "Cancel"
}).then((result) => {
if (result.isConfirmed) {
$btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm"></span>');
$.post("{{ route('backup-restore.delete') }}", {
_token: "{{ csrf_token() }}",
disk: disk,
path: path
}, function (response) {
if (response.success) {
// Live Reload immediately
renderBackups(response.backups);
StandardSwal.fire({
title: "Deleted Successfully!",
text: response.message || "The backup archive has been removed from storage.",
icon: 'success',
showConfirmButton: false,
timer: 2000,
timerProgressBar: true
});
} else {
StandardSwal.fire({
title: 'Deletion Failed!',
text: response.message || "Failed to remove the requested backup file.",
icon: 'error'
});
}
}).fail(function (xhr) {
const msg = xhr.responseJSON ? xhr.responseJSON.message : "An error occurred on the server during deletion.";
StandardSwal.fire({
title: 'System Error!',
text: msg,
icon: 'error'
});
}).always(() => {
$btn.prop('disabled', false).html('<i class="bi bi-trash"></i>');
});
}
});
});
// Restore Backup
$(document).on('click', '.btn-restore-backup', function () {
const $btn = $(this);
const disk = $btn.data('disk');
const path = $btn.data('path');
StandardSwal.fire({
title: "Initiate System Restore?",
html: `<div class="alert alert-danger mb-0 small">
<strong>CRITICAL WARNING:</strong> This will OVERWRITE your current database with the selected backup data. This process cannot be undone.
</div>`,
icon: 'warning',
showCancelButton: true,
customClass: {
confirmButton: 'btn-pill-danger',
cancelButton: 'btn-pill-cancel'
},
confirmButtonText: "Yes, Restore Now",
cancelButtonText: "Cancel",
showLoaderOnConfirm: true,
preConfirm: () => {
return $.post("{{ route('backup-restore.restore') }}", {
_token: "{{ csrf_token() }}",
disk: disk,
path: path
}).fail(xhr => {
const msg = xhr.responseJSON ? xhr.responseJSON.message : "{{ __('Restore failed') }}";
Swal.showValidationMessage(`Request failed: ${msg}`);
});
},
allowOutsideClick: () => !Swal.isLoading()
}).then((result) => {
if (result.isConfirmed) {
if (result.value && result.value.success === false) {
StandardSwal.fire({
title: 'Restoration Failed!',
text: result.value.message || "Failed to restore from the selected archive.",
icon: 'error'
});
} else {
const msg = result.value ? result.value.message : "System data has been successfully reverted to the selected state.";
StandardSwal.fire({
title: "Restoration Complete!",
text: msg,
icon: 'success',
showConfirmButton: false,
timer: 3000,
timerProgressBar: true
});
setTimeout(() => location.reload(), 3000);
}
}
});
});
// ===== AI CONFIGURATION LOGIC =====
const modelMap = {
'gpt': ['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'gpt-3.5-turbo'],
'gemini': ['gemini-1.5-pro', 'gemini-1.5-flash', 'gemini-1.0-pro'],
'claude': ['claude-3-5-sonnet-20240620', 'claude-3-opus-20240229', 'claude-3-sonnet-20240229', 'claude-3-haiku-20240307'],
'deepseek': ['deepseek-chat', 'deepseek-coder'],
'grok': ['grok-1'],
'mistral': ['mistral-large-latest', 'mistral-medium-latest', 'mistral-small-latest', 'open-mistral-7b', 'open-mixtral-8x7b'],
'ollama': ['llama3', 'mistral', 'phi3', 'gemma:2b', 'command-r'],
'openrouter': ['openai/gpt-4o', 'anthropic/claude-3.5-sonnet', 'google/gemini-pro-1.5', 'meta-llama/llama-3-70b-instruct', 'mistralai/mixtral-8x7b-instruct']
};
function updateModelList(provider) {
const $select = $('#ai_default_model');
const initialValue = $select.attr('data-initial-value');
const currentValue = $select.val() || initialValue;
$select.empty();
if (modelMap[provider]) {
modelMap[provider].forEach(model => {
const selected = (model === currentValue) ? 'selected' : '';
$select.append(`<option value="${model}" ${selected}>${model}</option>`);
});
// If the currentValue was not in the new provider's list,
// and it's not the first time (initialValue), select the first one.
if (!$select.val() && modelMap[provider].length > 0) {
$select.val(modelMap[provider][0]);
}
}
// Clear initial value after first use to allow switching
$select.removeAttr('data-initial-value');
}
function loadAiStats() {
const period = $('input[name="ai_period"]:checked').val() || 'all';
$.get("{{ route('system-config.ai-stats') }}", { period: period }, function (res) {
if (res.success) {
// Unified value updater like monitoring system
updateVal('#stat-total-requests', res.stats.total_requests.toLocaleString());
updateVal('#stat-total-tokens', (res.stats.total_tokens || 0).toLocaleString());
updateVal('#stat-total-cost', '$' + parseFloat(res.stats.total_cost || 0).toFixed(4));
}
});
}
function updateVal(selector, newVal) {
const el = $(selector);
if (el.text() !== newVal.toString()) {
el.text(newVal).addClass('animate__animated animate__pulse');
setTimeout(() => el.removeClass('animate__animated animate__pulse'), 1000);
}
}
// Period Filter Handler
$('.period-filter').on('change', function () {
loadAiStats();
});
// Initial load
if ($('#ai-config').hasClass('active')) {
loadAiStats();
updateModelList($('input[name="ai_provider"]:checked').val());
}
$('#ai-config-tab').on('shown.bs.tab', function () {
loadAiStats();
updateModelList($('input[name="ai_provider"]:checked').val());
});
// Toggle provider settings visibility
$('input[name="ai_provider"]').on('change', function () {
const provider = $(this).val();
$('.provider-settings').addClass('d-none');
$(`#${provider}_settings`).removeClass('d-none');
updateModelList(provider);
});
// Password Visibility Toggle for API Keys
// Run AI Simulation
$('#btn-run-simulation').on('click', function () {
const $btn = $(this);
const prompt = $('#simulation-prompt').val().trim();
const $output = $('#ai-simulation-output');
const $metrics = $('#simulation-metrics');
// Get current form values for live testing
const provider = $('input[name="ai_provider"]:checked').val();
const key = $(`input[name="ai_${provider}_key"]`).val();
const model = $('input[name="ai_default_model"]').val();
const instruction = $('textarea[name="ai_system_instruction"]').val();
const temperature = $('input[name="ai_temperature"]').val();
const maxTokens = $('input[name="ai_max_tokens"]').val();
if (!prompt) {
Toast.fire({ icon: 'warning', title: 'Please enter a prompt.' });
return;
}
// Clear input immediately
$('#simulation-prompt').val('');
const startTime = performance.now();
$btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm"></span>');
$output.html('<div class="text-center mt-5"><div class="spinner-grow text-primary" role="status"></div><p class="mt-2 text-muted small">AI is thinking...</p></div>');
$metrics.addClass('d-none');
$.ajax({
url: "{{ route('system-config.ai-simulate') }}",
method: 'POST',
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') },
data: {
prompt: prompt,
ai_provider: provider,
ai_key: key,
ai_model: model,
ai_instruction: instruction,
ai_temperature: temperature,
ai_max_tokens: maxTokens
},
success: function (res) {
const endTime = performance.now();
const latency = Math.round(endTime - startTime);
if (res.success) {
$output.html(`<div class="ai-response p-3 rounded-4 bg-white shadow-sm border animate__animated animate__fadeIn">
<div class="d-flex align-items-center mb-2 border-bottom pb-2">
<img src="/assets/img/AI/${provider}.png" width="16" class="me-2">
<span class="badge bg-primary-subtle text-primary rounded-pill x-small px-2 me-auto">${res.provider.toUpperCase()}</span>
<span class="x-small text-muted"><i class="bi bi-clock me-1"></i>${new Date().toLocaleTimeString()}</span>
</div>
<div class="response-content py-2" style="white-space: pre-wrap; font-size: 0.9rem; line-height: 1.6;">${res.response}</div>
<div class="d-flex gap-3 mt-2 pt-2 border-top x-small text-muted italic">
<span><i class="bi bi-cpu me-1"></i>${model}</span>
${res.usage ? `<span><i class="bi bi-lightning-charge me-1"></i>${res.usage.total_tokens} tokens</span>` : ''}
</div>
</div>`);
// Update metrics bar
$('#metric-latency').text(latency);
if (res.usage && res.usage.estimated_cost) {
$('#metric-cost').text(parseFloat(res.usage.estimated_cost).toFixed(4));
} else {
$('#metric-cost').text('0.000');
}
$metrics.removeClass('d-none').addClass('animate__animated animate__fadeIn');
// Refresh global stats
loadAiStats();
} else {
$output.html(`<div class="alert alert-danger rounded-4 py-3 shadow-sm border-0">
<h6 class="fw-bold mb-1"><i class="bi bi-exclamation-octagon-fill me-2"></i>Simulation Failed</h6>
<p class="small mb-0">${res.message}</p>
</div>`);
}
},
error: function (xhr) {
const msg = xhr.responseJSON?.message || "An unexpected error occurred during simulation.";
$output.html(`<div class="alert alert-danger rounded-4 py-3 shadow-sm border-0">
<h6 class="fw-bold mb-1"><i class="bi bi-bug-fill me-2"></i>Error Contacting Provider</h6>
<p class="small mb-0">${msg}</p>
</div>`);
},
complete: function () {
$btn.prop('disabled', false).html('<i class="bi bi-send-fill fs-5"></i>');
}
});
});
// Feature Toggle Protection (Safeguard)
$('#feature_notification_center, #maintenance_mode_enabled').on('change', function () {
const $checkbox = $(this);
const isChecked = $checkbox.is(':checked');
const id = $checkbox.attr('id');
const featureName = id.replace('feature_', '').replace(/_/g, ' ').toUpperCase();
// Only show alert when DISABLING
if (!isChecked) {
StandardSwal.fire({
title: `Deactivate ${featureName}?`,
text: "WARNING: Disabling this core feature may cause application errors (404) or hide critical monitoring data for all users. Are you absolutely sure?",
icon: 'warning',
showCancelButton: true,
confirmButtonText: "Yes, Deactivate",
cancelButtonText: "Cancel",
customClass: {
confirmButton: 'btn-pill-danger',
cancelButton: 'btn-pill-cancel shadow-sm'
}
}).then((result) => {
if (!result.isConfirmed) {
// Re-enable if user cancels
$checkbox.prop('checked', true);
}
});
}
});
// ===== HANDLE URL ANCHOR (FOR GLOBAL SEARCH) =====
const urlParams = new URLSearchParams(window.location.search);
const anchor = urlParams.get('anchor');
if (anchor) {
const $targetTab = $(`#${anchor}-tab`);
if ($targetTab.length) {
$targetTab.tab('show');
// Optional: Scroll to top of the card
$('html, body').animate({
scrollTop: $(".card").offset().top - 100
}, 500);
}
}
// ===== SMART SEARCH ENGINE 2.2 (TAB FILTER ONLY) =====
$('#configSearch').on('input', function () {
const query = $(this).val().toLowerCase();
const $navItems = $('#configTabs .nav-item');
const $tabPanes = $('.tab-pane');
if (query === '') {
$navItems.show();
$tabPanes.find('.mb-3, .mb-4, .row > div, hr, h6').show(); // Reset visibility
return;
}
let firstMatchingTabId = null;
let currentTabHasMatch = false;
const activeTabId = $('.tab-pane.active').attr('id');
// Reset all content visibility inside panes to "Full"
$tabPanes.find('.mb-3, .mb-4, hr, h6, .row > div').show();
$tabPanes.each(function () {
const $pane = $(this);
const paneId = $pane.attr('id');
let paneHasMatch = false;
// Check if this tab contains the query anywhere
const paneText = $pane.text().toLowerCase();
if (paneText.includes(query)) {
paneHasMatch = true;
}
// Update Nav Tabs visibility
const $navLink = $(`button[data-bs-target="#${paneId}"]`);
if (paneHasMatch) {
$navLink.parent('.nav-item').show();
if (!firstMatchingTabId) firstMatchingTabId = paneId;
if (paneId === activeTabId) currentTabHasMatch = true;
} else {
$navLink.parent('.nav-item').hide();
}
});
// Pivot to the first matching tab if current one doesn't match
if (!currentTabHasMatch && firstMatchingTabId) {
$(`#${firstMatchingTabId}-tab`).tab('show');
}
});
// SAP Connection Test
$('#btn-test-sap').on('click', function () {
const btn = $(this);
const originalHtml = btn.html();
btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-1"></span> TESTING...');
$.post('{{ route("system-config.test-sap") }}', {
_token: '{{ csrf_token() }}',
sap_rfc_ashost: $('input[name="sap_rfc_ashost"]').val(),
sap_rfc_sysnr: $('input[name="sap_rfc_sysnr"]').val(),
sap_rfc_client: $('input[name="sap_rfc_client"]').val(),
sap_rfc_user: $('input[name="sap_rfc_user"]').val(),
sap_rfc_passwd: $('input[name="sap_rfc_passwd"]').val(),
sap_rfc_router: $('input[name="sap_rfc_router"]').val()
}, function (d) {
StandardSwal.fire({
title: 'SAP Connection Success',
text: d.message,
icon: 'success',
confirmButtonText: 'Great!'
});
btn.prop('disabled', false).html(originalHtml);
}).fail(function (xhr) {
StandardSwal.fire({
title: 'SAP Connection Failed',
text: xhr.responseJSON.message || 'Check your credentials and network connection.',
icon: 'error',
confirmButtonText: 'Try Again'
});
btn.prop('disabled', false).html(originalHtml);
});
});
// Database Connection Test
$('#btn-test-db').on('click', function () {
const btn = $(this);
const originalHtml = btn.html();
btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-1"></span> TESTING...');
$.post('{{ route("system-config.test-db") }}', {
_token: '{{ csrf_token() }}'
}, function (d) {
StandardSwal.fire({
title: 'Database Connection Success',
text: d.message,
icon: 'success',
confirmButtonText: 'Great!'
});
btn.prop('disabled', false).html(originalHtml);
}).fail(function (xhr) {
StandardSwal.fire({
title: 'Database Connection Failed',
text: xhr.responseJSON.message || 'System was unable to establish a connection.',
icon: 'error',
confirmButtonText: 'Try Again'
});
btn.prop('disabled', false).html(originalHtml);
});
});
});
</script>
@endpush
@push('styles')
<style>
.ls-n2 {
letter-spacing: -2px;
}
.fw-black {
font-weight: 900 !important;
}
.hover-opacity-100:hover {
opacity: 1 !important;
}
.transition-all {
transition: all 0.2s ease-in-out;
}
.bg-decoration {
position: absolute;
right: -50px;
bottom: -50px;
width: 200px;
height: 200px;
background: rgba(255, 255, 255, 0.03);
border-radius: 50%;
}
.bg-decoration::before {
content: '';
position: absolute;
top: -50px;
left: -50px;
width: 150px;
height: 150px;
background: rgba(255, 255, 255, 0.05);
border-radius: 50%;
}
.display-3 {
font-size: 3.2rem;
line-height: 1;
}
.x-small {
font-size: 0.7rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.025em;
}
.op-75 {
opacity: 0.75;
}
/* SweetAlert2 Theme Customization */
.swal2-styled.swal2-confirm {
background-color: #1e1e1e !important;
box-shadow: none !important;
border-radius: 50rem !important;
padding: 0.45rem 1.6rem !important;
font-size: 0.85rem !important;
font-weight: 500 !important;
}
.swal2-popup {
border-radius: 1.5rem !important;
}
/* AI Provider Active State Styling */
.btn-check:checked+label.btn-outline-primary {
background-color: #1a1d21 !important;
border-color: #1a1d21 !important;
color: #ffffff !important;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05) !important;
}
.btn-check:checked+label.btn-outline-primary img {
filter: brightness(0) invert(1);
}
.btn-check:checked+label.btn-outline-primary span {
color: #ffffff !important;
}
.btn-outline-primary {
border-color: #e2e8f0;
color: #475569;
background-color: #ffffff;
transition: all 0.2s ease-in-out;
}
.btn-outline-primary:hover {
background-color: #f8fafc;
border-color: #cbd5e1;
color: #1e293b;
}
</style>
@endpush
</x-app-layout>