diff --git a/app/Filament/Training/Pages/Exam/ExamHistory.php b/app/Filament/Training/Pages/Exam/ExamHistory.php index 83e5f8ec2..6c86d0c8f 100644 --- a/app/Filament/Training/Pages/Exam/ExamHistory.php +++ b/app/Filament/Training/Pages/Exam/ExamHistory.php @@ -2,6 +2,7 @@ namespace App\Filament\Training\Pages\Exam; +use App\Filament\Training\Pages\Exam\Widgets\ExamOverview; use App\Repositories\Cts\ExamResultRepository; use Filament\Forms; use Filament\Pages\Page; @@ -28,6 +29,13 @@ public static function canAccess(): bool return auth()->user()->can('training.exams.access'); } + protected function getHeaderWidgets(): array + { + return [ + ExamOverview::class, + ]; + } + public function table(Table $table): Table { $userPermissionsTruthTable = [ diff --git a/app/Filament/Training/Pages/Exam/Widgets/ExamOverview.php b/app/Filament/Training/Pages/Exam/Widgets/ExamOverview.php new file mode 100644 index 000000000..113881ac1 --- /dev/null +++ b/app/Filament/Training/Pages/Exam/Widgets/ExamOverview.php @@ -0,0 +1,55 @@ +startOfYear(); + $endofYear = now()->endOfYear(); + + $overall = PracticalResult::select( + DB::raw('count(*) as total'), + DB::raw("SUM(CASE WHEN result = '".PracticalResult::PASSED."' THEN 1 ELSE 0 END) as passed"), + DB::raw("SUM(CASE WHEN result = '".PracticalResult::FAILED."' THEN 1 ELSE 0 END) as failed"), + DB::raw("SUM(CASE WHEN result = '".PracticalResult::INCOMPLETE."' THEN 1 ELSE 0 END) as incomplete"), + ) + ->WhereBetween('date', [$startofYear, $endofYear]) + ->first(); + + $examStats = PracticalResult::whereBetween('date', [$startofYear, $endofYear]) + ->select('exam', 'result', DB::raw('count(*) as total')) + ->groupBy('exam', 'result') + ->get() + ->groupBy('exam'); + + $cards = [ + Stat::make('Total Taken', $overall->total), + Stat::make('Pass Rate', ($overall->total ? round($overall->passed / $overall->total * 100) : 100).'%') + ->description("$overall->passed Passed, $overall->failed Failed, $overall->incomplete Incomplete"), + ]; + + $examOrder = ['OBS', 'TWR', 'APP', 'CTR']; + + foreach ($examOrder as $exam) { + $results = $examStats->get($exam, collect()); + $examTotal = $results->sum('total'); + $examPassed = $results->firstWhere('result', PracticalResult::PASSED)->total ?? 0; + $examFailed = $results->firstWhere('result', PracticalResult::FAILED)->total ?? 0; + $examIncomplete = $results->firstWhere('result', PracticalResult::INCOMPLETE)->total ?? 0; + + $cards[] = Stat::make("{$exam} Pass Rate", ($examTotal ? round($examPassed / $examTotal * 100) : 100).'%') + ->description("$examTotal Total, $examPassed Passed, $examFailed Failed, $examIncomplete Incomplete"); + } + + return $cards; + } +} diff --git a/app/Filament/Training/Pages/TheoryExamHistory.php b/app/Filament/Training/Pages/TheoryExam/TheoryExamHistory.php similarity index 96% rename from app/Filament/Training/Pages/TheoryExamHistory.php rename to app/Filament/Training/Pages/TheoryExam/TheoryExamHistory.php index 98e7bdcff..93e9e9084 100644 --- a/app/Filament/Training/Pages/TheoryExamHistory.php +++ b/app/Filament/Training/Pages/TheoryExam/TheoryExamHistory.php @@ -1,7 +1,8 @@ user()->can('training.theory.access'); } + protected function getHeaderWidgets(): array + { + return [ + TheoryExamOverview::class, + ]; + } + protected function buildQuestionPlaceholders($record): array { diff --git a/app/Filament/Training/Pages/TheoryExam/Widgets/TheoryExamOverview.php b/app/Filament/Training/Pages/TheoryExam/Widgets/TheoryExamOverview.php new file mode 100644 index 000000000..8dd6a9b3e --- /dev/null +++ b/app/Filament/Training/Pages/TheoryExam/Widgets/TheoryExamOverview.php @@ -0,0 +1,51 @@ +startOfYear(); + $endofYear = now()->endOfYear(); + $overall = TheoryResult::select( + DB::raw('count(*) as total'), + DB::raw('SUM(CASE WHEN pass = 1 THEN 1 ELSE 0 END) as passed'), + DB::raw('SUM(CASE WHEN pass = 0 THEN 1 ELSE 0 END) as failed') + ) + ->whereBetween('started', [$startofYear, $endofYear]) + ->first(); + + $examStats = TheoryResult::whereBetween('started', [$startofYear, $endofYear]) + ->select('exam', 'pass', DB::raw('count(*) as total')) + ->groupBy('exam', 'pass') + ->get() + ->groupBy('exam'); + + $cards = [ + Stat::make('Total Taken', $overall->total), + Stat::make('Pass Rate', ($overall->total ? round($overall->passed / $overall->total * 100) : 100).'%')->description("$overall->passed Passed, $overall->failed Failed"), + ]; + + $examOrder = ['S1', 'S2', 'S3', 'C1']; + + foreach ($examOrder as $exam) { + $results = $examStats->get($exam, collect()); + $examTotal = $results->sum('total'); + $examPassed = $results->firstWhere('pass', true)->total ?? 0; + $examFailed = $results->firstWhere('pass', false)->total ?? 0; + + $cards[] = Stat::make("{$exam} Pass Rate", ($examTotal ? round($examPassed / $examTotal * 100) : 100).'%') + ->description("$examTotal Total, $examPassed Passed, $examFailed Failed"); + } + + return $cards; + } +} diff --git a/tests/Feature/TrainingPanel/Exams/TheoryExamHistoryTest.php b/tests/Feature/TrainingPanel/Exams/TheoryExamHistoryTest.php index cfa27c129..7e7afaea7 100644 --- a/tests/Feature/TrainingPanel/Exams/TheoryExamHistoryTest.php +++ b/tests/Feature/TrainingPanel/Exams/TheoryExamHistoryTest.php @@ -2,7 +2,7 @@ namespace Tests\Feature\TrainingPanel\Exams; -use App\Filament\Training\Pages\TheoryExamHistory; +use App\Filament\Training\Pages\TheoryExam\TheoryExamHistory; use App\Models\Cts\Member; use App\Models\Cts\TheoryAnswer; use App\Models\Cts\TheoryQuestion;