diff --git a/app/Filament/Pages/StudentReport.php b/app/Filament/Pages/StudentReport.php
new file mode 100644
index 0000000..7fd64c6
--- /dev/null
+++ b/app/Filament/Pages/StudentReport.php
@@ -0,0 +1,223 @@
+user()->hasAnyRole(['super_admin']);
+ }
+
+ public static function shouldRegisterNavigation(): bool
+ {
+ return auth()->user()->hasAnyRole(['super_admin']);
+ }
+
+ public function mount(): void
+ {
+ $this->class = null;
+ $this->academicYear = null;
+ $this->semester = null;
+ $this->data = [];
+ }
+
+ 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('academic_year')
+ ->label('Academic Year')
+ ->required()
+ ->options(AcademicYear::pluck('name', 'id')->toArray())
+ ->searchable()
+ ->reactive()
+ ->afterStateUpdated(function ($state) {
+ $this->academic_year = $state;
+ $this->data['academic_year'] = $state; // Update data array
+ $this->loadData();
+ }),
+
+ Select::make('semester')
+ ->label('Semester')
+ ->required()
+ ->options([
+ 'first' => 'First Semester',
+ 'second' => 'Second Semester'
+ ])
+ ->reactive()
+ ->afterStateUpdated(function ($state) {
+ $this->semester = $state;
+ $this->data['semester'] = $state;
+ $this->loadData();
+ }),
+ ])->columns(3);
+ }
+
+ protected function loadData(): void
+ {
+ if (count($this->data) < 3) {
+ $this->list = [];
+ return;
+ }
+
+ $groupedAssessment = [];
+
+ $assessments = Assessment::where('semester', $this->semester)
+ ->whereHas('teacherSubject', function($query) {
+ $query->where('academic_year_id', $this->academic_year)
+ ->where('class_id', $this->class_id);
+ })
+ ->with('teacherSubject', 'student')
+ ->get()
+ ->toArray();
+
+ $classSubjects = ClassSubject::with(['subject', 'class', 'academicYear'])
+ ->where('class_room_id', $this->class_id)
+ ->where('academic_year_id', $this->academic_year)
+ ->get()
+ ->sortByDesc(function ($item) {
+ return $item->subject->name;
+ })
+ ->toArray();
+
+ $header = [];
+
+ foreach ($classSubjects as $classSubject) {
+ $category = strtolower($classSubject['subject']['category']);
+ $subjectName = $classSubject['subject']['name'];
+ $subjectId = $classSubject['subject']['id'];
+ $header[$category][$subjectId] = $subjectName;
+ }
+
+ $students = ClassStudent::with(['class', 'academicYear', 'student'])
+ ->where('class_room_id', $this->class_id)
+ ->where('academic_year_id', $this->academic_year)
+ ->get()
+ ->map(function($student) {
+ return $student['student'];
+ })
+ ->toArray();
+
+ $finals = [];
+ foreach ($students as $student) {
+ $studentData = [
+ 'student_id' => $student['id'],
+ 'name' => $student['full_name'],
+ ];
+
+ foreach ($header as $category => $subjects) {
+ foreach ($subjects as $subjectId => $subjectName) {
+ $matchingAssessment = collect($assessments)->first(function ($a) use ($student, $subjectId) {
+ return $a['student_id'] == $student['id'] && $a['teacher_subject']['subject_id'] == $subjectId;
+ });
+
+ $studentData[$category][$subjectId] = $matchingAssessment['score'] ?? '-'; // atau null
+ }
+ }
+
+ $finals[] = $studentData;
+ }
+
+ $result = [];
+
+ foreach ($finals as $final => $fnl) {
+ $existStudent = Student::where('id', $fnl['student_id'])->firstOrFail();
+
+ $studentData = [
+ 'name' => $fnl['name'],
+ ];
+
+ $mapel = $fnl['umum'] ?? null;
+
+ if ($mapel) {
+ foreach ($mapel as $key => $value) {
+ $existSubject = Subject::where('id', $key)->firstOrFail();
+
+ if ($existSubject->is_religious) {
+ $studentReligion = strtolower($existStudent->religion); // contoh: "islam"
+ $subjectName = strtolower($existSubject->name); // contoh: "pendidikan agama islam"
+
+ if (str_contains($subjectName, $studentReligion)) {
+ // Hanya mapel agama yang sesuai dengan agama siswa dimasukkan ke umum[0]
+ $studentData['umum'][0] = $value;
+ }
+ // Mapel agama lain tidak dimasukkan sama sekali
+ } else {
+ $studentData['umum'][$key] = $value;
+ }
+ }
+ }
+
+ $studentData['muatan lokal'] = $fnl['muatan lokal'] ?? null;
+
+ $result[] = $studentData;
+ }
+
+ $groupedAssessment["data"] = $result;
+
+ $groupedSubjectsHeader = [];
+
+ $groupedSubjectsHeader['name'] = "Nama";
+
+ $religionAdded = false;
+
+ foreach ($classSubjects as $classSubject) {
+ $category = strtolower($classSubject['subject']['category']);
+ $subjectName = $classSubject['subject']['name'];
+ $isReligion = $classSubject['subject']['is_religious'];
+ $subjectId = $classSubject['subject']['id'];
+
+ if ($isReligion) {
+ if (!$religionAdded) {
+ $groupedSubjectsHeader['umum'][0] = 'Pendidikan Agama';
+ $religionAdded = true;
+ }
+ continue;
+ }
+
+ $groupedSubjectsHeader[$category][$subjectId] = $subjectName;
+ }
+
+ $groupedAssessment["header"] = $groupedSubjectsHeader;
+
+ $this->list = $groupedAssessment;
+ }
+}
diff --git a/app/Filament/Resources/AcademicYearResource.php b/app/Filament/Resources/AcademicYearResource.php
new file mode 100644
index 0000000..3971a1d
--- /dev/null
+++ b/app/Filament/Resources/AcademicYearResource.php
@@ -0,0 +1,105 @@
+schema([
+ Forms\Components\TextInput::make('name')
+ ->required()
+ ->placeholder("ex: 2024/2025")
+ ->maxLength(255),
+ Forms\Components\Toggle::make('is_active')
+ ->required(),
+ Forms\Components\DatePicker::make('start_date'),
+ Forms\Components\DatePicker::make('end_date'),
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('name')
+ ->searchable(),
+ Tables\Columns\IconColumn::make('is_active')
+ ->boolean(),
+ Tables\Columns\TextColumn::make('start_date')
+ ->date()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('end_date')
+ ->date()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('created_at')
+ ->dateTime()
+ ->sortable()
+ ->toggleable(isToggledHiddenByDefault: true),
+ Tables\Columns\TextColumn::make('updated_at')
+ ->dateTime()
+ ->sortable()
+ ->toggleable(isToggledHiddenByDefault: true),
+ Tables\Columns\TextColumn::make('deleted_at')
+ ->dateTime()
+ ->sortable()
+ ->toggleable(isToggledHiddenByDefault: true),
+ ])
+ ->filters([
+ Tables\Filters\TrashedFilter::make(),
+ ])
+ ->actions([
+ Tables\Actions\EditAction::make(),
+ ])
+ ->bulkActions([
+ Tables\Actions\BulkActionGroup::make([
+ Tables\Actions\DeleteBulkAction::make(),
+ Tables\Actions\ForceDeleteBulkAction::make(),
+ Tables\Actions\RestoreBulkAction::make(),
+ ]),
+ ])
+ ->emptyStateActions([
+ Tables\Actions\CreateAction::make(),
+ ]);
+ }
+
+ public static function getRelations(): array
+ {
+ return [
+ //
+ ];
+ }
+
+ public static function getPages(): array
+ {
+ return [
+ 'index' => Pages\ListAcademicYears::route('/'),
+ 'create' => Pages\CreateAcademicYear::route('/create'),
+ 'edit' => Pages\EditAcademicYear::route('/{record}/edit'),
+ ];
+ }
+
+ public static function getEloquentQuery(): Builder
+ {
+ return parent::getEloquentQuery()
+ ->withoutGlobalScopes([
+ SoftDeletingScope::class,
+ ]);
+ }
+}
diff --git a/app/Filament/Resources/AcademicYearResource/Pages/CreateAcademicYear.php b/app/Filament/Resources/AcademicYearResource/Pages/CreateAcademicYear.php
new file mode 100644
index 0000000..476eb31
--- /dev/null
+++ b/app/Filament/Resources/AcademicYearResource/Pages/CreateAcademicYear.php
@@ -0,0 +1,33 @@
+exists();
+
+ if ($exists) {
+ Notification::make()
+ ->title('Failed to save')
+ ->body('A record already exists.')
+ ->danger()
+ ->send();
+
+ $this->halt(); // Stop the save process
+ }
+
+ return $data;
+ }
+}
diff --git a/app/Filament/Resources/AcademicYearResource/Pages/EditAcademicYear.php b/app/Filament/Resources/AcademicYearResource/Pages/EditAcademicYear.php
new file mode 100644
index 0000000..aa85232
--- /dev/null
+++ b/app/Filament/Resources/AcademicYearResource/Pages/EditAcademicYear.php
@@ -0,0 +1,42 @@
+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 getHeaderActions(): array
+ {
+ return [
+ Actions\DeleteAction::make(),
+ Actions\ForceDeleteAction::make(),
+ Actions\RestoreAction::make(),
+ ];
+ }
+}
diff --git a/app/Filament/Resources/AcademicYearResource/Pages/ListAcademicYears.php b/app/Filament/Resources/AcademicYearResource/Pages/ListAcademicYears.php
new file mode 100644
index 0000000..5b44ba1
--- /dev/null
+++ b/app/Filament/Resources/AcademicYearResource/Pages/ListAcademicYears.php
@@ -0,0 +1,19 @@
+required()
->relationship('teacherSubject', 'id')
->getOptionLabelFromRecordUsing(fn (TeacherSubject $record) =>
- $record->teacher->name . ' - ' . $record->subject->name . ' - ' . $record->class->class_name . ' - ' . $record->academic_year)
+ $record->teacher->name . ' - ' . $record->subject->name . ' - ' . $record->class->class_name . ' - ' . $record->academicYear->name)
->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
+ $set('student_id', null);
}
}
})
@@ -51,14 +51,15 @@ class AssessmentResource extends Resource
->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')
+ $students = ClassStudent::where('class_room_id', $teacherSubject->class_id)
+ ->where('academic_year_id', $teacherSubject->academic_year_id)
+ ->with('student')
+ ->get()
+ ->pluck('student.full_name', 'id')
->toArray();
return $students;
@@ -68,8 +69,15 @@ class AssessmentResource extends Resource
->getOptionLabelUsing(function ($value) {
$student = Student::find($value);
return $student ? $student->full_name . ' (' . $student->nis . ')' : null;
- })
- ->required(),
+ }),
+
+ Forms\Components\Select::make('semester')
+ ->label('Semester')
+ ->required()
+ ->options([
+ 'first' => 'First Semester',
+ 'second' => 'Second Semester'
+ ]),
Forms\Components\TextInput::make('score')
->label('Score')
@@ -122,6 +130,9 @@ class AssessmentResource extends Resource
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
+ ])
+ ->emptyStateActions([
+ Tables\Actions\CreateAction::make(),
]);
}
diff --git a/app/Filament/Resources/AssessmentResource/Pages/ListAssessments.php b/app/Filament/Resources/AssessmentResource/Pages/ListAssessments.php
index 150f9d9..55d1e12 100644
--- a/app/Filament/Resources/AssessmentResource/Pages/ListAssessments.php
+++ b/app/Filament/Resources/AssessmentResource/Pages/ListAssessments.php
@@ -15,7 +15,7 @@ class ListAssessments extends ListRecords
return [
Actions\CreateAction::make(),
Actions\Action::make('multiple')
- ->label('Multiple Attendance')
+ ->label('Multiple Assessments')
->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
index ca44098..3e60223 100644
--- a/app/Filament/Resources/AssessmentResource/Pages/MultipleAssessments.php
+++ b/app/Filament/Resources/AssessmentResource/Pages/MultipleAssessments.php
@@ -5,13 +5,16 @@ namespace App\Filament\Resources\AssessmentResource\Pages;
use App\Filament\Resources\AssessmentResource;
use App\Models\Assessment;
use App\Models\Attendances;
+use App\Models\ClassStudent;
use Filament\Actions;
+use Filament\Forms\Components\Select;
use Filament\Resources\Pages\page;
use App\Models\Student;
use App\Models\TeacherSubject;
use Filament\Forms;
use Filament\Notifications\Notification;
use Illuminate\Support\Collection;
+use function Symfony\Component\Translation\t;
class MultipleAssessments extends page
{
@@ -21,10 +24,15 @@ class MultipleAssessments extends page
use Forms\Concerns\InteractsWithForms;
+ public ?array $data = [];
public ?int $teacherSubjectId = null;
+ public $teacherSubject;
+
public array $students = [];
+ public $semester = 'first';
+
public function mount(): void
{
$this->form->fill();
@@ -33,18 +41,38 @@ class MultipleAssessments extends page
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()),
+ Forms\Components\Grid::make(2)
+ ->schema([
+ Forms\Components\Select::make('teacherSubjectId')
+ ->label('Teacher Subject')
+ ->options(
+ TeacherSubject::with(['teacher', 'subject', 'class', 'academicYear'])->get()->mapWithKeys(function ($item) {
+ return [
+ $item->id => "{$item->teacher->name} - {$item->subject->name} - {$item->class->class_name} - {$item->academicYear->name}"
+ ];
+ })->toArray()
+ )
+ ->searchable()
+ ->reactive()
+ ->afterStateUpdated(function ($state) {
+ $this->teacherSubjectId = $state;
+ $this->loadStudents();
+ }),
+
+ Forms\Components\Select::make('semester')
+ ->label('Semester')
+ ->required()
+ ->default('first')
+ ->options([
+ 'first' => 'First Semester',
+ 'second' => 'Second Semester'
+ ])
+ ->live()
+ ->afterStateUpdated(function ($state) {
+ $this->semester = $state;
+ $this->loadStudents();
+ }),
+ ]),
];
}
@@ -55,34 +83,47 @@ class MultipleAssessments extends page
return;
}
- $teacherSubject = TeacherSubject::find($this->teacherSubjectId);
+ $this->teacherSubject = TeacherSubject::with(['subject','class','academicYear','teacher'])
+ ->where('id', $this->teacherSubjectId)
+ ->firstOrFail();
- if (!$teacherSubject) {
- $this->students = [];
+ $classStudents = ClassStudent::where('class_room_id', $this->teacherSubject->class_id)
+ ->where('academic_year_id', $this->teacherSubject->academic_year_id)
+ ->with('student')
+ ->get();
- Notification::make()
- ->title('Not Found')
- ->body('Selected teacher subject not found.')
- ->danger()
- ->send();
+ $isSubjectReligion = $this->teacherSubject->subject->is_religious;
+ $subjectName = strtolower($this->teacherSubject->subject->name);
- return;
+ $result = [];
+
+ foreach ($classStudents as $classStudent) {
+ $student = $classStudent->student;
+
+ if (!$student) continue; // Jaga-jaga kalau relasi student-nya null
+
+ $existingAssessment = Assessment::where('student_id', $student->id)
+ ->where('teacher_subject_id', $this->teacherSubjectId)
+ ->where('semester', $this->semester)
+ ->first();
+
+ if ($isSubjectReligion) {
+ $studentReligion = strtolower($student->religion);
+
+ if (!str_contains($subjectName, $studentReligion)) {
+ continue; // Skip kalau agama tidak cocok
+ }
+ }
+
+ $result[] = [
+ 'id' => $student->id,
+ 'name' => $student->full_name,
+ 'nis' => $student->nis,
+ 'score' => $existingAssessment ? $existingAssessment->score : null,
+ ];
}
- $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();
+ $this->students = $result;
}
public function submit(): void
@@ -106,6 +147,7 @@ class MultipleAssessments extends page
],
[
'score' => $student['score'],
+ 'semester' => $this->semester,
]
);
}
diff --git a/app/Filament/Resources/AttendancesResource.php b/app/Filament/Resources/AttendancesResource.php
index 266486e..af8bf6b 100644
--- a/app/Filament/Resources/AttendancesResource.php
+++ b/app/Filament/Resources/AttendancesResource.php
@@ -5,6 +5,7 @@ namespace App\Filament\Resources;
use App\Filament\Resources\AttendancesResource\Pages;
use App\Models\Attendances;
use App\Models\ClassRoom;
+use App\Models\ClassStudent;
use App\Models\Student;
use App\Models\Subject;
use App\Models\TeacherSubject;
@@ -26,22 +27,21 @@ class AttendancesResource extends Resource
{
return $form
->schema([
- Forms\Components\Section::make('Informasi Absensi')
+ Forms\Components\Section::make('Data Absensi')
->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)
+ $record->teacher->name . ' - ' . $record->subject->name . ' - ' . $record->class->class_name . ' - ' . $record->academicYear->name)
->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
+ $set('student_id', null);
}
}
})
@@ -51,20 +51,21 @@ class AttendancesResource extends Resource
->label('Date')
->required()
->default(now())
- ->maxDate(now()),
+ ->live(),
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')
+ $students = ClassStudent::where('class_room_id', $teacherSubject->class_id)
+ ->where('academic_year_id', $teacherSubject->academic_year_id)
+ ->with('student')
+ ->get()
+ ->pluck('student.full_name', 'id')
->toArray();
return $students;
@@ -153,7 +154,7 @@ class AttendancesResource extends Resource
'second' => 'Second Semester'
}),
- Tables\Columns\TextColumn::make('teacherSubject.academic_year')
+ Tables\Columns\TextColumn::make('teacherSubject.academicYear.name')
->label('Academic Year')
->searchable(),
diff --git a/app/Filament/Resources/AttendancesResource/Pages/EditAttendances.php b/app/Filament/Resources/AttendancesResource/Pages/EditAttendances.php
index 5a812a8..cd4df18 100644
--- a/app/Filament/Resources/AttendancesResource/Pages/EditAttendances.php
+++ b/app/Filament/Resources/AttendancesResource/Pages/EditAttendances.php
@@ -3,13 +3,36 @@
namespace App\Filament\Resources\AttendancesResource\Pages;
use App\Filament\Resources\AttendancesResource;
+use App\Models\Assessment;
+use App\Models\Attendances;
use Filament\Actions;
+use Filament\Notifications\Notification;
use Filament\Resources\Pages\EditRecord;
class EditAttendances extends EditRecord
{
protected static string $resource = AttendancesResource::class;
+ protected function mutateFormDataBeforeSave(array $data): array
+ {
+ $exists = Attendances::where('teacher_subject_id', $data['teacher_subject_id'])
+ ->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 [
diff --git a/app/Filament/Resources/AttendancesResource/Pages/MultipleAttendances.php b/app/Filament/Resources/AttendancesResource/Pages/MultipleAttendances.php
index ad36c6a..90058d0 100644
--- a/app/Filament/Resources/AttendancesResource/Pages/MultipleAttendances.php
+++ b/app/Filament/Resources/AttendancesResource/Pages/MultipleAttendances.php
@@ -3,8 +3,10 @@
namespace App\Filament\Resources\AttendancesResource\Pages;
use App\Filament\Resources\AttendancesResource;
+use App\Models\Assessment;
use App\Models\Attendances;
use App\Models\ClassRoom;
+use App\Models\ClassStudent;
use App\Models\Student;
use App\Models\TeacherSubject;
use Filament\Actions;
@@ -26,7 +28,8 @@ class MultipleAttendances extends Page
public $teacherSubject;
public $attendanceDate;
- public $semester = 'first'; // Default semester
+ public $semester = 'first';
+
public $students = [];
public function mount(): void
@@ -48,7 +51,7 @@ class MultipleAttendances extends Page
->options(TeacherSubject::with(['teacher', 'subject', 'class'])
->get()
->mapWithKeys(fn ($item) => [
- $item->id => $item->teacher->name . ' - ' . $item->subject->name . ' - ' . $item->class->class_name
+ $item->id => $item->teacher->name . ' - ' . $item->subject->name . ' - ' . $item->class->class_name . ' - ' . $item->academicYear->name
]))
->searchable()
->live()
@@ -61,7 +64,6 @@ class MultipleAttendances extends Page
->label('Attendance Date')
->required()
->default(now())
- ->maxDate(now())
->live()
->afterStateUpdated(function ($state) {
$this->attendanceDate = $state;
@@ -81,7 +83,8 @@ class MultipleAttendances extends Page
$this->loadStudents();
}),
])
- ->statePath('data');
+ ->statePath('data')
+ ->columns(3);
}
protected function loadStudents(): void
@@ -93,25 +96,67 @@ class MultipleAttendances extends Page
$this->teacherSubject = TeacherSubject::where('id', $this->teacherSubjectId)->firstOrFail();
- $this->students = Student::where('class_id', $this->teacherSubject->class_id)
- ->orderBy('full_name')
- ->get()
- ->map(function ($student) {
- $existingAttendance = Attendances::where('student_id', $student->id)
- ->where('teacher_subject_id', $this->teacherSubjectId)
- ->whereDate('date', $this->attendanceDate)
- ->where('semester', $this->semester)
- ->first();
+ $classStudents = ClassStudent::where('class_room_id', $this->teacherSubject->class_id)
+ ->where('academic_year_id', $this->teacherSubject->academic_year_id)
+ ->with('student')
+ ->get();
- return [
- 'id' => $student->id,
- 'name' => $student->full_name,
- 'nis' => $student->nis,
- 'status' => $existingAttendance ? $existingAttendance->status : null,
- 'attendance_id' => $existingAttendance ? $existingAttendance->id : null,
- ];
- })
- ->toArray();
+ $isSubjectReligion = $this->teacherSubject->subject->is_religious;
+ $subjectName = strtolower($this->teacherSubject->subject->name);
+
+ $result = [];
+
+ foreach ($classStudents as $classStudent) {
+ $student = $classStudent->student;
+
+ if (!$student) continue;
+
+ if ($isSubjectReligion) {
+ $studentReligion = strtolower($student->religion ?? '');
+
+ if (!str_contains($subjectName, $studentReligion)) {
+ continue;
+ }
+ }
+
+ $existingAttendance = Attendances::where('student_id', $student->id)
+ ->where('teacher_subject_id', $this->teacherSubjectId)
+ ->whereDate('date', $this->attendanceDate)
+ ->where('semester', $this->semester)
+ ->first();
+
+ $result[] = [
+ 'id' => $student->id,
+ 'name' => $student->full_name,
+ 'nis' => $student->nis,
+ 'status' => $existingAttendance ? $existingAttendance->status : null,
+ 'attendance_id' => $existingAttendance ? $existingAttendance->id : null,
+ ];
+ }
+
+ $this->students = $result;
+
+// $this->students = ClassStudent::where('class_room_id', $this->teacherSubjectId)
+// ->where('academic_year_id', $this->teacherSubject->academic_year_id)
+// ->with('student')
+// ->get()
+// ->map(function ($student) {
+// $existingAttendance = Attendances::where('student_id', $student->student_id)
+// ->where('teacher_subject_id', $this->teacherSubjectId)
+// ->whereDate('date', $this->attendanceDate)
+// ->where('semester', $this->semester)
+// ->first();
+//
+// return [
+// 'id' => $student->student->id,
+// 'name' => $student->student->full_name,
+// 'nis' => $student->student->nis,
+// 'status' => $existingAttendance ? $existingAttendance->status : null,
+// 'attendance_id' => $existingAttendance ? $existingAttendance->id : null,
+// ];
+// })
+// ->values()
+// ->toArray();
}
public function markAll($status): void
diff --git a/app/Filament/Resources/ClassRoomResource.php b/app/Filament/Resources/ClassRoomResource.php
index b1f13e2..194b4de 100644
--- a/app/Filament/Resources/ClassRoomResource.php
+++ b/app/Filament/Resources/ClassRoomResource.php
@@ -43,24 +43,6 @@ class ClassRoomResource extends Resource
'5' => 'Class 5',
'6' => 'Class 6',
]),
-
- Forms\Components\Select::make('homeroom_teacher_id')
- ->label('Homeroom Teacher')
- ->relationship(
- name: 'homeroomTeacher',
- titleAttribute: 'name',
- modifyQueryUsing: fn ($query) => $query->whereHas('roles', function ($q) {
- $q->where('name', 'teacher');
- }),
- )
- ->searchable()
- ->preload()
- ->required(),
- Forms\Components\TextInput::make('academic_year')
- ->label('Academic Year')
- ->required()
- ->placeholder('Example: 2023/2024')
- ->maxLength(9),
])->columns(2)
]);
}
@@ -73,10 +55,6 @@ class ClassRoomResource extends Resource
->searchable(),
Tables\Columns\TextColumn::make('class_level')
->searchable(),
- Tables\Columns\TextColumn::make('homeroomTeacher.name')
- ->label('Homeroom Teacher'),
- Tables\Columns\TextColumn::make('academic_year')
- ->searchable(),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
@@ -87,16 +65,28 @@ class ClassRoomResource extends Resource
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
- //
+ Tables\Filters\TrashedFilter::make(),
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
+ Tables\Actions\RestoreAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
+ ])
+ ->emptyStateActions([
+ Tables\Actions\CreateAction::make(),
+ ]);
+ }
+
+ public static function getEloquentQuery(): Builder
+ {
+ return parent::getEloquentQuery()
+ ->withoutGlobalScopes([
+ SoftDeletingScope::class,
]);
}
diff --git a/app/Filament/Resources/ClassStudentResource.php b/app/Filament/Resources/ClassStudentResource.php
new file mode 100644
index 0000000..127fde1
--- /dev/null
+++ b/app/Filament/Resources/ClassStudentResource.php
@@ -0,0 +1,112 @@
+schema([
+ Forms\Components\Select::make('class_room_id')
+ ->label('Class Room')
+ ->required()
+ ->options(ClassRoom::pluck('class_name', 'id')->toArray())
+ ->searchable()
+ ->native(false),
+
+ Forms\Components\Select::make('student_id')
+ ->label('Student')
+ ->required()
+ ->options(Student::pluck('full_name', 'id')->toArray())
+ ->searchable()
+ ->native(false),
+
+ Forms\Components\Select::make('academic_year_id')
+ ->label('Academic Year')
+ ->required()
+ ->options(AcademicYear::pluck('name', 'id')->toArray())
+ ->searchable()
+ ->native(false),
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('class.class_name')
+ ->label('Class Room')
+ ->numeric()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('student.full_name')
+ ->label('Student')
+ ->numeric()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('academicYear.name')
+ ->label('Academic Year')
+ ->numeric()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('created_at')
+ ->dateTime()
+ ->sortable()
+ ->toggleable(isToggledHiddenByDefault: true),
+ Tables\Columns\TextColumn::make('updated_at')
+ ->dateTime()
+ ->sortable()
+ ->toggleable(isToggledHiddenByDefault: true),
+ Tables\Columns\TextColumn::make('deleted_at')
+ ->dateTime()
+ ->sortable()
+ ->toggleable(isToggledHiddenByDefault: true),
+ ])
+ ->filters([
+ //
+ ])
+ ->actions([
+ Tables\Actions\EditAction::make(),
+ ])
+ ->bulkActions([
+ Tables\Actions\BulkActionGroup::make([
+ Tables\Actions\DeleteBulkAction::make(),
+ ]),
+ ])
+ ->emptyStateActions([
+ Tables\Actions\CreateAction::make(),
+ ]);
+ }
+
+ public static function getRelations(): array
+ {
+ return [
+ //
+ ];
+ }
+
+ public static function getPages(): array
+ {
+ return [
+ 'index' => Pages\ListClassStudents::route('/'),
+ 'create' => Pages\CreateClassStudent::route('/create'),
+ 'edit' => Pages\EditClassStudent::route('/{record}/edit'),
+ ];
+ }
+}
diff --git a/app/Filament/Resources/ClassStudentResource/Pages/CreateClassStudent.php b/app/Filament/Resources/ClassStudentResource/Pages/CreateClassStudent.php
new file mode 100644
index 0000000..e60ba80
--- /dev/null
+++ b/app/Filament/Resources/ClassStudentResource/Pages/CreateClassStudent.php
@@ -0,0 +1,35 @@
+where('student_id', $data['student_id'])
+ ->where('academic_year_id', $data['academic_year_id'])
+ ->exists();
+
+ if ($exists) {
+ Notification::make()
+ ->title('Failed to save')
+ ->body('A record for this class room, student, and academic year combination already exists.')
+ ->danger()
+ ->send();
+
+ $this->halt(); // Stop the save process
+ }
+
+ return $data;
+ }
+}
diff --git a/app/Filament/Resources/ClassStudentResource/Pages/EditClassStudent.php b/app/Filament/Resources/ClassStudentResource/Pages/EditClassStudent.php
new file mode 100644
index 0000000..02fd510
--- /dev/null
+++ b/app/Filament/Resources/ClassStudentResource/Pages/EditClassStudent.php
@@ -0,0 +1,41 @@
+where('student_id', $data['student_id'])
+ ->where('academic_year_id', $data['academic_year_id'])
+ ->exists();
+
+ if ($exists) {
+ Notification::make()
+ ->title('Failed to save')
+ ->body('A record for this class room, student, and academic year combination already exists.')
+ ->danger()
+ ->send();
+
+ $this->halt(); // Stop the save process
+ }
+
+ return $data;
+ }
+
+ protected function getHeaderActions(): array
+ {
+ return [
+ Actions\DeleteAction::make(),
+ ];
+ }
+}
diff --git a/app/Filament/Resources/ClassStudentResource/Pages/ListClassStudents.php b/app/Filament/Resources/ClassStudentResource/Pages/ListClassStudents.php
new file mode 100644
index 0000000..7c0daba
--- /dev/null
+++ b/app/Filament/Resources/ClassStudentResource/Pages/ListClassStudents.php
@@ -0,0 +1,19 @@
+schema([
+ Select::make('class_room_id')
+ ->label('Kelas')
+ ->relationship('class', 'class_name')
+ ->required(),
+
+ Select::make('subject_id')
+ ->label('Mata Pelajaran')
+ ->relationship('subject', 'name')
+ ->required(),
+
+ Select::make('academic_year_id')
+ ->label('Tahun Ajaran')
+ ->relationship('academicYear', 'name') // ganti "name" jika kolomnya berbeda
+ ->required(),
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ TextColumn::make('class.class_name')->label('Kelas')->sortable()->searchable(),
+ TextColumn::make('subject.name')->label('Mata Pelajaran')->sortable()->searchable(),
+ TextColumn::make('academicYear.name')->label('Tahun Ajaran')->sortable(),
+ ])
+ ->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\ListClassSubjects::route('/'),
+ 'create' => Pages\CreateClassSubject::route('/create'),
+ 'edit' => Pages\EditClassSubject::route('/{record}/edit'),
+ ];
+ }
+}
diff --git a/app/Filament/Resources/ClassSubjectResource/Pages/CreateClassSubject.php b/app/Filament/Resources/ClassSubjectResource/Pages/CreateClassSubject.php
new file mode 100644
index 0000000..289780d
--- /dev/null
+++ b/app/Filament/Resources/ClassSubjectResource/Pages/CreateClassSubject.php
@@ -0,0 +1,34 @@
+where('subject_id', $data['subject_id'])
+ ->where('academic_year_id', $data['academic_year_id'])
+ ->exists();
+
+ if ($exists) {
+ Notification::make()
+ ->title('Failed to save')
+ ->body('A record for this class, subject, and academic year combination already exists.')
+ ->danger()
+ ->send();
+
+ $this->halt(); // Stop the save process
+ }
+
+ return $data;
+ }
+}
diff --git a/app/Filament/Resources/ClassSubjectResource/Pages/EditClassSubject.php b/app/Filament/Resources/ClassSubjectResource/Pages/EditClassSubject.php
new file mode 100644
index 0000000..27b66e9
--- /dev/null
+++ b/app/Filament/Resources/ClassSubjectResource/Pages/EditClassSubject.php
@@ -0,0 +1,19 @@
+schema([
Forms\Components\Select::make('subject_id')
->label('Subject')
- ->options(
- fn () => \App\Models\Subject::pluck('name', 'id')->toArray()
- )
- ->searchable()
- ->required(),
- Forms\Components\TextInput::make('religion')
- ->maxLength(255),
- Forms\Components\TextInput::make('learning_goal')
->required()
- ->maxLength(255),
- Forms\Components\Textarea::make('scope')
+ ->options(Subject::pluck('name', 'id')->toArray())
+ ->searchable()
+ ->native(false),
+
+ Forms\Components\Select::make('class_room_id')
+ ->label('Class')
+ ->required()
+ ->options(ClassRoom::pluck('class_name', 'id')->toArray())
+ ->searchable()
+ ->native(false),
+
+ Forms\Components\TextInput::make('min_score')
+ ->required()
+ ->numeric()
+ ->default(0),
+ Forms\Components\TextInput::make('max_score')
+ ->required()
+ ->numeric()
+ ->default(0),
+ Forms\Components\Textarea::make('description')
->required()
->columnSpanFull(),
]);
@@ -50,10 +60,15 @@ class SubjectScopeResource extends Resource
Tables\Columns\TextColumn::make('subject.name')
->numeric()
->sortable(),
- Tables\Columns\TextColumn::make('religion')
- ->searchable(),
- Tables\Columns\TextColumn::make('learning_goal')
- ->searchable(),
+ Tables\Columns\TextColumn::make('classRoom.class_name')
+ ->numeric()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('min_score')
+ ->numeric()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('max_score')
+ ->numeric()
+ ->sortable(),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
@@ -68,11 +83,15 @@ class SubjectScopeResource extends Resource
])
->actions([
Tables\Actions\EditAction::make(),
+ Tables\Actions\ViewAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
+ ])
+ ->emptyStateActions([
+ Tables\Actions\CreateAction::make(),
]);
}
@@ -86,9 +105,9 @@ class SubjectScopeResource extends Resource
public static function getPages(): array
{
return [
- 'index' => Pages\ListSubjectScopes::route('/'),
- 'create' => Pages\CreateSubjectScope::route('/create'),
- 'edit' => Pages\EditSubjectScope::route('/{record}/edit'),
+ 'index' => Pages\ListCompetencyAchievements::route('/'),
+ 'create' => Pages\CreateCompetencyAchievement::route('/create'),
+ 'edit' => Pages\EditCompetencyAchievement::route('/{record}/edit'),
];
}
}
diff --git a/app/Filament/Resources/CompetencyAchievementResource/Pages/CreateCompetencyAchievement.php b/app/Filament/Resources/CompetencyAchievementResource/Pages/CreateCompetencyAchievement.php
new file mode 100644
index 0000000..86c6919
--- /dev/null
+++ b/app/Filament/Resources/CompetencyAchievementResource/Pages/CreateCompetencyAchievement.php
@@ -0,0 +1,12 @@
+actions([
- Tables\Actions\EditAction::make()->label('Edit'),
- Tables\Actions\DeleteAction::make()->label('Hapus'),
+ Tables\Actions\EditAction::make(),
+ Tables\Actions\DeleteAction::make(),
])
->bulkActions([
- Tables\Actions\DeleteBulkAction::make()->label('Hapus Massal'),
+ Tables\Actions\DeleteBulkAction::make(),
+ ])
+ ->emptyStateActions([
+ Tables\Actions\CreateAction::make(),
]);
}
public static function getRelations(): array
{
return [
- // Tambahkan RelationManager jika ada
+ //
];
}
diff --git a/app/Filament/Resources/HomeRoomTeacherResource.php b/app/Filament/Resources/HomeRoomTeacherResource.php
new file mode 100644
index 0000000..a94a57e
--- /dev/null
+++ b/app/Filament/Resources/HomeRoomTeacherResource.php
@@ -0,0 +1,109 @@
+schema([
+ Forms\Components\Select::make('class_room_id')
+ ->label('Class Room')
+ ->required()
+ ->options(ClassRoom::pluck('class_name', 'id')->toArray())
+ ->searchable()
+ ->native(false),
+
+ Forms\Components\Select::make('teacher_id')
+ ->label('Teacher')
+ ->required()
+ ->options(User::role('teacher')->pluck('name', 'id')->toArray())
+ ->searchable()
+ ->native(false),
+
+ Forms\Components\Select::make('academic_year_id')
+ ->label('Academic Year')
+ ->required()
+ ->options(AcademicYear::pluck('name', 'id')->toArray())
+ ->searchable()
+ ->native(false),
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('classRoom.class_name')
+ ->numeric()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('teacher.name')
+ ->numeric()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('academicYear.name')
+ ->numeric()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('created_at')
+ ->dateTime()
+ ->sortable()
+ ->toggleable(isToggledHiddenByDefault: true),
+ Tables\Columns\TextColumn::make('updated_at')
+ ->dateTime()
+ ->sortable()
+ ->toggleable(isToggledHiddenByDefault: true),
+ Tables\Columns\TextColumn::make('deleted_at')
+ ->dateTime()
+ ->sortable()
+ ->toggleable(isToggledHiddenByDefault: true),
+ ])
+ ->filters([
+ //
+ ])
+ ->actions([
+ Tables\Actions\EditAction::make(),
+ ])
+ ->bulkActions([
+ Tables\Actions\BulkActionGroup::make([
+ Tables\Actions\DeleteBulkAction::make(),
+ ]),
+ ])
+ ->emptyStateActions([
+ Tables\Actions\CreateAction::make(),
+ ]);
+ }
+
+ public static function getRelations(): array
+ {
+ return [
+ //
+ ];
+ }
+
+ public static function getPages(): array
+ {
+ return [
+ 'index' => Pages\ListHomeRoomTeachers::route('/'),
+ 'create' => Pages\CreateHomeRoomTeacher::route('/create'),
+ 'edit' => Pages\EditHomeRoomTeacher::route('/{record}/edit'),
+ ];
+ }
+}
diff --git a/app/Filament/Resources/HomeRoomTeacherResource/Pages/CreateHomeRoomTeacher.php b/app/Filament/Resources/HomeRoomTeacherResource/Pages/CreateHomeRoomTeacher.php
new file mode 100644
index 0000000..bc8e363
--- /dev/null
+++ b/app/Filament/Resources/HomeRoomTeacherResource/Pages/CreateHomeRoomTeacher.php
@@ -0,0 +1,35 @@
+where('teacher_id', $data['teacher_id'])
+ ->where('academic_year_id', $data['academic_year_id'])
+ ->exists();
+
+ if ($exists) {
+ Notification::make()
+ ->title('Failed to save')
+ ->body('A record for this class room, teacher, and academic year combination already exists.')
+ ->danger()
+ ->send();
+
+ $this->halt(); // Stop the save process
+ }
+
+ return $data;
+ }
+}
diff --git a/app/Filament/Resources/HomeRoomTeacherResource/Pages/EditHomeRoomTeacher.php b/app/Filament/Resources/HomeRoomTeacherResource/Pages/EditHomeRoomTeacher.php
new file mode 100644
index 0000000..e0b9da7
--- /dev/null
+++ b/app/Filament/Resources/HomeRoomTeacherResource/Pages/EditHomeRoomTeacher.php
@@ -0,0 +1,42 @@
+where('teacher_id', $data['teacher_id'])
+ ->where('academic_year_id', $data['academic_year_id'])
+ ->exists();
+
+ if ($exists) {
+ Notification::make()
+ ->title('Failed to save')
+ ->body('A record for this class room, teacher, and academic year combination already exists.')
+ ->danger()
+ ->send();
+
+ $this->halt(); // Stop the save process
+ }
+
+ return $data;
+ }
+
+ protected function getHeaderActions(): array
+ {
+ return [
+ Actions\DeleteAction::make(),
+ ];
+ }
+}
diff --git a/app/Filament/Resources/HomeRoomTeacherResource/Pages/ListHomeRoomTeachers.php b/app/Filament/Resources/HomeRoomTeacherResource/Pages/ListHomeRoomTeachers.php
new file mode 100644
index 0000000..7b5be4d
--- /dev/null
+++ b/app/Filament/Resources/HomeRoomTeacherResource/Pages/ListHomeRoomTeachers.php
@@ -0,0 +1,19 @@
+schema([
- Forms\Components\Section::make('Informasi Siswa')
+ Forms\Components\Section::make('Data Siswa')
->schema([
+ Forms\Components\TextInput::make('nisn')
+ ->label('NISN')
+ ->maxLength(20),
+
Forms\Components\TextInput::make('nis')
->label('NIS')
->required()
@@ -62,14 +66,6 @@ class StudentResource extends Resource
->email()
->maxLength(100),
- Forms\Components\Select::make('class_id')
- ->label('Class')
- ->options(
- fn () => \App\Models\ClassRoom::pluck('class_name', 'id')->toArray()
- )
- ->searchable()
- ->required(),
-
Forms\Components\TextInput::make('parent_name')
->label("Parent's Name")
->required()
@@ -79,9 +75,19 @@ class StudentResource extends Resource
->label("Parent's Phone")
->maxLength(15),
+ Forms\Components\Select::make('religion')
+ ->label('Religion')
+ ->options([
+ 'islam' => 'Islam',
+ 'hindu' => 'Hindu',
+ 'katolik' => 'Katolik',
+ 'kristen' => 'Kristen',
+ 'buddha' => 'Buddha',
+ ]),
+
Forms\Components\Textarea::make('address')
->label('Address')
- ->rows(3),
+ ->rows(1),
])
->columns(2),
@@ -107,12 +113,12 @@ class StudentResource extends Resource
Tables\Columns\TextColumn::make('birth_date')
->label('Birth Date')
->date(),
- Tables\Columns\TextColumn::make('classRoom.class_name')
- ->label('Class')
- ->sortable()
- ->searchable(),
Tables\Columns\TextColumn::make('parent_name')
->label("Parent's Name"),
+ Tables\Columns\TextColumn::make('religion')
+ ->label("Religion")
+ ->formatStateUsing(fn (string $state): string => strtoupper($state))
+ ->badge(),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
@@ -129,6 +135,9 @@ class StudentResource extends Resource
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
+ ])
+ ->emptyStateActions([
+ Tables\Actions\CreateAction::make(),
]);
}
diff --git a/app/Filament/Resources/SubjectResource.php b/app/Filament/Resources/SubjectResource.php
index e7c475f..0eed1a2 100644
--- a/app/Filament/Resources/SubjectResource.php
+++ b/app/Filament/Resources/SubjectResource.php
@@ -28,8 +28,18 @@ class SubjectResource extends Resource
Forms\Components\TextInput::make('name')
->required()
->maxLength(255),
+
Forms\Components\Toggle::make('is_religious')
->required(),
+
+ Forms\Components\Select::make('category')
+ ->options([
+ 'umum' => 'Umum',
+ 'muatan lokal' => 'Muatan Lokal',
+ 'seni' => 'Seni',
+ ])
+ ->required(),
+
]);
}
@@ -38,9 +48,14 @@ class SubjectResource extends Resource
return $table
->columns([
Tables\Columns\TextColumn::make('name')
+ ->label("Name")
->searchable(),
Tables\Columns\IconColumn::make('is_religious')
+ ->label("Is Religious")
->boolean(),
+ Tables\Columns\TextColumn::make('category')
+ ->label("Category")
+ ->sortable(),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
@@ -60,6 +75,9 @@ class SubjectResource extends Resource
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
+ ])
+ ->emptyStateActions([
+ Tables\Actions\CreateAction::make(),
]);
}
diff --git a/app/Filament/Resources/SubjectScopeResource/Pages/CreateSubjectScope.php b/app/Filament/Resources/SubjectScopeResource/Pages/CreateSubjectScope.php
deleted file mode 100644
index ad960bb..0000000
--- a/app/Filament/Resources/SubjectScopeResource/Pages/CreateSubjectScope.php
+++ /dev/null
@@ -1,12 +0,0 @@
-searchable()
->native(false),
- Forms\Components\TextInput::make('academic_year')
+ Forms\Components\Select::make('academic_year_id')
->label('Academic Year')
->required()
- ->placeholder('e.g. 2023/2024')
- ->maxLength(9),
+ ->options(AcademicYear::pluck('name', 'id')->toArray())
+ ->searchable()
+ ->native(false),
])
->columns(2),
@@ -80,7 +82,7 @@ class TeacherSubjectResource extends Resource
->searchable()
->sortable(),
- Tables\Columns\TextColumn::make('academic_year')
+ Tables\Columns\TextColumn::make('academicYear.name')
->label('Academic Year')
->searchable()
->sortable(),
diff --git a/app/Filament/Resources/TeacherSubjectResource/Pages/CreateTeacherSubject.php b/app/Filament/Resources/TeacherSubjectResource/Pages/CreateTeacherSubject.php
index ea8ec15..74f1182 100644
--- a/app/Filament/Resources/TeacherSubjectResource/Pages/CreateTeacherSubject.php
+++ b/app/Filament/Resources/TeacherSubjectResource/Pages/CreateTeacherSubject.php
@@ -17,7 +17,7 @@ class CreateTeacherSubject extends CreateRecord
$exists = TeacherSubject::where('teacher_id', $data['teacher_id'])
->where('subject_id', $data['subject_id'])
->where('class_id', $data['class_id'])
- ->where('academic_year', $data['academic_year'])
+ ->where('academic_year_id', $data['academic_year_id'])
->exists();
if ($exists) {
diff --git a/app/Filament/Resources/UserResource.php b/app/Filament/Resources/UserResource.php
index 481321d..4fdd054 100644
--- a/app/Filament/Resources/UserResource.php
+++ b/app/Filament/Resources/UserResource.php
@@ -73,8 +73,11 @@ class UserResource extends Resource
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
- Tables\Actions\DeleteBulkAction::make(),
+// Tables\Actions\DeleteBulkAction::make(),
]),
+ ])
+ ->emptyStateActions([
+ Tables\Actions\CreateAction::make(),
]);
}
diff --git a/app/Models/AcademicYear.php b/app/Models/AcademicYear.php
new file mode 100644
index 0000000..6102f97
--- /dev/null
+++ b/app/Models/AcademicYear.php
@@ -0,0 +1,34 @@
+hasMany(HomeRoomTeacher::class);
+ }
+
+ public function teacherSubject(): HasMany
+ {
+ return $this->hasMany(TeacherSubject::class, 'academic_year_id');
+ }
+
+ public function classStudents()
+ {
+ return $this->hasMany(ClassStudent::class);
+ }
+
+ public function classSubjects()
+ {
+ return $this->hasMany(ClassStudent::class);
+ }
+}
diff --git a/app/Models/Assessment.php b/app/Models/Assessment.php
index d2712be..416e738 100644
--- a/app/Models/Assessment.php
+++ b/app/Models/Assessment.php
@@ -10,6 +10,7 @@ class Assessment extends Model
'teacher_subject_id',
'student_id',
'score',
+ 'semester'
];
public function teacherSubject()
diff --git a/app/Models/ClassRoom.php b/app/Models/ClassRoom.php
index f619c36..ac91530 100644
--- a/app/Models/ClassRoom.php
+++ b/app/Models/ClassRoom.php
@@ -4,28 +4,44 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
+use Illuminate\Database\Eloquent\SoftDeletes;
class ClassRoom extends Model
{
+ use SoftDeletes;
+
protected $fillable = [
'class_name',
'class_level',
- 'homeroom_teacher_id',
- 'academic_year'
];
public function homeroomTeacher()
{
- return $this->belongsTo(User::class, 'homeroom_teacher_id');
+ return $this->hasMany(HomeRoomTeacher::class);
}
public function students()
{
- return $this->hasMany(Student::class, 'class_id');
+ return $this->hasMany(Student::class);
}
public function teacherAssignments(): HasMany
{
- return $this->hasMany(TeacherSubject::class, 'class_id');
+ return $this->hasMany(TeacherSubject::class);
+ }
+
+ public function competencyAchievements()
+ {
+ return $this->hasMany(CompetencyAchievement::class);
+ }
+
+ public function classStudents()
+ {
+ return $this->hasMany(ClassStudent::class);
+ }
+
+ public function classSubjects(): HasMany
+ {
+ return $this->hasMany(ClassSubject::class);
}
}
diff --git a/app/Models/ClassStudent.php b/app/Models/ClassStudent.php
new file mode 100644
index 0000000..8a007e8
--- /dev/null
+++ b/app/Models/ClassStudent.php
@@ -0,0 +1,28 @@
+belongsTo(ClassRoom::class, 'class_room_id');
+ }
+
+ public function student()
+ {
+ return $this->belongsTo(Student::class, 'student_id');
+ }
+
+ public function academicYear()
+ {
+ return $this->belongsTo(AcademicYear::class, 'academic_year_id');
+ }
+}
diff --git a/app/Models/ClassSubject.php b/app/Models/ClassSubject.php
new file mode 100644
index 0000000..76d4525
--- /dev/null
+++ b/app/Models/ClassSubject.php
@@ -0,0 +1,27 @@
+belongsTo(Subject::class, 'subject_id');
+ }
+
+ public function class(): BelongsTo
+ {
+ return $this->belongsTo(ClassRoom::class, 'class_room_id');
+ }
+
+ public function academicYear(): BelongsTo
+ {
+ return $this->belongsTo(AcademicYear::class, 'academic_year_id');
+ }
+}
diff --git a/app/Models/CompetencyAchievement.php b/app/Models/CompetencyAchievement.php
new file mode 100644
index 0000000..29c13e4
--- /dev/null
+++ b/app/Models/CompetencyAchievement.php
@@ -0,0 +1,31 @@
+belongsTo(Subject::class, 'subject_id');
+ }
+
+ // Relasi ke ClassRoom
+ public function classRoom()
+ {
+ return $this->belongsTo(ClassRoom::class, 'class_room_id');
+ }
+}
diff --git a/app/Models/HomeRoomTeacher.php b/app/Models/HomeRoomTeacher.php
new file mode 100644
index 0000000..fa75b47
--- /dev/null
+++ b/app/Models/HomeRoomTeacher.php
@@ -0,0 +1,28 @@
+belongsTo(ClassRoom::class, 'class_room_id');
+ }
+
+ public function teacher()
+ {
+ return $this->belongsTo(User::class, 'teacher_id');
+ }
+
+ public function academicYear()
+ {
+ return $this->belongsTo(AcademicYear::class, 'academic_year_id');
+ }
+}
diff --git a/app/Models/Student.php b/app/Models/Student.php
index 0ef2d6e..17295fb 100644
--- a/app/Models/Student.php
+++ b/app/Models/Student.php
@@ -17,18 +17,17 @@ class Student extends Model
'religion',
'phone',
'email',
- 'class_id',
'parent_name',
'parent_phone',
+ 'is_active',
];
protected $casts = [
'birth_date' => 'date',
];
- // Relasi dengan kelas
- public function classRoom()
+ public function classStudents()
{
- return $this->belongsTo(ClassRoom::class, 'class_id');
+ return $this->hasMany(ClassStudent::class);
}
}
diff --git a/app/Models/Subject.php b/app/Models/Subject.php
index 31bd242..e44b863 100644
--- a/app/Models/Subject.php
+++ b/app/Models/Subject.php
@@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
class Subject extends Model
{
- protected $fillable = ['name', 'is_religious'];
+ protected $fillable = ['name', 'is_religious', 'category'];
public function scopes()
{
@@ -16,12 +16,16 @@ class Subject extends Model
public function teacherAssignments(): HasMany
{
- return $this->hasMany(TeacherSubject::class, 'subject_id');
+ return $this->hasMany(TeacherSubject::class);
}
+ public function competencyAchievements()
+ {
+ return $this->hasMany(CompetencyAchievement::class);
+ }
-// public function grades()
-// {
-// return $this->hasMany(Grade::class);
-// }
+ public function classSubjects(): HasMany
+ {
+ return $this->hasMany(ClassSubject::class);
+ }
}
diff --git a/app/Models/SubjectScope.php b/app/Models/SubjectScope.php
deleted file mode 100644
index 4811af9..0000000
--- a/app/Models/SubjectScope.php
+++ /dev/null
@@ -1,15 +0,0 @@
-belongsTo(Subject::class);
- }
-}
diff --git a/app/Models/TeacherSubject.php b/app/Models/TeacherSubject.php
index 72b5f88..4f828b3 100644
--- a/app/Models/TeacherSubject.php
+++ b/app/Models/TeacherSubject.php
@@ -4,53 +4,34 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\Relations\HasMany;
class TeacherSubject extends Model
{
- protected $fillable = ['teacher_id', 'subject_id', 'class_id', 'academic_year'];
+ protected $fillable = ['teacher_id', 'subject_id', 'class_id', 'academic_year_id'];
- /**
- * Get the teacher associated with this assignment
- */
public function teacher(): BelongsTo
{
return $this->belongsTo(User::class, 'teacher_id');
}
- /**
- * Get the subject associated with this assignment
- */
public function subject(): BelongsTo
{
return $this->belongsTo(Subject::class, 'subject_id');
}
- /**
- * Get the class associated with this assignment
- */
public function class(): BelongsTo
{
return $this->belongsTo(ClassRoom::class, 'class_id');
}
- /**
- * Scope for current academic year
- */
- public function scopeCurrentYear($query)
- {
- return $query->where('academic_year', now()->format('Y'));
- }
-
- /**
- * Scope for specific academic year
- */
- public function scopeForYear($query, $year)
- {
- return $query->where('academic_year', $year);
- }
-
public function attendances()
{
return $this->hasMany(Attendances::class);
}
+
+ public function academicYear() : BelongsTo
+ {
+ return $this->belongsTo(AcademicYear::class, 'academic_year_id');
+ }
}
diff --git a/app/Models/User.php b/app/Models/User.php
index 7f5ed38..c56ea0c 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -57,4 +57,9 @@ class User extends Authenticatable
{
return $this->hasMany(TeacherSubject::class, 'teacher_id');
}
+
+ public function homeRoomTeacher(): HasMany
+ {
+ return $this->hasMany(HomeRoomTeacher::class, 'teacher_id');
+ }
}
diff --git a/app/Policies/SubjectScopePolicy.php b/app/Policies/SubjectScopePolicy.php
index fbad942..1a95c02 100644
--- a/app/Policies/SubjectScopePolicy.php
+++ b/app/Policies/SubjectScopePolicy.php
@@ -12,7 +12,7 @@ class SubjectScopePolicy
*/
public function viewAny(User $user): bool
{
- return $user->can('view_any_subject_scope');
+ return $user->can('view_any_subject::scope');
}
/**
@@ -20,7 +20,7 @@ class SubjectScopePolicy
*/
public function view(User $user, SubjectScope $subjectScope): bool
{
- return $user->can('view_subject_scope');
+ return $user->can('view_subject::scope');
}
/**
@@ -28,7 +28,7 @@ class SubjectScopePolicy
*/
public function create(User $user): bool
{
- return $user->can('create_subject_scope');
+ return $user->can('create_subject::scope');
}
/**
@@ -36,7 +36,7 @@ class SubjectScopePolicy
*/
public function update(User $user, SubjectScope $subjectScope): bool
{
- return $user->can('update_subject_scope');
+ return $user->can('update_subject::scope');
}
/**
@@ -44,7 +44,7 @@ class SubjectScopePolicy
*/
public function delete(User $user, SubjectScope $subjectScope): bool
{
- return $user->can('delete_subject_scope');
+ return $user->can('delete_subject::scope');
}
/**
@@ -52,7 +52,7 @@ class SubjectScopePolicy
*/
public function restore(User $user, SubjectScope $subjectScope): bool
{
- return $user->can('restore_subject_scope');
+ return $user->can('restore_subject::scope');
}
/**
@@ -60,6 +60,6 @@ class SubjectScopePolicy
*/
public function forceDelete(User $user, SubjectScope $subjectScope): bool
{
- return $user->can('force_delete_subject_scope');
+ return $user->can('force_delete_subject::scope');
}
}
diff --git a/app/Policies/TeacherSubjectPolicy.php b/app/Policies/TeacherSubjectPolicy.php
index 4ed4761..f842648 100644
--- a/app/Policies/TeacherSubjectPolicy.php
+++ b/app/Policies/TeacherSubjectPolicy.php
@@ -12,7 +12,7 @@ class TeacherSubjectPolicy
*/
public function viewAny(User $user): bool
{
- return $user->can('view_any_teacher_subject');
+ return $user->can('view_any_teacher::subject');
}
/**
@@ -20,7 +20,7 @@ class TeacherSubjectPolicy
*/
public function view(User $user, TeacherSubject $teacherSubject): bool
{
- return $user->can('view_teacher_subject');
+ return $user->can('view_teacher::subject');
}
/**
@@ -28,7 +28,7 @@ class TeacherSubjectPolicy
*/
public function create(User $user): bool
{
- return $user->can('create_teacher_subject');
+ return $user->can('create_teacher::subject');
}
/**
@@ -36,7 +36,7 @@ class TeacherSubjectPolicy
*/
public function update(User $user, TeacherSubject $teacherSubject): bool
{
- return $user->can('update_teacher_subject');
+ return $user->can('update_teacher::subject');
}
/**
@@ -44,7 +44,7 @@ class TeacherSubjectPolicy
*/
public function delete(User $user, TeacherSubject $teacherSubject): bool
{
- return $user->can('delete_teacher_subject');
+ return $user->can('delete_teacher::subject');
}
/**
@@ -52,7 +52,7 @@ class TeacherSubjectPolicy
*/
public function restore(User $user, TeacherSubject $teacherSubject): bool
{
- return $user->can('restore_teacher_subject');
+ return $user->can('restore_teacher::subject');
}
/**
@@ -60,6 +60,6 @@ class TeacherSubjectPolicy
*/
public function forceDelete(User $user, TeacherSubject $teacherSubject): bool
{
- return $user->can('force_delete_teacher_subject');
+ return $user->can('force_delete_teacher::subject');
}
}
diff --git a/database/migrations/2025_04_10_000425_create_class_rooms_table.php b/database/migrations/2025_04_10_000425_create_class_rooms_table.php
index d2efcf2..40b6e1e 100644
--- a/database/migrations/2025_04_10_000425_create_class_rooms_table.php
+++ b/database/migrations/2025_04_10_000425_create_class_rooms_table.php
@@ -15,9 +15,10 @@ return new class extends Migration
$table->id();
$table->string('class_name');
$table->string('class_level');
- $table->foreignId('homeroom_teacher_id')->nullable()->constrained('users');
- $table->string('academic_year');
$table->timestamps();
+
+ $table->softDeletes();
+ $table->unique(['class_name', 'class_level']);
});
}
diff --git a/database/migrations/2025_04_10_000426_create_students_table.php b/database/migrations/2025_04_10_000426_create_students_table.php
index df567bb..28ab720 100644
--- a/database/migrations/2025_04_10_000426_create_students_table.php
+++ b/database/migrations/2025_04_10_000426_create_students_table.php
@@ -23,10 +23,13 @@ return new class extends Migration
$table->text('religion')->nullable();
$table->string('phone')->nullable();
$table->string('email')->nullable();
- $table->foreignId('class_id')->nullable()->constrained('class_rooms');
$table->string('parent_name')->nullable();
$table->string('parent_phone')->nullable();
+ $table->boolean('is_active')->default(true);
$table->timestamps();
+
+ $table->softDeletes();
+ $table->unique(['nis', 'nisn']);
});
}
diff --git a/database/migrations/2025_04_10_151152_create_subject_scopes_table.php b/database/migrations/2025_04_10_000427_create_academic_years_table.php
similarity index 51%
rename from database/migrations/2025_04_10_151152_create_subject_scopes_table.php
rename to database/migrations/2025_04_10_000427_create_academic_years_table.php
index f70d7a5..d407b0a 100644
--- a/database/migrations/2025_04_10_151152_create_subject_scopes_table.php
+++ b/database/migrations/2025_04_10_000427_create_academic_years_table.php
@@ -11,13 +11,16 @@ return new class extends Migration
*/
public function up(): void
{
- Schema::create('subject_scopes', function (Blueprint $table) {
+ Schema::create('academic_years', function (Blueprint $table) {
$table->id();
- $table->foreignId('subject_id')->constrained()->onDelete('cascade');
- $table->string('religion')->nullable(); // null jika bukan mapel agama
- $table->string('learning_goal');
- $table->text('scope');
+ $table->string('name'); // contoh: 2024/2025
+ $table->boolean('is_active')->default(false);
+ $table->date('start_date')->nullable();
+ $table->date('end_date')->nullable();
$table->timestamps();
+
+ $table->softDeletes();
+ $table->unique(['name']);
});
}
@@ -26,6 +29,6 @@ return new class extends Migration
*/
public function down(): void
{
- Schema::dropIfExists('subject_scopes');
+ Schema::dropIfExists('academic_years');
}
};
diff --git a/database/migrations/2025_04_10_151020_create_subjects_table.php b/database/migrations/2025_04_10_151020_create_subjects_table.php
index 5772701..a4f58fc 100644
--- a/database/migrations/2025_04_10_151020_create_subjects_table.php
+++ b/database/migrations/2025_04_10_151020_create_subjects_table.php
@@ -15,7 +15,10 @@ return new class extends Migration
$table->id();
$table->string('name');
$table->boolean('is_religious')->default(false);
+ $table->enum('category', ['umum', 'muatan lokal', 'seni']);
$table->timestamps();
+
+ $table->unique(['name', 'is_religious', 'category']);
});
}
diff --git a/database/migrations/2025_04_13_010342_create_teacher_subjects_table.php b/database/migrations/2025_04_13_010342_create_teacher_subjects_table.php
index 16d4b6a..0a515e6 100644
--- a/database/migrations/2025_04_13_010342_create_teacher_subjects_table.php
+++ b/database/migrations/2025_04_13_010342_create_teacher_subjects_table.php
@@ -16,10 +16,10 @@ return new class extends Migration
$table->foreignId('teacher_id')->constrained('users');
$table->foreignId('subject_id')->constrained('subjects');
$table->foreignId('class_id')->constrained('class_rooms');
- $table->string('academic_year');
+ $table->foreignId('academic_year_id')->constrained('academic_years');
$table->timestamps();
- $table->unique(['teacher_id', 'subject_id', 'class_id', 'academic_year']);
+ $table->unique(['teacher_id', 'subject_id', 'class_id', 'academic_year_id']);
});
}
diff --git a/database/migrations/2025_04_30_125442_create_assessments_table.php b/database/migrations/2025_04_30_125442_create_assessments_table.php
index 51a040c..123f8a2 100644
--- a/database/migrations/2025_04_30_125442_create_assessments_table.php
+++ b/database/migrations/2025_04_30_125442_create_assessments_table.php
@@ -16,9 +16,10 @@ return new class extends Migration
$table->foreignId('teacher_subject_id')->constrained('teacher_subjects');
$table->foreignId('student_id')->constrained('students');
$table->float('score');
+ $table->string('semester');
$table->timestamps();
- $table->unique(['teacher_subject_id', 'student_id']);
+ $table->unique(['teacher_subject_id', 'student_id', 'semester']);
});
}
diff --git a/database/migrations/2025_05_03_091105_create_competency_achievements_table.php b/database/migrations/2025_05_03_091105_create_competency_achievements_table.php
new file mode 100644
index 0000000..bb23304
--- /dev/null
+++ b/database/migrations/2025_05_03_091105_create_competency_achievements_table.php
@@ -0,0 +1,34 @@
+id();
+ $table->foreignId('subject_id')->constrained('subjects');
+ $table->foreignId('class_room_id')->constrained('class_rooms');
+ $table->float("min_score")->default(0);
+ $table->float("max_score")->default(0);
+ $table->text("description");
+ $table->timestamps();
+
+ $table->softDeletes();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('competency_achievements');
+ }
+};
diff --git a/database/migrations/2025_05_04_120638_create_home_room_teachers_table.php b/database/migrations/2025_05_04_120638_create_home_room_teachers_table.php
new file mode 100644
index 0000000..2208625
--- /dev/null
+++ b/database/migrations/2025_05_04_120638_create_home_room_teachers_table.php
@@ -0,0 +1,33 @@
+id();
+ $table->foreignId('class_room_id')->constrained('class_rooms');
+ $table->foreignId('teacher_id')->constrained('users');
+ $table->foreignId('academic_year_id')->constrained('academic_years');
+ $table->timestamps();
+
+ $table->unique(['class_room_id', 'teacher_id', 'academic_year_id']);
+ $table->softDeletes();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('home_room_teachers');
+ }
+};
diff --git a/database/migrations/2025_05_04_121938_create_class_students_table.php b/database/migrations/2025_05_04_121938_create_class_students_table.php
new file mode 100644
index 0000000..b0665fc
--- /dev/null
+++ b/database/migrations/2025_05_04_121938_create_class_students_table.php
@@ -0,0 +1,33 @@
+id();
+ $table->foreignId('class_room_id')->constrained('class_rooms');
+ $table->foreignId('student_id')->constrained('students');
+ $table->foreignId('academic_year_id')->constrained('academic_years');
+ $table->timestamps();
+
+ $table->unique(['class_room_id', 'student_id', 'academic_year_id']);
+ $table->softDeletes();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('class_students');
+ }
+};
diff --git a/database/migrations/2025_05_06_041554_create_class_subjects_table.php b/database/migrations/2025_05_06_041554_create_class_subjects_table.php
new file mode 100644
index 0000000..85bd9c0
--- /dev/null
+++ b/database/migrations/2025_05_06_041554_create_class_subjects_table.php
@@ -0,0 +1,33 @@
+id();
+ $table->foreignId('class_room_id')->constrained('class_rooms');
+ $table->foreignId('subject_id')->constrained('subjects');
+ $table->foreignId('academic_year_id')->constrained('academic_years');
+ $table->timestamps();
+
+ $table->softDeletes();
+ $table->unique(['class_room_id', 'subject_id', 'academic_year_id']);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('class_subjects');
+ }
+};
diff --git a/database/seeders/AcademicYearSeeder.php b/database/seeders/AcademicYearSeeder.php
new file mode 100644
index 0000000..a4682d4
--- /dev/null
+++ b/database/seeders/AcademicYearSeeder.php
@@ -0,0 +1,36 @@
+insert([
+ [
+ 'name' => '2023/2024',
+ 'is_active' => false,
+ 'start_date' => Carbon::create(2023, 7, 1),
+ 'end_date' => Carbon::create(2024, 6, 30),
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'name' => '2024/2025',
+ 'is_active' => true,
+ 'start_date' => Carbon::create(2024, 7, 1),
+ 'end_date' => Carbon::create(2025, 6, 30),
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+ }
+}
diff --git a/database/seeders/AttendanceSeeder.php b/database/seeders/AttendanceSeeder.php
deleted file mode 100644
index 2605c7b..0000000
--- a/database/seeders/AttendanceSeeder.php
+++ /dev/null
@@ -1,17 +0,0 @@
-get();
$classes = [
- ['class_name' => '1 A', 'class_level' => '1', 'academic_year' => '2024/2025'],
- ['class_name' => '1 B', 'class_level' => '1', 'academic_year' => '2024/2025'],
- ['class_name' => '2 A', 'class_level' => '2', 'academic_year' => '2024/2025'],
- ['class_name' => '2 B', 'class_level' => '2', 'academic_year' => '2024/2025'],
+ ['class_name' => '1 A', 'class_level' => '1'],
+ ['class_name' => '1 B', 'class_level' => '1'],
+ ['class_name' => '2 A', 'class_level' => '2'],
+ ['class_name' => '2 B', 'class_level' => '2'],
];
foreach ($classes as $index => $class) {
- $class['homeroom_teacher_id'] = $teachers[$index % count($teachers)]->id;
ClassRoom::create($class);
}
}
diff --git a/database/seeders/ClassStudentSeeder.php b/database/seeders/ClassStudentSeeder.php
new file mode 100644
index 0000000..f5f11d9
--- /dev/null
+++ b/database/seeders/ClassStudentSeeder.php
@@ -0,0 +1,40 @@
+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,
+ ]);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/database/seeders/ClassSubjectSeeder.php b/database/seeders/ClassSubjectSeeder.php
new file mode 100644
index 0000000..671dd6c
--- /dev/null
+++ b/database/seeders/ClassSubjectSeeder.php
@@ -0,0 +1,41 @@
+first();
+
+ if (!$academicYear) {
+ $this->command->error('Tahun ajaran aktif tidak ditemukan.');
+ return;
+ }
+
+ foreach ($classRooms as $classRoom) {
+ // Contoh: ambil 3 sampai 5 mapel random untuk tiap kelas
+ $assignedSubjects = $subjects->random(rand(3, 5));
+
+ foreach ($assignedSubjects as $subject) {
+ ClassSubject::firstOrCreate([
+ 'class_room_id' => $classRoom->id,
+ 'subject_id' => $subject->id,
+ 'academic_year_id' => $academicYear->id,
+ ]);
+ }
+ }
+ }
+}
diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php
index edf7859..a466e15 100644
--- a/database/seeders/DatabaseSeeder.php
+++ b/database/seeders/DatabaseSeeder.php
@@ -2,11 +2,7 @@
namespace Database\Seeders;
-use App\Models\ClassRoom;
-use App\Models\User;
use Illuminate\Database\Seeder;
-use Spatie\Permission\Models\Permission;
-use Spatie\Permission\Models\Role;
class DatabaseSeeder extends Seeder
{
@@ -19,9 +15,12 @@ class DatabaseSeeder extends Seeder
UserSeeder::class,
SubjectSeeder::class,
ClassRoomSeeder::class,
+ AcademicYearSeeder::class,
StudentSeeder::class,
ExtracurricularSeeder::class,
- AttendanceSeeder::class,
+ ClassSubjectSeeder::class,
+ ClassStudentSeeder::class,
+ HomeRoomTeacherSeeder::class,
]);
}
}
diff --git a/database/seeders/SubjectScopeSeeder.php b/database/seeders/HomeRoomTeacherSeeder.php
similarity index 59%
rename from database/seeders/SubjectScopeSeeder.php
rename to database/seeders/HomeRoomTeacherSeeder.php
index 5e13ebb..4b4470c 100644
--- a/database/seeders/SubjectScopeSeeder.php
+++ b/database/seeders/HomeRoomTeacherSeeder.php
@@ -2,10 +2,14 @@
namespace Database\Seeders;
+use App\Models\AcademicYear;
+use App\Models\ClassRoom;
+use App\Models\HomeRoomTeacher;
+use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
-class SubjectScopeSeeder extends Seeder
+class HomeRoomTeacherSeeder extends Seeder
{
/**
* Run the database seeds.
@@ -14,4 +18,5 @@ class SubjectScopeSeeder extends Seeder
{
}
+
}
diff --git a/database/seeders/StudentSeeder.php b/database/seeders/StudentSeeder.php
index 5c9e5b1..fc38ee2 100644
--- a/database/seeders/StudentSeeder.php
+++ b/database/seeders/StudentSeeder.php
@@ -4,6 +4,7 @@ namespace Database\Seeders;
use App\Models\ClassRoom;
use App\Models\Student;
+use Carbon\Carbon;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
@@ -14,31 +15,29 @@ class StudentSeeder extends Seeder
*/
public function run(): void
{
- $classrooms = ClassRoom::all();
$religions = ['islam', 'kristen', 'katolik', 'hindu', 'buddha'];
- foreach ($classrooms as $classroom) {
- for ($i = 1; $i <= 20; $i++) {
- $gender = $i % 2 == 0 ? 'L' : 'P';
- $religion = $religions[array_rand($religions)];
- $nis = $classroom->class_level . str_pad($i, 3, '0', STR_PAD_LEFT);
+ 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
- Student::firstOrCreate(
- ['nis' => $nis], // Cek berdasarkan NIS
- [
- 'full_name' => 'Siswa ' . $classroom->class_name . ' ' . $i,
- 'gender' => $gender,
- 'birth_date' => now()->subYears(rand(15, 18))->subMonths(rand(1, 12)),
- 'birth_place' => 'Kota ' . chr(65 + rand(0, 25)),
- 'address' => 'Jl. Contoh No.' . $i,
- 'phone' => '0812' . rand(1000000, 9999999),
- 'class_id' => $classroom->id,
- 'parent_name' => 'Orang Tua Siswa ' . $i,
- 'religion' => $religion,
- 'parent_phone' => '0813' . rand(1000000, 9999999),
- ]
- );
- }
+ Student::firstOrCreate(
+ ['nis' => $nis], // Cek berdasarkan NIS
+ [
+ 'full_name' => 'Siswa ' . $i,
+ 'gender' => $gender,
+ 'birth_date' => Carbon::now()->subYears(rand(15, 18))->subMonths(rand(1, 12)),
+ 'birth_place' => 'Kota ' . chr(65 + rand(0, 25)),
+ 'address' => 'Jl. Contoh No.' . $i,
+ 'phone' => '0812' . rand(1000000, 9999999),
+ 'parent_name' => 'Orang Tua Siswa ' . $i,
+ 'religion' => $religion,
+ 'parent_phone' => '0813' . rand(1000000, 9999999),
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]
+ );
}
}
}
diff --git a/database/seeders/SubjectSeeder.php b/database/seeders/SubjectSeeder.php
index f332b43..de1b19c 100644
--- a/database/seeders/SubjectSeeder.php
+++ b/database/seeders/SubjectSeeder.php
@@ -3,7 +3,6 @@
namespace Database\Seeders;
use App\Models\Subject;
-use App\Models\SubjectScope;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
@@ -15,16 +14,21 @@ class SubjectSeeder extends Seeder
public function run(): void
{
$subjects = [
- ['name' => 'Matematika', 'is_religious' => false],
- ['name' => 'Bahasa Indonesia', 'is_religious' => false],
- ['name' => 'Bahasa Inggris', 'is_religious' => false],
- ['name' => 'IPA', 'is_religious' => false],
- ['name' => 'IPS', 'is_religious' => false],
- ['name' => 'Pendidikan Agama Islam', 'is_religious' => true],
- ['name' => 'Pendidikan Agama Kristen', 'is_religious' => true],
- ['name' => 'Pendidikan Agama Katolik', 'is_religious' => true],
- ['name' => 'Pendidikan Agama Hindu', 'is_religious' => true],
- ['name' => 'Pendidikan Agama Buddha', 'is_religious' => true],
+ ['name' => 'Matematika', 'is_religious' => false, 'category' => 'umum'],
+ ['name' => 'Bahasa Indonesia', 'is_religious' => false, 'category' => 'umum'],
+ ['name' => 'Bahasa Inggris', 'is_religious' => false, 'category' => 'umum'],
+ ['name' => 'IPA', 'is_religious' => false, 'category' => 'umum'],
+ ['name' => 'IPS', 'is_religious' => false, 'category' => 'umum'],
+ ['name' => 'Seni Rupa', 'is_religious' => false, 'category' => 'seni'],
+ ['name' => 'Seni Musik', 'is_religious' => false, 'category' => 'seni'],
+ ['name' => 'Seni Tari', 'is_religious' => false, 'category' => 'seni'],
+ ['name' => 'Seni Teater', 'is_religious' => false, 'category' => 'seni'],
+ ['name' => 'Bahasa Sunda', 'is_religious' => false, 'category' => 'muatan lokal'],
+ ['name' => 'Pendidikan Agama Islam', 'is_religious' => true, 'category' => 'umum'],
+ ['name' => 'Pendidikan Agama Kristen', 'is_religious' => true, 'category' => 'umum'],
+ ['name' => 'Pendidikan Agama Katolik', 'is_religious' => true, 'category' => 'umum'],
+ ['name' => 'Pendidikan Agama Hindu', 'is_religious' => true, 'category' => 'umum'],
+ ['name' => 'Pendidikan Agama Buddha', 'is_religious' => true, 'category' => 'umum'],
];
foreach ($subjects as $subject) {
@@ -40,15 +44,6 @@ class SubjectSeeder extends Seeder
str_contains($createdSubject->name, 'Buddha') => 'buddha',
default => null
};
-
- if ($religion) {
- SubjectScope::create([
- 'subject_id' => $createdSubject->id,
- 'religion' => $religion,
- 'learning_goal' => 'Memahami prinsip dasar agama ' . $religion,
- 'scope' => 'Tingkat dasar'
- ]);
- }
}
}
}
diff --git a/resources/views/filament/pages/student-report.blade.php b/resources/views/filament/pages/student-report.blade.php
new file mode 100644
index 0000000..a6abd90
--- /dev/null
+++ b/resources/views/filament/pages/student-report.blade.php
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+ {{ $this->list['header']['name'] }}
+
+
+
+ @foreach(['umum', 'muatan lokal'] as $category)
+ @if(!empty($this->list['header'][$category]))
+
+
+ {{ ucfirst($category) }}
+
+
+ @endif
+ @endforeach
+
+ @foreach(['umum', 'muatan lokal'] as $category)
+ @if(!empty($this->list['header'][$category]))
+ @foreach($this->list['header'][$category] as $subjectName)
+
+
+
+
+ @foreach($this->list['data'] as $student)
+
+
+ {{ $subjectName }}
+
+
+ @endforeach
+ @endif
+ @endforeach
+
+
+
+ @endforeach
+
+
+
+ {{ $student['name'] }}
+
+
+
+
+ @foreach(['umum', 'muatan lokal'] as $category)
+ @if(!empty($this->list['header'][$category]))
+ @foreach($this->list['header'][$category] as $subjectId => $subjectName)
+
+
+ {{ $student[$category][$subjectId] ?? '-' }}
+
+
+ @endforeach
+ @endif
+ @endforeach
+
{{ $student['name'] }}
-{{ $student['nis'] }}
+{{ $student['name'] ?? "" }}
+{{ $student['nis'] ?? "" }}