diff --git a/app/Filament/Resources/Learning/Assignments/Actions/MarkAsSentAction.php b/app/Filament/Resources/Learning/Assignments/Actions/MarkAsSentAction.php new file mode 100644 index 0000000..7001077 --- /dev/null +++ b/app/Filament/Resources/Learning/Assignments/Actions/MarkAsSentAction.php @@ -0,0 +1,55 @@ +label(function (array $arguments, ?Assignment $record) { + $assignment = $record ?? Assignment::find($arguments['record'] ?? null); + + return $assignment?->is_sent_to_lecturer ? 'Buka Kunci' : 'Tandai Terkirim'; + }) + ->icon(function (array $arguments, ?Assignment $record) { + $assignment = $record ?? Assignment::find($arguments['record'] ?? null); + + return $assignment?->is_sent_to_lecturer ? 'heroicon-o-lock-open' : 'heroicon-o-check-circle'; + }) + ->color(function (array $arguments, ?Assignment $record) { + $assignment = $record ?? Assignment::find($arguments['record'] ?? null); + + return $assignment?->is_sent_to_lecturer ? 'warning' : 'success'; + }) + ->link() + ->visible(fn () => auth()->user()->hasRole(['Kosma', 'Developer'])) + ->action(function (array $arguments, $livewire, ?Assignment $record) { + $assignment = $record ?? Assignment::find($arguments['record'] ?? null); + if (! $assignment) { + return; + } + + $assignment->update([ + 'is_sent_to_lecturer' => ! $assignment->is_sent_to_lecturer, + ]); + + SystemNotification::send($assignment->is_sent_to_lecturer ? 'assignment_sent' : 'assignment_unlocked') + ->send(); + + if (isset($livewire->assignments)) { + unset($livewire->assignments); + } + }); + } +} diff --git a/app/Filament/Resources/Learning/Assignments/Pages/ListAssignments.php b/app/Filament/Resources/Learning/Assignments/Pages/ListAssignments.php index e4da826..bf35372 100644 --- a/app/Filament/Resources/Learning/Assignments/Pages/ListAssignments.php +++ b/app/Filament/Resources/Learning/Assignments/Pages/ListAssignments.php @@ -7,6 +7,7 @@ use App\Filament\Resources\Learning\Assignments\Actions\CreateAssignmentAction; use App\Filament\Resources\Learning\Assignments\Actions\DeleteAssignmentAction; use App\Filament\Resources\Learning\Assignments\Actions\EditAssignmentAction; +use App\Filament\Resources\Learning\Assignments\Actions\MarkAsSentAction; use App\Filament\Resources\Learning\Assignments\Actions\PinAction; use App\Filament\Resources\Learning\Assignments\Actions\ShareAssignmentAction; use App\Filament\Resources\Learning\Assignments\AssignmentResource; @@ -156,6 +157,11 @@ public function shareAssignmentAction(): Action return ShareAssignmentAction::make(); } + public function markAsSentAction(): Action + { + return MarkAsSentAction::make(); + } + #[Computed] public function assignments(): Collection { @@ -234,15 +240,20 @@ public function assignments(): Collection private function getAssignmentPriority($assignment): int { + $isSent = $assignment->is_sent_to_lecturer; + if ($isSent) { + return 5; // Closed + } + $isSubmitted = $assignment->assignmentSubmissions?->isNotEmpty(); $isOverdue = now()->isAfter($assignment->due_date); if (! $isOverdue) { - return $isSubmitted ? 2 : 1; + return $isSubmitted ? 3 : 1; // 1: Active, 3: Completed Active } - // Overdue - return $isSubmitted ? 3 : 4; + // Overdue but not sent + return $isSubmitted ? 4 : 2; // 2: Actionable Overdue, 4: Completed Overdue } #[Computed] @@ -269,8 +280,10 @@ public function assignmentCards() $isLeader = $userGroup && $userGroup->leader_id === $studentProfile->id; } + $isSentToLecturer = $assignment->is_sent_to_lecturer; $isOverdue = now()->isAfter($assignment->due_date); - $canSubmit = ! $isOverdue; + + $canSubmit = ! $isSentToLecturer; $canSubmitByRole = ! $isGroup || $isLeader; $canSubmitActual = $canSubmit && $canSubmitByRole; @@ -279,30 +292,35 @@ public function assignmentCards() $isNew = $assignment->created_at?->diffInDays(now()) <= 3; $isPinned = in_array($assignment->id, $pinnedIds); - $statusLabel = SystemNotification::getByKey('labels.assignment_status.not_submitted'); - $statusColor = 'warning'; - $statusIcon = 'heroicon-o-arrow-up-tray'; - if ($isSubmitted) { - $statusLabel = SystemNotification::getByKey('labels.assignment_status.submitted'); - $statusColor = 'success'; - $statusIcon = 'heroicon-o-check-circle'; + $submissionLabel = SystemNotification::getByKey('labels.assignment_status.submitted'); + $submissionColor = 'success'; + $submissionIcon = 'heroicon-o-check-circle'; } elseif ($isOverdue) { - $statusLabel = SystemNotification::getByKey('labels.assignment_status.overdue'); - $statusColor = 'danger'; - $statusIcon = 'heroicon-o-clock'; + $submissionLabel = SystemNotification::getByKey('labels.assignment_status.overdue'); + $submissionColor = 'danger'; + $submissionIcon = 'heroicon-o-clock'; } elseif ($isGroup && ! $isLeader && ! $isSubmitted) { - $statusLabel = SystemNotification::getByKey('labels.assignment_status.waiting_leader'); - $statusColor = 'gray'; - $statusIcon = 'heroicon-o-user-group'; + $submissionLabel = SystemNotification::getByKey('labels.assignment_status.waiting_leader'); + $submissionColor = 'gray'; + $submissionIcon = 'heroicon-o-user-group'; + } else { + $submissionLabel = SystemNotification::getByKey('labels.assignment_status.not_submitted'); + $submissionColor = 'warning'; + $submissionIcon = 'heroicon-o-arrow-up-tray'; } + $deliveryLabel = $isSentToLecturer ? 'Telah Dikirim' : 'Belum Dikirim'; + $deliveryColor = $isSentToLecturer ? 'success' : 'amber'; + $deliveryIcon = $isSentToLecturer ? 'heroicon-o-check-badge' : 'heroicon-o-clock'; + return (object) [ 'id' => $assignment->id, 'title' => $assignment->title, 'course_name' => $assignment->course?->name ?? '-', 'due_date_formatted' => $assignment->due_date?->translatedFormat('l, d F Y H:i'), 'submitted_at_formatted' => ($isSubmitted && $submission->submitted_at) ? $submission->submitted_at?->translatedFormat('l, d F Y H:i') : null, + 'is_sent_to_lecturer' => $isSentToLecturer, 'is_submitted' => $isSubmitted, 'is_group' => $isGroup, 'is_leader' => $isLeader, @@ -311,8 +329,28 @@ public function assignmentCards() 'is_urgent' => $isUrgent, 'is_new' => $isNew, 'is_pinned' => $isPinned, - 'status_label' => $statusLabel, - 'status_icon' => $statusIcon, + 'submission_status' => (object) [ + 'label' => $submissionLabel, + 'color' => $submissionColor, + 'icon' => $submissionIcon, + 'classes' => Arr::toCssClasses([ + 'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-semibold', // font-semibold for clarity + 'bg-success-100 text-success-700 dark:bg-success-900/30 dark:text-success-400' => $submissionColor === 'success', + 'bg-danger-100 text-danger-700 dark:bg-danger-900/30 dark:text-danger-400' => $submissionColor === 'danger', + 'bg-warning-100 text-warning-700 dark:bg-warning-900/30 dark:text-warning-400' => $submissionColor === 'warning', + 'bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-400' => $submissionColor === 'gray', + ]), + ], + 'delivery_status' => (object) [ + 'label' => $deliveryLabel, + 'color' => $deliveryColor, + 'icon' => $deliveryIcon, + 'classes' => Arr::toCssClasses([ + 'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-bold ring-1 ring-inset', // font-bold and ring for "delivery" status to make it pop + 'bg-success-50 text-success-700 ring-success-600/20 dark:bg-success-900/10 dark:text-success-400 dark:ring-success-500/20' => $deliveryColor === 'success', + 'bg-amber-50 text-amber-700 ring-amber-600/20 dark:bg-amber-900/10 dark:text-amber-400 dark:ring-amber-500/20' => $deliveryColor === 'amber', + ]), + ], 'url' => AssignmentResource::getUrl('submit', ['record' => $assignment->id]), // Pre-calculated classes 'card_classes' => Arr::toCssClasses([ @@ -327,14 +365,6 @@ public function assignmentCards() 'bg-danger-50 dark:bg-danger-900/20 text-danger-600 dark:text-danger-400' => ! $isSubmitted && $isOverdue, 'bg-warning-50 dark:bg-warning-900/20 text-warning-600 dark:text-warning-400' => ! $isSubmitted && ! $isOverdue, ]), - 'status_badge_classes' => Arr::toCssClasses([ - 'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium', - 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400' => $statusColor === 'amber', - 'bg-success-100 text-success-700 dark:bg-success-900/30 dark:text-success-400' => $statusColor === 'success', - 'bg-danger-100 text-danger-700 dark:bg-danger-900/30 dark:text-danger-400' => $statusColor === 'danger', - 'bg-warning-100 text-warning-700 dark:bg-warning-900/30 dark:text-warning-400' => $statusColor === 'warning', - 'bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-400' => $statusColor === 'gray', - ]), 'indicator_icon_classes' => Arr::toCssClasses([ 'h-5 w-5 opacity-20', 'text-primary-500' => $isLeader, diff --git a/app/Filament/Resources/Learning/Assignments/Pages/SubmissionDetailPage.php b/app/Filament/Resources/Learning/Assignments/Pages/SubmissionDetailPage.php index 11403e0..d1c5c3a 100644 --- a/app/Filament/Resources/Learning/Assignments/Pages/SubmissionDetailPage.php +++ b/app/Filament/Resources/Learning/Assignments/Pages/SubmissionDetailPage.php @@ -4,7 +4,9 @@ use App\Enums\AssignmentType; use App\Filament\Actions\BackAction; +use App\Filament\Resources\Learning\Assignments\Actions\MarkAsSentAction; use App\Filament\Resources\Learning\Assignments\AssignmentResource; +use App\Filament\Support\SystemNotification; use App\Models\Assignment; use App\Models\AssignmentSubmission; use Filament\Actions\Action; @@ -53,6 +55,14 @@ public function statCards(): array 'icon' => 'heroicon-o-chart-bar', 'color_classes' => 'bg-primary-100 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400', ], + [ + 'label' => 'Status Dosen', + 'value' => $this->record?->is_sent_to_lecturer ? 'SUDAH TERKIRIM' : 'BELUM TERKIRIM', + 'icon' => $this->record?->is_sent_to_lecturer ? 'heroicon-o-check-badge' : 'heroicon-o-clock', + 'color_classes' => $this->record?->is_sent_to_lecturer + ? 'bg-success-500 text-white shadow-lg shadow-success-200 dark:shadow-none' + : 'bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-400', + ], ]; } @@ -164,9 +174,18 @@ public function assignmentSummary(): array 'due_date' => $this->record?->due_date?->translatedFormat('l, d F Y H:i'), 'type' => $this->record?->type->value, 'is_overdue' => $this->isOverdue, + 'is_sent_to_lecturer' => $this->record?->is_sent_to_lecturer, ]; } + #[Computed] + public function sectionIcon(): string + { + return SystemNotification::getNotifStyle() === \App\Enums\NotifStyle::Cheerful + ? 'heroicon-o-document-magnifying-glass' + : 'heroicon-o-document-text'; + } + public function previewSubmissionAction(): Action { return Action::make('previewSubmission') @@ -186,6 +205,8 @@ public function previewSubmissionAction(): Action protected function getHeaderActions(): array { return [ + MarkAsSentAction::make() + ->record($this->record), BackAction::make() ->url(AssignmentResource::getUrl()), diff --git a/app/Filament/Resources/Learning/Assignments/Pages/SubmitAssignmentPage.php b/app/Filament/Resources/Learning/Assignments/Pages/SubmitAssignmentPage.php index 2460f17..4bb2285 100644 --- a/app/Filament/Resources/Learning/Assignments/Pages/SubmitAssignmentPage.php +++ b/app/Filament/Resources/Learning/Assignments/Pages/SubmitAssignmentPage.php @@ -56,6 +56,9 @@ public function form(Schema $schema): Schema #[Computed] public function statusCards(): array { + $isSent = $this->record->is_sent_to_lecturer; + $existing = $this->existingSubmission; + return [ [ 'label' => 'Batas Waktu', @@ -71,14 +74,28 @@ public function statusCards(): array ], [ 'label' => 'Status Pengumpulan', - 'value' => $this->isOverdue ? 'Ditutup' : 'Terbuka', - 'icon' => $this->isOverdue ? 'heroicon-o-lock-closed' : 'heroicon-o-check-circle', - 'is_danger' => $this->isOverdue, - 'is_success' => ! $this->isOverdue, + 'value' => $existing ? 'Sudah Dikumpulkan' : ($isSent ? 'Terlambat & Terkunci' : ($this->isOverdue ? 'Belum (Masih Terbuka)' : 'Belum Dikumpulkan')), + 'icon' => $existing ? 'heroicon-o-check-circle' : ($isSent ? 'heroicon-o-lock-closed' : 'heroicon-o-arrow-up-tray'), + 'is_success' => (bool) $existing, + 'is_danger' => ! $existing && $isSent, + 'is_warning' => ! $existing && ! $isSent && $this->isOverdue, 'icon_classes' => Arr::toCssClasses([ 'flex h-9 w-9 shrink-0 items-center justify-center rounded-lg', - 'bg-danger-50 dark:bg-danger-900/20 text-danger-600' => $this->isOverdue, - 'bg-success-50 dark:bg-success-900/20 text-success-600' => ! $this->isOverdue, + 'bg-success-50 dark:bg-success-900/20 text-success-600' => $existing, + 'bg-danger-50 dark:bg-danger-900/20 text-danger-600' => ! $existing && $isSent, + 'bg-warning-50 dark:bg-warning-900/20 text-warning-600' => ! $existing && ! $isSent && $this->isOverdue, + ]), + ], + [ + 'label' => 'Status ke Dosen', + 'value' => $isSent ? 'Telah Dikirim' : 'Belum Dikirim', + 'icon' => $isSent ? 'heroicon-o-paper-airplane' : 'heroicon-o-clock', + 'is_success' => $isSent, + 'badge' => $isSent ? '(Kunci Aktif)' : '(Masih Terbuka)', + 'icon_classes' => Arr::toCssClasses([ + 'flex h-9 w-9 shrink-0 items-center justify-center rounded-lg', + 'bg-success-50 dark:bg-success-900/20 text-success-600' => $isSent, + 'bg-gray-100 dark:bg-gray-800 text-gray-500' => ! $isSent, ]), ], ]; @@ -243,6 +260,13 @@ public function submit(): void return; } + if ($assignment->is_sent_to_lecturer) { + SystemNotification::send('submission_locked', type: 'danger') + ->send(); + + return; + } + if (! $this->canSubmit) { SystemNotification::send('submission_not_leader', type: 'danger') ->send(); @@ -313,7 +337,7 @@ protected function getHeaderActions(): array return [ BackAction::make() - ->url(url()->previous() ?? AssignmentResource::getUrl('index')), + ->url(url()->previous() !== AssignmentResource::getUrl('submit', ['record' => $this->record->id]) ? url()->previous() : AssignmentResource::getUrl('index')), ]; } } diff --git a/app/Filament/Resources/Learning/Attendances/Pages/ManageAttendances.php b/app/Filament/Resources/Learning/Attendances/Pages/ManageAttendances.php index 1b0fa7e..4640ccc 100644 --- a/app/Filament/Resources/Learning/Attendances/Pages/ManageAttendances.php +++ b/app/Filament/Resources/Learning/Attendances/Pages/ManageAttendances.php @@ -2,6 +2,7 @@ namespace App\Filament\Resources\Learning\Attendances\Pages; +use App\Enums\NotifStyle; use App\Filament\Resources\Learning\Attendances\AttendanceResource; use App\Filament\Support\SystemNotification; use App\Models\Attendance; @@ -71,6 +72,22 @@ public function emptyDescription(): string return SystemNotification::getByKey('labels.empty_attendance.description'); } + #[Computed] + public function sectionIcon(): string + { + return SystemNotification::getNotifStyle() === NotifStyle::Cheerful + ? 'heroicon-o-hand-raised' + : 'heroicon-o-clipboard-document-check'; + } + + #[Computed] + public function historyIcon(): string + { + return SystemNotification::getNotifStyle() === NotifStyle::Cheerful + ? 'heroicon-o-clock' + : 'heroicon-o-archive-box'; + } + public function getSchedules() { /** @var User|null $user */ diff --git a/app/Models/Assignment.php b/app/Models/Assignment.php index f70cd79..f4dc63c 100644 --- a/app/Models/Assignment.php +++ b/app/Models/Assignment.php @@ -30,6 +30,7 @@ protected function casts(): array return [ 'due_date' => 'datetime', 'type' => AssignmentType::class, + 'is_sent_to_lecturer' => 'boolean', ]; } diff --git a/database/migrations/2026_04_07_094148_add_is_sent_to_lecturer_to_assignments_table.php b/database/migrations/2026_04_07_094148_add_is_sent_to_lecturer_to_assignments_table.php new file mode 100644 index 0000000..d4606d6 --- /dev/null +++ b/database/migrations/2026_04_07_094148_add_is_sent_to_lecturer_to_assignments_table.php @@ -0,0 +1,30 @@ +boolean('is_sent_to_lecturer')->default(false)->after('due_date'); + }); + } + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('assignments', function (Blueprint $table) { + $table->dropColumn('is_sent_to_lecturer'); + }); + } +}; diff --git a/lang/id/notif.php b/lang/id/notif.php index 32dba5a..826b890 100644 --- a/lang/id/notif.php +++ b/lang/id/notif.php @@ -145,6 +145,18 @@ 'title' => 'Mantap! Sudah Dibaca โœ…โœจ', 'body' => 'Pembaruan ":title" sudah ditandai. Makin update makin jago! ๐Ÿš€๐Ÿ”ฅ', ], + 'assignment_sent' => [ + 'title' => 'Tugas Berhasil Dikirim! ๐Ÿš€โœจ', + 'body' => 'Tugas kolektif sudah berhasil ditandai terkirim ke dosen. Status pengumpulan resmi ditutup! ๐Ÿ”’', + ], + 'assignment_unlocked' => [ + 'title' => 'Kunci Tugas Dibuka! ๐Ÿ”“โœจ', + 'body' => 'Mahasiswa sekarang diperbolehkan kembali untuk mengumpulkan atau memperbarui tugas mereka. ๐Ÿ“', + ], + 'submission_locked' => [ + 'title' => 'Tugas Terkunci! ๐Ÿ”’', + 'body' => 'Mohon maaf, tugas ini sudah ditandai terkirim ke dosen oleh Kosma dan tidak dapat diubah lagi. ๐Ÿšซ', + ], // UI Labels & Descriptions 'labels' => [ @@ -437,6 +449,18 @@ 'title' => 'Pembaruan Berhasil Ditandai', 'body' => 'Catatan rilis ":title" telah berhasil ditandai sebagai sudah dibaca.', ], + 'assignment_sent' => [ + 'title' => 'Konfirmasi Pengiriman Berhasil', + 'body' => 'Seluruh berkas tugas kolektif telah berhasil ditandai sebagai terkirim ke dosen pengampu.', + ], + 'assignment_unlocked' => [ + 'title' => 'Kunci Akses Dibuka', + 'body' => 'Otoritas pengumpulan tugas telah diaktifkan kembali untuk seluruh mahasiswa terkait.', + ], + 'submission_locked' => [ + 'title' => 'Akses Pengumpulan Ditutup', + 'body' => 'Tugas ini telah dalam status final (terkirim ke dosen). Perubahan data tidak lagi dimungkinkan.', + ], // UI Labels & Descriptions 'labels' => [ diff --git a/resources/views/filament/resources/learning/assignments/index.blade.php b/resources/views/filament/resources/learning/assignments/index.blade.php index cc88264..df51569 100644 --- a/resources/views/filament/resources/learning/assignments/index.blade.php +++ b/resources/views/filament/resources/learning/assignments/index.blade.php @@ -19,7 +19,7 @@ class="flex flex-1 items-start gap-4 p-5 text-left min-w-0 hover:bg-primary-500/5 transition-colors cursor-pointer">
- +
@@ -51,11 +51,16 @@ class="inline-flex items-center gap-1.5 rounded-full bg-blue-100 text-blue-700 d @endif - - @if ($card->status_icon) - - @endif - {{ $card->status_label }} + {{-- Status Pengumpulan (Submission Status) --}} + + + {{ $card->submission_status->label }} + + + {{-- Status Pengiriman ke Dosen (Delivery Status) --}} + + + {{ $card->delivery_status->label }} @if ($card->is_urgent) @@ -91,6 +96,7 @@ class="flex flex-wrap items-center gap-3 px-5 py-4 border-t border-gray-100 dark @endcan @canAny(['Update:Assignment', 'Delete:Assignment']) + {{ ($this->markAsSentAction)(['record' => $card->id]) }} {{ ($this->editAssignmentAction)(['record' => $card->id]) }} {{ ($this->deleteAssignmentAction)(['record' => $card->id]) }} @endcanAny diff --git a/resources/views/filament/resources/learning/assignments/submission-detail.blade.php b/resources/views/filament/resources/learning/assignments/submission-detail.blade.php index e012398..6e18b74 100644 --- a/resources/views/filament/resources/learning/assignments/submission-detail.blade.php +++ b/resources/views/filament/resources/learning/assignments/submission-detail.blade.php @@ -26,11 +26,18 @@ style="width: {{ $this->percentage }}%">
- - {{ $this->assignmentSummary['title'] }} + +
+ {{ $this->assignmentSummary['title'] }} + @if ($this->assignmentSummary['is_sent_to_lecturer']) + Sudah Dikirim ke Dosen + @endif +
+
{{ $this->assignmentSummary['course'] }}  ยท  diff --git a/resources/views/filament/resources/learning/assignments/submit-assignment.blade.php b/resources/views/filament/resources/learning/assignments/submit-assignment.blade.php index 05a17f0..88dafd4 100644 --- a/resources/views/filament/resources/learning/assignments/submit-assignment.blade.php +++ b/resources/views/filament/resources/learning/assignments/submit-assignment.blade.php @@ -5,7 +5,7 @@ {{ $this->record->title }} {{ $this->record->course?->name ?? '-' }} -
+
@foreach ($this->statusCards as $card)
@@ -44,29 +44,28 @@ class="block border-0"> @endif - @if ($this->isOverdue) + {{-- Kondisi Form: Muncul jika BELUM dikirim ke dosen --}} + @if ($this->record->is_sent_to_lecturer) - {{ $this->overdueHeading }} - {{ $this->overdueDescription }} + Penerimaan Tugas Ditutup + Tugas ini sudah dikirim ke dosen oleh Kosma dan tidak dapat diubah lagi.
-
- - {{ $this->submissionStatus->badge_label }} - +
+ Tugas sudah dikirim ke dosen pada status final.
@if ($url = $this->getSubmissionFileUrl())
-

File yang Dikumpulkan

+

File yang Terakhir Dikumpulkan

-
@@ -96,6 +95,16 @@ class="block border-0"> @endif @else + @if ($this->isOverdue) +
+ +
+

Tenggat Waktu Sudah Terlewat

+

Anda masih diperbolehkan mengumpulkan tugas karena belum dikirim ke dosen oleh Kosma.

+
+
+ @endif + {{ $this->submissionHeading }} {{ $this->submissionDescription }} diff --git a/resources/views/filament/resources/learning/attendances/index.blade.php b/resources/views/filament/resources/learning/attendances/index.blade.php index 9ef597f..96479be 100644 --- a/resources/views/filament/resources/learning/attendances/index.blade.php +++ b/resources/views/filament/resources/learning/attendances/index.blade.php @@ -1,6 +1,6 @@ - {{ $this->heading }} @@ -102,7 +102,7 @@ class="text-[10px] font-bold text-gray-400 uppercase tracking-widest leading-non @endforeach
@else - @@ -111,8 +111,8 @@ class="text-[10px] font-bold text-gray-400 uppercase tracking-widest leading-non
- {{ $this->historyHeading }} diff --git a/tests/Feature/AssignmentTest.php b/tests/Feature/AssignmentTest.php index 4260f08..4def8a9 100644 --- a/tests/Feature/AssignmentTest.php +++ b/tests/Feature/AssignmentTest.php @@ -366,3 +366,71 @@ ->assertSee($assignment->title); }); }); + +describe('Assignment Delivery Status', function () { + beforeEach(function () { + $this->kosmaUser = User::factory()->create(); + $this->kosmaUser->assignRole(RoleEnum::Kosma); + $this->kosmaUser->givePermissionTo(['ViewAny:Assignment', 'View:Assignment', 'View:CourseSchedule']); + + $this->studentUser = User::factory()->create(); + $this->studentUser->assignRole(RoleEnum::Student); + $this->studentUser->givePermissionTo(['ViewAny:Assignment', 'View:CourseSchedule']); + $this->student = Student::factory()->create(['user_id' => $this->studentUser->id]); + + $this->currentSemester = app(GeneralSettings::class)->current_semester; + }); + + it('can toggle assignment delivery status (Mark as Sent)', function () { + $assignment = Assignment::factory()->create([ + 'is_sent_to_lecturer' => false, + ]); + + $this->actingAs($this->kosmaUser); + + Livewire::test(ListAssignments::class) + ->callAction('markAsSentAction', [], ['record' => $assignment->id]); + + expect($assignment->refresh()->is_sent_to_lecturer)->toBeTrue(); + + Livewire::test(ListAssignments::class) + ->callAction('markAsSentAction', [], ['record' => $assignment->id]); + + expect($assignment->refresh()->is_sent_to_lecturer)->toBeFalse(); + }); + + it('allows students to submit overdue assignments if not yet sent to lecturer', function () { + $assignment = Assignment::factory()->create([ + 'due_date' => now()->subDays(2)->toDateTimeString(), // Far enough in the past + 'is_sent_to_lecturer' => false, + 'type' => AssignmentType::Individual, + ]); + $assignment->students()->attach($this->student->id); + $assignment->course->update(['semester' => $this->currentSemester]); + + $this->actingAs($this->studentUser); + + Livewire::test(SubmitAssignmentPage::class, ['record' => $assignment]) + ->assertSuccessful() + ->assertSet('isOverdue', true) + ->assertSet('canSubmit', true) + ->assertSee('Tenggat Waktu Sudah Terlewat'); + }); + + it('prevents students from submitting if assignment is marked as sent to lecturer', function () { + $assignment = Assignment::factory()->create([ + 'due_date' => now()->addDay(), + 'is_sent_to_lecturer' => true, + ]); + $assignment->students()->attach($this->student->id); + $assignment->course->update(['semester' => $this->currentSemester]); + + $this->actingAs($this->studentUser); + + Livewire::test(SubmitAssignmentPage::class, ['record' => $assignment]) + ->assertSuccessful() + ->assertSee('Penerimaan Tugas Ditutup') + ->assertDontSeeHtml('type="file"'); + }); +}); +