227 lines
7.8 KiB
PHP
227 lines
7.8 KiB
PHP
<?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\Filament\Support\SystemNotification;
|
||
use App\Models\Course;
|
||
use App\Models\CourseSchedule;
|
||
use App\Settings\GeneralSettings;
|
||
use BackedEnum;
|
||
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
|
||
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 Illuminate\Support\Collection;
|
||
use Livewire\Attributes\Computed;
|
||
use UnitEnum;
|
||
|
||
class Index extends Page implements HasActions, HasForms
|
||
{
|
||
use HasPageShield, InteractsWithActions, InteractsWithForms;
|
||
|
||
protected static ?string $model = CourseSchedule::class;
|
||
|
||
protected static string|UnitEnum|null $navigationGroup = 'Informasi';
|
||
|
||
protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-calendar-days';
|
||
|
||
protected static ?string $title = 'Jadwal Kuliah';
|
||
|
||
protected static ?int $navigationSort = 5;
|
||
|
||
protected static ?string $slug = 'information/course-schedules';
|
||
|
||
protected string $view = 'filament.pages.information.course-schedule.index';
|
||
|
||
#[Computed]
|
||
public function instructions(): string
|
||
{
|
||
return SystemNotification::getByKey('labels.course_schedule_hint');
|
||
}
|
||
|
||
#[Computed]
|
||
public function emptyHeading(): string
|
||
{
|
||
return SystemNotification::getByKey('labels.empty_course_schedule.title');
|
||
}
|
||
|
||
#[Computed]
|
||
public function emptyDescription(): string
|
||
{
|
||
return SystemNotification::getByKey('labels.empty_course_schedule.description');
|
||
}
|
||
|
||
public ?string $search = '';
|
||
|
||
public static function getPagePermission(): string
|
||
{
|
||
return 'View:CourseSchedule';
|
||
}
|
||
|
||
public function mount(): void
|
||
{
|
||
$this->form->fill();
|
||
}
|
||
|
||
public function form(Schema $schema): Schema
|
||
{
|
||
return $schema
|
||
->schema([
|
||
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,
|
||
]);
|
||
}
|
||
|
||
protected function getHeaderActions(): array
|
||
{
|
||
return [
|
||
CreateScheduleAction::make()
|
||
->visible(fn () => auth()->user()->can('Create:CourseSchedule')),
|
||
];
|
||
}
|
||
|
||
public function editScheduleAction(): Action
|
||
{
|
||
return EditScheduleAction::make()
|
||
->visible(fn () => auth()->user()->can('Update:CourseSchedule'));
|
||
}
|
||
|
||
public function deleteScheduleAction(): Action
|
||
{
|
||
return DeleteScheduleAction::make()
|
||
->visible(fn () => auth()->user()->can('Delete:CourseSchedule'));
|
||
}
|
||
|
||
public function getSchedules(): Collection
|
||
{
|
||
$query = CourseSchedule::with(['course']);
|
||
|
||
$query->whereHas('course', fn ($q) => $q->where('semester', app(GeneralSettings::class)->current_semester));
|
||
|
||
if ($this->search) {
|
||
$query->where(function ($q) {
|
||
$q->whereHas('course', fn ($sq) => $sq->where('name', 'like', "%{$this->search}%")
|
||
->orWhere('lecturer', 'like', "%{$this->search}%"));
|
||
});
|
||
}
|
||
|
||
return $query->get()
|
||
->sortBy([
|
||
['day_of_week', 'asc'],
|
||
['start_time', 'asc'],
|
||
])
|
||
->groupBy('day_of_week')
|
||
->map(function ($daySchedules) {
|
||
return $daySchedules->map(fn ($schedule) => (object) [
|
||
'id' => $schedule->id,
|
||
'course_code' => $schedule->course->code ?? 'MATKUL',
|
||
'course_name' => $schedule->course->name ?? 'Mata Kuliah Tidak Diketahui',
|
||
'lecturer' => $schedule->course->lecturer ?? 'Dosen Belum Ditentukan',
|
||
'semester' => $schedule->course->semester,
|
||
'credit' => $schedule->course->credit ?? '-',
|
||
'room' => $schedule->room,
|
||
'mode_label' => $schedule->mode?->getLabel(),
|
||
'mode_color' => $schedule->mode?->getColor(),
|
||
'time_range' => $schedule->start_time->format('H:i').' – '.$schedule->end_time->format('H:i'),
|
||
]);
|
||
});
|
||
}
|
||
|
||
#[Computed]
|
||
public function schedulesGrouped(): Collection
|
||
{
|
||
$days = [
|
||
1 => 'Senin',
|
||
2 => 'Selasa',
|
||
3 => 'Rabu',
|
||
4 => 'Kamis',
|
||
5 => 'Jumat',
|
||
6 => 'Sabtu',
|
||
7 => 'Minggu',
|
||
];
|
||
|
||
return $this->getSchedules()->mapWithKeys(function ($schedules, $day) use ($days) {
|
||
return [$days[$day] ?? 'Lainnya' => $schedules];
|
||
});
|
||
}
|
||
|
||
public function scheduleFormSchema(): array
|
||
{
|
||
return [
|
||
Grid::make(2)
|
||
->schema([
|
||
Select::make('course_id')
|
||
->label('Mata Kuliah')
|
||
->options(function ($record) {
|
||
return Course::query()
|
||
->where('semester', app(GeneralSettings::class)->current_semester)
|
||
->where(function ($query) use ($record) {
|
||
$query->whereDoesntHave('courseSchedules');
|
||
|
||
if ($record && $record->course_id) {
|
||
$query->orWhere('id', $record->course_id);
|
||
}
|
||
})
|
||
->pluck('name', 'id')
|
||
->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(),
|
||
]),
|
||
];
|
||
}
|
||
}
|