feat: add assignment status indication and improve submission logic for assigned students
This commit is contained in:
parent
7c5b279689
commit
eb39408dae
@ -186,16 +186,25 @@ public function assignments(): Collection
|
|||||||
|
|
||||||
$pinnedIds = $this->pinnedIds;
|
$pinnedIds = $this->pinnedIds;
|
||||||
|
|
||||||
$assignments = Assignment::with(['course', 'assignmentSubmissions' => function ($q) use ($studentProfile) {
|
$isStaff = auth()->user()->hasAnyRole(['Developer', 'Kosma']);
|
||||||
$q->where('student_id', $studentProfile->id)
|
|
||||||
->orWhereHas('studyGroup', fn ($sq) => $sq->where('leader_id', $studentProfile->id)->orWhereHas('students', fn ($ssq) => $ssq->whereKey($studentProfile->id)));
|
$assignments = Assignment::with([
|
||||||
}, 'studyGroups.students'])
|
'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',
|
||||||
|
'students',
|
||||||
|
])
|
||||||
->whereHas('course', function ($q) {
|
->whereHas('course', function ($q) {
|
||||||
$q->where('semester', app(GeneralSettings::class)->current_semester);
|
$q->where('semester', app(GeneralSettings::class)->current_semester);
|
||||||
})
|
})
|
||||||
->where(function ($query) use ($studentProfile) {
|
->when(! $isStaff, function ($query) use ($studentProfile) {
|
||||||
$query->whereHas('students', fn ($q) => $q->whereKey($studentProfile->id))
|
$query->where(function ($q) use ($studentProfile) {
|
||||||
->orWhereHas('studyGroups', fn ($q) => $q->where('leader_id', $studentProfile->id)->orWhereHas('students', fn ($sq) => $sq->whereKey($studentProfile->id)));
|
$q->whereHas('students', fn ($sq) => $sq->whereKey($studentProfile->id))
|
||||||
|
->orWhereHas('studyGroups', fn ($sq) => $sq->where('leader_id', $studentProfile->id)->orWhereHas('students', fn ($ssq) => $ssq->whereKey($studentProfile->id)));
|
||||||
|
});
|
||||||
})
|
})
|
||||||
->when($this->search, function ($query) {
|
->when($this->search, function ($query) {
|
||||||
$query->where(function ($q) {
|
$query->where(function ($q) {
|
||||||
@ -273,11 +282,15 @@ public function assignmentCards()
|
|||||||
$isGroup = $assignment->type === AssignmentType::Group;
|
$isGroup = $assignment->type === AssignmentType::Group;
|
||||||
|
|
||||||
$isLeader = false;
|
$isLeader = false;
|
||||||
|
$isAssigned = false;
|
||||||
if ($isGroup) {
|
if ($isGroup) {
|
||||||
$userGroup = $assignment->studyGroups?->first(function ($g) use ($studentProfile) {
|
$userGroup = $assignment->studyGroups?->first(function ($g) use ($studentProfile) {
|
||||||
return $g->leader_id === $studentProfile->id || $g->students?->contains($studentProfile->id);
|
return $g->leader_id === $studentProfile->id || $g->students?->contains($studentProfile->id);
|
||||||
});
|
});
|
||||||
$isLeader = $userGroup && $userGroup->leader_id === $studentProfile->id;
|
$isLeader = $userGroup && $userGroup->leader_id === $studentProfile->id;
|
||||||
|
$isAssigned = $userGroup !== null;
|
||||||
|
} else {
|
||||||
|
$isAssigned = $assignment->students?->contains($studentProfile->id) ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$isSentToLecturer = $assignment->is_sent_to_lecturer;
|
$isSentToLecturer = $assignment->is_sent_to_lecturer;
|
||||||
@ -286,13 +299,17 @@ public function assignmentCards()
|
|||||||
$canSubmit = ! $isSentToLecturer;
|
$canSubmit = ! $isSentToLecturer;
|
||||||
|
|
||||||
$canSubmitByRole = ! $isGroup || $isLeader;
|
$canSubmitByRole = ! $isGroup || $isLeader;
|
||||||
$canSubmitActual = $canSubmit && $canSubmitByRole;
|
$canSubmitActual = $canSubmit && $canSubmitByRole && $isAssigned;
|
||||||
|
|
||||||
$isUrgent = ! $isSubmitted && $canSubmitActual && now()->diffInHours($assignment->due_date) <= 48;
|
$isUrgent = $isAssigned && ! $isSubmitted && $canSubmitActual && now()->diffInHours($assignment->due_date) <= 48;
|
||||||
$isNew = $assignment->created_at?->diffInDays(now()) <= 3;
|
$isNew = $assignment->created_at?->diffInDays(now()) <= 3;
|
||||||
$isPinned = in_array($assignment->id, $pinnedIds);
|
$isPinned = in_array($assignment->id, $pinnedIds);
|
||||||
|
|
||||||
if ($isSubmitted) {
|
if (! $isAssigned) {
|
||||||
|
$submissionLabel = 'Tidak Ditugaskan';
|
||||||
|
$submissionColor = 'gray';
|
||||||
|
$submissionIcon = 'heroicon-o-minus-circle';
|
||||||
|
} elseif ($isSubmitted) {
|
||||||
$submissionLabel = SystemNotification::getByKey('labels.assignment_status.submitted');
|
$submissionLabel = SystemNotification::getByKey('labels.assignment_status.submitted');
|
||||||
$submissionColor = 'success';
|
$submissionColor = 'success';
|
||||||
$submissionIcon = 'heroicon-o-check-circle';
|
$submissionIcon = 'heroicon-o-check-circle';
|
||||||
@ -329,12 +346,13 @@ public function assignmentCards()
|
|||||||
'is_urgent' => $isUrgent,
|
'is_urgent' => $isUrgent,
|
||||||
'is_new' => $isNew,
|
'is_new' => $isNew,
|
||||||
'is_pinned' => $isPinned,
|
'is_pinned' => $isPinned,
|
||||||
|
'is_assigned' => $isAssigned,
|
||||||
'submission_status' => (object) [
|
'submission_status' => (object) [
|
||||||
'label' => $submissionLabel,
|
'label' => $submissionLabel,
|
||||||
'color' => $submissionColor,
|
'color' => $submissionColor,
|
||||||
'icon' => $submissionIcon,
|
'icon' => $submissionIcon,
|
||||||
'classes' => Arr::toCssClasses([
|
'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
|
'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-semibold',
|
||||||
'bg-success-100 text-success-700 dark:bg-success-900/30 dark:text-success-400' => $submissionColor === 'success',
|
'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-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-warning-100 text-warning-700 dark:bg-warning-900/30 dark:text-warning-400' => $submissionColor === 'warning',
|
||||||
@ -346,7 +364,7 @@ public function assignmentCards()
|
|||||||
'color' => $deliveryColor,
|
'color' => $deliveryColor,
|
||||||
'icon' => $deliveryIcon,
|
'icon' => $deliveryIcon,
|
||||||
'classes' => Arr::toCssClasses([
|
'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
|
'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-bold ring-1 ring-inset',
|
||||||
'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-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',
|
'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',
|
||||||
]),
|
]),
|
||||||
@ -355,15 +373,17 @@ public function assignmentCards()
|
|||||||
// Pre-calculated classes
|
// Pre-calculated classes
|
||||||
'card_classes' => Arr::toCssClasses([
|
'card_classes' => Arr::toCssClasses([
|
||||||
'group flex w-full rounded-xl border transition-all overflow-hidden relative',
|
'group flex w-full rounded-xl border transition-all overflow-hidden relative',
|
||||||
'border-primary-300 dark:border-primary-700 bg-primary-50/30 dark:bg-primary-900/10 shadow-sm' => $isPinned,
|
'border-dashed border-gray-300 dark:border-gray-700 bg-gray-50/50 dark:bg-gray-800/10 opacity-75' => ! $isAssigned,
|
||||||
'border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800' => ! $isPinned && $canSubmitActual,
|
'border-primary-300 dark:border-primary-700 bg-primary-50/30 dark:bg-primary-900/10 shadow-sm' => $isAssigned && $isPinned,
|
||||||
'border-gray-100 dark:border-gray-800 bg-gray-50 dark:bg-gray-800/40 opacity-80' => ! $canSubmitActual,
|
'border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800' => $isAssigned && ! $isPinned && $canSubmitActual,
|
||||||
|
'border-gray-100 dark:border-gray-800 bg-gray-50 dark:bg-gray-800/40 opacity-80' => $isAssigned && ! $isPinned && ! $canSubmitActual,
|
||||||
]),
|
]),
|
||||||
'icon_wrapper_classes' => Arr::toCssClasses([
|
'icon_wrapper_classes' => Arr::toCssClasses([
|
||||||
'flex h-11 w-11 shrink-0 items-center justify-center rounded-lg',
|
'flex h-11 w-11 shrink-0 items-center justify-center rounded-lg',
|
||||||
'bg-success-50 dark:bg-success-900/20 text-success-600 dark:text-success-400' => $isSubmitted,
|
'bg-gray-100 dark:bg-gray-800 text-gray-400' => ! $isAssigned,
|
||||||
'bg-danger-50 dark:bg-danger-900/20 text-danger-600 dark:text-danger-400' => ! $isSubmitted && $isOverdue,
|
'bg-success-50 dark:bg-success-900/20 text-success-600 dark:text-success-400' => $isAssigned && $isSubmitted,
|
||||||
'bg-warning-50 dark:bg-warning-900/20 text-warning-600 dark:text-warning-400' => ! $isSubmitted && ! $isOverdue,
|
'bg-danger-50 dark:bg-danger-900/20 text-danger-600 dark:text-danger-400' => $isAssigned && ! $isSubmitted && $isOverdue,
|
||||||
|
'bg-warning-50 dark:bg-warning-900/20 text-warning-600 dark:text-warning-400' => $isAssigned && ! $isSubmitted && ! $isOverdue,
|
||||||
]),
|
]),
|
||||||
'indicator_icon_classes' => Arr::toCssClasses([
|
'indicator_icon_classes' => Arr::toCssClasses([
|
||||||
'h-5 w-5 opacity-20',
|
'h-5 w-5 opacity-20',
|
||||||
|
|||||||
@ -101,7 +101,7 @@ public function statusCards(): array
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[Computed]
|
#[Computed]
|
||||||
public function student(): Student
|
public function student(): ?Student
|
||||||
{
|
{
|
||||||
/** @var User|null $user */
|
/** @var User|null $user */
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
@ -152,9 +152,28 @@ public function isOverdue(): bool
|
|||||||
return now()->isAfter($this->record?->due_date);
|
return now()->isAfter($this->record?->due_date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Computed]
|
||||||
|
public function isAssigned(): bool
|
||||||
|
{
|
||||||
|
$student = $this->student;
|
||||||
|
if (! $student) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->record?->type === AssignmentType::Individual) {
|
||||||
|
return $this->record?->students()->whereKey($student->id)->exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->currentGroup !== null;
|
||||||
|
}
|
||||||
|
|
||||||
#[Computed]
|
#[Computed]
|
||||||
public function canSubmit(): bool
|
public function canSubmit(): bool
|
||||||
{
|
{
|
||||||
|
if (! $this->isAssigned) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->record?->type === AssignmentType::Individual) {
|
if ($this->record?->type === AssignmentType::Individual) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,6 +38,12 @@ class="inline-flex items-center gap-1.5 rounded-full bg-primary-100 text-primary
|
|||||||
📌 Dipinned
|
📌 Dipinned
|
||||||
</span>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
|
@if (isset($card->is_assigned) && ! $card->is_assigned)
|
||||||
|
<span
|
||||||
|
class="inline-flex items-center gap-1.5 rounded-full bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300 px-2.5 py-1 text-xs font-bold whitespace-nowrap border border-gray-200 dark:border-gray-700">
|
||||||
|
🚫 Tidak Ditugaskan
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
@if ($card->is_new)
|
@if ($card->is_new)
|
||||||
<span
|
<span
|
||||||
class="inline-flex items-center gap-1.5 rounded-full bg-violet-100 text-violet-700 dark:bg-violet-900/30 dark:text-violet-400 px-2.5 py-1 text-xs font-bold whitespace-nowrap border border-violet-200/50 dark:border-violet-500/20">
|
class="inline-flex items-center gap-1.5 rounded-full bg-violet-100 text-violet-700 dark:bg-violet-900/30 dark:text-violet-400 px-2.5 py-1 text-xs font-bold whitespace-nowrap border border-violet-200/50 dark:border-violet-500/20">
|
||||||
|
|||||||
@ -105,6 +105,17 @@ class="block border-0"></iframe>
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</x-filament::section>
|
</x-filament::section>
|
||||||
|
@elseif (!$this->isAssigned)
|
||||||
|
<x-filament::section>
|
||||||
|
<div
|
||||||
|
class="flex flex-col items-center justify-center py-8 text-center text-gray-500 dark:text-gray-400">
|
||||||
|
<x-filament::icon icon="heroicon-o-x-circle" class="w-12 h-12 mb-3 text-gray-400" />
|
||||||
|
<p class="font-semibold text-gray-700 dark:text-gray-300">Anda Tidak Ditugaskan</p>
|
||||||
|
<p class="text-sm mt-1 max-w-sm">
|
||||||
|
Anda dapat melihat detail tugas ini karena role Anda (Kosma/Developer), tetapi Anda tidak ditugaskan untuk mengumpulkannya.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</x-filament::section>
|
||||||
@elseif (!$this->canSubmit)
|
@elseif (!$this->canSubmit)
|
||||||
<x-filament::section>
|
<x-filament::section>
|
||||||
<div
|
<div
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user