refactor: remove unused widgets from AdminPanelProvider to streamline widget management

This commit is contained in:
Yoga Pangestu 2026-03-30 11:16:34 +07:00
parent 6277d50cc0
commit 4426fe4d84
5 changed files with 311 additions and 6 deletions

View File

@ -0,0 +1,74 @@
<?php
namespace App\Filament\Widgets;
use App\Models\Assignment;
use Filament\Widgets\ChartWidget;
use Illuminate\Database\Eloquent\Builder;
class MyAssignmentCompletionChart extends ChartWidget
{
protected static ?int $sort = 3;
protected ?string $heading = 'Status Penyelesaian Tugas';
protected ?string $maxHeight = '275px';
public static function canView(): bool
{
return auth()->user()?->student !== null;
}
protected function getData(): array
{
$studentId = auth()->user()?->student?->id;
$baseQuery = Assignment::query()
->whereHas('assignmentTargets', function (Builder $query) use ($studentId) {
$query->where('student_id', $studentId)
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('study_group_id')->from('study_group_members')->where('student_id', $studentId);
})
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('id')->from('study_groups')->where('leader_id', $studentId);
});
});
$submittedCount = (clone $baseQuery)->whereHas('assignmentSubmissions', function (Builder $query) use ($studentId) {
$query->where('student_id', $studentId)
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('study_group_id')->from('study_group_members')->where('student_id', $studentId);
})
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('id')->from('study_groups')->where('leader_id', $studentId);
});
})->count();
$totalCount = $baseQuery->count();
$notSubmittedCount = $totalCount - $submittedCount;
return [
'datasets' => [
[
'label' => 'Tugas',
'data' => [$submittedCount, $notSubmittedCount],
'backgroundColor' => [
'rgba(59, 130, 246, 0.8)', // Blue 500
'rgba(245, 158, 11, 0.8)', // Amber 500
],
'borderColor' => [
'rgba(59, 130, 246, 1)',
'rgba(245, 158, 11, 1)',
],
],
],
'labels' => ['Sudah Dikerjakan', 'Belum Dikerjakan'],
];
}
protected function getType(): string
{
return 'doughnut';
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace App\Filament\Widgets;
use App\Models\Attendance;
use Filament\Widgets\ChartWidget;
class MyAttendanceRatioChart extends ChartWidget
{
protected static ?int $sort = 2;
protected ?string $heading = 'Persentase Presensi';
protected ?string $maxHeight = '275px';
public static function canView(): bool
{
return auth()->user()?->student !== null;
}
protected function getData(): array
{
$studentId = auth()->user()?->student?->id;
$presentCount = Attendance::where('student_id', $studentId)
->whereNotNull('attended_at')
->count();
$absentCount = Attendance::where('student_id', $studentId)
->whereNull('attended_at')
->where('date', '<=', today())
->count();
return [
'datasets' => [
[
'label' => 'Presensi',
'data' => [$presentCount, $absentCount],
'backgroundColor' => [
'rgba(16, 185, 129, 0.8)', // Emerald 500
'rgba(244, 63, 94, 0.8)', // Rose 500
],
'borderColor' => [
'rgba(16, 185, 129, 1)',
'rgba(244, 63, 94, 1)',
],
],
],
'labels' => ['Hadir', 'Tidak / Belum Hadir'],
];
}
protected function getType(): string
{
return 'doughnut';
}
}

View File

@ -0,0 +1,95 @@
<?php
namespace App\Filament\Widgets;
use App\Models\Assignment;
use Filament\Actions\Action;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Filament\Widgets\TableWidget as BaseWidget;
use Illuminate\Database\Eloquent\Builder;
class MyPendingAssignmentsTable extends BaseWidget
{
protected static ?int $sort = 4;
protected int|string|array $columnSpan = 'full';
protected static ?string $heading = 'Tugas Mendatang yang Belum Selesai';
public static function canView(): bool
{
return auth()->user()?->student !== null;
}
public function table(Table $table): Table
{
$studentId = auth()->user()?->student?->id;
return $table
->query(
Assignment::query()
->whereHas('assignmentTargets', function (Builder $query) use ($studentId) {
$query->where('student_id', $studentId)
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('study_group_id')
->from('study_group_members')
->where('student_id', $studentId);
})
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('id')
->from('study_groups')
->where('leader_id', $studentId);
});
})
->whereDoesntHave('assignmentSubmissions', function (Builder $query) use ($studentId) {
$query->where('student_id', $studentId)
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('study_group_id')
->from('study_group_members')
->where('student_id', $studentId);
})
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('id')
->from('study_groups')
->where('leader_id', $studentId);
});
})
->where('due_date', '>=', now())
->orderBy('due_date', 'asc')
)
->columns([
TextColumn::make('title')
->label('Judul Tugas')
->searchable()
->sortable()
->wrap(),
TextColumn::make('course.name')
->label('Mata Kuliah')
->searchable()
->sortable()
->wrap(),
TextColumn::make('type')
->label('Jenis')
->badge(),
TextColumn::make('due_date')
->label('Tenggat Waktu')
->dateTime('d M Y H:i')
->sortable()
->color(fn (Assignment $record) => $record->due_date < now()->addDays(2) ? 'danger' : 'warning'),
])
->recordActions([
Action::make('kerjakan')
->label('Lihat Detail & Kerjakan')
->url(fn (Assignment $record): string => '/admin/learning/assignments/'.$record->id.'/submit')
->icon('heroicon-m-arrow-top-right-on-square')
->button()
->color('primary'),
])
->emptyStateHeading('Tidak Ada Tugas')
->emptyStateDescription('Semua tugas telah diselesaikan atau tidak ada tugas mendatang.');
}
}

View File

@ -0,0 +1,84 @@
<?php
namespace App\Filament\Widgets;
use App\Models\Assignment;
use App\Models\Attendance;
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
use Illuminate\Database\Eloquent\Builder;
class StatsOverview extends BaseWidget
{
protected static ?int $sort = 1;
public static function canView(): bool
{
return auth()->user()?->student !== null;
}
protected function getStats(): array
{
$studentId = auth()->user()?->student?->id;
if (! $studentId) {
return [];
}
$presentCount = Attendance::where('student_id', $studentId)
->whereNotNull('attended_at')
->count();
$totalSessions = Attendance::where('student_id', $studentId)->count();
$attendanceRate = $totalSessions > 0 ? round(($presentCount / $totalSessions) * 100) : 0;
$baseAssignmentQuery = Assignment::query()
->whereHas('assignmentTargets', function (Builder $query) use ($studentId) {
$query->where('student_id', $studentId)
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('study_group_id')->from('study_group_members')->where('student_id', $studentId);
})
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('id')->from('study_groups')->where('leader_id', $studentId);
});
});
$completedAssignments = (clone $baseAssignmentQuery)->whereHas('assignmentSubmissions', function (Builder $query) use ($studentId) {
$query->where('student_id', $studentId)
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('study_group_id')->from('study_group_members')->where('student_id', $studentId);
})
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('id')->from('study_groups')->where('leader_id', $studentId);
});
})->count();
$pendingAssignments = (clone $baseAssignmentQuery)->whereDoesntHave('assignmentSubmissions', function (Builder $query) use ($studentId) {
$query->where('student_id', $studentId)
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('study_group_id')->from('study_group_members')->where('student_id', $studentId);
})
->orWhereIn('study_group_id', function ($q) use ($studentId) {
$q->select('id')->from('study_groups')->where('leader_id', $studentId);
});
})
->where('due_date', '>=', now())
->count();
return [
Stat::make('Kehadiran', $presentCount.' / '.$totalSessions.' Sesi')
->description($attendanceRate.'% Tingkat Kehadiran')
->descriptionIcon('heroicon-m-check-circle')
->color($attendanceRate >= 75 ? 'success' : 'danger'),
Stat::make('Tugas Selesai', $completedAssignments.' Tugas')
->description('Telah dikumpulkan')
->descriptionIcon('heroicon-m-clipboard-document-check')
->color('success'),
Stat::make('Tugas Mendatang', $pendingAssignments.' Tugas')
->description('Belum dikerjakan')
->descriptionIcon($pendingAssignments > 0 ? 'heroicon-m-exclamation-circle' : 'heroicon-m-face-smile')
->color($pendingAssignments > 0 ? 'warning' : 'gray'),
];
}
}

View File

@ -15,7 +15,6 @@
use Filament\Panel;
use Filament\PanelProvider;
use Filament\Support\Colors\Color;
use Filament\Widgets\AccountWidget;
use Hammadzafar05\MobileBottomNav\MobileBottomNav;
use Hammadzafar05\MobileBottomNav\MobileBottomNavItem;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
@ -27,7 +26,6 @@
use Saade\Facehash\Enums\Variant;
use Saade\FilamentFacehash\FacehashPlugin;
use Saade\FilamentFacehash\FacehashProvider;
use SalmanAlmajali\JokesWidget\JokesWidget;
class AdminPanelProvider extends PanelProvider
{
@ -49,10 +47,7 @@ public function panel(Panel $panel): Panel
Dashboard::class,
])
->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\Filament\Widgets')
->widgets([
AccountWidget::class,
JokesWidget::class,
])
->widgets([])
->middleware([
EncryptCookies::class,
AddQueuedCookiesToResponse::class,