feat: Add course schedule model, migration, seeder, and Filament CRUD for managing schedules.
This commit is contained in:
parent
1c51ccd5b5
commit
7a9cb7fed9
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Pages\Information\CourseSchedule\Actions;
|
||||
|
||||
use App\Filament\Actions\Cheerful\CreateAction;
|
||||
use App\Models\CourseSchedule;
|
||||
use Filament\Support\Enums\Width;
|
||||
|
||||
class CreateScheduleAction extends CreateAction
|
||||
{
|
||||
public static function getDefaultName(): ?string
|
||||
{
|
||||
return 'createSchedule';
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->model(CourseSchedule::class)
|
||||
->label('Tambah')
|
||||
->modalHeading('Tambah Jadwal Kuliah')
|
||||
->modalSubmitActionLabel('Simpan')
|
||||
->modalCancelActionLabel('Batal')
|
||||
->extraModalFooterActions(fn (CreateAction $action): array => [
|
||||
$action->makeModalSubmitAction('createAnother', arguments: ['another' => true])
|
||||
->label('Simpan dan Tambah Lagi'),
|
||||
])
|
||||
->modalWidth(Width::Large)
|
||||
->schema(fn ($livewire) => $livewire->scheduleFormSchema());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Pages\Information\CourseSchedule\Actions;
|
||||
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Models\CourseSchedule;
|
||||
|
||||
class DeleteScheduleAction extends DeleteAction
|
||||
{
|
||||
public static function getDefaultName(): ?string
|
||||
{
|
||||
return 'deleteSchedule';
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->record(function (array $arguments): CourseSchedule {
|
||||
return CourseSchedule::findOrFail($arguments['schedule']);
|
||||
})
|
||||
->modalHeading('Hapus Jadwal Kuliah')
|
||||
->modalDescription('Apakah Anda yakin ingin menghapus jadwal ini? Tindakan ini tidak dapat dibatalkan.')
|
||||
->modalSubmitActionLabel('Hapus')
|
||||
->modalCancelActionLabel('Batal');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Pages\Information\CourseSchedule\Actions;
|
||||
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Models\CourseSchedule;
|
||||
use Filament\Support\Enums\Width;
|
||||
|
||||
class EditScheduleAction extends EditAction
|
||||
{
|
||||
public static function getDefaultName(): ?string
|
||||
{
|
||||
return 'editSchedule';
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->record(function (array $arguments): CourseSchedule {
|
||||
return CourseSchedule::findOrFail($arguments['schedule']);
|
||||
})
|
||||
->modalHeading('Ubah Jadwal Kuliah')
|
||||
->modalSubmitActionLabel('Simpan')
|
||||
->modalCancelActionLabel('Batal')
|
||||
->modalWidth(Width::Large)
|
||||
->schema(fn ($livewire) => $livewire->scheduleFormSchema());
|
||||
}
|
||||
}
|
||||
217
app/Filament/Pages/Information/CourseSchedule/Index.php
Normal file
217
app/Filament/Pages/Information/CourseSchedule/Index.php
Normal file
@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Pages\Information\CourseSchedule;
|
||||
|
||||
use App\Filament\Pages\Information\CourseSchedule\Actions\CreateScheduleAction;
|
||||
use App\Filament\Pages\Information\CourseSchedule\Actions\DeleteScheduleAction;
|
||||
use App\Filament\Pages\Information\CourseSchedule\Actions\EditScheduleAction;
|
||||
use App\Models\Course;
|
||||
use App\Models\CourseSchedule;
|
||||
use BackedEnum;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\Concerns\InteractsWithActions;
|
||||
use Filament\Actions\Contracts\HasActions;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\TimePicker;
|
||||
use Filament\Forms\Concerns\InteractsWithForms;
|
||||
use Filament\Forms\Contracts\HasForms;
|
||||
use Filament\Pages\Page;
|
||||
use Filament\Schemas\Components\Grid;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Illuminate\Support\Collection;
|
||||
use UnitEnum;
|
||||
|
||||
class Index extends Page implements HasActions, HasForms
|
||||
{
|
||||
use InteractsWithActions, InteractsWithForms;
|
||||
|
||||
protected static ?string $model = CourseSchedule::class;
|
||||
|
||||
protected static string|UnitEnum|null $navigationGroup = 'Informasi';
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedCalendarDays;
|
||||
|
||||
protected static ?string $title = 'Jadwal Kuliah';
|
||||
|
||||
protected static ?int $navigationSort = 1;
|
||||
|
||||
protected static ?string $recordTitleAttribute = 'day_of_week';
|
||||
|
||||
protected static ?string $slug = 'information/course-schedules';
|
||||
|
||||
protected string $view = 'filament.pages.information.list-course-schedules';
|
||||
|
||||
public ?int $course_semester = null;
|
||||
|
||||
public ?string $search = '';
|
||||
|
||||
public static function getPagePermission(): string
|
||||
{
|
||||
return 'View:CourseSchedule';
|
||||
}
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->course_semester = null;
|
||||
|
||||
$this->form->fill([
|
||||
'course_semester' => $this->course_semester,
|
||||
]);
|
||||
}
|
||||
|
||||
public function form(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->schema([
|
||||
Select::make('course_semester')
|
||||
->label('Semester')
|
||||
->options(array_combine(range(1, 8), array_map(fn ($i) => "Semester $i", range(1, 8))))
|
||||
->native(false)
|
||||
->live()
|
||||
->afterStateUpdated(fn ($state) => $this->course_semester = $state),
|
||||
|
||||
TextInput::make('search')
|
||||
->label('Cari')
|
||||
->placeholder('Cari Mata Kuliah atau Dosen...')
|
||||
->autocomplete(false)
|
||||
->live(debounce: 500)
|
||||
->afterStateUpdated(fn ($state) => $this->search = $state),
|
||||
])
|
||||
->columns([
|
||||
'sm' => 1,
|
||||
'md' => 3,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateScheduleAction::make(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function editScheduleAction(): Action
|
||||
{
|
||||
return EditScheduleAction::make();
|
||||
}
|
||||
|
||||
protected function deleteScheduleAction(): Action
|
||||
{
|
||||
return DeleteScheduleAction::make();
|
||||
}
|
||||
|
||||
public function getSchedules(): Collection
|
||||
{
|
||||
$user = auth()->user();
|
||||
$lecturer = $user->lecturer;
|
||||
|
||||
$query = CourseSchedule::with(['course.lecturer']);
|
||||
|
||||
if ($lecturer) {
|
||||
$query->whereHas('course', fn ($q) => $q->where('lecturer_id', $lecturer->id));
|
||||
}
|
||||
|
||||
if ($this->course_semester) {
|
||||
$query->whereHas('course', fn ($q) => $q->where('semester', $this->course_semester));
|
||||
}
|
||||
|
||||
if ($this->search) {
|
||||
$query->where(function ($q) {
|
||||
$q->whereHas('course', fn ($sq) => $sq->where('name', 'like', "%{$this->search}%"))
|
||||
->orWhereHas('course.lecturer', fn ($sq) => $sq->where('full_name', 'like', "%{$this->search}%"));
|
||||
});
|
||||
}
|
||||
|
||||
return $query->get()
|
||||
->sortBy([
|
||||
['day_of_week', 'asc'],
|
||||
['start_time', 'asc'],
|
||||
])
|
||||
->groupBy('day_of_week');
|
||||
}
|
||||
|
||||
protected function getViewData(): array
|
||||
{
|
||||
return [
|
||||
'schedules' => $this->getSchedules(),
|
||||
'days' => [
|
||||
1 => 'Senin',
|
||||
2 => 'Selasa',
|
||||
3 => 'Rabu',
|
||||
4 => 'Kamis',
|
||||
5 => 'Jumat',
|
||||
6 => 'Sabtu',
|
||||
7 => 'Minggu',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function scheduleFormSchema(): array
|
||||
{
|
||||
return [
|
||||
Grid::make(2)
|
||||
->schema([
|
||||
Select::make('course_id')
|
||||
->label('Mata Kuliah')
|
||||
->options(function () {
|
||||
$user = auth()->user();
|
||||
$lecturer = $user->lecturer;
|
||||
|
||||
if ($lecturer) {
|
||||
$courses = Course::getOptionsForLecturer($lecturer);
|
||||
} else {
|
||||
$courses = Course::all();
|
||||
}
|
||||
|
||||
return $courses
|
||||
->groupBy('semester')
|
||||
->mapWithKeys(function ($courses, $semester) {
|
||||
return [
|
||||
"Semester $semester" => $courses->pluck('name', 'id')->toArray(),
|
||||
];
|
||||
})
|
||||
->toArray();
|
||||
})
|
||||
->searchable()
|
||||
->live()
|
||||
->required()
|
||||
->columnSpanFull(),
|
||||
|
||||
Grid::make(3)
|
||||
->schema([
|
||||
Select::make('day_of_week')
|
||||
->label('Hari')
|
||||
->placeholder('Pilih Hari')
|
||||
->options([
|
||||
1 => 'Senin',
|
||||
2 => 'Selasa',
|
||||
3 => 'Rabu',
|
||||
4 => 'Kamis',
|
||||
5 => 'Jumat',
|
||||
6 => 'Sabtu',
|
||||
7 => 'Minggu',
|
||||
])
|
||||
->native(false)
|
||||
->required(),
|
||||
|
||||
TimePicker::make('start_time')
|
||||
->label('Jam Mulai')
|
||||
->placeholder('08:00')
|
||||
->required()
|
||||
->native(false)
|
||||
->seconds(false),
|
||||
|
||||
TimePicker::make('end_time')
|
||||
->label('Jam Selesai')
|
||||
->placeholder('10:00')
|
||||
->required()
|
||||
->native(false)
|
||||
->seconds(false),
|
||||
])
|
||||
->columnSpanFull(),
|
||||
]),
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@ -17,4 +18,11 @@ public function lecturer(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Lecturer::class);
|
||||
}
|
||||
|
||||
public static function getOptionsForLecturer(Lecturer $lecturer): Collection
|
||||
{
|
||||
return static::query()
|
||||
->where('lecturer_id', $lecturer->id)
|
||||
->get();
|
||||
}
|
||||
}
|
||||
|
||||
28
app/Models/CourseSchedule.php
Normal file
28
app/Models/CourseSchedule.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class CourseSchedule extends Model
|
||||
{
|
||||
use HasFactory, SoftDeletes;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'end_time' => 'datetime:H:i',
|
||||
'start_time' => 'datetime:H:i',
|
||||
];
|
||||
}
|
||||
|
||||
public function course(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Course::class);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('course_schedules', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('course_id')->constrained()->cascadeOnDelete();
|
||||
$table->integer('day_of_week');
|
||||
$table->time('start_time');
|
||||
$table->time('end_time');
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->index('course_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('course_schedules');
|
||||
}
|
||||
};
|
||||
34
database/seeders/CourseScheduleSeeder.php
Normal file
34
database/seeders/CourseScheduleSeeder.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Models\CourseSchedule;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class CourseScheduleSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$courses = Course::all();
|
||||
|
||||
$timeSlots = [
|
||||
['08:00:00', '10:00:00'],
|
||||
['10:00:00', '12:00:00'],
|
||||
['13:00:00', '15:00:00'],
|
||||
['15:00:00', '17:00:00'],
|
||||
];
|
||||
|
||||
foreach ($courses as $course) {
|
||||
|
||||
$slot = $timeSlots[array_rand($timeSlots)];
|
||||
|
||||
CourseSchedule::create([
|
||||
'course_id' => $course->id,
|
||||
'day_of_week' => rand(1, 6),
|
||||
'start_time' => $slot[0],
|
||||
'end_time' => $slot[1],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Models\Lecturer;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class CourseSeeder extends Seeder
|
||||
@ -83,6 +84,33 @@ public function run(): void
|
||||
['code' => 'FSI839', 'name' => 'Startup Digital', 'credit' => 2, 'semester' => 8],
|
||||
];
|
||||
|
||||
$lecturers = Lecturer::pluck('id')->toArray();
|
||||
|
||||
shuffle($lecturers);
|
||||
|
||||
$lecturerSemesterMap = [];
|
||||
|
||||
foreach ($courses as $i => &$course) {
|
||||
|
||||
$semester = $course['semester'];
|
||||
|
||||
if ($i < count($lecturers)) {
|
||||
$lecturerId = $lecturers[$i];
|
||||
} else {
|
||||
|
||||
do {
|
||||
$lecturerId = $lecturers[array_rand($lecturers)];
|
||||
} while (
|
||||
isset($lecturerSemesterMap[$lecturerId]) &&
|
||||
in_array($semester, $lecturerSemesterMap[$lecturerId])
|
||||
);
|
||||
}
|
||||
|
||||
$course['lecturer_id'] = $lecturerId;
|
||||
|
||||
$lecturerSemesterMap[$lecturerId][] = $semester;
|
||||
}
|
||||
|
||||
Course::insert($courses);
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ public function run(): void
|
||||
UserSeeder::class,
|
||||
LecturerSeeder::class,
|
||||
CourseSeeder::class,
|
||||
CourseScheduleSeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,140 @@
|
||||
<x-filament-panels::page>
|
||||
<x-filament::section>
|
||||
<div
|
||||
class="fi-section-content rounded-xl border border-info-200 bg-info-50 dark:bg-info-500/10 dark:border-info-500/30 p-4 mb-6">
|
||||
<div class="flex items-start gap-3">
|
||||
<x-heroicon-o-information-circle class="w-5 h-5 text-info-600 dark:text-info-400 mt-0.5" />
|
||||
|
||||
<div class="text-sm text-info-800 dark:text-info-200">
|
||||
Geser ke samping untuk melihat hari lainnya.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between gap-4 mb-6">
|
||||
<div class="w-full">
|
||||
{{ $this->form }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if ($schedules->isNotEmpty())
|
||||
<div class="overflow-x-auto">
|
||||
<div class="flex flex-nowrap gap-6 min-w-max pb-4">
|
||||
|
||||
@foreach ($days as $dayNumber => $dayName)
|
||||
@php
|
||||
$daySchedules = $schedules->get($dayNumber);
|
||||
@endphp
|
||||
|
||||
@if ($daySchedules && $daySchedules->count() > 0)
|
||||
<section class="w-80 shrink-0 space-y-4">
|
||||
|
||||
<div class="flex items-center gap-2 border-b border-gray-200 dark:border-gray-700 pb-2">
|
||||
<x-heroicon-o-calendar class="w-5 h-5 text-primary-500" />
|
||||
<h2 class="text-lg font-semibold tracking-tight text-gray-950 dark:text-white">
|
||||
{{ $dayName }}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
@foreach ($daySchedules as $schedule)
|
||||
<div
|
||||
class="fi-card rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 shadow-sm hover:shadow-md transition">
|
||||
|
||||
<div class="p-5 space-y-4">
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<div class="flex items-center gap-2">
|
||||
<span
|
||||
class="inline-flex items-center rounded-md bg-primary-50 dark:bg-primary-500/10 px-2 py-1 text-xs font-semibold text-primary-700 dark:text-primary-300 ring-1 ring-inset ring-primary-600/20">
|
||||
{{ $schedule->course->code ?? 'MATKUL' }}
|
||||
</span>
|
||||
|
||||
@if ($schedule->mode)
|
||||
@php
|
||||
$color = $schedule->mode->getColor();
|
||||
@endphp
|
||||
<span
|
||||
class="inline-flex items-center rounded-md bg-{{ $color }}-50 dark:bg-{{ $color }}-500/10 px-2 py-1 text-xs font-semibold text-{{ $color }}-700 dark:text-{{ $color }}-300 ring-1 ring-inset ring-{{ $color }}-600/20">
|
||||
{{ $schedule->mode->getLabel() }}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if ($schedule->room)
|
||||
<span
|
||||
class="inline-flex items-center text-xs text-gray-500 dark:text-gray-400">
|
||||
<x-heroicon-m-map-pin class="w-4 h-4 mr-1 opacity-70" />
|
||||
{{ $schedule->room }}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<h3
|
||||
class="text-base font-semibold leading-tight text-gray-950 dark:text-white">
|
||||
{{ $schedule->course->name ?? 'Mata Kuliah Tidak Diketahui' }}
|
||||
</h3>
|
||||
<div class="flex items-center text-sm text-gray-600 dark:text-gray-400">
|
||||
<x-heroicon-m-user class="w-4 h-4 mr-1.5 opacity-70" />
|
||||
<span class="truncate">
|
||||
{{ $schedule->course->lecturer->full_name ?? 'Dosen Belum Ditentukan' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-2 mt-1">
|
||||
@if ($schedule->course?->semester)
|
||||
<span
|
||||
class="inline-flex items-center gap-1 rounded-md bg-amber-50 dark:bg-amber-500/10 px-2 py-1 text-xs font-medium text-amber-700 dark:text-amber-300 ring-1 ring-inset ring-amber-600/20">
|
||||
<x-heroicon-m-academic-cap class="w-3 h-3" />
|
||||
Semester {{ $schedule->course->semester }}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex items-center justify-between pt-3 border-t border-gray-100 dark:border-gray-800 text-sm">
|
||||
<div
|
||||
class="flex items-center font-medium text-gray-800 dark:text-gray-200">
|
||||
<x-heroicon-o-clock class="w-4 h-4 mr-1.5 text-primary-500" />
|
||||
{{ $schedule->start_time->format('H:i') }}
|
||||
<span class="mx-1">–</span>
|
||||
{{ $schedule->end_time->format('H:i') }}
|
||||
</div>
|
||||
|
||||
<span
|
||||
class="text-[11px] font-semibold tracking-wide text-gray-400 uppercase">
|
||||
{{ $schedule->course->credit ?? '-' }} SKS
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex items-center justify-end gap-1 pt-3 border-t border-gray-100 dark:border-gray-800">
|
||||
<x-filament::button size="xs" color="warning" tooltip="Ubah"
|
||||
variant="primary"
|
||||
wire:click="mountAction('editSchedule', { schedule: {{ $schedule->id }} })">
|
||||
<x-heroicon-m-pencil-square class="w-4 h-4" />
|
||||
</x-filament::button>
|
||||
|
||||
<x-filament::button size="xs" color="danger" tooltip="Hapus"
|
||||
wire:click="mountAction('deleteSchedule', { schedule: {{ $schedule->id }} })">
|
||||
<x-heroicon-m-trash class="w-4 h-4" />
|
||||
</x-filament::button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</section>
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($schedules->isEmpty())
|
||||
<x-filament::empty-state icon="heroicon-o-calendar-days" heading="Tidak ada data yang ditemukan"
|
||||
description="Setelah Anda membuat data pertama, maka akan muncul disini." iconColor="gray">
|
||||
</x-filament::empty-state>
|
||||
@endif
|
||||
</x-filament::section>
|
||||
</x-filament-panels::page>
|
||||
Loading…
Reference in New Issue
Block a user