refactor: update class session management by introducing dedicated actions for viewing assignments, attendance, and materials, enhancing modularity and user interaction
This commit is contained in:
parent
66c07556b7
commit
b7e8f64d8b
@ -13,6 +13,7 @@ protected function setUp(): void
|
||||
|
||||
$this->successNotification(
|
||||
SystemNotification::update()
|
||||
);
|
||||
)
|
||||
->color('warning');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Actions;
|
||||
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Support\Enums\Width;
|
||||
|
||||
class GoToDateAction extends Action
|
||||
{
|
||||
public static function getDefaultName(): ?string
|
||||
{
|
||||
return 'goToDate';
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->label('Lompat ke Tanggal')
|
||||
->icon('heroicon-o-calendar-days')
|
||||
->schema([
|
||||
DatePicker::make('date')
|
||||
->label('Pilih Tanggal')
|
||||
->placeholder(fn () => now()->addMonth(10)->format('l, d F Y'))
|
||||
->required()
|
||||
->native(false)
|
||||
->displayFormat('l, d F Y'),
|
||||
])
|
||||
->action(function (array $data, $livewire) {
|
||||
$livewire->setOption('date', $data['date']);
|
||||
})
|
||||
->modalWidth(Width::Large);
|
||||
}
|
||||
}
|
||||
@ -29,7 +29,7 @@ public function getHeading(): string|Htmlable
|
||||
return '';
|
||||
}
|
||||
|
||||
public function form(Schema $schema): Schema
|
||||
public function schema(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Models\CourseSchedule;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
|
||||
class DeleteScheduleAction extends DeleteAction
|
||||
{
|
||||
@ -21,9 +20,9 @@ protected function setUp(): void
|
||||
return CourseSchedule::findOrFail($arguments['schedule']);
|
||||
})
|
||||
->label('Hapus')
|
||||
->icon(Heroicon::OutlinedTrash)
|
||||
->icon('heroicon-o-trash')
|
||||
->color('danger')
|
||||
->iconButton()
|
||||
->link()
|
||||
->tooltip('Hapus')
|
||||
->modalHeading('Hapus Jadwal Kuliah')
|
||||
->modalDescription('Apakah Anda yakin ingin menghapus jadwal ini? Tindakan ini tidak dapat dibatalkan.')
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Models\CourseSchedule;
|
||||
use Filament\Support\Enums\Width;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
|
||||
class EditScheduleAction extends EditAction
|
||||
{
|
||||
@ -20,8 +19,9 @@ protected function setUp(): void
|
||||
|
||||
$this
|
||||
->label('Ubah')
|
||||
->icon(Heroicon::OutlinedPencilSquare)
|
||||
->iconButton()
|
||||
->color('warning')
|
||||
->icon('heroicon-o-pencil-square')
|
||||
->link()
|
||||
->tooltip('Ubah')
|
||||
->record(function (array $arguments): CourseSchedule {
|
||||
return CourseSchedule::findOrFail($arguments['schedule']);
|
||||
|
||||
@ -58,7 +58,7 @@ public function mount(): void
|
||||
$this->form->fill();
|
||||
}
|
||||
|
||||
public function form(Schema $schema): Schema
|
||||
public function schema(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->schema([
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Models\StudyGroup;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
|
||||
class DeleteStudyGroupAction extends DeleteAction
|
||||
{
|
||||
@ -19,9 +18,9 @@ protected function setUp(): void
|
||||
|
||||
$this->record(fn (array $arguments): StudyGroup => StudyGroup::findOrFail($arguments['studyGroup']))
|
||||
->label('Hapus')
|
||||
->icon(Heroicon::OutlinedTrash)
|
||||
->icon('heroicon-o-trash')
|
||||
->color('danger')
|
||||
->iconButton()
|
||||
->link()
|
||||
->tooltip('Hapus')
|
||||
->modalHeading(fn (StudyGroup $record) => "Hapus {$record->name}")
|
||||
->modalDescription('Apakah Anda yakin ingin menghapus kelompok ini? Tindakan ini tidak dapat dibatalkan.')
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Models\StudyGroup;
|
||||
use Filament\Support\Enums\Width;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
|
||||
class EditStudyGroupAction extends EditAction
|
||||
{
|
||||
@ -20,8 +19,9 @@ protected function setUp(): void
|
||||
|
||||
$this
|
||||
->label('Ubah')
|
||||
->icon(Heroicon::OutlinedPencilSquare)
|
||||
->iconButton()
|
||||
->color('warning')
|
||||
->icon('heroicon-o-pencil-square')
|
||||
->link()
|
||||
->tooltip('Ubah')
|
||||
->record(fn (array $arguments): StudyGroup => StudyGroup::findOrFail($arguments['studyGroup']))
|
||||
->modalHeading(fn (StudyGroup $record) => "Ubah {$record->name}")
|
||||
|
||||
@ -61,7 +61,7 @@ public function mount(): void
|
||||
]);
|
||||
}
|
||||
|
||||
public function form(Schema $schema): Schema
|
||||
public function schema(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->schema([
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
class Profile extends EditProfile
|
||||
{
|
||||
public function form(Schema $schema): Schema
|
||||
public function schema(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
|
||||
@ -40,7 +40,7 @@ public static function getPagePermission(): string
|
||||
|
||||
protected static string $settings = GeneralSettings::class;
|
||||
|
||||
public function form(Schema $schema): Schema
|
||||
public function schema(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
|
||||
@ -18,15 +18,14 @@ protected function setUp(): void
|
||||
|
||||
$this
|
||||
->label('Hapus')
|
||||
->icon('heroicon-o-trash')
|
||||
->link()
|
||||
->modalHeading(fn (Assignment $record) => "Hapus {$record->title}")
|
||||
->record(fn (array $arguments) => Assignment::find($arguments['record']))
|
||||
->after(function ($livewire) {
|
||||
unset($livewire->assignments);
|
||||
})
|
||||
->icon('heroicon-m-trash')
|
||||
->color('danger')
|
||||
->tooltip('Hapus')
|
||||
->size('sm')
|
||||
->iconButton();
|
||||
->tooltip('Hapus');
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,15 +23,15 @@ protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->icon('heroicon-m-pencil-square')
|
||||
$this->label('Ubah')
|
||||
->color('warning')
|
||||
->icon('heroicon-o-pencil-square')
|
||||
->link()
|
||||
->tooltip('Ubah')
|
||||
->size('sm')
|
||||
->iconButton()
|
||||
->record(fn (array $arguments) => Assignment::find($arguments['record']))
|
||||
->modalHeading(fn (Assignment $record) => "Ubah {$record->title}")
|
||||
->modalWidth(Width::FourExtraLarge)
|
||||
->schema(fn (Schema $schema) => AssignmentForm::configure($schema)->getComponents())
|
||||
->form(AssignmentForm::configure(new Schema)->getComponents())
|
||||
->fillForm(function (Assignment $record): array {
|
||||
$data = $record->toArray();
|
||||
|
||||
|
||||
@ -17,14 +17,18 @@ protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->icon(fn (array $arguments, $livewire) => in_array($arguments['record'], $livewire->pinnedIds) ? 'heroicon-s-bookmark' : 'heroicon-o-bookmark')
|
||||
$this->label(fn (array $arguments, $livewire) => in_array($arguments['record'], $livewire->pinnedIds) ? 'Lepas Pin' : 'Pin Tugas')
|
||||
->color(fn (array $arguments, $livewire) => in_array($arguments['record'], $livewire->pinnedIds) ? 'primary' : 'gray')
|
||||
->icon(fn (array $arguments, $livewire) => in_array($arguments['record'], $livewire->pinnedIds) ? 'heroicon-s-bookmark' : 'heroicon-o-bookmark')
|
||||
->link()
|
||||
->tooltip(fn (array $arguments, $livewire) => in_array($arguments['record'], $livewire->pinnedIds) ? 'Lepas pin' : 'Pin tugas ini')
|
||||
->size('sm')
|
||||
->iconButton()
|
||||
->action(function (array $arguments, $livewire) {
|
||||
$assignmentId = $arguments['record'];
|
||||
$studentProfile = auth()->user()->student;
|
||||
$studentProfile = auth()->user()?->student;
|
||||
|
||||
if (! $studentProfile) {
|
||||
return;
|
||||
}
|
||||
|
||||
$existing = AssignmentPin::where('student_id', $studentProfile->id)
|
||||
->where('assignment_id', $assignmentId)
|
||||
|
||||
@ -19,8 +19,9 @@ protected function setUp(): void
|
||||
parent::setUp();
|
||||
|
||||
$this->label('Kumpulkan')
|
||||
->icon('heroicon-o-arrow-up-tray')
|
||||
->color('primary')
|
||||
->color('success')
|
||||
->icon('heroicon-o-paper-airplane')
|
||||
->link()
|
||||
->url(fn (Assignment $record) => AssignmentResource::getUrl('submit', ['record' => $record->id]))
|
||||
->visible(function (Assignment $record) {
|
||||
if (now()->isAfter($record->due_date)) {
|
||||
|
||||
@ -19,11 +19,11 @@ class AttendanceResource extends Resource
|
||||
|
||||
protected static ?string $navigationLabel = 'Presensi';
|
||||
|
||||
protected static ?int $navigationSort = 3;
|
||||
protected static ?int $navigationSort = 20;
|
||||
|
||||
protected static ?string $modelLabel = 'Presensi';
|
||||
protected static ?string $recordTitleAttribute = 'date';
|
||||
|
||||
protected static ?string $pluralModelLabel = 'Presensi';
|
||||
protected static ?string $slug = 'learning/attendances';
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Learning\ClassSessions\Actions;
|
||||
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Models\ClassSession;
|
||||
|
||||
class DeleteSessionAction extends DeleteAction
|
||||
{
|
||||
public static function getDefaultName(): ?string
|
||||
{
|
||||
return 'deleteSession';
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->label('Hapus')
|
||||
->icon('heroicon-o-trash')
|
||||
->link()
|
||||
->record(fn (array $arguments) => ClassSession::find($arguments['session'], ['*']))
|
||||
->color('danger');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Learning\ClassSessions\Actions;
|
||||
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Models\ClassSession;
|
||||
use Filament\Support\Enums\Width;
|
||||
|
||||
class EditSessionAction extends EditAction
|
||||
{
|
||||
public static function getDefaultName(): ?string
|
||||
{
|
||||
return 'editSession';
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->label('Ubah')
|
||||
->color('warning')
|
||||
->icon('heroicon-o-pencil')
|
||||
->link()
|
||||
->record(fn (array $arguments) => ClassSession::find($arguments['session'], ['*']))
|
||||
->schema(fn ($livewire) => $livewire->schema())
|
||||
->modalWidth(Width::TwoExtraLarge);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Learning\ClassSessions\Actions;
|
||||
|
||||
use App\Filament\Support\SystemNotification;
|
||||
use App\Models\ClassSession;
|
||||
use Carbon\Carbon;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
|
||||
class GenerateSessionsAction extends Action
|
||||
{
|
||||
public static function getDefaultName(): ?string
|
||||
{
|
||||
return 'generateSessions';
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->label('Generate Sesi')
|
||||
->color('warning')
|
||||
->requiresConfirmation()
|
||||
->modalHeading('Generate Sesi Pembelajaran')
|
||||
->modalDescription('Sistem akan men-generate atau memperbarui sesi 1 sampai 16 secara otomatis berdasarkan jadwal mata kuliah ini.')
|
||||
->schema([
|
||||
DatePicker::make('start_date')
|
||||
->label('Tanggal Pertemuan Ke-1')
|
||||
->default(now())
|
||||
->required()
|
||||
->native(false)
|
||||
->displayFormat('l, d F Y'),
|
||||
])
|
||||
->action(function (array $data, $livewire) {
|
||||
$course = $livewire->course;
|
||||
$schedule = $course->courseSchedules()->first();
|
||||
|
||||
if (! $schedule) {
|
||||
SystemNotification::danger('Batal!', 'Jadwal belum ditentukan untuk mata kuliah ini.')->send();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$startDate = Carbon::parse($data['start_date']);
|
||||
|
||||
for ($i = 1; $i <= 16; $i++) {
|
||||
ClassSession::updateOrCreate(
|
||||
[
|
||||
'course_id' => $course->id,
|
||||
'session_number' => $i,
|
||||
],
|
||||
[
|
||||
'date' => $startDate->copy()->addWeeks($i - 1)->toDateString(),
|
||||
'start_time' => $schedule->start_time,
|
||||
'end_time' => $schedule->end_time,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
SystemNotification::success('Selesai!', '16 Sesi berhasil digenerate/diperbarui.')->send();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Learning\ClassSessions\Actions;
|
||||
|
||||
use App\Models\ClassSession;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Support\Enums\Width;
|
||||
|
||||
class ViewAssignmentsAction extends Action
|
||||
{
|
||||
public static function getDefaultName(): ?string
|
||||
{
|
||||
return 'viewAssignments';
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->label('Tugas')
|
||||
->color('info')
|
||||
->icon('heroicon-o-clipboard-document-list')
|
||||
->link()
|
||||
->modalHeading(fn (array $arguments) => 'Tugas Kuliah - Sesi Ke-'.ClassSession::find($arguments['session'], ['*'])->session_number)
|
||||
->modalSubmitAction(false)
|
||||
->modalCancelActionLabel('Tutup')
|
||||
->modalWidth(Width::Large)
|
||||
->modalContent(fn (array $arguments) => view('filament.resources.learning.class-sessions.assignments-modal', [
|
||||
'assignments' => ClassSession::find($arguments['session'], ['*'])->assignments()->latest()->get(),
|
||||
]));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Learning\ClassSessions\Actions;
|
||||
|
||||
use App\Models\ClassSession;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Support\Enums\Width;
|
||||
|
||||
class ViewAttendanceAction extends Action
|
||||
{
|
||||
public static function getDefaultName(): ?string
|
||||
{
|
||||
return 'viewAttendance';
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->label('Presensi')
|
||||
->color('success')
|
||||
->icon('heroicon-o-check-circle')
|
||||
->link()
|
||||
->modalHeading(fn (array $arguments) => 'Daftar Presensi - Sesi Ke-'.ClassSession::find($arguments['session'], ['*'])->session_number)
|
||||
->modalSubmitAction(false)
|
||||
->modalCancelActionLabel('Tutup')
|
||||
->modalWidth(Width::ExtraLarge)
|
||||
->modalContent(fn (array $arguments) => view('filament.resources.learning.class-sessions.attendance-modal', [
|
||||
'attendances' => ClassSession::find($arguments['session'], ['*'])->attendances()->with('student')->latest('attended_at')->get(),
|
||||
]));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Learning\ClassSessions\Actions;
|
||||
|
||||
use App\Models\ClassSession;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Support\Enums\Width;
|
||||
|
||||
class ViewMaterialsAction extends Action
|
||||
{
|
||||
public static function getDefaultName(): ?string
|
||||
{
|
||||
return 'viewMaterials';
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->label('Materi')
|
||||
->color('warning')
|
||||
->icon('heroicon-o-book-open')
|
||||
->link()
|
||||
->modalHeading(fn (array $arguments) => 'Materi Kuliah - Sesi Ke-'.ClassSession::find($arguments['session'], ['*'])->session_number)
|
||||
->modalSubmitAction(false)
|
||||
->modalCancelActionLabel('Tutup')
|
||||
->modalWidth(Width::Large)
|
||||
->modalContent(fn (array $arguments) => view('filament.resources.learning.class-sessions.materials-modal', [
|
||||
'materials' => ClassSession::find($arguments['session'], ['*'])->materials()->latest()->get(),
|
||||
]));
|
||||
}
|
||||
}
|
||||
@ -2,33 +2,14 @@
|
||||
|
||||
namespace App\Filament\Resources\Learning\ClassSessions;
|
||||
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Filament\Actions\Cheerful\ForceDeleteAction;
|
||||
use App\Filament\Actions\Cheerful\RestoreAction;
|
||||
use App\Filament\Actions\DefaultBulkActions;
|
||||
use App\Filament\Columns\TimestampColumns;
|
||||
use App\Filament\Resources\Learning\ClassSessions\Pages\ListCourseSessions;
|
||||
use App\Filament\Resources\Learning\ClassSessions\Pages\ManageClassSessions;
|
||||
use App\Filament\Resources\Learning\ClassSessions\RelationManagers\AttendanceRelationManager;
|
||||
use App\Models\ClassSession;
|
||||
use App\Models\Course;
|
||||
use App\Settings\GeneralSettings;
|
||||
use BackedEnum;
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\TimePicker;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Components\Grid;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Enums\Width;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Filters\TrashedFilter;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||
use UnitEnum;
|
||||
@ -43,155 +24,11 @@ class ClassSessionResource extends Resource
|
||||
|
||||
protected static ?string $navigationLabel = 'Sesi Kelas';
|
||||
|
||||
protected static ?int $navigationSort = 1;
|
||||
protected static ?int $navigationSort = 5;
|
||||
|
||||
protected static ?string $modelLabel = 'Sesi Kelas';
|
||||
protected static ?string $recordTitleAttribute = 'session_number';
|
||||
|
||||
protected static ?string $pluralModelLabel = 'Sesi Kelas';
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
Grid::make(2)
|
||||
->schema([
|
||||
Select::make('course_id')
|
||||
->label('Mata Kuliah')
|
||||
->placeholder('Pilih Mata Kuliah')
|
||||
->options(function () {
|
||||
return Course::query()
|
||||
->where('semester', app(GeneralSettings::class)->current_semester)
|
||||
->pluck('name', 'id')
|
||||
->toArray();
|
||||
})
|
||||
->searchable()
|
||||
->required()
|
||||
->preload()
|
||||
->live()
|
||||
->afterStateUpdated(function ($state, $set) {
|
||||
if (! $state) {
|
||||
return;
|
||||
}
|
||||
|
||||
$schedule = \App\Models\CourseSchedule::where('course_id', $state)->first();
|
||||
|
||||
if ($schedule) {
|
||||
$set('start_time', $schedule->start_time?->format('H:i'));
|
||||
$set('end_time', $schedule->end_time?->format('H:i'));
|
||||
}
|
||||
|
||||
// Ambil pertemuan terakhir + 1
|
||||
$lastSession = \App\Models\ClassSession::where('course_id', $state)->max('session_number');
|
||||
$set('session_number', ($lastSession ?? 0) + 1);
|
||||
})
|
||||
->columnSpanFull(),
|
||||
|
||||
TextInput::make('session_number')
|
||||
->label('Pertemuan Ke-')
|
||||
->placeholder('1')
|
||||
->numeric()
|
||||
->required()
|
||||
->minValue(1)
|
||||
->maxValue(16)
|
||||
->autocomplete(false),
|
||||
|
||||
DatePicker::make('date')
|
||||
->label('Tanggal')
|
||||
->placeholder('Pilih Tanggal')
|
||||
->required()
|
||||
->native(false)
|
||||
->displayFormat('l, d F Y')
|
||||
->default(now()->toDateString()),
|
||||
|
||||
TimePicker::make('start_time')
|
||||
->label('Waktu Mulai')
|
||||
->placeholder('08:00')
|
||||
->native(false)
|
||||
->displayFormat('H:i')
|
||||
->seconds(false)
|
||||
->required(),
|
||||
|
||||
TimePicker::make('end_time')
|
||||
->label('Waktu Selesai')
|
||||
->placeholder('10:00')
|
||||
->native(false)
|
||||
->displayFormat('H:i')
|
||||
->seconds(false)
|
||||
->required(),
|
||||
])
|
||||
->columnSpanFull(),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('session_number')
|
||||
->label('Pertemuan Ke-')
|
||||
->sortable()
|
||||
->badge(),
|
||||
|
||||
TextColumn::make('course.name')
|
||||
->label('Mata Kuliah')
|
||||
->searchable()
|
||||
->sortable()
|
||||
->wrap()
|
||||
->description(fn (ClassSession $record) => $record->course->code),
|
||||
|
||||
TextColumn::make('date')
|
||||
->label('Tanggal')
|
||||
->date('l, d F Y')
|
||||
->sortable()
|
||||
->description(fn (ClassSession $record) => $record->start_time->format('H:i').' - '.$record->end_time->format('H:i').' WIB'),
|
||||
|
||||
TextColumn::make('attendances_count')
|
||||
->counts('attendances')
|
||||
->label('Presensi')
|
||||
->badge()
|
||||
->color('success'),
|
||||
|
||||
TextColumn::make('materials_count')
|
||||
->counts('materials')
|
||||
->label('Materi')
|
||||
->badge()
|
||||
->color('warning'),
|
||||
|
||||
TextColumn::make('assignments_count')
|
||||
->counts('assignments')
|
||||
->label('Tugas')
|
||||
->badge()
|
||||
->color('info'),
|
||||
|
||||
...TimestampColumns::make(),
|
||||
])
|
||||
->filters([
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()->hasRole(RoleEnum::Developer)),
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make()
|
||||
->modalWidth(Width::TwoExtraLarge),
|
||||
|
||||
DeleteAction::make(),
|
||||
|
||||
ForceDeleteAction::make(),
|
||||
|
||||
RestoreAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
...DefaultBulkActions::make('Sesi Kelas'),
|
||||
]),
|
||||
])
|
||||
->emptyStateIcon(Heroicon::OutlinedPresentationChartBar)
|
||||
->emptyStateDescription('Setelah Anda membuat data pertama, maka akan muncul disini.')
|
||||
->defaultSort('created_at', 'desc')
|
||||
->deferFilters(false)
|
||||
->paginated([25, 50, 100, 'all'])
|
||||
->defaultPaginationPageOption(25);
|
||||
}
|
||||
protected static ?string $slug = 'learning/class-sessions';
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
|
||||
@ -4,11 +4,13 @@
|
||||
|
||||
use App\Filament\Actions\BackAction;
|
||||
use App\Filament\Actions\Cheerful\CreateAction;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Filament\Resources\Learning\ClassSessions\Actions\DeleteSessionAction;
|
||||
use App\Filament\Resources\Learning\ClassSessions\Actions\EditSessionAction;
|
||||
use App\Filament\Resources\Learning\ClassSessions\Actions\GenerateSessionsAction;
|
||||
use App\Filament\Resources\Learning\ClassSessions\Actions\ViewAssignmentsAction;
|
||||
use App\Filament\Resources\Learning\ClassSessions\Actions\ViewAttendanceAction;
|
||||
use App\Filament\Resources\Learning\ClassSessions\Actions\ViewMaterialsAction;
|
||||
use App\Filament\Resources\Learning\ClassSessions\ClassSessionResource;
|
||||
use App\Filament\Support\SystemNotification;
|
||||
use App\Models\ClassSession;
|
||||
use App\Models\Course;
|
||||
use App\Models\Student;
|
||||
use Filament\Actions\Action;
|
||||
@ -70,34 +72,43 @@ public function sessions(): Collection
|
||||
]);
|
||||
}
|
||||
|
||||
public function formSchema(): array
|
||||
public function schema(): array
|
||||
{
|
||||
return [
|
||||
Grid::make(['default' => 3])
|
||||
Grid::make(['default' => 2])
|
||||
->schema([
|
||||
TextInput::make('session_number')
|
||||
->label('Pertemuan Ke-')
|
||||
->placeholder('1')
|
||||
->numeric()
|
||||
->default(fn () => ($this->course->classSessions()->max('session_number') ?? 0) + 1)
|
||||
->required(),
|
||||
->required()
|
||||
->minValue(1)
|
||||
->maxValue(16)
|
||||
->autocomplete(false),
|
||||
|
||||
DatePicker::make('date')
|
||||
->label('Tanggal')
|
||||
->default(now())
|
||||
->placeholder('Pilih Tanggal')
|
||||
->required()
|
||||
->native(false)
|
||||
->displayFormat('l, d F Y')
|
||||
->default(now()->toDateString()),
|
||||
|
||||
TimePicker::make('start_time')
|
||||
->label('Waktu Mulai')
|
||||
->placeholder('08:00')
|
||||
->native(false)
|
||||
->displayFormat('H:i')
|
||||
->seconds(false)
|
||||
->required(),
|
||||
|
||||
TimePicker::make('end_time')
|
||||
->label('Waktu Selesai')
|
||||
->placeholder('10:00')
|
||||
->native(false)
|
||||
->displayFormat('H:i')
|
||||
->seconds(false)
|
||||
->required(),
|
||||
Grid::make(['default' => 2])
|
||||
->schema([
|
||||
TimePicker::make('start_time')
|
||||
->label('Mulai')
|
||||
->native(false)
|
||||
->seconds(false)
|
||||
->required(),
|
||||
TimePicker::make('end_time')
|
||||
->label('Selesai')
|
||||
->native(false)
|
||||
->seconds(false)
|
||||
->required(),
|
||||
])->columnSpan(1),
|
||||
]),
|
||||
];
|
||||
}
|
||||
@ -119,14 +130,15 @@ protected function getHeaderActions(): array
|
||||
BackAction::make()
|
||||
->url(ManageClassSessions::getUrl()),
|
||||
|
||||
$this->generateSessionsAction(),
|
||||
GenerateSessionsAction::make(),
|
||||
|
||||
CreateAction::make()
|
||||
->label('Tambah Sesi')
|
||||
->label('Tambah')
|
||||
->modalHeading('Tambah Sesi')
|
||||
->modalSubmitActionLabel('Simpan')
|
||||
->modalCancelActionLabel('Batal')
|
||||
->form($this->formSchema())
|
||||
->mutateFormDataUsing(function (array $data): array {
|
||||
->schema($this->schema())
|
||||
->mutateDataUsing(function (array $data): array {
|
||||
$data['course_id'] = $this->courseId;
|
||||
|
||||
return $data;
|
||||
@ -139,102 +151,28 @@ protected function getHeaderActions(): array
|
||||
];
|
||||
}
|
||||
|
||||
public function generateSessionsAction(): Action
|
||||
public function viewAttendanceAction(): Action
|
||||
{
|
||||
return Action::make('generateSessions')
|
||||
->label('Generate Sesi')
|
||||
->icon('heroicon-o-sparkles')
|
||||
->color('warning')
|
||||
->requiresConfirmation()
|
||||
->modalHeading('Generate Sesi Pembelajaran')
|
||||
->modalDescription('Sistem akan men-generate atau memperbarui sesi 1 sampai 16 secara otomatis berdasarkan jadwal mata kuliah ini.')
|
||||
->form([
|
||||
DatePicker::make('start_date')
|
||||
->label('Tanggal Pertemuan Ke-1')
|
||||
->default(now())
|
||||
->required()
|
||||
->native(false),
|
||||
])
|
||||
->action(function (array $data) {
|
||||
$course = $this->course;
|
||||
$schedule = $course->courseSchedules()->first();
|
||||
|
||||
if (! $schedule) {
|
||||
SystemNotification::danger('Batal!', 'Jadwal belum ditentukan untuk mata kuliah ini.')->send();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$startDate = \Carbon\Carbon::parse($data['start_date']);
|
||||
|
||||
for ($i = 1; $i <= 16; $i++) {
|
||||
ClassSession::updateOrCreate(
|
||||
[
|
||||
'course_id' => $course->id,
|
||||
'session_number' => $i,
|
||||
],
|
||||
[
|
||||
'date' => $startDate->copy()->addWeeks($i - 1)->toDateString(),
|
||||
'start_time' => $schedule->start_time,
|
||||
'end_time' => $schedule->end_time,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
SystemNotification::success('Selesai!', '16 Sesi berhasil digenerate/diperbarui.')->send();
|
||||
});
|
||||
return ViewAttendanceAction::make();
|
||||
}
|
||||
|
||||
protected function viewAttendanceAction(): Action
|
||||
public function viewMaterialsAction(): Action
|
||||
{
|
||||
return Action::make('viewAttendance')
|
||||
->label('Lihat Presensi')
|
||||
->modalHeading(fn (array $arguments) => 'Daftar Presensi - Sesi Ke-'.ClassSession::find($arguments['session'])->session_number)
|
||||
->modalSubmitAction(false)
|
||||
->modalCancelActionLabel('Tutup')
|
||||
->modalWidth(Width::ExtraLarge)
|
||||
->modalContent(fn (array $arguments) => view('filament.resources.learning.class-sessions.attendance-modal', [
|
||||
'attendances' => ClassSession::find($arguments['session'])->attendances()->with('student')->latest('attended_at')->get(),
|
||||
]));
|
||||
return ViewMaterialsAction::make();
|
||||
}
|
||||
|
||||
protected function viewMaterialsAction(): Action
|
||||
public function viewAssignmentsAction(): Action
|
||||
{
|
||||
return Action::make('viewMaterials')
|
||||
->label('Daftar Materi')
|
||||
->modalHeading(fn (array $arguments) => 'Materi Kuliah - Sesi Ke-'.ClassSession::find($arguments['session'])->session_number)
|
||||
->modalSubmitAction(false)
|
||||
->modalCancelActionLabel('Tutup')
|
||||
->modalWidth(Width::Large)
|
||||
->modalContent(fn (array $arguments) => view('filament.resources.learning.class-sessions.materials-modal', [
|
||||
'materials' => ClassSession::find($arguments['session'])->materials()->latest()->get(),
|
||||
]));
|
||||
}
|
||||
|
||||
protected function viewAssignmentsAction(): Action
|
||||
{
|
||||
return Action::make('viewAssignments')
|
||||
->label('Daftar Tugas')
|
||||
->modalHeading(fn (array $arguments) => 'Tugas Kuliah - Sesi Ke-'.ClassSession::find($arguments['session'])->session_number)
|
||||
->modalSubmitAction(false)
|
||||
->modalCancelActionLabel('Tutup')
|
||||
->modalWidth(Width::Large)
|
||||
->modalContent(fn (array $arguments) => view('filament.resources.learning.class-sessions.assignments-modal', [
|
||||
'assignments' => ClassSession::find($arguments['session'])->assignments()->latest()->get(),
|
||||
]));
|
||||
return ViewAssignmentsAction::make();
|
||||
}
|
||||
|
||||
public function editSessionAction(): Action
|
||||
{
|
||||
return EditAction::make('editSession')
|
||||
->record(fn (array $arguments) => ClassSession::find($arguments['session']))
|
||||
->form($this->formSchema())
|
||||
->modalWidth(Width::TwoExtraLarge);
|
||||
return EditSessionAction::make();
|
||||
}
|
||||
|
||||
public function deleteSessionAction(): Action
|
||||
{
|
||||
return DeleteAction::make('deleteSession')
|
||||
->record(fn (array $arguments) => ClassSession::find($arguments['session']));
|
||||
return DeleteSessionAction::make();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
|
||||
namespace App\Filament\Resources\Learning\ClassSessions\Pages;
|
||||
|
||||
use App\Filament\Resources\Learning\ClassSessions\Actions\ViewAssignmentsAction;
|
||||
use App\Filament\Resources\Learning\ClassSessions\Actions\ViewAttendanceAction;
|
||||
use App\Filament\Resources\Learning\ClassSessions\Actions\ViewMaterialsAction;
|
||||
use App\Filament\Resources\Learning\ClassSessions\ClassSessionResource;
|
||||
use App\Models\ClassSession;
|
||||
use App\Models\Course;
|
||||
@ -15,7 +18,6 @@
|
||||
use Filament\Forms\Contracts\HasForms;
|
||||
use Filament\Resources\Pages\Page;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Enums\Width;
|
||||
use Illuminate\Support\Collection;
|
||||
use Livewire\Attributes\Computed;
|
||||
|
||||
@ -132,42 +134,18 @@ public function courses(): Collection
|
||||
});
|
||||
}
|
||||
|
||||
protected function viewAttendanceAction(): Action
|
||||
public function viewAttendanceAction(): Action
|
||||
{
|
||||
return Action::make('viewAttendance')
|
||||
->label('Lihat Presensi')
|
||||
->modalHeading(fn (array $arguments) => 'Daftar Presensi - Sesi Ke-'.ClassSession::find($arguments['session'])->session_number)
|
||||
->modalSubmitAction(false)
|
||||
->modalCancelActionLabel('Tutup')
|
||||
->modalWidth(Width::ExtraLarge)
|
||||
->modalContent(fn (array $arguments) => view('filament.resources.learning.class-sessions.attendance-modal', [
|
||||
'attendances' => ClassSession::find($arguments['session'])->attendances()->with('student')->latest('attended_at')->get(),
|
||||
]));
|
||||
return ViewAttendanceAction::make();
|
||||
}
|
||||
|
||||
protected function viewMaterialsAction(): Action
|
||||
public function viewMaterialsAction(): Action
|
||||
{
|
||||
return Action::make('viewMaterials')
|
||||
->label('Daftar Materi')
|
||||
->modalHeading(fn (array $arguments) => 'Materi Kuliah - Sesi Ke-'.ClassSession::find($arguments['session'])->session_number)
|
||||
->modalSubmitAction(false)
|
||||
->modalCancelActionLabel('Tutup')
|
||||
->modalWidth(Width::Large)
|
||||
->modalContent(fn (array $arguments) => view('filament.resources.learning.class-sessions.materials-modal', [
|
||||
'materials' => ClassSession::find($arguments['session'])->materials()->latest()->get(),
|
||||
]));
|
||||
return ViewMaterialsAction::make();
|
||||
}
|
||||
|
||||
protected function viewAssignmentsAction(): Action
|
||||
public function viewAssignmentsAction(): Action
|
||||
{
|
||||
return Action::make('viewAssignments')
|
||||
->label('Daftar Tugas')
|
||||
->modalHeading(fn (array $arguments) => 'Tugas Kuliah - Sesi Ke-'.ClassSession::find($arguments['session'])->session_number)
|
||||
->modalSubmitAction(false)
|
||||
->modalCancelActionLabel('Tutup')
|
||||
->modalWidth(Width::Large)
|
||||
->modalContent(fn (array $arguments) => view('filament.resources.learning.class-sessions.assignments-modal', [
|
||||
'assignments' => ClassSession::find($arguments['session'])->assignments()->latest()->get(),
|
||||
]));
|
||||
return ViewAssignmentsAction::make();
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ class AttendanceRelationManager extends RelationManager
|
||||
|
||||
protected static ?string $title = 'Presensi Mahasiswa';
|
||||
|
||||
public function form(Schema $schema): Schema
|
||||
public function schema(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
|
||||
@ -34,11 +34,9 @@ class CourseResource extends Resource
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedRectangleStack;
|
||||
|
||||
protected static ?string $title = 'Mata Kuliah';
|
||||
|
||||
protected static ?string $navigationLabel = 'Mata Kuliah';
|
||||
|
||||
protected static ?int $navigationSort = 15;
|
||||
protected static ?int $navigationSort = 10;
|
||||
|
||||
protected static ?string $recordTitleAttribute = 'name';
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Support\Enums\Width;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class ChangePasswordAction extends Action
|
||||
@ -17,7 +16,6 @@ protected function setUp(): void
|
||||
parent::setUp();
|
||||
|
||||
$this->label('Ganti Kata Sandi')
|
||||
->icon(Heroicon::OutlinedKey)
|
||||
->color('warning')
|
||||
->modalWidth(Width::Medium)
|
||||
->schema([
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Course;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
@ -16,8 +18,8 @@ public function up(): void
|
||||
});
|
||||
|
||||
// Populate existing courses with a random token
|
||||
\App\Models\Course::all()->each(function ($course) {
|
||||
$course->update(['sharing_token' => \Illuminate\Support\Str::random(32)]);
|
||||
Course::all()->each(function ($course) {
|
||||
$course->update(['sharing_token' => Str::random(32)]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -91,7 +91,7 @@ class="h-4 w-4 text-gray-400 group-hover:text-primary-500 mt-1 transition-colors
|
||||
</a>
|
||||
|
||||
<div
|
||||
class="flex flex-col items-center justify-center border-l border-gray-100 dark:border-gray-700 p-1 gap-3 p-3">
|
||||
class="flex flex-col items-start justify-center border-l border-gray-100 dark:border-gray-700 p-1 gap-3 p-3">
|
||||
{{ ($this->pinAction)(['record' => $card->id]) }}
|
||||
|
||||
@canAny(['Update:Assignment', 'Delete:Assignment'])
|
||||
|
||||
@ -52,6 +52,8 @@ class="flex items-center gap-1.5 font-bold text-success-600 dark:text-success-40
|
||||
|
||||
<div class="flex items-center gap-1">
|
||||
{{ ($this->viewAttendanceAction)(['session' => $session->id]) }}
|
||||
{{ ($this->viewMaterialsAction)(['session' => $session->id]) }}
|
||||
{{ ($this->viewAssignmentsAction)(['session' => $session->id]) }}
|
||||
{{ ($this->editSessionAction)(['session' => $session->id]) }}
|
||||
{{ ($this->deleteSessionAction)(['session' => $session->id]) }}
|
||||
</div>
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\ShareAttendanceController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::get('/', function () {
|
||||
return redirect()->route('filament.admin.auth.login');
|
||||
});
|
||||
|
||||
Route::get('/share/presensi/{token}', [\App\Http\Controllers\ShareAttendanceController::class, 'show'])->name('share.attendance');
|
||||
Route::get('/share/presensi/{token}', [ShareAttendanceController::class, 'show'])->name('share.attendance');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user