314 lines
24 KiB
PHP
314 lines
24 KiB
PHP
<x-master-page title="Detail Siswa" description="Ringkasan lengkap data siswa yang tersimpan di sistem.">
|
|
@php
|
|
$isAdmin = auth()->user()?->isAdmin() ?? false;
|
|
@endphp
|
|
<div class="mb-6 rounded-3xl border border-slate-200 bg-white p-6 shadow-sm shadow-slate-200/50">
|
|
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
|
|
<div>
|
|
<h3 class="text-lg font-semibold text-slate-900">Kelengkapan Dokumen Wajib</h3>
|
|
<p class="mt-1 text-sm text-slate-500">Ringkasan upload dan verifikasi dokumen wajib siswa.</p>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-4 text-right">
|
|
<div>
|
|
<div class="text-3xl font-bold text-slate-900">{{ $requiredDocumentSummary['percentage'] }}%</div>
|
|
<div class="text-sm {{ $requiredDocumentSummary['missing'] === 0 ? 'text-emerald-600' : 'text-amber-600' }}">
|
|
{{ $requiredDocumentSummary['missing'] === 0 ? 'Upload lengkap' : 'Kurang ' . $requiredDocumentSummary['missing'] . ' dokumen' }}
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="text-3xl font-bold text-slate-900">{{ $requiredDocumentSummary['verification_percentage'] }}%</div>
|
|
<div class="text-sm {{ $requiredDocumentSummary['unverified'] === 0 && $requiredDocumentSummary['missing'] === 0 ? 'text-emerald-600' : 'text-sky-600' }}">
|
|
{{ $requiredDocumentSummary['unverified'] === 0 && $requiredDocumentSummary['missing'] === 0 ? 'Terverifikasi penuh' : $requiredDocumentSummary['unverified'] . ' belum valid' }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-4 space-y-4">
|
|
<div>
|
|
<div class="mb-2 flex items-center justify-between text-xs font-semibold uppercase tracking-[0.16em] text-slate-400">
|
|
<span>Upload Dokumen Wajib</span>
|
|
<span>{{ $requiredDocumentSummary['uploaded'] }}/{{ $requiredDocumentSummary['total'] }}</span>
|
|
</div>
|
|
<div class="h-3 overflow-hidden rounded-full bg-slate-200">
|
|
<div class="h-full rounded-full {{ $requiredDocumentSummary['missing'] === 0 ? 'bg-emerald-500' : 'bg-amber-500' }}" style="width: {{ $requiredDocumentSummary['percentage'] }}%"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<div class="mb-2 flex items-center justify-between text-xs font-semibold uppercase tracking-[0.16em] text-slate-400">
|
|
<span>Verifikasi Dokumen Wajib</span>
|
|
<span>{{ $requiredDocumentSummary['verified'] }}/{{ $requiredDocumentSummary['total'] }}</span>
|
|
</div>
|
|
<div class="h-3 overflow-hidden rounded-full bg-slate-200">
|
|
<div class="h-full rounded-full {{ $requiredDocumentSummary['unverified'] === 0 && $requiredDocumentSummary['missing'] === 0 ? 'bg-sky-500' : 'bg-slate-500' }}" style="width: {{ $requiredDocumentSummary['verification_percentage'] }}%"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@if ($requiredDocumentSummary['missing_items']->isNotEmpty() || $requiredDocumentSummary['unverified_items']->isNotEmpty())
|
|
<div class="mt-4 flex flex-wrap gap-2">
|
|
@foreach ($requiredDocumentSummary['missing_items'] as $missingDocument)
|
|
<span class="rounded-full bg-rose-100 px-3 py-1 text-xs font-semibold text-rose-700">Belum upload: {{ $missingDocument }}</span>
|
|
@endforeach
|
|
@foreach ($requiredDocumentSummary['unverified_items'] as $unverifiedDocument)
|
|
<span class="rounded-full bg-sky-100 px-3 py-1 text-xs font-semibold text-sky-700">Belum valid: {{ $unverifiedDocument }}</span>
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 gap-6 xl:grid-cols-3">
|
|
<x-master-card title="Identitas Utama" subtitle="Informasi inti siswa.">
|
|
<div class="space-y-4 text-sm text-slate-600">
|
|
<div><span class="font-semibold text-slate-800">Nama:</span> {{ $student->full_name }}</div>
|
|
<div><span class="font-semibold text-slate-800">NIS:</span> {{ $student->student_number ?: '-' }}</div>
|
|
<div><span class="font-semibold text-slate-800">NISN:</span> {{ $student->nisn ?: '-' }}</div>
|
|
<div><span class="font-semibold text-slate-800">Jenis Kelamin:</span> {{ $student->gender === 'L' ? 'Laki-laki' : 'Perempuan' }}</div>
|
|
<div><span class="font-semibold text-slate-800">TTL:</span> {{ $student->place_of_birth ?: '-' }}, {{ $student->date_of_birth?->format('d-m-Y') ?: '-' }}</div>
|
|
<div><span class="font-semibold text-slate-800">Agama:</span> {{ $student->religion ?: '-' }}</div>
|
|
<div><span class="font-semibold text-slate-800">Kewarganegaraan:</span> {{ $student->nationality ?: '-' }}</div>
|
|
<div><span class="font-semibold text-slate-800">Status:</span> {{ ucfirst($student->status) }}</div>
|
|
</div>
|
|
</x-master-card>
|
|
|
|
<x-master-card title="Akademik" subtitle="Relasi akademik siswa.">
|
|
<div class="space-y-4 text-sm text-slate-600">
|
|
<div><span class="font-semibold text-slate-800">Tahun Angkatan:</span> {{ $student->academicYear?->name ?: '-' }}</div>
|
|
<div><span class="font-semibold text-slate-800">Program Keahlian:</span> {{ $student->department?->name ?: '-' }}</div>
|
|
<div><span class="font-semibold text-slate-800">Kelas:</span> {{ $student->classRoom?->name ?: '-' }}</div>
|
|
<div><span class="font-semibold text-slate-800">Tanggal Masuk:</span> {{ $student->entry_date?->format('d-m-Y') ?: '-' }}</div>
|
|
</div>
|
|
</x-master-card>
|
|
|
|
<x-master-card title="Kontak & Alamat" subtitle="Informasi komunikasi siswa.">
|
|
<div class="space-y-4 text-sm text-slate-600">
|
|
<div><span class="font-semibold text-slate-800">No. HP:</span> {{ $student->phone_number ?: '-' }}</div>
|
|
<div><span class="font-semibold text-slate-800">Email:</span> {{ $student->email ?: '-' }}</div>
|
|
<div><span class="font-semibold text-slate-800">Alamat:</span> {{ $student->address ?: '-' }}</div>
|
|
<div><span class="font-semibold text-slate-800">Wilayah:</span> {{ collect([$student->village, $student->district, $student->city, $student->province])->filter()->join(', ') ?: '-' }}</div>
|
|
<div><span class="font-semibold text-slate-800">Kode Pos:</span> {{ $student->postal_code ?: '-' }}</div>
|
|
</div>
|
|
</x-master-card>
|
|
</div>
|
|
|
|
<div class="mt-6 grid grid-cols-1 gap-6 xl:grid-cols-2">
|
|
<x-master-card title="Histori Akademik Siswa" subtitle="Riwayat penempatan siswa per tahun angkatan, jurusan, dan kelas.">
|
|
@if ($student->academicHistories->isEmpty())
|
|
<div class="text-sm text-slate-500">Belum ada histori akademik untuk siswa ini.</div>
|
|
@else
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full divide-y divide-slate-200">
|
|
<thead class="bg-slate-50">
|
|
<tr>
|
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Tahun</th>
|
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Jurusan</th>
|
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Kelas</th>
|
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Status</th>
|
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Periode</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-slate-100 bg-white">
|
|
@foreach ($student->academicHistories as $history)
|
|
<tr>
|
|
<td class="px-4 py-3 text-sm text-slate-700">{{ $history->academicYear?->name ?: '-' }}</td>
|
|
<td class="px-4 py-3 text-sm text-slate-600">{{ $history->department?->name ?: '-' }}</td>
|
|
<td class="px-4 py-3 text-sm text-slate-600">{{ $history->classRoom?->name ?: '-' }}</td>
|
|
<td class="px-4 py-3 text-sm text-slate-600">
|
|
<span class="rounded-full {{ $history->is_current ? 'bg-emerald-100 text-emerald-700' : 'bg-slate-100 text-slate-600' }} px-3 py-1 text-xs font-semibold">
|
|
{{ $history->is_current ? 'Aktif Sekarang' : ucfirst($history->status) }}
|
|
</span>
|
|
</td>
|
|
<td class="px-4 py-3 text-sm text-slate-500">
|
|
{{ $history->start_date?->format('d-m-Y') ?: '-' }} s/d {{ $history->end_date?->format('d-m-Y') ?: 'Sekarang' }}
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
@endif
|
|
</x-master-card>
|
|
|
|
<x-master-card title="Riwayat Prestasi Siswa" subtitle="Catatan prestasi akademik maupun non-akademik siswa.">
|
|
<div class="mb-4">
|
|
<a href="{{ route('student-achievements.create', ['student_id' => $student->id]) }}" class="inline-flex items-center rounded-2xl bg-amber-500 px-4 py-2.5 text-sm font-semibold text-white shadow-lg shadow-amber-200 transition hover:bg-amber-600">
|
|
Tambah Prestasi
|
|
</a>
|
|
</div>
|
|
|
|
@if ($student->achievements->isEmpty())
|
|
<div class="text-sm text-slate-500">Belum ada data prestasi untuk siswa ini.</div>
|
|
@else
|
|
<div class="space-y-4">
|
|
@foreach ($student->achievements as $achievement)
|
|
<div class="rounded-3xl border border-slate-200 bg-slate-50 p-5 text-sm text-slate-600 shadow-sm shadow-slate-200/40">
|
|
<div class="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
|
|
<div>
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
<div class="font-semibold text-slate-800">{{ $achievement->achievement_name }}</div>
|
|
@if ($achievement->level)
|
|
<span class="rounded-full bg-amber-100 px-3 py-1 text-xs font-semibold text-amber-700">{{ $achievement->level }}</span>
|
|
@endif
|
|
@if ($achievement->rank)
|
|
<span class="rounded-full bg-indigo-100 px-3 py-1 text-xs font-semibold text-indigo-700">{{ $achievement->rank }}</span>
|
|
@endif
|
|
</div>
|
|
<div class="mt-2">Kategori: {{ $achievement->category ?: '-' }}</div>
|
|
<div>Penyelenggara: {{ $achievement->organizer ?: '-' }}</div>
|
|
<div>Tahun/Tanggal: {{ $achievement->achievement_year ?: '-' }} · {{ $achievement->achievement_date?->format('d-m-Y') ?: '-' }}</div>
|
|
@if ($achievement->description)
|
|
<div class="mt-2 rounded-xl bg-white px-3 py-2 text-xs text-slate-500">
|
|
{{ $achievement->description }}
|
|
</div>
|
|
@endif
|
|
</div>
|
|
<div class="flex flex-wrap gap-2">
|
|
@if ($achievement->certificate_file)
|
|
<a href="{{ asset('storage/' . $achievement->certificate_file) }}" target="_blank" class="rounded-xl border border-indigo-200 px-3 py-2 text-xs font-semibold text-indigo-700 transition hover:bg-indigo-50">Piagam</a>
|
|
@endif
|
|
@if ($achievement->activity_photo)
|
|
<button type="button" data-lightbox-trigger data-lightbox-src="{{ asset('storage/' . $achievement->activity_photo) }}" data-lightbox-title="Foto Kegiatan — {{ $achievement->achievement_name }}" class="rounded-xl border border-emerald-200 px-3 py-2 text-xs font-semibold text-emerald-700 transition hover:bg-emerald-50">Foto</button>
|
|
@endif
|
|
<a href="{{ route('student-achievements.edit', $achievement) }}" class="rounded-xl border border-slate-200 px-3 py-2 text-xs font-semibold text-slate-700 transition hover:bg-slate-100">Edit</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
</x-master-card>
|
|
</div>
|
|
|
|
<div class="mt-6 grid grid-cols-1 gap-6 xl:grid-cols-2">
|
|
<x-master-card title="Data Orang Tua / Wali" subtitle="Kelola data ayah, ibu, atau wali siswa.">
|
|
<div class="mb-4">
|
|
<a href="{{ route('students.parents.create', $student) }}" class="inline-flex items-center rounded-2xl bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white shadow-lg shadow-indigo-200 transition hover:bg-indigo-700">
|
|
Tambah Orang Tua / Wali
|
|
</a>
|
|
</div>
|
|
|
|
@if ($student->parents->isEmpty())
|
|
<div class="text-sm text-slate-500">Belum ada data orang tua/wali untuk siswa ini.</div>
|
|
@else
|
|
<div class="space-y-4">
|
|
@foreach ($student->parents as $parent)
|
|
<div class="rounded-2xl border border-slate-200 bg-slate-50 p-4 text-sm text-slate-600">
|
|
<div class="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
|
|
<div>
|
|
<div class="font-semibold text-slate-800">{{ ucfirst($parent->relation_type === 'father' ? 'Ayah' : ($parent->relation_type === 'mother' ? 'Ibu' : 'Wali')) }} - {{ $parent->name }}</div>
|
|
<div class="mt-1">Pekerjaan: {{ $parent->occupation ?: '-' }}</div>
|
|
<div>No. HP: {{ $parent->phone_number ?: '-' }}</div>
|
|
<div>Pendidikan: {{ $parent->education ?: '-' }}</div>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2">
|
|
<a href="{{ route('students.parents.edit', [$student, $parent]) }}" class="rounded-xl border border-slate-200 px-3 py-2 text-xs font-semibold text-slate-700 transition hover:bg-slate-100">Edit</a>
|
|
@if ($isAdmin)
|
|
<form action="{{ route('students.parents.destroy', [$student, $parent]) }}" method="POST" class="delete-form" data-entity="data {{ $parent->name }}">
|
|
@csrf
|
|
@method('DELETE')
|
|
<button type="submit" class="rounded-xl border border-rose-200 px-3 py-2 text-xs font-semibold text-rose-600 transition hover:bg-rose-50">Hapus</button>
|
|
</form>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
</x-master-card>
|
|
|
|
<x-master-card title="Dokumen Siswa" subtitle="Kelola file dan status verifikasi dokumen siswa.">
|
|
<div class="mb-4">
|
|
<a href="{{ route('students.documents.create', $student) }}" class="inline-flex items-center rounded-2xl bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white shadow-lg shadow-indigo-200 transition hover:bg-indigo-700">
|
|
Tambah Dokumen
|
|
</a>
|
|
</div>
|
|
|
|
@if ($student->documents->isEmpty())
|
|
<div class="text-sm text-slate-500">Belum ada dokumen siswa yang diunggah.</div>
|
|
@else
|
|
<div class="space-y-4">
|
|
@foreach ($student->documents as $document)
|
|
@php
|
|
$verificationMap = [
|
|
'pending' => 'bg-slate-100 text-slate-600',
|
|
'valid' => 'bg-emerald-100 text-emerald-700',
|
|
'invalid' => 'bg-rose-100 text-rose-700',
|
|
'revision' => 'bg-amber-100 text-amber-700',
|
|
];
|
|
@endphp
|
|
<div class="rounded-3xl border border-slate-200 bg-slate-50 p-5 text-sm text-slate-600 shadow-sm shadow-slate-200/40">
|
|
<div class="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
|
|
<div>
|
|
<div class="font-semibold text-slate-800">{{ $document->documentType?->name ?: '-' }}</div>
|
|
<div class="mt-1">File: {{ $document->file_name }}</div>
|
|
<div>Format: {{ strtoupper($document->file_extension ?: '-') }}</div>
|
|
<div>Ukuran: {{ $document->file_size ? number_format($document->file_size / 1024, 1) . ' KB' : '-' }}</div>
|
|
@if ($document->verifiedBy)
|
|
<div>Diverifikasi oleh: {{ $document->verifiedBy->name }}</div>
|
|
@endif
|
|
<div class="mt-2 flex flex-wrap gap-2">
|
|
<span class="rounded-full px-3 py-1 text-xs font-semibold {{ $verificationMap[$document->verification_status] ?? 'bg-slate-100 text-slate-600' }}">
|
|
{{ ucfirst($document->verification_status) }}
|
|
</span>
|
|
@if ($document->verified_at)
|
|
<span class="rounded-full bg-slate-100 px-3 py-1 text-xs font-semibold text-slate-600">
|
|
Diverifikasi {{ $document->verified_at->format('d-m-Y H:i') }}
|
|
</span>
|
|
@endif
|
|
</div>
|
|
@if ($document->verification_note)
|
|
<div class="mt-2 rounded-xl bg-white px-3 py-2 text-xs text-slate-500">
|
|
Catatan: {{ $document->verification_note }}
|
|
</div>
|
|
@endif
|
|
</div>
|
|
<div class="flex flex-wrap gap-2">
|
|
<a href="{{ route('students.documents.preview', $document) }}" class="rounded-xl border border-indigo-200 px-3 py-2 text-xs font-semibold text-indigo-700 transition hover:bg-indigo-50">Lihat</a>
|
|
<a href="{{ route('students.documents.download', $document) }}" class="rounded-xl border border-sky-200 px-3 py-2 text-xs font-semibold text-sky-700 transition hover:bg-sky-50">Download</a>
|
|
<a href="{{ route('students.documents.edit', [$student, $document]) }}" class="rounded-xl border border-slate-200 px-3 py-2 text-xs font-semibold text-slate-700 transition hover:bg-slate-100">Edit</a>
|
|
|
|
@if ($isAdmin)
|
|
<form action="{{ route('students.documents.quick-verify', [$student, $document]) }}" method="POST" class="inline-flex gap-2">
|
|
@csrf
|
|
<input type="hidden" name="verification_status" value="valid">
|
|
<input type="hidden" name="verification_note" value="Dokumen dinyatakan valid.">
|
|
<button type="submit" @disabled($document->verification_status === 'valid') class="rounded-xl border border-emerald-200 px-3 py-2 text-xs font-semibold text-emerald-700 transition hover:bg-emerald-50 disabled:cursor-not-allowed disabled:bg-emerald-100 disabled:text-emerald-500">Valid</button>
|
|
</form>
|
|
|
|
<form action="{{ route('students.documents.quick-verify', [$student, $document]) }}" method="POST" class="inline-flex gap-2">
|
|
@csrf
|
|
<input type="hidden" name="verification_status" value="revision">
|
|
<input type="hidden" name="verification_note" value="Dokumen perlu revisi.">
|
|
<button type="submit" @disabled($document->verification_status === 'revision') class="rounded-xl border border-amber-200 px-3 py-2 text-xs font-semibold text-amber-700 transition hover:bg-amber-50 disabled:cursor-not-allowed disabled:bg-amber-100 disabled:text-amber-500">Revisi</button>
|
|
</form>
|
|
|
|
<form action="{{ route('students.documents.quick-verify', [$student, $document]) }}" method="POST" class="inline-flex gap-2">
|
|
@csrf
|
|
<input type="hidden" name="verification_status" value="invalid">
|
|
<input type="hidden" name="verification_note" value="Dokumen dinyatakan tidak valid.">
|
|
<button type="submit" @disabled($document->verification_status === 'invalid') class="rounded-xl border border-rose-200 px-3 py-2 text-xs font-semibold text-rose-700 transition hover:bg-rose-50 disabled:cursor-not-allowed disabled:bg-rose-100 disabled:text-rose-500">Invalid</button>
|
|
</form>
|
|
|
|
<form action="{{ route('students.documents.destroy', [$student, $document]) }}" method="POST" class="delete-form" data-entity="dokumen {{ $document->file_name }}">
|
|
@csrf
|
|
@method('DELETE')
|
|
<button type="submit" class="rounded-xl border border-rose-200 px-3 py-2 text-xs font-semibold text-rose-600 transition hover:bg-rose-50">Hapus</button>
|
|
</form>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
</x-master-card>
|
|
</div>
|
|
|
|
<div class="mt-6 flex flex-wrap items-center gap-3">
|
|
<a href="{{ route('students.edit', $student) }}" class="rounded-2xl bg-indigo-600 px-5 py-3 text-sm font-semibold text-white shadow-lg shadow-indigo-200 transition hover:bg-indigo-700">Edit Siswa</a>
|
|
<a href="{{ route('students.index') }}" class="rounded-2xl border border-slate-200 px-5 py-3 text-sm font-semibold text-slate-700 transition hover:bg-slate-50">Kembali</a>
|
|
</div>
|
|
</x-master-page>
|