Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 96 additions & 12 deletions app/Http/Controllers/Mahasiswa/LmsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,118 @@

use App\Http\Controllers\Controller;
use App\Models\Kelas;
use App\Models\TahunAkademik;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LmsController extends Controller
{
/**
* Show LMS dashboard with enrolled kelas
* Supports semester filtering: aktif, arsip, semua
*/
public function index()
public function index(Request $request)
{
$mahasiswa = Auth::user()->mahasiswa;
if (!$mahasiswa) {
abort(403, 'Anda tidak memiliki akses sebagai mahasiswa.');
}

// Get enrolled kelas
$krs = $mahasiswa->krs()->where('status', 'approved')->first();
$kelasIds = $krs?->krsDetail?->pluck('kelas_id')->toArray() ?? [];
// Get active tahun akademik
$tahunAktif = TahunAkademik::active();

// Get all approved KRS with kelas data
$allKrs = $mahasiswa->krs()
->where('status', 'approved')
->with(['tahunAkademik', 'krsDetail.kelas.mataKuliah', 'krsDetail.kelas.dosen.user', 'krsDetail.kelas.tahunAkademik'])
->get();

$kelasList = Kelas::whereIn('id', $kelasIds)
->with(['mataKuliah', 'dosen.user', 'tugas' => fn($q) => $q->where('is_active', true)])
->get()
->map(function($kelas) use ($mahasiswa) {
// Count pending tugas (not submitted yet)
$submittedTugasIds = $mahasiswa->tugasSubmissions()->pluck('tugas_id')->toArray();
$kelas->pending_tugas = $kelas->tugas->whereNotIn('id', $submittedTugasIds)->count();
// Extract all kelas from KRS details with the KRS tahun_akademik for proper filtering
$allKelas = $allKrs->flatMap(function($krs) {
return $krs->krsDetail->map(function($detail) use ($krs) {
$kelas = $detail->kelas;
$kelas->krs_tahun_akademik = $krs->tahunAkademik;
$kelas->krs_tahun_akademik_id = $krs->tahun_akademik_id; // Use this for filtering!
return $kelas;
});
})->unique('id');

// Get available semesters for dropdown with sequential numbering
$semesterList = $allKrs->pluck('tahunAkademik')->unique('id')->sortBy('id'); // Sort chronologically (oldest first)

// Add semester number (Semester 1, 2, 3...) based on enrollment order
$semesterNumber = 1;
$availableSemesters = $semesterList->map(function($semester) use (&$semesterNumber) {
$semester->semester_number = $semesterNumber;
$semester->semester_label = "Semester {$semesterNumber}";
$semesterNumber++;
return $semester;
})->sortByDesc('id'); // Sort back to newest first for dropdown display

// Get current semester number (for active semester)
$currentSemesterNumber = $tahunAktif ? $availableSemesters->firstWhere('id', $tahunAktif->id)?->semester_number : null;

// Determine semester filter - USE krs_tahun_akademik_id for filtering (semester when enrolled)
if ($tahunAktif === null) {
// Libur semester: check if specific semester is selected
$semesterFilter = $request->query('semester', 'semua');

if (is_numeric($semesterFilter)) {
// Filter by specific semester (using KRS tahun akademik)
$kelasList = $allKelas->filter(fn($k) => $k->krs_tahun_akademik_id == $semesterFilter);
} else {
// Show all classes
$kelasList = $allKelas;
$semesterFilter = 'semua';
}
} else {
$semesterFilter = $request->query('semester', 'aktif');

if (is_numeric($semesterFilter)) {
// Filter by specific semester ID (using KRS tahun akademik)
$kelasList = $allKelas->filter(fn($k) => $k->krs_tahun_akademik_id == $semesterFilter);
} elseif ($semesterFilter === 'aktif') {
// Show active semester classes (using KRS tahun akademik)
$kelasList = $allKelas->filter(fn($k) => $k->krs_tahun_akademik_id === $tahunAktif->id);
} else {
// Default to active
$kelasList = $allKelas->filter(fn($k) => $k->krs_tahun_akademik_id === $tahunAktif->id);
$semesterFilter = 'aktif';
}
}

// Add pending tugas count and archive status to each kelas
$kelasList = $kelasList->map(function($kelas) use ($mahasiswa, $tahunAktif) {
// Count pending tugas (only for active semester)
// Use krs_tahun_akademik_id to determine if archived (based on enrollment semester)
$isArchived = $tahunAktif === null || $kelas->krs_tahun_akademik_id !== $tahunAktif->id;
$kelas->is_archived = $isArchived;

if (!$isArchived) {
$submittedTugasIds = $mahasiswa->tugasSubmissions()->pluck('tugas_id')->toArray();
$activeTugas = $kelas->tugas()->where('is_active', true)->get();
$kelas->pending_tugas = $activeTugas->whereNotIn('id', $submittedTugasIds)->count();
} else {
$kelas->pending_tugas = 0;
}

return $kelas;
});

// Group by semester for display (especially for 'semua' views)
// Use krs_tahun_akademik_id for proper grouping by enrollment semester
$kelasGrouped = $kelasList->groupBy(function($kelas) use ($availableSemesters) {
$semester = $availableSemesters->firstWhere('id', $kelas->krs_tahun_akademik_id);
return $semester?->semester_label ?? $kelas->krs_tahun_akademik->display_name ?? 'Unknown';
});

return view('mahasiswa.lms.index', compact('kelasList'));
return view('mahasiswa.lms.index', compact(
'kelasList',
'kelasGrouped',
'semesterFilter',
'availableSemesters',
'tahunAktif',
'currentSemesterNumber'
));
}
}
12 changes: 9 additions & 3 deletions app/Http/Controllers/Mahasiswa/MateriController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use App\Models\Kelas;
use App\Models\Materi;
use App\Models\Pertemuan;
use App\Models\TahunAkademik;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
Expand All @@ -14,6 +15,7 @@ class MateriController extends Controller
{
/**
* Show materi for a specific kelas (mahasiswa view)
* Supports historical access for archived semesters
*/
public function index($kelasId)
{
Expand All @@ -22,7 +24,7 @@ public function index($kelasId)
abort(403, 'Anda tidak memiliki akses sebagai mahasiswa.');
}

// Verify mahasiswa is enrolled in this kelas
// Verify mahasiswa is enrolled in this kelas (from any semester)
$isEnrolled = $mahasiswa->krs()
->where('status', 'approved')
->whereHas('krsDetail', fn($q) => $q->where('kelas_id', $kelasId))
Expand All @@ -32,15 +34,19 @@ public function index($kelasId)
abort(403, 'Anda tidak terdaftar di kelas ini.');
}

$kelas = Kelas::with('mataKuliah', 'dosen.user')->findOrFail($kelasId);
$kelas = Kelas::with('mataKuliah', 'dosen.user', 'tahunAkademik')->findOrFail($kelasId);

// Check if this is an archived class
$tahunAktif = TahunAkademik::active();
$isArchived = $tahunAktif === null || $kelas->tahun_akademik_id !== $tahunAktif->id;

// Get all pertemuan for this kelas
$pertemuanList = Pertemuan::whereHas('jadwalKuliah', fn($q) => $q->where('kelas_id', $kelasId))
->with('materiList')
->orderBy('pertemuan_ke')
->get();

return view('mahasiswa.materi.index', compact('kelas', 'pertemuanList'));
return view('mahasiswa.materi.index', compact('kelas', 'pertemuanList', 'isArchived'));
}

/**
Expand Down
42 changes: 29 additions & 13 deletions app/Http/Controllers/Mahasiswa/TugasController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use App\Http\Controllers\Controller;
use App\Models\Kelas;
use App\Models\TahunAkademik;
use App\Models\Tugas;
use App\Models\TugasSubmission;
use Illuminate\Http\Request;
Expand All @@ -14,12 +15,13 @@ class TugasController extends Controller
{
/**
* List all tugas for a kelas
* Supports historical access for archived semesters
*/
public function index($kelasId)
{
$mahasiswa = Auth::user()->mahasiswa;

// Verify enrollment
// Verify enrollment (from any semester)
$isEnrolled = $mahasiswa->krs()
->where('status', 'approved')
->whereHas('krsDetail', fn($q) => $q->where('kelas_id', $kelasId))
Expand All @@ -29,26 +31,35 @@ public function index($kelasId)
abort(403, 'Anda tidak terdaftar di kelas ini.');
}

$kelas = Kelas::with(['mataKuliah', 'dosen.user'])->findOrFail($kelasId);
$kelas = Kelas::with(['mataKuliah', 'dosen.user', 'tahunAkademik'])->findOrFail($kelasId);

// Check if this is an archived class
$tahunAktif = TahunAkademik::active();
$isArchived = $tahunAktif === null || $kelas->tahun_akademik_id !== $tahunAktif->id;

// Get tugas with submission status (show all tugas for archived, only active for current)
$tugasQuery = Tugas::where('kelas_id', $kelasId)
->with(['submissions' => fn($q) => $q->where('mahasiswa_id', $mahasiswa->id)]);

// For active semester, only show active tugas. For archived, show all.
if (!$isArchived) {
$tugasQuery->where('is_active', true);
}

// Get tugas with submission status
$tugasList = Tugas::where('kelas_id', $kelasId)
->where('is_active', true)
->with(['submissions' => fn($q) => $q->where('mahasiswa_id', $mahasiswa->id)])
->latest()
->get();

return view('mahasiswa.tugas.index', compact('kelas', 'tugasList', 'mahasiswa'));
$tugasList = $tugasQuery->latest()->get();

return view('mahasiswa.tugas.index', compact('kelas', 'tugasList', 'mahasiswa', 'isArchived'));
}

/**
* Show tugas detail
* Supports historical access for archived semesters
*/
public function show($kelasId, Tugas $tugas)
{
$mahasiswa = Auth::user()->mahasiswa;

// Verify enrollment
// Verify enrollment (from any semester)
$isEnrolled = $mahasiswa->krs()
->where('status', 'approved')
->whereHas('krsDetail', fn($q) => $q->where('kelas_id', $kelasId))
Expand All @@ -58,10 +69,15 @@ public function show($kelasId, Tugas $tugas)
abort(403);
}

$kelas = Kelas::with(['mataKuliah', 'dosen.user'])->findOrFail($kelasId);
$kelas = Kelas::with(['mataKuliah', 'dosen.user', 'tahunAkademik'])->findOrFail($kelasId);

// Check if this is an archived class
$tahunAktif = TahunAkademik::active();
$isArchived = $tahunAktif === null || $kelas->tahun_akademik_id !== $tahunAktif->id;

$submission = $tugas->submissions()->where('mahasiswa_id', $mahasiswa->id)->first();

return view('mahasiswa.tugas.show', compact('kelas', 'tugas', 'submission'));
return view('mahasiswa.tugas.show', compact('kelas', 'tugas', 'submission', 'isArchived'));
}

/**
Expand Down
47 changes: 47 additions & 0 deletions debug_output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
Mahasiswa: Budi Santoso
ID: 1

=== KRS Records ===
KRS #1 - TahunAkademik ID: 4 - 2022/2023 Ganjil
KRS Detail Count: 7
- Kelas ID: 1, Kelas Tahun: 3
- Kelas ID: 2, Kelas Tahun: 3
- Kelas ID: 3, Kelas Tahun: 3
- Kelas ID: 4, Kelas Tahun: 3
- Kelas ID: 5, Kelas Tahun: 3
- Kelas ID: 6, Kelas Tahun: 3
- Kelas ID: 7, Kelas Tahun: 3
KRS #2 - TahunAkademik ID: 5 - 2022/2023 Genap
KRS Detail Count: 7
- Kelas ID: 8, Kelas Tahun: 3
- Kelas ID: 9, Kelas Tahun: 3
- Kelas ID: 10, Kelas Tahun: 3
- Kelas ID: 11, Kelas Tahun: 3
- Kelas ID: 12, Kelas Tahun: 3
- Kelas ID: 13, Kelas Tahun: 3
- Kelas ID: 14, Kelas Tahun: 3
KRS #3 - TahunAkademik ID: 1 - 2023/2024 Ganjil
KRS Detail Count: 7
- Kelas ID: 15, Kelas Tahun: 1
- Kelas ID: 16, Kelas Tahun: 1
- Kelas ID: 17, Kelas Tahun: 1
- Kelas ID: 18, Kelas Tahun: 1
- Kelas ID: 19, Kelas Tahun: 1
- Kelas ID: 20, Kelas Tahun: 1
- Kelas ID: 21, Kelas Tahun: 1
KRS #4 - TahunAkademik ID: 2 - 2023/2024 Genap
KRS Detail Count: 7
- Kelas ID: 22, Kelas Tahun: 2
- Kelas ID: 23, Kelas Tahun: 2
- Kelas ID: 24, Kelas Tahun: 2
- Kelas ID: 25, Kelas Tahun: 2
- Kelas ID: 26, Kelas Tahun: 2
- Kelas ID: 27, Kelas Tahun: 2
- Kelas ID: 28, Kelas Tahun: 2

=== Tahun Akademik ===
ID: 1 - 2023/2024 Ganjil - Active: No
ID: 2 - 2023/2024 Genap - Active: No
ID: 3 - 2024/2025 Ganjil - Active: Yes
ID: 4 - 2022/2023 Ganjil - Active: No
ID: 5 - 2022/2023 Genap - Active: No
41 changes: 41 additions & 0 deletions debug_semester.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

require_once 'vendor/autoload.php';

$app = require_once 'bootstrap/app.php';
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();

use App\Models\Mahasiswa;
use App\Models\TahunAkademik;

$output = "";

// Get first mahasiswa
$mahasiswa = Mahasiswa::first();
$output .= "Mahasiswa: " . ($mahasiswa->user->name ?? 'Unknown') . "\n";
$output .= "ID: " . $mahasiswa->id . "\n\n";

// Get all approved KRS
$allKrs = $mahasiswa->krs()
->where('status', 'approved')
->with(['tahunAkademik', 'krsDetail.kelas'])
->get();

$output .= "=== KRS Records ===\n";
foreach ($allKrs as $krs) {
$output .= "KRS #{$krs->id} - TahunAkademik ID: {$krs->tahun_akademik_id} - {$krs->tahunAkademik->display_name}\n";
$output .= " KRS Detail Count: " . $krs->krsDetail->count() . "\n";
foreach ($krs->krsDetail as $detail) {
$kelas = $detail->kelas;
$output .= " - Kelas ID: {$detail->kelas_id}, Kelas Tahun: " . ($kelas->tahun_akademik_id ?? 'null') . "\n";
}
}

$output .= "\n=== Tahun Akademik ===\n";
$tahunAkademiks = TahunAkademik::orderBy('id')->get();
foreach ($tahunAkademiks as $ta) {
$output .= "ID: {$ta->id} - {$ta->display_name} - Active: " . ($ta->is_active ? 'Yes' : 'No') . "\n";
}

file_put_contents('debug_output.txt', $output);
echo "Output written to debug_output.txt\n";
43 changes: 43 additions & 0 deletions resources/views/mahasiswa/lms/_kelas-card.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{{-- Kelas Card Partial - reusable card component for kelas list --}}
<div class="kelas-card card-saas dark:bg-gray-800 overflow-hidden hover:shadow-lg transition-shadow" data-search="{{ strtolower($kelas->mataKuliah->nama_mk . ' ' . $kelas->mataKuliah->kode_mk . ' ' . ($kelas->dosen->user->name ?? '')) }}">
<div class="p-5">
<div class="flex items-start gap-3 mb-3">
<div class="w-12 h-12 bg-gradient-to-br from-siakad-primary to-siakad-dark rounded-xl flex items-center justify-center text-white font-bold text-lg flex-shrink-0">
{{ $kelas->nama_kelas }}
</div>
<div class="min-w-0 flex-1">
<div class="flex items-start justify-between gap-2">
<h3 class="font-semibold text-siakad-dark dark:text-white truncate">{{ $kelas->mataKuliah->nama_mk }}</h3>
@if($kelas->is_archived ?? false)
<span class="flex-shrink-0 px-2 py-0.5 text-xs font-medium bg-gray-100 dark:bg-gray-600 text-gray-600 dark:text-gray-300 rounded-full">
Arsip
</span>
@endif
</div>
<p class="text-xs text-siakad-secondary dark:text-gray-400">{{ $kelas->mataKuliah->kode_mk }} • {{ $kelas->mataKuliah->sks }} SKS</p>
</div>
</div>

<p class="text-xs text-siakad-secondary dark:text-gray-400 mb-4">
Dosen: {{ $kelas->dosen->user->name ?? '-' }}
</p>

@if(($kelas->pending_tugas ?? 0) > 0 && !($kelas->is_archived ?? false))
<div class="mb-4 px-3 py-2 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg">
<p class="text-xs text-amber-700 dark:text-amber-400 flex items-center gap-1">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path></svg>
{{ $kelas->pending_tugas }} tugas belum dikumpulkan
</p>
</div>
@endif

<div class="flex gap-2">
<a href="{{ route('mahasiswa.materi.index', $kelas->id) }}" class="flex-1 text-center px-3 py-2 text-sm font-medium bg-siakad-light dark:bg-gray-700 text-siakad-dark dark:text-white rounded-lg hover:bg-siakad-light/80 dark:hover:bg-gray-600 transition">
Materi
</a>
<a href="{{ route('mahasiswa.tugas.index', $kelas->id) }}" class="flex-1 text-center px-3 py-2 text-sm font-medium {{ $kelas->is_archived ?? false ? 'bg-gray-200 dark:bg-gray-600 text-gray-700 dark:text-gray-300' : 'bg-siakad-primary text-white hover:bg-siakad-primary/90' }} rounded-lg transition">
Tugas
</a>
</div>
</div>
</div>
Loading
Loading