From 15bab26439453fbb8d19778a347ae9b7ef9805b0 Mon Sep 17 00:00:00 2001 From: reihanrere Date: Sun, 25 May 2025 11:13:50 +0700 Subject: [PATCH] add-page-parent --- app/Filament/Pages/SchoolInformation.php | 4 +- app/Filament/Pages/StudentReport.php | 61 ++++++++++++------- app/Filament/Resources/AssessmentResource.php | 2 +- .../Pages/ListAssessments.php | 4 +- .../Resources/AttendancesResource.php | 2 +- .../Pages/ListAttendances.php | 4 +- .../CompetencyAchievementResource.php | 2 +- .../ExtracurricularAssessmentResource.php | 4 +- app/Filament/Resources/StudentResource.php | 4 +- .../StudentResource/Pages/CreateStudent.php | 61 +++++++------------ .../StudentResource/Pages/EditStudent.php | 32 +++++++++- app/Filament/Resources/UserResource.php | 10 +-- app/Policies/SchoolInformationPolicy.php | 14 ++--- config/filament-shield.php | 2 +- database/seeders/ClassStudentSeeder.php | 47 ++++++++------ database/seeders/StudentSeeder.php | 37 ++++++++--- database/seeders/UserSeeder.php | 12 +++- 17 files changed, 187 insertions(+), 115 deletions(-) diff --git a/app/Filament/Pages/SchoolInformation.php b/app/Filament/Pages/SchoolInformation.php index d435c34..9149705 100644 --- a/app/Filament/Pages/SchoolInformation.php +++ b/app/Filament/Pages/SchoolInformation.php @@ -24,12 +24,12 @@ class SchoolInformation extends Page implements HasForms public static function canAccess(): bool { - return auth()->user()->hasAnyRole(['super_admin']); + return auth()->user()?->can('page_SchoolInformation'); } public static function shouldRegisterNavigation(): bool { - return auth()->user()->hasAnyRole(['super_admin']); + return auth()->user()?->can('page_SchoolInformation'); } public ?array $data = []; diff --git a/app/Filament/Pages/StudentReport.php b/app/Filament/Pages/StudentReport.php index 3f51eda..4985071 100644 --- a/app/Filament/Pages/StudentReport.php +++ b/app/Filament/Pages/StudentReport.php @@ -34,25 +34,29 @@ class StudentReport extends Page public static function canAccess(): bool { $user = auth()->user(); - $isTeacher = false; - $homeRoomTeacher = HomeRoomTeacher::where('teacher_id', $user->id)->first(); - if ($homeRoomTeacher) { - $isTeacher = true; + + if ($user->hasRole('parent')) { + return true; } - return auth()->user()->hasAnyRole(['super_admin']) || auth()->user()->hasAnyRole(['headmaster']) || $isTeacher; + $isHomeRoomTeacher = HomeRoomTeacher::where('teacher_id', $user->id)->exists(); + + return $user->can('page_SchoolInformation') || $isHomeRoomTeacher; } public static function shouldRegisterNavigation(): bool { $user = auth()->user(); - $isTeacher = false; - $homeRoomTeacher = HomeRoomTeacher::where('teacher_id', $user->id)->first(); - if ($homeRoomTeacher) { - $isTeacher = true; + + if ($user->hasRole('parent')) { + return true; } - return auth()->user()->hasAnyRole(['super_admin']) || auth()->user()->hasAnyRole(['headmaster']) || $isTeacher; + // Untuk teacher (wali kelas) + $isHomeRoomTeacher = HomeRoomTeacher::where('teacher_id', $user->id)->exists(); + + // Atau punya permission khusus + return $user->can('page_SchoolInformation') || $isHomeRoomTeacher; } public function mount(): void @@ -66,17 +70,6 @@ class StudentReport extends Page public function form(Form $form): Form { return $form->schema([ -// Select::make('class_id') -// ->label('Class') -// ->required() -// ->options(ClassRoom::pluck('class_name', 'id')->toArray()) -// ->searchable() -// ->reactive() -// ->afterStateUpdated(function ($state) { -// $this->class_id = $state; -// $this->data['class_id'] = $state; // Update data array -// $this->loadData(); -// }), Select::make('class_id') ->label('Class') ->required() @@ -90,6 +83,17 @@ class StudentReport extends Page if ($homeRoomTeacher) { $query->where('id', $homeRoomTeacher->class_room_id); } + } else if ($user->hasAnyRole(['parent'])) { + $student = Student::where("email", $user->email)->first(); // Changed from student email to parent_email + + if ($student) { + $classStudentIds = ClassStudent::where("student_id", $student->id) + ->pluck('class_room_id') + ->toArray(); + + $query->whereIn("id", $classStudentIds); + } + } return $query->pluck('class_name', 'id')->toArray(); @@ -137,6 +141,15 @@ class StudentReport extends Page return; } + $user = auth()->user(); + + $isParent = $user->hasRole('parent'); + $studentId = null; + if ($isParent) { + $student = Student::where('email', $user->email)->first(); + $studentId = $student->id ?? null; + } + $groupedAssessment = []; $assessments = Assessment::where('semester', $this->semester) @@ -144,6 +157,9 @@ class StudentReport extends Page $query->where('academic_year_id', $this->academic_year) ->where('class_id', $this->class_id); }) + ->when($isParent && $studentId, function($query) use ($studentId) { + $query->where('student_id', $studentId); // Tambahan filter untuk parent + }) ->with('teacherSubject', 'student') ->get() ->toArray(); @@ -170,6 +186,9 @@ class StudentReport extends Page $students = ClassStudent::with(['class', 'academicYear', 'student']) ->where('class_room_id', $this->class_id) ->where('academic_year_id', $this->academic_year) + ->when($isParent && $studentId, function($query) use ($studentId) { + $query->where('student_id', $studentId); // Tambahan filter untuk parent + }) ->get() ->map(function($student) { return $student['student']; diff --git a/app/Filament/Resources/AssessmentResource.php b/app/Filament/Resources/AssessmentResource.php index 7642951..6bb2297 100644 --- a/app/Filament/Resources/AssessmentResource.php +++ b/app/Filament/Resources/AssessmentResource.php @@ -171,7 +171,7 @@ class AssessmentResource extends Resource ]) ->bulkActions([ Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DeleteBulkAction::make()->visible(fn () => auth()->user()->hasRole('super_admin') || auth()->user()->hasRole('teacher')), + Tables\Actions\DeleteBulkAction::make()->visible(fn () => auth()->user()->hasRole('admin') || auth()->user()->hasRole('teacher')), ]), ]) ->emptyStateActions([ diff --git a/app/Filament/Resources/AssessmentResource/Pages/ListAssessments.php b/app/Filament/Resources/AssessmentResource/Pages/ListAssessments.php index 74afe8e..a014939 100644 --- a/app/Filament/Resources/AssessmentResource/Pages/ListAssessments.php +++ b/app/Filament/Resources/AssessmentResource/Pages/ListAssessments.php @@ -34,12 +34,12 @@ class ListAssessments extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make()->visible(fn () => auth()->user()->hasRole('super_admin')), + Actions\CreateAction::make()->visible(fn () => auth()->user()->hasRole('admin')), Actions\Action::make('multiple') ->label('Multiple Assessments') ->url('assessments/multiple') ->icon('heroicon-o-user-group') - ->visible(fn () => auth()->user()->hasRole('super_admin') || auth()->user()->hasRole('teacher')), + ->visible(fn () => auth()->user()->hasRole('admin') || auth()->user()->hasRole('teacher')), ]; } } diff --git a/app/Filament/Resources/AttendancesResource.php b/app/Filament/Resources/AttendancesResource.php index 6d991e9..6e0af40 100644 --- a/app/Filament/Resources/AttendancesResource.php +++ b/app/Filament/Resources/AttendancesResource.php @@ -240,7 +240,7 @@ class AttendancesResource extends Resource ]) ->bulkActions([ Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DeleteBulkAction::make()->visible(fn () => auth()->user()->hasRole('super_admin') || auth()->user()->hasRole('teacher')), + Tables\Actions\DeleteBulkAction::make()->visible(fn () => auth()->user()->hasRole('admin') || auth()->user()->hasRole('teacher')), ]), ]) ->defaultSort('date', 'desc') diff --git a/app/Filament/Resources/AttendancesResource/Pages/ListAttendances.php b/app/Filament/Resources/AttendancesResource/Pages/ListAttendances.php index 1a85dfd..50a98db 100644 --- a/app/Filament/Resources/AttendancesResource/Pages/ListAttendances.php +++ b/app/Filament/Resources/AttendancesResource/Pages/ListAttendances.php @@ -34,12 +34,12 @@ class ListAttendances extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make()->visible(fn () => auth()->user()->hasRole('super_admin')), + Actions\CreateAction::make()->visible(fn () => auth()->user()->hasRole('admin')), Actions\Action::make('multiple') ->label('Multiple Attendance') ->url('attendances/multiple') ->icon('heroicon-o-user-group') - ->visible(fn () => auth()->user()->hasRole('super_admin') || auth()->user()->hasRole('teacher')), + ->visible(fn () => auth()->user()->hasRole('admin') || auth()->user()->hasRole('teacher')), ]; } } diff --git a/app/Filament/Resources/CompetencyAchievementResource.php b/app/Filament/Resources/CompetencyAchievementResource.php index 40d7772..af13c13 100644 --- a/app/Filament/Resources/CompetencyAchievementResource.php +++ b/app/Filament/Resources/CompetencyAchievementResource.php @@ -101,7 +101,7 @@ class CompetencyAchievementResource extends Resource ]) ->bulkActions([ Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DeleteBulkAction::make()->visible(fn () => auth()->user()->hasRole('super_admin') || auth()->user()->hasRole('teacher')), + Tables\Actions\DeleteBulkAction::make()->visible(fn () => auth()->user()->hasRole('admin') || auth()->user()->hasRole('teacher')), ]), ]) ->emptyStateActions([ diff --git a/app/Filament/Resources/ExtracurricularAssessmentResource.php b/app/Filament/Resources/ExtracurricularAssessmentResource.php index 41681c6..02a97c0 100644 --- a/app/Filament/Resources/ExtracurricularAssessmentResource.php +++ b/app/Filament/Resources/ExtracurricularAssessmentResource.php @@ -32,7 +32,7 @@ class ExtracurricularAssessmentResource extends Resource $user = auth()->user(); $query = ClassStudent::with(['student', 'class']); - if ($user->hasAnyRole(['super_admin'])) + if ($user->hasAnyRole(['admin'])) { return $query->get()->mapWithKeys(function ($cs) { return [ @@ -125,7 +125,7 @@ class ExtracurricularAssessmentResource extends Resource ]) ->bulkActions([ Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DeleteBulkAction::make()->visible(fn () => auth()->user()->hasRole('super_admin') || auth()->user()->hasRole('teacher')), + Tables\Actions\DeleteBulkAction::make()->visible(fn () => auth()->user()->hasRole('admin') || auth()->user()->hasRole('teacher')), ]), ]) ->emptyStateActions([ diff --git a/app/Filament/Resources/StudentResource.php b/app/Filament/Resources/StudentResource.php index b10d13f..6494b3f 100644 --- a/app/Filament/Resources/StudentResource.php +++ b/app/Filament/Resources/StudentResource.php @@ -62,8 +62,9 @@ class StudentResource extends Resource ->maxLength(15), Forms\Components\TextInput::make('email') - ->label('Email') + ->label("Parent's Email") ->email() + ->required() ->maxLength(100), Forms\Components\TextInput::make('parent_name') @@ -73,6 +74,7 @@ class StudentResource extends Resource Forms\Components\TextInput::make('parent_phone') ->label("Parent's Phone") + ->required() ->maxLength(15), Forms\Components\Select::make('religion') diff --git a/app/Filament/Resources/StudentResource/Pages/CreateStudent.php b/app/Filament/Resources/StudentResource/Pages/CreateStudent.php index 4b4046d..7a75c08 100644 --- a/app/Filament/Resources/StudentResource/Pages/CreateStudent.php +++ b/app/Filament/Resources/StudentResource/Pages/CreateStudent.php @@ -5,51 +5,34 @@ namespace App\Filament\Resources\StudentResource\Pages; use App\Filament\Resources\StudentResource; use App\Models\Student; use App\Models\User; +use Carbon\Carbon; use Filament\Actions; use Filament\Notifications\Notification; use Filament\Resources\Pages\CreateRecord; +use Spatie\Permission\Models\Role; class CreateStudent extends CreateRecord { protected static string $resource = StudentResource::class; -// protected function mutateFormDataBeforeCreate(array $data): array -// { -//// $user = User::firstOrCreate( -//// ['email' => 'teacher@example.com'], -//// [ -//// 'name' => 'teacher', -//// 'password' => bcrypt('teacher'), -//// ] -//// ); -//// -// $birthDate = explode('-', $data['birth_date']); -// -// -// $password = join("", $birthDate) . '-' . $data['nis']; -// -// $add = [ -// 'email' => $data['email'], -// 'name' => $data['parent_name'], -// 'password' => $password, -// ]; -// -// dd($add); -// die; -// -// $exists = Student::where('name', $data['name']) -// ->exists(); -// -// if ($exists) { -// Notification::make() -// ->title('Failed to save') -// ->body('A record already exists.') -// ->danger() -// ->send(); -// -// $this->halt(); // Stop the save process -// } -// -// return $data; -// } + protected function mutateFormDataBeforeCreate(array $data): array + { + $parentRole = Role::where('name', 'parent')->first(); + + $birthDate = Carbon::parse($data['birth_date']); + $password = $birthDate->format('dmY') . $data['nis']; + + $parentUser = User::updateOrCreate( + ['email' => $data['email']], + [ + 'name' => $data['parent_name'], + 'password' => bcrypt($password), + 'phone' => $data['parent_phone'], + ] + ); + + $parentUser->assignRole($parentRole); + + return $data; + } } diff --git a/app/Filament/Resources/StudentResource/Pages/EditStudent.php b/app/Filament/Resources/StudentResource/Pages/EditStudent.php index 51d7019..d4f1d70 100644 --- a/app/Filament/Resources/StudentResource/Pages/EditStudent.php +++ b/app/Filament/Resources/StudentResource/Pages/EditStudent.php @@ -3,17 +3,47 @@ namespace App\Filament\Resources\StudentResource\Pages; use App\Filament\Resources\StudentResource; +use App\Models\User; use Filament\Actions; +use Filament\Notifications\Notification; use Filament\Resources\Pages\EditRecord; +use Spatie\Permission\Models\Role; class EditStudent extends EditRecord { protected static string $resource = StudentResource::class; + protected function mutateFormDataBeforeSave(array $data): array + { + $parentRole = Role::where('name', 'parent')->first(); + + $parentUser = User::updateOrCreate( + ['email' => $data['email']], + [ + 'name' => $data['parent_name'], + 'phone' => $data['parent_phone'], + ] + ); + + // Pastikan user memiliki role parent + if (!$parentUser->hasRole('parent')) { + $parentUser->assignRole($parentRole); + } + + return $data; + } + protected function getHeaderActions(): array { return [ - Actions\DeleteAction::make(), + Actions\DeleteAction::make() + ->before(function (Actions\DeleteAction $action) { + $student = $this->record; + + if ($student->email) { + User::where('email', $student->email)->delete(); + } + }), ]; } } diff --git a/app/Filament/Resources/UserResource.php b/app/Filament/Resources/UserResource.php index 7260c3a..a062124 100644 --- a/app/Filament/Resources/UserResource.php +++ b/app/Filament/Resources/UserResource.php @@ -83,12 +83,12 @@ class UserResource extends Resource Tables\Columns\TextColumn::make('gender') ->formatStateUsing(fn (string $state): string => ucfirst($state)), Tables\Columns\TextColumn::make('birth_date') - ->date() - ->sortable(), + ->date(), Tables\Columns\TextColumn::make('phone') ->searchable(), Tables\Columns\TextColumn::make('roles.name') - ->searchable(), + ->searchable() + ->sortable(), Tables\Columns\TextColumn::make('created_at') ->dateTime() ->sortable() @@ -102,11 +102,11 @@ class UserResource extends Resource // ]) ->actions([ - Tables\Actions\EditAction::make()->visible(fn () => auth()->user()->hasRole('super_admin')), + Tables\Actions\EditAction::make()->visible(fn () => auth()->user()->hasRole('admin')), ]) ->bulkActions([ Tables\Actions\BulkActionGroup::make([ -// Tables\Actions\DeleteBulkAction::make()->visible(fn () => auth()->user()->hasRole('super_admin')), +// Tables\Actions\DeleteBulkAction::make()->visible(fn () => auth()->user()->hasRole('admin')), ]), ]) ->emptyStateActions([ diff --git a/app/Policies/SchoolInformationPolicy.php b/app/Policies/SchoolInformationPolicy.php index 61908b1..64a116f 100644 --- a/app/Policies/SchoolInformationPolicy.php +++ b/app/Policies/SchoolInformationPolicy.php @@ -13,7 +13,7 @@ class SchoolInformationPolicy */ public function viewAny(User $user): bool { - return $user->can('view_any_school::information'); + return $user->can('page_SchoolInformation'); } /** @@ -21,7 +21,7 @@ class SchoolInformationPolicy */ public function view(User $user, SchoolInformation $schoolInformation): bool { - return $user->can('view_school::information'); + return $user->can('page_SchoolInformation'); } /** @@ -29,7 +29,7 @@ class SchoolInformationPolicy */ public function create(User $user): bool { - return $user->can('create_school::information'); + return $user->can('page_SchoolInformation'); } /** @@ -37,7 +37,7 @@ class SchoolInformationPolicy */ public function update(User $user, SchoolInformation $schoolInformation): bool { - return $user->can('update_school::information'); + return $user->can('page_SchoolInformation'); } /** @@ -45,7 +45,7 @@ class SchoolInformationPolicy */ public function delete(User $user, SchoolInformation $schoolInformation): bool { - return $user->can('delete_school::information'); + return $user->can('page_SchoolInformation'); } /** @@ -53,7 +53,7 @@ class SchoolInformationPolicy */ public function restore(User $user, SchoolInformation $schoolInformation): bool { - return $user->can('restore_school::information'); + return $user->can('page_SchoolInformation'); } /** @@ -61,6 +61,6 @@ class SchoolInformationPolicy */ public function forceDelete(User $user, SchoolInformation $schoolInformation): bool { - return $user->can('force_delete_school::information'); + return $user->can('page_SchoolInformation'); } } diff --git a/config/filament-shield.php b/config/filament-shield.php index 451c6c5..9b29a09 100644 --- a/config/filament-shield.php +++ b/config/filament-shield.php @@ -21,7 +21,7 @@ return [ 'super_admin' => [ 'enabled' => true, - 'name' => 'super_admin', + 'name' => 'admin', 'define_via_gate' => false, 'intercept_gate' => 'before', // after ], diff --git a/database/seeders/ClassStudentSeeder.php b/database/seeders/ClassStudentSeeder.php index f5f11d9..77086ff 100644 --- a/database/seeders/ClassStudentSeeder.php +++ b/database/seeders/ClassStudentSeeder.php @@ -6,34 +6,45 @@ use App\Models\AcademicYear; use App\Models\ClassRoom; use App\Models\ClassStudent; use App\Models\Student; -use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; class ClassStudentSeeder extends Seeder { - /** - * Run the database seeds. - */ public function run(): void { - // Pastikan data ClassRoom, Student, dan AcademicYear sudah ada + $academicYears = AcademicYear::all(); $classRooms = ClassRoom::all(); $students = Student::all(); - $academicYears = AcademicYear::all(); - // Hanya melanjutkan jika data tersedia - if ($classRooms->isNotEmpty() && $students->isNotEmpty() && $academicYears->isNotEmpty()) { - foreach ($classRooms as $classRoom) { - foreach ($students as $student) { - foreach ($academicYears as $academicYear) { - // Buat ClassStudent baru untuk setiap kombinasi - ClassStudent::create([ - 'class_room_id' => $classRoom->id, - 'student_id' => $student->id, - 'academic_year_id' => $academicYear->id, - ]); - } + // Pastikan ada data yang tersedia + if ($academicYears->isEmpty() || $classRooms->isEmpty() || $students->isEmpty()) { + return; + } + + // Distribusikan siswa ke kelas secara merata + $studentsPerClass = ceil($students->count() / $classRooms->count()); + $studentChunks = $students->chunk($studentsPerClass); + + foreach ($academicYears as $academicYear) { + $classIndex = 0; + + foreach ($studentChunks as $studentGroup) { + // Pastikan kita tidak melebihi jumlah kelas yang tersedia + if ($classIndex >= $classRooms->count()) { + break; } + + $classRoom = $classRooms[$classIndex]; + + foreach ($studentGroup as $student) { + ClassStudent::firstOrCreate([ + 'class_room_id' => $classRoom->id, + 'student_id' => $student->id, + 'academic_year_id' => $academicYear->id, + ]); + } + + $classIndex++; } } } diff --git a/database/seeders/StudentSeeder.php b/database/seeders/StudentSeeder.php index fc38ee2..18b0f55 100644 --- a/database/seeders/StudentSeeder.php +++ b/database/seeders/StudentSeeder.php @@ -2,38 +2,55 @@ namespace Database\Seeders; -use App\Models\ClassRoom; use App\Models\Student; +use App\Models\User; use Carbon\Carbon; -use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; +use Spatie\Permission\Models\Role; class StudentSeeder extends Seeder { - /** - * Run the database seeds. - */ public function run(): void { $religions = ['islam', 'kristen', 'katolik', 'hindu', 'buddha']; + $parentRole = Role::where('name', 'parent')->firstOrFail(); for ($i = 1; $i <= 20; $i++) { $gender = $i % 2 == 0 ? 'L' : 'P'; $religion = $religions[array_rand($religions)]; - $nis = '24' . str_pad($i, 4, '0', STR_PAD_LEFT); // NIS unik, misal 240001 + $nis = '24' . str_pad($i, 4, '0', STR_PAD_LEFT); + $birthDate = Carbon::now()->subYears(rand(15, 18))->subMonths(rand(1, 12)); + $parentName = 'Orang Tua Siswa ' . $i; + $parentEmail = 'parent' . $i . '@example.com'; + $parentPhone = '0813' . rand(1000000, 9999999); + + $birthDateParse = Carbon::parse($birthDate); + $password = $birthDateParse->format('dmY') . $nis; + + $parentUser = User::firstOrCreate( + ['email' => $parentEmail], + [ + 'name' => $parentName, + 'password' => bcrypt($password), + 'phone' => $parentPhone, + ] + ); + + $parentUser->assignRole($parentRole); Student::firstOrCreate( - ['nis' => $nis], // Cek berdasarkan NIS + ['nis' => $nis], [ 'full_name' => 'Siswa ' . $i, 'gender' => $gender, - 'birth_date' => Carbon::now()->subYears(rand(15, 18))->subMonths(rand(1, 12)), + 'birth_date' => $birthDate, 'birth_place' => 'Kota ' . chr(65 + rand(0, 25)), 'address' => 'Jl. Contoh No.' . $i, 'phone' => '0812' . rand(1000000, 9999999), - 'parent_name' => 'Orang Tua Siswa ' . $i, + 'parent_name' => $parentName, 'religion' => $religion, - 'parent_phone' => '0813' . rand(1000000, 9999999), + 'parent_phone' => $parentPhone, + 'email' => $parentEmail, 'created_at' => now(), 'updated_at' => now(), ] diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index 0664c80..fa850f2 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -51,7 +51,7 @@ class UserSeeder extends Seeder // 4. Buat role super_admin jika belum ada $role = Role::firstOrCreate([ - 'name' => 'super_admin', + 'name' => 'admin', 'guard_name' => 'web', ]); @@ -60,6 +60,16 @@ class UserSeeder extends Seeder 'guard_name' => 'web', ]); + $headmaster = Role::firstOrCreate([ + 'name' => 'headmaster', + 'guard_name' => 'web', + ]); + + $parent = Role::firstOrCreate([ + 'name' => 'parent', + 'guard_name' => 'web', + ]); + $teacher->syncPermissions($rolePermissions); $role->syncPermissions($rolePermissions);