Add DatabaseSeeder and enhance settings management: Created DatabaseSeeder to seed initial data, including a test user. Updated ListSettings page to support group filtering and added new settings groups in localization files. Enhanced SettingForm and SettingsTable to accommodate new group options and improved UI for settings management.

This commit is contained in:
Ümit Tunç
2025-10-29 16:58:05 -03:00
parent 1791108b1e
commit 3669e17119
9 changed files with 1350 additions and 64 deletions
@@ -0,0 +1,29 @@
<?php
namespace Database\Seeders;
use App\Models\User;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
// Settings seed
$this->call([
SettingSeeder::class,
]);
// User::factory(10)->create();
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
]);
}
}
@@ -3,18 +3,37 @@
namespace App\Filament\Admin\Resources\Settings\Pages;
use App\Filament\Admin\Resources\Settings\SettingResource;
use App\Filament\Admin\Resources\Settings\Tables\SettingsTable;
use Filament\Actions\CreateAction;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Resources\Pages\ListRecords;
use Filament\Support\Icons\Heroicon;
use Illuminate\Contracts\Support\Htmlable;
class ListSettings extends ListRecords
class ListSettings extends ListRecords implements HasForms
{
use InteractsWithForms;
protected static string $resource = SettingResource::class;
public ?string $activeGroup = null;
public function getView(): string
{
return 'filament.admin.resources.settings.pages.list-settings';
}
public function getTitle(): string
{
return __('settings.title');
}
public function getHeading(): string | Htmlable
{
return __('settings.title');
}
protected function getHeaderActions(): array
{
return [
@@ -22,4 +41,78 @@ class ListSettings extends ListRecords
->label(__('settings.create')),
];
}
public function mount(): void
{
parent::mount();
// Query string'den activeGroup' 별 al, yoksa tüm ayarları göster (null)
$this->activeGroup = request()->query('group', null);
}
public function getGroups(): \Illuminate\Support\Collection
{
return \App\Models\Setting::whereNull('deleted_at')
->select('group')
->distinct()
->orderBy('group')
->pluck('group')
->mapWithKeys(function ($group) {
return [$group => __("settings.group_{$group}")];
});
}
public function setActiveGroup(?string $group): void
{
$this->activeGroup = $group;
}
protected function getTableQuery(): \Illuminate\Database\Eloquent\Builder
{
$query = parent::getTableQuery();
// Eğer bir grup seçildiyse filtrele
if ($this->activeGroup) {
$query->where('group', $this->activeGroup);
}
return $query;
}
protected function getGroupIcon(?string $group): string
{
if (!$group) {
return 'heroicon-o-squares-2x2';
}
return match($group) {
'general' => 'heroicon-o-cog-6-tooth',
'theme' => 'heroicon-o-paint-brush',
'localization' => 'heroicon-o-language',
'email' => 'heroicon-o-envelope',
'seo' => 'heroicon-o-magnifying-glass',
'social' => 'heroicon-o-share',
'security' => 'heroicon-o-shield-check',
'upload' => 'heroicon-o-cloud-arrow-up',
'payment' => 'heroicon-o-credit-card',
'notification' => 'heroicon-o-bell',
'cache' => 'heroicon-o-arrow-path',
'api' => 'heroicon-o-code-bracket',
'logging' => 'heroicon-o-document-text',
'performance' => 'heroicon-o-bolt',
'integration' => 'heroicon-o-puzzle-piece',
default => 'heroicon-o-squares-2x2',
};
}
protected function getGroupCount(?string $group): int
{
if (!$group) {
return \App\Models\Setting::whereNull('deleted_at')->count();
}
return \App\Models\Setting::where('group', $group)
->whereNull('deleted_at')
->count();
}
}
@@ -92,12 +92,20 @@ class SettingForm
->required()
->options([
'general' => __('settings.group_general'),
'theme' => __('settings.group_theme'),
'localization' => __('settings.group_localization'),
'email' => __('settings.group_email'),
'seo' => __('settings.group_seo'),
'social' => __('settings.group_social'),
'security' => __('settings.group_security'),
'upload' => __('settings.group_upload'),
'payment' => __('settings.group_payment'),
'notification' => __('settings.group_notification'),
'cache' => __('settings.group_cache'),
'api' => __('settings.group_api'),
'logging' => __('settings.group_logging'),
'performance' => __('settings.group_performance'),
'integration' => __('settings.group_integration'),
'other' => __('settings.group_other'),
])
->default('general'),
@@ -88,19 +88,6 @@ class SettingsTable
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
SelectFilter::make('group')
->label(__('settings.filter_group'))
->options([
'general' => __('settings.group_general'),
'email' => __('settings.group_email'),
'seo' => __('settings.group_seo'),
'social' => __('settings.group_social'),
'security' => __('settings.group_security'),
'payment' => __('settings.group_payment'),
'notification' => __('settings.group_notification'),
'other' => __('settings.group_other'),
]),
SelectFilter::make('type')
->label(__('settings.filter_type'))
->options([
+5
View File
@@ -13,6 +13,11 @@ class DatabaseSeeder extends Seeder
*/
public function run(): void
{
// Settings seed
$this->call([
SettingSeeder::class,
]);
// User::factory(10)->create();
User::factory()->create([
File diff suppressed because it is too large Load Diff
+13
View File
@@ -75,12 +75,20 @@ return [
// Groups
'group_general' => 'General',
'group_theme' => 'Theme',
'group_localization' => 'Localization',
'group_email' => 'Email',
'group_seo' => 'SEO',
'group_social' => 'Social Media',
'group_security' => 'Security',
'group_upload' => 'Upload',
'group_payment' => 'Payment',
'group_notification' => 'Notification',
'group_cache' => 'Cache',
'group_api' => 'API',
'group_logging' => 'Logging',
'group_performance' => 'Performance',
'group_integration' => 'Integration',
'group_other' => 'Other',
// Validation messages
@@ -121,5 +129,10 @@ return [
'filter_type' => 'By Type',
'filter_active' => 'Active',
'filter_public' => 'Public',
// Tabs
'tabs_title' => 'Setting Groups',
'settings_count' => 'settings',
'all_settings' => 'All Settings',
];
+13
View File
@@ -75,12 +75,20 @@ return [
// Groups
'group_general' => 'Genel',
'group_theme' => 'Tema',
'group_localization' => 'Lokalizasyon',
'group_email' => 'E-posta',
'group_seo' => 'SEO',
'group_social' => 'Sosyal Medya',
'group_security' => 'Güvenlik',
'group_upload' => 'Dosya Yükleme',
'group_payment' => 'Ödeme',
'group_notification' => 'Bildirim',
'group_cache' => 'Cache',
'group_api' => 'API',
'group_logging' => 'Logging',
'group_performance' => 'Performans',
'group_integration' => 'Entegrasyon',
'group_other' => 'Diğer',
// Validation messages
@@ -121,5 +129,10 @@ return [
'filter_type' => 'Tipe Göre',
'filter_active' => 'Aktif',
'filter_public' => 'Herkese Açık',
// Tabs
'tabs_title' => 'Ayar Grupları',
'settings_count' => 'ayar',
'all_settings' => 'Tüm Ayarlar',
];
@@ -0,0 +1,122 @@
<!-- CUSTOM SETTINGS VIEW LOADED -->
<x-filament-panels::page>
<div class="grid grid-cols-12 gap-6">
<!-- Left Sidebar - Vertical Tabs -->
<div class="col-span-12 lg:col-span-3">
<div class="fi-section rounded-xl bg-white dark:bg-gray-800 shadow-sm ring-1 ring-gray-950/5 dark:ring-white/10">
<div class="p-4">
<h3 class="text-sm font-semibold text-gray-950 dark:text-white mb-4">
{{ __('settings.tabs_title') }}
</h3>
<nav class="space-y-1" aria-label="Settings Groups">
<!-- Tüm Ayarlar -->
<a
href="{{ request()->url() }}"
wire:navigate
@class([
'group flex items-center gap-3 px-3 py-2.5 rounded-lg w-full text-left transition-all',
'bg-primary-50 dark:bg-primary-900/20 text-primary-600 dark:text-primary-400 font-medium ring-1 ring-primary-500/20' => $activeGroup === null,
'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700/50' => $activeGroup !== null,
])
>
<x-filament::icon
:icon="$this->getGroupIcon(null)"
@class([
'h-5 w-5 transition-colors shrink-0',
'text-primary-600 dark:text-primary-400' => $activeGroup === null,
'text-gray-400 dark:text-gray-500 group-hover:text-gray-600' => $activeGroup !== null,
])
/>
<span class="flex-1 text-sm font-medium">{{ __('settings.all_settings') }}</span>
<span @class([
'px-2 py-0.5 text-xs rounded-full font-medium min-w-[1.5rem] text-center',
'bg-primary-100 dark:bg-primary-800 text-primary-700 dark:text-primary-300' => $activeGroup === null,
'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400' => $activeGroup !== null,
])>
{{ $this->getGroupCount(null) }}
</span>
</a>
<!-- Divider -->
<div class="my-2 border-t border-gray-200 dark:border-gray-700"></div>
<!-- Gruplar -->
@foreach($this->getGroups() as $groupKey => $groupLabel)
<a
href="{{ request()->url() }}?group={{ $groupKey }}"
wire:navigate
@class([
'group flex items-center gap-3 px-3 py-2.5 rounded-lg w-full text-left transition-all',
'bg-primary-50 dark:bg-primary-900/20 text-primary-600 dark:text-primary-400 font-medium ring-1 ring-primary-500/20' => $activeGroup === $groupKey,
'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700/50' => $activeGroup !== $groupKey,
])
>
<x-filament::icon
:icon="$this->getGroupIcon($groupKey)"
@class([
'h-5 w-5 transition-colors shrink-0',
'text-primary-600 dark:text-primary-400' => $activeGroup === $groupKey,
'text-gray-400 dark:text-gray-500 group-hover:text-gray-600' => $activeGroup !== $groupKey,
])
/>
<span class="flex-1 text-sm font-medium">{{ $groupLabel }}</span>
<span @class([
'px-2 py-0.5 text-xs rounded-full font-medium min-w-[1.5rem] text-center',
'bg-primary-100 dark:bg-primary-800 text-primary-700 dark:text-primary-300' => $activeGroup === $groupKey,
'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400' => $activeGroup !== $groupKey,
])>
{{ $this->getGroupCount($groupKey) }}
</span>
</a>
@endforeach
</nav>
</div>
</div>
</div>
<!-- Right Content Area - Settings Table -->
<div class="col-span-12 lg:col-span-9">
<!-- Active Group Header -->
@if($activeGroup)
<div class="mb-4 flex items-center gap-3">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary-50 dark:bg-primary-900/20">
<x-filament::icon
:icon="$this->getGroupIcon($activeGroup)"
class="h-5 w-5 text-primary-600 dark:text-primary-400"
/>
</div>
<div>
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">
{{ $this->getGroups()->get($activeGroup) }}
</h2>
<p class="text-sm text-gray-600 dark:text-gray-400">
{{ $this->getGroupCount($activeGroup) }} {{ __('settings.settings_count') }}
</p>
</div>
</div>
@else
<div class="mb-4 flex items-center gap-3">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary-50 dark:bg-primary-900/20">
<x-filament::icon
:icon="$this->getGroupIcon(null)"
class="h-5 w-5 text-primary-600 dark:text-primary-400"
/>
</div>
<div>
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">
{{ __('settings.all_settings') }}
</h2>
<p class="text-sm text-gray-600 dark:text-gray-400">
{{ $this->getGroupCount(null) }} {{ __('settings.settings_count') }}
</p>
</div>
</div>
@endif
<!-- Table -->
{{ $this->table }}
</div>
</div>
</x-filament-panels::page>