This commit is contained in:
HelgaFaisa 2026-01-17 16:46:24 +07:00
parent 3201648b16
commit ca05c2459a
224 changed files with 14773 additions and 3626 deletions

View File

@ -1,5 +1,5 @@
<?php
// app/Http/Controllers/admin/AbsensiKegiatanController.php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;

View File

@ -1,5 +1,5 @@
<?php
// app/Http/Controllers/admin/KategoriKegiatanController.php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;

View File

@ -1,5 +1,5 @@
<?php
// app/Http/Controllers/admin/KegiatanController.php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;

View File

@ -48,7 +48,7 @@ public function index(Request $request)
'total_data' => Kepulangan::count(),
'menunggu_approval' => Kepulangan::where('status', 'Menunggu')->count(),
'sedang_izin' => Kepulangan::aktif()->count(),
'over_limit_santri' => $this->getOverLimitSantri()->count(),
'over_limit_santri' => count(Kepulangan::getSantriOverLimit()),
];
// Get unique years for filter
@ -58,13 +58,17 @@ public function index(Request $request)
->pluck('tahun');
// Get santri yang over limit untuk highlight
$santriOverLimit = $this->getOverLimitSantri()->pluck('total_hari', 'id_santri');
$santriOverLimit = Kepulangan::getSantriOverLimit();
// Get settings untuk info periode
$settings = Kepulangan::getSettings();
return view('admin.kepulangan.index', compact(
'kepulangan',
'stats',
'tahunList',
'santriOverLimit'
'santriOverLimit',
'settings'
));
}
@ -77,7 +81,9 @@ public function create()
->orderBy('nama_lengkap')
->get();
return view('admin.kepulangan.create', compact('santriList'));
$settings = Kepulangan::getSettings();
return view('admin.kepulangan.create', compact('santriList', 'settings'));
}
/**
@ -102,11 +108,21 @@ public function store(Request $request)
'alasan.max' => 'Alasan maksimal 500 karakter.',
]);
// Create kepulangan
Kepulangan::create($validated);
// Create kepulangan (durasi_izin akan otomatis dihitung di model)
$kepulangan = Kepulangan::create($validated);
// Check apakah over limit
$kuota = Kepulangan::getSisaKuotaSantri($validated['id_santri']);
$message = 'Izin kepulangan berhasil diajukan.';
if ($kuota['status'] === 'melebihi') {
$message .= ' ⚠️ PERHATIAN: Santri ini sudah melebihi kuota ' . $kuota['kuota_maksimal'] . ' hari per tahun (Total: ' . $kuota['total_terpakai'] . ' hari).';
} elseif ($kuota['status'] === 'hampir_habis') {
$message .= ' ⚠️ Kuota hampir habis. Sisa: ' . $kuota['sisa_kuota'] . ' hari.';
}
return redirect()->route('admin.kepulangan.index')
->with('success', 'Izin kepulangan berhasil diajukan.');
->with('success', $message);
}
/**
@ -114,14 +130,22 @@ public function store(Request $request)
*/
public function show($id_kepulangan)
{
// Cari data berdasarkan id_kepulangan (KP001, KP002, dst)
$kepulangan = Kepulangan::where('id_kepulangan', $id_kepulangan)
->with('santri')
->firstOrFail();
// Get detail kuota santri
$kuotaSantri = Kepulangan::getSisaKuotaSantri($kepulangan->id_santri);
// Get settings
$settings = Kepulangan::getSettings();
// Get detail izin tahun ini
$tahunSekarang = Carbon::now()->year;
$detailIzin = $this->getDetailIzinSantri($kepulangan->id_santri, $tahunSekarang);
$detailIzin = $this->getDetailIzinSantri(
$kepulangan->id_santri,
$settings->periode_mulai,
$settings->periode_akhir
);
// Get history kepulangan santri (exclude current)
$history = Kepulangan::where('id_santri', $kepulangan->id_santri)
@ -132,8 +156,10 @@ public function show($id_kepulangan)
return view('admin.kepulangan.show', compact(
'kepulangan',
'kuotaSantri',
'detailIzin',
'history'
'history',
'settings'
));
}
@ -142,10 +168,8 @@ public function show($id_kepulangan)
*/
public function edit($id_kepulangan)
{
// Cari data berdasarkan id_kepulangan
$kepulangan = Kepulangan::where('id_kepulangan', $id_kepulangan)->firstOrFail();
// Hanya bisa edit jika status Menunggu
if ($kepulangan->status !== 'Menunggu') {
return redirect()->route('admin.kepulangan.index')
->with('error', 'Hanya izin dengan status "Menunggu" yang bisa diedit.');
@ -155,7 +179,15 @@ public function edit($id_kepulangan)
->orderBy('nama_lengkap')
->get();
return view('admin.kepulangan.edit', compact('kepulangan', 'santriList'));
$settings = Kepulangan::getSettings();
$kuotaSantri = Kepulangan::getSisaKuotaSantri($kepulangan->id_santri);
return view('admin.kepulangan.edit', compact(
'kepulangan',
'santriList',
'settings',
'kuotaSantri'
));
}
/**
@ -163,10 +195,8 @@ public function edit($id_kepulangan)
*/
public function update(Request $request, $id_kepulangan)
{
// Cari data berdasarkan id_kepulangan
$kepulangan = Kepulangan::where('id_kepulangan', $id_kepulangan)->firstOrFail();
// Hanya bisa update jika status Menunggu
if ($kepulangan->status !== 'Menunggu') {
return redirect()->route('admin.kepulangan.index')
->with('error', 'Hanya izin dengan status "Menunggu" yang bisa diubah.');
@ -184,10 +214,19 @@ public function update(Request $request, $id_kepulangan)
'alasan.min' => 'Alasan minimal 10 karakter.',
]);
// Update (durasi_izin akan otomatis dihitung ulang di model)
$kepulangan->update($validated);
return redirect()->route('admin.kepulangan.index')
->with('success', 'Data kepulangan berhasil diperbarui.');
// Check apakah over limit setelah update
$kuota = Kepulangan::getSisaKuotaSantri($kepulangan->id_santri);
$message = 'Data kepulangan berhasil diperbarui.';
if ($kuota['status'] === 'melebihi') {
$message .= ' ⚠️ PERHATIAN: Santri ini sudah melebihi kuota ' . $kuota['kuota_maksimal'] . ' hari.';
}
return redirect()->route('admin.kepulangan.show', $id_kepulangan)
->with('success', $message);
}
/**
@ -195,10 +234,8 @@ public function update(Request $request, $id_kepulangan)
*/
public function destroy($id_kepulangan)
{
// Cari data berdasarkan id_kepulangan
$kepulangan = Kepulangan::where('id_kepulangan', $id_kepulangan)->firstOrFail();
// Hanya bisa hapus jika status Menunggu atau Ditolak
if (!in_array($kepulangan->status, ['Menunggu', 'Ditolak'])) {
return response()->json([
'success' => false,
@ -219,7 +256,6 @@ public function destroy($id_kepulangan)
*/
public function approve(Request $request, $id_kepulangan)
{
// Cari data berdasarkan id_kepulangan
$kepulangan = Kepulangan::where('id_kepulangan', $id_kepulangan)->firstOrFail();
if ($kepulangan->status !== 'Menunggu') {
@ -229,7 +265,6 @@ public function approve(Request $request, $id_kepulangan)
], 400);
}
// Update status - catatan opsional (tidak perlu validasi)
$kepulangan->update([
'status' => 'Disetujui',
'approved_by' => Auth::user()->name,
@ -248,10 +283,8 @@ public function approve(Request $request, $id_kepulangan)
*/
public function reject(Request $request, $id_kepulangan)
{
// Cari data berdasarkan id_kepulangan
$kepulangan = Kepulangan::where('id_kepulangan', $id_kepulangan)->firstOrFail();
// Validasi alasan penolakan (wajib diisi minimal 10 karakter)
$validated = $request->validate([
'alasan_penolakan' => 'required|string|min:10',
], [
@ -280,11 +313,10 @@ public function reject(Request $request, $id_kepulangan)
}
/**
* Complete kepulangan (mark as selesai)
* Complete kepulangan
*/
public function complete($id_kepulangan)
{
// Cari data berdasarkan id_kepulangan
$kepulangan = Kepulangan::where('id_kepulangan', $id_kepulangan)->firstOrFail();
if ($kepulangan->status !== 'Disetujui') {
@ -294,9 +326,7 @@ public function complete($id_kepulangan)
], 400);
}
$kepulangan->update([
'status' => 'Selesai',
]);
$kepulangan->update(['status' => 'Selesai']);
return response()->json([
'success' => true,
@ -309,7 +339,6 @@ public function complete($id_kepulangan)
*/
public function print($id_kepulangan)
{
// Cari data berdasarkan id_kepulangan
$kepulangan = Kepulangan::where('id_kepulangan', $id_kepulangan)
->with('santri')
->firstOrFail();
@ -332,7 +361,7 @@ public function print($id_kepulangan)
}
/**
* API: Get santri data with penggunaan izin
* API: Get santri data with penggunaan kuota
*/
public function getSantriData($idSantri)
{
@ -345,36 +374,164 @@ public function getSantriData($idSantri)
], 404);
}
$tahunSekarang = Carbon::now()->year;
$penggunaanIzin = $this->getDetailIzinSantri($idSantri, $tahunSekarang);
$kuotaSantri = Kepulangan::getSisaKuotaSantri($idSantri);
return response()->json([
'success' => true,
'santri' => $santri,
'penggunaan_izin' => [
'total_hari' => $penggunaanIzin['total_hari'],
'total_izin' => $penggunaanIzin['total_izin'],
'sisa_kuota' => $penggunaanIzin['sisa_kuota'],
'over_limit' => $penggunaanIzin['over_limit'],
]
'penggunaan_izin' => $kuotaSantri
]);
}
/**
* Helper: Get detail izin santri per tahun
* ========================================
* FITUR PENGATURAN KUOTA
* ========================================
*/
private function getDetailIzinSantri($idSantri, $tahun)
/**
* Show settings page
*/
public function settings()
{
$settings = Kepulangan::getSettings();
$resetLogs = Kepulangan::getResetLogs(20);
// Statistik periode saat ini
$totalSantri = Santri::where('status', 'Aktif')->count();
$santriOverLimit = Kepulangan::getSantriOverLimit();
$totalIzinPeriodeIni = Kepulangan::whereBetween('tanggal_pulang', [
$settings->periode_mulai,
$settings->periode_akhir
])->whereIn('status', ['Disetujui', 'Selesai'])->count();
return view('admin.kepulangan.settings', compact(
'settings',
'resetLogs',
'totalSantri',
'santriOverLimit',
'totalIzinPeriodeIni'
));
}
/**
* Update settings
*/
public function updateSettings(Request $request)
{
$validated = $request->validate([
'kuota_maksimal' => 'required|integer|min:1|max:365',
'periode_mulai' => 'required|date',
'periode_akhir' => 'required|date|after:periode_mulai',
], [
'kuota_maksimal.required' => 'Kuota maksimal wajib diisi.',
'kuota_maksimal.min' => 'Kuota minimal 1 hari.',
'kuota_maksimal.max' => 'Kuota maksimal 365 hari.',
'periode_mulai.required' => 'Periode mulai wajib diisi.',
'periode_akhir.required' => 'Periode akhir wajib diisi.',
'periode_akhir.after' => 'Periode akhir harus setelah periode mulai.',
]);
Kepulangan::updateSettings(
$validated['kuota_maksimal'],
$validated['periode_mulai'],
$validated['periode_akhir']
);
return redirect()->route('admin.kepulangan.settings')
->with('success', 'Pengaturan kuota berhasil diperbarui.');
}
/**
* Reset kuota satu santri
*/
public function resetKuotaSantri(Request $request, $idSantri)
{
$validated = $request->validate([
'catatan' => 'nullable|string|max:500',
]);
$santri = Santri::where('id_santri', $idSantri)->firstOrFail();
$result = Kepulangan::resetKuotaSantri(
$idSantri,
Auth::user()->name,
$validated['catatan'] ?? 'Reset kuota individual untuk ' . $santri->nama_lengkap
);
return response()->json([
'success' => true,
'message' => 'Kuota santri ' . $santri->nama_lengkap . ' berhasil direset. Total ' . $result['total_hari_direset'] . ' hari telah direset.'
]);
}
/**
* Reset kuota semua santri
*/
public function resetKuotaSemuaSantri(Request $request)
{
$validated = $request->validate([
'catatan' => 'nullable|string|max:500',
'konfirmasi' => 'required|accepted',
], [
'konfirmasi.accepted' => 'Anda harus mencentang konfirmasi untuk melanjutkan reset massal.',
]);
$result = Kepulangan::resetKuotaSemuaSantri(
Auth::user()->name,
$validated['catatan'] ?? 'Reset kuota tahunan massal'
);
return response()->json([
'success' => true,
'message' => 'Kuota berhasil direset untuk ' . $result['total_santri'] . ' santri. Total ' . $result['total_hari_direset'] . ' hari telah direset.',
'data' => $result
]);
}
/**
* Show list santri over limit
*/
public function santriOverLimit()
{
$settings = Kepulangan::getSettings();
$santriOverLimitIds = Kepulangan::getSantriOverLimit();
$santriList = Santri::whereIn('id_santri', array_keys($santriOverLimitIds))
->with(['kepulangan' => function($query) use ($settings) {
$query->whereBetween('tanggal_pulang', [
$settings->periode_mulai,
$settings->periode_akhir
])->whereIn('status', ['Disetujui', 'Selesai']);
}])
->get()
->map(function($santri) use ($santriOverLimitIds) {
$kuota = Kepulangan::getSisaKuotaSantri($santri->id_santri);
$santri->total_hari_izin = $santriOverLimitIds[$santri->id_santri];
$santri->kuota_info = $kuota;
return $santri;
})
->sortByDesc('total_hari_izin');
return view('admin.kepulangan.over-limit', compact('santriList', 'settings'));
}
/**
* Helper: Get detail izin santri
*/
private function getDetailIzinSantri($idSantri, $periodeMulai, $periodeAkhir)
{
$kepulanganList = Kepulangan::where('id_santri', $idSantri)
->where('status', 'Disetujui')
->whereYear('tanggal_pulang', $tahun)
->whereIn('status', ['Disetujui', 'Selesai'])
->whereBetween('tanggal_pulang', [$periodeMulai, $periodeAkhir])
->orderBy('tanggal_pulang', 'desc')
->get();
$settings = Kepulangan::getSettings();
$totalHari = $kepulanganList->sum('durasi_izin');
$totalIzin = $kepulanganList->count();
$sisaKuota = max(0, 12 - $totalHari);
$overLimit = $totalHari > 12;
$sisaKuota = max(0, $settings->kuota_maksimal - $totalHari);
$overLimit = $totalHari > $settings->kuota_maksimal;
$details = $kepulanganList->map(function($item) {
return [
@ -382,6 +539,7 @@ private function getDetailIzinSantri($idSantri, $tahun)
'tanggal' => $item->tanggal_pulang_formatted . ' - ' . $item->tanggal_kembali_formatted,
'durasi' => $item->durasi_izin,
'alasan' => $item->alasan,
'status' => $item->status,
];
});
@ -393,19 +551,4 @@ private function getDetailIzinSantri($idSantri, $tahun)
'details' => $details,
];
}
/**
* Helper: Get santri yang over limit
*/
private function getOverLimitSantri()
{
$tahunSekarang = Carbon::now()->year;
return Kepulangan::selectRaw('id_santri, SUM(durasi_izin) as total_hari')
->where('status', 'Disetujui')
->whereYear('tanggal_pulang', $tahunSekarang)
->groupBy('id_santri')
->having('total_hari', '>', 12)
->get();
}
}

View File

@ -1,5 +1,5 @@
<?php
// app/Http/Controllers/admin/RiwayatKegiatanController.php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;

View File

@ -7,6 +7,7 @@
use App\Models\Santri;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
class SantriController extends Controller
{
@ -46,6 +47,7 @@ public function index(Request $request)
'jenis_kelamin',
'kelas',
'status',
'foto', // TAMBAHAN
'created_at'
)
->orderBy('created_at', 'desc')
@ -87,15 +89,33 @@ public function store(Request $request)
'daerah_asal' => 'nullable|string|max:255',
'nama_orang_tua' => 'nullable|string|max:255',
'nomor_hp_ortu' => 'nullable|string|max:20',
'foto' => 'nullable|image|mimes:jpg,jpeg,png|max:2048', // TAMBAHAN: max 2MB
], [
'nis.unique' => 'NIS sudah digunakan oleh santri lain.',
'nama_lengkap.required' => 'Nama lengkap wajib diisi.',
'jenis_kelamin.required' => 'Jenis kelamin wajib dipilih.',
'kelas.required' => 'Kelas wajib dipilih.',
'status.required' => 'Status wajib dipilih.',
'foto.image' => 'File harus berupa gambar.',
'foto.mimes' => 'Foto harus berformat JPG, JPEG, atau PNG.',
'foto.max' => 'Ukuran foto maksimal 2 MB.',
]);
Santri::create($validated);
// Buat santri terlebih dahulu untuk mendapatkan id_santri
$santri = Santri::create($validated);
// Handle upload foto
if ($request->hasFile('foto')) {
$file = $request->file('foto');
$extension = $file->getClientOriginalExtension();
$filename = $santri->id_santri . '.' . $extension;
// Simpan file ke storage/app/public/santri
$path = $file->storeAs('santri', $filename, 'public');
// Update path foto di database
$santri->update(['foto' => $path]);
}
// Clear cache
Cache::forget('next_santri_id');
@ -137,14 +157,34 @@ public function update(Request $request, Santri $santri)
'daerah_asal' => 'nullable|string|max:255',
'nama_orang_tua' => 'nullable|string|max:255',
'nomor_hp_ortu' => 'nullable|string|max:20',
'foto' => 'nullable|image|mimes:jpg,jpeg,png|max:2048', // TAMBAHAN: max 2MB
], [
'nis.unique' => 'NIS sudah digunakan oleh santri lain.',
'nama_lengkap.required' => 'Nama lengkap wajib diisi.',
'jenis_kelamin.required' => 'Jenis kelamin wajib dipilih.',
'kelas.required' => 'Kelas wajib dipilih.',
'status.required' => 'Status wajib dipilih.',
'foto.image' => 'File harus berupa gambar.',
'foto.mimes' => 'Foto harus berformat JPG, JPEG, atau PNG.',
'foto.max' => 'Ukuran foto maksimal 2 MB.',
]);
// Handle upload foto baru
if ($request->hasFile('foto')) {
// Hapus foto lama jika ada
if ($santri->foto && Storage::disk('public')->exists($santri->foto)) {
Storage::disk('public')->delete($santri->foto);
}
$file = $request->file('foto');
$extension = $file->getClientOriginalExtension();
$filename = $santri->id_santri . '.' . $extension;
// Simpan file ke storage/app/public/santri
$path = $file->storeAs('santri', $filename, 'public');
$validated['foto'] = $path;
}
$santri->update($validated);
// Clear cache
@ -162,6 +202,11 @@ public function destroy(Santri $santri)
{
$namaSantri = $santri->nama_lengkap;
// Hapus foto jika ada
if ($santri->foto && Storage::disk('public')->exists($santri->foto)) {
Storage::disk('public')->delete($santri->foto);
}
$santri->delete();
// Clear cache

View File

@ -0,0 +1,164 @@
<?php
// app/Http/Controllers/Api/ApiAuthController.php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\Santri;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
class ApiAuthController extends Controller
{
/**
* Login Santri/Wali via Mobile
*
* Request:
* - id_santri (username)
* - password
*
* Response:
* - token
* - user (name, role, role_id)
* - santri (data lengkap santri jika role=santri)
*/
public function login(Request $request)
{
$request->validate([
'id_santri' => 'required|string',
'password' => 'required|string',
]);
// Cari user berdasarkan username (id_santri)
$user = User::where('username', $request->id_santri)->first();
// Validasi user dan password
if (!$user || !Hash::check($request->password, $user->password)) {
throw ValidationException::withMessages([
'id_santri' => ['ID Santri atau password salah.'],
]);
}
// Cek apakah user adalah santri atau wali
if (!in_array($user->role, ['santri', 'wali'])) {
return response()->json([
'success' => false,
'message' => 'Akun ini tidak memiliki akses ke aplikasi mobile.',
], 403);
}
// Hapus token lama (optional, untuk keamanan)
$user->tokens()->delete();
// Buat token baru
$token = $user->createToken('mobile-app')->plainTextToken;
// Prepare response data
$responseData = [
'success' => true,
'message' => 'Login berhasil',
'token' => $token,
'user' => [
'name' => $user->name,
'role' => $user->role,
'role_id' => $user->role_id,
],
];
// Jika santri, sertakan data santri
if ($user->role === 'santri') {
$santri = Santri::where('id_santri', $user->role_id)
->select([
'id_santri',
'nis',
'nama_lengkap',
'jenis_kelamin',
'kelas',
'status',
'alamat_santri',
'daerah_asal',
'nama_orang_tua',
'nomor_hp_ortu',
'foto'
])
->first();
$responseData['santri'] = $santri;
}
return response()->json($responseData, 200);
}
/**
* Logout - Hapus token
*/
public function logout(Request $request)
{
// Hapus token yang sedang digunakan
$request->user()->currentAccessToken()->delete();
return response()->json([
'success' => true,
'message' => 'Logout berhasil',
], 200);
}
/**
* Get Profile Santri yang sedang login
*/
public function profile(Request $request)
{
$user = $request->user();
if ($user->role !== 'santri') {
return response()->json([
'success' => false,
'message' => 'Hanya santri yang bisa mengakses profil.',
], 403);
}
$santri = Santri::where('id_santri', $user->role_id)
->select([
'id_santri',
'nis',
'nama_lengkap',
'jenis_kelamin',
'kelas',
'status',
'alamat_santri',
'daerah_asal',
'nama_orang_tua',
'nomor_hp_ortu',
'foto',
'created_at'
])
->first();
if (!$santri) {
return response()->json([
'success' => false,
'message' => 'Data santri tidak ditemukan.',
], 404);
}
return response()->json([
'success' => true,
'data' => [
'id_santri' => $santri->id_santri,
'nis' => $santri->nis,
'nama_lengkap' => $santri->nama_lengkap,
'jenis_kelamin' => $santri->jenis_kelamin,
'kelas' => $santri->kelas,
'status' => $santri->status,
'alamat_santri' => $santri->alamat_santri,
'daerah_asal' => $santri->daerah_asal,
'nama_orang_tua' => $santri->nama_orang_tua,
'nomor_hp_ortu' => $santri->nomor_hp_ortu,
'foto_url' => $santri->foto_url, // Accessor dari Model Santri
'bergabung_sejak' => $santri->created_at->format('d F Y'),
]
], 200);
}
}

View File

@ -4,13 +4,14 @@
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use App\Models\Santri;
use App\Models\User;
use App\Models\RiwayatPelanggaran;
use App\Models\Berita;
use App\Models\KesehatanSantri;
use App\Models\Kepulangan;
use App\Models\Capaian;
use App\Models\Semester;
use Carbon\Carbon;
class DashboardController extends Controller
@ -31,68 +32,215 @@ public function admin()
} catch (\Exception $e) {
Log::error('Error di Dashboard Admin: ' . $e->getMessage());
return response()->view('errors.500', [
'error' => 'Terjadi kesalahan saat memuat dashboard',
'message' => $e->getMessage()
], 500);
abort(500, 'Terjadi kesalahan saat memuat dashboard Admin: ' . $e->getMessage());
}
}
/**
* Dashboard Santri/Wali - OPTIMIZED
* Dashboard Santri/Wali - FIXED VERSION
*/
public function santri()
{
try {
$user = Auth::user();
Log::info('=== DASHBOARD SANTRI START ===');
Log::info('User ID: ' . $user->id);
Log::info('Role: ' . $user->role);
Log::info('Role ID: ' . $user->role_id);
// Validasi role
if (!in_array($user->role, ['santri', 'wali'])) {
Log::error('Role tidak sesuai: ' . $user->role);
abort(403, 'Akses ditolak. Role Anda: ' . $user->role);
}
// ✅ QUERY OPTIMIZED - Ambil data santri dengan kolom minimal
// ✅ Ambil data santri
$santri = Santri::where('id_santri', $user->role_id)
->select('id_santri', 'nama_lengkap', 'kelas')
->firstOrFail();
->first();
if (!$santri) {
Log::error('Santri tidak ditemukan dengan role_id: ' . $user->role_id);
abort(404, 'Data santri tidak ditemukan.');
}
Log::info('Santri ditemukan: ' . $santri->nama_lengkap);
$idSantri = $santri->id_santri;
$today = Carbon::today();
$weekAgo = Carbon::now()->subDays(7);
// ✅ PARALLEL QUERIES - Eksekusi query secara bersamaan untuk performa
// ✅ Ambil semester aktif dengan FALLBACK
$semesterAktif = null;
try {
$semesterAktif = Semester::where('status', 'aktif')
->select('id_semester', 'nama_semester', 'tahun_ajaran')
->first();
if (!$semesterAktif) {
$semesterAktif = Semester::select('id_semester', 'nama_semester', 'tahun_ajaran')
->orderBy('tahun_ajaran', 'desc')
->orderBy('periode', 'desc')
->first();
}
Log::info('Semester aktif: ' . ($semesterAktif ? $semesterAktif->nama_semester : 'Tidak ada'));
} catch (\Exception $e) {
Log::warning('Error mengambil semester: ' . $e->getMessage());
$semesterAktif = null;
}
// ✅ AMBIL PROGRES AL-QUR'AN dengan FALLBACK
$progresAlquran = 0;
try {
$query = Capaian::where('id_santri', $idSantri);
if ($semesterAktif) {
$query->where('id_semester', $semesterAktif->id_semester);
}
$progresAlquran = $query->whereHas('materi', function($q) {
$q->where('kategori', 'Al-Qur\'an');
})->avg('persentase') ?? 0;
Log::info('Progres Al-Quran: ' . $progresAlquran);
} catch (\Exception $e) {
Log::warning('Error progres Al-Quran: ' . $e->getMessage());
$progresAlquran = 0;
}
// ✅ AMBIL PROGRES HADIST dengan FALLBACK
$progresHadist = 0;
try {
$query = Capaian::where('id_santri', $idSantri);
if ($semesterAktif) {
$query->where('id_semester', $semesterAktif->id_semester);
}
$progresHadist = $query->whereHas('materi', function($q) {
$q->where('kategori', 'Hadist');
})->avg('persentase') ?? 0;
Log::info('Progres Hadist: ' . $progresHadist);
} catch (\Exception $e) {
Log::warning('Error progres Hadist: ' . $e->getMessage());
$progresHadist = 0;
}
// ✅ AMBIL PROGRES MATERI TAMBAHAN dengan FALLBACK
$progresMateriTambahan = 0;
try {
$query = Capaian::where('id_santri', $idSantri);
if ($semesterAktif) {
$query->where('id_semester', $semesterAktif->id_semester);
}
$progresMateriTambahan = $query->whereHas('materi', function($q) {
$q->where('kategori', 'Materi Tambahan');
})->avg('persentase') ?? 0;
Log::info('Progres Materi Tambahan: ' . $progresMateriTambahan);
} catch (\Exception $e) {
Log::warning('Error progres Materi Tambahan: ' . $e->getMessage());
$progresMateriTambahan = 0;
}
// ✅ DATA UNTUK GRAFIK 1: Progress per Materi dengan FALLBACK
$capaianPerMateri = collect([]);
try {
$query = Capaian::with(['materi' => function($q) {
$q->select('id_materi', 'nama_kitab', 'kategori', 'total_halaman');
}])
->where('id_santri', $idSantri);
if ($semesterAktif) {
$query->where('id_semester', $semesterAktif->id_semester);
}
$capaianPerMateri = $query->select('id', 'id_materi', 'persentase', 'halaman_selesai')
->orderBy('persentase', 'desc')
->limit(10)
->get();
Log::info('Capaian per materi: ' . $capaianPerMateri->count() . ' items');
} catch (\Exception $e) {
Log::warning('Error capaian per materi: ' . $e->getMessage());
$capaianPerMateri = collect([]);
}
// ✅ DATA UNTUK GRAFIK 2: Distribusi Status dengan FALLBACK
$distribusiStatus = [
'selesai' => 0,
'hampir_selesai' => 0,
'sedang_berjalan' => 0,
'baru_dimulai' => 0,
];
try {
$baseQuery = Capaian::where('id_santri', $idSantri);
if ($semesterAktif) {
$baseQuery->where('id_semester', $semesterAktif->id_semester);
}
$distribusiStatus = [
'selesai' => (clone $baseQuery)->where('persentase', '>=', 100)->count(),
'hampir_selesai' => (clone $baseQuery)->whereBetween('persentase', [75, 99.99])->count(),
'sedang_berjalan' => (clone $baseQuery)->whereBetween('persentase', [25, 74.99])->count(),
'baru_dimulai' => (clone $baseQuery)->whereBetween('persentase', [0, 24.99])->count(),
];
Log::info('Distribusi status: ' . json_encode($distribusiStatus));
} catch (\Exception $e) {
Log::warning('Error distribusi status: ' . $e->getMessage());
}
// ✅ Data dashboard utama
$data = [
'nama_santri' => $santri->nama_lengkap,
'kelas' => $santri->kelas,
'progres_quran' => 0, // Nanti diisi dari database capaian
'progres_hadist' => 0, // Nanti diisi dari database capaian
// Query langsung untuk saldo uang saku (dari accessor model)
'saldo_uang_saku' => $santri->saldo_uang_saku,
// Query optimized untuk poin pelanggaran
'poin_pelanggaran' => RiwayatPelanggaran::where('id_santri', $idSantri)
->sum('poin'),
'progres_quran' => round($progresAlquran, 1),
'progres_hadist' => round($progresHadist, 1),
'progres_materi_tambahan' => round($progresMateriTambahan, 1),
'saldo_uang_saku' => method_exists($santri, 'getSaldoUangSakuAttribute')
? $santri->saldo_uang_saku
: 0,
'poin_pelanggaran' => RiwayatPelanggaran::where('id_santri', $idSantri)->sum('poin') ?? 0,
];
// ✅ Query status kesehatan (hanya jika sedang dirawat)
Log::info('Data array: ' . json_encode($data));
// ✅ Query status kesehatan dengan FALLBACK
$statusKesehatan = null;
try {
$statusKesehatan = KesehatanSantri::where('id_santri', $idSantri)
->where('status', 'dirawat')
->select('id', 'keluhan', 'tanggal_masuk')
->orderBy('tanggal_masuk', 'desc')
->first();
} catch (\Exception $e) {
Log::warning('Error status kesehatan: ' . $e->getMessage());
}
// ✅ Query kepulangan aktif (hanya jika sedang dalam periode pulang)
// ✅ Query kepulangan aktif dengan FALLBACK
$kepulanganAktif = null;
try {
$kepulanganAktif = Kepulangan::where('id_santri', $idSantri)
->where('status', 'Disetujui')
->whereDate('tanggal_pulang', '<=', $today)
->whereDate('tanggal_kembali', '>=', $today)
->select('id_kepulangan', 'tanggal_pulang', 'tanggal_kembali', 'alasan')
->first();
} catch (\Exception $e) {
Log::warning('Error kepulangan aktif: ' . $e->getMessage());
}
// ✅ Query berita terbaru (7 hari terakhir) - OPTIMIZED
// ✅ Query berita terbaru dengan FALLBACK
$beritaTerbaru = collect([]);
try {
$beritaTerbaru = Berita::select('id_berita', 'judul', 'created_at')
->where('status', 'published')
->where('created_at', '>=', $weekAgo)
@ -101,34 +249,46 @@ public function santri()
->orWhere(function($q) use ($santri) {
$q->where('target_berita', 'kelas_tertentu')
->whereJsonContains('target_kelas', $santri->kelas);
})
->orWhereHas('santriTertentu', function($q) use ($santri) {
$q->where('santris.id_santri', $santri->id_santri);
});
})
->orderBy('created_at', 'desc')
->limit(5)
->get();
// Return view dengan data yang sudah dioptimasi
Log::info('Berita terbaru: ' . $beritaTerbaru->count() . ' items');
} catch (\Exception $e) {
Log::warning('Error berita terbaru: ' . $e->getMessage());
$beritaTerbaru = collect([]);
}
Log::info('=== DASHBOARD SANTRI SUCCESS ===');
// Return view dengan semua data
return view('santri.dashboardSantri', compact(
'data',
'santri',
'user',
'beritaTerbaru',
'statusKesehatan',
'kepulanganAktif'
'kepulanganAktif',
'capaianPerMateri',
'distribusiStatus',
'semesterAktif'
));
} catch (\Exception $e) {
Log::error('=== ERROR DI DASHBOARD SANTRI ===');
Log::error('=== FATAL ERROR DI DASHBOARD SANTRI ===');
Log::error('Message: ' . $e->getMessage());
Log::error('File: ' . $e->getFile());
Log::error('Line: ' . $e->getLine());
Log::error('Trace: ' . $e->getTraceAsString());
return response()->view('errors.500', [
'error' => $e->getMessage(),
], 500);
// Tampilkan error detail jika debug mode
if (config('app.debug')) {
abort(500, 'Error: ' . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine());
} else {
abort(500, 'Terjadi kesalahan saat memuat dashboard. Silakan hubungi administrator.');
}
}
}
}

View File

@ -0,0 +1,178 @@
<?php
// app/Http/Controllers/Santri/RiwayatKegiatanSantriController.php
namespace App\Http\Controllers\Santri;
use App\Http\Controllers\Controller;
use App\Models\AbsensiKegiatan;
use App\Models\Kegiatan;
use App\Models\Santri;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
class RiwayatKegiatanSantriController extends Controller
{
/**
* Halaman utama: Jadwal Harian + Riwayat Absensi
*/
public function index(Request $request)
{
$user = Auth::user();
if ($user->role !== 'santri') {
abort(403, 'Akses ditolak.');
}
$santri = Santri::where('id_santri', $user->role_id)
->select('id_santri', 'nama_lengkap', 'kelas')
->firstOrFail();
$idSantri = $santri->id_santri;
$today = Carbon::today();
$hariIni = Carbon::now()->locale('id')->dayName; // Senin, Selasa, etc.
// ✅ JADWAL KEGIATAN HARI INI (Tetap)
$jadwalHariIni = Kegiatan::with('kategori')
->where('hari', ucfirst($hariIni))
->select('kegiatan_id', 'kategori_id', 'nama_kegiatan', 'waktu_mulai', 'waktu_selesai', 'materi')
->orderBy('waktu_mulai')
->get();
// ✅ CEK STATUS ABSENSI HARI INI
$absensiHariIni = AbsensiKegiatan::where('id_santri', $idSantri)
->whereDate('tanggal', $today)
->pluck('status', 'kegiatan_id')
->toArray();
// ✅ RIWAYAT ABSENSI (dengan filter)
$query = AbsensiKegiatan::with('kegiatan.kategori')
->where('id_santri', $idSantri);
// Filter Bulan
if ($request->filled('bulan')) {
$bulan = Carbon::parse($request->bulan);
$query->whereMonth('tanggal', $bulan->month)
->whereYear('tanggal', $bulan->year);
}
// Filter Status
if ($request->filled('status')) {
$query->where('status', $request->status);
}
$riwayats = $query->orderBy('tanggal', 'desc')
->orderBy('waktu_absen', 'desc')
->paginate(15)
->appends(request()->query());
// ✅ STATISTIK KEHADIRAN (30 HARI TERAKHIR)
$stats30Hari = AbsensiKegiatan::where('id_santri', $idSantri)
->whereDate('tanggal', '>=', Carbon::now()->subDays(30))
->select('status', DB::raw('count(*) as total'))
->groupBy('status')
->pluck('total', 'status')
->toArray();
$totalKegiatan30Hari = array_sum($stats30Hari);
$persentaseKehadiran = $totalKegiatan30Hari > 0
? round(($stats30Hari['Hadir'] ?? 0) / $totalKegiatan30Hari * 100, 1)
: 0;
// ✅ DATA GRAFIK: Kehadiran per Minggu (4 Minggu Terakhir)
$dataGrafikMingguan = [];
for ($i = 3; $i >= 0; $i--) {
$startWeek = Carbon::now()->subWeeks($i)->startOfWeek();
$endWeek = Carbon::now()->subWeeks($i)->endOfWeek();
$hadir = AbsensiKegiatan::where('id_santri', $idSantri)
->whereBetween('tanggal', [$startWeek, $endWeek])
->where('status', 'Hadir')
->count();
$total = AbsensiKegiatan::where('id_santri', $idSantri)
->whereBetween('tanggal', [$startWeek, $endWeek])
->count();
$dataGrafikMingguan[] = [
'minggu' => 'Minggu ' . (4 - $i),
'hadir' => $hadir,
'total' => $total,
'persentase' => $total > 0 ? round($hadir / $total * 100, 1) : 0,
];
}
// ✅ STATISTIK PER KATEGORI KEGIATAN
$statsByKategori = AbsensiKegiatan::where('id_santri', $idSantri)
->join('kegiatans', 'absensi_kegiatans.kegiatan_id', '=', 'kegiatans.kegiatan_id')
->join('kategori_kegiatans', 'kegiatans.kategori_id', '=', 'kategori_kegiatans.kategori_id')
->select(
'kategori_kegiatans.nama_kategori',
DB::raw('SUM(CASE WHEN absensi_kegiatans.status = "Hadir" THEN 1 ELSE 0 END) as hadir'),
DB::raw('COUNT(*) as total')
)
->groupBy('kategori_kegiatans.nama_kategori')
->get();
return view('santri.kegiatan.index', compact(
'santri',
'jadwalHariIni',
'absensiHariIni',
'riwayats',
'stats30Hari',
'totalKegiatan30Hari',
'persentaseKehadiran',
'dataGrafikMingguan',
'statsByKategori',
'hariIni'
));
}
/**
* Detail Riwayat Absensi per Kegiatan
*/
public function show($kegiatan_id)
{
$user = Auth::user();
if ($user->role !== 'santri') {
abort(403, 'Akses ditolak.');
}
$santri = Santri::where('id_santri', $user->role_id)
->select('id_santri', 'nama_lengkap')
->firstOrFail();
$kegiatan = Kegiatan::with('kategori')
->where('kegiatan_id', $kegiatan_id)
->firstOrFail();
// Riwayat absensi untuk kegiatan ini
$riwayats = AbsensiKegiatan::where('id_santri', $santri->id_santri)
->where('kegiatan_id', $kegiatan_id)
->orderBy('tanggal', 'desc')
->paginate(20);
// Statistik kehadiran untuk kegiatan ini
$stats = AbsensiKegiatan::where('id_santri', $santri->id_santri)
->where('kegiatan_id', $kegiatan_id)
->select('status', DB::raw('count(*) as total'))
->groupBy('status')
->pluck('total', 'status')
->toArray();
$totalAbsensi = array_sum($stats);
$persentaseHadir = $totalAbsensi > 0
? round(($stats['Hadir'] ?? 0) / $totalAbsensi * 100, 1)
: 0;
return view('santri.kegiatan.show', compact(
'santri',
'kegiatan',
'riwayats',
'stats',
'totalAbsensi',
'persentaseHadir'
));
}
}

View File

@ -43,6 +43,7 @@ function () use ($user) {
'nama_orang_tua',
'nomor_hp_ortu',
'rfid_uid',
'foto', // ✅ TAMBAHAN INI - PENTING!
'created_at'
])
->firstOrFail();
@ -68,8 +69,10 @@ public function edit()
'id',
'id_santri',
'nama_lengkap',
'jenis_kelamin', // ✅ TAMBAHAN untuk fallback foto default
'alamat_santri',
'nomor_hp_ortu'
'nomor_hp_ortu',
'foto' // ✅ TAMBAHAN INI - PENTING!
])
->firstOrFail();

View File

@ -1,9 +1,10 @@
<?php
// app/Models/AbsensiKegiatan.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
class AbsensiKegiatan extends Model
{
@ -75,7 +76,7 @@ public function scopeKegiatan($query, $kegiatan_id)
}
/**
* Accessor: Status Badge
* Accessor: Status Badge (HTML - untuk admin)
*/
public function getStatusBadgeAttribute()
{
@ -88,4 +89,55 @@ public function getStatusBadgeAttribute()
return $badges[$this->status] ?? $this->status;
}
// ============================================
// ✅ TAMBAHKAN METHOD-METHOD BARU DI BAWAH INI
// ============================================
/**
* Accessor: Tanggal Formatted (untuk view santri)
*/
public function getTanggalFormattedAttribute()
{
return Carbon::parse($this->tanggal)->locale('id')->isoFormat('dddd, D MMMM YYYY');
}
/**
* Accessor: Waktu Absen Formatted (untuk view santri)
*/
public function getWaktuAbsenFormattedAttribute()
{
return $this->waktu_absen ? Carbon::parse($this->waktu_absen)->format('H:i') : '-';
}
/**
* Accessor: Status Badge Class (CSS class only - untuk view santri)
*/
public function getStatusBadgeClassAttribute()
{
return match($this->status) {
'Hadir' => 'badge-success',
'Izin' => 'badge-info',
'Sakit' => 'badge-warning',
'Alpa' => 'badge-danger',
default => 'badge-secondary',
};
}
/**
* Scope: Filter by date range
*/
public function scopeDateRange($query, $start, $end)
{
return $query->whereBetween('tanggal', [$start, $end]);
}
/**
* Scope: Filter by month
*/
public function scopeByMonth($query, $month, $year)
{
return $query->whereMonth('tanggal', $month)
->whereYear('tanggal', $year);
}
}

View File

@ -1,5 +1,5 @@
<?php
// Models/KategoriKegiatan
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;

View File

@ -1,5 +1,5 @@
<?php
// Models/Kegiatan
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;

View File

@ -6,6 +6,7 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
class Kepulangan extends Model
{
@ -32,47 +33,61 @@ class Kepulangan extends Model
'tanggal_pulang' => 'date',
'tanggal_kembali' => 'date',
'approved_at' => 'datetime',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
/**
* Boot method untuk auto-generate ID Kepulangan
* Boot method - Auto generate ID & calculate durasi
*/
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
// Generate ID Kepulangan
if (empty($model->id_kepulangan)) {
$last = Kepulangan::orderBy('id', 'desc')->first();
$num = $last ? intval(substr($last->id_kepulangan, 2)) + 1 : 1;
$model->id_kepulangan = 'KP' . str_pad($num, 3, '0', STR_PAD_LEFT);
}
// Auto-calculate durasi_izin
// PENTING: Hitung durasi_izin otomatis
if ($model->tanggal_pulang && $model->tanggal_kembali) {
$pulang = Carbon::parse($model->tanggal_pulang);
$kembali = Carbon::parse($model->tanggal_kembali);
$model->durasi_izin = $pulang->diffInDays($kembali) + 1;
$model->durasi_izin = $model->hitungDurasiIzin(
$model->tanggal_pulang,
$model->tanggal_kembali
);
}
// Set tanggal_izin ke hari ini jika tidak diisi
// Set tanggal_izin jika kosong
if (empty($model->tanggal_izin)) {
$model->tanggal_izin = now();
}
});
static::updating(function ($model) {
// Recalculate durasi_izin saat update
// Recalculate durasi_izin saat update tanggal
if ($model->isDirty(['tanggal_pulang', 'tanggal_kembali'])) {
$pulang = Carbon::parse($model->tanggal_pulang);
$kembali = Carbon::parse($model->tanggal_kembali);
$model->durasi_izin = $pulang->diffInDays($kembali) + 1;
$model->durasi_izin = $model->hitungDurasiIzin(
$model->tanggal_pulang,
$model->tanggal_kembali
);
}
});
}
/**
* Method untuk menghitung durasi izin dalam hari
* Formula: (tanggal_kembali - tanggal_pulang) + 1
*/
private function hitungDurasiIzin($tanggalPulang, $tanggalKembali)
{
$pulang = Carbon::parse($tanggalPulang);
$kembali = Carbon::parse($tanggalKembali);
// +1 karena hari pertama juga dihitung
return $pulang->diffInDays($kembali) + 1;
}
/**
* Relasi ke Santri
*/
@ -82,52 +97,38 @@ public function santri()
}
/**
* Accessor: Format tanggal izin
* Accessor: Format tanggal
*/
public function getTanggalIzinFormattedAttribute()
{
return $this->tanggal_izin ? $this->tanggal_izin->format('d F Y') : '-';
}
/**
* Accessor: Format tanggal pulang
*/
public function getTanggalPulangFormattedAttribute()
{
return $this->tanggal_pulang ? $this->tanggal_pulang->format('d F Y') : '-';
}
/**
* Accessor: Format tanggal kembali
*/
public function getTanggalKembaliFormattedAttribute()
{
return $this->tanggal_kembali ? $this->tanggal_kembali->format('d F Y') : '-';
}
/**
* Accessor: Format approved_at
*/
public function getApprovedAtFormattedAttribute()
{
return $this->approved_at ? $this->approved_at->format('d F Y H:i') : '-';
}
/**
* Accessor: Durasi izin calculated
* Accessor: Durasi izin calculated (untuk backward compatibility)
*/
public function getDurasiIzinCalculatedAttribute()
{
if ($this->tanggal_pulang && $this->tanggal_kembali) {
$pulang = Carbon::parse($this->tanggal_pulang);
$kembali = Carbon::parse($this->tanggal_kembali);
return $pulang->diffInDays($kembali) + 1;
}
return $this->durasi_izin ?? 0;
return $this->durasi_izin;
}
/**
* Accessor: Status badge HTML
* Accessor: Status badge
*/
public function getStatusBadgeAttribute()
{
@ -137,7 +138,6 @@ public function getStatusBadgeAttribute()
'Ditolak' => 'badge-danger',
'Selesai' => 'badge-secondary',
];
return $badges[$this->status] ?? 'badge-secondary';
}
@ -163,24 +163,18 @@ public function getIsTerlambatAttribute()
}
/**
* Scope: Filter berdasarkan status
* Scopes
*/
public function scopeStatus($query, $status)
{
return $query->where('status', $status);
}
/**
* Scope: Filter berdasarkan santri
*/
public function scopeSantri($query, $idSantri)
{
return $query->where('id_santri', $idSantri);
}
/**
* Scope: Kepulangan yang sedang aktif
*/
public function scopeAktif($query)
{
$today = Carbon::today();
@ -189,18 +183,12 @@ public function scopeAktif($query)
->whereDate('tanggal_kembali', '>=', $today);
}
/**
* Scope: Kepulangan yang terlambat
*/
public function scopeTerlambat($query)
{
return $query->where('status', 'Disetujui')
->whereDate('tanggal_kembali', '<', Carbon::today());
}
/**
* Scope: Search kepulangan
*/
public function scopeSearch($query, $search)
{
return $query->where(function($q) use ($search) {
@ -215,33 +203,285 @@ public function scopeSearch($query, $search)
}
/**
* Static method: Get total hari izin per santri per tahun
* ========================================
* FITUR KUOTA TAHUNAN
* ========================================
*/
public static function getTotalHariIzinSantri($idSantri, $tahun = null)
/**
* Get settings kepulangan (kuota, periode)
*/
public static function getSettings()
{
$tahun = $tahun ?? Carbon::now()->year;
$settings = DB::table('kepulangan_settings')->latest()->first();
if (!$settings) {
// Create default settings
DB::table('kepulangan_settings')->insert([
'kuota_maksimal' => 12,
'periode_mulai' => now()->startOfYear()->format('Y-m-d'),
'periode_akhir' => now()->endOfYear()->format('Y-m-d'),
'created_at' => now(),
'updated_at' => now(),
]);
$settings = DB::table('kepulangan_settings')->latest()->first();
}
return (object) [
'id' => $settings->id,
'kuota_maksimal' => $settings->kuota_maksimal,
'periode_mulai' => Carbon::parse($settings->periode_mulai),
'periode_akhir' => Carbon::parse($settings->periode_akhir),
'terakhir_reset' => $settings->terakhir_reset ? Carbon::parse($settings->terakhir_reset) : null,
'reset_by' => $settings->reset_by,
];
}
/**
* Update settings kepulangan
*/
public static function updateSettings($kuotaMaksimal, $periodeMulai, $periodeAkhir)
{
$existing = DB::table('kepulangan_settings')->latest()->first();
if ($existing) {
DB::table('kepulangan_settings')
->where('id', $existing->id)
->update([
'kuota_maksimal' => $kuotaMaksimal,
'periode_mulai' => $periodeMulai,
'periode_akhir' => $periodeAkhir,
'updated_at' => now(),
]);
} else {
DB::table('kepulangan_settings')->insert([
'kuota_maksimal' => $kuotaMaksimal,
'periode_mulai' => $periodeMulai,
'periode_akhir' => $periodeAkhir,
'created_at' => now(),
'updated_at' => now(),
]);
}
}
/**
* Get total hari izin santri dalam periode tertentu
*/
public static function getTotalHariIzinSantri($idSantri, $periodeMulai = null, $periodeAkhir = null)
{
if (!$periodeMulai || !$periodeAkhir) {
$settings = self::getSettings();
$periodeMulai = $settings->periode_mulai;
$periodeAkhir = $settings->periode_akhir;
}
return self::where('id_santri', $idSantri)
->where('status', 'Disetujui')
->whereYear('tanggal_pulang', $tahun)
->whereIn('status', ['Disetujui', 'Selesai'])
->whereBetween('tanggal_pulang', [$periodeMulai, $periodeAkhir])
->sum('durasi_izin');
}
/**
* Static method: Check apakah santri over limit (lebih dari 12 hari/tahun)
* Get detail kuota santri
*/
public static function isOverLimit($idSantri, $tahun = null)
public static function getSisaKuotaSantri($idSantri)
{
$totalHari = self::getTotalHariIzinSantri($idSantri, $tahun);
return $totalHari > 12;
$settings = self::getSettings();
$totalTerpakai = self::getTotalHariIzinSantri(
$idSantri,
$settings->periode_mulai,
$settings->periode_akhir
);
$sisaKuota = $settings->kuota_maksimal - $totalTerpakai;
$persentase = $settings->kuota_maksimal > 0 ?
($totalTerpakai / $settings->kuota_maksimal) * 100 : 0;
// Tentukan status berdasarkan persentase
$status = 'aman'; // 0-80%
if ($persentase >= 80 && $persentase < 100) {
$status = 'hampir_habis'; // 80-100%
} elseif ($persentase >= 100) {
$status = 'melebihi'; // >100%
}
// Warna badge
$badgeColor = 'success'; // Hijau
if ($persentase >= 80 && $persentase < 100) {
$badgeColor = 'warning'; // Kuning
} elseif ($persentase >= 100) {
$badgeColor = 'danger'; // Merah
}
return [
'kuota_maksimal' => $settings->kuota_maksimal,
'total_terpakai' => $totalTerpakai,
'sisa_kuota' => max(0, $sisaKuota),
'persentase' => round($persentase, 1),
'status' => $status,
'badge_color' => $badgeColor,
'periode_mulai' => $settings->periode_mulai->format('d M Y'),
'periode_akhir' => $settings->periode_akhir->format('d M Y'),
'terakhir_reset' => $settings->terakhir_reset ?
$settings->terakhir_reset->format('d M Y') : '-',
];
}
/**
* Static method: Get sisa kuota izin santri
* Check apakah santri over limit
*/
public static function getSisaKuota($idSantri, $tahun = null)
public static function isOverLimit($idSantri)
{
$totalHari = self::getTotalHariIzinSantri($idSantri, $tahun);
return max(0, 12 - $totalHari);
$kuota = self::getSisaKuotaSantri($idSantri);
return $kuota['status'] === 'melebihi';
}
/**
* Get list santri yang over limit
*/
public static function getSantriOverLimit()
{
$settings = self::getSettings();
$santriIds = Santri::where('status', 'Aktif')->pluck('id_santri');
$overLimitList = [];
foreach ($santriIds as $idSantri) {
$totalHari = self::getTotalHariIzinSantri(
$idSantri,
$settings->periode_mulai,
$settings->periode_akhir
);
if ($totalHari > $settings->kuota_maksimal) {
$overLimitList[$idSantri] = $totalHari;
}
}
return $overLimitList;
}
/**
* ========================================
* FITUR RESET KUOTA
* ========================================
*/
/**
* Reset kuota untuk satu santri
*/
public static function resetKuotaSantri($idSantri, $resetBy, $catatan = null)
{
$settings = self::getSettings();
// Hitung total hari sebelum reset
$totalHariSebelumReset = self::getTotalHariIzinSantri(
$idSantri,
$settings->periode_mulai,
$settings->periode_akhir
);
// Catat log reset
DB::table('kepulangan_reset_logs')->insert([
'id_santri' => $idSantri,
'total_hari_sebelum_reset' => $totalHariSebelumReset,
'periode_mulai' => $settings->periode_mulai,
'periode_akhir' => $settings->periode_akhir,
'kuota_tahunan' => $settings->kuota_maksimal,
'jenis_reset' => 'individual',
'reset_by' => $resetBy,
'catatan' => $catatan,
'created_at' => now(),
'updated_at' => now(),
]);
// Update semua kepulangan santri yang Disetujui menjadi Selesai
// Ini cara "reset" dengan menandai semua izin lama sebagai selesai
self::where('id_santri', $idSantri)
->where('status', 'Disetujui')
->whereBetween('tanggal_pulang', [$settings->periode_mulai, $settings->periode_akhir])
->update(['status' => 'Selesai']);
return [
'success' => true,
'total_hari_direset' => $totalHariSebelumReset,
];
}
/**
* Reset kuota untuk semua santri
*/
public static function resetKuotaSemuaSantri($resetBy, $catatan = null)
{
$settings = self::getSettings();
// Get semua santri aktif
$santriIds = Santri::where('status', 'Aktif')->pluck('id_santri');
$totalSantri = $santriIds->count();
$totalHariDireset = 0;
foreach ($santriIds as $idSantri) {
$totalHari = self::getTotalHariIzinSantri(
$idSantri,
$settings->periode_mulai,
$settings->periode_akhir
);
$totalHariDireset += $totalHari;
}
// Catat log reset massal
DB::table('kepulangan_reset_logs')->insert([
'id_santri' => null, // Null untuk reset massal
'total_hari_sebelum_reset' => $totalHariDireset,
'periode_mulai' => $settings->periode_mulai,
'periode_akhir' => $settings->periode_akhir,
'kuota_tahunan' => $settings->kuota_maksimal,
'jenis_reset' => 'massal',
'reset_by' => $resetBy,
'catatan' => $catatan ?? "Reset massal untuk {$totalSantri} santri",
'created_at' => now(),
'updated_at' => now(),
]);
// Update semua kepulangan yang Disetujui menjadi Selesai
$jumlahDiupdate = self::whereIn('id_santri', $santriIds)
->where('status', 'Disetujui')
->whereBetween('tanggal_pulang', [$settings->periode_mulai, $settings->periode_akhir])
->update(['status' => 'Selesai']);
// Update tanggal terakhir reset di settings
DB::table('kepulangan_settings')
->where('id', $settings->id)
->update([
'terakhir_reset' => now(),
'reset_by' => $resetBy,
'updated_at' => now(),
]);
return [
'success' => true,
'total_santri' => $totalSantri,
'total_hari_direset' => $totalHariDireset,
'jumlah_izin_diupdate' => $jumlahDiupdate,
];
}
/**
* Get history reset logs
*/
public static function getResetLogs($limit = 20)
{
return DB::table('kepulangan_reset_logs')
->leftJoin('santris', 'kepulangan_reset_logs.id_santri', '=', 'santris.id_santri')
->select(
'kepulangan_reset_logs.*',
'santris.nama_lengkap'
)
->orderBy('kepulangan_reset_logs.created_at', 'desc')
->limit($limit)
->get();
}
}

View File

@ -1,5 +1,5 @@
<?php
// app/Models/Santri.php - Model untuk Data Santri (LENGKAP)
// app/Models/Santri.php - Model untuk Data Santri (DENGAN FOTO)
namespace App\Models;
@ -24,7 +24,8 @@ class Santri extends Model
'daerah_asal',
'nama_orang_tua',
'nomor_hp_ortu',
'rfid_uid', // TAMBAHAN BARU
'rfid_uid',
'foto', // TAMBAHAN BARU
];
/**
@ -246,6 +247,23 @@ public function getTotalKehadiranAttribute()
return $this->absensiKegiatans()->where('status', 'Hadir')->count();
}
/**
* Accessor: URL Foto Santri (BARU)
*/
public function getFotoUrlAttribute()
{
if ($this->foto && file_exists(storage_path('app/public/' . $this->foto))) {
return asset('storage/' . $this->foto);
}
// Fallback ke gambar default berdasarkan jenis kelamin
if ($this->jenis_kelamin === 'Perempuan') {
return asset('images/default-female.png');
}
return asset('images/default-male.png');
}
/**
* Scope untuk filter santri aktif
*/

View File

@ -3,7 +3,6 @@
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
@ -13,41 +12,42 @@ class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'username', // Ditambahkan
'username',
'password',
'role', // Ditambahkan
'role_id', // Ditambahkan
'role',
'role_id',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
// Helper method untuk cek role
/**
* Relasi ke Santri
*/
public function santri()
{
return $this->belongsTo(Santri::class, 'role_id', 'id_santri');
}
/**
* Relasi ke Wali
*/
public function wali()
{
return $this->belongsTo(Wali::class, 'role_id', 'id_wali');
}
// Helper methods
public function isAdmin()
{
return $this->role === 'admin';

View File

@ -1,45 +0,0 @@
<?php
// database/migrations/xxxx_xx_xx_xxxxxx_create_kepulangan_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('kepulangan', function (Blueprint $table) {
$table->id();
$table->string('id_kepulangan')->unique(); // KP001, KP002, dst
$table->string('id_santri'); // Relasi ke santri (S001, S002, dst)
$table->date('tanggal_izin'); // Tanggal pengajuan izin
$table->date('tanggal_pulang'); // Tanggal mulai pulang
$table->date('tanggal_kembali'); // Tanggal rencana kembali
$table->integer('durasi_izin'); // Durasi dalam hari
$table->text('alasan'); // Alasan kepulangan
$table->enum('status', ['Menunggu', 'Disetujui', 'Ditolak', 'Selesai'])->default('Menunggu');
$table->string('approved_by')->nullable(); // Admin yang menyetujui
$table->timestamp('approved_at')->nullable(); // Waktu persetujuan
$table->text('catatan')->nullable(); // Catatan dari admin
$table->timestamps();
// Foreign key
$table->foreign('id_santri')
->references('id_santri')
->on('santris')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('kepulangan');
}
};

View File

@ -0,0 +1,54 @@
<?php
// database/migrations/xxxx_xx_xx_create_kepulangan_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('kepulangan', function (Blueprint $table) {
$table->id();
$table->string('id_kepulangan', 20)->unique()->index();
$table->string('id_santri', 20);
$table->date('tanggal_izin');
$table->date('tanggal_pulang');
$table->date('tanggal_kembali');
$table->integer('durasi_izin')->default(0)->comment('Durasi dalam hari');
$table->text('alasan');
$table->enum('status', ['Menunggu', 'Disetujui', 'Ditolak', 'Selesai'])
->default('Menunggu');
$table->string('approved_by', 100)->nullable();
$table->timestamp('approved_at')->nullable();
$table->text('catatan')->nullable()->comment('Catatan approval atau penolakan');
$table->timestamps();
// Foreign key
$table->foreign('id_santri')
->references('id_santri')
->on('santris')
->onDelete('cascade')
->onUpdate('cascade');
// Indexes untuk performa
$table->index('status');
$table->index('tanggal_pulang');
$table->index('tanggal_kembali');
$table->index(['id_santri', 'status']);
$table->index(['tanggal_pulang', 'tanggal_kembali']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('kepulangan');
}
};

View File

@ -0,0 +1,42 @@
<?php
// database/migrations/xxxx_xx_xx_create_kepulangan_settings_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('kepulangan_settings', function (Blueprint $table) {
$table->id();
$table->integer('kuota_maksimal')->default(12)->comment('Kuota hari izin per tahun');
$table->date('periode_mulai')->comment('Awal periode kuota');
$table->date('periode_akhir')->comment('Akhir periode kuota');
$table->timestamp('terakhir_reset')->nullable();
$table->string('reset_by', 100)->nullable();
$table->timestamps();
});
// Insert default settings
DB::table('kepulangan_settings')->insert([
'kuota_maksimal' => 12,
'periode_mulai' => now()->startOfYear()->format('Y-m-d'),
'periode_akhir' => now()->endOfYear()->format('Y-m-d'),
'created_at' => now(),
'updated_at' => now(),
]);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('kepulangan_settings');
}
};

View File

@ -0,0 +1,48 @@
<?php
// database/migrations/xxxx_xx_xx_create_kepulangan_reset_logs_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('kepulangan_reset_logs', function (Blueprint $table) {
$table->id();
$table->string('id_santri', 20)->nullable()->comment('Null jika reset massal');
$table->integer('total_hari_sebelum_reset')->default(0);
$table->date('periode_mulai');
$table->date('periode_akhir');
$table->integer('kuota_tahunan');
$table->enum('jenis_reset', ['individual', 'massal'])->default('individual');
$table->string('reset_by', 100);
$table->text('catatan')->nullable();
$table->timestamps();
// Foreign key (nullable untuk reset massal)
$table->foreign('id_santri')
->references('id_santri')
->on('santris')
->onDelete('set null')
->onUpdate('cascade');
// Indexes
$table->index('id_santri');
$table->index('jenis_reset');
$table->index('created_at');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('kepulangan_reset_logs');
}
};

View File

@ -0,0 +1,29 @@
<?php
// database/migrations/YYYY_MM_DD_HHMMSS_add_foto_to_santris_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('santris', function (Blueprint $table) {
$table->string('foto')->nullable()->after('rfid_uid');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('santris', function (Blueprint $table) {
$table->dropColumn('foto');
});
}
};

View File

@ -9,6 +9,20 @@
<h2><i class="fas fa-plus-circle"></i> Tambah Izin Kepulangan</h2>
</div>
{{-- Info Periode Kuota --}}
<div style="background: #E8F7F2; padding: 15px; border-radius: 8px; margin-bottom: 20px; border-left: 4px solid #6FBA9D;">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
<div>
<strong>📅 Periode Kuota:</strong><br>
{{ $settings->periode_mulai->format('d M Y') }} - {{ $settings->periode_akhir->format('d M Y') }}
</div>
<div>
<strong>📊 Kuota Maksimal:</strong><br>
{{ $settings->kuota_maksimal }} Hari / Tahun
</div>
</div>
</div>
@if($errors->any())
<div class="alert alert-danger">
<ul style="margin: 0; padding-left: 20px;">
@ -38,22 +52,34 @@
</select>
</div>
{{-- Info Santri --}}
{{-- Info Santri & Kuota --}}
<div id="santriInfo" style="display: none; background: #f8f9fa; padding: 20px; border-radius: 8px; margin-bottom: 20px; border-left: 4px solid #6FBA9D;">
<h4 style="margin-top: 0; color: #2C3E50;">Informasi Santri</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px;">
<h4 style="margin-top: 0; color: #2C3E50;">📋 Informasi Santri & Kuota</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px;">
<div>
<p style="margin: 5px 0;"><strong>Nama:</strong> <span id="santriNama">-</span></p>
<p style="margin: 5px 0;"><strong>Kelas:</strong> <span id="santriKelas">-</span></p>
<p style="margin: 5px 0;"><strong>Periode:</strong> <span id="santriPeriode">-</span></p>
</div>
<div>
<p style="margin: 5px 0;"><strong>Total Hari Izin Tahun Ini:</strong> <span id="totalHariIzin" style="display: inline-block; background: #81C6E8; color: white; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">0 hari</span></p>
<p style="margin: 5px 0;"><strong>Sisa Kuota:</strong> <span id="sisaKuota" style="display: inline-block; background: #6FBA9D; color: white; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">12 hari</span></p>
<p style="margin: 5px 0;"><strong>Kuota Maksimal:</strong> <span id="kuotaMaksimal">-</span></p>
<p style="margin: 5px 0;"><strong>Total Terpakai:</strong> <span id="totalTerpakai" class="badge">-</span></p>
<p style="margin: 5px 0;"><strong>Sisa Kuota:</strong> <span id="sisaKuota" class="badge">-</span></p>
</div>
</div>
{{-- Progress Bar Kuota --}}
<div style="margin-top: 15px;">
<label style="font-size: 0.9rem; color: #7F8C8D; margin-bottom: 5px;">Penggunaan Kuota:</label>
<div style="width: 100%; height: 20px; background: #E0F0EC; border-radius: 10px; overflow: hidden; position: relative;">
<div id="progressBar" style="height: 100%; width: 0%; background: #28a745; transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.75rem; font-weight: 600;"></div>
</div>
<small id="progressText" style="color: #7F8C8D; margin-top: 5px; display: block;">0% dari kuota terpakai</small>
</div>
<div id="warningOverLimit" style="display: none; margin-top: 15px; padding: 12px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; color: #856404;">
<i class="fas fa-exclamation-triangle"></i>
<strong>Peringatan:</strong> Santri ini sudah melebihi batas 12 hari per tahun!
<strong>⚠️ PERHATIAN:</strong> <span id="warningText"></span>
</div>
</div>
@ -86,23 +112,29 @@ class="form-control"
</div>
</div>
{{-- Info Durasi --}}
<div id="durasiInfo" style="display: none; background: #f8f9fa; padding: 20px; border-radius: 8px; margin-bottom: 20px; border-left: 4px solid #FF8B94;">
<h4 style="margin-top: 0; color: #2C3E50;">Informasi Durasi Izin</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
<div>
<p style="margin: 5px 0;"><strong>Durasi Izin:</strong> <span id="durasiHari" style="display: inline-block; background: #007bff; color: white; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">0 hari</span></p>
{{-- Info Durasi Izin --}}
<div id="durasiInfo" style="display: none; background: #fff3e0; padding: 20px; border-radius: 8px; margin-bottom: 20px; border-left: 4px solid #ff9800;">
<h4 style="margin-top: 0; color: #2C3E50;">⏱️ Detail Durasi Izin</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 15px;">
<div style="text-align: center; padding: 15px; background: white; border-radius: 8px;">
<div style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Durasi Izin</div>
<div id="durasiHari" style="font-size: 2rem; font-weight: 700; color: #ff9800;">0</div>
<div style="font-size: 0.8rem; color: #7F8C8D;">hari</div>
</div>
<div>
<p style="margin: 5px 0;"><strong>Total Setelah Izin:</strong> <span id="totalSetelahIzin" style="display: inline-block; background: #6c757d; color: white; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">0 hari</span></p>
<div style="text-align: center; padding: 15px; background: white; border-radius: 8px;">
<div style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Total Setelah Izin</div>
<div id="totalSetelahIzin" style="font-size: 2rem; font-weight: 700; color: #2196f3;">0</div>
<div style="font-size: 0.8rem; color: #7F8C8D;">hari terpakai</div>
</div>
<div>
<p style="margin: 5px 0;"><strong>Sisa Kuota Setelah Izin:</strong> <span id="sisaKuotaSetelah" style="display: inline-block; background: #6FBA9D; color: white; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">12 hari</span></p>
<div style="text-align: center; padding: 15px; background: white; border-radius: 8px;">
<div style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Sisa Kuota</div>
<div id="sisaKuotaSetelah" style="font-size: 2rem; font-weight: 700; color: #28a745;">12</div>
<div style="font-size: 0.8rem; color: #7F8C8D;">hari tersisa</div>
</div>
</div>
<div id="warningDurasi" style="display: none; margin-top: 15px; padding: 12px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; color: #856404;">
<i class="fas fa-exclamation-triangle"></i>
<span id="warningMessage"></span>
<div id="warningDurasi" style="display: none; margin-top: 15px; padding: 12px; background: #ffebee; border: 1px solid #ffcdd2; border-radius: 6px; color: #c62828;">
<i class="fas fa-exclamation-circle"></i>
<strong>⚠️ PERHATIAN:</strong> <span id="warningDurasiMessage"></span>
</div>
</div>
@ -141,18 +173,19 @@ class="form-control"
<div class="modal-dialog">
<div class="modal-content" style="background: white; border-radius: 12px; padding: 20px;">
<div style="margin-bottom: 20px;">
<h3 style="margin: 0; color: #2C3E50;">Konfirmasi Izin Melebihi Batas</h3>
<h3 style="margin: 0; color: #2C3E50;">⚠️ Konfirmasi Izin Melebihi Batas</h3>
</div>
<div style="padding: 15px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; margin-bottom: 15px;">
<i class="fas fa-exclamation-triangle" style="font-size: 2rem; color: #856404; margin-bottom: 10px;"></i>
<h4 style="margin: 10px 0; color: #856404;">Peringatan!</h4>
<p id="overLimitMessage" style="margin: 0; color: #856404;"></p>
</div>
<p>Apakah Anda yakin ingin melanjutkan pengajuan izin ini?</p>
<p style="margin: 15px 0;">Izin tetap bisa diproses, tetapi santri ini akan <strong>melebihi kuota maksimal</strong>.</p>
<p style="margin: 15px 0; color: #7F8C8D; font-size: 0.9rem;">Apakah Anda yakin ingin melanjutkan pengajuan izin ini?</p>
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px;">
<button type="button" class="btn btn-secondary" onclick="closeModal('overLimitModal')">Batal</button>
<button type="button" class="btn btn-warning" id="confirmOverLimit">
<i class="fas fa-check"></i> Lanjutkan Tetap
<button type="button" class="btn btn-warning" id="confirmOverLimit" style="background: #ff9800; border-color: #ff9800;">
<i class="fas fa-check"></i> Ya, Lanjutkan Tetap
</button>
</div>
</div>
@ -163,6 +196,7 @@ class="form-control"
.modal.fade { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
.modal-dialog { max-width: 500px; width: 90%; margin: auto; }
.modal-content { max-height: 90vh; overflow-y: auto; }
.badge { display: inline-block; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; font-weight: 600; }
</style>
<script>
@ -182,46 +216,82 @@ class="form-control"
const infoDiv = document.getElementById('santriInfo');
infoDiv.style.display = 'block';
infoDiv.innerHTML = '<div style="text-align: center;"><i class="fas fa-spinner fa-spin"></i> Memuat data santri...</div>';
infoDiv.innerHTML = '<div style="text-align: center; padding: 20px;"><i class="fas fa-spinner fa-spin"></i> Memuat data santri...</div>';
fetch(`/admin/api/kepulangan/santri/${santriId}`)
.then(response => response.json())
.then(data => {
if (data.success) {
currentSantriData = data;
updateSantriInfo(data);
calculateDurasi();
} else {
infoDiv.innerHTML = `<div class="alert alert-danger">${data.message}</div>`;
}
})
.catch(error => {
infoDiv.innerHTML = `<div style="padding: 15px; background: #ffe8ea; border: 1px solid #ffd5d8; border-radius: 6px; color: #7C2D35;">Error loading santri data: ${error.message}</div>`;
infoDiv.innerHTML = `<div class="alert alert-danger">Error: ${error.message}</div>`;
});
});
function updateSantriInfo(data) {
const santri = data.santri;
const penggunaan = data.penggunaan_izin;
const kuota = data.penggunaan_izin;
const totalColor = penggunaan.total_hari > 8 ? '#ffc107' : '#81C6E8';
const sisaColor = penggunaan.sisa_kuota <= 3 ? '#dc3545' : '#6FBA9D';
// Tentukan warna badge berdasarkan status
let badgeColor = '#28a745'; // Hijau (aman)
let badgeTextColor = 'white';
if (kuota.status === 'hampir_habis') {
badgeColor = '#ffc107'; // Kuning
badgeTextColor = '#000';
} else if (kuota.status === 'melebihi') {
badgeColor = '#dc3545'; // Merah
}
document.getElementById('santriInfo').innerHTML = `
<h4 style="margin-top: 0; color: #2C3E50;">Informasi Santri</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px;">
<div>
<p style="margin: 5px 0;"><strong>Nama:</strong> ${santri.nama_lengkap}</p>
<p style="margin: 5px 0;"><strong>Kelas:</strong> ${santri.kelas}</p>
</div>
<div>
<p style="margin: 5px 0;"><strong>Total Hari Izin Tahun Ini:</strong> <span style="display: inline-block; background: ${totalColor}; color: ${penggunaan.total_hari > 8 ? '#000' : 'white'}; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">${penggunaan.total_hari} hari</span></p>
<p style="margin: 5px 0;"><strong>Sisa Kuota:</strong> <span style="display: inline-block; background: ${sisaColor}; color: white; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">${penggunaan.sisa_kuota} hari</span></p>
</div>
</div>
${penggunaan.over_limit ? `
<div style="margin-top: 15px; padding: 12px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; color: #856404;">
<i class="fas fa-exclamation-triangle"></i>
<strong>Peringatan:</strong> Santri ini sudah melebihi batas 12 hari per tahun!
</div>
` : ''}
`;
// Update info santri
document.getElementById('santriNama').textContent = santri.nama_lengkap;
document.getElementById('santriKelas').textContent = santri.kelas;
document.getElementById('santriPeriode').textContent = kuota.periode_mulai + ' - ' + kuota.periode_akhir;
document.getElementById('kuotaMaksimal').textContent = kuota.kuota_maksimal + ' hari';
const totalTerpakaiSpan = document.getElementById('totalTerpakai');
totalTerpakaiSpan.textContent = kuota.total_terpakai + ' hari';
totalTerpakaiSpan.style.background = badgeColor;
totalTerpakaiSpan.style.color = badgeTextColor;
const sisaKuotaSpan = document.getElementById('sisaKuota');
sisaKuotaSpan.textContent = kuota.sisa_kuota + ' hari';
sisaKuotaSpan.style.background = badgeColor;
sisaKuotaSpan.style.color = badgeTextColor;
// Update progress bar
const progressBar = document.getElementById('progressBar');
const progressText = document.getElementById('progressText');
progressBar.style.width = Math.min(100, kuota.persentase) + '%';
progressBar.textContent = kuota.persentase + '%';
progressText.textContent = kuota.persentase + '% dari kuota terpakai';
// Ubah warna progress bar
if (kuota.persentase >= 100) {
progressBar.style.background = '#dc3545'; // Merah
} else if (kuota.persentase >= 80) {
progressBar.style.background = '#ffc107'; // Kuning
} else {
progressBar.style.background = '#28a745'; // Hijau
}
// Tampilkan warning jika over limit
const warningDiv = document.getElementById('warningOverLimit');
const warningText = document.getElementById('warningText');
if (kuota.status === 'melebihi') {
warningDiv.style.display = 'block';
warningText.textContent = `Santri ini sudah melebihi kuota ${kuota.kuota_maksimal} hari per tahun! Total terpakai: ${kuota.total_terpakai} hari.`;
} else {
warningDiv.style.display = 'none';
}
// Restore full HTML structure
document.getElementById('santriInfo').style.display = 'block';
}
// Calculate durasi when dates change
@ -246,57 +316,67 @@ function calculateDurasi() {
return;
}
// Hitung durasi (termasuk hari pertama)
const diffTime = Math.abs(endDate - startDate);
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1;
durasiInfoDiv.style.display = 'block';
// Update durasi
document.getElementById('durasiHari').textContent = diffDays;
let totalSetelah = diffDays;
let sisaSetelah = 12 - diffDays;
let showWarning = false;
let warningMessage = '';
if (currentSantriData) {
const currentUsage = currentSantriData.penggunaan_izin.total_hari;
totalSetelah = currentUsage + diffDays;
sisaSetelah = 12 - totalSetelah;
const currentUsage = currentSantriData.penggunaan_izin.total_terpakai;
const kuotaMaks = currentSantriData.penggunaan_izin.kuota_maksimal;
if (totalSetelah > 12) {
totalSetelah = currentUsage + diffDays;
sisaSetelah = kuotaMaks - totalSetelah;
// Update nilai
document.getElementById('totalSetelahIzin').textContent = totalSetelah;
document.getElementById('sisaKuotaSetelah').textContent = Math.max(0, sisaSetelah);
// Ubah warna berdasarkan status
const totalSetelahEl = document.getElementById('totalSetelahIzin');
const sisaSetelahEl = document.getElementById('sisaKuotaSetelah');
if (totalSetelah > kuotaMaks) {
totalSetelahEl.style.color = '#dc3545';
sisaSetelahEl.style.color = '#dc3545';
showWarning = true;
warningMessage = `Izin ini akan melebihi batas 12 hari per tahun (total: ${totalSetelah} hari)`;
warningMessage = `Izin ini akan melebihi batas ${kuotaMaks} hari per tahun (Total setelah izin: ${totalSetelah} hari, Kelebihan: ${totalSetelah - kuotaMaks} hari)`;
isOverLimit = true;
} else if (totalSetelah >= kuotaMaks * 0.8) {
totalSetelahEl.style.color = '#ff9800';
sisaSetelahEl.style.color = '#ff9800';
showWarning = true;
warningMessage = `Perhatian: Kuota hampir habis! Sisa kuota setelah izin ini hanya ${sisaSetelah} hari.`;
isOverLimit = false;
} else {
totalSetelahEl.style.color = '#2196f3';
sisaSetelahEl.style.color = '#28a745';
showWarning = false;
isOverLimit = false;
}
}
const durasiColor = diffDays > 7 ? '#ffc107' : '#007bff';
const totalColor = totalSetelah > 12 ? '#dc3545' : '#6c757d';
const sisaColor = sisaSetelah < 0 ? '#dc3545' : sisaSetelah <= 3 ? '#ffc107' : '#6FBA9D';
durasiInfoDiv.innerHTML = `
<h4 style="margin-top: 0; color: #2C3E50;">Informasi Durasi Izin</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
<div>
<p style="margin: 5px 0;"><strong>Durasi Izin:</strong> <span style="display: inline-block; background: ${durasiColor}; color: ${diffDays > 7 ? '#000' : 'white'}; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">${diffDays} hari</span></p>
</div>
<div>
<p style="margin: 5px 0;"><strong>Total Setelah Izin:</strong> <span style="display: inline-block; background: ${totalColor}; color: white; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">${totalSetelah} hari</span></p>
</div>
<div>
<p style="margin: 5px 0;"><strong>Sisa Kuota Setelah Izin:</strong> <span style="display: inline-block; background: ${sisaColor}; color: ${sisaSetelah <= 3 && sisaSetelah >= 0 ? '#000' : 'white'}; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">${Math.max(0, sisaSetelah)} hari</span></p>
</div>
</div>
${showWarning ? `
<div style="margin-top: 15px; padding: 12px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; color: #856404;">
<i class="fas fa-exclamation-triangle"></i>
${warningMessage}
</div>
` : ''}
`;
// Tampilkan warning durasi
const warningDiv = document.getElementById('warningDurasi');
const warningMessageEl = document.getElementById('warningDurasiMessage');
if (showWarning) {
warningDiv.style.display = 'block';
warningMessageEl.textContent = warningMessage;
} else {
warningDiv.style.display = 'none';
}
}
// Character counter for alasan
// Character counter
document.getElementById('alasan').addEventListener('input', function() {
const current = this.value.length;
const counter = document.getElementById('charCount');
@ -316,8 +396,8 @@ function calculateDurasi() {
if (isOverLimit) {
e.preventDefault();
const warningDiv = document.querySelector('#durasiInfo div[style*="background: #fff3cd"]');
const message = warningDiv ? warningDiv.textContent.trim() : 'Izin ini melebihi batas 12 hari per tahun';
const warningMessageEl = document.getElementById('warningDurasiMessage');
const message = warningMessageEl ? warningMessageEl.textContent : 'Izin ini akan melebihi batas kuota per tahun';
document.getElementById('overLimitMessage').textContent = message;
document.getElementById('overLimitModal').style.display = 'flex';

View File

@ -9,6 +9,33 @@
<h2><i class="fas fa-home"></i> Data Kepulangan Santri</h2>
</div>
{{-- Info Periode Kuota --}}
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 12px; margin-bottom: 20px;">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; align-items: center;">
<div>
<h4 style="margin: 0 0 5px 0; opacity: 0.9;">📅 Periode Kuota</h4>
<p style="margin: 0; font-size: 1.1rem; font-weight: 600;">
{{ $settings->periode_mulai->format('d M Y') }} - {{ $settings->periode_akhir->format('d M Y') }}
</p>
</div>
<div>
<h4 style="margin: 0 0 5px 0; opacity: 0.9;">📊 Kuota Maksimal</h4>
<p style="margin: 0; font-size: 1.1rem; font-weight: 600;">{{ $settings->kuota_maksimal }} Hari / Tahun</p>
</div>
<div>
<h4 style="margin: 0 0 5px 0; opacity: 0.9;">🔄 Terakhir Reset</h4>
<p style="margin: 0; font-size: 1.1rem; font-weight: 600;">
{{ $settings->terakhir_reset ? $settings->terakhir_reset->format('d M Y') : 'Belum Pernah' }}
</p>
</div>
<div style="text-align: right;">
<a href="{{ route('admin.kepulangan.settings') }}" class="btn btn-light" style="background: white; color: #667eea; font-weight: 600;">
<i class="fas fa-cog"></i> Kelola Pengaturan
</a>
</div>
</div>
</div>
{{-- Dashboard Cards --}}
<div class="row-cards">
<div class="card card-info">
@ -27,9 +54,14 @@
<i class="fas fa-home card-icon"></i>
</div>
<div class="card card-danger">
<h3>Over Limit</h3>
<h3>Over Limit (>{{ $settings->kuota_maksimal }} Hari)</h3>
<div class="card-value">{{ $stats['over_limit_santri'] }}</div>
<i class="fas fa-exclamation-triangle card-icon"></i>
@if($stats['over_limit_santri'] > 0)
<a href="{{ route('admin.kepulangan.over-limit') }}" style="font-size: 0.85rem; color: #dc3545; text-decoration: underline; margin-top: 5px; display: block;">
Lihat Detail
</a>
@endif
</div>
</div>
@ -64,7 +96,7 @@
<input type="text"
name="search"
class="form-control"
placeholder="Nama, ID, atau alasan..."
placeholder="Cari nama, ID, atau alasan..."
value="{{ request('search') }}"
id="searchInput">
</div>
@ -122,6 +154,7 @@ class="form-control"
<th>Tanggal Pulang</th>
<th>Tanggal Kembali</th>
<th>Durasi</th>
<th>Total Kuota Terpakai</th>
<th>Alasan</th>
<th>Status</th>
<th class="text-center">Aksi</th>
@ -129,12 +162,16 @@ class="form-control"
</thead>
<tbody>
@forelse($kepulangan as $item)
<tr style="{{ isset($santriOverLimit[$item->id_santri]) ? 'background-color: #fff3cd;' : '' }}">
@php
$isOverLimit = isset($santriOverLimit[$item->id_santri]);
$totalHariTerpakai = $isOverLimit ? $santriOverLimit[$item->id_santri] : 0;
@endphp
<tr style="{{ $isOverLimit ? 'background-color: rgba(220, 53, 69, 0.1); border-left: 4px solid #dc3545;' : '' }}">
<td>
<strong>{{ $item->id_kepulangan }}</strong>
@if(isset($santriOverLimit[$item->id_santri]))
<span style="display: inline-block; background: #dc3545; color: white; padding: 2px 6px; border-radius: 4px; font-size: 0.75rem; margin-left: 5px;"
title="Over Limit: {{ $santriOverLimit[$item->id_santri] }} hari">
@if($isOverLimit)
<span style="display: inline-block; background: #dc3545; color: white; padding: 2px 6px; border-radius: 4px; font-size: 0.75rem; margin-left: 5px; animation: pulse 2s infinite;"
title="Over Limit: {{ $totalHariTerpakai }} hari">
<i class="fas fa-exclamation-triangle"></i>
</span>
@endif
@ -150,10 +187,31 @@ class="form-control"
<td>{{ $item->tanggal_pulang_formatted }}</td>
<td>{{ $item->tanggal_kembali_formatted }}</td>
<td>
<span style="display: inline-block; background: {{ $item->durasi_izin_calculated > 7 ? '#ffc107' : '#6c757d' }}; color: {{ $item->durasi_izin_calculated > 7 ? '#000' : '#fff' }}; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">
{{ $item->durasi_izin_calculated }} hari
<span style="display: inline-block; background: {{ $item->durasi_izin > 7 ? '#ffc107' : '#6c757d' }}; color: {{ $item->durasi_izin > 7 ? '#000' : '#fff' }}; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem; font-weight: 600;">
{{ $item->durasi_izin }} hari
</span>
</td>
<td>
@php
$kuotaSantri = \App\Models\Kepulangan::getSisaKuotaSantri($item->id_santri);
$badgeColor = $kuotaSantri['badge_color'];
$badgeColors = [
'success' => '#28a745',
'warning' => '#ffc107',
'danger' => '#dc3545'
];
$bgColor = $badgeColors[$badgeColor] ?? '#6c757d';
$textColor = $badgeColor == 'warning' ? '#000' : '#fff';
@endphp
<div style="text-align: center;">
<span style="display: inline-block; background: {{ $bgColor }}; color: {{ $textColor }}; padding: 4px 10px; border-radius: 4px; font-size: 0.85rem; font-weight: 600;">
{{ $kuotaSantri['total_terpakai'] }} / {{ $kuotaSantri['kuota_maksimal'] }} hari
</span>
<div style="margin-top: 5px; font-size: 0.75rem; color: #7F8C8D;">
Sisa: {{ $kuotaSantri['sisa_kuota'] }} hari ({{ $kuotaSantri['persentase'] }}%)
</div>
</div>
</td>
<td>
<span style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block;" title="{{ $item->alasan }}">
{{ $item->alasan }}
@ -169,9 +227,9 @@ class="form-control"
{{ $item->status }}
</span>
@if($item->is_aktif)
<br><small style="color: #28a745; font-weight: 600;">Sedang Izin</small>
<br><small style="color: #28a745; font-weight: 600;">🏠 Sedang Izin</small>
@elseif($item->is_terlambat)
<br><small style="color: #dc3545; font-weight: 600;">Terlambat</small>
<br><small style="color: #dc3545; font-weight: 600;">Terlambat</small>
@endif
</td>
<td class="text-center">
@ -227,7 +285,7 @@ class="btn btn-sm btn-danger"
</tr>
@empty
<tr>
<td colspan="8" style="text-align: center; padding: 40px;">
<td colspan="9" style="text-align: center; padding: 40px;">
<i class="fas fa-inbox" style="font-size: 3rem; color: #ccc; margin-bottom: 15px;"></i>
<p style="color: #7F8C8D;">Tidak ada data kepulangan ditemukan</p>
</td>
@ -251,7 +309,7 @@ class="btn btn-sm btn-danger"
@endif
</div>
{{-- Modal Approve --}}
{{-- Modals (sama seperti sebelumnya) --}}
<div class="modal fade" id="approveModal" tabindex="-1" style="display: none;">
<div class="modal-dialog">
<div class="modal-content" style="background: white; border-radius: 12px; padding: 20px;">
@ -276,7 +334,6 @@ class="btn btn-sm btn-danger"
</div>
</div>
{{-- Modal Reject --}}
<div class="modal fade" id="rejectModal" tabindex="-1" style="display: none;">
<div class="modal-dialog">
<div class="modal-content" style="background: white; border-radius: 12px; padding: 20px;">
@ -301,7 +358,6 @@ class="btn btn-sm btn-danger"
</div>
</div>
{{-- Modal Delete --}}
<div class="modal fade" id="deleteModal" tabindex="-1" style="display: none;">
<div class="modal-dialog">
<div class="modal-content" style="background: white; border-radius: 12px; padding: 20px;">
@ -324,12 +380,17 @@ class="btn btn-sm btn-danger"
.modal.fade { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
.modal-dialog { max-width: 500px; width: 90%; margin: auto; }
.modal-content { max-height: 90vh; overflow-y: auto; }
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
</style>
<script>
let currentActionId = null;
// Auto submit search with debounce
// Auto submit search dengan debounce
let searchTimeout;
document.getElementById('searchInput')?.addEventListener('input', function() {
clearTimeout(searchTimeout);

View File

@ -0,0 +1,361 @@
{{-- resources/views/admin/kepulangan/over-limit.blade.php --}}
@extends('layouts.app')
@section('title', 'Santri Over Limit Kuota')
@section('content')
<div class="page-header">
<h2><i class="fas fa-exclamation-triangle"></i> Santri Over Limit Kuota</h2>
</div>
{{-- Info Periode --}}
<div style="background: linear-gradient(135deg, #ff5252 0%, #f48fb1 100%); color: white; padding: 20px; border-radius: 12px; margin-bottom: 20px;">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; align-items: center;">
<div>
<h4 style="margin: 0 0 5px 0; opacity: 0.9;">⚠️ Total Santri Over Limit</h4>
<p style="margin: 0; font-size: 2rem; font-weight: 700;">{{ $santriList->count() }}</p>
</div>
<div>
<h4 style="margin: 0 0 5px 0; opacity: 0.9;">📅 Periode Kuota</h4>
<p style="margin: 0; font-size: 1.1rem; font-weight: 600;">
{{ $settings->periode_mulai->format('d M Y') }} - {{ $settings->periode_akhir->format('d M Y') }}
</p>
</div>
<div>
<h4 style="margin: 0 0 5px 0; opacity: 0.9;">📊 Kuota Maksimal</h4>
<p style="margin: 0; font-size: 1.1rem; font-weight: 600;">{{ $settings->kuota_maksimal }} Hari / Tahun</p>
</div>
<div style="text-align: right;">
<a href="{{ route('admin.kepulangan.index') }}" class="btn btn-light" style="background: white; color: #dc3545; font-weight: 600;">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</div>
</div>
{{-- Alert Info --}}
<div style="background: #fff3cd; padding: 15px; border-radius: 8px; margin-bottom: 20px; border-left: 4px solid #ffc107;">
<strong> Informasi:</strong>
<p style="margin: 10px 0 0 0;">
Berikut adalah daftar santri yang telah melebihi kuota maksimal <strong>{{ $settings->kuota_maksimal }} hari</strong> dalam periode ini.
Santri tetap bisa mengajukan izin, namun akan mendapat peringatan visual.
</p>
</div>
<div class="content-box">
@if($santriList->count() > 0)
<div style="overflow-x: auto;">
<table class="data-table">
<thead>
<tr>
<th>No</th>
<th>ID Santri</th>
<th>Nama Santri</th>
<th>Kelas</th>
<th>Total Hari Terpakai</th>
<th>Kuota Maksimal</th>
<th>Kelebihan</th>
<th>Persentase</th>
<th>Jumlah Izin</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach($santriList as $index => $santri)
@php
$kelebihan = $santri->total_hari_izin - $settings->kuota_maksimal;
@endphp
<tr style="background-color: rgba(220, 53, 69, 0.05);">
<td>{{ $index + 1 }}</td>
<td><strong>{{ $santri->id_santri }}</strong></td>
<td>
<div>
<strong>{{ $santri->nama_lengkap }}</strong><br>
<small style="color: #7F8C8D;">NIS: {{ $santri->nis ?? '-' }}</small>
</div>
</td>
<td>{{ $santri->kelas }}</td>
<td>
<span style="display: inline-block; background: #dc3545; color: white; padding: 6px 12px; border-radius: 6px; font-size: 1rem; font-weight: 700;">
{{ $santri->total_hari_izin }} hari
</span>
</td>
<td>
<span style="color: #7F8C8D;">{{ $settings->kuota_maksimal }} hari</span>
</td>
<td>
<span style="display: inline-block; background: #721c24; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; font-weight: 600;">
+{{ $kelebihan }} hari
</span>
</td>
<td>
<div style="display: flex; align-items: center; gap: 10px;">
<div style="flex: 1; height: 20px; background: #ffebee; border-radius: 10px; overflow: hidden; position: relative;">
<div style="height: 100%; width: {{ min(200, $santri->kuota_info['persentase']) }}%; background: linear-gradient(90deg, #dc3545, #c62828); transition: width 0.3s ease; display: flex; align-items: center; justify-content: center;">
<span style="font-size: 0.75rem; font-weight: 600; color: white; z-index: 1;">
{{ $santri->kuota_info['persentase'] }}%
</span>
</div>
</div>
</div>
</td>
<td>
<span style="display: inline-block; background: #6c757d; color: white; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">
{{ $santri->kepulangan->count() }} kali izin
</span>
</td>
<td>
<div style="display: flex; gap: 5px; flex-wrap: wrap;">
<button type="button"
class="btn btn-sm btn-primary"
onclick="showDetailSantri('{{ $santri->id_santri }}')"
title="Detail">
<i class="fas fa-eye"></i>
</button>
<button type="button"
class="btn btn-sm btn-warning"
onclick="resetKuotaSantri('{{ $santri->id_santri }}', '{{ $santri->nama_lengkap }}')"
title="Reset Kuota">
<i class="fas fa-sync-alt"></i>
</button>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
{{-- Summary Statistics --}}
<div style="margin-top: 30px; padding: 20px; background: #f8f9fa; border-radius: 8px;">
<h4 style="margin: 0 0 15px 0; color: #2C3E50;">📊 Ringkasan Statistik</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px;">
<div style="text-align: center; padding: 15px; background: white; border-radius: 8px; border: 2px solid #dc3545;">
<div style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Total Santri Over Limit</div>
<div style="font-size: 2rem; font-weight: 700; color: #dc3545;">{{ $santriList->count() }}</div>
</div>
<div style="text-align: center; padding: 15px; background: white; border-radius: 8px; border: 2px solid #ff9800;">
<div style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Rata-rata Kelebihan</div>
<div style="font-size: 2rem; font-weight: 700; color: #ff9800;">
{{ round($santriList->avg(function($s) use ($settings) { return $s->total_hari_izin - $settings->kuota_maksimal; }), 1) }} hari
</div>
</div>
<div style="text-align: center; padding: 15px; background: white; border-radius: 8px; border: 2px solid #f44336;">
<div style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Tertinggi</div>
<div style="font-size: 2rem; font-weight: 700; color: #f44336;">
{{ $santriList->max('total_hari_izin') }} hari
</div>
</div>
<div style="text-align: center; padding: 15px; background: white; border-radius: 8px; border: 2px solid #9c27b0;">
<div style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Total Kelebihan</div>
<div style="font-size: 2rem; font-weight: 700; color: #9c27b0;">
{{ $santriList->sum(function($s) use ($settings) { return $s->total_hari_izin - $settings->kuota_maksimal; }) }} hari
</div>
</div>
</div>
</div>
{{-- Action Buttons --}}
<div style="margin-top: 20px; display: flex; gap: 10px; flex-wrap: wrap;">
<button type="button" class="btn btn-danger" onclick="showResetSemuaOverLimit()">
<i class="fas fa-sync-alt"></i> Reset Semua Santri Over Limit
</button>
<a href="{{ route('admin.kepulangan.settings') }}" class="btn btn-primary">
<i class="fas fa-cog"></i> Pengaturan Kuota
</a>
</div>
@else
<div style="text-align: center; padding: 60px; color: #28a745;">
<i class="fas fa-check-circle" style="font-size: 4rem; margin-bottom: 20px; display: block;"></i>
<h3 style="margin: 0 0 10px 0;">Tidak Ada Santri Over Limit!</h3>
<p style="color: #7F8C8D;">Semua santri masih dalam batas kuota yang ditentukan.</p>
<a href="{{ route('admin.kepulangan.index') }}" class="btn btn-primary" style="margin-top: 20px;">
<i class="fas fa-arrow-left"></i> Kembali ke Kepulangan
</a>
</div>
@endif
</div>
{{-- Modal Detail Santri --}}
<div class="modal fade" id="detailSantriModal" tabindex="-1" style="display: none;">
<div class="modal-dialog modal-lg">
<div class="modal-content" style="background: white; border-radius: 12px; padding: 20px;">
<div style="margin-bottom: 20px;">
<h3 style="margin: 0; color: #2C3E50;">Detail Riwayat Izin Santri</h3>
</div>
<div id="detailSantriContent">
<div style="text-align: center; padding: 40px;">
<i class="fas fa-spinner fa-spin" style="font-size: 2rem;"></i>
<p style="margin-top: 10px;">Memuat data...</p>
</div>
</div>
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px;">
<button type="button" class="btn btn-secondary" onclick="closeModal('detailSantriModal')">Tutup</button>
</div>
</div>
</div>
</div>
{{-- Modal Reset Kuota --}}
<div class="modal fade" id="resetKuotaModal" tabindex="-1" style="display: none;">
<div class="modal-dialog">
<div class="modal-content" style="background: white; border-radius: 12px; padding: 20px;">
<form id="resetKuotaForm">
@csrf
<div style="margin-bottom: 20px;">
<h3 style="margin: 0; color: #2C3E50;">Reset Kuota Santri</h3>
</div>
<div style="padding: 15px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; margin-bottom: 15px;">
<p style="margin: 0; color: #856404;">
<i class="fas fa-exclamation-triangle"></i>
Anda akan mereset kuota untuk santri: <strong id="resetSantriName"></strong>
</p>
</div>
<div class="form-group">
<label>Catatan Reset (Opsional):</label>
<textarea name="catatan" class="form-control" rows="2" placeholder="Alasan reset kuota..."></textarea>
</div>
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px;">
<button type="button" class="btn btn-secondary" onclick="closeModal('resetKuotaModal')">Batal</button>
<button type="submit" class="btn btn-warning"><i class="fas fa-sync-alt"></i> Reset Kuota</button>
</div>
</form>
</div>
</div>
</div>
<style>
.modal.fade { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
.modal-dialog { max-width: 500px; width: 90%; margin: auto; }
.modal-dialog.modal-lg { max-width: 800px; }
.modal-content { max-height: 90vh; overflow-y: auto; }
</style>
<script>
let currentResetSantriId = null;
function showDetailSantri(idSantri) {
document.getElementById('detailSantriModal').style.display = 'flex';
// Load detail via AJAX
fetch(`/admin/api/kepulangan/santri/${idSantri}`)
.then(response => response.json())
.then(data => {
if (data.success) {
const santri = data.santri;
const kuota = data.penggunaan_izin;
document.getElementById('detailSantriContent').innerHTML = `
<div style="background: #f8f9fa; padding: 20px; border-radius: 8px; margin-bottom: 20px;">
<h4 style="margin: 0 0 15px 0;">${santri.nama_lengkap}</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 15px;">
<div>
<div style="font-size: 0.85rem; color: #7F8C8D;">ID Santri</div>
<div style="font-weight: 600;">${santri.id_santri}</div>
</div>
<div>
<div style="font-size: 0.85rem; color: #7F8C8D;">Kelas</div>
<div style="font-weight: 600;">${santri.kelas}</div>
</div>
<div>
<div style="font-size: 0.85rem; color: #7F8C8D;">Total Terpakai</div>
<div style="font-weight: 600; color: #dc3545;">${kuota.total_terpakai} hari</div>
</div>
<div>
<div style="font-size: 0.85rem; color: #7F8C8D;">Persentase</div>
<div style="font-weight: 600; color: #dc3545;">${kuota.persentase}%</div>
</div>
</div>
</div>
<div style="padding: 15px; background: #ffebee; border-radius: 8px;">
<p style="margin: 0; color: #c62828;">
<i class="fas fa-exclamation-triangle"></i>
<strong>Over Limit!</strong> Santri ini telah melebihi kuota maksimal ${kuota.kuota_maksimal} hari.
</p>
</div>
`;
} else {
document.getElementById('detailSantriContent').innerHTML = `
<div class="alert alert-danger">${data.message}</div>
`;
}
})
.catch(error => {
document.getElementById('detailSantriContent').innerHTML = `
<div class="alert alert-danger">Error: ${error.message}</div>
`;
});
}
function resetKuotaSantri(idSantri, namaSantri) {
currentResetSantriId = idSantri;
document.getElementById('resetSantriName').textContent = namaSantri;
document.getElementById('resetKuotaModal').style.display = 'flex';
}
document.getElementById('resetKuotaForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
const submitBtn = this.querySelector('button[type="submit"]');
const originalText = submitBtn.innerHTML;
submitBtn.disabled = true;
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Mereset...';
fetch(`/admin/kepulangan/reset/santri/${currentResetSantriId}`, {
method: 'POST',
body: formData,
headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' }
})
.then(response => response.json())
.then(data => {
if (data.success) {
closeModal('resetKuotaModal');
showAlert('success', data.message);
setTimeout(() => window.location.reload(), 1500);
} else {
showAlert('danger', data.message);
}
})
.catch(error => showAlert('danger', 'Error: ' + error.message))
.finally(() => {
submitBtn.disabled = false;
submitBtn.innerHTML = originalText;
});
});
function showResetSemuaOverLimit() {
if (confirm('Apakah Anda yakin ingin mereset kuota SEMUA santri yang over limit ({{ $santriList->count() }} santri)?')) {
window.location.href = '{{ route("admin.kepulangan.settings") }}#reset-section';
}
}
function closeModal(modalId) {
document.getElementById(modalId).style.display = 'none';
}
function showAlert(type, message) {
const alertDiv = document.createElement('div');
alertDiv.className = `alert alert-${type}`;
alertDiv.innerHTML = `<i class="fas fa-${type === 'success' ? 'check' : 'exclamation'}-circle"></i> ${message}`;
const pageHeader = document.querySelector('.page-header');
pageHeader.insertAdjacentElement('afterend', alertDiv);
setTimeout(() => alertDiv.remove(), 5000);
}
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
document.querySelectorAll('.modal.fade').forEach(modal => modal.style.display = 'none');
}
});
document.querySelectorAll('.modal.fade').forEach(modal => {
modal.addEventListener('click', function(e) {
if (e.target === this) {
closeModal(this.id);
}
});
});
</script>
@endsection

View File

@ -0,0 +1,424 @@
{{-- resources/views/admin/kepulangan/settings.blade.php --}}
@extends('layouts.app')
@section('title', 'Pengaturan Kuota Kepulangan')
@section('content')
<div class="page-header">
<h2><i class="fas fa-cog"></i> Pengaturan Kuota Kepulangan</h2>
</div>
{{-- Flash Messages --}}
@if(session('success'))
<div class="alert alert-success">
<i class="fas fa-check-circle"></i> {{ session('success') }}
</div>
@endif
@if(session('error'))
<div class="alert alert-danger">
<i class="fas fa-exclamation-circle"></i> {{ session('error') }}
</div>
@endif
{{-- Statistik Periode Saat Ini --}}
<div class="row-cards">
<div class="card card-info">
<h3>Total Santri Aktif</h3>
<div class="card-value">{{ $totalSantri }}</div>
<i class="fas fa-users card-icon"></i>
</div>
<div class="card card-warning">
<h3>Total Izin Periode Ini</h3>
<div class="card-value">{{ $totalIzinPeriodeIni }}</div>
<i class="fas fa-clipboard-list card-icon"></i>
</div>
<div class="card card-danger">
<h3>Santri Over Limit</h3>
<div class="card-value">{{ count($santriOverLimit) }}</div>
<i class="fas fa-exclamation-triangle card-icon"></i>
@if(count($santriOverLimit) > 0)
<a href="{{ route('admin.kepulangan.over-limit') }}" style="font-size: 0.85rem; color: #dc3545; text-decoration: underline; margin-top: 5px; display: block;">
Lihat Detail
</a>
@endif
</div>
<div class="card card-success">
<h3>Terakhir Reset</h3>
<div class="card-value" style="font-size: 1.2rem;">
{{ $settings->terakhir_reset ? $settings->terakhir_reset->format('d M Y') : 'Belum Pernah' }}
</div>
<i class="fas fa-history card-icon"></i>
@if($settings->reset_by)
<small style="display: block; margin-top: 5px;">oleh {{ $settings->reset_by }}</small>
@endif
</div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 20px;">
{{-- Settings Form --}}
<div class="content-box">
<h3 style="margin-top: 0; color: #2C3E50; border-bottom: 2px solid #6FBA9D; padding-bottom: 10px;">
<i class="fas fa-sliders-h"></i> Pengaturan Kuota
</h3>
<form action="{{ route('admin.kepulangan.settings.update') }}" method="POST">
@csrf
@method('PUT')
<div class="form-group">
<label for="kuota_maksimal">
<i class="fas fa-calculator"></i> Kuota Maksimal (Hari/Tahun)
<span style="color: #dc3545;">*</span>
</label>
<input type="number"
name="kuota_maksimal"
id="kuota_maksimal"
class="form-control"
value="{{ old('kuota_maksimal', $settings->kuota_maksimal) }}"
min="1"
max="365"
required>
<small style="color: #7F8C8D; display: block; margin-top: 5px;">
Maksimal hari izin yang diperbolehkan per tahun (1-365 hari)
</small>
</div>
<div class="form-group">
<label for="periode_mulai">
<i class="fas fa-calendar-alt"></i> Tanggal Mulai Periode
<span style="color: #dc3545;">*</span>
</label>
<input type="date"
name="periode_mulai"
id="periode_mulai"
class="form-control"
value="{{ old('periode_mulai', $settings->periode_mulai->format('Y-m-d')) }}"
required>
</div>
<div class="form-group">
<label for="periode_akhir">
<i class="fas fa-calendar-check"></i> Tanggal Akhir Periode
<span style="color: #dc3545;">*</span>
</label>
<input type="date"
name="periode_akhir"
id="periode_akhir"
class="form-control"
value="{{ old('periode_akhir', $settings->periode_akhir->format('Y-m-d')) }}"
required>
</div>
<div style="background: #E8F7F2; padding: 15px; border-radius: 8px; margin-bottom: 20px; border-left: 4px solid #6FBA9D;">
<strong> Informasi:</strong>
<ul style="margin: 10px 0 0 20px; padding: 0;">
<li>Periode ini menentukan rentang waktu perhitungan kuota</li>
<li>Perubahan periode akan mempengaruhi perhitungan kuota santri</li>
<li>Gunakan fitur reset jika ingin memulai periode baru</li>
</ul>
</div>
<button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i> Simpan Pengaturan
</button>
</form>
</div>
{{-- Reset Actions --}}
<div class="content-box">
<h3 style="margin-top: 0; color: #2C3E50; border-bottom: 2px solid #FF8B94; padding-bottom: 10px;">
<i class="fas fa-sync-alt"></i> Reset Kuota
</h3>
<div style="background: #fff3cd; padding: 15px; border-radius: 8px; margin-bottom: 20px; border-left: 4px solid #ffc107;">
<strong>⚠️ PERHATIAN:</strong>
<p style="margin: 10px 0 0 0;">
Reset kuota akan mengubah status semua izin yang "Disetujui" dalam periode saat ini menjadi "Selesai".
Ini akan mereset perhitungan kuota untuk memulai periode baru.
</p>
</div>
{{-- Reset Semua Santri --}}
<div style="background: #ffebee; padding: 20px; border-radius: 8px; border: 2px solid #dc3545; margin-bottom: 20px;">
<h4 style="margin: 0 0 10px 0; color: #dc3545;">
<i class="fas fa-users"></i> Reset Kuota Semua Santri
</h4>
<p style="color: #7F8C8D; font-size: 0.9rem; margin-bottom: 15px;">
Mereset kuota untuk {{ $totalSantri }} santri aktif. Gunakan di awal tahun ajaran atau periode baru.
</p>
<form id="resetSemuaForm">
@csrf
<div class="form-group">
<label for="catatan_reset_semua">Catatan Reset (Opsional):</label>
<textarea name="catatan"
id="catatan_reset_semua"
class="form-control"
rows="2"
placeholder="Contoh: Reset untuk tahun ajaran 2025/2026"></textarea>
</div>
<div style="margin-bottom: 15px;">
<label style="display: flex; align-items: center; cursor: pointer;">
<input type="checkbox" name="konfirmasi" id="konfirmasi_reset_semua" required style="margin-right: 10px; width: 18px; height: 18px;">
<span>Saya memahami bahwa tindakan ini akan mereset kuota untuk <strong>SEMUA santri</strong></span>
</label>
</div>
<button type="button" onclick="confirmResetSemua()" class="btn btn-danger" style="width: 100%;">
<i class="fas fa-sync-alt"></i> Reset Kuota Semua Santri
</button>
</form>
</div>
{{-- Info Tambahan --}}
<div style="background: #e3f2fd; padding: 15px; border-radius: 8px; border-left: 4px solid #2196f3;">
<strong>💡 Tips:</strong>
<ul style="margin: 10px 0 0 20px; padding: 0; font-size: 0.9rem;">
<li>Reset individual dapat dilakukan dari halaman detail santri</li>
<li>Reset massal sebaiknya dilakukan di akhir periode</li>
<li>Semua aktivitas reset tercatat dalam log history</li>
<li>Data izin lama tetap tersimpan untuk arsip</li>
</ul>
</div>
</div>
</div>
{{-- History Reset Logs --}}
<div class="content-box" style="margin-top: 20px;">
<h3 style="margin-top: 0; color: #2C3E50; border-bottom: 2px solid #6FBA9D; padding-bottom: 10px;">
<i class="fas fa-history"></i> History Reset Kuota
</h3>
@if($resetLogs->count() > 0)
<div style="overflow-x: auto;">
<table class="data-table">
<thead>
<tr>
<th>Tanggal Reset</th>
<th>Jenis Reset</th>
<th>Santri</th>
<th>Total Hari Direset</th>
<th>Periode</th>
<th>Kuota Tahunan</th>
<th>Reset By</th>
<th>Catatan</th>
</tr>
</thead>
<tbody>
@foreach($resetLogs as $log)
<tr>
<td>{{ \Carbon\Carbon::parse($log->created_at)->format('d M Y H:i') }}</td>
<td>
<span style="display: inline-block; padding: 4px 10px; border-radius: 4px; font-size: 0.85rem; font-weight: 600;
{{ $log->jenis_reset == 'massal' ? 'background: #dc3545; color: white;' : 'background: #ffc107; color: #000;' }}">
{{ $log->jenis_reset == 'massal' ? '👥 Massal' : '👤 Individual' }}
</span>
</td>
<td>
@if($log->id_santri)
<strong>{{ $log->nama_lengkap ?? $log->id_santri }}</strong><br>
<small style="color: #7F8C8D;">{{ $log->id_santri }}</small>
@else
<span style="color: #7F8C8D;">Semua Santri</span>
@endif
</td>
<td>
<span style="display: inline-block; background: #6c757d; color: white; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem; font-weight: 600;">
{{ $log->total_hari_sebelum_reset }} hari
</span>
</td>
<td>
<small>
{{ \Carbon\Carbon::parse($log->periode_mulai)->format('d M Y') }} -
{{ \Carbon\Carbon::parse($log->periode_akhir)->format('d M Y') }}
</small>
</td>
<td>{{ $log->kuota_tahunan }} hari</td>
<td>{{ $log->reset_by }}</td>
<td>
<span style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block;"
title="{{ $log->catatan }}">
{{ $log->catatan ?? '-' }}
</span>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@else
<div style="text-align: center; padding: 40px; color: #7F8C8D;">
<i class="fas fa-inbox" style="font-size: 3rem; margin-bottom: 15px; display: block;"></i>
<p>Belum ada history reset kuota</p>
</div>
@endif
</div>
{{-- Modal Konfirmasi Reset Semua --}}
<div class="modal fade" id="confirmResetSemuaModal" tabindex="-1" style="display: none;">
<div class="modal-dialog">
<div class="modal-content" style="background: white; border-radius: 12px; padding: 20px;">
<div style="margin-bottom: 20px;">
<h3 style="margin: 0; color: #dc3545;">
<i class="fas fa-exclamation-triangle"></i> KONFIRMASI RESET MASSAL
</h3>
</div>
<div style="padding: 20px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; margin-bottom: 15px;">
<h4 style="margin: 0 0 10px 0; color: #856404;">⚠️ PERINGATAN PENTING!</h4>
<p style="margin: 0; color: #856404;">
Anda akan mereset kuota untuk <strong>{{ $totalSantri }} santri aktif</strong>.
Semua izin yang berstatus "Disetujui" akan diubah menjadi "Selesai".
</p>
</div>
<div style="background: #e3f2fd; padding: 15px; border-radius: 6px; margin-bottom: 20px;">
<p style="margin: 0; font-size: 0.9rem;">
<strong>Yang akan terjadi:</strong>
</p>
<ul style="margin: 10px 0 0 20px; padding: 0; font-size: 0.9rem;">
<li>Semua perhitungan kuota akan direset ke 0</li>
<li>Status izin "Disetujui" "Selesai"</li>
<li>Data arsip tetap tersimpan</li>
<li>Aktivitas tercatat dalam log</li>
</ul>
</div>
<p style="margin: 15px 0; font-weight: 600; color: #2C3E50;">
Ketik "<span style="color: #dc3545;">RESET SEMUA</span>" untuk melanjutkan:
</p>
<input type="text"
id="confirmationText"
class="form-control"
placeholder="Ketik: RESET SEMUA"
style="margin-bottom: 20px;">
<div style="display: flex; gap: 10px; justify-content: flex-end;">
<button type="button" class="btn btn-secondary" onclick="closeModal('confirmResetSemuaModal')">Batal</button>
<button type="button" class="btn btn-danger" id="executeResetSemuaBtn" disabled>
<i class="fas fa-sync-alt"></i> Ya, Reset Semua Kuota
</button>
</div>
</div>
</div>
</div>
<style>
.modal.fade { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
.modal-dialog { max-width: 600px; width: 90%; margin: auto; }
.modal-content { max-height: 90vh; overflow-y: auto; }
@media (max-width: 768px) {
div[style*="grid-template-columns: 1fr 1fr"] {
grid-template-columns: 1fr !important;
}
}
</style>
<script>
// Validate confirmation text
document.getElementById('confirmationText')?.addEventListener('input', function() {
const btn = document.getElementById('executeResetSemuaBtn');
if (this.value.trim().toUpperCase() === 'RESET SEMUA') {
btn.disabled = false;
btn.style.opacity = '1';
} else {
btn.disabled = true;
btn.style.opacity = '0.5';
}
});
// Show confirmation modal
function confirmResetSemua() {
const checkbox = document.getElementById('konfirmasi_reset_semua');
if (!checkbox.checked) {
alert('Anda harus mencentang konfirmasi terlebih dahulu!');
return;
}
document.getElementById('confirmResetSemuaModal').style.display = 'flex';
}
// Execute reset semua
document.getElementById('executeResetSemuaBtn')?.addEventListener('click', function() {
const btn = this;
const originalText = btn.innerHTML;
btn.disabled = true;
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses Reset...';
const formData = new FormData(document.getElementById('resetSemuaForm'));
fetch('{{ route("admin.kepulangan.reset.semua") }}', {
method: 'POST',
body: formData,
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
closeModal('confirmResetSemuaModal');
showAlert('success', data.message);
setTimeout(() => window.location.reload(), 2000);
} else {
showAlert('danger', data.message || 'Terjadi kesalahan saat reset');
}
})
.catch(error => {
showAlert('danger', 'Error: ' + error.message);
})
.finally(() => {
btn.disabled = false;
btn.innerHTML = originalText;
});
});
// Helper functions
function closeModal(modalId) {
document.getElementById(modalId).style.display = 'none';
// Reset confirmation text
const confirmInput = document.getElementById('confirmationText');
if (confirmInput) confirmInput.value = '';
}
function showAlert(type, message) {
const alertDiv = document.createElement('div');
alertDiv.className = `alert alert-${type}`;
alertDiv.innerHTML = `<i class="fas fa-${type === 'success' ? 'check' : 'exclamation'}-circle"></i> ${message}`;
const pageHeader = document.querySelector('.page-header');
pageHeader.insertAdjacentElement('afterend', alertDiv);
setTimeout(() => alertDiv.remove(), 5000);
}
// Close modals on ESC
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
document.querySelectorAll('.modal.fade').forEach(modal => {
modal.style.display = 'none';
});
}
});
// Close modal on outside click
document.querySelectorAll('.modal.fade').forEach(modal => {
modal.addEventListener('click', function(e) {
if (e.target === this) {
closeModal(this.id);
}
});
});
// Auto-set periode akhir when periode mulai changes
document.getElementById('periode_mulai')?.addEventListener('change', function() {
const mulai = new Date(this.value);
const akhir = new Date(mulai);
akhir.setFullYear(akhir.getFullYear() + 1);
akhir.setDate(akhir.getDate() - 1);
document.getElementById('periode_akhir').value = akhir.toISOString().split('T')[0];
});
</script>
@endsection

View File

@ -27,7 +27,7 @@
<div class="content-box">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; flex-wrap: wrap; gap: 10px;">
<h3 style="margin: 0;">Informasi Kepulangan</h3>
<span style="display: inline-block; padding: 6px 14px; border-radius: 6px; font-size: 1rem; font-weight: 600;
<span style="display: inline-block; padding: 8px 16px; border-radius: 6px; font-size: 1rem; font-weight: 600;
@if($kepulangan->status == 'Menunggu') background: #ffc107; color: #000;
@elseif($kepulangan->status == 'Disetujui') background: #28a745; color: white;
@elseif($kepulangan->status == 'Ditolak') background: #dc3545; color: white;
@ -40,7 +40,7 @@
<table class="detail-table">
<tr>
<th>ID Kepulangan:</th>
<td>{{ $kepulangan->id_kepulangan }}</td>
<td><strong>{{ $kepulangan->id_kepulangan }}</strong></td>
</tr>
<tr>
<th>Tanggal Pengajuan:</th>
@ -57,8 +57,8 @@
<tr>
<th>Durasi Izin:</th>
<td>
<span style="display: inline-block; background: {{ $kepulangan->durasi_izin_calculated > 7 ? '#ffc107' : '#007bff' }}; color: {{ $kepulangan->durasi_izin_calculated > 7 ? '#000' : 'white' }}; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;">
{{ $kepulangan->durasi_izin_calculated }} hari
<span style="display: inline-block; background: {{ $kepulangan->durasi_izin > 7 ? '#ffc107' : '#007bff' }}; color: {{ $kepulangan->durasi_izin > 7 ? '#000' : 'white' }}; padding: 6px 12px; border-radius: 6px; font-size: 1rem; font-weight: 600;">
{{ $kepulangan->durasi_izin }} hari
</span>
</td>
</tr>
@ -66,13 +66,21 @@
<th>Status Kepulangan:</th>
<td>
@if($kepulangan->is_aktif)
<span style="display: inline-block; background: #28a745; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.85rem;">Sedang Izin</span>
<span style="display: inline-block; background: #28a745; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;">
🏠 Sedang Izin
</span>
@elseif($kepulangan->is_terlambat)
<span style="display: inline-block; background: #dc3545; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.85rem;">Terlambat Kembali</span>
<span style="display: inline-block; background: #dc3545; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;">
Terlambat Kembali
</span>
@elseif($kepulangan->status == 'Selesai')
<span style="display: inline-block; background: #6c757d; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.85rem;">Sudah Selesai</span>
<span style="display: inline-block; background: #6c757d; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;">
Sudah Selesai
</span>
@else
<span style="display: inline-block; background: #81C6E8; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.85rem;">Belum Dimulai</span>
<span style="display: inline-block; background: #81C6E8; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;">
📅 Belum Dimulai
</span>
@endif
</td>
</tr>
@ -82,11 +90,11 @@
</tr>
@if($kepulangan->approved_by)
<tr>
<th>Disetujui Oleh:</th>
<th>Diproses Oleh:</th>
<td>{{ $kepulangan->approved_by }}</td>
</tr>
<tr>
<th>Tanggal Persetujuan:</th>
<th>Tanggal Diproses:</th>
<td>{{ $kepulangan->approved_at_formatted }}</td>
</tr>
@endif
@ -163,56 +171,83 @@ class="btn btn-primary" target="_blank">
</table>
</div>
{{-- Statistik Penggunaan Izin --}}
{{-- Statistik Kuota Santri --}}
<div class="content-box" style="margin-bottom: 20px;">
<h4 style="margin-top: 0; color: #2C3E50; border-bottom: 2px solid #6FBA9D; padding-bottom: 10px;">
<i class="fas fa-chart-bar"></i> Statistik Izin {{ $kepulangan->tanggal_pulang->year }}
<i class="fas fa-chart-pie"></i> Kuota Izin Periode Ini
</h4>
<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; text-align: center;">
<div style="background: linear-gradient(135deg, {{ $kuotaSantri['badge_color'] == 'danger' ? '#ff5252 0%, #f48fb1 100%' : ($kuotaSantri['badge_color'] == 'warning' ? '#ffd54f 0%, #ffb74d 100%' : '#81c784 0%, #66bb6a 100%') }}); padding: 20px; border-radius: 12px; text-align: center; color: white; margin-bottom: 15px;">
<div style="font-size: 0.9rem; opacity: 0.9; margin-bottom: 5px;">Total Terpakai</div>
<div style="font-size: 3rem; font-weight: 700; line-height: 1;">{{ $kuotaSantri['total_terpakai'] }}</div>
<div style="font-size: 1rem; opacity: 0.9;">dari {{ $kuotaSantri['kuota_maksimal'] }} hari</div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 15px;">
<div>
<h3 style="margin: 0; color: #007bff;">{{ $detailIzin['total_hari'] }}</h3>
<small style="color: #7F8C8D;">Total Hari</small>
<div style="text-align: center; padding: 15px; background: #f8f9fa; border-radius: 8px;">
<div style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Sisa Kuota</div>
<div style="font-size: 1.8rem; font-weight: 700; color: {{ $kuotaSantri['badge_color'] == 'danger' ? '#dc3545' : ($kuotaSantri['badge_color'] == 'warning' ? '#ff9800' : '#28a745') }};">
{{ $kuotaSantri['sisa_kuota'] }}
</div>
<div>
<h3 style="margin: 0; color: #81C6E8;">{{ $detailIzin['total_izin'] }}</h3>
<small style="color: #7F8C8D;">Total Izin</small>
<div style="font-size: 0.8rem; color: #7F8C8D;">hari</div>
</div>
<div style="text-align: center; padding: 15px; background: #f8f9fa; border-radius: 8px;">
<div style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Persentase</div>
<div style="font-size: 1.8rem; font-weight: 700; color: {{ $kuotaSantri['badge_color'] == 'danger' ? '#dc3545' : ($kuotaSantri['badge_color'] == 'warning' ? '#ff9800' : '#28a745') }};">
{{ $kuotaSantri['persentase'] }}%
</div>
<hr style="margin: 15px 0; border: none; border-top: 1px solid #dee2e6;">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
<div>
<h4 style="margin: 0; color: {{ $detailIzin['sisa_kuota'] <= 3 ? '#dc3545' : '#28a745' }};">
{{ $detailIzin['sisa_kuota'] }}
</h4>
<small style="color: #7F8C8D;">Sisa Kuota</small>
</div>
<div>
@if($detailIzin['over_limit'])
<span style="display: inline-block; background: #dc3545; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.85rem;">Over Limit</span>
@else
<span style="display: inline-block; background: #28a745; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.85rem;">Normal</span>
@endif
</div>
<div style="font-size: 0.8rem; color: #7F8C8D;">terpakai</div>
</div>
</div>
{{-- Progress Bar --}}
<div style="margin-top: 15px;">
<div style="margin-bottom: 15px;">
<label style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px; display: block;">
Penggunaan Kuota ({{ $detailIzin['total_hari'] }}/12 hari)
Penggunaan Kuota ({{ $kuotaSantri['total_terpakai'] }}/{{ $kuotaSantri['kuota_maksimal'] }} hari)
</label>
<div style="width: 100%; height: 10px; background: #E0F0EC; border-radius: 5px; overflow: hidden;">
<div style="width: {{ min(100, ($detailIzin['total_hari'] / 12) * 100) }}%; height: 100%; background: {{ $detailIzin['over_limit'] ? '#dc3545' : ($detailIzin['total_hari'] > 8 ? '#ffc107' : '#28a745') }}; transition: width 0.3s ease;"></div>
</div>
<div style="width: 100%; height: 15px; background: #E0F0EC; border-radius: 8px; overflow: hidden;">
<div style="width: {{ min(100, $kuotaSantri['persentase']) }}%; height: 100%; background: {{ $kuotaSantri['badge_color'] == 'danger' ? '#dc3545' : ($kuotaSantri['badge_color'] == 'warning' ? '#ffc107' : '#28a745') }}; transition: width 0.3s ease;"></div>
</div>
</div>
{{-- Riwayat Izin --}}
@if($kuotaSantri['status'] == 'melebihi')
<div style="padding: 12px; background: #ffebee; border: 1px solid #ffcdd2; border-radius: 6px; color: #c62828; font-size: 0.9rem;">
<i class="fas fa-exclamation-triangle"></i>
<strong>OVER LIMIT!</strong> Santri ini telah melebihi kuota maksimal.
</div>
@elseif($kuotaSantri['status'] == 'hampir_habis')
<div style="padding: 12px; background: #fff3e0; border: 1px solid #ffe0b2; border-radius: 6px; color: #e65100; font-size: 0.9rem;">
<i class="fas fa-exclamation-circle"></i>
<strong>Hampir Habis!</strong> Kuota hampir mencapai batas maksimal.
</div>
@else
<div style="padding: 12px; background: #e8f5e9; border: 1px solid #c8e6c9; border-radius: 6px; color: #2e7d32; font-size: 0.9rem;">
<i class="fas fa-check-circle"></i>
<strong>Aman!</strong> Kuota masih dalam batas normal.
</div>
@endif
<div style="margin-top: 15px; padding: 10px; background: #f8f9fa; border-radius: 6px; font-size: 0.85rem; color: #7F8C8D;">
<strong>Periode:</strong><br>
{{ $kuotaSantri['periode_mulai'] }} - {{ $kuotaSantri['periode_akhir'] }}
</div>
{{-- Reset Individual Button --}}
@if($kuotaSantri['total_terpakai'] > 0)
<button type="button"
class="btn btn-warning"
style="width: 100%; margin-top: 15px;"
onclick="resetKuotaSantri('{{ $kepulangan->id_santri }}', '{{ $kepulangan->santri->nama_lengkap }}')">
<i class="fas fa-sync-alt"></i> Reset Kuota Santri Ini
</button>
@endif
</div>
{{-- Riwayat Izin Periode Ini --}}
@if(count($detailIzin['details']) > 0)
<div class="content-box">
<h4 style="margin-top: 0; color: #2C3E50; border-bottom: 2px solid #6FBA9D; padding-bottom: 10px;">
<i class="fas fa-history"></i> Riwayat Izin {{ $kepulangan->tanggal_pulang->year }}
<i class="fas fa-history"></i> Riwayat Izin Periode Ini
</h4>
<div style="position: relative; padding-left: 20px;">
@foreach($detailIzin['details'] as $detail)
@ -222,14 +257,19 @@ class="btn btn-primary" target="_blank">
<i class="fas fa-star" style="color: #ffc107;"></i>
</div>
@endif
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 5px;">
<strong style="color: #2C3E50;">{{ $detail['id'] }}</strong>
<div style="font-size: 0.85rem; color: #7F8C8D; margin-top: 3px;">{{ $detail['tanggal'] }}</div>
<div style="font-size: 0.9rem; margin-top: 5px;">
<span style="display: inline-block; background: #6c757d; color: white; padding: 2px 6px; border-radius: 3px; font-size: 0.8rem;">
<span style="display: inline-block; background: {{ $detail['status'] == 'Disetujui' ? '#28a745' : '#6c757d' }}; color: white; padding: 2px 6px; border-radius: 3px; font-size: 0.75rem;">
{{ $detail['status'] }}
</span>
</div>
<div style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">{{ $detail['tanggal'] }}</div>
<div style="font-size: 0.9rem; margin-bottom: 5px;">
<span style="display: inline-block; background: #007bff; color: white; padding: 2px 8px; border-radius: 3px; font-size: 0.8rem; font-weight: 600;">
{{ $detail['durasi'] }} hari
</span>
</div>
<div style="font-size: 0.85rem; color: #7F8C8D; margin-top: 5px;">
<div style="font-size: 0.85rem; color: #7F8C8D;">
{{ \Illuminate\Support\Str::limit($detail['alasan'], 50) }}
</div>
</div>
@ -244,31 +284,28 @@ class="btn btn-primary" target="_blank">
@if($history->count() > 0)
<div class="content-box" style="margin-top: 20px;">
<h4 style="margin-top: 0; color: #2C3E50; border-bottom: 2px solid #6FBA9D; padding-bottom: 10px;">
<i class="fas fa-list"></i> Riwayat Kepulangan Lainnya
<i class="fas fa-list"></i> Riwayat Kepulangan Lainnya (5 Terakhir)
</h4>
<div style="overflow-x: auto;">
<table class="data-table">
<thead>
<tr>
<th>ID</th>
<th>Tanggal</th>
<th>Tanggal Pulang</th>
<th>Durasi</th>
<th>Status</th>
<th>Alasan</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach($history as $item)
<tr>
<td>
<a href="{{ route('admin.kepulangan.show', $item->id_kepulangan) }}" style="color: #6FBA9D; text-decoration: none; font-weight: 600;">
{{ $item->id_kepulangan }}
</a>
</td>
<td><strong>{{ $item->id_kepulangan }}</strong></td>
<td>{{ $item->tanggal_pulang_formatted }}</td>
<td>
<span style="display: inline-block; background: #6c757d; color: white; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">
{{ $item->durasi_izin_calculated }} hari
{{ $item->durasi_izin }} hari
</span>
</td>
<td>
@ -282,6 +319,12 @@ class="btn btn-primary" target="_blank">
</span>
</td>
<td>{{ \Illuminate\Support\Str::limit($item->alasan, 30) }}</td>
<td>
<a href="{{ route('admin.kepulangan.show', $item->id_kepulangan) }}"
class="btn btn-sm btn-primary">
<i class="fas fa-eye"></i>
</a>
</td>
</tr>
@endforeach
</tbody>
@ -290,7 +333,7 @@ class="btn btn-primary" target="_blank">
</div>
@endif
{{-- Modals (sama seperti di index) --}}
{{-- Modals --}}
<div class="modal fade" id="approveModal" tabindex="-1" style="display: none;">
<div class="modal-dialog">
<div class="modal-content" style="background: white; border-radius: 12px; padding: 20px;">
@ -333,6 +376,33 @@ class="btn btn-primary" target="_blank">
</div>
</div>
<div class="modal fade" id="resetKuotaModal" tabindex="-1" style="display: none;">
<div class="modal-dialog">
<div class="modal-content" style="background: white; border-radius: 12px; padding: 20px;">
<form id="resetKuotaForm">
@csrf
<div style="margin-bottom: 20px;">
<h3 style="margin: 0; color: #2C3E50;">Reset Kuota Santri</h3>
</div>
<div style="padding: 15px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; margin-bottom: 15px;">
<p style="margin: 0; color: #856404;">
<i class="fas fa-exclamation-triangle"></i>
Anda akan mereset kuota untuk santri: <strong id="resetSantriName"></strong>
</p>
</div>
<div class="form-group">
<label>Catatan Reset (Opsional):</label>
<textarea name="catatan" class="form-control" rows="2" placeholder="Alasan reset kuota..."></textarea>
</div>
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px;">
<button type="button" class="btn btn-secondary" onclick="closeModal('resetKuotaModal')">Batal</button>
<button type="submit" class="btn btn-warning"><i class="fas fa-sync-alt"></i> Reset Kuota</button>
</div>
</form>
</div>
</div>
</div>
<style>
.modal.fade { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
.modal-dialog { max-width: 500px; width: 90%; margin: auto; }
@ -343,6 +413,8 @@ class="btn btn-primary" target="_blank">
</style>
<script>
let currentResetSantriId = null;
function approveKepulangan() {
document.getElementById('approveModal').style.display = 'flex';
}
@ -432,6 +504,43 @@ function completeKepulangan() {
}
}
function resetKuotaSantri(idSantri, namaSantri) {
currentResetSantriId = idSantri;
document.getElementById('resetSantriName').textContent = namaSantri;
document.getElementById('resetKuotaModal').style.display = 'flex';
}
document.getElementById('resetKuotaForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
const submitBtn = this.querySelector('button[type="submit"]');
const originalText = submitBtn.innerHTML;
submitBtn.disabled = true;
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Mereset...';
fetch(`/admin/kepulangan/reset/santri/${currentResetSantriId}`, {
method: 'POST',
body: formData,
headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' }
})
.then(response => response.json())
.then(data => {
if (data.success) {
closeModal('resetKuotaModal');
showAlert('success', data.message);
setTimeout(() => window.location.reload(), 1500);
} else {
showAlert('danger', data.message);
}
})
.catch(error => showAlert('danger', 'Error: ' + error.message))
.finally(() => {
submitBtn.disabled = false;
submitBtn.innerHTML = originalText;
});
});
function closeModal(modalId) {
document.getElementById(modalId).style.display = 'none';
}
@ -450,5 +559,13 @@ function showAlert(type, message) {
document.querySelectorAll('.modal.fade').forEach(modal => modal.style.display = 'none');
}
});
document.querySelectorAll('.modal.fade').forEach(modal => {
modal.addEventListener('click', function(e) {
if (e.target === this) {
closeModal(this.id);
}
});
});
</script>
@endsection

View File

@ -12,98 +12,126 @@
line-height: 1.6;
margin: 0;
padding: 20mm;
color: #000;
}
.header {
text-align: center;
margin-bottom: 30px;
border-bottom: 2px solid #000;
border-bottom: 3px solid #000;
padding-bottom: 15px;
}
.logo {
width: 80px;
height: 80px;
margin: 0 auto 10px;
display: block;
}
.header h1 {
font-size: 18pt;
font-weight: bold;
margin: 5px 0;
text-transform: uppercase;
}
.header h2 {
font-size: 16pt;
margin: 5px 0;
font-weight: normal;
}
.header p {
font-size: 10pt;
margin: 2px 0;
}
.title {
text-align: center;
margin: 30px 0;
margin: 30px 0 20px 0;
font-size: 14pt;
font-weight: bold;
text-decoration: underline;
text-transform: uppercase;
}
.nomor {
text-align: center;
margin-bottom: 30px;
font-size: 12pt;
font-size: 11pt;
}
.content {
margin-bottom: 30px;
text-align: justify;
}
.content p {
margin-bottom: 15px;
}
.data-santri {
margin: 20px 0;
padding-left: 50px;
margin: 20px 0 20px 50px;
}
.data-row {
display: table;
width: 100%;
margin-bottom: 5px;
margin-bottom: 8px;
}
.data-label {
display: table-cell;
width: 150px;
width: 180px;
vertical-align: top;
}
.data-separator {
display: table-cell;
width: 20px;
vertical-align: top;
}
.data-value {
display: table-cell;
vertical-align: top;
font-weight: bold;
}
.signature-section {
margin-top: 50px;
margin-top: 60px;
}
.signature-row {
display: table;
width: 100%;
}
.signature-left, .signature-right {
display: table-cell;
width: 50%;
text-align: center;
vertical-align: top;
padding: 0 20px;
}
.signature-space {
height: 80px;
margin: 20px 0 10px;
}
.signature-name {
font-weight: bold;
border-bottom: 1px solid #000;
display: inline-block;
min-width: 150px;
min-width: 180px;
padding-bottom: 2px;
}
.footer {
position: fixed;
bottom: 10mm;
bottom: 15mm;
left: 20mm;
right: 20mm;
font-size: 8pt;
@ -112,23 +140,81 @@
padding-top: 10px;
color: #666;
}
.watermark {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(-45deg);
font-size: 72pt;
color: rgba(0, 0, 0, 0.05);
font-size: 100pt;
color: rgba(0, 0, 0, 0.03);
z-index: -1;
font-weight: bold;
white-space: nowrap;
}
.status-approved {
color: green;
color: #28a745;
font-weight: bold;
}
.catatan-box {
margin: 20px 0;
padding: 15px;
background-color: #f8f9fa;
border: 2px solid #dee2e6;
border-radius: 5px;
}
.info-box {
margin: 20px 0;
padding: 12px;
background-color: #fff3cd;
border-left: 4px solid #ffc107;
}
ul {
margin: 10px 0;
padding-left: 30px;
}
ul li {
margin-bottom: 5px;
}
.page-break {
page-break-after: always;
}
@media print {
body { margin: 0; }
.footer { position: fixed; }
body {
margin: 0;
}
.footer {
position: fixed;
}
.page-break {
page-break-after: always;
}
}
.tracking-table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
.tracking-table th,
.tracking-table td {
border: 1px solid #000;
padding: 8px;
text-align: left;
font-size: 10pt;
}
.tracking-table th {
background-color: #f0f0f0;
font-weight: bold;
}
</style>
</head>
@ -138,10 +224,13 @@
{{-- Header --}}
<div class="header">
{{-- Logo (jika ada) --}}
{{-- <img src="{{ asset('images/logo-pesantren.png') }}" alt="Logo" class="logo"> --}}
<h1>Pondok Pesantren Al-Hikmah</h1>
<h2>Yayasan Pendidikan Islam</h2>
<p>Jl. Raya Pesantren No. 123, Jakarta Selatan</p>
<p>Telp: (021) 123456 | Email: info@alhikmah.ac.id</p>
<p>Jl. Raya Pesantren No. 123, Jakarta Selatan 12345</p>
<p>Telp: (021) 123456 | Email: info@alhikmah.ac.id | Website: www.alhikmah.ac.id</p>
</div>
{{-- Title --}}
@ -151,7 +240,7 @@
{{-- Nomor Surat --}}
<div class="nomor">
Nomor: {{ $kepulangan->id_kepulangan }}/IZIN/{{ $kepulangan->tanggal_pulang->format('m') }}/{{ $kepulangan->tanggal_pulang->year }}
Nomor: {{ $kepulangan->id_kepulangan }}/IZIN-PULANG/PP-AH/{{ $kepulangan->tanggal_pulang->format('m') }}/{{ $kepulangan->tanggal_pulang->year }}
</div>
{{-- Content --}}
@ -160,12 +249,12 @@
<div class="data-santri">
<div class="data-row">
<div class="data-label">Nama</div>
<div class="data-label">Nama Lengkap</div>
<div class="data-separator">:</div>
<div class="data-value">{{ $santri->nama_lengkap }}</div>
</div>
<div class="data-row">
<div class="data-label">NIS</div>
<div class="data-label">Nomor Induk Santri (NIS)</div>
<div class="data-separator">:</div>
<div class="data-value">{{ $santri->nis ?? '-' }}</div>
</div>
@ -187,27 +276,32 @@
<div class="data-row">
<div class="data-label">Alamat</div>
<div class="data-separator">:</div>
<div class="data-value">{{ $santri->alamat_santri ?? $santri->daerah_asal ?? '-' }}</div>
<div class="data-value">{{ $santri->alamat_santri ?? $santri->daerah_asal ?? 'Tidak tercatat' }}</div>
</div>
</div>
<p>Adalah benar-benar santri aktif di Pondok Pesantren Al-Hikmah dan telah mendapat izin untuk pulang ke rumah dengan keterangan sebagai berikut:</p>
<div class="data-santri">
<div class="data-row">
<div class="data-label">Tanggal Pengajuan Izin</div>
<div class="data-separator">:</div>
<div class="data-value">{{ $kepulangan->tanggal_izin->format('d F Y') }}</div>
</div>
<div class="data-row">
<div class="data-label">Tanggal Pulang</div>
<div class="data-separator">:</div>
<div class="data-value">{{ $kepulangan->tanggal_pulang->format('d F Y') }}</div>
</div>
<div class="data-row">
<div class="data-label">Tanggal Kembali</div>
<div class="data-label">Tanggal Wajib Kembali</div>
<div class="data-separator">:</div>
<div class="data-value">{{ $kepulangan->tanggal_kembali->format('d F Y') }}</div>
</div>
<div class="data-row">
<div class="data-label">Durasi Izin</div>
<div class="data-separator">:</div>
<div class="data-value">{{ $kepulangan->durasi_izin_calculated }} hari</div>
<div class="data-value">{{ $kepulangan->durasi_izin }} hari</div>
</div>
<div class="data-row">
<div class="data-label">Alasan Kepulangan</div>
@ -228,16 +322,19 @@
@endif
</div>
<p>Demikian surat izin ini dibuat untuk dapat digunakan sebagaimana mestinya. Santri yang bersangkutan <strong>WAJIB</strong> kembali pada tanggal yang telah ditentukan.</p>
<p>Demikian surat izin ini dibuat dengan sebenarnya untuk dapat digunakan sebagaimana mestinya. Santri yang bersangkutan <strong>WAJIB</strong> kembali ke pesantren pada tanggal yang telah ditentukan di atas.</p>
<p><strong>Catatan Penting:</strong></p>
<ul style="margin-left: 30px;">
<div class="info-box">
<p style="margin: 0;"><strong>⚠️ KETENTUAN PENTING:</strong></p>
<ul style="margin: 10px 0 0 0;">
<li>Santri wajib kembali sesuai tanggal yang tertera dalam surat ini</li>
<li>Apabila terlambat kembali tanpa pemberitahuan, akan dikenakan sanksi sesuai peraturan pesantren</li>
<li>Apabila terlambat kembali tanpa pemberitahuan yang sah, akan dikenakan sanksi sesuai peraturan pesantren</li>
<li>Surat ini harus dibawa dan ditunjukkan kepada petugas jaga saat keluar dan masuk pesantren</li>
<li>Orang tua/wali santri bertanggung jawab penuh selama santri berada di rumah</li>
<li>Orang tua/wali santri bertanggung jawab penuh atas keselamatan santri selama berada di rumah</li>
<li>Harap menghubungi pihak pesantren jika terjadi kondisi darurat yang mengharuskan perpanjangan waktu kepulangan</li>
</ul>
</div>
</div>
{{-- Signature Section --}}
<div class="signature-section">
@ -245,14 +342,13 @@
<div class="signature-left">
<p>Mengetahui,<br>Wali Santri</p>
<div class="signature-space"></div>
<div class="signature-name">{{ $santri->nama_orang_tua ?? '........................' }}</div>
<div class="signature-name">{{ $santri->nama_orang_tua ?? '( ........................... )' }}</div>
</div>
<div class="signature-right">
<p>Jakarta, {{ $tanggalCetak }}</p>
<p>Pengurus Pondok Pesantren</p>
<p>Pengurus Pondok Pesantren<br>Bidang Kesiswaan</p>
<div class="signature-space"></div>
<div class="signature-name">{{ $kepulangan->approved_by ?? 'Admin' }}</div>
<p style="margin-top: 5px; font-size: 10pt;">Bidang Kesiswaan</p>
</div>
</div>
</div>
@ -263,7 +359,137 @@
Dicetak pada: {{ $tanggalCetak }} |
ID: {{ $kepulangan->id_kepulangan }} |
Status: {{ $kepulangan->status }} |
Surat ini sah tanpa tanda tangan basah
Surat ini sah tanpa tanda tangan basah (Digital Signature)
</p>
</div>
{{-- PAGE BREAK untuk halaman kedua (Lembar Tracking) --}}
<div class="page-break"></div>
{{-- Halaman 2: Lembar Tracking & Arsip --}}
<div class="header">
<h1>Pondok Pesantren Al-Hikmah</h1>
<h2>Lembar Tracking Kepulangan Santri</h2>
<p style="font-style: italic; color: #666;">(Lembar Arsip Internal - Tidak untuk diserahkan kepada santri)</p>
</div>
<div class="title" style="font-size: 12pt;">
Tracking ID: {{ $kepulangan->id_kepulangan }}
</div>
<div class="content">
<div class="catatan-box">
<p style="margin: 0 0 10px 0;"><strong>📋 Data Kepulangan</strong></p>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="padding: 5px; width: 180px;"><strong>ID Kepulangan</strong></td>
<td style="padding: 5px;">: {{ $kepulangan->id_kepulangan }}</td>
</tr>
<tr>
<td style="padding: 5px;"><strong>Nama Santri</strong></td>
<td style="padding: 5px;">: {{ $santri->nama_lengkap }} ({{ $santri->id_santri }})</td>
</tr>
<tr>
<td style="padding: 5px;"><strong>Kelas</strong></td>
<td style="padding: 5px;">: {{ $santri->kelas }}</td>
</tr>
<tr>
<td style="padding: 5px;"><strong>No. HP Wali</strong></td>
<td style="padding: 5px;">: {{ $santri->no_hp_wali ?? '-' }}</td>
</tr>
<tr>
<td style="padding: 5px;"><strong>Periode Izin</strong></td>
<td style="padding: 5px;">: {{ $kepulangan->tanggal_pulang_formatted }} s/d {{ $kepulangan->tanggal_kembali_formatted }} ({{ $kepulangan->durasi_izin }} hari)</td>
</tr>
<tr>
<td style="padding: 5px; vertical-align: top;"><strong>Alasan</strong></td>
<td style="padding: 5px;">: {{ $kepulangan->alasan }}</td>
</tr>
<tr>
<td style="padding: 5px;"><strong>Disetujui Oleh</strong></td>
<td style="padding: 5px;">: {{ $kepulangan->approved_by }} - {{ $kepulangan->approved_at_formatted }}</td>
</tr>
</table>
</div>
<h3 style="margin: 30px 0 15px 0; font-size: 12pt;">📊 Tracking Kepulangan</h3>
<table class="tracking-table">
<thead>
<tr>
<th style="width: 25%;">Status</th>
<th style="width: 25%;">Tanggal/Waktu</th>
<th style="width: 30%;">Keterangan</th>
<th style="width: 20%;">Petugas</th>
</tr>
</thead>
<tbody>
<tr>
<td>Diajukan</td>
<td>{{ $kepulangan->tanggal_izin_formatted }}</td>
<td>Pengajuan izin kepulangan</td>
<td>Santri</td>
</tr>
<tr>
<td>{{ $kepulangan->status }}</td>
<td>{{ $kepulangan->approved_at_formatted }}</td>
<td>{{ $kepulangan->status == 'Disetujui' ? 'Izin disetujui dan surat dicetak' : 'Status diubah' }}</td>
<td>{{ $kepulangan->approved_by }}</td>
</tr>
<tr>
<td>Keluar Pesantren</td>
<td>_______________________</td>
<td>Santri keluar dari pesantren</td>
<td>_____________________</td>
</tr>
<tr>
<td>Kembali ke Pesantren</td>
<td>_______________________</td>
<td>Santri kembali ke pesantren</td>
<td>_____________________</td>
</tr>
</tbody>
</table>
<div style="margin-top: 30px; padding: 15px; background-color: #f8f9fa; border: 1px solid #dee2e6; border-radius: 5px;">
<p style="margin: 0 0 10px 0;"><strong>📞 Kontak Darurat:</strong></p>
<table style="width: 100%; font-size: 10pt;">
<tr>
<td style="padding: 3px;"><strong>Pesantren (Kantor)</strong></td>
<td style="padding: 3px;">: (021) 123456</td>
<td style="padding: 3px;"><strong>Keamanan 24 Jam</strong></td>
<td style="padding: 3px;">: (021) 123457</td>
</tr>
<tr>
<td style="padding: 3px;"><strong>Pengurus Putra</strong></td>
<td style="padding: 3px;">: 0812-3456-7890</td>
<td style="padding: 3px;"><strong>Pengurus Putri</strong></td>
<td style="padding: 3px;">: 0812-3456-7891</td>
</tr>
<tr>
<td style="padding: 3px;"><strong>Wali Santri</strong></td>
<td style="padding: 3px;">: {{ $santri->no_hp_wali ?? 'Belum ada data' }}</td>
<td style="padding: 3px;"><strong>Email Pesantren</strong></td>
<td style="padding: 3px;">: info@alhikmah.ac.id</td>
</tr>
</table>
</div>
<div style="margin-top: 20px; padding: 12px; background-color: #fff3cd; border-left: 4px solid #ffc107;">
<p style="margin: 0; font-size: 10pt;"><strong>⚠️ Catatan untuk Petugas:</strong></p>
<ul style="margin: 5px 0 0 20px; font-size: 10pt;">
<li>Pastikan santri membawa surat izin asli saat keluar</li>
<li>Catat waktu keluar dan kembali dengan akurat</li>
<li>Hubungi wali santri jika santri terlambat kembali lebih dari 2 jam</li>
<li>Simpan lembar tracking ini untuk arsip administrasi</li>
</ul>
</div>
</div>
<div class="footer">
<p>
Lembar Arsip Internal | Dicetak: {{ $tanggalCetak }} |
ID: {{ $kepulangan->id_kepulangan }} |
Halaman 2 dari 2
</p>
</div>
</body>

View File

@ -4,17 +4,10 @@
@section('content')
<div class="page-header">
<h2><i class="fas fa-user-edit"></i> Edit Santri</h2>
<h2><i class="fas fa-user-edit"></i> Edit Data Santri</h2>
</div>
<div class="content-box">
<div style="background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); padding: 15px 20px; border-radius: 8px; margin-bottom: 25px; border-left: 4px solid #6FBA9D;">
<p style="margin: 0; color: #2C5F4F;">
<i class="fas fa-info-circle"></i>
<strong>Sedang mengedit data:</strong> {{ $santri->nama_lengkap }} ({{ $santri->id_santri }})
</p>
</div>
@if ($errors->any())
<div class="alert alert-danger">
<strong><i class="fas fa-exclamation-triangle"></i> Terdapat kesalahan:</strong>
@ -26,6 +19,32 @@
</div>
@endif
@include('admin.santri.form', ['santri' => $santri])
{{-- Info Box: Data Santri yang Sedang Diedit --}}
<div style="background: linear-gradient(135deg, #E3F2FD 0%, #D1E9F9 100%); padding: 20px; border-radius: 8px; border-left: 4px solid #81C6E8; margin-bottom: 25px;">
<div style="display: flex; align-items: center; gap: 15px;">
@if($santri->foto)
<img src="{{ asset('storage/' . $santri->foto) }}"
alt="Foto {{ $santri->nama_lengkap }}"
style="width: 60px; height: 60px; border-radius: 50%; object-fit: cover; border: 3px solid #81C6E8;"
loading="lazy">
@else
<div style="width: 60px; height: 60px; border-radius: 50%; background: #81C6E8; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 1.5rem;">
{{ strtoupper(substr($santri->nama_lengkap, 0, 1)) }}
</div>
@endif
<div>
<p style="margin: 0; color: #2D4A7C; font-size: 0.9rem;">
<i class="fas fa-info-circle"></i>
<strong>Sedang mengedit data:</strong>
</p>
<p style="margin: 5px 0 0 0; color: #2D4A7C; font-weight: 600; font-size: 1.1rem;">
{{ $santri->nama_lengkap }} ({{ $santri->id_santri }})
</p>
</div>
</div>
</div>
@include('admin.santri.form')
</div>
@endsection

View File

@ -2,7 +2,7 @@
$isEdit = isset($santri);
@endphp
<form action="{{ $isEdit ? route('admin.santri.update', $santri) : route('admin.santri.store') }}" method="POST" class="data-form">
<form action="{{ $isEdit ? route('admin.santri.update', $santri) : route('admin.santri.store') }}" method="POST" class="data-form" enctype="multipart/form-data">
@csrf
@if ($isEdit)
@method('PUT')
@ -14,6 +14,50 @@
<small class="form-text text-muted">{{ $isEdit ? 'ID Santri tidak dapat diubah.' : 'ID akan otomatis di-generate (Contoh: ' . ($nextIdSantri ?? 'S001') . ')' }}</small>
</div>
{{-- FOTO SANTRI (BARU) --}}
<div class="form-group">
<label for="foto">
<i class="fas fa-image form-icon"></i>
Foto Santri
</label>
@if($isEdit && $santri->foto)
<div style="margin-bottom: 10px;">
<img src="{{ asset('storage/' . $santri->foto) }}"
alt="Foto {{ $santri->nama_lengkap }}"
style="max-width: 150px; max-height: 150px; border-radius: 8px; border: 2px solid var(--primary-light); object-fit: cover;"
loading="lazy">
<p style="margin-top: 5px; font-size: 0.85rem; color: var(--text-light);">
<i class="fas fa-info-circle"></i> Foto saat ini
</p>
</div>
@endif
<input type="file"
id="foto"
name="foto"
class="form-control @error('foto') is-invalid @enderror"
accept="image/jpeg,image/jpg,image/png"
onchange="previewImage(event)">
@error('foto')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
<small class="form-text text-muted">
<i class="fas fa-info-circle"></i>
Format: JPG, JPEG, atau PNG. Maksimal 2 MB.
@if($isEdit)
Upload foto baru akan mengganti foto lama.
@endif
</small>
{{-- Preview Image --}}
<img id="preview"
style="display: none; margin-top: 10px; max-width: 150px; max-height: 150px; border-radius: 8px; border: 2px solid var(--primary-color); object-fit: cover;"
loading="lazy">
</div>
<div class="form-group">
<label for="nis">NIS (Nomor Induk Santri)</label>
<input type="text" id="nis" name="nis" value="{{ old('nis', $isEdit ? $santri->nis : '') }}" class="form-control @error('nis') is-invalid @enderror" placeholder="Masukkan NIS">
@ -94,3 +138,39 @@
</a>
</div>
</form>
{{-- JavaScript untuk Preview Image --}}
<script>
function previewImage(event) {
const preview = document.getElementById('preview');
const file = event.target.files[0];
if (file) {
// Validasi ukuran file (2 MB = 2097152 bytes)
if (file.size > 2097152) {
alert('Ukuran file terlalu besar! Maksimal 2 MB.');
event.target.value = '';
preview.style.display = 'none';
return;
}
// Validasi tipe file
const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png'];
if (!allowedTypes.includes(file.type)) {
alert('Format file tidak valid! Hanya JPG, JPEG, dan PNG yang diperbolehkan.');
event.target.value = '';
preview.style.display = 'none';
return;
}
const reader = new FileReader();
reader.onload = function(e) {
preview.src = e.target.result;
preview.style.display = 'block';
};
reader.readAsDataURL(file);
} else {
preview.style.display = 'none';
}
}
</script>

View File

@ -55,6 +55,7 @@
<thead>
<tr>
<th>No</th>
<th>Foto</th>
<th>ID Santri</th>
<th>NIS</th>
<th>Nama Lengkap</th>
@ -67,7 +68,20 @@
<tbody>
@forelse ($santris as $index => $santri)
<tr>
<td>{{ $index + 1 }}</td>
<td>{{ $santris->firstItem() + $index }}</td>
<td>
{{-- Foto Santri --}}
@if($santri->foto)
<img src="{{ asset('storage/' . $santri->foto) }}"
alt="Foto {{ $santri->nama_lengkap }}"
style="width: 40px; height: 40px; border-radius: 50%; object-fit: cover; border: 2px solid var(--primary-color);"
loading="lazy">
@else
<div class="santri-avatar-initial" style="width: 40px; height: 40px; border-radius: 50%; background: var(--primary-color); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 0.9rem;">
{{ strtoupper(substr($santri->nama_lengkap, 0, 1)) }}
</div>
@endif
</td>
<td><strong>{{ $santri->id_santri }}</strong></td>
<td>{{ $santri->nis ?? '-' }}</td>
<td>{{ $santri->nama_lengkap }}</td>
@ -104,7 +118,7 @@
</tr>
@empty
<tr>
<td colspan="8" class="text-center" style="padding: 40px;">
<td colspan="9" class="text-center" style="padding: 40px;">
<i class="fas fa-inbox" style="font-size: 3rem; color: #ccc; margin-bottom: 15px; display: block;"></i>
@if(request('search') || request('status') || request('kelas'))
<strong>Data tidak ditemukan.</strong><br>
@ -123,15 +137,15 @@
<div style="margin-top: 20px; padding-top: 20px; border-top: 1px solid #E8F7F2;">
<p style="color: #7F8C8D; font-size: 0.9rem;">
<i class="fas fa-info-circle"></i>
Menampilkan <strong>{{ $santris->count() }}</strong> data santri
Menampilkan <strong>{{ $santris->count() }}</strong> dari <strong>{{ $santris->total() }}</strong> data santri
@if(request('search') || request('status') || request('kelas'))
dari hasil pencarian/filter
(hasil pencarian/filter)
@endif
</p>
</div>
@endif
<!-- Pagination (jika menggunakan paginate) -->
<!-- Pagination -->
@if(method_exists($santris, 'links'))
<div style="margin-top: 20px;">
{{ $santris->links() }}

View File

@ -9,6 +9,19 @@
<div class="content-box">
<div class="detail-header">
<div style="display: flex; align-items: center; gap: 20px;">
{{-- Foto Santri --}}
@if($santri->foto)
<img src="{{ asset('storage/' . $santri->foto) }}"
alt="Foto {{ $santri->nama_lengkap }}"
style="width: 80px; height: 80px; border-radius: 50%; object-fit: cover; border: 3px solid var(--primary-color); flex-shrink: 0;"
loading="lazy">
@else
<div style="width: 80px; height: 80px; border-radius: 50%; background: var(--primary-color); display: flex; align-items: center; justify-content: center; color: white; font-size: 2rem; font-weight: bold; flex-shrink: 0;">
{{ strtoupper(substr($santri->nama_lengkap, 0, 1)) }}
</div>
@endif
<div>
<h3>{{ $santri->nama_lengkap }}</h3>
<p style="color: #7F8C8D; margin: 5px 0 0 0;">
@ -18,6 +31,7 @@
@endif
</p>
</div>
</div>
<div style="display: flex; gap: 10px;">
<a href="{{ route('admin.santri.edit', $santri) }}" class="btn btn-warning">
<i class="fas fa-edit"></i> Edit

View File

@ -85,7 +85,7 @@
color: white;
text-decoration: none;
border-radius: 50px;
margin-top: 30px;
margin: 10px;
transition: all 0.3s ease;
font-weight: 600;
}
@ -131,23 +131,20 @@
Maaf, terjadi kesalahan pada server. Tim kami sudah diberitahu dan sedang menangani masalah ini.
</p>
<?php if(isset($error) && config('app.debug')): ?>
@if(isset($error) && config('app.debug'))
<div class="error-message">
<strong><i class="fas fa-bug"></i> Detail Error (Debug Mode):</strong>
<p><?php echo e($error); ?></p>
<?php if(isset($message)): ?>
<p style="margin-top: 10px;"><strong>Message:</strong> <?php echo e($message); ?></p>
<?php endif; ?>
<p>{{ $error }}</p>
</div>
<?php endif; ?>
@endif
<a href="<?php echo e(url()->previous()); ?>" class="btn">
<a href="javascript:history.back()" class="btn">
<i class="fas fa-arrow-left"></i> Kembali
</a>
<a href="<?php echo e(route('santri.dashboard')); ?>" class="btn" style="margin-left: 10px;">
<a href="{{ route('santri.dashboard') }}" class="btn">
<i class="fas fa-home"></i> Dashboard
</a>
</div>
</body>
</html><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/errors/500.blade.php ENDPATH**/ ?>
</html>

View File

@ -16,11 +16,11 @@
</a>
</li>
{{-- Riwayat Absensi --}}
{{-- Kegiatan & Absensi --}}
<li>
<a href="#" class="{{ Request::routeIs('santri.absensi.*') ? 'active' : '' }}">
<a href="{{ route('santri.kegiatan.index') }}" class="{{ Request::routeIs('santri.kegiatan.*') ? 'active' : '' }}">
<i class="fas fa-calendar-check"></i>
<span>Riwayat Absensi</span>
<span>Kegiatan & Absensi</span>
</a>
</li>

View File

@ -7,6 +7,11 @@
<h2><i class="fas fa-tachometer-alt"></i> Dashboard Progres</h2>
<p style="margin: 5px 0 0 0; color: var(--text-light);">
Selamat datang, <strong>{{ $data['nama_santri'] }}</strong> - Kelas {{ $data['kelas'] }}
@if($semesterAktif)
<span class="badge badge-success" style="margin-left: 10px;">
<i class="fas fa-calendar-alt"></i> {{ $semesterAktif->nama_semester }}
</span>
@endif
</p>
</div>
@ -33,65 +38,57 @@
{{-- Cards Statistik --}}
<div class="row-cards">
{{-- Card Progres Al-Qur'an --}}
<div class="card card-info">
<div class="card card-success">
<h3><i class="fas fa-book-quran"></i> Progres Al-Qur'an</h3>
<div class="card-value">{{ $data['progres_quran'] }}%</div>
<div class="card-icon"><i class="fas fa-book-quran"></i></div>
<div style="margin-top: 10px;">
<div class="progress-bar">
<div class="progress-fill" style="width: {{ $data['progres_quran'] }}%; background: var(--info-color);"></div>
<div class="progress-fill" style="width: {{ $data['progres_quran'] }}%; background: var(--success-color);"></div>
</div>
</div>
</div>
{{-- Card Progres Hadist --}}
<div class="card card-primary">
<div class="card card-info">
<h3><i class="fas fa-scroll"></i> Progres Hadist</h3>
<div class="card-value">{{ $data['progres_hadist'] }}%</div>
<div class="card-icon"><i class="fas fa-scroll"></i></div>
<div style="margin-top: 10px;">
<div class="progress-bar">
<div class="progress-fill" style="width: {{ $data['progres_hadist'] }}%; background: var(--primary-color);"></div>
<div class="progress-fill" style="width: {{ $data['progres_hadist'] }}%; background: var(--info-color);"></div>
</div>
</div>
</div>
{{-- Card Progres Materi Tambahan --}}
<div class="card card-warning">
<h3><i class="fas fa-book"></i> Materi Tambahan</h3>
<div class="card-value">{{ $data['progres_materi_tambahan'] }}%</div>
<div class="card-icon"><i class="fas fa-book"></i></div>
<div style="margin-top: 10px;">
<div class="progress-bar">
<div class="progress-fill" style="width: {{ $data['progres_materi_tambahan'] }}%; background: var(--warning-color);"></div>
</div>
</div>
</div>
{{-- Card Saldo Uang Saku --}}
<div class="card card-success">
<div class="card card-primary">
<h3><i class="fas fa-wallet"></i> Saldo Uang Saku</h3>
<div class="card-value">{{ 'Rp ' . number_format($data['saldo_uang_saku'], 0, ',', '.') }}</div>
<div class="card-value-small">{{ 'Rp ' . number_format($data['saldo_uang_saku'], 0, ',', '.') }}</div>
<div class="card-icon"><i class="fas fa-wallet"></i></div>
<div style="margin-top: 10px;">
<a href="{{ route('santri.uang-saku.index') }}" class="btn btn-sm btn-success" style="width: 100%; justify-content: center;">
<a href="{{ route('santri.uang-saku.index') }}" class="btn btn-sm btn-primary" style="width: 100%; justify-content: center;">
<i class="fas fa-eye"></i> Lihat Riwayat
</a>
</div>
</div>
{{-- Card Poin Pelanggaran --}}
<div class="card card-{{ $data['poin_pelanggaran'] > 0 ? 'danger' : 'warning' }}">
<h3><i class="fas fa-exclamation-triangle"></i> Total Poin Pelanggaran</h3>
<div class="card-value">{{ $data['poin_pelanggaran'] }}</div>
<div class="card-icon"><i class="fas fa-exclamation-triangle"></i></div>
@if($data['poin_pelanggaran'] > 0)
<div style="margin-top: 10px;">
<a href="{{ route('santri.pelanggaran.index') }}" class="btn btn-sm btn-danger" style="width: 100%; justify-content: center;">
<i class="fas fa-eye"></i> Lihat Riwayat
</a>
</div>
@else
<div style="margin-top: 10px;">
<span class="badge badge-success">
<i class="fas fa-check-circle"></i> Tidak ada pelanggaran
</span>
</div>
@endif
</div>
</div>
{{-- BERITA TERBARU --}}
@if($beritaTerbaru->isNotEmpty())
<div class="content-box" style="margin-top: 20px;">
<div class="content-box" style="margin-top: 25px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
<h3 style="margin: 0; color: var(--primary-color);">
<i class="fas fa-newspaper"></i> Berita Terbaru (7 Hari Terakhir)
@ -125,63 +122,164 @@
</div>
@endif
{{-- Quick Links --}}
<div class="content-box" style="margin-top: 20px;">
<h3 style="margin: 0 0 20px 0; color: var(--primary-color);">
<i class="fas fa-bolt"></i> Akses Cepat
{{-- Card Poin Pelanggaran --}}
<div class="content-box" style="margin-top: 25px;">
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;">
<div style="flex: 1;">
<h3 style="margin: 0 0 5px 0; color: var(--{{ $data['poin_pelanggaran'] > 0 ? 'danger' : 'success' }}-color);">
<i class="fas fa-exclamation-triangle"></i> Total Poin Pelanggaran: <strong>{{ $data['poin_pelanggaran'] }}</strong>
</h3>
@if($data['poin_pelanggaran'] > 0)
<p style="margin: 0; color: var(--text-light); font-size: 0.9rem;">
Anda memiliki {{ $data['poin_pelanggaran'] }} poin pelanggaran. Jaga kedisiplinan!
</p>
@else
<p style="margin: 0; color: var(--text-light); font-size: 0.9rem;">
<i class="fas fa-check-circle" style="color: var(--success-color);"></i> Alhamdulillah, tidak ada catatan pelanggaran.
</p>
@endif
</div>
<a href="{{ route('santri.pelanggaran.index') }}" class="btn btn-{{ $data['poin_pelanggaran'] > 0 ? 'danger' : 'success' }}">
<i class="fas fa-eye"></i> Lihat Riwayat
</a>
</div>
</div>
{{-- SECTION GRAFIK (2 Grafik Berdampingan: Pie & Line) --}}
@if($capaianPerMateri->count() > 0 || array_sum($distribusiStatus) > 0)
<div class="content-box" style="margin-top: 25px;">
<h3 style="margin-bottom: 20px; color: var(--primary-dark);">
<i class="fas fa-chart-line"></i> Visualisasi Capaian Pembelajaran
</h3>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
{{-- Profil Saya --}}
<a href="{{ route('santri.profil.index') }}" class="btn btn-primary hover-lift" style="padding: 15px; text-align: center;">
<i class="fas fa-user" style="font-size: 1.5rem; display: block; margin-bottom: 8px;"></i>
<span style="font-size: 0.9rem;">Profil Saya</span>
</a>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 25px; margin-bottom: 30px;">
{{-- Berita --}}
<a href="{{ route('santri.berita.index') }}" class="btn btn-info hover-lift" style="padding: 15px; text-align: center;">
<i class="fas fa-newspaper" style="font-size: 1.5rem; display: block; margin-bottom: 8px;"></i>
<span style="font-size: 0.9rem;">Berita</span>
</a>
{{-- GRAFIK 1: Distribusi Status (PIE CHART) --}}
@if(array_sum($distribusiStatus) > 0)
<div style="background: white; padding: 25px; border-radius: var(--border-radius); box-shadow: var(--shadow-md); border: 2px solid var(--primary-light);">
<h4 style="margin: 0 0 20px 0; font-size: 1.1rem; color: var(--text-color); text-align: center; font-weight: 700;">
<i class="fas fa-chart-pie"></i> Distribusi Status Pembelajaran
</h4>
{{-- Uang Saku --}}
<a href="{{ route('santri.uang-saku.index') }}" class="btn btn-success hover-lift" style="padding: 15px; text-align: center;">
<i class="fas fa-wallet" style="font-size: 1.5rem; display: block; margin-bottom: 8px;"></i>
<span style="font-size: 0.9rem;">Uang Saku</span>
</a>
{{-- Layout: Grafik di Kiri, Legend di Kanan --}}
<div style="display: flex; align-items: center; gap: 25px; flex-wrap: wrap;">
{{-- Grafik Pie --}}
<div style="flex: 1; min-width: 250px; max-width: 350px;">
<canvas id="chartPieStatus" style="max-height: 300px;"></canvas>
</div>
{{-- Pelanggaran --}}
<a href="{{ route('santri.pelanggaran.index') }}" class="btn btn-danger hover-lift" style="padding: 15px; text-align: center;">
<i class="fas fa-exclamation-circle" style="font-size: 1.5rem; display: block; margin-bottom: 8px;"></i>
<span style="font-size: 0.9rem;">Pelanggaran</span>
</a>
{{-- Kesehatan (dengan badge dinamis) --}}
<a href="{{ route('santri.kesehatan.index') }}" class="btn btn-{{ isset($statusKesehatan) && $statusKesehatan ? 'danger' : 'info' }} hover-lift" style="padding: 15px; text-align: center; position: relative;">
<i class="fas fa-heartbeat" style="font-size: 1.5rem; display: block; margin-bottom: 8px;"></i>
<span style="font-size: 0.9rem;">Kesehatan</span>
@if(isset($statusKesehatan) && $statusKesehatan)
<span class="badge badge-light" style="display: block; margin-top: 5px; font-size: 0.75rem; background: rgba(255,255,255,0.9); color: var(--danger-color);">
<i class="fas fa-exclamation-circle"></i> Sedang Dirawat
</span>
@endif
</a>
{{-- Kepulangan (dengan badge dinamis) --}}
<a href="{{ route('santri.kepulangan.index') }}" class="btn btn-{{ isset($kepulanganAktif) && $kepulanganAktif ? 'info' : 'primary' }} hover-lift" style="padding: 15px; text-align: center; position: relative;">
<i class="fas fa-home" style="font-size: 1.5rem; display: block; margin-bottom: 8px;"></i>
<span style="font-size: 0.9rem;">Kepulangan</span>
@if(isset($kepulanganAktif) && $kepulanganAktif)
<span class="badge badge-light" style="display: block; margin-top: 5px; font-size: 0.75rem; background: rgba(255,255,255,0.9); color: var(--info-color);">
<i class="fas fa-home"></i> Sedang Pulang
</span>
@endif
</a>
{{-- Legend/Keterangan di Samping --}}
<div style="flex: 1; min-width: 200px; display: flex; flex-direction: column; gap: 12px;">
<div style="display: flex; align-items: center; gap: 10px;">
<div style="width: 24px; height: 24px; background: linear-gradient(135deg, #6FBA9D 0%, #5EA98C 100%); border-radius: 4px; flex-shrink: 0;"></div>
<div style="flex: 1;">
<div style="font-weight: 700; color: var(--text-color); font-size: 0.9rem;">Selesai (100%)</div>
<div style="font-size: 0.75rem; color: var(--text-light);">{{ $distribusiStatus['selesai'] }} materi</div>
</div>
</div>
{{-- Tips Hari Ini --}}
<div class="content-box" style="margin-top: 20px; background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); border: 2px solid var(--primary-color);">
<div style="display: flex; align-items: center; gap: 10px;">
<div style="width: 24px; height: 24px; background: linear-gradient(135deg, #81C6E8 0%, #6AB0D4 100%); border-radius: 4px; flex-shrink: 0;"></div>
<div style="flex: 1;">
<div style="font-weight: 700; color: var(--text-color); font-size: 0.9rem;">Hampir Selesai (75-99%)</div>
<div style="font-size: 0.75rem; color: var(--text-light);">{{ $distribusiStatus['hampir_selesai'] }} materi</div>
</div>
</div>
<div style="display: flex; align-items: center; gap: 10px;">
<div style="width: 24px; height: 24px; background: linear-gradient(135deg, #FFD56B 0%, #E6B85C 100%); border-radius: 4px; flex-shrink: 0;"></div>
<div style="flex: 1;">
<div style="font-weight: 700; color: var(--text-color); font-size: 0.9rem;">Sedang Berjalan (25-74%)</div>
<div style="font-size: 0.75rem; color: var(--text-light);">{{ $distribusiStatus['sedang_berjalan'] }} materi</div>
</div>
</div>
<div style="display: flex; align-items: center; gap: 10px;">
<div style="width: 24px; height: 24px; background: linear-gradient(135deg, #FF8B94 0%, #E77580 100%); border-radius: 4px; flex-shrink: 0;"></div>
<div style="flex: 1;">
<div style="font-weight: 700; color: var(--text-color); font-size: 0.9rem;">Baru Dimulai (0-24%)</div>
<div style="font-size: 0.75rem; color: var(--text-light);">{{ $distribusiStatus['baru_dimulai'] }} materi</div>
</div>
</div>
</div>
</div>
{{-- 4 Kotak Statistik Berjejer Horizontal (Di Bawah) --}}
<div style="margin-top: 20px; padding-top: 20px; border-top: 1px solid #f0f0f0; display: flex; justify-content: space-between; gap: 8px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 70px; text-align: center; padding: 10px 8px; background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
<div style="font-size: 1.3rem; font-weight: 700; color: var(--success-color); line-height: 1;">{{ $distribusiStatus['selesai'] }}</div>
<div style="font-size: 0.75rem; color: var(--text-color); font-weight: 600; margin-top: 4px; line-height: 1.2;">Selesai</div>
</div>
<div style="flex: 1; min-width: 70px; text-align: center; padding: 10px 8px; background: linear-gradient(135deg, #E3F2FD 0%, #D1E9F9 100%); border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
<div style="font-size: 1.3rem; font-weight: 700; color: var(--info-color); line-height: 1;">{{ $distribusiStatus['hampir_selesai'] }}</div>
<div style="font-size: 0.75rem; color: var(--text-color); font-weight: 600; margin-top: 4px; line-height: 1.2;">Hampir Selesai</div>
</div>
<div style="flex: 1; min-width: 70px; text-align: center; padding: 10px 8px; background: linear-gradient(135deg, #FFF8E1 0%, #FFF3CD 100%); border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
<div style="font-size: 1.3rem; font-weight: 700; color: var(--warning-color); line-height: 1;">{{ $distribusiStatus['sedang_berjalan'] }}</div>
<div style="font-size: 0.75rem; color: var(--text-color); font-weight: 600; margin-top: 4px; line-height: 1.2;">Sedang Berjalan</div>
</div>
<div style="flex: 1; min-width: 70px; text-align: center; padding: 10px 8px; background: linear-gradient(135deg, #FFE8EA 0%, #FFD5D8 100%); border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
<div style="font-size: 1.3rem; font-weight: 700; color: var(--danger-color); line-height: 1;">{{ $distribusiStatus['baru_dimulai'] }}</div>
<div style="font-size: 0.75rem; color: var(--text-color); font-weight: 600; margin-top: 4px; line-height: 1.2;">Baru Dimulai</div>
</div>
</div>
</div>
@endif
{{-- GRAFIK 2: Perbandingan Kategori (LINE CHART) --}}
<div style="background: white; padding: 25px; border-radius: var(--border-radius); box-shadow: var(--shadow-md); border: 2px solid var(--primary-light);">
<h4 style="margin: 0 0 20px 0; font-size: 1.1rem; color: var(--text-color); text-align: center; font-weight: 700;">
<i class="fas fa-chart-line"></i> Perbandingan Progress Kategori
</h4>
<div style="max-width: 450px; margin: 0 auto;">
<canvas id="chartLineKategori" style="max-height: 300px;"></canvas>
</div>
<div style="margin-top: 20px; display: flex; justify-content: center; gap: 20px; flex-wrap: wrap;">
<div style="text-align: center;">
<div style="width: 60px; height: 60px; border-radius: 50%; background: linear-gradient(135deg, var(--success-color), #5EA98C); display: flex; align-items: center; justify-content: center; margin: 0 auto 8px; color: white; font-size: 1.1rem; font-weight: 700; box-shadow: 0 4px 8px rgba(111, 186, 157, 0.3);">
{{ $data['progres_quran'] }}%
</div>
<div style="font-size: 0.85rem; color: var(--text-color); font-weight: 600;">Al-Qur'an</div>
</div>
<div style="text-align: center;">
<div style="width: 60px; height: 60px; border-radius: 50%; background: linear-gradient(135deg, var(--info-color), #6AB0D4); display: flex; align-items: center; justify-content: center; margin: 0 auto 8px; color: white; font-size: 1.1rem; font-weight: 700; box-shadow: 0 4px 8px rgba(129, 198, 232, 0.3);">
{{ $data['progres_hadist'] }}%
</div>
<div style="font-size: 0.85rem; color: var(--text-color); font-weight: 600;">Hadist</div>
</div>
<div style="text-align: center;">
<div style="width: 60px; height: 60px; border-radius: 50%; background: linear-gradient(135deg, var(--warning-color), #E6B85C); display: flex; align-items: center; justify-content: center; margin: 0 auto 8px; color: white; font-size: 1.1rem; font-weight: 700; box-shadow: 0 4px 8px rgba(255, 213, 107, 0.3);">
{{ $data['progres_materi_tambahan'] }}%
</div>
<div style="font-size: 0.85rem; color: var(--text-color); font-weight: 600;">Materi Tambahan</div>
</div>
</div>
</div>
</div>
</div>
@endif
{{-- GRAFIK BATANG: Progress per Materi (SEBELUM TIPS) --}}
@if($capaianPerMateri->count() > 0)
<div class="content-box" style="margin-top: 25px;">
<h3 style="margin-bottom: 20px; color: var(--primary-dark);">
<i class="fas fa-chart-bar"></i> Progress per Materi (Top 10)
</h3>
<div style="background: white; padding: 25px; border-radius: var(--border-radius); box-shadow: var(--shadow-sm); border: 2px solid var(--primary-light);">
<canvas id="chartBarMateri" style="max-height: 450px;"></canvas>
</div>
<div style="margin-top: 20px; text-align: center;">
<a href="{{ route('santri.capaian.index') }}" class="btn btn-primary">
<i class="fas fa-list"></i> Lihat Semua Capaian Detail
</a>
</div>
</div>
@endif
{{-- TIPS HARI INI (PALING BAWAH SENDIRI) --}}
<div class="content-box" style="margin-top: 25px; background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); border: 2px solid var(--primary-color);">
<h4 style="margin: 0 0 15px 0; color: var(--primary-dark);">
<i class="fas fa-lightbulb"></i> Tips Hari Ini
</h4>
@ -191,4 +289,265 @@
untuk mengetahui peraturan yang berlaku.
</p>
</div>
{{-- Chart.js Script --}}
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// ============================================
// GRAFIK 1: Distribusi Status (PIE CHART)
// ============================================
@if(array_sum($distribusiStatus) > 0)
const ctxPieStatus = document.getElementById('chartPieStatus');
if (ctxPieStatus) {
new Chart(ctxPieStatus.getContext('2d'), {
type: 'pie',
data: {
// labels: ['Selesai (100%)', 'Hampir Selesai (75-99%)', 'Sedang Berjalan (25-74%)', 'Baru Dimulai (0-24%)'],
datasets: [{
data: [
{{ $distribusiStatus['selesai'] }},
{{ $distribusiStatus['hampir_selesai'] }},
{{ $distribusiStatus['sedang_berjalan'] }},
{{ $distribusiStatus['baru_dimulai'] }}
],
backgroundColor: [
'rgba(111, 186, 157, 0.9)',
'rgba(129, 198, 232, 0.9)',
'rgba(255, 213, 107, 0.9)',
'rgba(255, 139, 148, 0.9)',
],
borderColor: '#fff',
borderWidth: 3
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
position: 'bottom',
labels: {
padding: 15,
font: {
size: 12,
weight: '600'
}
}
},
tooltip: {
callbacks: {
label: function(context) {
const label = context.label || '';
const value = context.parsed || 0;
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = total > 0 ? ((value / total) * 100).toFixed(1) : 0;
return label + ': ' + value + ' materi (' + percentage + '%)';
}
}
}
}
}
});
}
@endif
// ============================================
// GRAFIK 2: Perbandingan Kategori (LINE CHART)
// ============================================
const ctxLineKategori = document.getElementById('chartLineKategori');
if (ctxLineKategori) {
new Chart(ctxLineKategori.getContext('2d'), {
type: 'line',
data: {
labels: ['Al-Qur\'an', 'Hadist', 'Materi Tambahan'],
datasets: [{
label: 'Progress (%)',
data: [
{{ $data['progres_quran'] }},
{{ $data['progres_hadist'] }},
{{ $data['progres_materi_tambahan'] }}
],
backgroundColor: 'rgba(111, 186, 157, 0.2)',
borderColor: 'rgba(111, 186, 157, 1)',
borderWidth: 4,
pointBackgroundColor: [
'rgba(111, 186, 157, 1)',
'rgba(129, 198, 232, 1)',
'rgba(255, 213, 107, 1)'
],
pointBorderColor: '#fff',
pointBorderWidth: 3,
pointRadius: 8,
pointHoverRadius: 10,
tension: 0.4,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
stepSize: 20,
callback: function(value) {
return value + '%';
},
font: {
size: 12,
weight: '600'
}
},
grid: {
color: 'rgba(0, 0, 0, 0.05)'
}
},
x: {
ticks: {
font: {
size: 12,
weight: '600'
}
},
grid: {
display: false
}
}
},
plugins: {
legend: {
display: false
},
tooltip: {
callbacks: {
label: function(context) {
return 'Progress: ' + context.parsed.y.toFixed(1) + '%';
}
}
}
}
}
});
}
// ============================================
// GRAFIK 3: Progress per Materi (BAR CHART - Vertikal)
// ============================================
@if($capaianPerMateri->count() > 0)
const ctxBarMateri = document.getElementById('chartBarMateri');
if (ctxBarMateri) {
new Chart(ctxBarMateri.getContext('2d'), {
type: 'bar',
data: {
labels: [
@foreach($capaianPerMateri as $item)
'{{ Str::limit($item->materi->nama_kitab, 30) }}',
@endforeach
],
datasets: [{
label: 'Progress (%)',
data: [
@foreach($capaianPerMateri as $item)
{{ $item->persentase }},
@endforeach
],
backgroundColor: [
@foreach($capaianPerMateri as $item)
@if($item->materi->kategori == 'Al-Qur\'an')
'rgba(111, 186, 157, 0.8)',
@elseif($item->materi->kategori == 'Hadist')
'rgba(129, 198, 232, 0.8)',
@else
'rgba(255, 213, 107, 0.8)',
@endif
@endforeach
],
borderColor: [
@foreach($capaianPerMateri as $item)
@if($item->materi->kategori == 'Al-Qur\'an')
'rgba(111, 186, 157, 1)',
@elseif($item->materi->kategori == 'Hadist')
'rgba(129, 198, 232, 1)',
@else
'rgba(255, 213, 107, 1)',
@endif
@endforeach
],
borderWidth: 2,
borderRadius: 8,
borderSkipped: false
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
display: false
},
tooltip: {
callbacks: {
label: function(context) {
return 'Progress: ' + context.parsed.y.toFixed(1) + '%';
}
}
}
},
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
stepSize: 10,
callback: function(value) {
return value + '%';
},
font: {
size: 12,
weight: '600'
}
},
grid: {
color: 'rgba(0, 0, 0, 0.05)'
},
title: {
display: true,
text: 'Persentase (%)',
font: {
size: 14,
weight: 'bold'
}
}
},
x: {
ticks: {
font: {
size: 11
},
maxRotation: 45,
minRotation: 45
},
grid: {
display: false
},
title: {
display: true,
text: 'Materi',
font: {
size: 14,
weight: 'bold'
}
}
}
}
}
});
}
@endif
});
</script>
@endsection

View File

@ -0,0 +1,365 @@
@extends('layouts.app')
@section('title', 'Riwayat Kegiatan & Absensi')
@section('content')
<div class="page-header">
<h2><i class="fas fa-calendar-check"></i> Riwayat Kegiatan & Absensi</h2>
<p style="margin: 5px 0 0 0; color: var(--text-light);">
{{ $santri->nama_lengkap }} - Kelas {{ $santri->kelas }}
</p>
</div>
{{-- JADWAL KEGIATAN HARI INI --}}
<div class="content-box" style="margin-bottom: 25px; background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); border: 2px solid var(--primary-color);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
<h3 style="margin: 0; color: var(--primary-dark);">
<i class="fas fa-clock"></i> Jadwal Kegiatan Hari Ini ({{ ucfirst($hariIni) }})
</h3>
<span class="badge badge-primary badge-lg">
<i class="fas fa-calendar-day"></i> {{ \Carbon\Carbon::now()->locale('id')->isoFormat('D MMMM YYYY') }}
</span>
</div>
@if($jadwalHariIni->count() > 0)
<div style="display: flex; flex-direction: column; gap: 12px;">
@foreach($jadwalHariIni as $jadwal)
<div style="background: white; padding: 18px; border-radius: var(--border-radius-sm); border-left: 4px solid {{ isset($absensiHariIni[$jadwal->kegiatan_id]) ? 'var(--success-color)' : 'var(--warning-color)' }}; display: flex; justify-content: space-between; align-items: center; box-shadow: var(--shadow-sm);">
<div style="flex: 1;">
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 8px;">
<span class="badge badge-info">{{ $jadwal->kategori->nama_kategori }}</span>
<h4 style="margin: 0; font-size: 1.1rem; color: var(--text-color);">{{ $jadwal->nama_kegiatan }}</h4>
</div>
<div style="display: flex; align-items: center; gap: 15px; font-size: 0.9rem; color: var(--text-light);">
<span><i class="fas fa-clock"></i> {{ date('H:i', strtotime($jadwal->waktu_mulai)) }} - {{ date('H:i', strtotime($jadwal->waktu_selesai)) }}</span>
@if($jadwal->materi)
<span><i class="fas fa-book"></i> {{ $jadwal->materi }}</span>
@endif
</div>
</div>
<div>
@if(isset($absensiHariIni[$jadwal->kegiatan_id]))
<span class="badge badge-success badge-lg">
<i class="fas fa-check-circle"></i> {{ $absensiHariIni[$jadwal->kegiatan_id] }}
</span>
@else
<span class="badge badge-warning badge-lg">
<i class="fas fa-hourglass-half"></i> Belum Absen
</span>
@endif
</div>
</div>
@endforeach
</div>
@else
<div class="empty-state" style="padding: 40px; text-align: center;">
<i class="fas fa-calendar-times" style="font-size: 3rem; color: #ccc;"></i>
<p style="margin-top: 15px; color: var(--text-light);">Tidak ada jadwal kegiatan untuk hari ini.</p>
</div>
@endif
</div>
{{-- STATISTIK KEHADIRAN 30 HARI TERAKHIR --}}
<div class="row-cards" style="margin-bottom: 25px;">
<div class="card card-success">
<h3><i class="fas fa-check-circle"></i> Total Kehadiran</h3>
<div class="card-value">{{ $stats30Hari['Hadir'] ?? 0 }}</div>
<div class="card-icon"><i class="fas fa-check-circle"></i></div>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">30 hari terakhir</p>
</div>
<div class="card card-info">
<h3><i class="fas fa-percentage"></i> Persentase Kehadiran</h3>
<div class="card-value">{{ $persentaseKehadiran }}%</div>
<div class="card-icon"><i class="fas fa-chart-line"></i></div>
<div style="margin-top: 10px;">
<div class="progress-bar">
<div class="progress-fill" style="width: {{ $persentaseKehadiran }}%; background: var(--info-color);"></div>
</div>
</div>
</div>
<div class="card card-warning">
<h3><i class="fas fa-exclamation-triangle"></i> Izin / Sakit / Alpa</h3>
<div class="card-value">{{ ($stats30Hari['Izin'] ?? 0) + ($stats30Hari['Sakit'] ?? 0) + ($stats30Hari['Alpa'] ?? 0) }}</div>
<div class="card-icon"><i class="fas fa-exclamation-triangle"></i></div>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">
Izin: {{ $stats30Hari['Izin'] ?? 0 }} | Sakit: {{ $stats30Hari['Sakit'] ?? 0 }} | Alpa: {{ $stats30Hari['Alpa'] ?? 0 }}
</p>
</div>
<div class="card card-primary">
<h3><i class="fas fa-list-check"></i> Total Kegiatan</h3>
<div class="card-value">{{ $totalKegiatan30Hari }}</div>
<div class="card-icon"><i class="fas fa-list-check"></i></div>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">30 hari terakhir</p>
</div>
</div>
{{-- GRAFIK KEHADIRAN MINGGUAN & PER KATEGORI (SIDE BY SIDE) --}}
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(450px, 1fr)); gap: 25px; margin-bottom: 25px;">
{{-- GRAFIK 1: Kehadiran per Minggu (LINE CHART) --}}
<div class="content-box">
<h3 style="margin-bottom: 20px; color: var(--primary-dark);">
<i class="fas fa-chart-line"></i> Tren Kehadiran (4 Minggu Terakhir)
</h3>
<canvas id="chartTrenKehadiran" style="max-height: 300px;"></canvas>
</div>
{{-- GRAFIK 2: Kehadiran per Kategori (BAR CHART) --}}
<div class="content-box">
<h3 style="margin-bottom: 20px; color: var(--primary-dark);">
<i class="fas fa-chart-bar"></i> Kehadiran per Kategori Kegiatan
</h3>
<canvas id="chartKategori" style="max-height: 300px;"></canvas>
</div>
</div>
{{-- FILTER & RIWAYAT ABSENSI --}}
<div class="content-box">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; flex-wrap: wrap; gap: 15px;">
<h3 style="margin: 0; color: var(--text-color);">
<i class="fas fa-history"></i> Riwayat Absensi Lengkap
</h3>
{{-- Form Filter --}}
<form method="GET" action="{{ route('santri.kegiatan.index') }}" style="display: flex; gap: 10px; flex-wrap: wrap;">
<input type="month" name="bulan" class="form-control" value="{{ request('bulan') }}"
style="max-width: 200px;" placeholder="Pilih Bulan">
<select name="status" class="form-control" style="max-width: 150px;">
<option value="">Semua Status</option>
<option value="Hadir" {{ request('status') == 'Hadir' ? 'selected' : '' }}>Hadir</option>
<option value="Izin" {{ request('status') == 'Izin' ? 'selected' : '' }}>Izin</option>
<option value="Sakit" {{ request('status') == 'Sakit' ? 'selected' : '' }}>Sakit</option>
<option value="Alpa" {{ request('status') == 'Alpa' ? 'selected' : '' }}>Alpa</option>
</select>
<button type="submit" class="btn btn-primary btn-sm">
<i class="fas fa-filter"></i> Filter
</button>
<a href="{{ route('santri.kegiatan.index') }}" class="btn btn-secondary btn-sm">
<i class="fas fa-redo"></i> Reset
</a>
</form>
</div>
@if($riwayats->count() > 0)
<div class="table-container">
<table class="data-table">
<thead>
<tr>
<th>No</th>
<th>Tanggal</th>
<th>Kegiatan</th>
<th>Kategori</th>
<th>Waktu Absen</th>
<th>Status</th>
<th>Metode</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach($riwayats as $index => $absensi)
<tr>
<td>{{ $riwayats->firstItem() + $index }}</td>
<td>{{ $absensi->tanggal_formatted }}</td>
<td><strong>{{ $absensi->kegiatan->nama_kegiatan }}</strong></td>
<td><span class="badge badge-info">{{ $absensi->kegiatan->kategori->nama_kategori }}</span></td>
<td>{{ $absensi->waktu_absen_formatted }}</td>
<td>
<span class="badge {{ $absensi->status_badge_class }}">
<i class="fas fa-{{ $absensi->status == 'Hadir' ? 'check' : ($absensi->status == 'Izin' ? 'info-circle' : ($absensi->status == 'Sakit' ? 'heartbeat' : 'times')) }}-circle"></i>
{{ $absensi->status }}
</span>
</td>
<td><span class="badge badge-secondary">{{ $absensi->metode_absen }}</span></td>
<td class="text-center">
<a href="{{ route('santri.kegiatan.show', $absensi->kegiatan_id) }}" class="btn btn-sm btn-primary" title="Lihat Detail Kegiatan">
<i class="fas fa-eye"></i>
</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
{{-- Pagination --}}
<div style="margin-top: 20px;">
{{ $riwayats->links() }}
</div>
@else
<div class="empty-state">
<i class="fas fa-inbox"></i>
<h3>Belum Ada Riwayat Absensi</h3>
<p>Riwayat absensi Anda akan muncul di sini setelah mengikuti kegiatan.</p>
</div>
@endif
</div>
{{-- Chart.js Script --}}
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// ============================================
// GRAFIK 1: Tren Kehadiran per Minggu (LINE CHART)
// ============================================
const ctxTren = document.getElementById('chartTrenKehadiran');
if (ctxTren) {
new Chart(ctxTren.getContext('2d'), {
type: 'line',
data: {
labels: [
@foreach($dataGrafikMingguan as $data)
'{{ $data["minggu"] }}',
@endforeach
],
datasets: [
{
label: 'Hadir',
data: [
@foreach($dataGrafikMingguan as $data)
{{ $data['hadir'] }},
@endforeach
],
borderColor: 'rgba(111, 186, 157, 1)',
backgroundColor: 'rgba(111, 186, 157, 0.2)',
borderWidth: 3,
pointRadius: 5,
pointBackgroundColor: 'rgba(111, 186, 157, 1)',
tension: 0.4,
fill: true
},
{
label: 'Total Kegiatan',
data: [
@foreach($dataGrafikMingguan as $data)
{{ $data['total'] }},
@endforeach
],
borderColor: 'rgba(129, 198, 232, 1)',
backgroundColor: 'rgba(129, 198, 232, 0.1)',
borderWidth: 2,
pointRadius: 4,
pointBackgroundColor: 'rgba(129, 198, 232, 1)',
tension: 0.4,
fill: true,
borderDash: [5, 5]
}
]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
display: true,
position: 'top',
labels: {
font: { size: 12, weight: '600' },
padding: 15
}
},
tooltip: {
callbacks: {
label: function(context) {
return context.dataset.label + ': ' + context.parsed.y;
}
}
}
},
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 1,
font: { size: 12, weight: '600' }
},
grid: { color: 'rgba(0, 0, 0, 0.05)' }
},
x: {
ticks: { font: { size: 12, weight: '600' } },
grid: { display: false }
}
}
}
});
}
// ============================================
// GRAFIK 2: Kehadiran per Kategori (BAR CHART)
// ============================================
const ctxKategori = document.getElementById('chartKategori');
if (ctxKategori) {
new Chart(ctxKategori.getContext('2d'), {
type: 'bar',
data: {
labels: [
@foreach($statsByKategori as $stat)
'{{ $stat->nama_kategori }}',
@endforeach
],
datasets: [{
label: 'Kehadiran',
data: [
@foreach($statsByKategori as $stat)
{{ $stat->hadir }},
@endforeach
],
backgroundColor: [
'rgba(111, 186, 157, 0.8)',
'rgba(129, 198, 232, 0.8)',
'rgba(255, 213, 107, 0.8)',
'rgba(255, 139, 148, 0.8)',
'rgba(179, 157, 219, 0.8)',
],
borderColor: [
'rgba(111, 186, 157, 1)',
'rgba(129, 198, 232, 1)',
'rgba(255, 213, 107, 1)',
'rgba(255, 139, 148, 1)',
'rgba(179, 157, 219, 1)',
],
borderWidth: 2,
borderRadius: 8,
borderSkipped: false
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: function(context) {
return 'Hadir: ' + context.parsed.y + ' kali';
}
}
}
},
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 1,
font: { size: 12, weight: '600' }
},
grid: { color: 'rgba(0, 0, 0, 0.05)' }
},
x: {
ticks: {
font: { size: 11 },
maxRotation: 45,
minRotation: 45
},
grid: { display: false }
}
}
}
});
}
});
</script>
@endsection

View File

@ -0,0 +1,211 @@
@extends('layouts.app')
@section('title', 'Detail Riwayat Kegiatan')
@section('content')
<div class="page-header">
<h2><i class="fas fa-clipboard-list"></i> Detail Riwayat Kegiatan</h2>
<p style="margin: 5px 0 0 0; color: var(--text-light);">
{{ $santri->nama_lengkap }}
</p>
</div>
{{-- INFO KEGIATAN --}}
<div class="content-box" style="margin-bottom: 25px; background: linear-gradient(135deg, #FFFFFF 0%, #F8FBF9 100%); border: 2px solid var(--primary-light);">
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px; margin-bottom: 20px;">
<div>
<h3 style="margin: 0 0 8px 0; color: var(--primary-dark); font-size: 1.5rem;">
{{ $kegiatan->nama_kegiatan }}
</h3>
<div style="display: flex; align-items: center; gap: 12px; flex-wrap: wrap;">
<span class="badge badge-info badge-lg">
<i class="fas fa-tag"></i> {{ $kegiatan->kategori->nama_kategori }}
</span>
<span class="badge badge-primary badge-lg">
<i class="fas fa-calendar-day"></i> {{ $kegiatan->hari }}
</span>
<span class="badge badge-secondary badge-lg">
<i class="fas fa-clock"></i> {{ date('H:i', strtotime($kegiatan->waktu_mulai)) }} - {{ date('H:i', strtotime($kegiatan->waktu_selesai)) }}
</span>
</div>
</div>
<a href="{{ route('santri.kegiatan.index') }}" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
@if($kegiatan->materi)
<div style="padding: 15px; background: var(--primary-light); border-radius: var(--border-radius-sm); margin-bottom: 15px;">
<strong><i class="fas fa-book"></i> Materi:</strong> {{ $kegiatan->materi }}
</div>
@endif
@if($kegiatan->keterangan)
<div style="padding: 15px; background: #FFF8E1; border-radius: var(--border-radius-sm); border-left: 4px solid var(--warning-color);">
<strong><i class="fas fa-info-circle"></i> Keterangan:</strong><br>
{{ $kegiatan->keterangan }}
</div>
@endif
</div>
{{-- STATISTIK KEHADIRAN UNTUK KEGIATAN INI --}}
<div class="row-cards" style="margin-bottom: 25px;">
<div class="card card-success">
<h3><i class="fas fa-check-circle"></i> Total Hadir</h3>
<div class="card-value">{{ $stats['Hadir'] ?? 0 }}</div>
<div class="card-icon"><i class="fas fa-check-circle"></i></div>
</div>
<div class="card card-info">
<h3><i class="fas fa-info-circle"></i> Izin</h3>
<div class="card-value">{{ $stats['Izin'] ?? 0 }}</div>
<div class="card-icon"><i class="fas fa-info-circle"></i></div>
</div>
<div class="card card-warning">
<h3><i class="fas fa-heartbeat"></i> Sakit</h3>
<div class="card-value">{{ $stats['Sakit'] ?? 0 }}</div>
<div class="card-icon"><i class="fas fa-heartbeat"></i></div>
</div>
<div class="card card-danger">
<h3><i class="fas fa-times-circle"></i> Alpa</h3>
<div class="card-value">{{ $stats['Alpa'] ?? 0 }}</div>
<div class="card-icon"><i class="fas fa-times-circle"></i></div>
</div>
</div>
{{-- GRAFIK PIE: Distribusi Status Kehadiran --}}
<div class="content-box" style="margin-bottom: 25px;">
<h3 style="margin-bottom: 20px; color: var(--primary-dark); text-align: center;">
<i class="fas fa-chart-pie"></i> Distribusi Status Kehadiran
</h3>
<div style="max-width: 400px; margin: 0 auto;">
<canvas id="chartDistribusiStatus" style="max-height: 350px;"></canvas>
</div>
<div style="margin-top: 25px; text-align: center; padding-top: 20px; border-top: 1px solid #f0f0f0;">
<div style="display: inline-block; padding: 15px 30px; background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); border-radius: var(--border-radius); box-shadow: var(--shadow-sm);">
<div style="font-size: 0.9rem; color: var(--text-light); margin-bottom: 5px;">Persentase Kehadiran</div>
<div style="font-size: 2.5rem; font-weight: 700; color: var(--success-color);">{{ $persentaseHadir }}%</div>
<div style="font-size: 0.85rem; color: var(--text-light); margin-top: 5px;">dari {{ $totalAbsensi }} total absensi</div>
</div>
</div>
</div>
{{-- RIWAYAT ABSENSI LENGKAP --}}
<div class="content-box">
<h3 style="margin-bottom: 20px; color: var(--text-color);">
<i class="fas fa-history"></i> Riwayat Absensi Lengkap
</h3>
@if($riwayats->count() > 0)
<div class="table-container">
<table class="data-table">
<thead>
<tr>
<th>No</th>
<th>Tanggal</th>
<th>Hari</th>
<th>Waktu Absen</th>
<th>Status</th>
<th>Metode</th>
</tr>
</thead>
<tbody>
@foreach($riwayats as $index => $absensi)
<tr>
<td>{{ $riwayats->firstItem() + $index }}</td>
<td>{{ $absensi->tanggal_formatted }}</td>
<td>{{ \Carbon\Carbon::parse($absensi->tanggal)->locale('id')->dayName }}</td>
<td>{{ $absensi->waktu_absen_formatted }}</td>
<td>
<span class="badge {{ $absensi->status_badge_class }}">
<i class="fas fa-{{ $absensi->status == 'Hadir' ? 'check' : ($absensi->status == 'Izin' ? 'info-circle' : ($absensi->status == 'Sakit' ? 'heartbeat' : 'times')) }}-circle"></i>
{{ $absensi->status }}
</span>
</td>
<td><span class="badge badge-secondary">{{ $absensi->metode_absen }}</span></td>
</tr>
@endforeach
</tbody>
</table>
</div>
{{-- Pagination --}}
<div style="margin-top: 20px;">
{{ $riwayats->links() }}
</div>
@else
<div class="empty-state">
<i class="fas fa-inbox"></i>
<h3>Belum Ada Riwayat</h3>
<p>Anda belum pernah mengikuti kegiatan ini atau belum ada data absensi yang tercatat.</p>
</div>
@endif
</div>
{{-- Chart.js Script --}}
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// ============================================
// GRAFIK PIE: Distribusi Status Kehadiran
// ============================================
const ctxPie = document.getElementById('chartDistribusiStatus');
if (ctxPie) {
new Chart(ctxPie.getContext('2d'), {
type: 'pie',
data: {
labels: ['Hadir', 'Izin', 'Sakit', 'Alpa'],
datasets: [{
data: [
{{ $stats['Hadir'] ?? 0 }},
{{ $stats['Izin'] ?? 0 }},
{{ $stats['Sakit'] ?? 0 }},
{{ $stats['Alpa'] ?? 0 }}
],
backgroundColor: [
'rgba(111, 186, 157, 0.9)',
'rgba(129, 198, 232, 0.9)',
'rgba(255, 213, 107, 0.9)',
'rgba(255, 139, 148, 0.9)',
],
borderColor: '#fff',
borderWidth: 3
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
position: 'bottom',
labels: {
padding: 20,
font: {
size: 13,
weight: '600'
}
}
},
tooltip: {
callbacks: {
label: function(context) {
const label = context.label || '';
const value = context.parsed || 0;
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = total > 0 ? ((value / total) * 100).toFixed(1) : 0;
return label + ': ' + value + ' kali (' + percentage + '%)';
}
}
}
}
}
});
}
});
</script>
@endsection

View File

@ -1,3 +1,4 @@
<!-- resources/views/santri/profil/index.blade.php -->
@extends('layouts.app')
@section('title', 'Edit Profil Santri')

View File

@ -18,10 +18,21 @@
{{-- Header Profil --}}
<div class="detail-header">
<div style="display: flex; align-items: center; gap: 20px;">
{{-- Avatar Santri --}}
{{-- Foto Santri --}}
@if($santri->foto && file_exists(public_path('storage/' . $santri->foto)))
<img src="{{ asset('storage/' . $santri->foto) }}"
alt="Foto {{ $santri->nama_lengkap }}"
style="width: 80px; height: 80px; border-radius: 50%; object-fit: cover; border: 3px solid var(--primary-color); flex-shrink: 0;"
loading="lazy"
onerror="this.onerror=null; this.style.display='none'; this.nextElementSibling.style.display='flex';">
<div class="santri-avatar-initial santri-avatar-initial-lg" style="display: none;">
{{ strtoupper(substr($santri->nama_lengkap, 0, 1)) }}
</div>
@else
<div class="santri-avatar-initial santri-avatar-initial-lg">
{{ strtoupper(substr($santri->nama_lengkap, 0, 1)) }}
</div>
@endif
<div>
<h3 style="margin: 0; font-size: 1.8rem; color: var(--text-color);">
@ -146,7 +157,7 @@
<div style="margin-top: 30px; padding: 20px; background: var(--primary-light); border-radius: var(--border-radius-sm); border-left: 4px solid var(--primary-color);">
<p style="margin: 0; color: var(--text-color); line-height: 1.6;">
<i class="fas fa-info-circle" style="color: var(--primary-color);"></i>
<strong>Catatan:</strong> Jika ada data yang perlu diperbarui selain alamat dan nomor HP orang tua, silakan hubungi admin atau pengurus pesantren.
<strong>Catatan:</strong> Jika ada data yang perlu diperbarui termasuk foto profil, silakan hubungi admin atau pengurus pesantren.
</p>
</div>
</div>

View File

@ -1,19 +1,32 @@
<?php
// routes/api.php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\ApiAuthController;
/*
|--------------------------------------------------------------------------
| API Routes
| API Routes untuk Mobile App
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "api" middleware group. Make something great!
|
*/
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
// Public routes (tanpa auth)
Route::prefix('v1')->group(function () {
// Login
Route::post('/login', [ApiAuthController::class, 'login']);
});
// Protected routes (butuh token)
Route::prefix('v1')->middleware('auth:sanctum')->group(function () {
// Logout
Route::post('/logout', [ApiAuthController::class, 'logout']);
// Profile
Route::get('/profile', [ApiAuthController::class, 'profile']);
// TODO: Tambahkan endpoint lain di sini
// Route::get('/uang-saku', [ApiUangSakuController::class, 'index']);
// Route::get('/pelanggaran', [ApiPelanggaranController::class, 'index']);
// dst...
});

View File

@ -29,6 +29,7 @@
use App\Http\Controllers\Santri\SantriKesehatanController;
use App\Http\Controllers\Santri\SantriCapaianController;
use App\Http\Controllers\Santri\SantriKepulanganController;
use App\Http\Controllers\Santri\RiwayatKegiatanSantriController; // ✅ TAMBAHKAN INI
/*
|--------------------------------------------------------------------------
@ -67,7 +68,8 @@
// --- RUTE ADMINISTRATOR (Prefix: admin) ---
Route::prefix('admin')
->middleware(['auth', 'role:admin'])
->name('admin.')->group(function () {
->name('admin.')
->group(function () {
// Logout Admin
Route::post('logout', [AdminAuthController::class, 'logout'])->name('logout');
@ -110,35 +112,40 @@
'cetakSurat'
])->name('kesehatan-santri.cetak-surat');
// 5. KEPULANGAN SANTRI
Route::resource('kepulangan', KepulanganController::class);
// 5. KEPULANGAN SANTRI (UPDATED - LENGKAP) ✅
Route::prefix('kepulangan')->name('kepulangan.')->group(function () {
// Route tambahan untuk approve/reject
Route::post('kepulangan/{kepulangan}/approve', [
KepulanganController::class,
'approve'
])->name('kepulangan.approve');
// Main CRUD
Route::get('/', [KepulanganController::class, 'index'])->name('index');
Route::get('/create', [KepulanganController::class, 'create'])->name('create');
Route::post('/', [KepulanganController::class, 'store'])->name('store');
Route::get('/{id_kepulangan}', [KepulanganController::class, 'show'])->name('show');
Route::get('/{id_kepulangan}/edit', [KepulanganController::class, 'edit'])->name('edit');
Route::put('/{id_kepulangan}', [KepulanganController::class, 'update'])->name('update');
Route::delete('/{id_kepulangan}', [KepulanganController::class, 'destroy'])->name('destroy');
Route::post('kepulangan/{kepulangan}/reject', [
KepulanganController::class,
'reject'
])->name('kepulangan.reject');
// Actions (Approval/Reject/Complete)
Route::post('/{id_kepulangan}/approve', [KepulanganController::class, 'approve'])->name('approve');
Route::post('/{id_kepulangan}/reject', [KepulanganController::class, 'reject'])->name('reject');
Route::post('/{id_kepulangan}/complete', [KepulanganController::class, 'complete'])->name('complete');
Route::post('kepulangan/{kepulangan}/complete', [
KepulanganController::class,
'complete'
])->name('kepulangan.complete');
// Print Surat Izin
Route::get('/{id_kepulangan}/print', [KepulanganController::class, 'print'])->name('print');
Route::get('kepulangan/{kepulangan}/print', [
KepulanganController::class,
'print'
])->name('kepulangan.print');
// Settings & Manajemen Kuota
Route::get('/settings/manage', [KepulanganController::class, 'settings'])->name('settings');
Route::put('/settings/update', [KepulanganController::class, 'updateSettings'])->name('settings.update');
// API route untuk get santri data
Route::get('api/kepulangan/santri/{id_santri}', [
KepulanganController::class,
'getSantriData'
])->name('api.kepulangan.santri');
// Reset Kuota
Route::post('/reset/santri/{id_santri}', [KepulanganController::class, 'resetKuotaSantri'])->name('reset.santri');
Route::post('/reset/semua', [KepulanganController::class, 'resetKuotaSemuaSantri'])->name('reset.semua');
// List Santri Over Limit
Route::get('/over-limit/list', [KepulanganController::class, 'santriOverLimit'])->name('over-limit');
// API untuk AJAX (Get Santri Data)
Route::get('/api/santri/{id_santri}', [KepulanganController::class, 'getSantriData'])->name('api.santri');
});
// 6. BERITA
Route::prefix('berita')->name('berita.')->group(function () {
@ -332,4 +339,10 @@
Route::get('/', [SantriKepulanganController::class, 'index'])->name('index');
Route::get('/{kepulangan:id_kepulangan}', [SantriKepulanganController::class, 'show'])->name('show');
});
// 8. RIWAYAT KEGIATAN & ABSENSI (BARU ✅)
Route::prefix('kegiatan')->name('kegiatan.')->group(function () {
Route::get('/', [\App\Http\Controllers\Santri\RiwayatKegiatanSantriController::class, 'index'])->name('index');
Route::get('/{kegiatan_id}', [\App\Http\Controllers\Santri\RiwayatKegiatanSantriController::class, 'show'])->name('show');
});
});

View File

@ -1 +0,0 @@
a:4:{s:6:"_token";s:40:"8ML9ZdqWCLmjAek9Pi9CSKX0CGiYJqxIKIH97x95";s:3:"url";a:1:{s:8:"intended";s:37:"http://127.0.0.1:8000/admin/dashboard";}s:9:"_previous";a:1:{s:3:"url";s:37:"http://127.0.0.1:8000/admin/dashboard";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}

View File

@ -1 +0,0 @@
a:4:{s:6:"_token";s:40:"tLWa7PcNO0JI4f1QHde6luLyp4Ex4H9kRkY0yFqo";s:13:"last_activity";i:1763627918;s:9:"_previous";a:1:{s:3:"url";s:33:"http://127.0.0.1:8000/admin/login";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}

View File

@ -0,0 +1 @@
a:3:{s:6:"_token";s:40:"HMiLcFVcm6pBs2CoAThDnWeSql4wY7Rg2wcESX53";s:7:"success";s:21:"Anda berhasil logout.";s:6:"_flash";a:2:{s:3:"new";a:0:{}s:3:"old";a:1:{i:0;s:7:"success";}}}

View File

@ -0,0 +1 @@
a:4:{s:6:"_token";s:40:"vvFpRFUMLEugpbL26sTeoMo21ei7FQXxYJzYURcb";s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}s:3:"url";a:1:{s:8:"intended";s:37:"http://127.0.0.1:8000/admin/dashboard";}s:9:"_previous";a:1:{s:3:"url";s:37:"http://127.0.0.1:8000/admin/dashboard";}}

View File

@ -1 +0,0 @@
a:6:{s:6:"_token";s:40:"9vNjPLLee09wl7aDFMu598IYqYrzhRXo2tGcpKYW";s:50:"login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d";i:2;s:17:"password_hash_web";s:60:"$2y$12$2MjNMVyBNLiANDZq0.J7E.wltuOfMH21Eqqx4teTEcr1T4ZayVGGq";s:13:"last_activity";i:1763627930;s:9:"_previous";a:1:{s:3:"url";s:38:"http://127.0.0.1:8000/santri/dashboard";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}

View File

@ -0,0 +1 @@
a:4:{s:6:"_token";s:40:"iGl6a2chuGMqLNfaeXnP152fY8roRVN4aQ3CaDBW";s:13:"last_activity";i:1767673469;s:9:"_previous";a:1:{s:3:"url";s:33:"http://127.0.0.1:8000/admin/login";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}

View File

@ -0,0 +1,5 @@
<?php $__env->startSection('title', __('Not Found')); ?>
<?php $__env->startSection('code', '404'); ?>
<?php $__env->startSection('message', __('Not Found')); ?>
<?php echo $__env->make('errors::minimal', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\vendor\laravel\framework\src\Illuminate\Foundation\Exceptions/views/404.blade.php ENDPATH**/ ?>

View File

@ -1,194 +0,0 @@
<?php $__env->startSection('title', 'Detail Capaian'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-book-reader"></i> Detail Capaian</h2>
</div>
<div class="content-box">
<div class="detail-header">
<h3><i class="fas fa-info-circle"></i> Informasi Capaian</h3>
<a href="<?php echo e(route('santri.capaian.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
<div class="detail-section">
<h4><i class="fas fa-book"></i> Informasi Materi</h4>
<table class="detail-table">
<tr>
<th>Nama Materi</th>
<td><strong><?php echo e($capaian->materi->nama_kitab); ?></strong></td>
</tr>
<tr>
<th>Kategori</th>
<td>
<span class="badge
<?php if($capaian->materi->kategori == 'Al-Qur\'an'): ?> badge-success
<?php elseif($capaian->materi->kategori == 'Hadist'): ?> badge-info
<?php else: ?> badge-warning
<?php endif; ?>
">
<?php echo e($capaian->materi->kategori); ?>
</span>
</td>
</tr>
<tr>
<th>Total Halaman</th>
<td><?php echo e($capaian->materi->total_halaman); ?> halaman (Hal. <?php echo e($capaian->materi->halaman_mulai); ?> - <?php echo e($capaian->materi->halaman_akhir); ?>)</td>
</tr>
</table>
</div>
<div class="detail-section">
<h4><i class="fas fa-chart-line"></i> Progress Pembelajaran</h4>
<table class="detail-table">
<tr>
<th>Persentase Selesai</th>
<td>
<div style="display: flex; align-items: center; gap: 15px;">
<div class="progress-bar" style="flex: 1;">
<div class="progress-fill" style="width: <?php echo e($capaian->persentase); ?>%; background:
<?php if($capaian->persentase >= 100): ?> var(--success-color)
<?php elseif($capaian->persentase >= 75): ?> var(--info-color)
<?php elseif($capaian->persentase >= 50): ?> var(--warning-color)
<?php else: ?> var(--danger-color)
<?php endif; ?>
;"></div>
</div>
<span style="font-weight: 700; font-size: 1.2rem; color: var(--primary-color);">
<?php echo e(number_format($capaian->persentase, 2)); ?>%
</span>
</div>
</td>
</tr>
<tr>
<th>Jumlah Halaman Selesai</th>
<td>
<strong style="color: var(--primary-color); font-size: 1.1rem;">
<?php echo e(count($capaian->pages_array)); ?>
</strong> dari <?php echo e($capaian->materi->total_halaman); ?> halaman
</td>
</tr>
<tr>
<th>Detail Halaman Selesai</th>
<td>
<div style="background: var(--primary-light); padding: 12px; border-radius: var(--border-radius-sm); font-family: monospace; color: var(--text-color); line-height: 1.8;">
<?php echo e($capaian->halaman_selesai); ?>
</div>
</td>
</tr>
<tr>
<th>Tanggal Input</th>
<td><?php echo e(\Carbon\Carbon::parse($capaian->tanggal_input)->format('d F Y')); ?></td>
</tr>
<tr>
<th>Semester</th>
<td>
<span class="badge badge-primary">
<?php echo e($capaian->semester->nama_semester); ?> - <?php echo e($capaian->semester->tahun_ajaran); ?>
</span>
</td>
</tr>
<?php if($capaian->catatan): ?>
<tr>
<th>Catatan</th>
<td>
<div style="background: #FFF8E1; padding: 12px; border-radius: var(--border-radius-sm); border-left: 4px solid var(--warning-color);">
<i class="fas fa-sticky-note" style="color: var(--warning-color); margin-right: 8px;"></i>
<?php echo e($capaian->catatan); ?>
</div>
</td>
</tr>
<?php endif; ?>
</table>
</div>
<div class="detail-section">
<h4><i class="fas fa-th"></i> Visualisasi Halaman yang Diselesaikan</h4>
<div style="background: white; padding: 20px; border-radius: var(--border-radius-sm); box-shadow: var(--shadow-sm);">
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(40px, 1fr)); gap: 8px;">
<?php
$completedPages = $capaian->pages_array;
$totalPages = $capaian->materi->total_halaman;
$startPage = $capaian->materi->halaman_mulai;
?>
<?php for($i = $startPage; $i <= ($startPage + $totalPages - 1); $i++): ?>
<?php
$isCompleted = in_array($i, $completedPages);
?>
<div style="
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
font-size: 0.8rem;
font-weight: 600;
<?php echo e($isCompleted
? 'background: linear-gradient(135deg, var(--success-color), #5EA98C); color: white; box-shadow: 0 2px 4px rgba(111, 186, 157, 0.3);'
: 'background: #F5F5F5; color: #999; border: 1px dashed #ddd;'); ?>
">
<?php echo e($i); ?>
</div>
<?php endfor; ?>
</div>
<div style="display: flex; justify-content: center; gap: 25px; margin-top: 20px; padding-top: 15px; border-top: 1px solid #E0E0E0;">
<div style="display: flex; align-items: center; gap: 8px;">
<div style="width: 20px; height: 20px; background: linear-gradient(135deg, var(--success-color), #5EA98C); border-radius: 4px;"></div>
<span style="font-size: 0.85rem; color: var(--text-color);">Selesai (<?php echo e(count($completedPages)); ?>)</span>
</div>
<div style="display: flex; align-items: center; gap: 8px;">
<div style="width: 20px; height: 20px; background: #F5F5F5; border: 1px dashed #ddd; border-radius: 4px;"></div>
<span style="font-size: 0.85rem; color: var(--text-color);">Belum (<?php echo e($totalPages - count($completedPages)); ?>)</span>
</div>
</div>
</div>
</div>
<div style="text-align: center; margin-top: 30px;">
<?php if($capaian->persentase >= 100): ?>
<div style="background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%); padding: 20px; border-radius: var(--border-radius); border: 2px solid var(--success-color);">
<i class="fas fa-check-circle" style="font-size: 3rem; color: var(--success-color); margin-bottom: 10px;"></i>
<h3 style="margin: 0; color: #155724;">Alhamdulillah, Materi Selesai! 🎉</h3>
<p style="margin: 8px 0 0 0; color: #155724;">Terus semangat untuk materi berikutnya!</p>
</div>
<?php elseif($capaian->persentase >= 75): ?>
<div style="background: linear-gradient(135deg, #d1ecf1 0%, #bee5eb 100%); padding: 20px; border-radius: var(--border-radius); border: 2px solid var(--info-color);">
<i class="fas fa-fire" style="font-size: 3rem; color: var(--info-color); margin-bottom: 10px;"></i>
<h3 style="margin: 0; color: #0c5460;">Hampir Selesai! 💪</h3>
<p style="margin: 8px 0 0 0; color: #0c5460;">Tinggal sedikit lagi, pertahankan semangatmu!</p>
</div>
<?php elseif($capaian->persentase >= 50): ?>
<div style="background: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%); padding: 20px; border-radius: var(--border-radius); border: 2px solid var(--warning-color);">
<i class="fas fa-hourglass-half" style="font-size: 3rem; color: var(--warning-color); margin-bottom: 10px;"></i>
<h3 style="margin: 0; color: #856404;">Setengah Perjalanan! </h3>
<p style="margin: 8px 0 0 0; color: #856404;">Terus berjuang, jangan menyerah!</p>
</div>
<?php else: ?>
<div style="background: linear-gradient(135deg, #f8d7da 0%, #f5c6cb 100%); padding: 20px; border-radius: var(--border-radius); border: 2px solid var(--danger-color);">
<i class="fas fa-seedling" style="font-size: 3rem; color: var(--danger-color); margin-bottom: 10px;"></i>
<h3 style="margin: 0; color: #721c24;">Baru Memulai! 🌱</h3>
<p style="margin: 8px 0 0 0; color: #721c24;">Setiap perjalanan dimulai dari langkah pertama. Semangat!</p>
</div>
<?php endif; ?>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/santri/capaian/show.blade.php ENDPATH**/ ?>

View File

@ -1,121 +0,0 @@
<?php $__env->startSection('title', 'Riwayat Pelanggaran'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-exclamation-circle"></i> Riwayat Pelanggaran Saya</h2>
</div>
<div class="row-cards">
<div class="card card-danger">
<h3>Total Pelanggaran</h3>
<div class="card-value"><?php echo e($totalPelanggaran); ?></div>
<i class="fas fa-exclamation-triangle card-icon"></i>
</div>
<div class="card card-warning">
<h3>Total Poin</h3>
<div class="card-value"><?php echo e($totalPoin); ?></div>
<i class="fas fa-star card-icon"></i>
</div>
<div class="card card-info">
<h3>Pelanggaran Bulan Ini</h3>
<div class="card-value"><?php echo e($pelanggaranBulanIni); ?></div>
<i class="fas fa-calendar-alt card-icon"></i>
</div>
</div>
<div class="content-box" style="margin-bottom: 20px;">
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;">
<form method="GET" action="<?php echo e(route('santri.pelanggaran.index')); ?>" style="display: flex; gap: 10px; flex-wrap: wrap; align-items: center;">
<input type="date" name="tanggal_mulai" class="form-control" style="width: auto;" value="<?php echo e(request('tanggal_mulai')); ?>" placeholder="Tanggal Mulai">
<input type="date" name="tanggal_selesai" class="form-control" style="width: auto;" value="<?php echo e(request('tanggal_selesai')); ?>" placeholder="Tanggal Selesai">
<button type="submit" class="btn btn-primary btn-sm">
<i class="fas fa-filter"></i> Filter
</button>
<a href="<?php echo e(route('santri.pelanggaran.index')); ?>" class="btn btn-secondary btn-sm">
<i class="fas fa-redo"></i> Reset
</a>
<a href="<?php echo e(route('santri.pelanggaran.index', ['bulan_ini' => 1])); ?>" class="btn btn-info btn-sm">
<i class="fas fa-calendar-check"></i> Bulan Ini
</a>
</form>
<a href="<?php echo e(route('santri.pelanggaran.kategori')); ?>" class="btn btn-warning btn-sm">
<i class="fas fa-list"></i> Lihat Daftar Kategori Pelanggaran
</a>
</div>
</div>
<div class="content-box">
<?php if($riwayat->count() > 0): ?>
<div style="overflow-x: auto;">
<table class="data-table">
<thead>
<tr>
<th style="width: 5%;">No</th>
<th style="width: 10%;">ID Riwayat</th>
<th style="width: 12%;">Tanggal</th>
<th style="width: 25%;">Jenis Pelanggaran</th>
<th style="width: 8%;">Poin</th>
<th style="width: 30%;">Keterangan</th>
<th style="width: 10%;" class="text-center">Aksi</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $riwayat; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><?php echo e($riwayat->firstItem() + $index); ?></td>
<td><strong><?php echo e($item->id_riwayat); ?></strong></td>
<td>
<i class="fas fa-calendar"></i>
<?php echo e(\Carbon\Carbon::parse($item->tanggal)->isoFormat('D MMM YYYY')); ?>
</td>
<td><?php echo e($item->kategori->nama_pelanggaran ?? '-'); ?></td>
<td>
<span class="badge badge-danger badge-lg">
<i class="fas fa-star"></i> <?php echo e($item->poin); ?>
</span>
</td>
<td>
<div class="content-preview">
<?php echo e($item->keterangan ?: '-'); ?>
</div>
</td>
<td class="text-center">
<a href="<?php echo e(route('santri.pelanggaran.show', $item->id)); ?>"
class="btn btn-info btn-sm"
title="Lihat Detail">
<i class="fas fa-eye"></i> Detail
</a>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
</div>
<div style="margin-top: 20px;">
<?php echo e($riwayat->links()); ?>
</div>
<?php else: ?>
<div class="empty-state">
<i class="fas fa-check-circle"></i>
<h3>Tidak Ada Riwayat Pelanggaran</h3>
<p>Selamat! Anda belum memiliki catatan pelanggaran.</p>
</div>
<?php endif; ?>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/santri/pelanggaran/index.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,247 @@
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-plus-circle"></i> Tambah Kegiatan Baru</h2>
</div>
<div class="form-container">
<form action="<?php echo e(route('admin.kegiatan.store')); ?>" method="POST">
<?php echo csrf_field(); ?>
<div class="form-group">
<label for="kegiatan_id">
<i class="fas fa-hashtag form-icon"></i>
ID Kegiatan (Otomatis)
</label>
<input type="text" class="form-control" value="<?php echo e($nextId); ?>" disabled>
<small class="form-text">ID akan dibuat otomatis saat disimpan</small>
</div>
<div class="form-group">
<label for="kategori_id">
<i class="fas fa-list-alt form-icon"></i>
Kategori Kegiatan <span style="color: red;">*</span>
</label>
<select name="kategori_id" id="kategori_id" class="form-control <?php $__errorArgs = ['kategori_id'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>" required>
<option value="">-- Pilih Kategori --</option>
<?php $__currentLoopData = $kategoris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kat): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($kat->kategori_id); ?>" <?php echo e(old('kategori_id') == $kat->kategori_id ? 'selected' : ''); ?>>
<?php echo e($kat->nama_kategori); ?>
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<?php $__errorArgs = ['kategori_id'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div class="form-group">
<label for="nama_kegiatan">
<i class="fas fa-calendar-check form-icon"></i>
Nama Kegiatan <span style="color: red;">*</span>
</label>
<input type="text"
name="nama_kegiatan"
id="nama_kegiatan"
class="form-control <?php $__errorArgs = ['nama_kegiatan'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
value="<?php echo e(old('nama_kegiatan')); ?>"
placeholder="Contoh: Kajian Tafsir Al-Quran"
required>
<?php $__errorArgs = ['nama_kegiatan'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div class="form-group">
<label for="hari">
<i class="fas fa-calendar-day form-icon"></i>
Hari <span style="color: red;">*</span>
</label>
<select name="hari" id="hari" class="form-control <?php $__errorArgs = ['hari'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>" required>
<option value="">-- Pilih Hari --</option>
<?php $__currentLoopData = $hariList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $h): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($h); ?>" <?php echo e(old('hari') == $h ? 'selected' : ''); ?>><?php echo e($h); ?></option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<?php $__errorArgs = ['hari'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
<div class="form-group">
<label for="waktu_mulai">
<i class="fas fa-clock form-icon"></i>
Waktu Mulai <span style="color: red;">*</span>
</label>
<input type="time"
name="waktu_mulai"
id="waktu_mulai"
class="form-control <?php $__errorArgs = ['waktu_mulai'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
value="<?php echo e(old('waktu_mulai')); ?>"
required>
<?php $__errorArgs = ['waktu_mulai'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div class="form-group">
<label for="waktu_selesai">
<i class="fas fa-clock form-icon"></i>
Waktu Selesai <span style="color: red;">*</span>
</label>
<input type="time"
name="waktu_selesai"
id="waktu_selesai"
class="form-control <?php $__errorArgs = ['waktu_selesai'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
value="<?php echo e(old('waktu_selesai')); ?>"
required>
<?php $__errorArgs = ['waktu_selesai'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
</div>
<div class="form-group">
<label for="materi">
<i class="fas fa-book form-icon"></i>
Materi/Topik
</label>
<input type="text"
name="materi"
id="materi"
class="form-control <?php $__errorArgs = ['materi'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
value="<?php echo e(old('materi')); ?>"
placeholder="Contoh: Surat Al-Baqarah Ayat 1-10">
<?php $__errorArgs = ['materi'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div class="form-group">
<label for="keterangan">
<i class="fas fa-align-left form-icon"></i>
Keterangan
</label>
<textarea name="keterangan"
id="keterangan"
class="form-control <?php $__errorArgs = ['keterangan'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
rows="4"
placeholder="Catatan tambahan tentang kegiatan ini..."><?php echo e(old('keterangan')); ?></textarea>
<?php $__errorArgs = ['keterangan'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div class="btn-group">
<button type="submit" class="btn btn-success">
<i class="fas fa-save"></i> Simpan
</button>
<a href="<?php echo e(route('admin.kegiatan.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</form>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/data/create.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,108 @@
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-id-card"></i> Daftarkan Kartu RFID</h2>
</div>
<div class="form-container">
<div class="info-box" style="margin-bottom: 25px;">
<p><i class="fas fa-info-circle"></i> Tempelkan kartu RFID ke reader, UID akan otomatis terdeteksi pada kolom di bawah.</p>
</div>
<form action="<?php echo e(route('admin.kartu-rfid.simpan', $santri->id_santri)); ?>" method="POST">
<?php echo csrf_field(); ?>
<div class="form-group">
<label><i class="fas fa-user form-icon"></i> Data Santri</label>
<table class="detail-table">
<tr>
<th>ID Santri</th>
<td><strong><?php echo e($santri->id_santri); ?></strong></td>
</tr>
<tr>
<th>Nama Lengkap</th>
<td><?php echo e($santri->nama_lengkap); ?></td>
</tr>
<tr>
<th>Kelas</th>
<td><span class="badge badge-secondary"><?php echo e($santri->kelas); ?></span></td>
</tr>
</table>
</div>
<div class="form-group">
<label for="rfid_uid">
<i class="fas fa-barcode form-icon"></i>
UID RFID <span style="color: red;">*</span>
</label>
<div style="display: flex; gap: 10px; align-items: center;">
<input type="text"
name="rfid_uid"
id="rfid_uid"
class="form-control <?php $__errorArgs = ['rfid_uid'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
value="<?php echo e(old('rfid_uid')); ?>"
placeholder="Tempelkan kartu ke reader..."
required
autofocus>
<button type="button" class="btn btn-warning" onclick="document.getElementById('rfid_uid').value = ''; document.getElementById('rfid_uid').focus();">
<i class="fas fa-redo"></i>
</button>
</div>
<?php $__errorArgs = ['rfid_uid'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
<small class="form-text">UID akan otomatis terisi saat kartu ditempelkan ke reader.</small>
</div>
<div id="scanStatus" style="padding: 15px; border-radius: var(--border-radius-sm); text-align: center; margin-bottom: 20px; display: none;"></div>
<div class="btn-group">
<button type="submit" class="btn btn-success">
<i class="fas fa-save"></i> Simpan & Daftarkan
</button>
<a href="<?php echo e(route('admin.kartu-rfid.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</form>
</div>
<script>
const rfidInput = document.getElementById('rfid_uid');
const scanStatus = document.getElementById('scanStatus');
rfidInput.addEventListener('input', function() {
if (this.value.length > 5) {
scanStatus.style.display = 'block';
scanStatus.style.background = 'linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%)';
scanStatus.style.color = 'var(--success-color)';
scanStatus.innerHTML = '<i class="fas fa-check-circle"></i> RFID Terdeteksi: <strong>' + this.value + '</strong>';
} else {
scanStatus.style.display = 'none';
}
});
// Auto-focus ke input
setInterval(() => {
if (document.activeElement !== rfidInput) {
rfidInput.focus();
}
}, 1000);
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/kartu/daftar.blade.php ENDPATH**/ ?>

View File

@ -1,184 +0,0 @@
<?php $__env->startSection('title', 'Detail Transaksi Uang Saku'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-file-invoice"></i> Detail Transaksi Uang Saku</h2>
</div>
<div class="content-box">
<div class="detail-header">
<div>
<h3><i class="fas fa-receipt"></i> Informasi Transaksi</h3>
<p class="text-muted">Detail lengkap transaksi uang saku</p>
</div>
<div style="display: flex; gap: 10px;">
<a href="<?php echo e(route('santri.uang-saku.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</div>
<div class="detail-section">
<h4><i class="fas fa-info-circle"></i> Data Transaksi</h4>
<table class="detail-table">
<tr>
<th><i class="fas fa-hashtag"></i> ID Transaksi</th>
<td><strong><?php echo e($transaksi->id_uang_saku); ?></strong></td>
</tr>
<tr>
<th><i class="fas fa-calendar"></i> Tanggal Transaksi</th>
<td><?php echo e(\Carbon\Carbon::parse($transaksi->tanggal_transaksi)->isoFormat('dddd, D MMMM YYYY')); ?></td>
</tr>
<tr>
<th><i class="fas fa-exchange-alt"></i> Jenis Transaksi</th>
<td>
<?php if($transaksi->jenis_transaksi === 'pemasukan'): ?>
<span class="badge badge-lg badge-success">
<i class="fas fa-arrow-down"></i> Pemasukan
</span>
<?php else: ?>
<span class="badge badge-lg badge-danger">
<i class="fas fa-arrow-up"></i> Pengeluaran
</span>
<?php endif; ?>
</td>
</tr>
<tr>
<th><i class="fas fa-money-bill-wave"></i> Nominal</th>
<td>
<span style="font-size: 1.3rem; font-weight: 700; color: <?php echo e($transaksi->jenis_transaksi === 'pemasukan' ? 'var(--success-color)' : 'var(--danger-color)'); ?>">
<?php echo e('Rp ' . number_format($transaksi->nominal, 0, ',', '.')); ?>
</span>
</td>
</tr>
<tr>
<th><i class="fas fa-wallet"></i> Saldo Sebelum</th>
<td><?php echo e('Rp ' . number_format($transaksi->saldo_sebelum, 0, ',', '.')); ?></td>
</tr>
<tr>
<th><i class="fas fa-wallet"></i> Saldo Sesudah</th>
<td>
<strong style="color: var(--primary-color); font-size: 1.1rem;">
<?php echo e('Rp ' . number_format($transaksi->saldo_sesudah, 0, ',', '.')); ?>
</strong>
</td>
</tr>
<tr>
<th><i class="fas fa-sticky-note"></i> Keterangan</th>
<td><?php echo e($transaksi->keterangan ?? '-'); ?></td>
</tr>
<tr>
<th><i class="fas fa-clock"></i> Dicatat Pada</th>
<td><?php echo e($transaksi->created_at->format('d/m/Y H:i:s')); ?></td>
</tr>
</table>
</div>
<div class="detail-section">
<h4><i class="fas fa-user-graduate"></i> Data Santri</h4>
<table class="detail-table">
<tr>
<th><i class="fas fa-id-card"></i> ID Santri</th>
<td><?php echo e($transaksi->santri->id_santri); ?></td>
</tr>
<tr>
<th><i class="fas fa-user"></i> Nama Lengkap</th>
<td><?php echo e($transaksi->santri->nama_lengkap); ?></td>
</tr>
<tr>
<th><i class="fas fa-chalkboard-teacher"></i> Kelas</th>
<td><?php echo e($transaksi->santri->kelas); ?></td>
</tr>
</table>
</div>
<div class="detail-section">
<h4><i class="fas fa-chart-line"></i> Visualisasi Transaksi</h4>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px;">
<div style="background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); padding: 20px; border-radius: 12px; text-align: center;">
<i class="fas fa-arrow-down" style="font-size: 2rem; color: var(--success-color); margin-bottom: 10px;"></i>
<h5 style="margin: 0 0 5px 0; color: var(--text-light); font-size: 0.9rem;">Nominal Pemasukan</h5>
<p style="font-size: 1.5rem; font-weight: 700; color: var(--success-color); margin: 0;">
<?php echo e($transaksi->jenis_transaksi === 'pemasukan' ? 'Rp ' . number_format($transaksi->nominal, 0, ',', '.') : 'Rp 0'); ?>
</p>
</div>
<div style="background: linear-gradient(135deg, #FFE8EA 0%, #FFD5D8 100%); padding: 20px; border-radius: 12px; text-align: center;">
<i class="fas fa-arrow-up" style="font-size: 2rem; color: var(--danger-color); margin-bottom: 10px;"></i>
<h5 style="margin: 0 0 5px 0; color: var(--text-light); font-size: 0.9rem;">Nominal Pengeluaran</h5>
<p style="font-size: 1.5rem; font-weight: 700; color: var(--danger-color); margin: 0;">
<?php echo e($transaksi->jenis_transaksi === 'pengeluaran' ? 'Rp ' . number_format($transaksi->nominal, 0, ',', '.') : 'Rp 0'); ?>
</p>
</div>
</div>
<div style="background: white; padding: 20px; border-radius: 12px; border: 2px solid var(--primary-light);">
<h5 style="margin: 0 0 15px 0; color: var(--text-color); font-size: 1rem;">
<i class="fas fa-wallet"></i> Perubahan Saldo
</h5>
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
<span style="font-size: 0.9rem; color: var(--text-light);">Saldo Sebelum</span>
<strong style="color: var(--text-color);"><?php echo e('Rp ' . number_format($transaksi->saldo_sebelum, 0, ',', '.')); ?></strong>
</div>
<?php
$maxSaldo = max($transaksi->saldo_sebelum, $transaksi->saldo_sesudah);
$persentaseSebelum = $maxSaldo > 0 ? ($transaksi->saldo_sebelum / $maxSaldo) * 100 : 0;
$persentaseSesudah = $maxSaldo > 0 ? ($transaksi->saldo_sesudah / $maxSaldo) * 100 : 0;
?>
<div style="position: relative; height: 40px; background: #e0e0e0; border-radius: 20px; overflow: hidden; margin-bottom: 10px;">
<div style="position: absolute; height: 100%; background: linear-gradient(90deg, var(--primary-color), var(--primary-dark)); width: <?php echo e($persentaseSebelum); ?>%; border-radius: 20px; display: flex; align-items: center; justify-content: center; color: white; font-weight: 600; font-size: 0.85rem;">
<?php if($persentaseSebelum > 15): ?>
<?php echo e(number_format($persentaseSebelum, 0)); ?>%
<?php endif; ?>
</div>
</div>
<div style="text-align: center; margin: 15px 0;">
<i class="fas fa-arrow-<?php echo e($transaksi->jenis_transaksi === 'pemasukan' ? 'up' : 'down'); ?>"
style="font-size: 1.5rem; color: <?php echo e($transaksi->jenis_transaksi === 'pemasukan' ? 'var(--success-color)' : 'var(--danger-color)'); ?>;"></i>
<p style="margin: 5px 0 0 0; font-size: 0.85rem; color: var(--text-light);">
<?php echo e($transaksi->jenis_transaksi === 'pemasukan' ? 'Bertambah' : 'Berkurang'); ?>
<strong><?php echo e('Rp ' . number_format(abs($transaksi->saldo_sesudah - $transaksi->saldo_sebelum), 0, ',', '.')); ?></strong>
</p>
</div>
<div style="position: relative; height: 40px; background: #e0e0e0; border-radius: 20px; overflow: hidden; margin-bottom: 10px;">
<div style="position: absolute; height: 100%; background: linear-gradient(90deg, <?php echo e($transaksi->jenis_transaksi === 'pemasukan' ? 'var(--success-color)' : 'var(--danger-color)'); ?>, <?php echo e($transaksi->jenis_transaksi === 'pemasukan' ? '#4CAF50' : '#E77580'); ?>); width: <?php echo e($persentaseSesudah); ?>%; border-radius: 20px; display: flex; align-items: center; justify-content: center; color: white; font-weight: 600; font-size: 0.85rem;">
<?php if($persentaseSesudah > 15): ?>
<?php echo e(number_format($persentaseSesudah, 0)); ?>%
<?php endif; ?>
</div>
</div>
<div style="display: flex; justify-content: space-between;">
<span style="font-size: 0.9rem; color: var(--text-light);">Saldo Sesudah</span>
<strong style="color: <?php echo e($transaksi->jenis_transaksi === 'pemasukan' ? 'var(--success-color)' : 'var(--danger-color)'); ?>; font-size: 1.1rem;">
<?php echo e('Rp ' . number_format($transaksi->saldo_sesudah, 0, ',', '.')); ?>
</strong>
</div>
</div>
</div>
<div style="margin-top: 30px; padding-top: 20px; border-top: 2px solid var(--primary-light); text-align: center;">
<a href="<?php echo e(route('santri.uang-saku.index')); ?>" class="btn btn-primary btn-lg">
<i class="fas fa-list"></i> Lihat Semua Riwayat
</a>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/santri/uang-saku/show.blade.php ENDPATH**/ ?>

View File

@ -1,295 +0,0 @@
<?php $__env->startSection('title', 'Detail Riwayat Pelanggaran'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-info-circle"></i> Detail Riwayat Pelanggaran</h2>
</div>
<!-- Breadcrumb -->
<div style="margin-bottom: 20px;">
<nav style="display: flex; align-items: center; gap: 8px; color: var(--text-light); font-size: 0.9em;">
<a href="<?php echo e(route('admin.riwayat-pelanggaran.index')); ?>" style="color: var(--primary-color); text-decoration: none;">
<i class="fas fa-history"></i> Riwayat Pelanggaran
</a>
<i class="fas fa-chevron-right" style="font-size: 0.7em;"></i>
<span>Detail</span>
</nav>
</div>
<div style="display: grid; grid-template-columns: 2fr 1fr; gap: 30px;">
<!-- Detail Riwayat -->
<div>
<div class="content-box">
<div class="detail-header">
<h3><i class="fas fa-clipboard-list"></i> Informasi Riwayat</h3>
<div style="display: flex; gap: 10px;">
<a href="<?php echo e(route('admin.riwayat-pelanggaran.edit', $riwayatPelanggaran)); ?>" class="btn btn-warning btn-sm">
<i class="fas fa-edit"></i> Edit
</a>
<a href="<?php echo e(route('admin.riwayat-pelanggaran.index')); ?>" class="btn btn-secondary btn-sm">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</div>
<table class="detail-table">
<tr>
<th><i class="fas fa-tag"></i> ID Riwayat</th>
<td>
<span class="badge badge-secondary" style="font-size: 1em;">
<?php echo e($riwayatPelanggaran->id_riwayat); ?>
</span>
</td>
</tr>
<tr>
<th><i class="fas fa-calendar"></i> Tanggal Pelanggaran</th>
<td>
<strong style="font-size: 1.1em;">
<?php echo e(\Carbon\Carbon::parse($riwayatPelanggaran->tanggal)->isoFormat('dddd, D MMMM YYYY')); ?>
</strong>
</td>
</tr>
<tr>
<th><i class="fas fa-fire"></i> Poin Pelanggaran</th>
<td>
<span class="badge badge-danger" style="font-size: 1.2em; padding: 10px 20px;">
<i class="fas fa-star"></i> <?php echo e($riwayatPelanggaran->poin); ?> Poin
</span>
</td>
</tr>
<tr>
<th><i class="fas fa-calendar-plus"></i> Tanggal Dicatat</th>
<td><?php echo e($riwayatPelanggaran->created_at->format('d F Y, H:i')); ?> WIB</td>
</tr>
<tr>
<th><i class="fas fa-calendar-check"></i> Terakhir Diperbarui</th>
<td><?php echo e($riwayatPelanggaran->updated_at->format('d F Y, H:i')); ?> WIB</td>
</tr>
</table>
</div>
<!-- Data Santri -->
<div class="content-box" style="margin-top: 30px;">
<h3 style="margin-bottom: 20px; color: var(--primary-color);">
<i class="fas fa-user"></i> Data Santri
</h3>
<?php if($riwayatPelanggaran->santri): ?>
<table class="detail-table">
<tr>
<th><i class="fas fa-id-card"></i> ID Santri</th>
<td>
<span class="badge badge-primary"><?php echo e($riwayatPelanggaran->santri->id_santri); ?></span>
</td>
</tr>
<tr>
<th><i class="fas fa-user"></i> Nama Lengkap</th>
<td>
<strong style="font-size: 1.1em;"><?php echo e($riwayatPelanggaran->santri->nama_lengkap); ?></strong>
</td>
</tr>
<tr>
<th><i class="fas fa-graduation-cap"></i> Kelas</th>
<td><?php echo e($riwayatPelanggaran->santri->kelas); ?></td>
</tr>
<tr>
<th><i class="fas fa-hashtag"></i> NIS</th>
<td><?php echo e($riwayatPelanggaran->santri->nis); ?></td>
</tr>
<tr>
<th><i class="fas fa-chart-line"></i> Total Poin Pelanggaran</th>
<td>
<span class="badge badge-danger" style="font-size: 1em;">
<?php echo e($riwayatPelanggaran->santri->total_poin_pelanggaran); ?> Poin
</span>
</td>
</tr>
</table>
<div style="margin-top: 15px;">
<a href="<?php echo e(route('admin.santri.show', $riwayatPelanggaran->santri)); ?>" class="btn btn-primary" style="width: 100%;">
<i class="fas fa-eye"></i> Lihat Detail Santri
</a>
</div>
<?php else: ?>
<div style="text-align: center; padding: 30px; color: var(--danger-color);">
<i class="fas fa-exclamation-triangle" style="font-size: 3em; margin-bottom: 15px;"></i>
<p>Data santri tidak ditemukan</p>
</div>
<?php endif; ?>
</div>
<!-- Kategori Pelanggaran -->
<div class="content-box" style="margin-top: 30px;">
<h3 style="margin-bottom: 20px; color: var(--primary-color);">
<i class="fas fa-tags"></i> Kategori Pelanggaran
</h3>
<?php if($riwayatPelanggaran->kategori): ?>
<table class="detail-table">
<tr>
<th><i class="fas fa-tag"></i> ID Kategori</th>
<td>
<span class="badge badge-primary"><?php echo e($riwayatPelanggaran->kategori->id_kategori); ?></span>
</td>
</tr>
<tr>
<th><i class="fas fa-exclamation-triangle"></i> Nama Pelanggaran</th>
<td>
<strong style="font-size: 1.1em;"><?php echo e($riwayatPelanggaran->kategori->nama_pelanggaran); ?></strong>
</td>
</tr>
<tr>
<th><i class="fas fa-star"></i> Poin Kategori</th>
<td>
<span class="badge badge-danger" style="font-size: 1em;">
<?php echo e($riwayatPelanggaran->kategori->poin); ?> Poin
</span>
</td>
</tr>
</table>
<div style="margin-top: 15px;">
<a href="<?php echo e(route('admin.kategori-pelanggaran.show', $riwayatPelanggaran->kategori)); ?>" class="btn btn-primary" style="width: 100%;">
<i class="fas fa-eye"></i> Lihat Detail Kategori
</a>
</div>
<?php else: ?>
<div style="text-align: center; padding: 30px; color: var(--danger-color);">
<i class="fas fa-exclamation-triangle" style="font-size: 3em; margin-bottom: 15px;"></i>
<p>Kategori tidak ditemukan</p>
</div>
<?php endif; ?>
</div>
<!-- Keterangan -->
<?php if($riwayatPelanggaran->keterangan): ?>
<div class="content-box" style="margin-top: 30px;">
<h3 style="margin-bottom: 15px; color: var(--primary-color);">
<i class="fas fa-comment"></i> Keterangan Tambahan
</h3>
<div style="background: var(--bg-color); padding: 15px; border-radius: var(--border-radius-sm); border-left: 4px solid var(--primary-color);">
<p style="margin: 0; line-height: 1.6;"><?php echo e($riwayatPelanggaran->keterangan); ?></p>
</div>
</div>
<?php endif; ?>
<!-- Riwayat Pelanggaran Lainnya -->
<?php if($riwayatLainnya->isNotEmpty()): ?>
<div class="content-box" style="margin-top: 30px;">
<h3 style="margin-bottom: 20px; color: var(--primary-color);">
<i class="fas fa-history"></i> Riwayat Pelanggaran Lainnya (Santri yang Sama)
</h3>
<table class="data-table">
<thead>
<tr>
<th style="width: 50px;">No</th>
<th>Tanggal</th>
<th>Kategori</th>
<th style="text-align: center;">Poin</th>
<th style="width: 100px; text-align: center;">Aksi</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $riwayatLainnya; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $riwayat): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><?php echo e($index + 1); ?></td>
<td><?php echo e(\Carbon\Carbon::parse($riwayat->tanggal)->format('d M Y')); ?></td>
<td>
<?php if($riwayat->kategori): ?>
<strong><?php echo e($riwayat->kategori->nama_pelanggaran); ?></strong>
<?php else: ?>
<span style="color: var(--danger-color);">-</span>
<?php endif; ?>
</td>
<td style="text-align: center;">
<span class="badge badge-danger"><?php echo e($riwayat->poin); ?></span>
</td>
<td style="text-align: center;">
<a href="<?php echo e(route('admin.riwayat-pelanggaran.show', $riwayat)); ?>" class="btn btn-sm btn-success">
<i class="fas fa-eye"></i>
</a>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
<div style="text-align: center; margin-top: 15px;">
<a href="<?php echo e(route('admin.riwayat-pelanggaran.index')); ?>?id_santri=<?php echo e($riwayatPelanggaran->id_santri); ?>" class="btn btn-primary">
<i class="fas fa-list"></i> Lihat Semua Riwayat Santri Ini
</a>
</div>
</div>
<?php endif; ?>
</div>
<!-- Sidebar -->
<div>
<!-- Quick Actions -->
<div class="card card-primary">
<h3 style="margin-bottom: 15px;">
<i class="fas fa-bolt"></i> Aksi Cepat
</h3>
<div style="display: flex; flex-direction: column; gap: 10px;">
<a href="<?php echo e(route('admin.riwayat-pelanggaran.edit', $riwayatPelanggaran)); ?>" class="btn btn-warning" style="width: 100%;">
<i class="fas fa-edit"></i> Edit Riwayat
</a>
<a href="<?php echo e(route('admin.riwayat-pelanggaran.create')); ?>" class="btn btn-primary" style="width: 100%;">
<i class="fas fa-plus"></i> Tambah Riwayat Baru
</a>
<a href="<?php echo e(route('admin.riwayat-pelanggaran.index')); ?>" class="btn btn-secondary" style="width: 100%;">
<i class="fas fa-list"></i> Semua Riwayat
</a>
<?php if($riwayatPelanggaran->santri): ?>
<a href="<?php echo e(route('admin.santri.show', $riwayatPelanggaran->santri)); ?>" class="btn btn-success" style="width: 100%;">
<i class="fas fa-user"></i> Lihat Santri
</a>
<?php endif; ?>
</div>
</div>
<!-- Statistik Poin -->
<div class="card card-danger" style="margin-top: 20px;">
<h3 style="margin-bottom: 15px;">
<i class="fas fa-fire"></i> Poin Pelanggaran
</h3>
<div style="text-align: center;">
<div class="card-value" style="color: var(--danger-color);"><?php echo e($riwayatPelanggaran->poin); ?></div>
<p style="margin: 0; color: var(--text-light);">Poin Pelanggaran Ini</p>
</div>
<?php if($riwayatPelanggaran->santri): ?>
<div style="margin-top: 20px; padding-top: 20px; border-top: 1px solid rgba(255, 139, 148, 0.3);">
<div style="text-align: center;">
<div class="card-value-small" style="color: var(--danger-color);">
<?php echo e($riwayatPelanggaran->santri->total_poin_pelanggaran); ?>
</div>
<p style="margin: 0; color: var(--text-light);">Total Poin Santri</p>
</div>
</div>
<?php endif; ?>
</div>
<!-- Info Box -->
<div class="card card-info" style="margin-top: 20px;">
<h3 style="margin-bottom: 10px;">
<i class="fas fa-info-circle"></i> Informasi
</h3>
<p style="font-size: 0.9em; line-height: 1.6; margin: 0; color: var(--text-color);">
Riwayat ini dicatat pada <strong><?php echo e($riwayatPelanggaran->created_at->format('d F Y')); ?></strong>
untuk pelanggaran yang terjadi pada <strong><?php echo e(\Carbon\Carbon::parse($riwayatPelanggaran->tanggal)->format('d F Y')); ?></strong>.
</p>
</div>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/riwayat_pelanggaran/show.blade.php ENDPATH**/ ?>

View File

@ -1,185 +0,0 @@
<?php $__env->startSection('title', 'Detail Kepulangan'); ?>
<?php $__env->startSection('content'); ?>
<div class="content-box">
<div class="detail-header">
<div>
<h3>Detail Izin Kepulangan</h3>
<p style="margin: 5px 0 0 0; color: var(--text-light);">
ID: <strong><?php echo e($kepulangan->id_kepulangan); ?></strong>
</p>
</div>
<a href="<?php echo e(route('santri.kepulangan.index')); ?>" class="btn btn-secondary btn-sm hover-lift">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
<hr style="border: none; border-top: 2px solid var(--primary-light); margin: 20px 0;">
<div style="text-align: center; margin: 20px 0;">
<span class="badge badge-<?php echo e($kepulangan->status == 'Menunggu' ? 'warning' :
($kepulangan->status == 'Disetujui' ? 'success' :
($kepulangan->status == 'Ditolak' ? 'danger' : 'secondary'))); ?> badge-lg">
<i class="fas
<?php if($kepulangan->status == 'Menunggu'): ?> fa-clock
<?php elseif($kepulangan->status == 'Disetujui'): ?> fa-check-circle
<?php elseif($kepulangan->status == 'Ditolak'): ?> fa-times-circle
<?php else: ?> fa-flag-checkered <?php endif; ?>
"></i>
Status: <?php echo e($kepulangan->status); ?>
</span>
<?php if($kepulangan->status == 'Disetujui' && $kepulangan->is_aktif): ?>
<span class="badge badge-info badge-lg" style="margin-left: 10px;">
<i class="fas fa-home"></i> Sedang Dalam Periode Pulang
</span>
<?php elseif($kepulangan->status == 'Disetujui' && $kepulangan->is_terlambat): ?>
<span class="badge badge-danger badge-lg" style="margin-left: 10px;">
<i class="fas fa-exclamation-triangle"></i> Terlambat Kembali
</span>
<?php endif; ?>
</div>
<table class="detail-table">
<tr>
<th><i class="fas fa-code"></i> ID Kepulangan</th>
<td><?php echo e($kepulangan->id_kepulangan); ?></td>
</tr>
<tr>
<th><i class="fas fa-calendar-plus"></i> Tanggal Pengajuan</th>
<td><?php echo e($kepulangan->tanggal_izin_formatted); ?></td>
</tr>
<tr>
<th><i class="fas fa-calendar-alt"></i> Tanggal Pulang</th>
<td><strong style="color: var(--primary-color);"><?php echo e($kepulangan->tanggal_pulang_formatted); ?></strong></td>
</tr>
<tr>
<th><i class="fas fa-calendar-check"></i> Tanggal Kembali</th>
<td><strong style="color: var(--primary-color);"><?php echo e($kepulangan->tanggal_kembali_formatted); ?></strong></td>
</tr>
<tr>
<th><i class="fas fa-clock"></i> Durasi Izin</th>
<td>
<span class="badge badge-info"><?php echo e($kepulangan->durasi_izin); ?> hari</span>
</td>
</tr>
<tr>
<th><i class="fas fa-comment-alt"></i> Alasan Kepulangan</th>
<td><strong><?php echo e($kepulangan->alasan); ?></strong></td>
</tr>
<tr>
<th><i class="fas fa-info-circle"></i> Status</th>
<td>
<span class="badge badge-<?php echo e($kepulangan->status == 'Menunggu' ? 'warning' :
($kepulangan->status == 'Disetujui' ? 'success' :
($kepulangan->status == 'Ditolak' ? 'danger' : 'secondary'))); ?>">
<?php echo e($kepulangan->status); ?>
</span>
</td>
</tr>
<?php if($kepulangan->approved_by): ?>
<tr>
<th><i class="fas fa-user-check"></i> Disetujui Oleh</th>
<td><?php echo e($kepulangan->approved_by); ?></td>
</tr>
<tr>
<th><i class="fas fa-calendar-check"></i> Tanggal Persetujuan</th>
<td><?php echo e($kepulangan->approved_at_formatted); ?></td>
</tr>
<?php endif; ?>
<?php if($kepulangan->catatan): ?>
<tr>
<th><i class="fas fa-sticky-note"></i> Catatan Admin</th>
<td style="white-space: pre-wrap;"><?php echo e($kepulangan->catatan); ?></td>
</tr>
<?php endif; ?>
</table>
<div style="margin-top: 25px; padding: 20px; background: linear-gradient(135deg, #E3F2FD, #D1E9F9); border-radius: var(--border-radius-sm); border-left: 4px solid var(--info-color);">
<h4 style="margin: 0 0 10px 0; color: var(--info-color);">
<i class="fas fa-chart-bar"></i> Informasi Kuota Tahun <?php echo e(date('Y')); ?>
</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 15px;">
<div>
<p style="margin: 0; font-size: 0.85rem; color: var(--text-light);">Total Hari Pulang</p>
<p style="margin: 5px 0 0 0; font-size: 1.3rem; font-weight: 700; color: var(--primary-color);">
<?php echo e($totalHariTahunIni); ?> hari
</p>
</div>
<div>
<p style="margin: 0; font-size: 0.85rem; color: var(--text-light);">Sisa Kuota</p>
<p style="margin: 5px 0 0 0; font-size: 1.3rem; font-weight: 700;color: <?php echo e($sisaKuota > 0 ? 'var(--success-color)' : 'var(--danger-color)'); ?>;">
<?php echo e($sisaKuota); ?> hari
</p>
</div>
<div>
<p style="margin: 0; font-size: 0.85rem; color: var(--text-light);">Kuota Maksimal</p>
<p style="margin: 5px 0 0 0; font-size: 1.3rem; font-weight: 700; color: var(--text-color);">
12 hari
</p>
</div>
</div>
</div>
</div>
<?php if($kepulangan->status == 'Menunggu'): ?>
<div class="info-box" style="margin-top: 20px; background: linear-gradient(135deg, #FFF8E1 0%, #FFF3CD 100%); border-color: var(--warning-color);">
<i class="fas fa-clock"></i>
<strong>Menunggu Persetujuan:</strong> Izin kepulangan Anda sedang dalam proses review.
Mohon tunggu konfirmasi dari pengurus.
</div>
<?php elseif($kepulangan->status == 'Disetujui'): ?>
<?php if($kepulangan->is_aktif): ?>
<div class="info-box" style="margin-top: 20px; background: linear-gradient(135deg, #E3F2FD 0%, #D1E9F9 100%); border-color: var(--info-color);">
<i class="fas fa-home"></i>
<strong>Sedang Pulang:</strong> Anda sedang dalam periode kepulangan.
Pastikan kembali sesuai jadwal: <strong><?php echo e($kepulangan->tanggal_kembali_formatted); ?></strong>.
</div>
<?php elseif($kepulangan->is_terlambat): ?>
<div class="alert alert-danger" style="margin-top: 20px;">
<i class="fas fa-exclamation-triangle"></i>
<strong>Terlambat Kembali:</strong> Anda telah melewati tanggal kembali yang dijadwalkan.
Segera hubungi pengurus!
</div>
<?php else: ?>
<div class="info-box" style="margin-top: 20px; background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); border-color: var(--success-color);">
<i class="fas fa-check-circle"></i>
<strong>Izin Disetujui:</strong> Kepulangan Anda telah disetujui.
Pastikan untuk pulang dan kembali sesuai jadwal yang telah ditentukan.
</div>
<?php endif; ?>
<?php elseif($kepulangan->status == 'Ditolak'): ?>
<div class="alert alert-danger" style="margin-top: 20px;">
<i class="fas fa-times-circle"></i>
<strong>Izin Ditolak:</strong> Maaf, izin kepulangan Anda tidak disetujui.
<?php if($kepulangan->catatan): ?>
Alasan: <strong><?php echo e($kepulangan->catatan); ?></strong>
<?php endif; ?>
</div>
<?php elseif($kepulangan->status == 'Selesai'): ?>
<div class="info-box" style="margin-top: 20px; background: linear-gradient(135deg, #E2E3E5 0%, #D6D8DB 100%); border-color: var(--text-light);">
<i class="fas fa-flag-checkered"></i>
<strong>Kepulangan Selesai:</strong> Anda telah menyelesaikan periode kepulangan ini.
</div>
<?php endif; ?>
<div style="margin-top: 20px; text-align: center;">
<a href="<?php echo e(route('santri.kepulangan.index')); ?>" class="btn btn-primary hover-lift">
<i class="fas fa-list"></i> Lihat Semua Riwayat
</a>
<a href="<?php echo e(route('santri.dashboard')); ?>" class="btn btn-secondary hover-lift">
<i class="fas fa-home"></i> Kembali ke Dashboard
</a>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/santri/kepulangan/show.blade.php ENDPATH**/ ?>

File diff suppressed because one or more lines are too long

View File

@ -1,134 +0,0 @@
<?php $__env->startSection('title', 'Riwayat Uang Saku'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-wallet"></i> Riwayat Uang Saku</h2>
</div>
<?php if(session('success')): ?>
<div class="alert alert-success">
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
</div>
<?php endif; ?>
<?php if(session('error')): ?>
<div class="alert alert-danger">
<i class="fas fa-exclamation-circle"></i> <?php echo e(session('error')); ?>
</div>
<?php endif; ?>
<div class="row-cards">
<div class="card card-success">
<h3><i class="fas fa-arrow-down"></i> Total Pemasukan</h3>
<div class="card-value"><?php echo e('Rp ' . number_format($totalPemasukan, 0, ',', '.')); ?></div>
<div class="card-icon"><i class="fas fa-arrow-down"></i></div>
</div>
<div class="card card-danger">
<h3><i class="fas fa-arrow-up"></i> Total Pengeluaran</h3>
<div class="card-value"><?php echo e('Rp ' . number_format($totalPengeluaran, 0, ',', '.')); ?></div>
<div class="card-icon"><i class="fas fa-arrow-up"></i></div>
</div>
<div class="card card-primary">
<h3><i class="fas fa-wallet"></i> Saldo Terakhir</h3>
<div class="card-value"><?php echo e('Rp ' . number_format($saldoTerakhir, 0, ',', '.')); ?></div>
<div class="card-icon"><i class="fas fa-wallet"></i></div>
</div>
</div>
<div class="content-box" style="margin-top: 20px;">
<form method="GET" action="<?php echo e(route('santri.uang-saku.index')); ?>" class="filter-form-inline">
<input type="text" name="search" class="form-control" placeholder="Cari keterangan..." value="<?php echo e(request('search')); ?>" style="min-width: 200px;">
<select name="jenis_transaksi" class="form-control" style="min-width: 150px;">
<option value="">Semua Jenis</option>
<option value="pemasukan" <?php echo e(request('jenis_transaksi') == 'pemasukan' ? 'selected' : ''); ?>>Pemasukan</option>
<option value="pengeluaran" <?php echo e(request('jenis_transaksi') == 'pengeluaran' ? 'selected' : ''); ?>>Pengeluaran</option>
</select>
<input type="date" name="tanggal_dari" class="form-control" value="<?php echo e(request('tanggal_dari')); ?>" placeholder="Dari Tanggal">
<input type="date" name="tanggal_sampai" class="form-control" value="<?php echo e(request('tanggal_sampai')); ?>" placeholder="Sampai Tanggal">
<button type="submit" class="btn btn-primary">
<i class="fas fa-filter"></i> Filter
</button>
<a href="<?php echo e(route('santri.uang-saku.index')); ?>" class="btn btn-secondary">
<i class="fas fa-redo"></i> Reset
</a>
</form>
</div>
<div class="table-container" style="margin-top: 20px;">
<?php if($riwayatUangSaku->count() > 0): ?>
<table class="data-table">
<thead>
<tr>
<th>No</th>
<th>ID Transaksi</th>
<th>Tanggal</th>
<th>Jenis</th>
<th>Nominal</th>
<th>Keterangan</th>
<th>Saldo Sebelum</th>
<th>Saldo Sesudah</th>
<th class="text-center">Aksi</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $riwayatUangSaku; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $transaksi): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><?php echo e($riwayatUangSaku->firstItem() + $index); ?></td>
<td><strong><?php echo e($transaksi->id_uang_saku); ?></strong></td>
<td><?php echo e(\Carbon\Carbon::parse($transaksi->tanggal_transaksi)->format('d/m/Y')); ?></td>
<td>
<?php if($transaksi->jenis_transaksi === 'pemasukan'): ?>
<span class="badge badge-success">
<i class="fas fa-arrow-down"></i> Pemasukan
</span>
<?php else: ?>
<span class="badge badge-danger">
<i class="fas fa-arrow-up"></i> Pengeluaran
</span>
<?php endif; ?>
</td>
<td class="nominal-highlight"><?php echo e('Rp ' . number_format($transaksi->nominal, 0, ',', '.')); ?></td>
<td><?php echo e($transaksi->keterangan ?? '-'); ?></td>
<td><?php echo e('Rp ' . number_format($transaksi->saldo_sebelum, 0, ',', '.')); ?></td>
<td><?php echo e('Rp ' . number_format($transaksi->saldo_sesudah, 0, ',', '.')); ?></td>
<td class="text-center">
<a href="<?php echo e(route('santri.uang-saku.show', $transaksi->id)); ?>" class="btn btn-sm btn-primary" title="Lihat Detail">
<i class="fas fa-eye"></i> Detail
</a>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
<div style="margin-top: 20px;">
<?php echo e($riwayatUangSaku->links()); ?>
</div>
<?php else: ?>
<div class="empty-state">
<i class="fas fa-inbox"></i>
<h3>Belum Ada Transaksi</h3>
<p>Riwayat uang saku Anda masih kosong.</p>
</div>
<?php endif; ?>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/santri/uang-saku/index.blade.php ENDPATH**/ ?>

View File

@ -1,195 +0,0 @@
<?php $__env->startSection('title', 'Detail Berita - ' . $berita->id_berita); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-newspaper"></i> Detail Berita</h2>
</div>
<!-- Header Actions -->
<div class="content-box" style="margin-bottom: 20px;">
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;">
<div>
<span class="badge <?php echo e($berita->status_badge); ?>" style="font-size: 1em; padding: 8px 15px;">
<?php if($berita->status === 'published'): ?>
<i class="fas fa-check-circle"></i> Published
<?php else: ?>
<i class="fas fa-edit"></i> Draft
<?php endif; ?>
</span>
</div>
<div style="display: flex; gap: 10px;">
<a href="<?php echo e(route('admin.berita.edit', $berita->id_berita)); ?>" class="btn btn-warning">
<i class="fas fa-edit"></i> Edit
</a>
<a href="<?php echo e(route('admin.berita.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</div>
</div>
<!-- Detail Berita -->
<div class="content-box">
<div style="padding: 10px;">
<!-- Header Berita -->
<div style="border-bottom: 3px solid var(--primary-color); padding-bottom: 25px; margin-bottom: 30px;">
<div style="margin-bottom: 15px;">
<span style="background: var(--primary-light); color: var(--primary-dark); padding: 6px 12px; border-radius: var(--border-radius-sm); font-weight: 600; font-size: 0.9em;">
ID: <?php echo e($berita->id_berita); ?>
</span>
</div>
<h1 style="color: var(--primary-dark); margin-bottom: 20px; font-size: 2em; line-height: 1.3;">
<?php echo e($berita->judul); ?>
</h1>
<div style="display: flex; flex-wrap: wrap; gap: 20px; align-items: center; color: var(--text-light); font-size: 0.95em;">
<span>
<i class="fas fa-user"></i>
<strong>Penulis:</strong> <?php echo e($berita->penulis); ?>
</span>
<span>
<i class="fas fa-calendar"></i>
<strong>Tanggal:</strong> <?php echo e($berita->created_at->format('d M Y, H:i')); ?> WIB
</span>
<span>
<?php
$badgeClass = match($berita->target_berita) {
'semua' => 'badge-primary',
'kelas_tertentu' => 'badge-info',
'santri_tertentu' => 'badge-warning',
default => 'badge-secondary'
};
?>
<span class="badge <?php echo e($badgeClass); ?>">
<i class="fas fa-bullseye"></i> <?php echo e($berita->target_audience); ?>
</span>
</span>
</div>
</div>
<!-- Gambar Berita -->
<?php if($berita->gambar): ?>
<div style="text-align: center; margin: 40px 0;">
<img src="<?php echo e(asset('storage/' . $berita->gambar)); ?>"
alt="Gambar Berita"
style="max-width: 100%; max-height: 500px; border-radius: var(--border-radius); box-shadow: var(--shadow-lg); object-fit: cover;">
</div>
<?php endif; ?>
<!-- Konten Berita -->
<div class="detail-section">
<h4><i class="fas fa-align-left"></i> Konten Berita</h4>
<div style="line-height: 1.9; font-size: 1.05em; color: var(--text-color); background: var(--primary-light); padding: 25px; border-radius: var(--border-radius-sm); border-left: 4px solid var(--primary-color);">
<?php echo nl2br(e($berita->konten)); ?>
</div>
</div>
<!-- Info Target Santri -->
<?php if($berita->target_berita === 'santri_tertentu' || $berita->target_berita === 'kelas_tertentu'): ?>
<div class="detail-section">
<?php if($berita->target_berita === 'kelas_tertentu'): ?>
<h4>
<i class="fas fa-graduation-cap"></i>
Target Kelas: <?php echo e(implode(', ', $berita->target_kelas ?? [])); ?>
</h4>
<div style="background: var(--info-color); background: linear-gradient(135deg, #E3F2FD 0%, #D1E9F9 100%); padding: 20px; border-radius: var(--border-radius-sm); border-left: 4px solid var(--info-color);">
<p style="margin: 0; color: var(--text-color); font-size: 1em;">
<i class="fas fa-info-circle"></i>
Berita ini ditujukan untuk santri dari kelas:
<strong><?php echo e(implode(', ', $berita->target_kelas ?? [])); ?></strong>
</p>
</div>
<?php endif; ?>
<?php if($berita->santriTertentu->count() > 0): ?>
<h4 style="margin-top: 25px;">
<i class="fas fa-users"></i>
Daftar Penerima Berita (<?php echo e($berita->santriTertentu->count()); ?> Santri)
</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;">
<?php $__currentLoopData = $berita->santriTertentu; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<div style="background: white; border: 2px solid var(--primary-light); border-radius: var(--border-radius-sm); padding: 15px; transition: all 0.3s ease; box-shadow: var(--shadow-sm);">
<div style="display: flex; align-items: center; gap: 15px;">
<!-- Hanya tampilkan initial, tanpa foto -->
<div style="width: 60px; height: 60px; border-radius: 50%; background: var(--primary-color); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 1.5em; flex-shrink: 0;">
<?php echo e(strtoupper(substr($santri->nama_lengkap, 0, 1))); ?>
</div>
<div style="flex-grow: 1; min-width: 0;">
<div style="font-weight: 600; color: var(--primary-color); margin-bottom: 3px;">
<?php echo e($santri->id_santri); ?>
</div>
<div style="font-weight: 600; color: var(--text-color); font-size: 1em; margin-bottom: 3px;">
<?php echo e($santri->nama_lengkap); ?>
</div>
<div style="font-size: 0.85em; color: var(--text-light);">
<i class="fas fa-graduation-cap"></i> <?php echo e($santri->kelas); ?>
</div>
</div>
<!-- Status Baca -->
<div style="text-align: center; flex-shrink: 0;">
<?php if($santri->pivot->sudah_dibaca): ?>
<span class="badge badge-success" title="Dibaca pada <?php echo e($santri->pivot->tanggal_baca); ?>">
<i class="fas fa-check"></i> Dibaca
</span>
<?php else: ?>
<span class="badge badge-warning">
<i class="fas fa-clock"></i> Belum
</span>
<?php endif; ?>
</div>
</div>
</div>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</div>
<?php else: ?>
<div style="text-align: center; padding: 40px; background: var(--primary-light); border-radius: var(--border-radius-sm);">
<i class="fas fa-users" style="font-size: 3em; color: #ccc; margin-bottom: 15px;"></i>
<p style="color: var(--text-light); margin: 0;">Belum ada santri yang dipilih untuk berita ini.</p>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
<!-- Aksi -->
<div style="border-top: 2px solid var(--primary-light); padding-top: 30px; margin-top: 40px; text-align: center;">
<div style="display: flex; justify-content: center; gap: 10px; flex-wrap: wrap;">
<a href="<?php echo e(route('admin.berita.edit', $berita->id_berita)); ?>" class="btn btn-warning">
<i class="fas fa-edit"></i> Edit Berita
</a>
<form action="<?php echo e(route('admin.berita.destroy', $berita->id_berita)); ?>"
method="POST"
style="display: inline;"
onsubmit="return confirm('Yakin ingin menghapus berita ini? Tindakan ini tidak dapat dibatalkan!')">
<?php echo csrf_field(); ?>
<?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-danger">
<i class="fas fa-trash"></i> Hapus Berita
</button>
</form>
<a href="<?php echo e(route('admin.berita.index')); ?>" class="btn btn-secondary">
<i class="fas fa-list"></i> Daftar Berita
</a>
</div>
</div>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/berita/show.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,105 @@
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-book-open"></i> Detail Materi</h2>
</div>
<div class="content-box">
<div class="detail-header">
<div>
<h3><?php echo e($materi->nama_kitab); ?></h3>
<p class="text-muted">ID: <?php echo e($materi->id_materi); ?></p>
</div>
<div style="display: flex; gap: 10px;">
<a href="<?php echo e(route('admin.materi.edit', $materi)); ?>" class="btn btn-warning">
<i class="fas fa-edit"></i> Edit
</a>
<a href="<?php echo e(route('admin.materi.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</div>
<div class="detail-section">
<h4><i class="fas fa-info-circle"></i> Informasi Materi</h4>
<table class="detail-table">
<tr>
<th><i class="fas fa-fingerprint"></i> ID Materi</th>
<td><strong><?php echo e($materi->id_materi); ?></strong></td>
</tr>
<tr>
<th><i class="fas fa-layer-group"></i> Kategori</th>
<td><?php echo $materi->kategori_badge; ?></td>
</tr>
<tr>
<th><i class="fas fa-users"></i> Kelas</th>
<td><?php echo $materi->kelas_badge; ?></td>
</tr>
<tr>
<th><i class="fas fa-book"></i> Nama Kitab</th>
<td><strong><?php echo e($materi->nama_kitab); ?></strong></td>
</tr>
<tr>
<th><i class="fas fa-file-alt"></i> Halaman Mulai</th>
<td><?php echo e($materi->halaman_mulai); ?></td>
</tr>
<tr>
<th><i class="fas fa-file-alt"></i> Halaman Akhir</th>
<td><?php echo e($materi->halaman_akhir); ?></td>
</tr>
<tr>
<th><i class="fas fa-calculator"></i> Total Halaman</th>
<td>
<span class="badge badge-lg badge-primary">
<i class="fas fa-book-open"></i> <?php echo e($materi->total_halaman); ?> Halaman
</span>
</td>
</tr>
<tr>
<th><i class="fas fa-align-left"></i> Deskripsi</th>
<td><?php echo e($materi->deskripsi ?? '-'); ?></td>
</tr>
<tr>
<th><i class="fas fa-calendar-plus"></i> Dibuat Pada</th>
<td><?php echo e($materi->created_at->format('d F Y, H:i')); ?> WIB</td>
</tr>
<tr>
<th><i class="fas fa-calendar-edit"></i> Terakhir Diupdate</th>
<td><?php echo e($materi->updated_at->format('d F Y, H:i')); ?> WIB</td>
</tr>
</table>
</div>
<div class="detail-section">
<h4><i class="fas fa-chart-bar"></i> Statistik Capaian</h4>
<div class="info-box">
<i class="fas fa-info-circle"></i>
<p style="margin: 0;">
Fitur statistik capaian santri akan tersedia setelah implementasi <strong>Langkah 2: Input Capaian per Santri</strong>.
</p>
</div>
</div>
<div style="margin-top: 30px; display: flex; gap: 10px; justify-content: flex-end;">
<a href="<?php echo e(route('admin.materi.edit', $materi)); ?>" class="btn btn-warning">
<i class="fas fa-edit"></i> Edit Materi
</a>
<form action="<?php echo e(route('admin.materi.destroy', $materi)); ?>" method="POST" style="display: inline-block;"
onsubmit="return confirm('Yakin ingin menghapus materi <?php echo e($materi->nama_kitab); ?>? Data capaian santri yang terkait juga akan terhapus!')">
<?php echo csrf_field(); ?>
<?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-danger">
<i class="fas fa-trash"></i> Hapus Materi
</button>
</form>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/materi/show.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,5 @@
<?php $__env->startSection('title', __('Page Expired')); ?>
<?php $__env->startSection('code', '419'); ?>
<?php $__env->startSection('message', __('Page Expired')); ?>
<?php echo $__env->make('errors::minimal', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\vendor\laravel\framework\src\Illuminate\Foundation\Exceptions/views/419.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,113 @@
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-id-card"></i> Kelola Kartu RFID Santri</h2>
</div>
<?php if(session('success')): ?>
<div class="alert alert-success">
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
</div>
<?php endif; ?>
<?php if(session('error')): ?>
<div class="alert alert-danger">
<i class="fas fa-exclamation-circle"></i> <?php echo e(session('error')); ?>
</div>
<?php endif; ?>
<div class="content-box">
<div style="margin-bottom: 20px;">
<form method="GET" class="filter-form-inline">
<select name="filter" class="form-control">
<option value="">-- Semua Santri --</option>
<option value="ada_rfid" <?php echo e(request('filter') == 'ada_rfid' ? 'selected' : ''); ?>>Sudah Punya RFID</option>
<option value="belum_rfid" <?php echo e(request('filter') == 'belum_rfid' ? 'selected' : ''); ?>>Belum Punya RFID</option>
</select>
<button type="submit" class="btn btn-primary">
<i class="fas fa-filter"></i> Filter
</button>
<?php if(request('filter')): ?>
<a href="<?php echo e(route('admin.kartu-rfid.index')); ?>" class="btn btn-secondary">
<i class="fas fa-times"></i> Reset
</a>
<?php endif; ?>
</form>
</div>
<?php if($santris->count() > 0): ?>
<table class="data-table">
<thead>
<tr>
<th style="width: 50px;">No</th>
<th style="width: 100px;">ID Santri</th>
<th>Nama Santri</th>
<th style="width: 100px;">Kelas</th>
<th style="width: 200px;">UID RFID</th>
<th style="width: 120px; text-align: center;">Status</th>
<th style="width: 250px; text-align: center;">Aksi</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $santris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><?php echo e($santris->firstItem() + $index); ?></td>
<td><strong><?php echo e($santri->id_santri); ?></strong></td>
<td><?php echo e($santri->nama_lengkap); ?></td>
<td><span class="badge badge-secondary"><?php echo e($santri->kelas); ?></span></td>
<td>
<?php if($santri->rfid_uid): ?>
<code style="font-size: 0.85rem;"><?php echo e($santri->rfid_uid); ?></code>
<?php else: ?>
<span style="color: var(--text-light);">-</span>
<?php endif; ?>
</td>
<td class="text-center">
<?php if($santri->rfid_uid): ?>
<span class="badge badge-success"><i class="fas fa-check"></i> Terdaftar</span>
<?php else: ?>
<span class="badge badge-warning"><i class="fas fa-exclamation"></i> Belum</span>
<?php endif; ?>
</td>
<td class="text-center">
<?php if($santri->rfid_uid): ?>
<a href="<?php echo e(route('admin.kartu-rfid.cetak', $santri->id_santri)); ?>" class="btn btn-sm btn-primary" title="Cetak Kartu" target="_blank">
<i class="fas fa-print"></i> Cetak
</a>
<form action="<?php echo e(route('admin.kartu-rfid.hapus', $santri->id_santri)); ?>" method="POST" style="display: inline-block;" onsubmit="return confirm('Yakin ingin menghapus RFID ini?')">
<?php echo csrf_field(); ?>
<?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-sm btn-danger" title="Hapus RFID">
<i class="fas fa-trash"></i> Hapus
</button>
</form>
<?php else: ?>
<a href="<?php echo e(route('admin.kartu-rfid.daftar', $santri->id_santri)); ?>" class="btn btn-sm btn-success" title="Daftarkan RFID">
<i class="fas fa-id-card"></i> Daftarkan RFID
</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
<div style="margin-top: 20px;">
<?php echo e($santris->links()); ?>
</div>
<?php else: ?>
<div class="empty-state">
<i class="fas fa-users-slash"></i>
<h3>Tidak Ada Data Santri</h3>
<p>Belum ada santri aktif yang terdaftar.</p>
</div>
<?php endif; ?>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/kartu/index.blade.php ENDPATH**/ ?>

View File

@ -1,275 +0,0 @@
<?php $__env->startSection('title', 'Riwayat Kesehatan'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-heartbeat"></i> Riwayat Kesehatan</h2>
<p style="margin: 5px 0 0 0; color: var(--text-light);">
Riwayat kunjungan UKP <strong><?php echo e($santri->nama_lengkap); ?></strong>
</p>
</div>
<?php if($errors->any()): ?>
<div class="alert alert-danger">
<i class="fas fa-exclamation-triangle"></i>
<strong>Error:</strong> <?php echo e($errors->first()); ?>
</div>
<?php endif; ?>
<div class="row-cards">
<div class="card card-info">
<h3><i class="fas fa-notes-medical"></i> Total Kunjungan</h3>
<div class="card-value"><?php echo e($statistik['total_kunjungan']); ?></div>
<div class="card-icon"><i class="fas fa-notes-medical"></i></div>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">
Periode yang dipilih
</p>
</div>
<div class="card card-danger">
<h3><i class="fas fa-procedures"></i> Sedang Dirawat</h3>
<div class="card-value"><?php echo e($statistik['sedang_dirawat']); ?></div>
<div class="card-icon"><i class="fas fa-procedures"></i></div>
<?php if($statistik['sedang_dirawat'] > 0): ?>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--danger-color);">
<i class="fas fa-exclamation-circle"></i> Perlu perhatian
</p>
<?php else: ?>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">
Tidak ada yang dirawat
</p>
<?php endif; ?>
</div>
<div class="card card-success">
<h3><i class="fas fa-check-circle"></i> Sembuh</h3>
<div class="card-value"><?php echo e($statistik['sembuh']); ?></div>
<div class="card-icon"><i class="fas fa-check-circle"></i></div>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">
Alhamdulillah
</p>
</div>
<div class="card card-warning">
<h3><i class="fas fa-home"></i> Izin Sakit</h3>
<div class="card-value"><?php echo e($statistik['izin']); ?></div>
<div class="card-icon"><i class="fas fa-home"></i></div>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">
Izin pulang
</p>
</div>
</div>
<div class="content-box" style="margin-bottom: 20px;">
<form method="GET" action="<?php echo e(route('santri.kesehatan.index')); ?>" id="filterForm">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; align-items: end;">
<div class="form-group" style="margin-bottom: 0;">
<label style="margin-bottom: 8px; display: block;">
<i class="fas fa-calendar-alt form-icon"></i> Tanggal Dari
</label>
<input type="date"
name="tanggal_dari"
class="form-control"
value="<?php echo e($tanggalDari->format('Y-m-d')); ?>"
max="<?php echo e(date('Y-m-d')); ?>">
</div>
<div class="form-group" style="margin-bottom: 0;">
<label style="margin-bottom: 8px; display: block;">
<i class="fas fa-calendar-check form-icon"></i> Tanggal Sampai
</label>
<input type="date"
name="tanggal_sampai"
class="form-control"
value="<?php echo e($tanggalSampai->format('Y-m-d')); ?>"
max="<?php echo e(date('Y-m-d')); ?>">
</div>
<div class="form-group" style="margin-bottom: 0;">
<label style="margin-bottom: 8px; display: block;">
<i class="fas fa-filter form-icon"></i> Status
</label>
<select name="status" class="form-control">
<option value="">Semua Status</option>
<?php $__currentLoopData = $statusOptions; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $value => $label): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($value); ?>" <?php echo e(request('status') == $value ? 'selected' : ''); ?>>
<?php echo e($label); ?>
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
</div>
<div style="display: flex; gap: 10px;">
<button type="submit" class="btn btn-primary hover-lift" style="flex: 1;">
<i class="fas fa-search"></i> Filter
</button>
<a href="<?php echo e(route('santri.kesehatan.index')); ?>" class="btn btn-secondary hover-lift" style="flex: 1;">
<i class="fas fa-sync"></i> Reset
</a>
</div>
</div>
</form>
<div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid var(--primary-light);">
<p style="margin: 0; color: var(--text-light); font-size: 0.9rem;">
<i class="fas fa-info-circle"></i>
Menampilkan data periode:
<strong style="color: var(--primary-color);">
<?php echo e($tanggalDari->locale('id')->isoFormat('D MMMM Y')); ?> - <?php echo e($tanggalSampai->locale('id')->isoFormat('D MMMM Y')); ?>
</strong>
(<?php echo e($tanggalDari->diffInDays($tanggalSampai) + 1); ?> hari)
</p>
</div>
</div>
<?php if($riwayatKesehatan->isEmpty()): ?>
<div class="empty-state" style="margin-top: 20px;">
<i class="fas fa-notes-medical"></i>
<h3>Tidak Ada Data</h3>
<p>Tidak ada riwayat kesehatan pada periode yang dipilih.</p>
<a href="<?php echo e(route('santri.kesehatan.index')); ?>" class="btn btn-primary" style="margin-top: 15px;">
<i class="fas fa-sync"></i> Lihat Semua Data
</a>
</div>
<?php else: ?>
<div class="content-box" style="margin-top: 20px;">
<h3 style="margin: 0 0 15px 0; color: var(--primary-color);">
<i class="fas fa-list"></i> Daftar Riwayat (<?php echo e($riwayatKesehatan->total()); ?> data)
</h3>
<div style="display: flex; flex-direction: column; gap: 15px;">
<?php $__currentLoopData = $riwayatKesehatan; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<a href="<?php echo e(route('santri.kesehatan.show', $item->id)); ?>"
style="display: flex; gap: 15px; padding: 15px; background: linear-gradient(135deg, #FFFFFF 0%, #FEFFFE 100%); border-radius: var(--border-radius-sm); border-left: 4px solid
<?php if($item->status == 'dirawat'): ?> var(--danger-color)
<?php elseif($item->status == 'sembuh'): ?> var(--success-color)
<?php else: ?> var(--warning-color) <?php endif; ?>
; text-decoration: none; transition: var(--transition-base); position: relative;"
onmouseover="this.style.boxShadow='var(--shadow-md)'; this.style.transform='translateX(5px)';"
onmouseout="this.style.boxShadow='none'; this.style.transform='translateX(0)';">
<div style="flex-shrink: 0; width: 60px; height: 60px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background:
<?php if($item->status == 'dirawat'): ?> linear-gradient(135deg, #FFE8EA, #FFD5D8)
<?php elseif($item->status == 'sembuh'): ?> linear-gradient(135deg, #E8F7F2, #D4F1E3)
<?php else: ?> linear-gradient(135deg, #FFF8E1, #FFF3CD) <?php endif; ?>
;">
<i class="fas
<?php if($item->status == 'dirawat'): ?> fa-procedures
<?php elseif($item->status == 'sembuh'): ?> fa-check-circle
<?php else: ?> fa-home <?php endif; ?>
" style="font-size: 1.8rem; color:
<?php if($item->status == 'dirawat'): ?> var(--danger-color)
<?php elseif($item->status == 'sembuh'): ?> var(--success-color)
<?php else: ?> var(--warning-color) <?php endif; ?>
;"></i>
</div>
<div style="flex: 1; display: flex; flex-direction: column; justify-content: space-between; min-width: 0;">
<div>
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 8px;">
<h3 style="margin: 0; font-size: 1rem; font-weight: 600; color: var(--text-color);">
<?php echo e($item->keluhan); ?>
</h3>
<span class="badge badge-<?php echo e($item->status_badge_color); ?>">
<?php echo e(ucfirst($item->status)); ?>
</span>
</div>
<p style="margin: 0 0 8px 0; font-size: 0.9rem; color: var(--text-light);">
<i class="fas fa-code"></i> <?php echo e($item->id_kesehatan); ?>
</p>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 15px; font-size: 0.85rem; color: var(--text-light);">
<span>
<i class="fas fa-calendar-plus"></i> Masuk: <?php echo e($item->tanggal_masuk_formatted); ?>
</span>
<?php if($item->tanggal_keluar): ?>
<span>
<i class="fas fa-calendar-check"></i> Keluar: <?php echo e($item->tanggal_keluar_formatted); ?>
</span>
<span class="badge badge-info badge-sm">
<i class="fas fa-clock"></i> <?php echo e($item->lama_dirawat); ?> hari
</span>
<?php else: ?>
<span class="badge badge-danger badge-sm">
<i class="fas fa-procedures"></i> Masih dirawat (<?php echo e($item->lama_dirawat); ?> hari)
</span>
<?php endif; ?>
</div>
</div>
<div style="flex-shrink: 0; display: flex; align-items: center;">
<i class="fas fa-chevron-right" style="color: var(--text-light);"></i>
</div>
</a>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</div>
<div style="margin-top: 25px;">
<?php echo e($riwayatKesehatan->links()); ?>
</div>
</div>
<?php endif; ?>
<div class="info-box" style="margin-top: 20px;">
<i class="fas fa-info-circle"></i>
<strong>Info:</strong> Gunakan filter tanggal untuk melihat riwayat kesehatan pada periode tertentu.
Jika tidak difilter, data yang ditampilkan adalah untuk bulan berjalan.
</div>
<div style="margin-top: 20px; text-align: center;">
<a href="<?php echo e(route('santri.dashboard')); ?>" class="btn btn-secondary hover-lift">
<i class="fas fa-home"></i> Kembali ke Dashboard
</a>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const tanggalDari = document.querySelector('input[name="tanggal_dari"]');
const tanggalSampai = document.querySelector('input[name="tanggal_sampai"]');
// Validasi tanggal
tanggalDari.addEventListener('change', function() {
if (tanggalSampai.value && tanggalSampai.value < this.value) {
alert('Tanggal sampai tidak boleh lebih kecil dari tanggal dari!');
this.value = tanggalSampai.value;
}
});
tanggalSampai.addEventListener('change', function() {
if (tanggalDari.value && this.value < tanggalDari.value) {
alert('Tanggal sampai tidak boleh lebih kecil dari tanggal dari!');
this.value = tanggalDari.value;
}
});
});
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/santri/kesehatan/index.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,189 @@
<?php $__env->startSection('title', 'Detail Santri: ' . $santri->nama_lengkap); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-user"></i> Detail Santri</h2>
</div>
<div class="content-box">
<div class="detail-header">
<div style="display: flex; align-items: center; gap: 20px;">
<?php if($santri->foto): ?>
<img src="<?php echo e(asset('storage/' . $santri->foto)); ?>"
alt="Foto <?php echo e($santri->nama_lengkap); ?>"
style="width: 80px; height: 80px; border-radius: 50%; object-fit: cover; border: 3px solid var(--primary-color); flex-shrink: 0;"
loading="lazy">
<?php else: ?>
<div style="width: 80px; height: 80px; border-radius: 50%; background: var(--primary-color); display: flex; align-items: center; justify-content: center; color: white; font-size: 2rem; font-weight: bold; flex-shrink: 0;">
<?php echo e(strtoupper(substr($santri->nama_lengkap, 0, 1))); ?>
</div>
<?php endif; ?>
<div>
<h3><?php echo e($santri->nama_lengkap); ?></h3>
<p style="color: #7F8C8D; margin: 5px 0 0 0;">
<i class="fas fa-id-badge"></i> <?php echo e($santri->id_santri); ?>
<?php if($santri->nis): ?>
| <i class="fas fa-barcode"></i> NIS: <?php echo e($santri->nis); ?>
<?php endif; ?>
</p>
</div>
</div>
<div style="display: flex; gap: 10px;">
<a href="<?php echo e(route('admin.santri.edit', $santri)); ?>" class="btn btn-warning">
<i class="fas fa-edit"></i> Edit
</a>
<a href="<?php echo e(route('admin.santri.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</div>
<hr style="border: none; border-top: 2px solid #E8F7F2; margin: 25px 0;">
<div class="detail-section">
<h4><i class="fas fa-id-card"></i> Informasi Dasar</h4>
<table class="detail-table">
<tr>
<th width="200">ID Santri</th>
<td><strong><?php echo e($santri->id_santri); ?></strong></td>
</tr>
<tr>
<th>NIS</th>
<td><?php echo e($santri->nis ?? '-'); ?></td>
</tr>
<tr>
<th>Nama Lengkap</th>
<td><strong><?php echo e($santri->nama_lengkap); ?></strong></td>
</tr>
<tr>
<th>Jenis Kelamin</th>
<td>
<?php if($santri->jenis_kelamin == 'Laki-laki'): ?>
<i class="fas fa-mars" style="color: #81C6E8;"></i> <?php echo e($santri->jenis_kelamin); ?>
<?php else: ?>
<i class="fas fa-venus" style="color: #FF8B94;"></i> <?php echo e($santri->jenis_kelamin); ?>
<?php endif; ?>
</td>
</tr>
<tr>
<th>Kelas</th>
<td>
<strong style="color: #6FBA9D; font-size: 1.1rem;"><?php echo e($santri->kelas); ?></strong>
<?php if($santri->kelas == 'PB'): ?>
<span style="color: #7F8C8D; font-size: 0.85rem;">(Pembinaan)</span>
<?php endif; ?>
</td>
</tr>
<tr>
<th>Status</th>
<td>
<?php if($santri->status == 'Aktif'): ?>
<span style="padding: 6px 12px; border-radius: 6px; font-size: 0.85rem; font-weight: 600; background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); color: #2C5F4F; display: inline-block;">
<i class="fas fa-check-circle"></i> <?php echo e($santri->status); ?>
</span>
<?php elseif($santri->status == 'Lulus'): ?>
<span style="padding: 6px 12px; border-radius: 6px; font-size: 0.85rem; font-weight: 600; background: linear-gradient(135deg, #E3F2FD 0%, #D1E9F9 100%); color: #2D4A7C; display: inline-block;">
<i class="fas fa-graduation-cap"></i> <?php echo e($santri->status); ?>
</span>
<?php else: ?>
<span style="padding: 6px 12px; border-radius: 6px; font-size: 0.85rem; font-weight: 600; background: linear-gradient(135deg, #E8ECF0 0%, #D1D8E0 100%); color: #555; display: inline-block;">
<i class="fas fa-times-circle"></i> <?php echo e($santri->status); ?>
</span>
<?php endif; ?>
</td>
</tr>
</table>
</div>
<div class="detail-section">
<h4><i class="fas fa-map-marker-alt"></i> Alamat & Asal</h4>
<table class="detail-table">
<tr>
<th width="200">Alamat Santri</th>
<td><?php echo e($santri->alamat_santri ?? '-'); ?></td>
</tr>
<tr>
<th>Daerah Asal</th>
<td>
<?php if($santri->daerah_asal): ?>
<i class="fas fa-map-pin" style="color: #6FBA9D;"></i> <?php echo e($santri->daerah_asal); ?>
<?php else: ?>
-
<?php endif; ?>
</td>
</tr>
</table>
</div>
<div class="detail-section">
<h4><i class="fas fa-users"></i> Data Orang Tua / Wali</h4>
<table class="detail-table">
<tr>
<th width="200">Nama Orang Tua</th>
<td><?php echo e($santri->nama_orang_tua ?? '-'); ?></td>
</tr>
<tr>
<th>Nomor HP Orang Tua</th>
<td>
<?php if($santri->nomor_hp_ortu): ?>
<i class="fas fa-phone" style="color: #6FBA9D;"></i>
<a href="tel:<?php echo e($santri->nomor_hp_ortu); ?>" style="color: #6FBA9D; text-decoration: none;">
<?php echo e($santri->nomor_hp_ortu); ?>
</a>
<?php else: ?>
-
<?php endif; ?>
</td>
</tr>
</table>
</div>
<div class="detail-section">
<h4><i class="fas fa-clock"></i> Informasi Sistem</h4>
<table class="detail-table">
<tr>
<th width="200">Tanggal Dibuat</th>
<td>
<i class="fas fa-calendar-plus" style="color: #81C6E8;"></i>
<?php echo e($santri->created_at->format('d M Y, H:i')); ?> WIB
<span style="color: #7F8C8D; font-size: 0.85rem;">
(<?php echo e($santri->created_at->diffForHumans()); ?>)
</span>
</td>
</tr>
<tr>
<th>Terakhir Diupdate</th>
<td>
<i class="fas fa-calendar-check" style="color: #FFD56B;"></i>
<?php echo e($santri->updated_at->format('d M Y, H:i')); ?> WIB
<span style="color: #7F8C8D; font-size: 0.85rem;">
(<?php echo e($santri->updated_at->diffForHumans()); ?>)
</span>
</td>
</tr>
</table>
</div>
<div style="margin-top: 30px; padding: 20px; background: linear-gradient(135deg, #F8FBF9 0%, #E8F7F2 100%); border-radius: 8px; border-left: 4px solid #6FBA9D;">
<p style="margin: 0; color: #2C5F4F; font-size: 0.9rem;">
<i class="fas fa-info-circle"></i>
<strong>Informasi:</strong> Data santri ini dapat diedit atau dihapus melalui halaman index atau menggunakan tombol Edit di atas.
</p>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', ['isAdmin' => true], \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/santri/show.blade.php ENDPATH**/ ?>

View File

@ -1,69 +0,0 @@
<?php $__env->startSection('title', 'Detail Riwayat Pelanggaran'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-file-alt"></i> Detail Riwayat Pelanggaran</h2>
</div>
<div class="content-box">
<div class="detail-header">
<h3>
<i class="fas fa-exclamation-circle" style="color: var(--danger-color);"></i>
Riwayat ID: <?php echo e($riwayatPelanggaran->id_riwayat); ?>
</h3>
<div>
<a href="<?php echo e(route('santri.pelanggaran.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</div>
<div class="detail-section">
<h4><i class="fas fa-info-circle"></i> Informasi Pelanggaran</h4>
<table class="detail-table">
<tr>
<th><i class="fas fa-hashtag"></i> ID Riwayat</th>
<td><strong><?php echo e($riwayatPelanggaran->id_riwayat); ?></strong></td>
</tr>
<tr>
<th><i class="fas fa-calendar"></i> Tanggal Kejadian</th>
<td><?php echo e(\Carbon\Carbon::parse($riwayatPelanggaran->tanggal)->isoFormat('dddd, D MMMM YYYY')); ?></td>
</tr>
<tr>
<th><i class="fas fa-list"></i> Jenis Pelanggaran</th>
<td><strong><?php echo e($riwayatPelanggaran->kategori->nama_pelanggaran ?? '-'); ?></strong></td>
</tr>
<tr>
<th><i class="fas fa-star"></i> Poin Pelanggaran</th>
<td>
<span class="badge badge-danger badge-lg">
<i class="fas fa-star"></i> <?php echo e($riwayatPelanggaran->poin); ?> Poin
</span>
</td>
</tr>
<tr>
<th><i class="fas fa-comment-alt"></i> Keterangan</th>
<td><?php echo e($riwayatPelanggaran->keterangan ?: '-'); ?></td>
</tr>
<tr>
<th><i class="fas fa-clock"></i> Dicatat Pada</th>
<td><?php echo e($riwayatPelanggaran->created_at->isoFormat('D MMMM YYYY, HH:mm')); ?> WIB</td>
</tr>
</table>
</div>
<div class="info-box">
<p>
<i class="fas fa-info-circle"></i>
<strong>Catatan:</strong> Data pelanggaran ini dicatat oleh admin/pengurus pondok.
Jika ada kesalahan data, silakan hubungi bagian administrasi.
</p>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/santri/pelanggaran/show.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,166 @@
<!-- resources/views/santri/profil/index.blade.php -->
<?php $__env->startSection('title', 'Edit Profil Santri'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-user-edit"></i> Edit Profil</h2>
</div>
<div class="form-container">
<form action="<?php echo e(route('santri.profil.update')); ?>" method="POST">
<?php echo csrf_field(); ?>
<?php echo method_field('PUT'); ?>
<div class="info-box" style="margin-bottom: 25px;">
<p style="margin: 0;">
<i class="fas fa-info-circle"></i>
<strong>Info:</strong> Anda hanya dapat mengubah alamat dan nomor HP orang tua.
Untuk perubahan data lain, silakan hubungi admin.
</p>
</div>
<div class="form-group">
<label>
<i class="fas fa-user form-icon"></i>
Nama Lengkap
</label>
<input type="text" class="form-control" value="<?php echo e($santri->nama_lengkap); ?>" disabled>
<span class="form-text">Data ini tidak dapat diubah</span>
</div>
<div class="form-group">
<label for="alamat_santri">
<i class="fas fa-map-marker-alt form-icon"></i>
Alamat Lengkap
</label>
<textarea
name="alamat_santri"
id="alamat_santri"
class="form-control <?php $__errorArgs = ['alamat_santri'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
rows="4"
placeholder="Masukkan alamat lengkap (nama jalan, RT/RW, kelurahan, kecamatan, kota/kabupaten)"
><?php echo e(old('alamat_santri', $santri->alamat_santri)); ?></textarea>
<?php $__errorArgs = ['alamat_santri'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<div class="invalid-feedback"><?php echo e($message); ?></div>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
<span class="form-text">
<i class="fas fa-lightbulb"></i>
Contoh: Jl. Merdeka No. 123, RT 02/RW 05, Kel. Sukamaju, Kec. Bandung Tengah, Kota Bandung
</span>
</div>
<div class="form-group">
<label for="nomor_hp_ortu">
<i class="fas fa-phone form-icon"></i>
Nomor HP Orang Tua/Wali
</label>
<input
type="text"
name="nomor_hp_ortu"
id="nomor_hp_ortu"
class="form-control <?php $__errorArgs = ['nomor_hp_ortu'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
value="<?php echo e(old('nomor_hp_ortu', $santri->nomor_hp_ortu)); ?>"
placeholder="Contoh: 0812-3456-7890 atau +62812-3456-7890"
>
<?php $__errorArgs = ['nomor_hp_ortu'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<div class="invalid-feedback"><?php echo e($message); ?></div>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
<span class="form-text">
<i class="fas fa-lightbulb"></i>
Format: 08XX-XXXX-XXXX atau +628XX-XXXX-XXXX
</span>
</div>
<div class="btn-group" style="margin-top: 30px;">
<button type="submit" class="btn btn-success">
<i class="fas fa-save"></i> Simpan Perubahan
</button>
<a href="<?php echo e(route('santri.profil.index')); ?>" class="btn btn-secondary">
<i class="fas fa-times"></i> Batal
</a>
</div>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const nomorHpInput = document.getElementById('nomor_hp_ortu');
if (nomorHpInput) {
nomorHpInput.addEventListener('input', function(e) {
// Hanya izinkan angka, +, -, spasi, dan tanda kurung
let value = e.target.value.replace(/[^\d+\-\s()]/g, '');
e.target.value = value;
});
nomorHpInput.addEventListener('blur', function(e) {
// Auto-format saat user selesai mengetik
let value = e.target.value.trim();
// Jika dimulai dengan 0 dan panjangnya cukup
if (value.startsWith('0') && value.length >= 10) {
// Format: 0812-3456-7890
value = value.replace(/\D/g, ''); // Hapus non-digit
if (value.length >= 11) {
value = value.substring(0, 4) + '-' +
value.substring(4, 8) + '-' +
value.substring(8, 12);
}
}
// Jika dimulai dengan +62
else if (value.startsWith('+62') && value.length >= 12) {
value = value.replace(/[^\d+]/g, ''); // Hapus non-digit kecuali +
if (value.length >= 13) {
value = '+62' + value.substring(3, 6) + '-' +
value.substring(6, 10) + '-' +
value.substring(10, 14);
}
}
e.target.value = value;
});
}
});
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/santri/profil/edit.blade.php ENDPATH**/ ?>

View File

@ -10,6 +10,35 @@
</div>
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 12px; margin-bottom: 20px;">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; align-items: center;">
<div>
<h4 style="margin: 0 0 5px 0; opacity: 0.9;">📅 Periode Kuota</h4>
<p style="margin: 0; font-size: 1.1rem; font-weight: 600;">
<?php echo e($settings->periode_mulai->format('d M Y')); ?> - <?php echo e($settings->periode_akhir->format('d M Y')); ?>
</p>
</div>
<div>
<h4 style="margin: 0 0 5px 0; opacity: 0.9;">📊 Kuota Maksimal</h4>
<p style="margin: 0; font-size: 1.1rem; font-weight: 600;"><?php echo e($settings->kuota_maksimal); ?> Hari / Tahun</p>
</div>
<div>
<h4 style="margin: 0 0 5px 0; opacity: 0.9;">🔄 Terakhir Reset</h4>
<p style="margin: 0; font-size: 1.1rem; font-weight: 600;">
<?php echo e($settings->terakhir_reset ? $settings->terakhir_reset->format('d M Y') : 'Belum Pernah'); ?>
</p>
</div>
<div style="text-align: right;">
<a href="<?php echo e(route('admin.kepulangan.settings')); ?>" class="btn btn-light" style="background: white; color: #667eea; font-weight: 600;">
<i class="fas fa-cog"></i> Kelola Pengaturan
</a>
</div>
</div>
</div>
<div class="row-cards">
<div class="card card-info">
<h3>Total Data</h3>
@ -27,9 +56,14 @@
<i class="fas fa-home card-icon"></i>
</div>
<div class="card card-danger">
<h3>Over Limit</h3>
<h3>Over Limit (><?php echo e($settings->kuota_maksimal); ?> Hari)</h3>
<div class="card-value"><?php echo e($stats['over_limit_santri']); ?></div>
<i class="fas fa-exclamation-triangle card-icon"></i>
<?php if($stats['over_limit_santri'] > 0): ?>
<a href="<?php echo e(route('admin.kepulangan.over-limit')); ?>" style="font-size: 0.85rem; color: #dc3545; text-decoration: underline; margin-top: 5px; display: block;">
Lihat Detail
</a>
<?php endif; ?>
</div>
</div>
@ -66,7 +100,7 @@
<input type="text"
name="search"
class="form-control"
placeholder="Nama, ID, atau alasan..."
placeholder="Cari nama, ID, atau alasan..."
value="<?php echo e(request('search')); ?>"
id="searchInput">
</div>
@ -126,6 +160,7 @@ class="form-control"
<th>Tanggal Pulang</th>
<th>Tanggal Kembali</th>
<th>Durasi</th>
<th>Total Kuota Terpakai</th>
<th>Alasan</th>
<th>Status</th>
<th class="text-center">Aksi</th>
@ -133,12 +168,16 @@ class="form-control"
</thead>
<tbody>
<?php $__empty_1 = true; $__currentLoopData = $kepulangan; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
<tr style="<?php echo e(isset($santriOverLimit[$item->id_santri]) ? 'background-color: #fff3cd;' : ''); ?>">
<?php
$isOverLimit = isset($santriOverLimit[$item->id_santri]);
$totalHariTerpakai = $isOverLimit ? $santriOverLimit[$item->id_santri] : 0;
?>
<tr style="<?php echo e($isOverLimit ? 'background-color: rgba(220, 53, 69, 0.1); border-left: 4px solid #dc3545;' : ''); ?>">
<td>
<strong><?php echo e($item->id_kepulangan); ?></strong>
<?php if(isset($santriOverLimit[$item->id_santri])): ?>
<span style="display: inline-block; background: #dc3545; color: white; padding: 2px 6px; border-radius: 4px; font-size: 0.75rem; margin-left: 5px;"
title="Over Limit: <?php echo e($santriOverLimit[$item->id_santri]); ?> hari">
<?php if($isOverLimit): ?>
<span style="display: inline-block; background: #dc3545; color: white; padding: 2px 6px; border-radius: 4px; font-size: 0.75rem; margin-left: 5px; animation: pulse 2s infinite;"
title="Over Limit: <?php echo e($totalHariTerpakai); ?> hari">
<i class="fas fa-exclamation-triangle"></i>
</span>
<?php endif; ?>
@ -155,10 +194,31 @@ class="form-control"
<td><?php echo e($item->tanggal_pulang_formatted); ?></td>
<td><?php echo e($item->tanggal_kembali_formatted); ?></td>
<td>
<span style="display: inline-block; background: <?php echo e($item->durasi_izin_calculated > 7 ? '#ffc107' : '#6c757d'); ?>; color: <?php echo e($item->durasi_izin_calculated > 7 ? '#000' : '#fff'); ?>; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;">
<?php echo e($item->durasi_izin_calculated); ?> hari
<span style="display: inline-block; background: <?php echo e($item->durasi_izin > 7 ? '#ffc107' : '#6c757d'); ?>; color: <?php echo e($item->durasi_izin > 7 ? '#000' : '#fff'); ?>; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem; font-weight: 600;">
<?php echo e($item->durasi_izin); ?> hari
</span>
</td>
<td>
<?php
$kuotaSantri = \App\Models\Kepulangan::getSisaKuotaSantri($item->id_santri);
$badgeColor = $kuotaSantri['badge_color'];
$badgeColors = [
'success' => '#28a745',
'warning' => '#ffc107',
'danger' => '#dc3545'
];
$bgColor = $badgeColors[$badgeColor] ?? '#6c757d';
$textColor = $badgeColor == 'warning' ? '#000' : '#fff';
?>
<div style="text-align: center;">
<span style="display: inline-block; background: <?php echo e($bgColor); ?>; color: <?php echo e($textColor); ?>; padding: 4px 10px; border-radius: 4px; font-size: 0.85rem; font-weight: 600;">
<?php echo e($kuotaSantri['total_terpakai']); ?> / <?php echo e($kuotaSantri['kuota_maksimal']); ?> hari
</span>
<div style="margin-top: 5px; font-size: 0.75rem; color: #7F8C8D;">
Sisa: <?php echo e($kuotaSantri['sisa_kuota']); ?> hari (<?php echo e($kuotaSantri['persentase']); ?>%)
</div>
</div>
</td>
<td>
<span style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block;" title="<?php echo e($item->alasan); ?>">
<?php echo e($item->alasan); ?>
@ -176,9 +236,9 @@ class="form-control"
</span>
<?php if($item->is_aktif): ?>
<br><small style="color: #28a745; font-weight: 600;">Sedang Izin</small>
<br><small style="color: #28a745; font-weight: 600;">🏠 Sedang Izin</small>
<?php elseif($item->is_terlambat): ?>
<br><small style="color: #dc3545; font-weight: 600;">Terlambat</small>
<br><small style="color: #dc3545; font-weight: 600;">Terlambat</small>
<?php endif; ?>
</td>
<td class="text-center">
@ -234,7 +294,7 @@ class="btn btn-sm btn-danger"
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
<tr>
<td colspan="8" style="text-align: center; padding: 40px;">
<td colspan="9" style="text-align: center; padding: 40px;">
<i class="fas fa-inbox" style="font-size: 3rem; color: #ccc; margin-bottom: 15px;"></i>
<p style="color: #7F8C8D;">Tidak ada data kepulangan ditemukan</p>
</td>
@ -284,7 +344,6 @@ class="btn btn-sm btn-danger"
</div>
</div>
<div class="modal fade" id="rejectModal" tabindex="-1" style="display: none;">
<div class="modal-dialog">
<div class="modal-content" style="background: white; border-radius: 12px; padding: 20px;">
@ -309,7 +368,6 @@ class="btn btn-sm btn-danger"
</div>
</div>
<div class="modal fade" id="deleteModal" tabindex="-1" style="display: none;">
<div class="modal-dialog">
<div class="modal-content" style="background: white; border-radius: 12px; padding: 20px;">
@ -332,12 +390,17 @@ class="btn btn-sm btn-danger"
.modal.fade { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
.modal-dialog { max-width: 500px; width: 90%; margin: auto; }
.modal-content { max-height: 90vh; overflow-y: auto; }
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
</style>
<script>
let currentActionId = null;
// Auto submit search with debounce
// Auto submit search dengan debounce
let searchTimeout;
document.getElementById('searchInput')?.addEventListener('input', function() {
clearTimeout(searchTimeout);

View File

@ -0,0 +1,105 @@
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-chart-bar"></i> Rekap Absensi: <?php echo e($kegiatan->nama_kegiatan); ?></h2>
</div>
<div class="row-cards">
<div class="card card-success">
<h3>Hadir</h3>
<div class="card-value"><?php echo e($stats['Hadir'] ?? 0); ?></div>
<i class="fas fa-check-circle card-icon"></i>
</div>
<div class="card card-warning">
<h3>Izin</h3>
<div class="card-value"><?php echo e($stats['Izin'] ?? 0); ?></div>
<i class="fas fa-info-circle card-icon"></i>
</div>
<div class="card card-info">
<h3>Sakit</h3>
<div class="card-value"><?php echo e($stats['Sakit'] ?? 0); ?></div>
<i class="fas fa-heartbeat card-icon"></i>
</div>
<div class="card card-danger">
<h3>Alpa</h3>
<div class="card-value"><?php echo e($stats['Alpa'] ?? 0); ?></div>
<i class="fas fa-times-circle card-icon"></i>
</div>
</div>
<div class="content-box">
<div style="margin-bottom: 20px;">
<form method="GET" class="filter-form-inline">
<input type="date" name="tanggal" class="form-control" value="<?php echo e(request('tanggal')); ?>">
<input type="month" name="bulan" class="form-control" value="<?php echo e(request('bulan')); ?>" placeholder="Pilih Bulan">
<button type="submit" class="btn btn-primary">
<i class="fas fa-filter"></i> Filter
</button>
<?php if(request()->hasAny(['tanggal', 'bulan'])): ?>
<a href="<?php echo e(route('admin.absensi-kegiatan.rekap', $kegiatan->kegiatan_id)); ?>" class="btn btn-secondary">
<i class="fas fa-times"></i> Reset
</a>
<?php endif; ?>
<a href="<?php echo e(route('admin.absensi-kegiatan.index')); ?>" class="btn btn-secondary" style="margin-left: auto;">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</form>
</div>
<?php if($absensis->count() > 0): ?>
<table class="data-table">
<thead>
<tr>
<th style="width: 50px;">No</th>
<th style="width: 100px;">Tanggal</th>
<th style="width: 100px;">ID Santri</th>
<th>Nama Santri</th>
<th style="width: 80px;">Kelas</th>
<th style="width: 120px; text-align: center;">Status</th>
<th style="width: 100px;">Metode</th>
<th style="width: 100px;">Waktu</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $absensis; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $absensi): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><?php echo e($absensis->firstItem() + $index); ?></td>
<td><?php echo e($absensi->tanggal->format('d/m/Y')); ?></td>
<td><strong><?php echo e($absensi->id_santri); ?></strong></td>
<td><?php echo e($absensi->santri->nama_lengkap); ?></td>
<td><span class="badge badge-secondary"><?php echo e($absensi->santri->kelas); ?></span></td>
<td class="text-center"><?php echo $absensi->status_badge; ?></td>
<td>
<?php if($absensi->metode_absen == 'RFID'): ?>
<span class="badge badge-primary"><i class="fas fa-id-card"></i> RFID</span>
<?php else: ?>
<span class="badge badge-secondary"><i class="fas fa-hand-pointer"></i> Manual</span>
<?php endif; ?>
</td>
<td><?php echo e($absensi->waktu_absen ? date('H:i', strtotime($absensi->waktu_absen)) : '-'); ?></td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
<div style="margin-top: 20px;">
<?php echo e($absensis->links()); ?>
</div>
<?php else: ?>
<div class="empty-state">
<i class="fas fa-clipboard"></i>
<h3>Belum Ada Data Absensi</h3>
<p>Silakan input absensi terlebih dahulu.</p>
<a href="<?php echo e(route('admin.absensi-kegiatan.input', $kegiatan->kegiatan_id)); ?>" class="btn btn-success">
<i class="fas fa-clipboard-check"></i> Input Absensi
</a>
</div>
<?php endif; ?>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/absensi/rekap.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,132 @@
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-file-alt"></i> Detail Riwayat Absensi</h2>
</div>
<div class="content-box">
<div class="detail-header">
<h3>Riwayat Absensi #<?php echo e($riwayat->absensi_id); ?></h3>
<div style="display: flex; gap: 10px;">
<a href="<?php echo e(route('admin.riwayat-kegiatan.edit', $riwayat->id)); ?>" class="btn btn-warning">
<i class="fas fa-edit"></i> Edit
</a>
<form action="<?php echo e(route('admin.riwayat-kegiatan.destroy', $riwayat->id)); ?>" method="POST" style="display: inline;" onsubmit="return confirm('Yakin ingin menghapus riwayat ini?')">
<?php echo csrf_field(); ?>
<?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-danger">
<i class="fas fa-trash"></i> Hapus
</button>
</form>
<a href="<?php echo e(route('admin.riwayat-kegiatan.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</div>
<div class="detail-section">
<h4><i class="fas fa-user"></i> Informasi Santri</h4>
<table class="detail-table">
<tr>
<th>ID Santri</th>
<td><strong><?php echo e($riwayat->santri->id_santri); ?></strong></td>
</tr>
<tr>
<th>Nama Lengkap</th>
<td><?php echo e($riwayat->santri->nama_lengkap); ?></td>
</tr>
<tr>
<th>Kelas</th>
<td><span class="badge badge-secondary badge-lg"><?php echo e($riwayat->santri->kelas); ?></span></td>
</tr>
<tr>
<th>Status Santri</th>
<td><span class="badge badge-success badge-lg"><?php echo e($riwayat->santri->status); ?></span></td>
</tr>
</table>
</div>
<div class="detail-section">
<h4><i class="fas fa-calendar-alt"></i> Informasi Kegiatan</h4>
<table class="detail-table">
<tr>
<th>ID Kegiatan</th>
<td><strong><?php echo e($riwayat->kegiatan->kegiatan_id); ?></strong></td>
</tr>
<tr>
<th>Nama Kegiatan</th>
<td><?php echo e($riwayat->kegiatan->nama_kegiatan); ?></td>
</tr>
<tr>
<th>Kategori</th>
<td><span class="badge badge-primary badge-lg"><?php echo e($riwayat->kegiatan->kategori->nama_kategori); ?></span></td>
</tr>
<tr>
<th>Hari</th>
<td><span class="badge badge-info badge-lg"><?php echo e($riwayat->kegiatan->hari); ?></span></td>
</tr>
<tr>
<th>Waktu Pelaksanaan</th>
<td>
<i class="fas fa-clock" style="color: var(--primary-color);"></i>
<?php echo e(date('H:i', strtotime($riwayat->kegiatan->waktu_mulai))); ?> -
<?php echo e(date('H:i', strtotime($riwayat->kegiatan->waktu_selesai))); ?> WIB
</td>
</tr>
</table>
</div>
<div class="detail-section">
<h4><i class="fas fa-clipboard-check"></i> Detail Absensi</h4>
<table class="detail-table">
<tr>
<th>ID Absensi</th>
<td><strong><?php echo e($riwayat->absensi_id); ?></strong></td>
</tr>
<tr>
<th>Tanggal Absensi</th>
<td><?php echo e($riwayat->tanggal->format('d F Y')); ?></td>
</tr>
<tr>
<th>Status Kehadiran</th>
<td><?php echo $riwayat->status_badge; ?></td>
</tr>
<tr>
<th>Metode Absensi</th>
<td>
<?php if($riwayat->metode_absen == 'RFID'): ?>
<span class="badge badge-primary badge-lg">
<i class="fas fa-id-card"></i> RFID
</span>
<?php else: ?>
<span class="badge badge-secondary badge-lg">
<i class="fas fa-hand-pointer"></i> Manual
</span>
<?php endif; ?>
</td>
</tr>
<tr>
<th>Waktu Absen</th>
<td>
<?php if($riwayat->waktu_absen): ?>
<i class="fas fa-clock" style="color: var(--primary-color);"></i>
<?php echo e(date('H:i:s', strtotime($riwayat->waktu_absen))); ?> WIB
<?php else: ?>
-
<?php endif; ?>
</td>
</tr>
<tr>
<th>Dicatat Pada</th>
<td><?php echo e($riwayat->created_at->format('d F Y, H:i:s')); ?> WIB</td>
</tr>
<tr>
<th>Terakhir Diubah</th>
<td><?php echo e($riwayat->updated_at->format('d F Y, H:i:s')); ?> WIB</td>
</tr>
</table>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/riwayat/show.blade.php ENDPATH**/ ?>

View File

@ -1,53 +0,0 @@
<?php $__env->startSection('title', 'Manajemen Akun Santri'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-user-cog"></i> Manajemen Akun Santri</h2>
</div>
<?php if(session('success')): ?>
<div class="alert alert-success"><?php echo e(session('success')); ?></div>
<?php endif; ?>
<div class="content-box">
<div class="content-header-flex">
<a href="<?php echo e(route('admin.users.santri_create')); ?>" class="btn btn-primary"><i class="fas fa-plus"></i> Buat Akun Santri</a>
</div>
<h3>Daftar Akun Santri (<?php echo e($users->count()); ?>)</h3>
<table class="data-table">
<thead>
<tr>
<th>ID Santri</th>
<th>Nama</th>
<th>Username</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
<?php $__empty_1 = true; $__currentLoopData = $users; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $user): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
<tr>
<td><?php echo e($user->role_id); ?></td>
<td><?php echo e($user->name); ?></td>
<td><?php echo e($user->username); ?></td>
<td>
<a href="#" class="btn btn-sm btn-warning"><i class="fas fa-key"></i> Reset Password</a>
<a href="#" class="btn btn-sm btn-danger"><i class="fas fa-trash"></i> Hapus Akun</a>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
<tr>
<td colspan="4" class="text-center">Belum ada akun Santri yang terdaftar.</td>
</tr>
<?php endif; ?>
</tbody>
</table>
<h3 style="margin-top: 30px;">Data Santri Tanpa Akun (<?php echo e($santris_tanpa_akun->count()); ?>)</h3>
<p>Berikut adalah data santri yang sudah terdaftar di Data Santri namun belum memiliki akun login. Mereka dapat dipilih saat Anda membuat akun baru.</p>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', ['isAdmin' => true], \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/users/santri_accounts.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,255 @@
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-history"></i> Riwayat Kegiatan & Absensi</h2>
</div>
<?php if(session('success')): ?>
<div class="alert alert-success">
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
</div>
<?php endif; ?>
<!-- Statistik Cards -->
<div class="row-cards">
<div class="card card-success">
<h3>Total Hadir</h3>
<div class="card-value"><?php echo e($stats['Hadir'] ?? 0); ?></div>
<i class="fas fa-check-circle card-icon"></i>
</div>
<div class="card card-warning">
<h3>Total Izin</h3>
<div class="card-value"><?php echo e($stats['Izin'] ?? 0); ?></div>
<i class="fas fa-info-circle card-icon"></i>
</div>
<div class="card card-info">
<h3>Total Sakit</h3>
<div class="card-value"><?php echo e($stats['Sakit'] ?? 0); ?></div>
<i class="fas fa-heartbeat card-icon"></i>
</div>
<div class="card card-danger">
<h3>Total Alpa</h3>
<div class="card-value"><?php echo e($stats['Alpa'] ?? 0); ?></div>
<i class="fas fa-times-circle card-icon"></i>
</div>
</div>
<!-- Grafik Kehadiran -->
<?php if(($stats['Hadir'] ?? 0) + ($stats['Izin'] ?? 0) + ($stats['Sakit'] ?? 0) + ($stats['Alpa'] ?? 0) > 0): ?>
<div class="content-box" style="margin-bottom: 20px;">
<h3 style="margin: 0 0 20px 0; color: var(--primary-color);">
<i class="fas fa-chart-pie"></i> Grafik Statistik Kehadiran
</h3>
<canvas id="chartKehadiran" style="max-height: 300px;"></canvas>
</div>
<?php endif; ?>
<!-- Filter -->
<div class="content-box">
<form method="GET" style="margin-bottom: 20px;">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
<div class="form-group" style="margin: 0;">
<label for="id_santri" style="font-size: 0.85rem; margin-bottom: 5px;">Santri</label>
<select name="id_santri" id="id_santri" class="form-control">
<option value="">-- Semua Santri --</option>
<?php $__currentLoopData = $santris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $s): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($s->id_santri); ?>" <?php echo e(request('id_santri') == $s->id_santri ? 'selected' : ''); ?>>
<?php echo e($s->nama_lengkap); ?>
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
</div>
<div class="form-group" style="margin: 0;">
<label for="kategori_id" style="font-size: 0.85rem; margin-bottom: 5px;">Kategori</label>
<select name="kategori_id" id="kategori_id" class="form-control">
<option value="">-- Semua Kategori --</option>
<?php $__currentLoopData = $kategoris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $k): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($k->kategori_id); ?>" <?php echo e(request('kategori_id') == $k->kategori_id ? 'selected' : ''); ?>>
<?php echo e($k->nama_kategori); ?>
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
</div>
<div class="form-group" style="margin: 0;">
<label for="kegiatan_id" style="font-size: 0.85rem; margin-bottom: 5px;">Kegiatan</label>
<select name="kegiatan_id" id="kegiatan_id" class="form-control">
<option value="">-- Semua Kegiatan --</option>
<?php $__currentLoopData = $kegiatans; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kg): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($kg->kegiatan_id); ?>" <?php echo e(request('kegiatan_id') == $kg->kegiatan_id ? 'selected' : ''); ?>>
<?php echo e($kg->nama_kegiatan); ?>
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
</div>
<div class="form-group" style="margin: 0;">
<label for="status" style="font-size: 0.85rem; margin-bottom: 5px;">Status</label>
<select name="status" id="status" class="form-control">
<option value="">-- Semua Status --</option>
<option value="Hadir" <?php echo e(request('status') == 'Hadir' ? 'selected' : ''); ?>>Hadir</option>
<option value="Izin" <?php echo e(request('status') == 'Izin' ? 'selected' : ''); ?>>Izin</option>
<option value="Sakit" <?php echo e(request('status') == 'Sakit' ? 'selected' : ''); ?>>Sakit</option>
<option value="Alpa" <?php echo e(request('status') == 'Alpa' ? 'selected' : ''); ?>>Alpa</option>
</select>
</div>
<div class="form-group" style="margin: 0;">
<label for="tanggal_dari" style="font-size: 0.85rem; margin-bottom: 5px;">Tanggal Dari</label>
<input type="date" name="tanggal_dari" id="tanggal_dari" class="form-control" value="<?php echo e(request('tanggal_dari')); ?>">
</div>
<div class="form-group" style="margin: 0;">
<label for="tanggal_sampai" style="font-size: 0.85rem; margin-bottom: 5px;">Tanggal Sampai</label>
<input type="date" name="tanggal_sampai" id="tanggal_sampai" class="form-control" value="<?php echo e(request('tanggal_sampai')); ?>">
</div>
<div class="form-group" style="margin: 0;">
<label for="bulan" style="font-size: 0.85rem; margin-bottom: 5px;">Atau Pilih Bulan</label>
<input type="month" name="bulan" id="bulan" class="form-control" value="<?php echo e(request('bulan')); ?>">
</div>
<div style="display: flex; align-items: flex-end; gap: 10px;">
<button type="submit" class="btn btn-primary" style="flex: 1;">
<i class="fas fa-filter"></i> Filter
</button>
<?php if(request()->hasAny(['id_santri', 'kategori_id', 'kegiatan_id', 'status', 'tanggal_dari', 'tanggal_sampai', 'bulan'])): ?>
<a href="<?php echo e(route('admin.riwayat-kegiatan.index')); ?>" class="btn btn-secondary">
<i class="fas fa-times"></i>
</a>
<?php endif; ?>
</div>
</div>
</form>
<?php if($riwayats->count() > 0): ?>
<table class="data-table">
<thead>
<tr>
<th style="width: 50px;">No</th>
<th style="width: 100px;">Tanggal</th>
<th style="width: 100px;">ID Santri</th>
<th>Nama Santri</th>
<th>Kegiatan</th>
<th style="width: 130px;">Kategori</th>
<th style="width: 120px; text-align: center;">Status</th>
<th style="width: 90px;">Metode</th>
<th style="width: 180px; text-align: center;">Aksi</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $riwayats; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $riwayat): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><?php echo e($riwayats->firstItem() + $index); ?></td>
<td><?php echo e($riwayat->tanggal->format('d/m/Y')); ?></td>
<td><strong><?php echo e($riwayat->id_santri); ?></strong></td>
<td>
<a href="<?php echo e(route('admin.riwayat-kegiatan.detail-santri', $riwayat->id_santri)); ?>"
style="color: var(--primary-color); text-decoration: none; font-weight: 500;">
<?php echo e($riwayat->santri->nama_lengkap); ?>
</a>
</td>
<td><?php echo e($riwayat->kegiatan->nama_kegiatan); ?></td>
<td><?php echo e($riwayat->kegiatan->kategori->nama_kategori); ?></td>
<td class="text-center"><?php echo $riwayat->status_badge; ?></td>
<td>
<?php if($riwayat->metode_absen == 'RFID'): ?>
<span class="badge badge-primary" style="font-size: 0.75rem;"><i class="fas fa-id-card"></i> RFID</span>
<?php else: ?>
<span class="badge badge-secondary" style="font-size: 0.75rem;"><i class="fas fa-hand-pointer"></i> Manual</span>
<?php endif; ?>
</td>
<td class="text-center">
<a href="<?php echo e(route('admin.riwayat-kegiatan.show', $riwayat->id)); ?>" class="btn btn-sm btn-primary" title="Detail">
<i class="fas fa-eye"></i>
</a>
<a href="<?php echo e(route('admin.riwayat-kegiatan.edit', $riwayat->id)); ?>" class="btn btn-sm btn-warning" title="Edit">
<i class="fas fa-edit"></i>
</a>
<form action="<?php echo e(route('admin.riwayat-kegiatan.destroy', $riwayat->id)); ?>" method="POST" style="display: inline-block;" onsubmit="return confirm('Yakin ingin menghapus riwayat ini?')">
<?php echo csrf_field(); ?>
<?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-sm btn-danger" title="Hapus">
<i class="fas fa-trash"></i>
</button>
</form>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
<div style="margin-top: 20px;">
<?php echo e($riwayats->links()); ?>
</div>
<?php else: ?>
<div class="empty-state">
<i class="fas fa-inbox"></i>
<h3>Tidak Ada Riwayat</h3>
<p>Belum ada data riwayat kegiatan dan absensi.</p>
</div>
<?php endif; ?>
</div>
<?php if(($stats['Hadir'] ?? 0) + ($stats['Izin'] ?? 0) + ($stats['Sakit'] ?? 0) + ($stats['Alpa'] ?? 0) > 0): ?>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const ctx = document.getElementById('chartKehadiran');
new Chart(ctx, {
type: 'pie',
data: {
labels: ['Hadir', 'Izin', 'Sakit', 'Alpa'],
datasets: [{
data: [
<?php echo e($stats['Hadir'] ?? 0); ?>,
<?php echo e($stats['Izin'] ?? 0); ?>,
<?php echo e($stats['Sakit'] ?? 0); ?>,
<?php echo e($stats['Alpa'] ?? 0); ?>
],
backgroundColor: [
'#6FBA9D',
'#FFD56B',
'#81C6E8',
'#FF8B94'
],
borderWidth: 2,
borderColor: '#fff'
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
position: 'bottom',
labels: {
padding: 15,
font: { size: 13 }
}
},
tooltip: {
callbacks: {
label: function(context) {
let total = context.dataset.data.reduce((a, b) => a + b, 0);
let value = context.parsed;
let percentage = ((value / total) * 100).toFixed(1);
return context.label + ': ' + value + ' (' + percentage + '%)';
}
}
}
}
}
});
</script>
<?php endif; ?>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/riwayat/index.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,372 @@
<?php $__env->startSection('title', 'Riwayat Kegiatan & Absensi'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-calendar-check"></i> Riwayat Kegiatan & Absensi</h2>
<p style="margin: 5px 0 0 0; color: var(--text-light);">
<?php echo e($santri->nama_lengkap); ?> - Kelas <?php echo e($santri->kelas); ?>
</p>
</div>
<div class="content-box" style="margin-bottom: 25px; background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); border: 2px solid var(--primary-color);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
<h3 style="margin: 0; color: var(--primary-dark);">
<i class="fas fa-clock"></i> Jadwal Kegiatan Hari Ini (<?php echo e(ucfirst($hariIni)); ?>)
</h3>
<span class="badge badge-primary badge-lg">
<i class="fas fa-calendar-day"></i> <?php echo e(\Carbon\Carbon::now()->locale('id')->isoFormat('D MMMM YYYY')); ?>
</span>
</div>
<?php if($jadwalHariIni->count() > 0): ?>
<div style="display: flex; flex-direction: column; gap: 12px;">
<?php $__currentLoopData = $jadwalHariIni; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $jadwal): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<div style="background: white; padding: 18px; border-radius: var(--border-radius-sm); border-left: 4px solid <?php echo e(isset($absensiHariIni[$jadwal->kegiatan_id]) ? 'var(--success-color)' : 'var(--warning-color)'); ?>; display: flex; justify-content: space-between; align-items: center; box-shadow: var(--shadow-sm);">
<div style="flex: 1;">
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 8px;">
<span class="badge badge-info"><?php echo e($jadwal->kategori->nama_kategori); ?></span>
<h4 style="margin: 0; font-size: 1.1rem; color: var(--text-color);"><?php echo e($jadwal->nama_kegiatan); ?></h4>
</div>
<div style="display: flex; align-items: center; gap: 15px; font-size: 0.9rem; color: var(--text-light);">
<span><i class="fas fa-clock"></i> <?php echo e(date('H:i', strtotime($jadwal->waktu_mulai))); ?> - <?php echo e(date('H:i', strtotime($jadwal->waktu_selesai))); ?></span>
<?php if($jadwal->materi): ?>
<span><i class="fas fa-book"></i> <?php echo e($jadwal->materi); ?></span>
<?php endif; ?>
</div>
</div>
<div>
<?php if(isset($absensiHariIni[$jadwal->kegiatan_id])): ?>
<span class="badge badge-success badge-lg">
<i class="fas fa-check-circle"></i> <?php echo e($absensiHariIni[$jadwal->kegiatan_id]); ?>
</span>
<?php else: ?>
<span class="badge badge-warning badge-lg">
<i class="fas fa-hourglass-half"></i> Belum Absen
</span>
<?php endif; ?>
</div>
</div>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</div>
<?php else: ?>
<div class="empty-state" style="padding: 40px; text-align: center;">
<i class="fas fa-calendar-times" style="font-size: 3rem; color: #ccc;"></i>
<p style="margin-top: 15px; color: var(--text-light);">Tidak ada jadwal kegiatan untuk hari ini.</p>
</div>
<?php endif; ?>
</div>
<div class="row-cards" style="margin-bottom: 25px;">
<div class="card card-success">
<h3><i class="fas fa-check-circle"></i> Total Kehadiran</h3>
<div class="card-value"><?php echo e($stats30Hari['Hadir'] ?? 0); ?></div>
<div class="card-icon"><i class="fas fa-check-circle"></i></div>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">30 hari terakhir</p>
</div>
<div class="card card-info">
<h3><i class="fas fa-percentage"></i> Persentase Kehadiran</h3>
<div class="card-value"><?php echo e($persentaseKehadiran); ?>%</div>
<div class="card-icon"><i class="fas fa-chart-line"></i></div>
<div style="margin-top: 10px;">
<div class="progress-bar">
<div class="progress-fill" style="width: <?php echo e($persentaseKehadiran); ?>%; background: var(--info-color);"></div>
</div>
</div>
</div>
<div class="card card-warning">
<h3><i class="fas fa-exclamation-triangle"></i> Izin / Sakit / Alpa</h3>
<div class="card-value"><?php echo e(($stats30Hari['Izin'] ?? 0) + ($stats30Hari['Sakit'] ?? 0) + ($stats30Hari['Alpa'] ?? 0)); ?></div>
<div class="card-icon"><i class="fas fa-exclamation-triangle"></i></div>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">
Izin: <?php echo e($stats30Hari['Izin'] ?? 0); ?> | Sakit: <?php echo e($stats30Hari['Sakit'] ?? 0); ?> | Alpa: <?php echo e($stats30Hari['Alpa'] ?? 0); ?>
</p>
</div>
<div class="card card-primary">
<h3><i class="fas fa-list-check"></i> Total Kegiatan</h3>
<div class="card-value"><?php echo e($totalKegiatan30Hari); ?></div>
<div class="card-icon"><i class="fas fa-list-check"></i></div>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">30 hari terakhir</p>
</div>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(450px, 1fr)); gap: 25px; margin-bottom: 25px;">
<div class="content-box">
<h3 style="margin-bottom: 20px; color: var(--primary-dark);">
<i class="fas fa-chart-line"></i> Tren Kehadiran (4 Minggu Terakhir)
</h3>
<canvas id="chartTrenKehadiran" style="max-height: 300px;"></canvas>
</div>
<div class="content-box">
<h3 style="margin-bottom: 20px; color: var(--primary-dark);">
<i class="fas fa-chart-bar"></i> Kehadiran per Kategori Kegiatan
</h3>
<canvas id="chartKategori" style="max-height: 300px;"></canvas>
</div>
</div>
<div class="content-box">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; flex-wrap: wrap; gap: 15px;">
<h3 style="margin: 0; color: var(--text-color);">
<i class="fas fa-history"></i> Riwayat Absensi Lengkap
</h3>
<form method="GET" action="<?php echo e(route('santri.kegiatan.index')); ?>" style="display: flex; gap: 10px; flex-wrap: wrap;">
<input type="month" name="bulan" class="form-control" value="<?php echo e(request('bulan')); ?>"
style="max-width: 200px;" placeholder="Pilih Bulan">
<select name="status" class="form-control" style="max-width: 150px;">
<option value="">Semua Status</option>
<option value="Hadir" <?php echo e(request('status') == 'Hadir' ? 'selected' : ''); ?>>Hadir</option>
<option value="Izin" <?php echo e(request('status') == 'Izin' ? 'selected' : ''); ?>>Izin</option>
<option value="Sakit" <?php echo e(request('status') == 'Sakit' ? 'selected' : ''); ?>>Sakit</option>
<option value="Alpa" <?php echo e(request('status') == 'Alpa' ? 'selected' : ''); ?>>Alpa</option>
</select>
<button type="submit" class="btn btn-primary btn-sm">
<i class="fas fa-filter"></i> Filter
</button>
<a href="<?php echo e(route('santri.kegiatan.index')); ?>" class="btn btn-secondary btn-sm">
<i class="fas fa-redo"></i> Reset
</a>
</form>
</div>
<?php if($riwayats->count() > 0): ?>
<div class="table-container">
<table class="data-table">
<thead>
<tr>
<th>No</th>
<th>Tanggal</th>
<th>Kegiatan</th>
<th>Kategori</th>
<th>Waktu Absen</th>
<th>Status</th>
<th>Metode</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $riwayats; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $absensi): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><?php echo e($riwayats->firstItem() + $index); ?></td>
<td><?php echo e($absensi->tanggal_formatted); ?></td>
<td><strong><?php echo e($absensi->kegiatan->nama_kegiatan); ?></strong></td>
<td><span class="badge badge-info"><?php echo e($absensi->kegiatan->kategori->nama_kategori); ?></span></td>
<td><?php echo e($absensi->waktu_absen_formatted); ?></td>
<td>
<span class="badge <?php echo e($absensi->status_badge_class); ?>">
<i class="fas fa-<?php echo e($absensi->status == 'Hadir' ? 'check' : ($absensi->status == 'Izin' ? 'info-circle' : ($absensi->status == 'Sakit' ? 'heartbeat' : 'times'))); ?>-circle"></i>
<?php echo e($absensi->status); ?>
</span>
</td>
<td><span class="badge badge-secondary"><?php echo e($absensi->metode_absen); ?></span></td>
<td class="text-center">
<a href="<?php echo e(route('santri.kegiatan.show', $absensi->kegiatan_id)); ?>" class="btn btn-sm btn-primary" title="Lihat Detail Kegiatan">
<i class="fas fa-eye"></i>
</a>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
</div>
<div style="margin-top: 20px;">
<?php echo e($riwayats->links()); ?>
</div>
<?php else: ?>
<div class="empty-state">
<i class="fas fa-inbox"></i>
<h3>Belum Ada Riwayat Absensi</h3>
<p>Riwayat absensi Anda akan muncul di sini setelah mengikuti kegiatan.</p>
</div>
<?php endif; ?>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// ============================================
// GRAFIK 1: Tren Kehadiran per Minggu (LINE CHART)
// ============================================
const ctxTren = document.getElementById('chartTrenKehadiran');
if (ctxTren) {
new Chart(ctxTren.getContext('2d'), {
type: 'line',
data: {
labels: [
<?php $__currentLoopData = $dataGrafikMingguan; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $data): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
'<?php echo e($data["minggu"]); ?>',
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
],
datasets: [
{
label: 'Hadir',
data: [
<?php $__currentLoopData = $dataGrafikMingguan; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $data): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<?php echo e($data['hadir']); ?>,
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
],
borderColor: 'rgba(111, 186, 157, 1)',
backgroundColor: 'rgba(111, 186, 157, 0.2)',
borderWidth: 3,
pointRadius: 5,
pointBackgroundColor: 'rgba(111, 186, 157, 1)',
tension: 0.4,
fill: true
},
{
label: 'Total Kegiatan',
data: [
<?php $__currentLoopData = $dataGrafikMingguan; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $data): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<?php echo e($data['total']); ?>,
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
],
borderColor: 'rgba(129, 198, 232, 1)',
backgroundColor: 'rgba(129, 198, 232, 0.1)',
borderWidth: 2,
pointRadius: 4,
pointBackgroundColor: 'rgba(129, 198, 232, 1)',
tension: 0.4,
fill: true,
borderDash: [5, 5]
}
]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
display: true,
position: 'top',
labels: {
font: { size: 12, weight: '600' },
padding: 15
}
},
tooltip: {
callbacks: {
label: function(context) {
return context.dataset.label + ': ' + context.parsed.y;
}
}
}
},
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 1,
font: { size: 12, weight: '600' }
},
grid: { color: 'rgba(0, 0, 0, 0.05)' }
},
x: {
ticks: { font: { size: 12, weight: '600' } },
grid: { display: false }
}
}
}
});
}
// ============================================
// GRAFIK 2: Kehadiran per Kategori (BAR CHART)
// ============================================
const ctxKategori = document.getElementById('chartKategori');
if (ctxKategori) {
new Chart(ctxKategori.getContext('2d'), {
type: 'bar',
data: {
labels: [
<?php $__currentLoopData = $statsByKategori; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $stat): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
'<?php echo e($stat->nama_kategori); ?>',
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
],
datasets: [{
label: 'Kehadiran',
data: [
<?php $__currentLoopData = $statsByKategori; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $stat): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<?php echo e($stat->hadir); ?>,
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
],
backgroundColor: [
'rgba(111, 186, 157, 0.8)',
'rgba(129, 198, 232, 0.8)',
'rgba(255, 213, 107, 0.8)',
'rgba(255, 139, 148, 0.8)',
'rgba(179, 157, 219, 0.8)',
],
borderColor: [
'rgba(111, 186, 157, 1)',
'rgba(129, 198, 232, 1)',
'rgba(255, 213, 107, 1)',
'rgba(255, 139, 148, 1)',
'rgba(179, 157, 219, 1)',
],
borderWidth: 2,
borderRadius: 8,
borderSkipped: false
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: function(context) {
return 'Hadir: ' + context.parsed.y + ' kali';
}
}
}
},
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 1,
font: { size: 12, weight: '600' }
},
grid: { color: 'rgba(0, 0, 0, 0.05)' }
},
x: {
ticks: {
font: { size: 11 },
maxRotation: 45,
minRotation: 45
},
grid: { display: false }
}
}
}
});
}
});
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/santri/kegiatan/index.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,110 @@
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-calendar-alt"></i> Manajemen Semester</h2>
</div>
<?php if(session('success')): ?>
<div class="alert alert-success">
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
</div>
<?php endif; ?>
<?php if(session('error')): ?>
<div class="alert alert-danger">
<i class="fas fa-exclamation-circle"></i> <?php echo e(session('error')); ?>
</div>
<?php endif; ?>
<div class="content-header-flex">
<a href="<?php echo e(route('admin.semester.create')); ?>" class="btn btn-success">
<i class="fas fa-plus"></i> Tambah Semester
</a>
</div>
<div class="content-box">
<?php if($semesters->count() > 0): ?>
<table class="data-table">
<thead>
<tr>
<th style="width: 5%;">No</th>
<th style="width: 10%;">ID Semester</th>
<th style="width: 25%;">Nama Semester</th>
<th style="width: 15%;">Tahun Ajaran</th>
<th style="width: 10%;">Periode</th>
<th style="width: 15%;">Tanggal</th>
<th style="width: 10%;">Status</th>
<th class="text-center" style="width: 10%;">Aksi</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $semesters; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $semester): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><?php echo e($semesters->firstItem() + $index); ?></td>
<td><strong><?php echo e($semester->id_semester); ?></strong></td>
<td><?php echo e($semester->nama_semester); ?></td>
<td><?php echo e($semester->tahun_ajaran); ?></td>
<td class="text-center">
<span class="badge <?php echo e($semester->periode == 1 ? 'badge-info' : 'badge-warning'); ?>">
Semester <?php echo e($semester->periode); ?>
</span>
</td>
<td>
<small>
<?php echo e($semester->tanggal_mulai->format('d/m/Y')); ?> -<br>
<?php echo e($semester->tanggal_akhir->format('d/m/Y')); ?>
</small>
</td>
<td><?php echo $semester->status_badge; ?></td>
<td class="text-center">
<div class="btn-group">
<a href="<?php echo e(route('admin.semester.show', $semester)); ?>"
class="btn btn-sm btn-info" title="Detail">
<i class="fas fa-eye"></i>
</a>
<a href="<?php echo e(route('admin.semester.edit', $semester)); ?>"
class="btn btn-sm btn-warning" title="Edit">
<i class="fas fa-edit"></i>
</a>
<form action="<?php echo e(route('admin.semester.destroy', $semester)); ?>"
method="POST" style="display: inline-block;"
onsubmit="return confirm('Yakin ingin menghapus semester ini?')">
<?php echo csrf_field(); ?>
<?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-sm btn-danger" title="Hapus">
<i class="fas fa-trash"></i>
</button>
</form>
</div>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
<div style="margin-top: 20px;">
<?php echo e($semesters->links()); ?>
</div>
<?php else: ?>
<div class="empty-state">
<i class="fas fa-calendar-times"></i>
<h3>Belum Ada Semester</h3>
<p>Silakan tambahkan semester terlebih dahulu sebelum mengelola capaian santri.</p>
<a href="<?php echo e(route('admin.semester.create')); ?>" class="btn btn-primary">
<i class="fas fa-plus"></i> Tambah Semester Pertama
</a>
</div>
<?php endif; ?>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/semester/index.blade.php ENDPATH**/ ?>

View File

@ -18,9 +18,9 @@
<li>
<a href="#" class="<?php echo e(Request::routeIs('santri.absensi.*') ? 'active' : ''); ?>">
<a href="<?php echo e(route('santri.kegiatan.index')); ?>" class="<?php echo e(Request::routeIs('santri.kegiatan.*') ? 'active' : ''); ?>">
<i class="fas fa-calendar-check"></i>
<span>Riwayat Absensi</span>
<span>Kegiatan & Absensi</span>
</a>
</li>

View File

@ -56,6 +56,7 @@
<thead>
<tr>
<th>No</th>
<th>Foto</th>
<th>ID Santri</th>
<th>NIS</th>
<th>Nama Lengkap</th>
@ -68,7 +69,21 @@
<tbody>
<?php $__empty_1 = true; $__currentLoopData = $santris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
<tr>
<td><?php echo e($index + 1); ?></td>
<td><?php echo e($santris->firstItem() + $index); ?></td>
<td>
<?php if($santri->foto): ?>
<img src="<?php echo e(asset('storage/' . $santri->foto)); ?>"
alt="Foto <?php echo e($santri->nama_lengkap); ?>"
style="width: 40px; height: 40px; border-radius: 50%; object-fit: cover; border: 2px solid var(--primary-color);"
loading="lazy">
<?php else: ?>
<div class="santri-avatar-initial" style="width: 40px; height: 40px; border-radius: 50%; background: var(--primary-color); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 0.9rem;">
<?php echo e(strtoupper(substr($santri->nama_lengkap, 0, 1))); ?>
</div>
<?php endif; ?>
</td>
<td><strong><?php echo e($santri->id_santri); ?></strong></td>
<td><?php echo e($santri->nis ?? '-'); ?></td>
<td><?php echo e($santri->nama_lengkap); ?></td>
@ -108,7 +123,7 @@
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
<tr>
<td colspan="8" class="text-center" style="padding: 40px;">
<td colspan="9" class="text-center" style="padding: 40px;">
<i class="fas fa-inbox" style="font-size: 3rem; color: #ccc; margin-bottom: 15px; display: block;"></i>
<?php if(request('search') || request('status') || request('kelas')): ?>
<strong>Data tidak ditemukan.</strong><br>
@ -127,15 +142,15 @@
<div style="margin-top: 20px; padding-top: 20px; border-top: 1px solid #E8F7F2;">
<p style="color: #7F8C8D; font-size: 0.9rem;">
<i class="fas fa-info-circle"></i>
Menampilkan <strong><?php echo e($santris->count()); ?></strong> data santri
Menampilkan <strong><?php echo e($santris->count()); ?></strong> dari <strong><?php echo e($santris->total()); ?></strong> data santri
<?php if(request('search') || request('status') || request('kelas')): ?>
dari hasil pencarian/filter
(hasil pencarian/filter)
<?php endif; ?>
</p>
</div>
<?php endif; ?>
<!-- Pagination (jika menggunakan paginate) -->
<!-- Pagination -->
<?php if(method_exists($santris, 'links')): ?>
<div style="margin-top: 20px;">
<?php echo e($santris->links()); ?>

View File

@ -0,0 +1,282 @@
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-clipboard-check"></i> Input Absensi: <?php echo e($kegiatan->nama_kegiatan); ?></h2>
</div>
<div class="content-box" style="margin-bottom: 20px;">
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;">
<div>
<h3 style="margin: 0; color: var(--primary-color);"><?php echo e($kegiatan->nama_kegiatan); ?></h3>
<p style="margin: 5px 0 0 0; color: var(--text-light);">
<i class="fas fa-calendar-day"></i> <?php echo e($kegiatan->hari); ?> |
<i class="fas fa-clock"></i> <?php echo e(date('H:i', strtotime($kegiatan->waktu_mulai))); ?> - <?php echo e(date('H:i', strtotime($kegiatan->waktu_selesai))); ?> |
<i class="fas fa-list-alt"></i> <?php echo e($kegiatan->kategori->nama_kategori); ?>
</p>
</div>
<div style="display: flex; gap: 10px;">
<button type="button" id="btnModeManual" class="btn btn-primary" onclick="setMode('manual')">
<i class="fas fa-hand-pointer"></i> Mode Manual
</button>
<button type="button" id="btnModeRfid" class="btn btn-success" onclick="setMode('rfid')">
<i class="fas fa-id-card"></i> Mode RFID
</button>
</div>
</div>
</div>
<!-- MODE MANUAL -->
<div id="modeManual" class="content-box">
<form action="<?php echo e(route('admin.absensi-kegiatan.simpan')); ?>" method="POST">
<?php echo csrf_field(); ?>
<input type="hidden" name="kegiatan_id" value="<?php echo e($kegiatan->kegiatan_id); ?>">
<div class="form-group">
<label for="tanggal">
<i class="fas fa-calendar form-icon"></i>
Tanggal Absensi
</label>
<input type="date" name="tanggal" id="tanggal" class="form-control" value="<?php echo e($tanggal); ?>" required>
</div>
<div class="info-box">
<p><i class="fas fa-info-circle"></i> Pilih status absensi untuk setiap santri. Jika tidak dipilih, akan dianggap <strong>Alpa</strong>.</p>
</div>
<table class="data-table">
<thead>
<tr>
<th style="width: 50px;">No</th>
<th style="width: 100px;">ID Santri</th>
<th>Nama Santri</th>
<th style="width: 100px;">Kelas</th>
<th style="width: 300px; text-align: center;">Status</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $santris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><?php echo e($index + 1); ?></td>
<td><strong><?php echo e($santri->id_santri); ?></strong></td>
<td><?php echo e($santri->nama_lengkap); ?></td>
<td><span class="badge badge-secondary"><?php echo e($santri->kelas); ?></span></td>
<td class="text-center">
<?php
$currentStatus = $absensiData[$santri->id_santri] ?? 'Alpa';
?>
<div style="display: flex; gap: 8px; justify-content: center;">
<label style="margin: 0; cursor: pointer;">
<input type="radio" name="absensi[<?php echo e($santri->id_santri); ?>]" value="Hadir"
<?php echo e($currentStatus == 'Hadir' ? 'checked' : ''); ?> required>
<span class="badge badge-success">Hadir</span>
</label>
<label style="margin: 0; cursor: pointer;">
<input type="radio" name="absensi[<?php echo e($santri->id_santri); ?>]" value="Izin"
<?php echo e($currentStatus == 'Izin' ? 'checked' : ''); ?>>
<span class="badge badge-warning">Izin</span>
</label>
<label style="margin: 0; cursor: pointer;">
<input type="radio" name="absensi[<?php echo e($santri->id_santri); ?>]" value="Sakit"
<?php echo e($currentStatus == 'Sakit' ? 'checked' : ''); ?>>
<span class="badge badge-info">Sakit</span>
</label>
<label style="margin: 0; cursor: pointer;">
<input type="radio" name="absensi[<?php echo e($santri->id_santri); ?>]" value="Alpa"
<?php echo e($currentStatus == 'Alpa' ? 'checked' : ''); ?>>
<span class="badge badge-danger">Alpa</span>
</label>
</div>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
<div class="btn-group" style="margin-top: 20px;">
<button type="submit" class="btn btn-success">
<i class="fas fa-save"></i> Simpan Absensi
</button>
<a href="<?php echo e(route('admin.absensi-kegiatan.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</form>
</div>
<!-- MODE RFID -->
<div id="modeRfid" class="content-box" style="display: none;">
<div class="form-group">
<label for="tanggalRfid">
<i class="fas fa-calendar form-icon"></i>
Tanggal Absensi
</label>
<input type="date" id="tanggalRfid" class="form-control" value="<?php echo e($tanggal); ?>">
</div>
<div class="info-box">
<p><i class="fas fa-id-card"></i> Tempelkan kartu RFID santri ke reader. Absensi akan otomatis tersimpan sebagai <strong>Hadir</strong>.</p>
</div>
<div style="background: linear-gradient(135deg, var(--primary-light) 0%, #D4F1E3 100%); padding: 30px; border-radius: var(--border-radius); text-align: center; margin-bottom: 20px;">
<div id="rfidStatus" style="font-size: 1.5rem; font-weight: 600; color: var(--primary-color); margin-bottom: 15px;">
<i class="fas fa-wifi"></i> Siap Scan RFID
</div>
<input type="text" id="rfidInput" placeholder="Fokus di sini untuk scan RFID..."
style="width: 100%; padding: 15px; font-size: 1.2rem; border: 3px solid var(--primary-color); border-radius: var(--border-radius-sm); text-align: center;"
autofocus>
</div>
<div id="rfidLog" style="max-height: 400px; overflow-y: auto; background: white; border-radius: var(--border-radius-sm); padding: 15px; border: 1px solid var(--primary-light);">
<h4 style="margin: 0 0 15px 0; color: var(--primary-color);"><i class="fas fa-history"></i> Log Absensi</h4>
<div id="rfidLogContent">
<p style="text-align: center; color: var(--text-light);">Belum ada absensi...</p>
</div>
</div>
<div class="btn-group" style="margin-top: 20px;">
<button type="button" class="btn btn-warning" onclick="clearLog()">
<i class="fas fa-trash"></i> Bersihkan Log
</button>
<a href="<?php echo e(route('admin.absensi-kegiatan.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</div>
<script>
let currentMode = 'manual';
const kegiatanId = '<?php echo e($kegiatan->kegiatan_id); ?>';
function setMode(mode) {
currentMode = mode;
if (mode === 'manual') {
document.getElementById('modeManual').style.display = 'block';
document.getElementById('modeRfid').style.display = 'none';
document.getElementById('btnModeManual').classList.add('btn-primary');
document.getElementById('btnModeManual').classList.remove('btn-secondary');
document.getElementById('btnModeRfid').classList.remove('btn-success');
document.getElementById('btnModeRfid').classList.add('btn-secondary');
} else {
document.getElementById('modeManual').style.display = 'none';
document.getElementById('modeRfid').style.display = 'block';
document.getElementById('btnModeManual').classList.remove('btn-primary');
document.getElementById('btnModeManual').classList.add('btn-secondary');
document.getElementById('btnModeRfid').classList.add('btn-success');
document.getElementById('btnModeRfid').classList.remove('btn-secondary');
document.getElementById('rfidInput').focus();
}
}
// RFID Scanner Handler
document.getElementById('rfidInput').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
const rfidUid = this.value.trim();
if (rfidUid) {
scanRfid(rfidUid);
this.value = '';
}
}
});
function scanRfid(rfidUid) {
const tanggal = document.getElementById('tanggalRfid').value;
const statusEl = document.getElementById('rfidStatus');
statusEl.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
statusEl.style.color = 'var(--warning-color)';
fetch('<?php echo e(route("admin.absensi-kegiatan.scan-rfid")); ?>', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': '<?php echo e(csrf_token()); ?>'
},
body: JSON.stringify({
rfid_uid: rfidUid,
kegiatan_id: kegiatanId,
tanggal: tanggal
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
statusEl.innerHTML = '<i class="fas fa-check-circle"></i> ' + data.message;
statusEl.style.color = 'var(--success-color)';
addLogEntry(data.data, 'success');
playSound('success');
} else {
statusEl.innerHTML = '<i class="fas fa-exclamation-circle"></i> ' + data.message;
statusEl.style.color = 'var(--danger-color)';
playSound('error');
}
setTimeout(() => {
statusEl.innerHTML = '<i class="fas fa-wifi"></i> Siap Scan RFID';
statusEl.style.color = 'var(--primary-color)';
}, 2000);
})
.catch(error => {
statusEl.innerHTML = '<i class="fas fa-times-circle"></i> Koneksi error';
statusEl.style.color = 'var(--danger-color)';
console.error('Error:', error);
setTimeout(() => {
statusEl.innerHTML = '<i class="fas fa-wifi"></i> Siap Scan RFID';
statusEl.style.color = 'var(--primary-color)';
}, 2000);
});
}
function addLogEntry(data, type) {
const logContent = document.getElementById('rfidLogContent');
if (logContent.querySelector('p')) {
logContent.innerHTML = '';
}
const entry = document.createElement('div');
entry.style.cssText = 'padding: 12px; margin-bottom: 10px; border-radius: 8px; background: ' +
(type === 'success' ? 'linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%)' : 'linear-gradient(135deg, #FFE8EA 0%, #FFD5D8 100%)') +
'; border-left: 4px solid ' + (type === 'success' ? 'var(--success-color)' : 'var(--danger-color)');
entry.innerHTML = `
<div style="display: flex; justify-content: space-between; align-items: center;">
<div>
<strong>${data.nama}</strong> (${data.id_santri})
<div style="font-size: 0.85rem; color: var(--text-light); margin-top: 3px;">
Kelas: ${data.kelas} | Waktu: ${data.waktu}
</div>
</div>
<span class="badge badge-success"><i class="fas fa-check"></i> Hadir</span>
</div>
`;
logContent.insertBefore(entry, logContent.firstChild);
}
function clearLog() {
if (confirm('Yakin ingin membersihkan log?')) {
document.getElementById('rfidLogContent').innerHTML = '<p style="text-align: center; color: var(--text-light);">Belum ada absensi...</p>';
}
}
function playSound(type) {
// Bisa ditambahkan audio feedback
const audio = new Audio(type === 'success' ? '/sounds/success.mp3' : '/sounds/error.mp3');
audio.play().catch(() => {}); // Ignore errors
}
// Auto-focus kembali ke input RFID jika kehilangan fokus
setInterval(() => {
if (currentMode === 'rfid' && document.activeElement !== document.getElementById('rfidInput')) {
document.getElementById('rfidInput').focus();
}
}, 1000);
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/absensi/input.blade.php ENDPATH**/ ?>

View File

@ -1,82 +0,0 @@
<?php $__env->startSection('title', 'Register Admin'); ?>
<?php $__env->startSection('auth-content'); ?>
<div class="auth-header">
<div class="logo-circle">
<i class="fas fa-lock-open fa-2x"></i>
</div>
<h2>Pendaftaran Akun Admin</h2>
<p>Mohon gunakan email dan password yang kuat untuk keamanan sistem.</p>
</div>
<?php if($errors->any()): ?>
<div class="alert alert-danger">
<?php $__currentLoopData = $errors->all(); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $error): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<p><?php echo e($error); ?></p>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</div>
<?php endif; ?>
<form method="POST" action="<?php echo e(route('admin.register')); ?>" class="data-form">
<?php echo csrf_field(); ?>
<div class="form-group">
<label for="email"><i class="fas fa-envelope form-icon"></i> Email Admin</label>
<input type="email" id="email" name="email" value="<?php echo e(old('email')); ?>" class="form-control <?php $__errorArgs = ['email'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>" required autofocus>
<?php $__errorArgs = ['email'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?><div class="invalid-feedback"><?php echo e($message); ?></div><?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div class="form-group">
<label for="password"><i class="fas fa-key form-icon"></i> Password</label>
<input type="password" id="password" name="password" class="form-control <?php $__errorArgs = ['password'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>" required>
<?php $__errorArgs = ['password'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?><div class="invalid-feedback"><?php echo e($message); ?></div><?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div class="form-group">
<label for="password_confirmation"><i class="fas fa-lock form-icon"></i> Konfirmasi Password</label>
<input type="password" id="password_confirmation" name="password_confirmation" class="form-control" required>
</div>
<div class="form-group action-group">
<button type="submit" class="btn btn-success btn-full hover-shadow">
<i class="fas fa-paper-plane"></i> Daftarkan Admin
</button>
</div>
<p style="text-align: center; font-size: 0.9rem; margin-top: 20px;">
Sudah punya akun? <a href="<?php echo e(route('admin.login')); ?>" class="link-primary">Login di sini</a>
</p>
</form>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('auth.auth_layout', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/auth/register.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,135 @@
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-book-open"></i> Master Materi Al-Qur'an & Hadist</h2>
</div>
<?php if(session('success')): ?>
<div class="alert alert-success">
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
</div>
<?php endif; ?>
<?php if(session('error')): ?>
<div class="alert alert-danger">
<i class="fas fa-exclamation-circle"></i> <?php echo e(session('error')); ?>
</div>
<?php endif; ?>
<div class="content-box" style="margin-bottom: 20px;">
<form method="GET" action="<?php echo e(route('admin.materi.index')); ?>" class="filter-form-inline">
<select name="kategori" class="form-control" style="width: 200px;">
<option value="">Semua Kategori</option>
<option value="Al-Qur'an" <?php echo e(request('kategori') == 'Al-Qur\'an' ? 'selected' : ''); ?>>Al-Qur'an</option>
<option value="Hadist" <?php echo e(request('kategori') == 'Hadist' ? 'selected' : ''); ?>>Hadist</option>
<option value="Materi Tambahan" <?php echo e(request('kategori') == 'Materi Tambahan' ? 'selected' : ''); ?>>Materi Tambahan</option>
</select>
<select name="kelas" class="form-control" style="width: 180px;">
<option value="">Semua Kelas</option>
<option value="Lambatan" <?php echo e(request('kelas') == 'Lambatan' ? 'selected' : ''); ?>>Lambatan</option>
<option value="Cepatan" <?php echo e(request('kelas') == 'Cepatan' ? 'selected' : ''); ?>>Cepatan</option>
<option value="PB" <?php echo e(request('kelas') == 'PB' ? 'selected' : ''); ?>>PB</option>
</select>
<input type="text" name="search" class="form-control" placeholder="Cari nama kitab..."
value="<?php echo e(request('search')); ?>" style="width: 250px;">
<button type="submit" class="btn btn-primary">
<i class="fas fa-search"></i> Filter
</button>
<?php if(request()->anyFilled(['kategori', 'kelas', 'search'])): ?>
<a href="<?php echo e(route('admin.materi.index')); ?>" class="btn btn-secondary">
<i class="fas fa-redo"></i> Reset
</a>
<?php endif; ?>
<a href="<?php echo e(route('admin.materi.create')); ?>" class="btn btn-success" style="margin-left: auto;">
<i class="fas fa-plus"></i> Tambah Materi
</a>
</form>
</div>
<div class="content-box">
<?php if($materis->count() > 0): ?>
<table class="data-table">
<thead>
<tr>
<th style="width: 5%;">No</th>
<th style="width: 10%;">ID Materi</th>
<th style="width: 15%;">Kategori</th>
<th style="width: 10%;">Kelas</th>
<th style="width: 25%;">Nama Kitab</th>
<th style="width: 15%;">Halaman</th>
<th style="width: 10%;">Total Hal</th>
<th class="text-center" style="width: 10%;">Aksi</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $materis; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $materi): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><?php echo e($materis->firstItem() + $index); ?></td>
<td><strong><?php echo e($materi->id_materi); ?></strong></td>
<td><?php echo $materi->kategori_badge; ?></td>
<td><?php echo $materi->kelas_badge; ?></td>
<td><?php echo e($materi->nama_kitab); ?></td>
<td>
<span class="badge badge-info">
<?php echo e($materi->halaman_mulai); ?> - <?php echo e($materi->halaman_akhir); ?>
</span>
</td>
<td class="text-center">
<strong><?php echo e($materi->total_halaman); ?></strong> hal
</td>
<td class="text-center">
<div class="btn-group">
<a href="<?php echo e(route('admin.materi.show', $materi)); ?>"
class="btn btn-sm btn-info" title="Detail">
<i class="fas fa-eye"></i>
</a>
<a href="<?php echo e(route('admin.materi.edit', $materi)); ?>"
class="btn btn-sm btn-warning" title="Edit">
<i class="fas fa-edit"></i>
</a>
<form action="<?php echo e(route('admin.materi.destroy', $materi)); ?>"
method="POST" style="display: inline-block;"
onsubmit="return confirm('Yakin ingin menghapus materi <?php echo e($materi->nama_kitab); ?>?')">
<?php echo csrf_field(); ?>
<?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-sm btn-danger" title="Hapus">
<i class="fas fa-trash"></i>
</button>
</form>
</div>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
<div style="margin-top: 20px;">
<?php echo e($materis->links()); ?>
</div>
<?php else: ?>
<div class="empty-state">
<i class="fas fa-book-open"></i>
<h3>Belum Ada Data Materi</h3>
<p>Silakan tambahkan materi pembelajaran Al-Qur'an, Hadist, atau Materi Tambahan.</p>
<a href="<?php echo e(route('admin.materi.create')); ?>" class="btn btn-primary">
<i class="fas fa-plus"></i> Tambah Materi Pertama
</a>
</div>
<?php endif; ?>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/materi/index.blade.php ENDPATH**/ ?>

View File

@ -8,6 +8,12 @@
<p style="margin: 5px 0 0 0; color: var(--text-light);">
Selamat datang, <strong><?php echo e($data['nama_santri']); ?></strong> - Kelas <?php echo e($data['kelas']); ?>
<?php if($semesterAktif): ?>
<span class="badge badge-success" style="margin-left: 10px;">
<i class="fas fa-calendar-alt"></i> <?php echo e($semesterAktif->nama_semester); ?>
</span>
<?php endif; ?>
</p>
</div>
@ -34,65 +40,57 @@
<div class="row-cards">
<div class="card card-info">
<div class="card card-success">
<h3><i class="fas fa-book-quran"></i> Progres Al-Qur'an</h3>
<div class="card-value"><?php echo e($data['progres_quran']); ?>%</div>
<div class="card-icon"><i class="fas fa-book-quran"></i></div>
<div style="margin-top: 10px;">
<div class="progress-bar">
<div class="progress-fill" style="width: <?php echo e($data['progres_quran']); ?>%; background: var(--info-color);"></div>
<div class="progress-fill" style="width: <?php echo e($data['progres_quran']); ?>%; background: var(--success-color);"></div>
</div>
</div>
</div>
<div class="card card-info">
<h3><i class="fas fa-scroll"></i> Progres Hadist</h3>
<div class="card-value"><?php echo e($data['progres_hadist']); ?>%</div>
<div class="card-icon"><i class="fas fa-scroll"></i></div>
<div style="margin-top: 10px;">
<div class="progress-bar">
<div class="progress-fill" style="width: <?php echo e($data['progres_hadist']); ?>%; background: var(--info-color);"></div>
</div>
</div>
</div>
<div class="card card-warning">
<h3><i class="fas fa-book"></i> Materi Tambahan</h3>
<div class="card-value"><?php echo e($data['progres_materi_tambahan']); ?>%</div>
<div class="card-icon"><i class="fas fa-book"></i></div>
<div style="margin-top: 10px;">
<div class="progress-bar">
<div class="progress-fill" style="width: <?php echo e($data['progres_materi_tambahan']); ?>%; background: var(--warning-color);"></div>
</div>
</div>
</div>
<div class="card card-primary">
<h3><i class="fas fa-scroll"></i> Progres Hadist</h3>
<div class="card-value"><?php echo e($data['progres_hadist']); ?>%</div>
<div class="card-icon"><i class="fas fa-scroll"></i></div>
<div style="margin-top: 10px;">
<div class="progress-bar">
<div class="progress-fill" style="width: <?php echo e($data['progres_hadist']); ?>%; background: var(--primary-color);"></div>
</div>
</div>
</div>
<div class="card card-success">
<h3><i class="fas fa-wallet"></i> Saldo Uang Saku</h3>
<div class="card-value"><?php echo e('Rp ' . number_format($data['saldo_uang_saku'], 0, ',', '.')); ?></div>
<div class="card-value-small"><?php echo e('Rp ' . number_format($data['saldo_uang_saku'], 0, ',', '.')); ?></div>
<div class="card-icon"><i class="fas fa-wallet"></i></div>
<div style="margin-top: 10px;">
<a href="<?php echo e(route('santri.uang-saku.index')); ?>" class="btn btn-sm btn-success" style="width: 100%; justify-content: center;">
<a href="<?php echo e(route('santri.uang-saku.index')); ?>" class="btn btn-sm btn-primary" style="width: 100%; justify-content: center;">
<i class="fas fa-eye"></i> Lihat Riwayat
</a>
</div>
</div>
<div class="card card-<?php echo e($data['poin_pelanggaran'] > 0 ? 'danger' : 'warning'); ?>">
<h3><i class="fas fa-exclamation-triangle"></i> Total Poin Pelanggaran</h3>
<div class="card-value"><?php echo e($data['poin_pelanggaran']); ?></div>
<div class="card-icon"><i class="fas fa-exclamation-triangle"></i></div>
<?php if($data['poin_pelanggaran'] > 0): ?>
<div style="margin-top: 10px;">
<a href="<?php echo e(route('santri.pelanggaran.index')); ?>" class="btn btn-sm btn-danger" style="width: 100%; justify-content: center;">
<i class="fas fa-eye"></i> Lihat Riwayat
</a>
</div>
<?php else: ?>
<div style="margin-top: 10px;">
<span class="badge badge-success">
<i class="fas fa-check-circle"></i> Tidak ada pelanggaran
</span>
</div>
<?php endif; ?>
</div>
</div>
<?php if($beritaTerbaru->isNotEmpty()): ?>
<div class="content-box" style="margin-top: 20px;">
<div class="content-box" style="margin-top: 25px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
<h3 style="margin: 0; color: var(--primary-color);">
<i class="fas fa-newspaper"></i> Berita Terbaru (7 Hari Terakhir)
@ -129,62 +127,163 @@
<?php endif; ?>
<div class="content-box" style="margin-top: 20px;">
<h3 style="margin: 0 0 20px 0; color: var(--primary-color);">
<i class="fas fa-bolt"></i> Akses Cepat
<div class="content-box" style="margin-top: 25px;">
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;">
<div style="flex: 1;">
<h3 style="margin: 0 0 5px 0; color: var(--<?php echo e($data['poin_pelanggaran'] > 0 ? 'danger' : 'success'); ?>-color);">
<i class="fas fa-exclamation-triangle"></i> Total Poin Pelanggaran: <strong><?php echo e($data['poin_pelanggaran']); ?></strong>
</h3>
<?php if($data['poin_pelanggaran'] > 0): ?>
<p style="margin: 0; color: var(--text-light); font-size: 0.9rem;">
Anda memiliki <?php echo e($data['poin_pelanggaran']); ?> poin pelanggaran. Jaga kedisiplinan!
</p>
<?php else: ?>
<p style="margin: 0; color: var(--text-light); font-size: 0.9rem;">
<i class="fas fa-check-circle" style="color: var(--success-color);"></i> Alhamdulillah, tidak ada catatan pelanggaran.
</p>
<?php endif; ?>
</div>
<a href="<?php echo e(route('santri.pelanggaran.index')); ?>" class="btn btn-<?php echo e($data['poin_pelanggaran'] > 0 ? 'danger' : 'success'); ?>">
<i class="fas fa-eye"></i> Lihat Riwayat
</a>
</div>
</div>
<?php if($capaianPerMateri->count() > 0 || array_sum($distribusiStatus) > 0): ?>
<div class="content-box" style="margin-top: 25px;">
<h3 style="margin-bottom: 20px; color: var(--primary-dark);">
<i class="fas fa-chart-line"></i> Visualisasi Capaian Pembelajaran
</h3>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
<a href="<?php echo e(route('santri.profil.index')); ?>" class="btn btn-primary hover-lift" style="padding: 15px; text-align: center;">
<i class="fas fa-user" style="font-size: 1.5rem; display: block; margin-bottom: 8px;"></i>
<span style="font-size: 0.9rem;">Profil Saya</span>
</a>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 25px; margin-bottom: 30px;">
<a href="<?php echo e(route('santri.berita.index')); ?>" class="btn btn-info hover-lift" style="padding: 15px; text-align: center;">
<i class="fas fa-newspaper" style="font-size: 1.5rem; display: block; margin-bottom: 8px;"></i>
<span style="font-size: 0.9rem;">Berita</span>
</a>
<?php if(array_sum($distribusiStatus) > 0): ?>
<div style="background: white; padding: 25px; border-radius: var(--border-radius); box-shadow: var(--shadow-md); border: 2px solid var(--primary-light);">
<h4 style="margin: 0 0 20px 0; font-size: 1.1rem; color: var(--text-color); text-align: center; font-weight: 700;">
<i class="fas fa-chart-pie"></i> Distribusi Status Pembelajaran
</h4>
<a href="<?php echo e(route('santri.uang-saku.index')); ?>" class="btn btn-success hover-lift" style="padding: 15px; text-align: center;">
<i class="fas fa-wallet" style="font-size: 1.5rem; display: block; margin-bottom: 8px;"></i>
<span style="font-size: 0.9rem;">Uang Saku</span>
</a>
<div style="display: flex; align-items: center; gap: 25px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 250px; max-width: 350px;">
<canvas id="chartPieStatus" style="max-height: 300px;"></canvas>
</div>
<a href="<?php echo e(route('santri.pelanggaran.index')); ?>" class="btn btn-danger hover-lift" style="padding: 15px; text-align: center;">
<i class="fas fa-exclamation-circle" style="font-size: 1.5rem; display: block; margin-bottom: 8px;"></i>
<span style="font-size: 0.9rem;">Pelanggaran</span>
</a>
<div style="flex: 1; min-width: 200px; display: flex; flex-direction: column; gap: 12px;">
<div style="display: flex; align-items: center; gap: 10px;">
<div style="width: 24px; height: 24px; background: linear-gradient(135deg, #6FBA9D 0%, #5EA98C 100%); border-radius: 4px; flex-shrink: 0;"></div>
<div style="flex: 1;">
<div style="font-weight: 700; color: var(--text-color); font-size: 0.9rem;">Selesai (100%)</div>
<div style="font-size: 0.75rem; color: var(--text-light);"><?php echo e($distribusiStatus['selesai']); ?> materi</div>
</div>
</div>
<div style="display: flex; align-items: center; gap: 10px;">
<div style="width: 24px; height: 24px; background: linear-gradient(135deg, #81C6E8 0%, #6AB0D4 100%); border-radius: 4px; flex-shrink: 0;"></div>
<div style="flex: 1;">
<div style="font-weight: 700; color: var(--text-color); font-size: 0.9rem;">Hampir Selesai (75-99%)</div>
<div style="font-size: 0.75rem; color: var(--text-light);"><?php echo e($distribusiStatus['hampir_selesai']); ?> materi</div>
</div>
</div>
<a href="<?php echo e(route('santri.kesehatan.index')); ?>" class="btn btn-<?php echo e(isset($statusKesehatan) && $statusKesehatan ? 'danger' : 'info'); ?> hover-lift" style="padding: 15px; text-align: center; position: relative;">
<i class="fas fa-heartbeat" style="font-size: 1.5rem; display: block; margin-bottom: 8px;"></i>
<span style="font-size: 0.9rem;">Kesehatan</span>
<?php if(isset($statusKesehatan) && $statusKesehatan): ?>
<span class="badge badge-light" style="display: block; margin-top: 5px; font-size: 0.75rem; background: rgba(255,255,255,0.9); color: var(--danger-color);">
<i class="fas fa-exclamation-circle"></i> Sedang Dirawat
</span>
<?php endif; ?>
</a>
<div style="display: flex; align-items: center; gap: 10px;">
<div style="width: 24px; height: 24px; background: linear-gradient(135deg, #FFD56B 0%, #E6B85C 100%); border-radius: 4px; flex-shrink: 0;"></div>
<div style="flex: 1;">
<div style="font-weight: 700; color: var(--text-color); font-size: 0.9rem;">Sedang Berjalan (25-74%)</div>
<div style="font-size: 0.75rem; color: var(--text-light);"><?php echo e($distribusiStatus['sedang_berjalan']); ?> materi</div>
</div>
</div>
<a href="<?php echo e(route('santri.kepulangan.index')); ?>" class="btn btn-<?php echo e(isset($kepulanganAktif) && $kepulanganAktif ? 'info' : 'primary'); ?> hover-lift" style="padding: 15px; text-align: center; position: relative;">
<i class="fas fa-home" style="font-size: 1.5rem; display: block; margin-bottom: 8px;"></i>
<span style="font-size: 0.9rem;">Kepulangan</span>
<?php if(isset($kepulanganAktif) && $kepulanganAktif): ?>
<span class="badge badge-light" style="display: block; margin-top: 5px; font-size: 0.75rem; background: rgba(255,255,255,0.9); color: var(--info-color);">
<i class="fas fa-home"></i> Sedang Pulang
</span>
<?php endif; ?>
</a>
<div style="display: flex; align-items: center; gap: 10px;">
<div style="width: 24px; height: 24px; background: linear-gradient(135deg, #FF8B94 0%, #E77580 100%); border-radius: 4px; flex-shrink: 0;"></div>
<div style="flex: 1;">
<div style="font-weight: 700; color: var(--text-color); font-size: 0.9rem;">Baru Dimulai (0-24%)</div>
<div style="font-size: 0.75rem; color: var(--text-light);"><?php echo e($distribusiStatus['baru_dimulai']); ?> materi</div>
</div>
</div>
</div>
</div>
<div class="content-box" style="margin-top: 20px; background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); border: 2px solid var(--primary-color);">
<div style="margin-top: 20px; padding-top: 20px; border-top: 1px solid #f0f0f0; display: flex; justify-content: space-between; gap: 8px; flex-wrap: wrap;">
<div style="flex: 1; min-width: 70px; text-align: center; padding: 10px 8px; background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
<div style="font-size: 1.3rem; font-weight: 700; color: var(--success-color); line-height: 1;"><?php echo e($distribusiStatus['selesai']); ?></div>
<div style="font-size: 0.75rem; color: var(--text-color); font-weight: 600; margin-top: 4px; line-height: 1.2;">Selesai</div>
</div>
<div style="flex: 1; min-width: 70px; text-align: center; padding: 10px 8px; background: linear-gradient(135deg, #E3F2FD 0%, #D1E9F9 100%); border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
<div style="font-size: 1.3rem; font-weight: 700; color: var(--info-color); line-height: 1;"><?php echo e($distribusiStatus['hampir_selesai']); ?></div>
<div style="font-size: 0.75rem; color: var(--text-color); font-weight: 600; margin-top: 4px; line-height: 1.2;">Hampir Selesai</div>
</div>
<div style="flex: 1; min-width: 70px; text-align: center; padding: 10px 8px; background: linear-gradient(135deg, #FFF8E1 0%, #FFF3CD 100%); border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
<div style="font-size: 1.3rem; font-weight: 700; color: var(--warning-color); line-height: 1;"><?php echo e($distribusiStatus['sedang_berjalan']); ?></div>
<div style="font-size: 0.75rem; color: var(--text-color); font-weight: 600; margin-top: 4px; line-height: 1.2;">Sedang Berjalan</div>
</div>
<div style="flex: 1; min-width: 70px; text-align: center; padding: 10px 8px; background: linear-gradient(135deg, #FFE8EA 0%, #FFD5D8 100%); border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
<div style="font-size: 1.3rem; font-weight: 700; color: var(--danger-color); line-height: 1;"><?php echo e($distribusiStatus['baru_dimulai']); ?></div>
<div style="font-size: 0.75rem; color: var(--text-color); font-weight: 600; margin-top: 4px; line-height: 1.2;">Baru Dimulai</div>
</div>
</div>
</div>
<?php endif; ?>
<div style="background: white; padding: 25px; border-radius: var(--border-radius); box-shadow: var(--shadow-md); border: 2px solid var(--primary-light);">
<h4 style="margin: 0 0 20px 0; font-size: 1.1rem; color: var(--text-color); text-align: center; font-weight: 700;">
<i class="fas fa-chart-line"></i> Perbandingan Progress Kategori
</h4>
<div style="max-width: 450px; margin: 0 auto;">
<canvas id="chartLineKategori" style="max-height: 300px;"></canvas>
</div>
<div style="margin-top: 20px; display: flex; justify-content: center; gap: 20px; flex-wrap: wrap;">
<div style="text-align: center;">
<div style="width: 60px; height: 60px; border-radius: 50%; background: linear-gradient(135deg, var(--success-color), #5EA98C); display: flex; align-items: center; justify-content: center; margin: 0 auto 8px; color: white; font-size: 1.1rem; font-weight: 700; box-shadow: 0 4px 8px rgba(111, 186, 157, 0.3);">
<?php echo e($data['progres_quran']); ?>%
</div>
<div style="font-size: 0.85rem; color: var(--text-color); font-weight: 600;">Al-Qur'an</div>
</div>
<div style="text-align: center;">
<div style="width: 60px; height: 60px; border-radius: 50%; background: linear-gradient(135deg, var(--info-color), #6AB0D4); display: flex; align-items: center; justify-content: center; margin: 0 auto 8px; color: white; font-size: 1.1rem; font-weight: 700; box-shadow: 0 4px 8px rgba(129, 198, 232, 0.3);">
<?php echo e($data['progres_hadist']); ?>%
</div>
<div style="font-size: 0.85rem; color: var(--text-color); font-weight: 600;">Hadist</div>
</div>
<div style="text-align: center;">
<div style="width: 60px; height: 60px; border-radius: 50%; background: linear-gradient(135deg, var(--warning-color), #E6B85C); display: flex; align-items: center; justify-content: center; margin: 0 auto 8px; color: white; font-size: 1.1rem; font-weight: 700; box-shadow: 0 4px 8px rgba(255, 213, 107, 0.3);">
<?php echo e($data['progres_materi_tambahan']); ?>%
</div>
<div style="font-size: 0.85rem; color: var(--text-color); font-weight: 600;">Materi Tambahan</div>
</div>
</div>
</div>
</div>
</div>
<?php endif; ?>
<?php if($capaianPerMateri->count() > 0): ?>
<div class="content-box" style="margin-top: 25px;">
<h3 style="margin-bottom: 20px; color: var(--primary-dark);">
<i class="fas fa-chart-bar"></i> Progress per Materi (Top 10)
</h3>
<div style="background: white; padding: 25px; border-radius: var(--border-radius); box-shadow: var(--shadow-sm); border: 2px solid var(--primary-light);">
<canvas id="chartBarMateri" style="max-height: 450px;"></canvas>
</div>
<div style="margin-top: 20px; text-align: center;">
<a href="<?php echo e(route('santri.capaian.index')); ?>" class="btn btn-primary">
<i class="fas fa-list"></i> Lihat Semua Capaian Detail
</a>
</div>
</div>
<?php endif; ?>
<div class="content-box" style="margin-top: 25px; background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); border: 2px solid var(--primary-color);">
<h4 style="margin: 0 0 15px 0; color: var(--primary-dark);">
<i class="fas fa-lightbulb"></i> Tips Hari Ini
</h4>
@ -194,5 +293,268 @@
untuk mengetahui peraturan yang berlaku.
</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// ============================================
// GRAFIK 1: Distribusi Status (PIE CHART)
// ============================================
<?php if(array_sum($distribusiStatus) > 0): ?>
const ctxPieStatus = document.getElementById('chartPieStatus');
if (ctxPieStatus) {
new Chart(ctxPieStatus.getContext('2d'), {
type: 'pie',
data: {
// labels: ['Selesai (100%)', 'Hampir Selesai (75-99%)', 'Sedang Berjalan (25-74%)', 'Baru Dimulai (0-24%)'],
datasets: [{
data: [
<?php echo e($distribusiStatus['selesai']); ?>,
<?php echo e($distribusiStatus['hampir_selesai']); ?>,
<?php echo e($distribusiStatus['sedang_berjalan']); ?>,
<?php echo e($distribusiStatus['baru_dimulai']); ?>
],
backgroundColor: [
'rgba(111, 186, 157, 0.9)',
'rgba(129, 198, 232, 0.9)',
'rgba(255, 213, 107, 0.9)',
'rgba(255, 139, 148, 0.9)',
],
borderColor: '#fff',
borderWidth: 3
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
position: 'bottom',
labels: {
padding: 15,
font: {
size: 12,
weight: '600'
}
}
},
tooltip: {
callbacks: {
label: function(context) {
const label = context.label || '';
const value = context.parsed || 0;
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = total > 0 ? ((value / total) * 100).toFixed(1) : 0;
return label + ': ' + value + ' materi (' + percentage + '%)';
}
}
}
}
}
});
}
<?php endif; ?>
// ============================================
// GRAFIK 2: Perbandingan Kategori (LINE CHART)
// ============================================
const ctxLineKategori = document.getElementById('chartLineKategori');
if (ctxLineKategori) {
new Chart(ctxLineKategori.getContext('2d'), {
type: 'line',
data: {
labels: ['Al-Qur\'an', 'Hadist', 'Materi Tambahan'],
datasets: [{
label: 'Progress (%)',
data: [
<?php echo e($data['progres_quran']); ?>,
<?php echo e($data['progres_hadist']); ?>,
<?php echo e($data['progres_materi_tambahan']); ?>
],
backgroundColor: 'rgba(111, 186, 157, 0.2)',
borderColor: 'rgba(111, 186, 157, 1)',
borderWidth: 4,
pointBackgroundColor: [
'rgba(111, 186, 157, 1)',
'rgba(129, 198, 232, 1)',
'rgba(255, 213, 107, 1)'
],
pointBorderColor: '#fff',
pointBorderWidth: 3,
pointRadius: 8,
pointHoverRadius: 10,
tension: 0.4,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
stepSize: 20,
callback: function(value) {
return value + '%';
},
font: {
size: 12,
weight: '600'
}
},
grid: {
color: 'rgba(0, 0, 0, 0.05)'
}
},
x: {
ticks: {
font: {
size: 12,
weight: '600'
}
},
grid: {
display: false
}
}
},
plugins: {
legend: {
display: false
},
tooltip: {
callbacks: {
label: function(context) {
return 'Progress: ' + context.parsed.y.toFixed(1) + '%';
}
}
}
}
}
});
}
// ============================================
// GRAFIK 3: Progress per Materi (BAR CHART - Vertikal)
// ============================================
<?php if($capaianPerMateri->count() > 0): ?>
const ctxBarMateri = document.getElementById('chartBarMateri');
if (ctxBarMateri) {
new Chart(ctxBarMateri.getContext('2d'), {
type: 'bar',
data: {
labels: [
<?php $__currentLoopData = $capaianPerMateri; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
'<?php echo e(Str::limit($item->materi->nama_kitab, 30)); ?>',
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
],
datasets: [{
label: 'Progress (%)',
data: [
<?php $__currentLoopData = $capaianPerMateri; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<?php echo e($item->persentase); ?>,
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
],
backgroundColor: [
<?php $__currentLoopData = $capaianPerMateri; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<?php if($item->materi->kategori == 'Al-Qur\'an'): ?>
'rgba(111, 186, 157, 0.8)',
<?php elseif($item->materi->kategori == 'Hadist'): ?>
'rgba(129, 198, 232, 0.8)',
<?php else: ?>
'rgba(255, 213, 107, 0.8)',
<?php endif; ?>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
],
borderColor: [
<?php $__currentLoopData = $capaianPerMateri; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<?php if($item->materi->kategori == 'Al-Qur\'an'): ?>
'rgba(111, 186, 157, 1)',
<?php elseif($item->materi->kategori == 'Hadist'): ?>
'rgba(129, 198, 232, 1)',
<?php else: ?>
'rgba(255, 213, 107, 1)',
<?php endif; ?>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
],
borderWidth: 2,
borderRadius: 8,
borderSkipped: false
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
display: false
},
tooltip: {
callbacks: {
label: function(context) {
return 'Progress: ' + context.parsed.y.toFixed(1) + '%';
}
}
}
},
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
stepSize: 10,
callback: function(value) {
return value + '%';
},
font: {
size: 12,
weight: '600'
}
},
grid: {
color: 'rgba(0, 0, 0, 0.05)'
},
title: {
display: true,
text: 'Persentase (%)',
font: {
size: 14,
weight: 'bold'
}
}
},
x: {
ticks: {
font: {
size: 11
},
maxRotation: 45,
minRotation: 45
},
grid: {
display: false
},
title: {
display: true,
text: 'Materi',
font: {
size: 14,
weight: 'bold'
}
}
}
}
}
});
}
<?php endif; ?>
});
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/santri/dashboardSantri.blade.php ENDPATH**/ ?>

View File

@ -1,194 +0,0 @@
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-plus-circle"></i> Tambah Transaksi Uang Saku</h2>
</div>
<div class="form-container">
<form action="<?php echo e(route('admin.uang-saku.store')); ?>" method="POST" id="transaksiForm">
<?php echo csrf_field(); ?>
<div class="form-group">
<label for="id_santri">
<i class="fas fa-user form-icon"></i>
Pilih Santri <span style="color: red;">*</span>
</label>
<select name="id_santri" id="id_santri" class="form-control <?php $__errorArgs = ['id_santri'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>" required>
<option value="">-- Pilih Santri --</option>
<?php $__currentLoopData = $santriList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($santri->id_santri); ?>"
<?php echo e((old('id_santri', request('id_santri')) == $santri->id_santri) ? 'selected' : ''); ?>>
<?php echo e($santri->id_santri); ?> - <?php echo e($santri->nama_lengkap); ?>
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<?php $__errorArgs = ['id_santri'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<div class="invalid-feedback"><?php echo e($message); ?></div>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div class="form-group">
<label for="jenis_transaksi">
<i class="fas fa-exchange-alt form-icon"></i>
Jenis Transaksi <span style="color: red;">*</span>
</label>
<select name="jenis_transaksi" id="jenis_transaksi" class="form-control <?php $__errorArgs = ['jenis_transaksi'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>" required>
<option value="">-- Pilih Jenis --</option>
<option value="pemasukan" <?php echo e(old('jenis_transaksi') == 'pemasukan' ? 'selected' : ''); ?>>
Pemasukan (Terima Uang Saku)
</option>
<option value="pengeluaran" <?php echo e(old('jenis_transaksi') == 'pengeluaran' ? 'selected' : ''); ?>>
Pengeluaran (Gunakan Uang Saku)
</option>
</select>
<?php $__errorArgs = ['jenis_transaksi'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<div class="invalid-feedback"><?php echo e($message); ?></div>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div class="form-group">
<label for="nominal">
<i class="fas fa-money-bill-wave form-icon"></i>
Nominal (Rp) <span style="color: red;">*</span>
</label>
<input type="number" name="nominal" id="nominal" class="form-control <?php $__errorArgs = ['nominal'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
value="<?php echo e(old('nominal')); ?>" placeholder="Contoh: 50000" min="1" step="1" required>
<?php $__errorArgs = ['nominal'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<div class="invalid-feedback"><?php echo e($message); ?></div>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
<small class="form-text">Masukkan nominal tanpa titik atau koma</small>
</div>
<div class="form-group">
<label for="tanggal_transaksi">
<i class="fas fa-calendar form-icon"></i>
Tanggal Transaksi <span style="color: red;">*</span>
</label>
<input type="date" name="tanggal_transaksi" id="tanggal_transaksi"
class="form-control <?php $__errorArgs = ['tanggal_transaksi'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
value="<?php echo e(old('tanggal_transaksi', date('Y-m-d'))); ?>" required>
<?php $__errorArgs = ['tanggal_transaksi'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<div class="invalid-feedback"><?php echo e($message); ?></div>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div class="form-group">
<label for="keterangan">
<i class="fas fa-sticky-note form-icon"></i>
Keterangan
</label>
<textarea name="keterangan" id="keterangan" class="form-control <?php $__errorArgs = ['keterangan'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
rows="4" placeholder="Contoh: Uang saku bulan Januari 2025"><?php echo e(old('keterangan')); ?></textarea>
<?php $__errorArgs = ['keterangan'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<div class="invalid-feedback"><?php echo e($message); ?></div>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
<small class="form-text">Opsional - Jelaskan detail transaksi</small>
</div>
<div class="btn-group">
<button type="submit" class="btn btn-success hover-lift">
<i class="fas fa-save"></i> Simpan Transaksi
</button>
<a href="<?php echo e(route('admin.uang-saku.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</form>
</div>
<script>
// Format nominal input (tambah separator ribuan saat blur)
document.getElementById('nominal').addEventListener('blur', function(e) {
if (this.value) {
const value = parseInt(this.value.replace(/\D/g, ''));
if (!isNaN(value)) {
this.value = value;
}
}
});
// Validasi form sebelum submit
document.getElementById('transaksiForm').addEventListener('submit', function(e) {
const nominal = document.getElementById('nominal').value;
if (nominal && parseInt(nominal) < 1) {
e.preventDefault();
alert('Nominal harus lebih dari 0');
return false;
}
});
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/uang-saku/create.blade.php ENDPATH**/ ?>

View File

@ -1,213 +0,0 @@
<?php $__env->startSection('title', 'Tambah Riwayat Pelanggaran'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-plus-circle"></i> Tambah Riwayat Pelanggaran</h2>
</div>
<!-- Breadcrumb -->
<div style="margin-bottom: 20px;">
<nav style="display: flex; align-items: center; gap: 8px; color: var(--text-light); font-size: 0.9em;">
<a href="<?php echo e(route('admin.riwayat-pelanggaran.index')); ?>" style="color: var(--primary-color); text-decoration: none;">
<i class="fas fa-history"></i> Riwayat Pelanggaran
</a>
<i class="fas fa-chevron-right" style="font-size: 0.7em;"></i>
<span>Tambah</span>
</nav>
</div>
<div class="content-box">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px;">
<h3 style="margin: 0; color: var(--primary-color);">
<i class="fas fa-edit"></i> Form Tambah Riwayat
</h3>
<div style="background: var(--primary-light); padding: 10px 20px; border-radius: var(--border-radius-sm);">
<small style="color: var(--text-light);">ID Riwayat Berikutnya:</small>
<strong style="color: var(--primary-dark); font-size: 1.1em;"><?php echo e($nextIdRiwayat); ?></strong>
</div>
</div>
<form action="<?php echo e(route('admin.riwayat-pelanggaran.store')); ?>" method="POST">
<?php echo csrf_field(); ?>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px;">
<!-- Santri -->
<div class="form-group">
<label for="id_santri">
<i class="fas fa-user form-icon"></i>
Santri <span style="color: var(--danger-color);">*</span>
</label>
<select name="id_santri"
id="id_santri"
class="form-control <?php $__errorArgs = ['id_santri'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
required>
<option value="">-- Pilih Santri --</option>
<?php $__currentLoopData = $santriList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($santri->id_santri); ?>" <?php echo e(old('id_santri') == $santri->id_santri ? 'selected' : ''); ?>>
<?php echo e($santri->nama_lengkap); ?> - <?php echo e($santri->kelas); ?> (<?php echo e($santri->id_santri); ?>)
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<?php $__errorArgs = ['id_santri'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<!-- Tanggal -->
<div class="form-group">
<label for="tanggal">
<i class="fas fa-calendar form-icon"></i>
Tanggal Pelanggaran <span style="color: var(--danger-color);">*</span>
</label>
<input type="date"
name="tanggal"
id="tanggal"
class="form-control <?php $__errorArgs = ['tanggal'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
value="<?php echo e(old('tanggal', date('Y-m-d'))); ?>"
required>
<?php $__errorArgs = ['tanggal'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
</div>
<!-- Kategori Pelanggaran -->
<div class="form-group">
<label for="id_kategori">
<i class="fas fa-tags form-icon"></i>
Kategori Pelanggaran <span style="color: var(--danger-color);">*</span>
</label>
<select name="id_kategori"
id="id_kategori"
class="form-control <?php $__errorArgs = ['id_kategori'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
required>
<option value="">-- Pilih Kategori Pelanggaran --</option>
<?php $__currentLoopData = $kategoriList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kategori): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($kategori->id_kategori); ?>"
data-poin="<?php echo e($kategori->poin); ?>"
<?php echo e(old('id_kategori') == $kategori->id_kategori ? 'selected' : ''); ?>>
<?php echo e($kategori->nama_pelanggaran); ?> - <?php echo e($kategori->poin); ?> Poin (<?php echo e($kategori->id_kategori); ?>)
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<?php $__errorArgs = ['id_kategori'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
<!-- Preview Poin -->
<div id="poin-preview" style="display: none; margin-top: 12px; padding: 12px; background: var(--danger-color); color: white; border-radius: var(--border-radius-sm); text-align: center;">
<i class="fas fa-fire"></i>
<strong>Poin yang akan ditambahkan: <span id="poin-value">0</span> Poin</strong>
</div>
</div>
<!-- Keterangan -->
<div class="form-group">
<label for="keterangan">
<i class="fas fa-comment form-icon"></i>
Keterangan Tambahan
</label>
<textarea name="keterangan"
id="keterangan"
rows="4"
class="form-control <?php $__errorArgs = ['keterangan'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
placeholder="Jelaskan detail pelanggaran (opsional)"><?php echo e(old('keterangan')); ?></textarea>
<?php $__errorArgs = ['keterangan'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
<span class="form-text">Maksimal 1000 karakter</span>
</div>
<div class="btn-group">
<button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i> Simpan Riwayat
</button>
<a href="<?php echo e(route('admin.riwayat-pelanggaran.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</form>
</div>
<script>
// Preview poin saat kategori dipilih
document.getElementById('id_kategori').addEventListener('change', function() {
const selectedOption = this.options[this.selectedIndex];
const poin = selectedOption.getAttribute('data-poin');
const preview = document.getElementById('poin-preview');
const poinValue = document.getElementById('poin-value');
if (poin) {
poinValue.textContent = poin;
preview.style.display = 'block';
} else {
preview.style.display = 'none';
}
});
// Trigger change event jika ada old value
if (document.getElementById('id_kategori').value) {
document.getElementById('id_kategori').dispatchEvent(new Event('change'));
}
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/riwayat_pelanggaran/create.blade.php ENDPATH**/ ?>

View File

@ -1,231 +0,0 @@
<?php $__env->startSection('title', 'Riwayat Kepulangan'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-home"></i> Riwayat Kepulangan</h2>
<p style="margin: 5px 0 0 0; color: var(--text-light);">
Riwayat izin pulang <strong><?php echo e($santri->nama_lengkap); ?></strong>
</p>
</div>
<div class="row-cards">
<div class="card card-info">
<h3><i class="fas fa-clipboard-list"></i> Total Pengajuan</h3>
<div class="card-value"><?php echo e($statistik['total_izin']); ?></div>
<div class="card-icon"><i class="fas fa-clipboard-list"></i></div>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">
Tahun <?php echo e($tahunSekarang); ?>
</p>
</div>
<div class="card card-success">
<h3><i class="fas fa-check-circle"></i> Disetujui</h3>
<div class="card-value"><?php echo e($statistik['disetujui']); ?></div>
<div class="card-icon"><i class="fas fa-check-circle"></i></div>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">
Izin diterima
</p>
</div>
<div class="card card-<?php echo e($statistik['over_limit'] ? 'danger' : 'primary'); ?>">
<h3><i class="fas fa-calendar-alt"></i> Total Hari Pulang</h3>
<div class="card-value"><?php echo e($statistik['total_hari']); ?> Hari</div>
<div class="card-icon"><i class="fas fa-calendar-alt"></i></div>
<?php if($statistik['over_limit']): ?>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--danger-color);">
<i class="fas fa-exclamation-triangle"></i> Melebihi batas!
</p>
<?php else: ?>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">
Dari kuota 12 hari
</p>
<?php endif; ?>
</div>
<div class="card card-<?php echo e($statistik['sisa_kuota'] > 0 ? 'warning' : 'danger'); ?>">
<h3><i class="fas fa-hourglass-half"></i> Sisa Kuota</h3>
<div class="card-value"><?php echo e($statistik['sisa_kuota']); ?> Hari</div>
<div class="card-icon"><i class="fas fa-hourglass-half"></i></div>
<?php if($statistik['menunggu'] > 0): ?>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--warning-color);">
<i class="fas fa-clock"></i> <?php echo e($statistik['menunggu']); ?> menunggu
</p>
<?php else: ?>
<p style="margin-top: 10px; font-size: 0.85rem; color: var(--text-light);">
Kuota tersisa
</p>
<?php endif; ?>
</div>
</div>
<?php if($statistik['over_limit']): ?>
<div class="alert alert-danger" style="margin-top: 20px;">
<i class="fas fa-exclamation-triangle"></i>
<strong>Peringatan:</strong> Anda telah melebihi batas kuota kepulangan (12 hari/tahun).
Total hari pulang Anda tahun ini: <strong><?php echo e($statistik['total_hari']); ?> hari</strong>.
</div>
<?php elseif($statistik['sisa_kuota'] <= 3 && $statistik['sisa_kuota'] > 0): ?>
<div class="alert alert-warning" style="margin-top: 20px;">
<i class="fas fa-info-circle"></i>
<strong>Perhatian:</strong> Sisa kuota kepulangan Anda tinggal <strong><?php echo e($statistik['sisa_kuota']); ?> hari</strong>.
Gunakan dengan bijak.
</div>
<?php endif; ?>
<div class="content-box" style="margin-top: 20px;">
<form method="GET" class="filter-form-inline">
<select name="tahun" class="form-control">
<?php $__currentLoopData = $tahunOptions; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $year): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($year); ?>" <?php echo e($tahunSekarang == $year ? 'selected' : ''); ?>>
Tahun <?php echo e($year); ?>
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<select name="status" class="form-control">
<option value="">Semua Status</option>
<?php $__currentLoopData = $statusOptions; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $value => $label): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($value); ?>" <?php echo e(request('status') == $value ? 'selected' : ''); ?>>
<?php echo e($label); ?>
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<button type="submit" class="btn btn-primary btn-sm">
<i class="fas fa-filter"></i> Filter
</button>
<a href="<?php echo e(route('santri.kepulangan.index')); ?>" class="btn btn-secondary btn-sm">
<i class="fas fa-sync"></i> Reset
</a>
</form>
</div>
<?php if($riwayatKepulangan->isEmpty()): ?>
<div class="empty-state" style="margin-top: 20px;">
<i class="fas fa-home"></i>
<h3>Belum Ada Riwayat Kepulangan</h3>
<p>Anda belum pernah mengajukan izin kepulangan pada periode yang dipilih.</p>
</div>
<?php else: ?>
<div class="content-box" style="margin-top: 20px;">
<h3 style="margin: 0 0 15px 0; color: var(--primary-color);">
<i class="fas fa-list"></i> Daftar Riwayat (<?php echo e($riwayatKepulangan->total()); ?> data)
</h3>
<div style="display: flex; flex-direction: column; gap: 15px;">
<?php $__currentLoopData = $riwayatKepulangan; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<a href="<?php echo e(route('santri.kepulangan.show', $item->id_kepulangan)); ?>"
style="display: flex; gap: 15px; padding: 15px; background: linear-gradient(135deg, #FFFFFF 0%, #FEFFFE 100%); border-radius: var(--border-radius-sm); border-left: 4px solid
<?php if($item->status == 'Menunggu'): ?> var(--warning-color)
<?php elseif($item->status == 'Disetujui'): ?> var(--success-color)
<?php elseif($item->status == 'Ditolak'): ?> var(--danger-color)
<?php else: ?> var(--text-light) <?php endif; ?>
; text-decoration: none; transition: var(--transition-base); position: relative;"
onmouseover="this.style.boxShadow='var(--shadow-md)'; this.style.transform='translateX(5px)';"
onmouseout="this.style.boxShadow='none'; this.style.transform='translateX(0)';">
<div style="flex-shrink: 0; width: 60px; height: 60px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background:
<?php if($item->status == 'Menunggu'): ?> linear-gradient(135deg, #FFF8E1, #FFF3CD)
<?php elseif($item->status == 'Disetujui'): ?> linear-gradient(135deg, #E8F7F2, #D4F1E3)
<?php elseif($item->status == 'Ditolak'): ?> linear-gradient(135deg, #FFE8EA, #FFD5D8)
<?php else: ?> linear-gradient(135deg, #E2E3E5, #D6D8DB) <?php endif; ?>
;">
<i class="fas
<?php if($item->status == 'Menunggu'): ?> fa-clock
<?php elseif($item->status == 'Disetujui'): ?> fa-check-circle
<?php elseif($item->status == 'Ditolak'): ?> fa-times-circle
<?php else: ?> fa-flag-checkered <?php endif; ?>
" style="font-size: 1.8rem; color:
<?php if($item->status == 'Menunggu'): ?> var(--warning-color)
<?php elseif($item->status == 'Disetujui'): ?> var(--success-color)
<?php elseif($item->status == 'Ditolak'): ?> var(--danger-color)
<?php else: ?> var(--text-light) <?php endif; ?>
;"></i>
</div>
<div style="flex: 1; display: flex; flex-direction: column; justify-content: space-between; min-width: 0;">
<div>
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 8px;">
<h3 style="margin: 0; font-size: 1rem; font-weight: 600; color: var(--text-color);">
<?php echo e($item->alasan); ?>
</h3>
<span class="badge badge-<?php echo e($item->status == 'Menunggu' ? 'warning' :
($item->status == 'Disetujui' ? 'success' :
($item->status == 'Ditolak' ? 'danger' : 'secondary'))); ?>">
<?php echo e($item->status); ?>
</span>
</div>
<p style="margin: 0 0 8px 0; font-size: 0.9rem; color: var(--text-light);">
<i class="fas fa-code"></i> <?php echo e($item->id_kepulangan); ?>
</p>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 15px; font-size: 0.85rem; color: var(--text-light);">
<span>
<i class="fas fa-calendar-alt"></i> <?php echo e($item->tanggal_pulang_formatted); ?> - <?php echo e($item->tanggal_kembali_formatted); ?>
</span>
<span class="badge badge-info badge-sm">
<i class="fas fa-clock"></i> <?php echo e($item->durasi_izin); ?> hari
</span>
<?php if($item->status == 'Disetujui'): ?>
<?php if($item->is_aktif): ?>
<span class="badge badge-success badge-sm">
<i class="fas fa-home"></i> Sedang Pulang
</span>
<?php elseif($item->is_terlambat): ?>
<span class="badge badge-danger badge-sm">
<i class="fas fa-exclamation-triangle"></i> Terlambat Kembali
</span>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
<div style="flex-shrink: 0; display: flex; align-items: center;">
<i class="fas fa-chevron-right" style="color: var(--text-light);"></i>
</div>
</a>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</div>
<div style="margin-top: 25px;">
<?php echo e($riwayatKepulangan->links()); ?>
</div>
</div>
<?php endif; ?>
<div class="info-box" style="margin-top: 20px;">
<i class="fas fa-info-circle"></i>
<strong>Info:</strong> Kuota kepulangan maksimal <strong>12 hari per tahun</strong>.
Pastikan Anda merencanakan kepulangan dengan bijak agar tidak melebihi batas kuota.
</div>
<div style="margin-top: 20px; text-align: center;">
<a href="<?php echo e(route('santri.dashboard')); ?>" class="btn btn-secondary hover-lift">
<i class="fas fa-home"></i> Kembali ke Dashboard
</a>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/santri/kepulangan/index.blade.php ENDPATH**/ ?>

View File

@ -20,10 +20,22 @@
<div class="detail-header">
<div style="display: flex; align-items: center; gap: 20px;">
<?php if($santri->foto && file_exists(public_path('storage/' . $santri->foto))): ?>
<img src="<?php echo e(asset('storage/' . $santri->foto)); ?>"
alt="Foto <?php echo e($santri->nama_lengkap); ?>"
style="width: 80px; height: 80px; border-radius: 50%; object-fit: cover; border: 3px solid var(--primary-color); flex-shrink: 0;"
loading="lazy"
onerror="this.onerror=null; this.style.display='none'; this.nextElementSibling.style.display='flex';">
<div class="santri-avatar-initial santri-avatar-initial-lg" style="display: none;">
<?php echo e(strtoupper(substr($santri->nama_lengkap, 0, 1))); ?>
</div>
<?php else: ?>
<div class="santri-avatar-initial santri-avatar-initial-lg">
<?php echo e(strtoupper(substr($santri->nama_lengkap, 0, 1))); ?>
</div>
<?php endif; ?>
<div>
<h3 style="margin: 0; font-size: 1.8rem; color: var(--text-color);">
@ -153,7 +165,7 @@
<div style="margin-top: 30px; padding: 20px; background: var(--primary-light); border-radius: var(--border-radius-sm); border-left: 4px solid var(--primary-color);">
<p style="margin: 0; color: var(--text-color); line-height: 1.6;">
<i class="fas fa-info-circle" style="color: var(--primary-color);"></i>
<strong>Catatan:</strong> Jika ada data yang perlu diperbarui selain alamat dan nomor HP orang tua, silakan hubungi admin atau pengurus pesantren.
<strong>Catatan:</strong> Jika ada data yang perlu diperbarui termasuk foto profil, silakan hubungi admin atau pengurus pesantren.
</p>
</div>
</div>

View File

@ -0,0 +1,76 @@
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-calendar-alt"></i> Detail Kegiatan</h2>
</div>
<div class="content-box">
<div class="detail-header">
<h3><?php echo e($kegiatan->nama_kegiatan); ?></h3>
<div style="display: flex; gap: 10px;">
<a href="<?php echo e(route('admin.kegiatan.edit', $kegiatan)); ?>" class="btn btn-warning">
<i class="fas fa-edit"></i> Edit
</a>
<form action="<?php echo e(route('admin.kegiatan.destroy', $kegiatan)); ?>" method="POST" style="display: inline;" onsubmit="return confirm('Yakin ingin menghapus kegiatan ini?')">
<?php echo csrf_field(); ?>
<?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-danger">
<i class="fas fa-trash"></i> Hapus
</button>
</form>
<a href="<?php echo e(route('admin.kegiatan.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
</div>
<div class="detail-section">
<h4><i class="fas fa-info-circle"></i> Informasi Kegiatan</h4>
<table class="detail-table">
<tr>
<th>ID Kegiatan</th>
<td><strong><?php echo e($kegiatan->kegiatan_id); ?></strong></td>
</tr>
<tr>
<th>Kategori</th>
<td>
<span class="badge badge-primary badge-lg"><?php echo e($kegiatan->kategori->nama_kategori); ?></span>
</td>
</tr>
<tr>
<th>Nama Kegiatan</th>
<td><strong><?php echo e($kegiatan->nama_kegiatan); ?></strong></td>
</tr>
<tr>
<th>Hari</th>
<td><span class="badge badge-info badge-lg"><?php echo e($kegiatan->hari); ?></span></td>
</tr>
<tr>
<th>Waktu Pelaksanaan</th>
<td>
<i class="fas fa-clock" style="color: var(--primary-color);"></i>
<?php echo e(date('H:i', strtotime($kegiatan->waktu_mulai))); ?> - <?php echo e(date('H:i', strtotime($kegiatan->waktu_selesai))); ?> WIB
</td>
</tr>
<tr>
<th>Materi/Topik</th>
<td><?php echo e($kegiatan->materi ?? '-'); ?></td>
</tr>
<tr>
<th>Keterangan</th>
<td><?php echo e($kegiatan->keterangan ?? '-'); ?></td>
</tr>
<tr>
<th>Dibuat Pada</th>
<td><?php echo e($kegiatan->created_at->format('d F Y, H:i')); ?> WIB</td>
</tr>
<tr>
<th>Terakhir Diubah</th>
<td><?php echo e($kegiatan->updated_at->format('d F Y, H:i')); ?> WIB</td>
</tr>
</table>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/data/show.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,379 @@
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-chart-pie"></i> Dashboard Capaian Al-Qur'an & Hadist</h2>
</div>
<div class="content-box" style="margin-bottom: 20px;">
<form method="GET" action="<?php echo e(route('admin.capaian.dashboard')); ?>" class="filter-form-inline">
<select name="id_santri" class="form-control" style="width: 250px;">
<option value="">Semua Santri</option>
<?php $__currentLoopData = $santris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($santri->id_santri); ?>" <?php echo e($idSantri == $santri->id_santri ? 'selected' : ''); ?>>
<?php echo e($santri->nama_lengkap); ?> (<?php echo e($santri->kelas); ?>)
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<select name="id_semester" class="form-control" style="width: 200px;">
<option value="">Semua Semester</option>
<?php $__currentLoopData = $semesters; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $semester): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($semester->id_semester); ?>" <?php echo e($selectedSemester == $semester->id_semester ? 'selected' : ''); ?>>
<?php echo e($semester->nama_semester); ?> <?php if($semester->is_active): ?> ★ <?php endif; ?>
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<select name="kelas" class="form-control" style="width: 150px;">
<option value="">Semua Kelas</option>
<option value="Lambatan" <?php echo e($kelas == 'Lambatan' ? 'selected' : ''); ?>>Lambatan</option>
<option value="Cepatan" <?php echo e($kelas == 'Cepatan' ? 'selected' : ''); ?>>Cepatan</option>
<option value="PB" <?php echo e($kelas == 'PB' ? 'selected' : ''); ?>>PB</option>
</select>
<button type="submit" class="btn btn-primary">
<i class="fas fa-filter"></i> Filter
</button>
<?php if($idSantri || $kelas): ?>
<a href="<?php echo e(route('admin.capaian.dashboard')); ?>" class="btn btn-secondary">
<i class="fas fa-redo"></i> Reset
</a>
<?php endif; ?>
</form>
</div>
<div class="row-cards">
<div class="card card-info">
<h3>Total Capaian</h3>
<div class="card-value"><?php echo e($totalCapaian); ?></div>
<p class="text-muted">Data capaian tercatat</p>
<i class="fas fa-clipboard-list card-icon"></i>
</div>
<div class="card card-success">
<h3>Total Santri</h3>
<div class="card-value"><?php echo e($totalSantri); ?></div>
<p class="text-muted">Santri aktif dengan capaian</p>
<i class="fas fa-users card-icon"></i>
</div>
<div class="card card-primary">
<h3>Rata-rata Progress</h3>
<div class="card-value"><?php echo e(number_format($rataRataPersentase, 1)); ?>%</div>
<p class="text-muted">Progress keseluruhan</p>
<i class="fas fa-chart-line card-icon"></i>
</div>
<div class="card card-warning">
<h3>Selesai 100%</h3>
<div class="card-value"><?php echo e($capaianSelesai); ?></div>
<p class="text-muted">Materi yang diselesaikan</p>
<i class="fas fa-trophy card-icon"></i>
</div>
</div>
<div class="row-cards">
<?php $__currentLoopData = $statistikKategori; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kategori => $stats): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<div class="card card-<?php echo e($kategori == 'Al-Qur\'an' ? 'primary' : ($kategori == 'Hadist' ? 'success' : 'info')); ?>">
<h3><?php echo e($kategori); ?></h3>
<div class="card-value-small"><?php echo e(number_format($stats['avg'], 1)); ?>%</div>
<p class="text-muted">
<?php echo e($stats['count']); ?> capaian | <?php echo e($stats['selesai']); ?> selesai
</p>
<i class="fas fa-<?php echo e($kategori == 'Al-Qur\'an' ? 'book-quran' : ($kategori == 'Hadist' ? 'scroll' : 'book')); ?> card-icon"></i>
</div>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px;">
<div class="content-box">
<h4 style="margin: 0 0 20px 0; color: var(--primary-dark);">
<i class="fas fa-chart-pie"></i> Progress per Kategori
</h4>
<canvas id="chartKategori" style="max-height: 300px;"></canvas>
</div>
<div class="content-box">
<h4 style="margin: 0 0 20px 0; color: var(--primary-dark);">
<i class="fas fa-chart-bar"></i> Distribusi Progress Santri
</h4>
<canvas id="chartDistribusi" style="max-height: 300px;"></canvas>
</div>
</div>
<div class="content-box" style="margin-bottom: 20px;">
<h4 style="margin: 0 0 20px 0; color: var(--primary-dark);">
<i class="fas fa-chart-line"></i> Trend Progress dari Waktu ke Waktu
</h4>
<canvas id="chartTrend" style="max-height: 250px;"></canvas>
</div>
<div class="content-box" style="margin-bottom: 20px;">
<h4 style="margin: 0 0 20px 0; color: var(--primary-dark);">
<i class="fas fa-trophy"></i> Top 10 Santri dengan Progress Tertinggi
</h4>
<?php if($topSantri->count() > 0): ?>
<table class="data-table">
<thead>
<tr>
<th style="width: 5%;">Rank</th>
<th style="width: 10%;">NIS</th>
<th style="width: 30%;">Nama Santri</th>
<th style="width: 10%;">Kelas</th>
<th style="width: 25%;">Rata-rata Progress</th>
<th class="text-center" style="width: 20%;">Aksi</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $topSantri; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td class="text-center">
<?php if($index < 3): ?>
<span style="font-size: 1.5rem;">
<?php if($index == 0): ?> 🥇
<?php elseif($index == 1): ?> 🥈
<?php else: ?> 🥉
<?php endif; ?>
</span>
<?php else: ?>
<strong><?php echo e($index + 1); ?></strong>
<?php endif; ?>
</td>
<td><?php echo e($item->santri->nis); ?></td>
<td><strong><?php echo e($item->santri->nama_lengkap); ?></strong></td>
<td><span class="badge badge-secondary"><?php echo e($item->santri->kelas); ?></span></td>
<td>
<div class="progress-bar" style="height: 25px;">
<div class="progress-fill" style="width: <?php echo e($item->rata_rata); ?>%; background: linear-gradient(90deg, var(--primary-color), var(--success-color)); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold;">
<?php echo e(number_format($item->rata_rata, 1)); ?>%
</div>
</div>
</td>
<td class="text-center">
<a href="<?php echo e(route('admin.capaian.riwayat-santri', $item->id_santri)); ?>" class="btn btn-sm btn-info">
<i class="fas fa-eye"></i> Lihat Detail
</a>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
<?php else: ?>
<div class="empty-state">
<i class="fas fa-chart-line"></i>
<p>Belum ada data untuk ditampilkan</p>
</div>
<?php endif; ?>
</div>
<?php if($materiTerendah->count() > 0): ?>
<div class="content-box">
<h4 style="margin: 0 0 20px 0; color: var(--danger-color);">
<i class="fas fa-exclamation-triangle"></i> Materi yang Perlu Perhatian (Progress < 50%)
</h4>
<table class="data-table">
<thead>
<tr>
<th style="width: 30%;">Nama Materi</th>
<th style="width: 15%;">Kategori</th>
<th style="width: 10%;">Kelas</th>
<th style="width: 10%;">Jumlah Santri</th>
<th style="width: 20%;">Rata-rata Progress</th>
<th class="text-center" style="width: 15%;">Aksi</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $materiTerendah; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><strong><?php echo e($item->materi->nama_kitab); ?></strong></td>
<td><?php echo $item->materi->kategori_badge; ?></td>
<td><?php echo $item->materi->kelas_badge; ?></td>
<td class="text-center"><?php echo e($item->jumlah_santri); ?> santri</td>
<td>
<div class="progress-bar" style="height: 20px;">
<div class="progress-fill" style="width: <?php echo e($item->rata_rata); ?>%; background: linear-gradient(90deg, var(--danger-color), var(--warning-color)); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 0.85rem;">
<?php echo e(number_format($item->rata_rata, 1)); ?>%
</div>
</div>
</td>
<td class="text-center">
<a href="<?php echo e(route('admin.capaian.detail-materi', $item->id_materi)); ?>" class="btn btn-sm btn-warning">
<i class="fas fa-eye"></i> Detail
</a>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
</div>
<?php endif; ?>
<div style="margin-top: 30px; display: flex; gap: 10px; justify-content: center;">
<a href="<?php echo e(route('admin.capaian.rekap-kelas')); ?>" class="btn btn-primary">
<i class="fas fa-table"></i> Rekap per Kelas
</a>
<a href="<?php echo e(route('admin.capaian.create')); ?>" class="btn btn-success">
<i class="fas fa-plus"></i> Input Capaian Baru
</a>
<a href="<?php echo e(route('admin.materi.index')); ?>" class="btn btn-info">
<i class="fas fa-book"></i> Master Materi
</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
// Chart 1: Pie Chart - Progress per Kategori
const ctxKategori = document.getElementById('chartKategori').getContext('2d');
const chartKategori = new Chart(ctxKategori, {
type: 'pie',
data: {
labels: ['Al-Qur\'an', 'Hadist', 'Materi Tambahan'],
datasets: [{
label: 'Rata-rata Progress (%)',
data: [
<?php echo e(number_format($statistikKategori['Al-Qur\'an']['avg'], 2)); ?>,
<?php echo e(number_format($statistikKategori['Hadist']['avg'], 2)); ?>,
<?php echo e(number_format($statistikKategori['Materi Tambahan']['avg'], 2)); ?>
],
backgroundColor: [
'rgba(111, 186, 157, 0.8)',
'rgba(129, 198, 232, 0.8)',
'rgba(255, 213, 107, 0.8)',
],
borderColor: [
'rgba(111, 186, 157, 1)',
'rgba(129, 198, 232, 1)',
'rgba(255, 213, 107, 1)',
],
borderWidth: 2
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
position: 'bottom',
labels: {
padding: 15,
font: {
size: 12
}
}
},
tooltip: {
callbacks: {
label: function(context) {
return context.label + ': ' + context.parsed.toFixed(2) + '%';
}
}
}
}
}
});
// Chart 2: Bar Chart - Distribusi Persentase
const ctxDistribusi = document.getElementById('chartDistribusi').getContext('2d');
const chartDistribusi = new Chart(ctxDistribusi, {
type: 'bar',
data: {
labels: ['0-25%', '26-50%', '51-75%', '76-99%', '100%'],
datasets: [{
label: 'Jumlah Santri',
data: [
<?php echo e($distribusiPersentase['0-25%']); ?>,
<?php echo e($distribusiPersentase['26-50%']); ?>,
<?php echo e($distribusiPersentase['51-75%']); ?>,
<?php echo e($distribusiPersentase['76-99%']); ?>,
<?php echo e($distribusiPersentase['100%']); ?>
],
backgroundColor: [
'rgba(255, 139, 148, 0.8)',
'rgba(255, 171, 145, 0.8)',
'rgba(255, 213, 107, 0.8)',
'rgba(129, 198, 232, 0.8)',
'rgba(111, 186, 157, 0.8)',
],
borderColor: [
'rgba(255, 139, 148, 1)',
'rgba(255, 171, 145, 1)',
'rgba(255, 213, 107, 1)',
'rgba(129, 198, 232, 1)',
'rgba(111, 186, 157, 1)',
],
borderWidth: 2
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 1
}
}
},
plugins: {
legend: {
display: false
}
}
}
});
// Chart 3: Line Chart - Trend Progress (Load via AJAX)
fetch('<?php echo e(route("admin.capaian.api.grafik-data")); ?>?type=trend&id_semester=<?php echo e($selectedSemester); ?>&kelas=<?php echo e($kelas); ?>')
.then(response => response.json())
.then(data => {
const ctxTrend = document.getElementById('chartTrend').getContext('2d');
const chartTrend = new Chart(ctxTrend, {
type: 'line',
data: data,
options: {
responsive: true,
maintainAspectRatio: true,
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
callback: function(value) {
return value + '%';
}
}
}
},
plugins: {
legend: {
display: true,
position: 'bottom'
},
tooltip: {
callbacks: {
label: function(context) {
return context.dataset.label + ': ' + context.parsed.y.toFixed(2) + '%';
}
}
}
}
}
});
})
.catch(error => console.error('Error loading trend chart:', error));
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/capaian/dashboard.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,501 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Kartu RFID 2 Sisi - <?php echo e($santri->nama_lengkap ?? 'Preview'); ?></title>
<style>
@page {
margin: 0;
size: 85.6mm 54mm;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
}
/* === SISI DEPAN === */
.card-front {
width: 85.6mm;
height: 54mm;
background: #2C3E50;
position: relative;
overflow: hidden;
page-break-after: always;
}
/* Background Elements */
.bg-circle-1 {
position: absolute;
top: -20mm;
right: -20mm;
width: 70mm;
height: 70mm;
background: #6FBA9D;
border-radius: 50%;
opacity: 0.15;
}
.bg-circle-2 {
position: absolute;
bottom: -25mm;
left: -15mm;
width: 60mm;
height: 60mm;
background: #8FCAAE;
border-radius: 50%;
opacity: 0.12;
}
.wave {
position: absolute;
top: 0;
right: 0;
width: 45mm;
height: 100%;
background: linear-gradient(135deg, #6FBA9D 0%, #5EA98C 100%);
clip-path: polygon(40% 0%, 100% 0%, 100% 100%, 0% 100%);
}
/* Header */
.header {
position: relative;
z-index: 10;
padding: 4mm 3.5mm;
display: table;
width: 100%;
}
.logo-cell {
display: table-cell;
width: 12mm;
vertical-align: middle;
}
.logo {
width: 10mm;
height: 10mm;
background: linear-gradient(135deg, #6FBA9D, #8FCAAE);
border-radius: 50%;
text-align: center;
line-height: 10mm;
font-size: 16pt;
box-shadow: 0 2mm 4mm rgba(0,0,0,0.2);
}
.title-cell {
display: table-cell;
vertical-align: middle;
padding-left: 2mm;
}
.title-cell h1 {
font-size: 11pt;
font-weight: 900;
color: white;
letter-spacing: 1pt;
text-shadow: 0 1mm 2mm rgba(0,0,0,0.2);
}
.title-cell p {
font-size: 6pt;
color: #6FBA9D;
margin-top: 0.5mm;
font-weight: 600;
}
/* Content Area */
.content {
position: relative;
z-index: 10;
padding: 0 3.5mm;
display: table;
width: 100%;
}
.photo-col {
display: table-cell;
width: 22mm;
vertical-align: middle;
text-align: center;
}
.photo-frame {
width: 18mm;
height: 18mm;
background: white;
border-radius: 50%;
margin: 0 auto 2mm;
padding: 1.5mm;
box-shadow: 0 2mm 6mm rgba(0,0,0,0.25);
position: relative;
}
.photo {
width: 100%;
height: 100%;
background: linear-gradient(135deg, #6FBA9D, #8FCAAE);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 20pt;
color: white;
font-weight: bold;
}
.badge {
position: absolute;
bottom: 0;
right: 0;
width: 5mm;
height: 5mm;
background: #6FBA9D;
border-radius: 50%;
border: 1.5mm solid white;
text-align: center;
line-height: 5mm;
color: white;
font-size: 7pt;
font-weight: bold;
}
.name {
font-size: 7pt;
color: white;
font-weight: 700;
text-transform: uppercase;
text-shadow: 0 0.5mm 1mm rgba(0,0,0,0.3);
line-height: 1.2;
}
.info-col {
display: table-cell;
vertical-align: middle;
padding: 0 2mm;
}
.info-box {
background: rgba(255, 255, 255, 0.95);
border-radius: 2mm;
padding: 2.5mm 3mm;
box-shadow: 0 1mm 4mm rgba(0,0,0,0.15);
}
.info-item {
margin-bottom: 1.5mm;
font-size: 6pt;
}
.info-item:last-child {
margin-bottom: 0;
}
.label {
font-weight: 800;
color: #2C3E50;
display: inline-block;
width: 12mm;
text-transform: uppercase;
}
.value {
color: #34495E;
font-weight: 600;
}
.rfid {
font-family: 'Courier New', monospace;
font-size: 5pt;
}
.qr-col {
display: table-cell;
width: 20mm;
vertical-align: middle;
text-align: center;
}
.qr-box {
background: white;
border-radius: 2mm;
padding: 1.5mm;
box-shadow: 0 2mm 5mm rgba(0,0,0,0.2);
display: inline-block;
}
.qr-img {
width: 16mm;
height: 16mm;
display: block;
}
.scan {
margin-top: 1.5mm;
font-size: 5pt;
color: white;
font-weight: 700;
background: linear-gradient(135deg, #6FBA9D, #5EA98C);
padding: 1mm 2mm;
border-radius: 1mm;
display: inline-block;
text-transform: uppercase;
}
.footer {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 1.5mm;
background: linear-gradient(90deg, #6FBA9D 0%, #5EA98C 50%, #6FBA9D 100%);
z-index: 10;
}
/* === SISI BELAKANG === */
.card-back {
width: 85.6mm;
height: 54mm;
background: linear-gradient(135deg, #6FBA9D 0%, #5EA98C 100%);
position: relative;
overflow: hidden;
}
.back-pattern-1 {
position: absolute;
top: -15mm;
left: -15mm;
width: 50mm;
height: 50mm;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
}
.back-pattern-2 {
position: absolute;
bottom: -20mm;
right: -20mm;
width: 60mm;
height: 60mm;
background: rgba(255, 255, 255, 0.08);
border-radius: 50%;
}
.back-content {
position: relative;
z-index: 5;
padding: 5mm;
height: 100%;
display: flex;
flex-direction: column;
}
.back-header {
text-align: center;
margin-bottom: 3mm;
}
.back-logo {
width: 12mm;
height: 12mm;
background: white;
border-radius: 50%;
margin: 0 auto 2mm;
text-align: center;
line-height: 12mm;
font-size: 20pt;
box-shadow: 0 2mm 6mm rgba(0,0,0,0.15);
}
.back-title {
font-size: 10pt;
font-weight: 900;
color: white;
text-transform: uppercase;
letter-spacing: 1pt;
}
.back-subtitle {
font-size: 7pt;
color: rgba(255, 255, 255, 0.9);
margin-top: 0.5mm;
}
.info-section {
background: rgba(255, 255, 255, 0.95);
border-radius: 2mm;
padding: 3mm;
margin-bottom: 2mm;
flex-grow: 1;
}
.section-title {
font-size: 7pt;
font-weight: 800;
color: #2C3E50;
text-transform: uppercase;
margin-bottom: 2mm;
border-bottom: 0.5mm solid #6FBA9D;
padding-bottom: 1mm;
}
.rule {
font-size: 5.5pt;
color: #34495E;
line-height: 1.4;
margin-bottom: 1.5mm;
display: flex;
}
.rule-icon {
color: #6FBA9D;
margin-right: 1.5mm;
font-weight: bold;
}
.contact {
background: white;
border-radius: 2mm;
padding: 2mm 3mm;
text-align: center;
font-size: 5pt;
color: #2C3E50;
}
.contact-item {
margin-bottom: 0.5mm;
font-weight: 600;
}
.contact-item:last-child {
margin-bottom: 0;
}
.contact-icon {
color: #6FBA9D;
margin-right: 1mm;
}
</style>
</head>
<body>
<!-- ========== SISI DEPAN ========== -->
<div class="card-front">
<div class="bg-circle-1"></div>
<div class="bg-circle-2"></div>
<div class="wave"></div>
<div class="header">
<div class="logo-cell">
<div class="logo">🕌</div>
</div>
<div class="title-cell">
<h1>PKPPS</h1>
<p>Pesantren Riyadlul Jannah</p>
</div>
</div>
<div class="content">
<div class="photo-col">
<div class="photo-frame">
<div class="photo">
<?php if(isset($santri)): ?><?php echo e(strtoupper(substr($santri->nama_lengkap, 0, 1))); ?><?php else: ?> A <?php endif; ?>
</div>
<div class="badge"></div>
</div>
<div class="name">
<?php if(isset($santri)): ?><?php echo e(strtoupper(Str::limit($santri->nama_lengkap, 12, ''))); ?><?php else: ?> YOUR NAME <?php endif; ?>
</div>
</div>
<div class="info-col">
<div class="info-box">
<div class="info-item">
<span class="label">ID</span>
<span class="value">: <?php if(isset($santri)): ?><?php echo e($santri->id_santri); ?><?php else: ?> S004 <?php endif; ?></span>
</div>
<div class="info-item">
<span class="label">Kelas</span>
<span class="value">: <?php if(isset($santri)): ?><?php echo e($santri->kelas); ?><?php else: ?> Lambatan <?php endif; ?></span>
</div>
<div class="info-item">
<span class="label">Status</span>
<span class="value">: <?php if(isset($santri)): ?><?php echo e($santri->status); ?><?php else: ?> Aktif <?php endif; ?></span>
</div>
<div class="info-item">
<span class="label">RFID</span>
<span class="value rfid">: <?php if(isset($santri) && $santri->rfid_uid): ?><?php echo e(Str::limit($santri->rfid_uid, 14)); ?><?php else: ?> 04A3B62FD9C1 <?php endif; ?></span>
</div>
</div>
</div>
<div class="qr-col">
<div class="qr-box">
<?php if(isset($santri) && $santri->rfid_uid): ?>
<img src="https://chart.googleapis.com/chart?cht=qr&chs=200x200&chl=<?php echo e(urlencode($santri->rfid_uid)); ?>" class="qr-img" alt="QR">
<?php else: ?>
<img src="https://chart.googleapis.com/chart?cht=qr&chs=200x200&chl=04A3B62FD9C1" class="qr-img" alt="QR">
<?php endif; ?>
</div>
<div class="scan">SCAN ME</div>
</div>
</div>
<div class="footer"></div>
</div>
<!-- ========== SISI BELAKANG ========== -->
<div class="card-back">
<div class="back-pattern-1"></div>
<div class="back-pattern-2"></div>
<div class="back-content">
<div class="back-header">
<div class="back-logo">🕌</div>
<div class="back-title">PKPPS</div>
<div class="back-subtitle">Pesantren Riyadlul Jannah</div>
</div>
<div class="info-section">
<div class="section-title">📋 Ketentuan Kartu</div>
<div class="rule">
<span class="rule-icon"></span>
<span>Kartu ini adalah identitas resmi santri PKPPS</span>
</div>
<div class="rule">
<span class="rule-icon"></span>
<span>Wajib dibawa setiap saat di lingkungan pesantren</span>
</div>
<div class="rule">
<span class="rule-icon"></span>
<span>Digunakan untuk absensi kegiatan dan akses fasilitas</span>
</div>
<div class="rule">
<span class="rule-icon"></span>
<span>Jika hilang segera lapor ke bagian administrasi</span>
</div>
<div class="rule">
<span class="rule-icon"></span>
<span>Harap dijaga dan tidak dipinjamkan</span>
</div>
</div>
<div class="contact">
<div class="contact-item">
<span class="contact-icon">📍</span> Jl. Pesantren No. 123, Yogyakarta
</div>
<div class="contact-item">
<span class="contact-icon">📞</span> (0274) 123-4567
</div>
<div class="contact-item">
<span class="contact-icon">📧</span> admin@pkpps.ac.id
</div>
</div>
</div>
</div>
</body>
</html><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/kartu/cetak.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,166 @@
<?php $__env->startSection('title', 'Pembayaran SPP'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-money-bill-wave"></i> Pembayaran SPP</h2>
</div>
<?php if(session('success')): ?>
<div class="alert alert-success">
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
</div>
<?php endif; ?>
<?php if(session('error')): ?>
<div class="alert alert-danger">
<i class="fas fa-exclamation-circle"></i> <?php echo e(session('error')); ?>
</div>
<?php endif; ?>
<div class="content-box">
<!-- Header Actions -->
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; flex-wrap: wrap; gap: 15px;">
<!-- Search & Filter Form -->
<form method="GET" action="<?php echo e(route('admin.pembayaran-spp.index')); ?>" style="display: flex; gap: 10px; flex-wrap: wrap; flex: 1;">
<input type="text"
name="search"
class="form-control"
placeholder="Cari santri atau ID..."
value="<?php echo e(request('search')); ?>"
style="max-width: 250px;">
<select name="status" class="form-control" style="max-width: 180px;">
<option value="">Semua Status</option>
<option value="Lunas" <?php echo e(request('status') === 'Lunas' ? 'selected' : ''); ?>>Lunas</option>
<option value="Belum Lunas" <?php echo e(request('status') === 'Belum Lunas' ? 'selected' : ''); ?>>Belum Lunas</option>
<option value="Telat" <?php echo e(request('status') === 'Telat' ? 'selected' : ''); ?>>Telat</option>
</select>
<select name="bulan" class="form-control" style="max-width: 150px;">
<option value="">Semua Bulan</option>
<?php for($i = 1; $i <= 12; $i++): ?>
<option value="<?php echo e($i); ?>" <?php echo e(request('bulan') == $i ? 'selected' : ''); ?>>
<?php echo e(DateTime::createFromFormat('!m', $i)->format('F')); ?>
</option>
<?php endfor; ?>
</select>
<select name="tahun" class="form-control" style="max-width: 120px;">
<option value="">Semua Tahun</option>
<?php $__currentLoopData = $tahunList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $tahun): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($tahun); ?>" <?php echo e(request('tahun') == $tahun ? 'selected' : ''); ?>>
<?php echo e($tahun); ?>
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<button type="submit" class="btn btn-primary btn-sm">
<i class="fas fa-search"></i> Cari
</button>
<?php if(request()->hasAny(['search', 'status', 'bulan', 'tahun'])): ?>
<a href="<?php echo e(route('admin.pembayaran-spp.index')); ?>" class="btn btn-secondary btn-sm">
<i class="fas fa-times"></i> Reset
</a>
<?php endif; ?>
</form>
<!-- Action Buttons -->
<div style="display: flex; gap: 10px;">
<a href="<?php echo e(route('admin.pembayaran-spp.generate')); ?>" class="btn btn-warning btn-sm hover-shadow">
<i class="fas fa-cogs"></i> Generate SPP
</a>
<a href="<?php echo e(route('admin.pembayaran-spp.create')); ?>" class="btn btn-success btn-sm hover-shadow">
<i class="fas fa-plus-circle"></i> Tambah Data
</a>
</div>
</div>
<!-- Table -->
<div style="overflow-x: auto;">
<table class="data-table">
<thead>
<tr>
<th>No</th>
<th>ID Pembayaran</th>
<th>Santri</th>
<th>Periode</th>
<th>Nominal</th>
<th>Batas Bayar</th>
<th>Status</th>
<th class="text-center">Aksi</th>
</tr>
</thead>
<tbody>
<?php $__empty_1 = true; $__currentLoopData = $pembayaranSpp; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $spp): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
<tr>
<td><?php echo e($pembayaranSpp->firstItem() + $index); ?></td>
<td><strong><?php echo e($spp->id_pembayaran); ?></strong></td>
<td>
<strong><?php echo e($spp->santri->nama_lengkap); ?></strong><br>
<small class="text-muted"><?php echo e($spp->santri->id_santri); ?> - <?php echo e($spp->santri->kelas); ?></small>
</td>
<td><?php echo e($spp->periode_lengkap); ?></td>
<td><strong><?php echo e($spp->nominal_format); ?></strong></td>
<td>
<?php echo e($spp->batas_bayar->format('d/m/Y')); ?>
<?php if($spp->isTelat()): ?>
<br><small class="text-muted" style="color: #FF8B94 !important;">
<i class="fas fa-exclamation-triangle"></i> Telat
</small>
<?php endif; ?>
</td>
<td><?php echo $spp->status_badge; ?></td>
<td class="text-center">
<a href="<?php echo e(route('admin.pembayaran-spp.show', $spp->id)); ?>"
class="btn btn-sm btn-primary"
title="Detail">
<i class="fas fa-eye"></i>
</a>
<a href="<?php echo e(route('admin.pembayaran-spp.edit', $spp->id)); ?>"
class="btn btn-sm btn-warning"
title="Edit">
<i class="fas fa-edit"></i>
</a>
<form action="<?php echo e(route('admin.pembayaran-spp.destroy', $spp->id)); ?>"
method="POST"
style="display: inline-block;"
onsubmit="return confirm('Yakin ingin menghapus data ini?')">
<?php echo csrf_field(); ?>
<?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-sm btn-danger" title="Hapus">
<i class="fas fa-trash"></i>
</button>
</form>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
<tr>
<td colspan="8" class="text-center" style="padding: 40px;">
<i class="fas fa-inbox" style="font-size: 3rem; color: #ccc; display: block; margin-bottom: 15px;"></i>
<p style="color: #999;">Tidak ada data pembayaran SPP.</p>
</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
<!-- Pagination -->
<?php if($pembayaranSpp->hasPages()): ?>
<div style="margin-top: 20px;">
<?php echo e($pembayaranSpp->links()); ?>
</div>
<?php endif; ?>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/pembayaran-spp/index.blade.php ENDPATH**/ ?>

View File

@ -1,421 +0,0 @@
<?php $__env->startSection('title', 'Tambah Berita Baru'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-plus-circle"></i> Tambah Berita Baru</h2>
</div>
<!-- Alert Errors -->
<?php if($errors->any()): ?>
<div class="alert alert-danger">
<strong><i class="fas fa-exclamation-circle"></i> Terdapat kesalahan:</strong>
<ul style="margin: 10px 0 0 20px;">
<?php $__currentLoopData = $errors->all(); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $error): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<li><?php echo e($error); ?></li>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</ul>
</div>
<?php endif; ?>
<div class="content-box">
<form action="<?php echo e(route('admin.berita.store')); ?>" method="POST" enctype="multipart/form-data">
<?php echo csrf_field(); ?>
<!-- Judul Berita -->
<div class="form-group">
<label for="judul">
<i class="fas fa-heading form-icon"></i>
Judul Berita <span style="color: var(--danger-color);">*</span>
</label>
<input type="text"
id="judul"
name="judul"
class="form-control <?php $__errorArgs = ['judul'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
value="<?php echo e(old('judul')); ?>"
placeholder="Masukkan judul berita..."
required>
<?php $__errorArgs = ['judul'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<!-- Konten Berita -->
<div class="form-group">
<label for="konten">
<i class="fas fa-align-left form-icon"></i>
Konten Berita <span style="color: var(--danger-color);">*</span>
</label>
<textarea id="konten"
name="konten"
class="form-control <?php $__errorArgs = ['konten'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
rows="10"
placeholder="Tulis konten berita di sini..."
required><?php echo e(old('konten')); ?></textarea>
<?php $__errorArgs = ['konten'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<!-- Penulis & Gambar -->
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<div class="form-group">
<label for="penulis">
<i class="fas fa-user-edit form-icon"></i>
Penulis <span style="color: var(--danger-color);">*</span>
</label>
<input type="text"
id="penulis"
name="penulis"
class="form-control <?php $__errorArgs = ['penulis'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
value="<?php echo e(old('penulis')); ?>"
placeholder="Nama penulis berita"
required>
<?php $__errorArgs = ['penulis'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div class="form-group">
<label for="gambar">
<i class="fas fa-image form-icon"></i>
Gambar Berita (Opsional)
</label>
<input type="file"
id="gambar"
name="gambar"
class="form-control <?php $__errorArgs = ['gambar'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
accept="image/*">
<small class="form-text">Format: JPG, PNG, GIF. Maksimal 2MB.</small>
<?php $__errorArgs = ['gambar'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
</div>
<!-- Target & Status -->
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<div class="form-group">
<label for="target_berita">
<i class="fas fa-bullseye form-icon"></i>
Target Berita <span style="color: var(--danger-color);">*</span>
</label>
<select id="target_berita"
name="target_berita"
class="form-control <?php $__errorArgs = ['target_berita'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
required>
<option value="">-- Pilih Target --</option>
<option value="semua" <?php echo e(old('target_berita') == 'semua' ? 'selected' : ''); ?>>
Semua Santri
</option>
<option value="kelas_tertentu" <?php echo e(old('target_berita') == 'kelas_tertentu' ? 'selected' : ''); ?>>
Kelas Tertentu
</option>
<option value="santri_tertentu" <?php echo e(old('target_berita') == 'santri_tertentu' ? 'selected' : ''); ?>>
Santri Tertentu
</option>
</select>
<?php $__errorArgs = ['target_berita'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div class="form-group">
<label for="status">
<i class="fas fa-toggle-on form-icon"></i>
Status Berita <span style="color: var(--danger-color);">*</span>
</label>
<select id="status"
name="status"
class="form-control <?php $__errorArgs = ['status'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
required>
<option value="">-- Pilih Status --</option>
<option value="draft" <?php echo e(old('status') == 'draft' ? 'selected' : ''); ?>>
Draft (Belum Dipublikasi)
</option>
<option value="published" <?php echo e(old('status') == 'published' ? 'selected' : ''); ?>>
Published (Dipublikasi)
</option>
</select>
<?php $__errorArgs = ['status'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
</div>
<!-- Section: Pilih Kelas Tertentu -->
<div id="kelas-section" class="form-group" style="display: none;">
<label>
<i class="fas fa-graduation-cap form-icon"></i>
Pilih Kelas yang Akan Menerima Berita <span style="color: var(--danger-color);">*</span>
</label>
<div style="border: 2px solid var(--primary-light); border-radius: var(--border-radius-sm); padding: 20px; background-color: var(--primary-light);">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 15px;">
<?php $__currentLoopData = $kelasOptions; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<div style="background: white; padding: 12px; border-radius: var(--border-radius-sm); box-shadow: var(--shadow-sm);">
<label style="display: flex; align-items: center; margin: 0; cursor: pointer;">
<input type="checkbox"
id="kelas_<?php echo e($kelas); ?>"
name="target_kelas[]"
value="<?php echo e($kelas); ?>"
class="kelas-checkbox"
style="margin-right: 10px; width: 18px; height: 18px;"
<?php echo e(in_array($kelas, old('target_kelas', [])) ? 'checked' : ''); ?>>
<span style="font-weight: 600; color: var(--text-color);">
Kelas <?php echo e($kelas); ?>
</span>
</label>
</div>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</div>
</div>
<small class="form-text">
<i class="fas fa-info-circle"></i>
<span id="selected-kelas-count">0</span> kelas dipilih dari <?php echo e(count($kelasOptions)); ?> total kelas.
</small>
</div>
<!-- Section: Pilih Santri Tertentu -->
<div id="santri-section" class="form-group" style="display: none;">
<label>
<i class="fas fa-users form-icon"></i>
Pilih Santri yang Akan Menerima Berita <span style="color: var(--danger-color);">*</span>
</label>
<!-- Select All -->
<div style="background: var(--primary-light); padding: 12px; border-radius: var(--border-radius-sm); margin-bottom: 10px;">
<label style="display: flex; align-items: center; margin: 0; cursor: pointer; font-weight: 600;">
<input type="checkbox"
id="select-all"
style="margin-right: 10px; width: 20px; height: 20px;">
<span style="color: var(--primary-dark);">
<i class="fas fa-check-double"></i> Pilih Semua Santri
</span>
</label>
</div>
<!-- List Santri -->
<div style="border: 2px solid var(--primary-light); border-radius: var(--border-radius-sm); padding: 15px; max-height: 400px; overflow-y: auto; background-color: #FAFAFA;">
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px;">
<?php $__currentLoopData = $santri; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $s): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<div style="background: white; padding: 12px; border-radius: var(--border-radius-sm); box-shadow: var(--shadow-sm); transition: all 0.2s ease;">
<label style="display: flex; align-items: center; gap: 10px; margin: 0; cursor: pointer;">
<input type="checkbox"
id="santri_<?php echo e($s->id_santri); ?>"
name="santri_tertentu[]"
value="<?php echo e($s->id_santri); ?>"
class="santri-checkbox"
style="width: 18px; height: 18px; flex-shrink: 0;"
<?php echo e(in_array($s->id_santri, old('santri_tertentu', [])) ? 'checked' : ''); ?>>
<!-- Hanya tampilkan initial, tanpa foto -->
<div style="width: 40px; height: 40px; border-radius: 50%; background: var(--primary-color); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; flex-shrink: 0;">
<?php echo e(strtoupper(substr($s->nama_lengkap, 0, 1))); ?>
</div>
<div style="flex-grow: 1; min-width: 0;">
<div style="font-weight: 600; color: var(--primary-color); font-size: 0.85em;">
<?php echo e($s->id_santri); ?>
</div>
<div style="font-weight: 500; color: var(--text-color); font-size: 0.9em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
<?php echo e($s->nama_lengkap); ?>
</div>
<div style="font-size: 0.8em; color: var(--text-light);">
<?php echo e($s->kelas); ?>
</div>
</div>
</label>
</div>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</div>
</div>
<small class="form-text">
<i class="fas fa-info-circle"></i>
<span id="selected-count">0</span> santri dipilih dari <?php echo e($santri->count()); ?> total santri aktif.
</small>
</div>
<!-- Submit Buttons -->
<div style="display: flex; gap: 10px; margin-top: 30px; padding-top: 20px; border-top: 2px solid var(--primary-light);">
<button type="submit" class="btn btn-success">
<i class="fas fa-save"></i> Simpan Berita
</button>
<a href="<?php echo e(route('admin.berita.index')); ?>" class="btn btn-secondary">
<i class="fas fa-times"></i> Batal
</a>
</div>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const targetBerita = document.getElementById('target_berita');
const santriSection = document.getElementById('santri-section');
const kelasSection = document.getElementById('kelas-section');
const selectAll = document.getElementById('select-all');
const santriCheckboxes = document.querySelectorAll('.santri-checkbox');
const kelasCheckboxes = document.querySelectorAll('.kelas-checkbox');
const selectedCount = document.getElementById('selected-count');
const selectedKelasCount = document.getElementById('selected-kelas-count');
// Toggle sections berdasarkan target berita
targetBerita.addEventListener('change', function() {
santriSection.style.display = 'none';
kelasSection.style.display = 'none';
if (this.value === 'santri_tertentu') {
santriSection.style.display = 'block';
} else if (this.value === 'kelas_tertentu') {
kelasSection.style.display = 'block';
} else {
// Reset checkboxes
if (selectAll) selectAll.checked = false;
santriCheckboxes.forEach(cb => cb.checked = false);
kelasCheckboxes.forEach(cb => cb.checked = false);
updateSelectedCount();
updateSelectedKelasCount();
}
});
// Trigger on page load jika ada old value
if (targetBerita.value === 'santri_tertentu') {
santriSection.style.display = 'block';
} else if (targetBerita.value === 'kelas_tertentu') {
kelasSection.style.display = 'block';
}
// Select All functionality untuk santri
if (selectAll) {
selectAll.addEventListener('change', function() {
santriCheckboxes.forEach(checkbox => {
checkbox.checked = this.checked;
});
updateSelectedCount();
});
}
// Update select all ketika checkbox santri individual berubah
santriCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', function() {
const checkedCount = document.querySelectorAll('.santri-checkbox:checked').length;
if (selectAll) {
selectAll.checked = checkedCount === santriCheckboxes.length;
selectAll.indeterminate = checkedCount > 0 && checkedCount < santriCheckboxes.length;
}
updateSelectedCount();
});
});
// Update counter untuk kelas
kelasCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', updateSelectedKelasCount);
});
// Functions untuk update counter
function updateSelectedCount() {
const checkedCount = document.querySelectorAll('.santri-checkbox:checked').length;
if (selectedCount) selectedCount.textContent = checkedCount;
}
function updateSelectedKelasCount() {
const checkedCount = document.querySelectorAll('.kelas-checkbox:checked').length;
if (selectedKelasCount) selectedKelasCount.textContent = checkedCount;
}
// Initial count
updateSelectedCount();
updateSelectedKelasCount();
});
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/berita/create.blade.php ENDPATH**/ ?>

View File

@ -0,0 +1,280 @@
<?php $__env->startSection('title', 'Tambah Data Kesehatan Santri'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-plus-circle"></i> Tambah Data Kesehatan Santri</h2>
</div>
<!-- Content Box -->
<div class="content-box">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
<h3 style="margin: 0; color: var(--primary-color);">
<i class="fas fa-file-medical"></i> Form Data Kesehatan
</h3>
<a href="<?php echo e(route('admin.kesehatan-santri.index')); ?>" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Kembali
</a>
</div>
<form action="<?php echo e(route('admin.kesehatan-santri.store')); ?>" method="POST">
<?php echo csrf_field(); ?>
<!-- Pilih Santri -->
<div class="form-group">
<label for="id_santri"><i class="fas fa-user form-icon"></i>Santri *</label>
<select name="id_santri" id="id_santri" class="form-control <?php $__errorArgs = ['id_santri'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>" required>
<option value="">-- Pilih Santri --</option>
<?php $__currentLoopData = $santri; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $s): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($s->id_santri); ?>" <?php echo e(old('id_santri') == $s->id_santri ? 'selected' : ''); ?>>
<?php echo e($s->id_santri); ?> - <?php echo e($s->nama_lengkap); ?> (<?php echo e($s->kelas); ?>)
</option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<?php $__errorArgs = ['id_santri'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<div class="invalid-feedback"><?php echo e($message); ?></div>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<!-- Tanggal Masuk -->
<div class="form-group">
<label for="tanggal_masuk"><i class="fas fa-calendar-plus form-icon"></i>Tanggal Masuk UKP *</label>
<input type="date"
name="tanggal_masuk"
id="tanggal_masuk"
class="form-control <?php $__errorArgs = ['tanggal_masuk'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
value="<?php echo e(old('tanggal_masuk', date('Y-m-d'))); ?>"
max="<?php echo e(date('Y-m-d')); ?>"
required>
<?php $__errorArgs = ['tanggal_masuk'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<div class="invalid-feedback"><?php echo e($message); ?></div>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<!-- Status -->
<div class="form-group">
<label for="status"><i class="fas fa-info-circle form-icon"></i>Status *</label>
<select name="status" id="status" class="form-control <?php $__errorArgs = ['status'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>" required>
<option value="">-- Pilih Status --</option>
<option value="dirawat" <?php echo e(old('status') == 'dirawat' ? 'selected' : ''); ?>>Dirawat</option>
<option value="sembuh" <?php echo e(old('status') == 'sembuh' ? 'selected' : ''); ?>>Sembuh</option>
<option value="izin" <?php echo e(old('status') == 'izin' ? 'selected' : ''); ?>>Izin Pulang</option>
</select>
<?php $__errorArgs = ['status'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<div class="invalid-feedback"><?php echo e($message); ?></div>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
</div>
<!-- Tanggal Keluar (Hidden by default) -->
<div id="tanggal_keluar_group" class="form-group" style="display: none;">
<label for="tanggal_keluar"><i class="fas fa-calendar-check form-icon"></i>Tanggal Keluar UKP</label>
<input type="date"
name="tanggal_keluar"
id="tanggal_keluar"
class="form-control <?php $__errorArgs = ['tanggal_keluar'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
value="<?php echo e(old('tanggal_keluar')); ?>"
max="<?php echo e(date('Y-m-d')); ?>">
<?php $__errorArgs = ['tanggal_keluar'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<div class="invalid-feedback"><?php echo e($message); ?></div>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
<small class="form-text">
<i class="fas fa-info-circle"></i> Kosongkan jika santri masih dirawat
</small>
</div>
<!-- Keluhan -->
<div class="form-group">
<label for="keluhan"><i class="fas fa-notes-medical form-icon"></i>Keluhan *</label>
<textarea name="keluhan"
id="keluhan"
rows="4"
class="form-control <?php $__errorArgs = ['keluhan'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
placeholder="Tuliskan keluhan atau gejala yang dialami santri..."
required><?php echo e(old('keluhan')); ?></textarea>
<?php $__errorArgs = ['keluhan'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<div class="invalid-feedback"><?php echo e($message); ?></div>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
<small class="form-text">Maksimal 1000 karakter</small>
</div>
<!-- Catatan -->
<div class="form-group">
<label for="catatan"><i class="fas fa-clipboard form-icon"></i>Catatan Petugas</label>
<textarea name="catatan"
id="catatan"
rows="3"
class="form-control <?php $__errorArgs = ['catatan'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>"
placeholder="Catatan tambahan dari petugas kesehatan..."><?php echo e(old('catatan')); ?></textarea>
<?php $__errorArgs = ['catatan'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<div class="invalid-feedback"><?php echo e($message); ?></div>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
<small class="form-text">Maksimal 1000 karakter (opsional)</small>
</div>
<!-- Buttons -->
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 30px;">
<a href="<?php echo e(route('admin.kesehatan-santri.index')); ?>" class="btn btn-secondary">
<i class="fas fa-times"></i> Batal
</a>
<button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i> Simpan Data
</button>
</div>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const statusSelect = document.getElementById('status');
const tanggalKeluarGroup = document.getElementById('tanggal_keluar_group');
const tanggalKeluarInput = document.getElementById('tanggal_keluar');
const tanggalMasukInput = document.getElementById('tanggal_masuk');
// Function to toggle tanggal keluar visibility
function toggleTanggalKeluar() {
if (statusSelect.value === 'dirawat') {
tanggalKeluarGroup.style.display = 'none';
tanggalKeluarInput.value = '';
tanggalKeluarInput.removeAttribute('required');
} else {
tanggalKeluarGroup.style.display = 'block';
if (statusSelect.value === 'sembuh' || statusSelect.value === 'izin') {
tanggalKeluarInput.setAttribute('required', 'required');
}
}
}
// Set minimum date for tanggal_keluar based on tanggal_masuk
function setMinTanggalKeluar() {
if (tanggalMasukInput.value) {
tanggalKeluarInput.min = tanggalMasukInput.value;
}
}
// Event listeners
statusSelect.addEventListener('change', toggleTanggalKeluar);
tanggalMasukInput.addEventListener('change', setMinTanggalKeluar);
// Initialize on page load
toggleTanggalKeluar();
setMinTanggalKeluar();
// Character counter
function setupCharacterCounter(textareaId, maxLength) {
const textarea = document.getElementById(textareaId);
const counter = document.createElement('div');
counter.style.cssText = 'text-align: right; font-size: 0.85em; color: #7F8C8D; margin-top: 5px;';
function updateCounter() {
const remaining = maxLength - textarea.value.length;
counter.textContent = `${textarea.value.length}/${maxLength} karakter`;
counter.style.color = remaining < 50 ? '#E74C3C' : '#7F8C8D';
}
textarea.addEventListener('input', updateCounter);
// Insert counter after the last sibling (after form-text if exists)
const lastSibling = textarea.parentNode.lastElementChild;
if (lastSibling.classList && lastSibling.classList.contains('form-text')) {
lastSibling.parentNode.appendChild(counter);
} else {
textarea.parentNode.appendChild(counter);
}
updateCounter();
}
setupCharacterCounter('keluhan', 1000);
setupCharacterCounter('catatan', 1000);
});
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kesehatan-santri/create.blade.php ENDPATH**/ ?>

View File

@ -1,68 +0,0 @@
<?php $__env->startSection('title', 'Daftar Kategori Pelanggaran'); ?>
<?php $__env->startSection('content'); ?>
<div class="page-header">
<h2><i class="fas fa-list-ul"></i> Daftar Kategori Pelanggaran & Poin</h2>
</div>
<div class="content-box">
<div style="margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center;">
<p class="text-muted">
<i class="fas fa-info-circle"></i>
Berikut adalah daftar kategori pelanggaran beserta poin yang berlaku di pondok.
</p>
<a href="<?php echo e(route('santri.pelanggaran.index')); ?>" class="btn btn-secondary btn-sm">
<i class="fas fa-arrow-left"></i> Kembali ke Riwayat
</a>
</div>
<?php if($kategoriList->count() > 0): ?>
<div style="overflow-x: auto;">
<table class="data-table">
<thead>
<tr>
<th style="width: 8%;">No</th>
<th style="width: 15%;">Kode</th>
<th style="width: 57%;">Jenis Pelanggaran</th>
<th style="width: 20%; text-align: center;">Poin</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $kategoriList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $kategori): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><?php echo e($index + 1); ?></td>
<td><strong><?php echo e($kategori->id_kategori); ?></strong></td>
<td><?php echo e($kategori->nama_pelanggaran); ?></td>
<td class="text-center">
<?php if($kategori->poin <= 5): ?>
<span class="badge badge-warning badge-lg">
<i class="fas fa-star"></i> <?php echo e($kategori->poin); ?> Poin
</span>
<?php elseif($kategori->poin <= 15): ?>
<span class="badge badge-danger badge-lg">
<i class="fas fa-star"></i> <?php echo e($kategori->poin); ?> Poin
</span>
<?php else: ?>
<span class="badge badge-danger badge-lg" style="background: linear-gradient(135deg, #dc3545 0%, #a71d2a 100%);">
<i class="fas fa-star"></i> <?php echo e($kategori->poin); ?> Poin
</span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
</div>
<?php else: ?>
<div class="empty-state">
<i class="fas fa-list"></i>
<h3>Belum Ada Kategori</h3>
<p>Daftar kategori pelanggaran belum tersedia.</p>
</div>
<?php endif; ?>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/santri/pelanggaran/kategori.blade.php ENDPATH**/ ?>

45
sim_mobile/.gitignore vendored Normal file
View File

@ -0,0 +1,45 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

45
sim_mobile/.metadata Normal file
View File

@ -0,0 +1,45 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "ea121f8859e4b13e47a8f845e4586164519588bc"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
- platform: android
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
- platform: ios
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
- platform: linux
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
- platform: macos
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
- platform: web
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
- platform: windows
create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

16
sim_mobile/README.md Normal file
View File

@ -0,0 +1,16 @@
# sim_mobile
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

View File

@ -0,0 +1,28 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

14
sim_mobile/android/.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
.cxx/
# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
key.properties
**/*.keystore
**/*.jks

View File

@ -0,0 +1,44 @@
plugins {
id("com.android.application")
id("kotlin-android")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}
android {
namespace = "com.example.sim_mobile"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.sim_mobile"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
}
}
}
flutter {
source = "../.."
}

View File

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -0,0 +1,45 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="sim_mobile"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>

View File

@ -0,0 +1,5 @@
package com.example.sim_mobile
import io.flutter.embedding.android.FlutterActivity
class MainActivity : FlutterActivity()

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Some files were not shown because too many files have changed in this diff Show More