*/
public array $diagnostics = [];
public function mount(): void
{
$this->fillForm();
$this->runDiagnostics();
}
protected function fillForm(): void
{
$paths = $this->autoDetectPaths();
$this->data = [
'alert_email_enabled' => $this->getSettingBool('alert_email_enabled'),
'alert_email_address' => $this->getSetting('alert_email_address', ''),
'alert_discord_enabled' => $this->getSettingBool('alert_discord_enabled'),
'alert_discord_webhook_url' => $this->getSetting('alert_discord_webhook_url', ''),
'discord_webhook_ranks' => json_decode($this->getSetting('discord_webhook_ranks', '[]'), true) ?? [],
'alert_emulator_enabled' => $this->getSettingBool('alert_emulator_enabled', true),
'alert_ddos_enabled' => $this->getSettingBool('alert_ddos_enabled', true),
'alert_ddos_threshold' => (int) $this->getSetting('alert_ddos_threshold', '100'),
'alert_ddos_auto_block' => $this->getSettingBool('alert_ddos_auto_block'),
'alert_errors_enabled' => $this->getSettingBool('alert_errors_enabled', true),
'alert_error_threshold' => $this->getSetting('alert_error_threshold', '10'),
'alert_min_severity' => $this->getSetting('alert_min_severity', AlertSeverity::ERROR->value),
'emulator_github_url' => $this->getSetting('emulator_github_url', ''),
'emulator_source_repo' => $this->getSetting('emulator_source_repo', ''),
'emulator_jar_direct_url' => $this->getSetting('emulator_jar_direct_url', ''),
'emulator_jar_path' => $this->getSetting('emulator_jar_path', $paths['emulator_jar_path']),
'emulator_source_path' => $this->getSetting('emulator_source_path', $paths['emulator_source_path']),
'emulator_service_name' => $this->getSetting('emulator_service_name', 'arcturus'),
'emulator_github_branch' => $this->getSetting('emulator_github_branch', 'main'),
'emulator_database_host' => $this->getSetting('emulator_database_host', '127.0.0.1'),
'emulator_database_port' => $this->getSetting('emulator_database_port', '3306'),
'emulator_database_name' => $this->getSetting('emulator_database_name', ''),
'emulator_database_username' => $this->getSetting('emulator_database_username', ''),
'emulator_database_password' => $this->getSetting('emulator_database_password', ''),
'emulator_version' => $this->getSetting('emulator_version', 'Onbekend'),
'auto_update_enabled' => $this->getSettingBool('auto_update_enabled'),
'auto_update_schedule' => $this->getSetting('auto_update_schedule', '03:00'),
'auto_update_days' => $this->getSetting('auto_update_days', '0,6'),
'nitro_client_path' => $this->getSetting('nitro_client_path', $paths['nitro_client_path']),
'nitro_renderer_path' => $this->getSetting('nitro_renderer_path', $paths['nitro_renderer_path']),
'nitro_build_path' => $this->getSetting('nitro_build_path', $paths['nitro_build_path']),
'nitro_webroot' => $this->getSetting('nitro_webroot', $paths['nitro_webroot']),
'gamedata_path' => $this->getSetting('gamedata_path', $paths['gamedata_path']),
'nitro_github_branch' => $this->getSetting('nitro_github_branch', 'main'),
'nitro_github_url' => $this->getSetting('nitro_github_url', ''),
'nitro_site_url' => $this->getSetting('nitro_site_url', $this->getCurrentSiteUrl()),
'nitro_auto_update_configs' => $this->getSettingBool('nitro_auto_update_configs'),
'nitro_auto_update_enabled' => $this->getSettingBool('nitro_auto_update_enabled'),
'nitro_auto_update_schedule' => $this->getSetting('nitro_auto_update_schedule', '03:00'),
'nitro_auto_update_days' => $this->getSetting('nitro_auto_update_days', '0,6'),
'hotel_alert_message' => '',
];
}
public function form(Schema $schema): Schema
{
return $schema
->components([
Section::make('🎯 Live Status')
->description('Real-time hotel statistieken')
->icon('heroicon-o-heart')
->columns(4)
->schema([
Placeholder::make('online_users')
->label('Online')
->content(fn (): HtmlString => $this->getCardHtml('Online', $this->getOnlineUsersCount(), '#22c55e', 'heroicon-o-users')),
Placeholder::make('emulator_status')
->label('Emulator')
->content(fn (): HtmlString => $this->getCardHtml('Emulator', $this->getEmulatorStatusText(), $this->getEmulatorStatusColor(), 'heroicon-o-server')),
Placeholder::make('database_status')
->label('Database')
->content(fn (): HtmlString => $this->getCardHtml('Database', $this->isDatabaseOnline() ? 'Online' : 'Offline', $this->isDatabaseOnline() ? '#22c55e' : '#ef4444', 'heroicon-o-circle-stack')),
Placeholder::make('server_load')
->label('Load')
->content(fn (): HtmlString => $this->getCardHtml('Load', $this->getServerLoad(), '#3b82f6', 'heroicon-o-cpu-chip')),
]),
Section::make('📊 Server Informatie')
->description('Gedetailleerde server status')
->icon('heroicon-o-information-circle')
->schema([
Placeholder::make('server_info')
->label('')
->content(fn (): HtmlString => $this->renderServerInfo()),
]),
Section::make('🩺 Systeem Gezondheid')
->description('Automatische systeem diagnostiek')
->icon('heroicon-o-heart')
->afterHeader([
Action::make('refresh_diagnostics')
->label('Vernieuwen')
->icon('heroicon-o-arrow-path')
->color('info')
->action('refreshDiagnostics'),
])
->schema([
Placeholder::make('diagnostics')
->label('')
->content(fn (): HtmlString => $this->renderDiagnostics()),
]),
Section::make('🏨 Hotel Status')
->description('Emulator en Nitro status')
->icon('heroicon-o-building-office')
->schema([
Placeholder::make('hotel_status')
->label('')
->content(fn (): HtmlString => $this->renderHotelStatus()),
]),
Section::make('📢 Hotel Alert')
->description('Stuur een bericht naar alle online gebruikers')
->icon('heroicon-o-megaphone')
->schema([
Placeholder::make('alert_form')
->label('')
->content(fn (): HtmlString => $this->renderAlertForm()),
]),
Section::make('📜 Emulator Logs')
->description('Live emulator log viewer')
->icon('heroicon-o-document-text')
->columnSpanFull()
->schema([
Placeholder::make('emulator_logs')
->label('')
->content(fn () => view('filament.components.emulator-log-viewer')),
]),
Section::make('🖥️ Emulator Control')
->description('Volledige emulator controle')
->icon('heroicon-o-server')
->columns(3)
->afterHeader([
Action::make('start_emulator')
->label('Start')
->icon('heroicon-o-play')
->color('success')
->action('startEmulator'),
Action::make('stop_emulator')
->label('Stop')
->icon('heroicon-o-stop')
->color('danger')
->action('stopEmulator'),
Action::make('restart_emulator')
->label('Restart')
->icon('heroicon-o-arrow-path')
->color('warning')
->action('restartEmulator'),
Action::make('check_emulator')
->label('Check')
->icon('heroicon-o-check-circle')
->color('info')
->action('checkEmulator'),
])
->schema([
Placeholder::make('emulator_info')
->label('')
->content(fn (): HtmlString => $this->renderEmulatorInfo()),
]),
Section::make('🔄 Emulator Updates')
->description('Configureer en update de emulator')
->icon('heroicon-o-arrow-down-circle')
->afterHeader([
Action::make('check_updates')
->label('Check Updates')
->color('info')
->action('checkEmulatorUpdates'),
Action::make('build_emulator')
->label('🔨 Build')
->color('success')
->action('buildEmulator'),
Action::make('run_sql')
->label('SQL Updates')
->color('purple')
->action('runSqlUpdates'),
Action::make('save_emulator')
->label('Opslaan')
->color('primary')
->action('saveEmulator'),
])
->schema([
Placeholder::make('emulator_settings')
->label('')
->content(fn (): HtmlString => $this->renderEmulatorSettings()),
]),
Section::make('💾 Emulator Backups')
->description('Bekijk en herstel emulator backups')
->icon('heroicon-s-archive-box')
->schema([
Placeholder::make('backups_list')
->label('')
->content(fn (): HtmlString => $this->renderBackupsList()),
]),
Section::make('📦 Nitro Client')
->description('Configureer en update Nitro')
->icon('heroicon-o-cloud-arrow-down')
->afterHeader([
Action::make('detect_paths')
->label('🔍 Auto Detect')
->color('success')
->action('detectAndSavePaths'),
Action::make('check_nitro')
->label('Check')
->color('info')
->action('checkNitroUpdates'),
Action::make('build_nitro')
->label('Build')
->color('pink')
->action('buildNitro'),
Action::make('generate_configs')
->label('Genereer Configs')
->color('indigo')
->action('generateNitroConfigs'),
Action::make('save_nitro')
->label('Opslaan')
->color('primary')
->action('saveNitro'),
])
->schema([
Placeholder::make('nitro_settings')
->label('')
->content(fn (): HtmlString => $this->renderNitroSettings()),
]),
Section::make('⚙️ Automatische Updates')
->description('Configureer automatische updates')
->icon('heroicon-o-clock')
->columns(2)
->afterHeader([
Action::make('save_auto')
->label('Opslaan')
->color('primary')
->action('saveAutoUpdate'),
])
->schema([
Toggle::make('auto_update_enabled')
->label('Automatische Updates Inschakelen'),
TextInput::make('auto_update_schedule')
->label('Schema (HH:MM)'),
TextInput::make('auto_update_days')
->label('Dagen (0-6)'),
]),
Section::make('👔 Kleding Sync')
->description('Sync catalogus kleding uit FigureMap')
->icon('heroicon-o-user')
->afterHeader([
Action::make('sync_clothing')
->label('🔄 Sync')
->color('success')
->action('syncClothing'),
])
->schema([
Placeholder::make('clothing_status')
->label('')
->content(fn (): HtmlString => $this->renderClothingStatus()),
]),
Section::make('🔔 Meldingen')
->description('E-mail en Discord alerts')
->icon('heroicon-o-bell')
->columns(2)
->afterHeader([
Action::make('save_alerts')
->label('Opslaan')
->color('primary')
->action('saveAlerts'),
Action::make('test_discord')
->label('Test Discord')
->color('info')
->action('testDiscord'),
])
->schema([
Toggle::make('alert_email_enabled')
->label('E-mail Meldingen'),
TextInput::make('alert_email_address')
->label('E-mail Adres')
->email()
->columnSpanFull(),
Toggle::make('alert_discord_enabled')
->label('Discord Meldingen'),
TextInput::make('alert_discord_webhook_url')
->label('Webhook URL')
->columnSpanFull(),
Select::make('discord_webhook_ranks')
->label('Ranks die Discord notificatie krijgen')
->multiple()
->options(fn () => WebsitePermission::query()->pluck('permission', 'min_rank')->mapWithKeys(fn ($perm, $rank) => [$rank => "Rank {$rank} ({$perm})"])->toArray())
->helperText('Laat leeg voor alleen staff (min_staff_rank)'),
]),
Section::make('📊 Update Geschiedenis')
->description('Laatste systeem updates')
->icon('heroicon-o-clock')
->schema([
Placeholder::make('history')
->label('')
->content(fn (): HtmlString => $this->getUpdateHistoryHtml()),
]),
Section::make('🔐 Social Login (v1.4)')
->description('Enable social login providers')
->icon('heroicon-o-user-circle')
->schema([
Toggle::make('social_login_google_enabled')
->label('Google Login')
->helperText('Allow users to login with Google'),
TextInput::make('social_login_google_client_id')
->label('Google Client ID')
->helperText('From Google Cloud Console'),
TextInput::make('social_login_google_client_secret')
->label('Google Client Secret')
->type('password'),
Toggle::make('social_login_discord_enabled')
->label('Discord Login')
->helperText('Allow users to login with Discord'),
TextInput::make('social_login_discord_client_id')
->label('Discord Client ID')
->helperText('From Discord Developer Portal'),
TextInput::make('social_login_discord_client_secret')
->label('Discord Client Secret')
->type('password'),
Toggle::make('social_login_github_enabled')
->label('GitHub Login')
->helperText('Allow users to login with GitHub'),
TextInput::make('social_login_github_client_id')
->label('GitHub Client ID')
->helperText('From GitHub Developer Settings'),
TextInput::make('social_login_github_client_secret')
->label('GitHub Client Secret')
->type('password'),
])
->columns(2),
Section::make('👔 Staff Activity Log')
->description('Recent staff activities in the housekeeping (v1.2)')
->icon('heroicon-o-user-group')
->schema([
Placeholder::make('staff_activity')
->label('')
->content(fn (): HtmlString => $this->getStaffActivityHtml()),
]),
]);
}
private function getSetting(string $key, string $default = ''): string
{
try {
return app(SettingsService::class)->getOrDefault($key, $default);
} catch (Exception) {
return $default;
}
}
private function getSettingBool(string $key, bool $default = false): bool
{
try {
$value = app(SettingsService::class)->getOrDefault($key, $default ? '1' : '0');
return in_array($value, ['1', 'true', 'yes'], true);
} catch (Exception) {
return $default;
}
}
private function getCurrentSiteUrl(): string
{
try {
return config('app.url', 'https://epicnabbo.nl');
} catch (Exception) {
return 'https://epicnabbo.nl';
}
}
private function autoDetectPaths(): array
{
$autoDetect = AutoDetectService::getInstance();
$autoDetect->clearCache();
return [
'nitro_client_path' => $autoDetect->detectNitroClientPath(),
'nitro_renderer_path' => $autoDetect->detectNitroRendererPath(),
'nitro_build_path' => $autoDetect->detectNitroBuildPath(),
'nitro_webroot' => $autoDetect->detectNitroWebroot(),
'gamedata_path' => $autoDetect->detectGamedataPath(),
'emulator_jar_path' => $autoDetect->detectEmulatorJarPath(),
'emulator_source_path' => $autoDetect->detectEmulatorSourcePath(),
];
}
private function getCardHtml(string $label, string $value, string $color, string $icon): HtmlString
{
$iconSvg = match ($icon) {
'heroicon-o-users' => '
No staff activities recorded yet.
Staff actions will appear here automatically.
Error loading staff activities
Make sure to run: php artisan migrate