feat: enhance assignment sharing view to support group assignments and update submission statistics display
This commit is contained in:
parent
9d05e4b594
commit
b05e5212b3
@ -55,10 +55,9 @@ public function deleteAssignmentAction(): Action
|
||||
public function assignments(): Collection
|
||||
{
|
||||
$studentProfile = auth()->user()->student;
|
||||
|
||||
$pinnedIds = $this->pinnedIds;
|
||||
|
||||
return Assignment::with(['course', 'assignmentSubmissions' => function ($q) use ($studentProfile) {
|
||||
$assignments = Assignment::with(['course', 'assignmentSubmissions' => function ($q) use ($studentProfile) {
|
||||
$q->where('student_id', $studentProfile->id)
|
||||
->orWhereHas('studyGroup', fn ($sq) => $sq->where('leader_id', $studentProfile->id)->orWhereHas('students', fn ($ssq) => $ssq->whereKey($studentProfile->id)));
|
||||
}, 'studyGroups.students'])
|
||||
@ -69,12 +68,49 @@ public function assignments(): Collection
|
||||
$query->whereHas('students', fn ($q) => $q->whereKey($studentProfile->id))
|
||||
->orWhereHas('studyGroups', fn ($q) => $q->where('leader_id', $studentProfile->id)->orWhereHas('students', fn ($sq) => $sq->whereKey($studentProfile->id)));
|
||||
})
|
||||
->when(! empty($pinnedIds), function ($query) use ($pinnedIds) {
|
||||
$ids = implode(',', $pinnedIds);
|
||||
$query->orderByRaw("FIELD(id, $ids) DESC");
|
||||
})
|
||||
->orderBy('due_date')
|
||||
->get();
|
||||
|
||||
return $assignments->sort(function ($a, $b) use ($pinnedIds) {
|
||||
if (! empty($pinnedIds)) {
|
||||
$aIndex = array_search($a->id, $pinnedIds);
|
||||
$bIndex = array_search($b->id, $pinnedIds);
|
||||
|
||||
$aPinned = $aIndex !== false;
|
||||
$bPinned = $bIndex !== false;
|
||||
|
||||
if ($aPinned && $bPinned) {
|
||||
return $bIndex <=> $aIndex;
|
||||
}
|
||||
if ($aPinned) {
|
||||
return -1;
|
||||
}
|
||||
if ($bPinned) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
$aPriority = $this->getAssignmentPriority($a);
|
||||
$bPriority = $this->getAssignmentPriority($b);
|
||||
|
||||
if ($aPriority !== $bPriority) {
|
||||
return $aPriority <=> $bPriority;
|
||||
}
|
||||
|
||||
return $a->due_date <=> $b->due_date;
|
||||
});
|
||||
}
|
||||
|
||||
private function getAssignmentPriority($assignment): int
|
||||
{
|
||||
$isSubmitted = $assignment->assignmentSubmissions->isNotEmpty();
|
||||
$isOverdue = now()->isAfter($assignment->due_date);
|
||||
|
||||
if (! $isOverdue) {
|
||||
return $isSubmitted ? 2 : 1;
|
||||
}
|
||||
|
||||
// Overdue
|
||||
return $isSubmitted ? 3 : 4;
|
||||
}
|
||||
|
||||
#[Computed]
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\AssignmentType;
|
||||
use App\Models\Assignment;
|
||||
use App\Models\AssignmentSubmission;
|
||||
use App\Models\Course;
|
||||
@ -15,13 +16,11 @@ class ShareAssignmentController extends Controller
|
||||
public function show(Request $request, Course $course): View
|
||||
{
|
||||
|
||||
// Retrieve available assignments for the dropdown (from the whole course)
|
||||
$availableAssignments = Assignment::where('course_id', $course->id)
|
||||
->with('classSession')
|
||||
->orderBy('created_at', 'desc')
|
||||
->get();
|
||||
|
||||
// Default: If session_id is provided, try to find an assignment for that session, or fallback to latest assignment.
|
||||
$assignmentId = $request->query('assignment_id');
|
||||
$sessionId = $request->query('session_id');
|
||||
|
||||
@ -36,17 +35,28 @@ public function show(Request $request, Course $course): View
|
||||
|
||||
$sessionInfo = $assignment ? $assignment->classSession : null;
|
||||
|
||||
// Get submissions and calculate stats
|
||||
$submissions = collect();
|
||||
$isGroup = false;
|
||||
$totalTargets = 0;
|
||||
|
||||
if ($assignment) {
|
||||
$submissions = AssignmentSubmission::with(['student', 'media'])
|
||||
$isGroup = $assignment->type === AssignmentType::Group;
|
||||
$submissions = AssignmentSubmission::with(['student', 'media', 'studyGroup.students'])
|
||||
->where('assignment_id', $assignment->id)
|
||||
->get();
|
||||
|
||||
if ($isGroup) {
|
||||
$totalTargets = $assignment->studyGroups()->count();
|
||||
} else {
|
||||
$totalTargets = $assignment->students()->count();
|
||||
if ($totalTargets === 0) {
|
||||
$totalTargets = Student::whereHas('user', fn ($q) => $q->active())->count();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$totalStudents = Student::whereHas('user', fn ($q) => $q->active())->count();
|
||||
$submittedCount = $submissions->count();
|
||||
$submissionPercentage = $totalStudents > 0 ? round(($submittedCount / $totalStudents) * 100) : 0;
|
||||
$submissionPercentage = $totalTargets > 0 ? round(($submittedCount / $totalTargets) * 100) : 0;
|
||||
|
||||
$formattedDeadline = $assignment && $assignment->due_date
|
||||
? Carbon::parse($assignment->due_date)->translatedFormat('l, d F Y H:i')
|
||||
@ -58,10 +68,11 @@ public function show(Request $request, Course $course): View
|
||||
'availableAssignments',
|
||||
'sessionInfo',
|
||||
'submissions',
|
||||
'totalStudents',
|
||||
'totalTargets',
|
||||
'submittedCount',
|
||||
'submissionPercentage',
|
||||
'formattedDeadline'
|
||||
'formattedDeadline',
|
||||
'isGroup'
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,8 +73,8 @@ class="fi-card rounded-xl border border-gray-200 dark:border-gray-700 bg-white d
|
||||
<thead
|
||||
class="border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50">
|
||||
<tr>
|
||||
<th class="px-5 py-4 font-semibold text-gray-950 dark:text-white">Mahasiswa</th>
|
||||
<th class="px-5 py-4 font-semibold text-gray-950 dark:text-white">Nomor Induk
|
||||
<th class="px-5 py-4 font-semibold text-gray-950 dark:text-white">{{ $isGroup ? 'Kelompok' : 'Mahasiswa' }}</th>
|
||||
<th class="px-5 py-4 font-semibold text-gray-950 dark:text-white">{{ $isGroup ? 'Anggota' : 'Nomor Induk' }}
|
||||
</th>
|
||||
<th class="px-5 py-4 font-semibold text-gray-950 dark:text-white">Hasil Tugas
|
||||
</th>
|
||||
@ -88,15 +88,29 @@ class="border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800
|
||||
<td class="px-5 py-4">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="flex flex-col gap-0.5">
|
||||
<span
|
||||
class="font-bold text-gray-950 dark:text-white text-sm">{{ $submission->student->full_name }}</span>
|
||||
@if($isGroup && $submission->studyGroup)
|
||||
<span class="font-bold text-gray-950 dark:text-white text-sm">{{ $submission->studyGroup->name }}</span>
|
||||
<span class="text-[10px] text-gray-500 dark:text-gray-400">Pengumpul: {{ $submission->student->full_name }}</span>
|
||||
@else
|
||||
<span class="font-bold text-gray-950 dark:text-white text-sm">{{ $submission->student->full_name }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-5 py-4">
|
||||
<span class="text-gray-500 dark:text-gray-400 font-medium text-sm">
|
||||
{{ $submission->student->student_number }}
|
||||
</span>
|
||||
@if($isGroup && $submission->studyGroup)
|
||||
<div class="flex flex-wrap gap-1 max-w-[200px]">
|
||||
@foreach($submission->studyGroup->students as $member)
|
||||
<span class="inline-flex items-center rounded-md bg-gray-50 dark:bg-gray-800/50 px-1.5 py-0.5 text-[10px] font-medium text-gray-600 dark:text-gray-400 ring-1 ring-inset ring-gray-500/10 whitespace-nowrap">
|
||||
{{ $member->full_name }}
|
||||
</span>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<span class="text-gray-500 dark:text-gray-400 font-medium text-sm">
|
||||
{{ $submission->student->student_number }}
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-5 py-4">
|
||||
<div class="flex flex-col gap-2 max-w-sm">
|
||||
@ -182,6 +196,10 @@ class="fi-card rounded-xl border border-gray-200 dark:border-gray-700 bg-white d
|
||||
Sesi Ke-{{ $assignment->classSession->session_number }}
|
||||
</span>
|
||||
@endif
|
||||
|
||||
<span class="inline-flex items-center rounded-md {{ $isGroup ? 'bg-indigo-50 dark:bg-indigo-500/10 text-indigo-600 dark:text-indigo-400 ring-indigo-500/20' : 'bg-emerald-50 dark:bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 ring-emerald-500/20' }} px-2 py-0.5 mt-2 text-[10px] font-bold uppercase tracking-wider ring-1 ring-inset w-fit ml-1">
|
||||
{{ $isGroup ? 'Tugas Kelompok' : 'Tugas Individu' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-gray-100 dark:border-gray-800"></div>
|
||||
@ -192,8 +210,8 @@ class="fi-card rounded-xl border border-gray-200 dark:border-gray-700 bg-white d
|
||||
class="text-[10px] font-bold text-gray-400 dark:text-gray-500 uppercase tracking-widest mb-0.5">Terkumpul</span>
|
||||
<span
|
||||
class="text-sm font-bold text-gray-950 dark:text-white">{{ $submittedCount }}<span
|
||||
class="text-[10px] text-gray-400 font-normal ml-0.5">/{{ $totalStudents }}</span>
|
||||
Orang</span>
|
||||
class="text-[10px] text-gray-400 font-normal ml-0.5">/{{ $totalTargets }}</span>
|
||||
{{ $isGroup ? 'Kelompok' : 'Orang' }}</span>
|
||||
|
||||
<div class="mt-2 flex items-center gap-2">
|
||||
<div
|
||||
|
||||
Loading…
Reference in New Issue
Block a user