diff --git a/app/Filament/Resources/AssessmentComponentResource.php b/app/Filament/Resources/AssessmentComponentResource.php deleted file mode 100644 index 36c071b..0000000 --- a/app/Filament/Resources/AssessmentComponentResource.php +++ /dev/null @@ -1,170 +0,0 @@ -schema([ - Forms\Components\Section::make('Component Information') - ->schema([ - Forms\Components\TextInput::make('name') - ->required() - ->maxLength(100) - ->live(onBlur: true) - ->afterStateUpdated(function ($set, $state) { - $abbreviation = self::generateAbbreviation($state); - $set('code', $abbreviation); - }), - - Forms\Components\TextInput::make('code') - ->required() - ->maxLength(50) - ->unique(ignoreRecord: true) - ->disabled() - ->dehydrated(), - - Forms\Components\TextInput::make('weight') - ->required() - ->numeric() - ->minValue(0) - ->maxValue(100) - ->suffix('%') - ->helperText('Bobot dalam persentase (0-100)'), - - Forms\Components\Toggle::make('is_active') - ->default(true) - ->inline(false) - ->onColor('success') - ->offColor('danger'), - ])->columns(2) - ]); - } - - public static function table(Table $table): Table - { - return $table - ->columns([ - Tables\Columns\TextColumn::make('name') - ->searchable() - ->sortable(), - - Tables\Columns\TextColumn::make('code') - ->searchable() - ->sortable() - ->badge() - ->color('info'), - - Tables\Columns\TextColumn::make('weight') - ->numeric() - ->suffix('%') - ->sortable() - ->alignCenter(), - - Tables\Columns\IconColumn::make('is_active') - ->boolean() - ->sortable() - ->alignCenter(), - - Tables\Columns\TextColumn::make('created_at') - ->dateTime() - ->sortable() - ->toggleable(isToggledHiddenByDefault: true), - ]) - ->filters([ - Tables\Filters\SelectFilter::make('is_active') - ->options([ - true => 'Active', - false => 'Inactive', - ]) - ->label('Status'), - ]) - ->actions([ - Tables\Actions\EditAction::make() - ->iconButton(), - Tables\Actions\DeleteAction::make() - ->iconButton(), - ]) - ->bulkActions([ - Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DeleteBulkAction::make(), - ]), - ]) - ->emptyStateActions([ - Tables\Actions\CreateAction::make(), - ]) - ->defaultSort('weight', 'desc'); - } - - public static function getPages(): array - { - return [ - 'index' => Pages\ListAssessmentComponents::route('/'), - 'create' => Pages\CreateAssessmentComponent::route('/create'), - 'edit' => Pages\EditAssessmentComponent::route('/{record}/edit'), - ]; - } - - protected static function generateAbbreviation(string $name): string - { - // Pastikan nama tidak kosong - if (empty(trim($name))) { - return 'DFT'; // Default value jika kosong - } - - $commonAbbreviations = [ - 'ulangan harian' => 'UH', - 'penilaian tengah semester' => 'PTS', - 'penilaian akhir semester' => 'PAS', - 'tugas' => 'TGS', - 'praktikum' => 'PRK', - 'kehadiran' => 'ABS', - 'proyek' => 'PRJ', - ]; - - $lowerName = Str::lower(trim($name)); - - // Cek apakah nama cocok dengan daftar singkatan umum - if (array_key_exists($lowerName, $commonAbbreviations)) { - return $commonAbbreviations[$lowerName]; - } - - // Logika untuk membuat singkatan dari kata pertama setiap kata - $words = preg_split('/\s+/', $lowerName); - $abbreviation = ''; - - foreach ($words as $word) { - // Ambil huruf pertama dari setiap kata yang tidak kosong - if (!empty($word)) { - $abbreviation .= strtoupper($word[0]); - } - } - - // Jika hasil singkatan terlalu pendek, ambil 3 huruf pertama (tanpa spasi) - if (strlen($abbreviation) < 2) { - $cleaned = preg_replace('/\s+/', '', $name); - $abbreviation = strtoupper(substr($cleaned, 0, 3)); - } - - return $abbreviation ?: 'DFT'; // Fallback jika masih kosong - } -} diff --git a/app/Filament/Resources/AssessmentComponentResource/Pages/CreateAssessmentComponent.php b/app/Filament/Resources/AssessmentComponentResource/Pages/CreateAssessmentComponent.php deleted file mode 100644 index f3f296c..0000000 --- a/app/Filament/Resources/AssessmentComponentResource/Pages/CreateAssessmentComponent.php +++ /dev/null @@ -1,12 +0,0 @@ -schema([ + Forms\Components\Select::make('teacher_subject_id') + ->label('Teacher Subject') + ->required() + ->relationship('teacherSubject', 'id') + ->getOptionLabelFromRecordUsing(fn (TeacherSubject $record) => + $record->teacher->name . ' - ' . $record->subject->name . ' - ' . $record->class->class_name . ' - ' . $record->academic_year) + ->searchable() + ->preload() + ->afterStateUpdated(function (callable $set, $state) { + // Filter siswa berdasarkan kelas yang dipilih dalam teacher_subject_id + if ($state) { + $teacherSubject = TeacherSubject::find($state); + if ($teacherSubject) { + $set('student_id', null); // Reset student_id jika teacher_subject_id berubah + } + } + }) + ->required(), + + Forms\Components\Select::make('student_id') + ->label('Student') + ->required() + ->searchable() + // Filter opsi siswa berdasarkan kelas yang terkait dengan teacher_subject_id + ->options(function ($get) { + $teacherSubjectId = $get('teacher_subject_id'); + if ($teacherSubjectId) { + $teacherSubject = TeacherSubject::find($teacherSubjectId); + // Ambil siswa yang memiliki kelas yang sesuai dengan teacher_subject_id + $students = Student::where('class_id', $teacherSubject->class_id) + ->pluck('full_name', 'id') + ->toArray(); + + return $students; + } + return []; + }) + ->getOptionLabelUsing(function ($value) { + $student = Student::find($value); + return $student ? $student->full_name . ' (' . $student->nis . ')' : null; + }) + ->required(), + + Forms\Components\TextInput::make('score') + ->label('Score') + ->numeric() + ->required() + ->minValue(0) + ->maxValue(100), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('student.full_name') + ->label('Student') + ->searchable() + ->sortable(), + + Tables\Columns\TextColumn::make('teacherSubject.class.class_name') + ->label('Class') + ->searchable(), + + Tables\Columns\TextColumn::make('teacherSubject.subject.name') + ->label('Subject') + ->searchable(), + + Tables\Columns\TextColumn::make('teacherSubject.teacher.name') + ->label('Teacher') + ->searchable(), + Tables\Columns\TextColumn::make('score') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListAssessments::route('/'), + 'create' => Pages\CreateAssessment::route('/create'), + 'edit' => Pages\EditAssessment::route('/{record}/edit'), + 'multiple' => Pages\MultipleAssessments::route('/multiple'), + ]; + } +} diff --git a/app/Filament/Resources/AssessmentResource/Pages/CreateAssessment.php b/app/Filament/Resources/AssessmentResource/Pages/CreateAssessment.php new file mode 100644 index 0000000..19f00c9 --- /dev/null +++ b/app/Filament/Resources/AssessmentResource/Pages/CreateAssessment.php @@ -0,0 +1,34 @@ +where('student_id', $data['student_id']) + ->exists(); + + if ($exists) { + Notification::make() + ->title('Failed to save') + ->body('A record for this teacher, subject, and student combination already exists.') + ->danger() + ->send(); + + $this->halt(); // Stop the save process + } + + return $data; + } + +} diff --git a/app/Filament/Resources/AssessmentResource/Pages/EditAssessment.php b/app/Filament/Resources/AssessmentResource/Pages/EditAssessment.php new file mode 100644 index 0000000..4c41de4 --- /dev/null +++ b/app/Filament/Resources/AssessmentResource/Pages/EditAssessment.php @@ -0,0 +1,41 @@ +where('student_id', $data['student_id']) + ->where('id', '!=', $this->record->id) // ignore current record + ->exists(); + + if ($exists) { + Notification::make() + ->title('Failed to save') + ->body('An assessment for this teacher, subject, and student combination already exists.') + ->danger() + ->send(); + + $this->halt(); + } + + return $data; + } + + protected function getHeaderActions(): array + { + return [ + Actions\DeleteAction::make(), + ]; + } +} diff --git a/app/Filament/Resources/AssessmentResource/Pages/ListAssessments.php b/app/Filament/Resources/AssessmentResource/Pages/ListAssessments.php new file mode 100644 index 0000000..150f9d9 --- /dev/null +++ b/app/Filament/Resources/AssessmentResource/Pages/ListAssessments.php @@ -0,0 +1,23 @@ +label('Multiple Attendance') + ->url('assessments/multiple') + ->icon('heroicon-o-user-group'), + ]; + } +} diff --git a/app/Filament/Resources/AssessmentResource/Pages/MultipleAssessments.php b/app/Filament/Resources/AssessmentResource/Pages/MultipleAssessments.php new file mode 100644 index 0000000..ca44098 --- /dev/null +++ b/app/Filament/Resources/AssessmentResource/Pages/MultipleAssessments.php @@ -0,0 +1,129 @@ +form->fill(); + } + + protected function getFormSchema(): array + { + return [ + Forms\Components\Select::make('teacherSubjectId') + ->label('Teacher Subject') + ->options( + TeacherSubject::with(['teacher', 'subject', 'class'])->get()->mapWithKeys(function ($item) { + return [ + $item->id => "{$item->teacher->name} - {$item->subject->name} - {$item->class->class_name}" + ]; + })->toArray() + ) + ->searchable() + ->reactive() + ->afterStateUpdated(fn ($state) => $this->loadStudents()), + ]; + } + + public function loadStudents(): void + { + if (!$this->teacherSubjectId) { + $this->students = []; + return; + } + + $teacherSubject = TeacherSubject::find($this->teacherSubjectId); + + if (!$teacherSubject) { + $this->students = []; + + Notification::make() + ->title('Not Found') + ->body('Selected teacher subject not found.') + ->danger() + ->send(); + + return; + } + + $this->students = Student::where('class_id', $teacherSubject->class_id) + ->get() + ->map(function ($student) { + $existingAssessment = Assessment::where('student_id', $student->id) + ->where('teacher_subject_id', $this->teacherSubjectId) + ->first(); + + return [ + 'id' => $student->id, + 'name' => $student->full_name, + 'nis' => $student->nis, + 'score' => $existingAssessment ? $existingAssessment->score : null, + ]; + })->toArray(); + } + + public function submit(): void + { + if (!$this->teacherSubjectId || empty($this->students)) { + Notification::make() + ->title('Error') + ->body('Please select a teacher subject and enter student scores.') + ->danger() + ->send(); + return; + } + + foreach ($this->students as $student) { + if (!isset($student['score'])) continue; + + Assessment::updateOrCreate( + [ + 'student_id' => $student['id'], + 'teacher_subject_id' => $this->teacherSubjectId, + ], + [ + 'score' => $student['score'], + ] + ); + } + + Notification::make() + ->title('Success') + ->body('Assessments saved successfully.') + ->success() + ->send(); + } + + protected function getHeaderActions(): array + { + return [ + Actions\Action::make('back') + ->label('Back to Assessments') + ->url(static::getResource()::getUrl('index')), + ]; + } + +} diff --git a/app/Filament/Resources/AttendancesResource.php b/app/Filament/Resources/AttendancesResource.php index caa483e..266486e 100644 --- a/app/Filament/Resources/AttendancesResource.php +++ b/app/Filament/Resources/AttendancesResource.php @@ -20,7 +20,7 @@ class AttendancesResource extends Resource { protected static ?string $model = Attendances::class; protected static ?string $navigationIcon = 'heroicon-o-clipboard-document-check'; - protected static ?string $navigationGroup = 'Student Management'; + protected static ?string $navigationGroup = 'Academic Management'; public static function form(Form $form): Form { @@ -36,6 +36,15 @@ class AttendancesResource extends Resource $record->teacher->name . ' - ' . $record->subject->name . ' - ' . $record->class->class_name . ' - ' . $record->academic_year) ->searchable() ->preload() + ->afterStateUpdated(function (callable $set, $state) { + // Filter siswa berdasarkan kelas yang dipilih dalam teacher_subject_id + if ($state) { + $teacherSubject = TeacherSubject::find($state); + if ($teacherSubject) { + $set('student_id', null); // Reset student_id jika teacher_subject_id berubah + } + } + }) ->columnSpanFull(), Forms\Components\DatePicker::make('date') @@ -48,7 +57,20 @@ class AttendancesResource extends Resource ->label('Student') ->required() ->searchable() - ->options(Student::pluck('full_name', 'id')->toArray()) + // Filter opsi siswa berdasarkan kelas yang terkait dengan teacher_subject_id + ->options(function ($get) { + $teacherSubjectId = $get('teacher_subject_id'); + if ($teacherSubjectId) { + $teacherSubject = TeacherSubject::find($teacherSubjectId); + // Ambil siswa yang memiliki kelas yang sesuai dengan teacher_subject_id + $students = Student::where('class_id', $teacherSubject->class_id) + ->pluck('full_name', 'id') + ->toArray(); + + return $students; + } + return []; + }) ->getOptionLabelUsing(function ($value) { $student = Student::find($value); return $student ? $student->full_name . ' (' . $student->nis . ')' : null; diff --git a/app/Filament/Resources/AttendancesResource/Pages/CreateAttendances.php b/app/Filament/Resources/AttendancesResource/Pages/CreateAttendances.php index 44e1f36..8902724 100644 --- a/app/Filament/Resources/AttendancesResource/Pages/CreateAttendances.php +++ b/app/Filament/Resources/AttendancesResource/Pages/CreateAttendances.php @@ -3,10 +3,31 @@ namespace App\Filament\Resources\AttendancesResource\Pages; use App\Filament\Resources\AttendancesResource; +use App\Models\Assessment; use Filament\Actions; +use Filament\Notifications\Notification; use Filament\Resources\Pages\CreateRecord; class CreateAttendances extends CreateRecord { protected static string $resource = AttendancesResource::class; + + protected function mutateFormDataBeforeCreate(array $data): array + { + $exists = Assessment::where('teacher_subject_id', $data['teacher_subject_id']) + ->where('student_id', $data['student_id']) + ->exists(); + + if ($exists) { + Notification::make() + ->title('Failed to save') + ->body('A record for this teacher, subject, and student combination already exists.') + ->danger() + ->send(); + + $this->halt(); // Stop the save process + } + + return $data; + } } diff --git a/app/Filament/Resources/StudentResource.php b/app/Filament/Resources/StudentResource.php index fbeac86..7736d55 100644 --- a/app/Filament/Resources/StudentResource.php +++ b/app/Filament/Resources/StudentResource.php @@ -18,7 +18,7 @@ class StudentResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-users'; - protected static ?string $navigationGroup = 'Student Management'; + protected static ?string $navigationGroup = 'Academic Management'; public static function form(Form $form): Form { diff --git a/app/Filament/Resources/SubjectScopeResource.php b/app/Filament/Resources/SubjectScopeResource.php index 963d961..3aeca2a 100644 --- a/app/Filament/Resources/SubjectScopeResource.php +++ b/app/Filament/Resources/SubjectScopeResource.php @@ -19,7 +19,7 @@ class SubjectScopeResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; - protected static ?string $navigationGroup = 'Student Management'; + protected static ?string $navigationGroup = 'Academic Management'; public static function form(Form $form): Form { diff --git a/app/Models/Assessment.php b/app/Models/Assessment.php new file mode 100644 index 0000000..d2712be --- /dev/null +++ b/app/Models/Assessment.php @@ -0,0 +1,24 @@ +belongsTo(TeacherSubject::class); + } + + public function student() + { + return $this->belongsTo(Student::class); + } +} diff --git a/app/Models/AssessmentComponent.php b/app/Models/AssessmentComponent.php deleted file mode 100644 index eb404ce..0000000 --- a/app/Models/AssessmentComponent.php +++ /dev/null @@ -1,10 +0,0 @@ -can('view_any_assessment'); + } + + /** + * Determine whether the user can view the model. + */ + public function view(User $user, Assessment $assessment): bool + { + return $user->can('view_assessment'); + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return $user->can('create_assessment'); + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, Assessment $assessment): bool + { + return $user->can('update_assessment'); + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, Assessment $assessment): bool + { + return $user->can('delete_assessment'); + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, Assessment $assessment): bool + { + return $user->can('restore_assessment'); + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, Assessment $assessment): bool + { + return $user->can('force_delete_assessment'); + } +} diff --git a/app/Policies/AttendancesPolicy.php b/app/Policies/AttendancesPolicy.php new file mode 100644 index 0000000..81f5a17 --- /dev/null +++ b/app/Policies/AttendancesPolicy.php @@ -0,0 +1,65 @@ +can('view_any_attendances'); + } + + /** + * Determine whether the user can view the model. + */ + public function view(User $user, Attendances $attendances): bool + { + return $user->can('view_attendances'); + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return $user->can('create_attendances'); + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, Attendances $attendances): bool + { + return $user->can('update_attendances'); + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, Attendances $attendances): bool + { + return $user->can('delete_attendances'); + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, Attendances $attendances): bool + { + return $user->can('restore_attendances'); + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, Attendances $attendances): bool + { + return $user->can('force_delete_attendances'); + } +} diff --git a/app/Policies/ClassRoomPolicy.php b/app/Policies/ClassRoomPolicy.php new file mode 100644 index 0000000..8a563c7 --- /dev/null +++ b/app/Policies/ClassRoomPolicy.php @@ -0,0 +1,65 @@ +can('view_any_class::room'); + } + + /** + * Determine whether the user can view the model. + */ + public function view(User $user, ClassRoom $classRoom): bool + { + return $user->can('view_class::room'); + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return $user->can('create_class::room'); + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, ClassRoom $classRoom): bool + { + return $user->can('update_class::room'); + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, ClassRoom $classRoom): bool + { + return $user->can('delete_class::room'); + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, ClassRoom $classRoom): bool + { + return $user->can('restore_class::room'); + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, ClassRoom $classRoom): bool + { + return $user->can('force_delete_class::room'); + } +} diff --git a/app/Policies/ExtracurricularPolicy.php b/app/Policies/ExtracurricularPolicy.php new file mode 100644 index 0000000..3f62d45 --- /dev/null +++ b/app/Policies/ExtracurricularPolicy.php @@ -0,0 +1,65 @@ +can('view_any_extracurricular'); + } + + /** + * Determine whether the user can view the model. + */ + public function view(User $user, Extracurricular $extracurricular): bool + { + return $user->can('view_extracurricular'); + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return $user->can('create_extracurricular'); + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, Extracurricular $extracurricular): bool + { + return $user->can('update_extracurricular'); + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, Extracurricular $extracurricular): bool + { + return $user->can('delete_extracurricular'); + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, Extracurricular $extracurricular): bool + { + return $user->can('restore_extracurricular'); + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, Extracurricular $extracurricular): bool + { + return $user->can('force_delete_extracurricular'); + } +} diff --git a/app/Policies/StudentPolicy.php b/app/Policies/StudentPolicy.php new file mode 100644 index 0000000..5e748f6 --- /dev/null +++ b/app/Policies/StudentPolicy.php @@ -0,0 +1,65 @@ +can('view_any_student'); + } + + /** + * Determine whether the user can view the model. + */ + public function view(User $user, Student $student): bool + { + return $user->can('view_student'); + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return $user->can('create_student'); + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, Student $student): bool + { + return $user->can('update_student'); + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, Student $student): bool + { + return $user->can('delete_student'); + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, Student $student): bool + { + return $user->can('restore_student'); + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, Student $student): bool + { + return $user->can('force_delete_student'); + } +} diff --git a/app/Policies/SubjectPolicy.php b/app/Policies/SubjectPolicy.php new file mode 100644 index 0000000..efd906e --- /dev/null +++ b/app/Policies/SubjectPolicy.php @@ -0,0 +1,65 @@ +can('view_any_subject'); + } + + /** + * Determine whether the user can view the model. + */ + public function view(User $user, Subject $subject): bool + { + return $user->can('view_subject'); + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return $user->can('create_subject'); + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, Subject $subject): bool + { + return $user->can('update_subject'); + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, Subject $subject): bool + { + return $user->can('delete_subject'); + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, Subject $subject): bool + { + return $user->can('restore_subject'); + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, Subject $subject): bool + { + return $user->can('force_delete_subject'); + } +} diff --git a/app/Policies/SubjectScopePolicy.php b/app/Policies/SubjectScopePolicy.php new file mode 100644 index 0000000..fbad942 --- /dev/null +++ b/app/Policies/SubjectScopePolicy.php @@ -0,0 +1,65 @@ +can('view_any_subject_scope'); + } + + /** + * Determine whether the user can view the model. + */ + public function view(User $user, SubjectScope $subjectScope): bool + { + return $user->can('view_subject_scope'); + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return $user->can('create_subject_scope'); + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, SubjectScope $subjectScope): bool + { + return $user->can('update_subject_scope'); + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, SubjectScope $subjectScope): bool + { + return $user->can('delete_subject_scope'); + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, SubjectScope $subjectScope): bool + { + return $user->can('restore_subject_scope'); + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, SubjectScope $subjectScope): bool + { + return $user->can('force_delete_subject_scope'); + } +} diff --git a/app/Policies/TeacherSubjectPolicy.php b/app/Policies/TeacherSubjectPolicy.php new file mode 100644 index 0000000..4ed4761 --- /dev/null +++ b/app/Policies/TeacherSubjectPolicy.php @@ -0,0 +1,65 @@ +can('view_any_teacher_subject'); + } + + /** + * Determine whether the user can view the model. + */ + public function view(User $user, TeacherSubject $teacherSubject): bool + { + return $user->can('view_teacher_subject'); + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return $user->can('create_teacher_subject'); + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, TeacherSubject $teacherSubject): bool + { + return $user->can('update_teacher_subject'); + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, TeacherSubject $teacherSubject): bool + { + return $user->can('delete_teacher_subject'); + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, TeacherSubject $teacherSubject): bool + { + return $user->can('restore_teacher_subject'); + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, TeacherSubject $teacherSubject): bool + { + return $user->can('force_delete_teacher_subject'); + } +} diff --git a/database/migrations/2025_04_11_153224_create_assessment_components_table.php b/database/migrations/2025_04_30_125442_create_assessments_table.php similarity index 53% rename from database/migrations/2025_04_11_153224_create_assessment_components_table.php rename to database/migrations/2025_04_30_125442_create_assessments_table.php index ab21958..51a040c 100644 --- a/database/migrations/2025_04_11_153224_create_assessment_components_table.php +++ b/database/migrations/2025_04_30_125442_create_assessments_table.php @@ -11,13 +11,14 @@ return new class extends Migration */ public function up(): void { - Schema::create('assessment_components', function (Blueprint $table) { + Schema::create('assessments', function (Blueprint $table) { $table->id(); - $table->string('name'); - $table->string('code')->unique(); - $table->float('weight')->default(0); - $table->boolean('is_active')->default(true); + $table->foreignId('teacher_subject_id')->constrained('teacher_subjects'); + $table->foreignId('student_id')->constrained('students'); + $table->float('score'); $table->timestamps(); + + $table->unique(['teacher_subject_id', 'student_id']); }); } @@ -26,6 +27,6 @@ return new class extends Migration */ public function down(): void { - Schema::dropIfExists('assessment_components'); + Schema::dropIfExists('assessments'); } }; diff --git a/database/seeders/AssessmentComponentSeeder.php b/database/seeders/AssessmentComponentSeeder.php deleted file mode 100644 index 026ea97..0000000 --- a/database/seeders/AssessmentComponentSeeder.php +++ /dev/null @@ -1,28 +0,0 @@ - 'Ulangan Harian', 'code' => 'UH', 'weight' => 20, 'is_active' => true], - ['name' => 'Penilaian Tengah Semester', 'code' => 'PTS', 'weight' => 20, 'is_active' => true], - ['name' => 'Penilaian Akhir Semester', 'code' => 'PAS', 'weight' => 30, 'is_active' => true], - ['name' => 'Absensi', 'code' => 'ABS', 'weight' => 20, 'is_active' => true], - ['name' => 'Ekstrakurikuler', 'code' => 'EKS', 'weight' => 10, 'is_active' => true], - ]; - - foreach ($components as $component) { - AssessmentComponent::create($component); - } - } -} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 04490f1..edf7859 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -21,7 +21,6 @@ class DatabaseSeeder extends Seeder ClassRoomSeeder::class, StudentSeeder::class, ExtracurricularSeeder::class, - AssessmentComponentSeeder::class, AttendanceSeeder::class, ]); } diff --git a/resources/views/filament/resources/assessment-resource/pages/multiple-assessment.blade.php b/resources/views/filament/resources/assessment-resource/pages/multiple-assessment.blade.php new file mode 100644 index 0000000..9e05cef --- /dev/null +++ b/resources/views/filament/resources/assessment-resource/pages/multiple-assessment.blade.php @@ -0,0 +1,38 @@ + + + {{ $this->form }} + + @if($this->teacherSubjectId) +
+

Multiple Assessment

+ +
+ @foreach($this->students as $index => $student) +
+
+

{{ $student['name'] }}

+

{{ $student['nis'] }}

+
+
+ +
+
+ @endforeach +
+ +
+ + Save Assessments + +
+
+ @endif +
+