final
This commit is contained in:
parent
46ded0ee5c
commit
1332db7373
|
|
@ -11,7 +11,7 @@ LOG_LEVEL=debug
|
||||||
DB_CONNECTION=mysql
|
DB_CONNECTION=mysql
|
||||||
DB_HOST=127.0.0.1
|
DB_HOST=127.0.0.1
|
||||||
DB_PORT=3306
|
DB_PORT=3306
|
||||||
DB_DATABASE=sim_santri
|
DB_DATABASE=laravel
|
||||||
DB_USERNAME=root
|
DB_USERNAME=root
|
||||||
DB_PASSWORD=
|
DB_PASSWORD=
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ public function __construct(private EpposGLogParser $parser) {}
|
||||||
// ──────────────────────────────────────────────────────────
|
// ──────────────────────────────────────────────────────────
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
// Hitung yang benar-benar belum punya santri (id_santri null atau kosong)
|
|
||||||
$belumMapping = MesinSantriMapping::where('is_active', true)
|
$belumMapping = MesinSantriMapping::where('is_active', true)
|
||||||
->where(function ($q) {
|
->where(function ($q) {
|
||||||
$q->whereNull('id_santri')->orWhere('id_santri', '');
|
$q->whereNull('id_santri')->orWhere('id_santri', '');
|
||||||
|
|
@ -35,9 +34,9 @@ public function index()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ──────────────────────────────────────────────────────────
|
// ──────────────────────────────────────────────────────────
|
||||||
// PREVIEW — hanya POST
|
// PREVIEW — POST
|
||||||
// Setelah proses selesai, redirect ke showPreview (GET)
|
// Proses file GLog, simpan hasil ke session, redirect ke
|
||||||
// Ini mencegah error "MethodNotAllowed" saat user refresh halaman preview
|
// showPreview (GET). PRG pattern agar refresh tidak error.
|
||||||
// ──────────────────────────────────────────────────────────
|
// ──────────────────────────────────────────────────────────
|
||||||
public function preview(Request $request)
|
public function preview(Request $request)
|
||||||
{
|
{
|
||||||
|
|
@ -49,8 +48,11 @@ public function preview(Request $request)
|
||||||
'conflict_strategy' => 'nullable|in:mesin,exist,manual',
|
'conflict_strategy' => 'nullable|in:mesin,exist,manual',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tolSebelum = (int)($request->tol_sebelum ?? 15);
|
// ── Baca toleransi PERSIS dari form (bukan hardcode) ──
|
||||||
$tolSesudah = (int)($request->tol_sesudah ?? 10);
|
// Jika field tidak dikirim (misal: disable JS), fallback ke nilai
|
||||||
|
// default form (15 dan 10) yang sama persis dengan default di index.blade.php
|
||||||
|
$tolSebelum = (int)($request->input('tol_sebelum', 15));
|
||||||
|
$tolSesudah = (int)($request->input('tol_sesudah', 10));
|
||||||
$isiAlpa = $request->has('isi_alpa');
|
$isiAlpa = $request->has('isi_alpa');
|
||||||
$conflictStrategy = $request->input('conflict_strategy', 'mesin');
|
$conflictStrategy = $request->input('conflict_strategy', 'mesin');
|
||||||
|
|
||||||
|
|
@ -70,29 +72,18 @@ public function preview(Request $request)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Ambil infoData dari mapping yang sudah ada ────────
|
// ── Bangun infoData dari mapping yang sudah ada ───────
|
||||||
// Kita bangun infoData dari tabel mesin_santri_mappings
|
|
||||||
// sehingga tidak perlu upload INFO.XLS lagi
|
|
||||||
$mappingAll = MesinSantriMapping::where('is_active', true)->get();
|
$mappingAll = MesinSantriMapping::where('is_active', true)->get();
|
||||||
|
$infoData = ['shifts' => [], 'jadwal' => []];
|
||||||
// Bangun struktur infoData['jadwal'] dari mapping yang ada
|
|
||||||
// shifts dikosongkan karena matching pakai jam langsung
|
|
||||||
$infoData = [
|
|
||||||
'shifts' => [],
|
|
||||||
'jadwal' => [],
|
|
||||||
];
|
|
||||||
foreach ($mappingAll as $m) {
|
foreach ($mappingAll as $m) {
|
||||||
$infoData['jadwal'][$m->id_mesin] = [
|
$infoData['jadwal'][$m->id_mesin] = [
|
||||||
'nama' => $m->nama_mesin ?? '',
|
'nama' => $m->nama_mesin ?? '',
|
||||||
'dept' => $m->dept_mesin ?? '',
|
'dept' => $m->dept_mesin ?? '',
|
||||||
'shift' => 1, // default, tidak dipakai untuk matching jam
|
'shift' => 1,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Kegiatan dari DB ──────────────────────────────────
|
// ── Kegiatan dari DB ──────────────────────────────────
|
||||||
// Ambil semua kegiatan — waktu_selesai boleh null, pakai waktu_mulai sebagai fallback
|
|
||||||
// getRawOriginal() bypass Eloquent cast (datetime:H:i → Carbon)
|
|
||||||
// sehingga kita dapat string murni "04:00:00" dari DB, lalu substr → "04:00"
|
|
||||||
$kegiatans = Kegiatan::orderBy('hari')->orderBy('waktu_mulai')
|
$kegiatans = Kegiatan::orderBy('hari')->orderBy('waktu_mulai')
|
||||||
->get()
|
->get()
|
||||||
->map(function ($k) {
|
->map(function ($k) {
|
||||||
|
|
@ -116,13 +107,17 @@ public function preview(Request $request)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Match ─────────────────────────────────────────────
|
// ── Match scan ke kegiatan (pakai toleransi dari form) ─
|
||||||
$glogGrouped = $this->parser->groupGLogByDay($glogRecords);
|
$glogGrouped = $this->parser->groupGLogByDay($glogRecords);
|
||||||
$rawHasil = $this->parser->matchToKegiatan(
|
$rawHasil = $this->parser->matchToKegiatan(
|
||||||
$glogGrouped, $infoData, $kegiatans, $tolSebelum, $tolSesudah
|
$glogGrouped,
|
||||||
|
$infoData,
|
||||||
|
$kegiatans,
|
||||||
|
$tolSebelum, // ← dari form, bukan hardcode
|
||||||
|
$tolSesudah // ← dari form, bukan hardcode
|
||||||
);
|
);
|
||||||
|
|
||||||
// ── Enrich (santri web + kepulangan + konflik) ────────
|
// ── Enrich: santri web + kepulangan + deteksi konflik ─
|
||||||
$kepulanganCache = [];
|
$kepulanganCache = [];
|
||||||
$hasilEnriched = [];
|
$hasilEnriched = [];
|
||||||
|
|
||||||
|
|
@ -139,7 +134,7 @@ public function preview(Request $request)
|
||||||
$namaWeb = $mapping?->santri?->nama_lengkap;
|
$namaWeb = $mapping?->santri?->nama_lengkap;
|
||||||
$kelas = $mapping?->santri?->kelasPrimary?->kelas?->nama_kelas ?? '-';
|
$kelas = $mapping?->santri?->kelasPrimary?->kelas?->nama_kelas ?? '-';
|
||||||
|
|
||||||
// Cache kepulangan per tanggal agar tidak query berulang
|
// Cache kepulangan per tanggal
|
||||||
if (!isset($kepulanganCache[$tanggal])) {
|
if (!isset($kepulanganCache[$tanggal])) {
|
||||||
$kepulanganCache[$tanggal] = Kepulangan::where('status', 'Disetujui')
|
$kepulanganCache[$tanggal] = Kepulangan::where('status', 'Disetujui')
|
||||||
->where('tanggal_pulang', '<=', $tanggal)
|
->where('tanggal_pulang', '<=', $tanggal)
|
||||||
|
|
@ -150,10 +145,8 @@ public function preview(Request $request)
|
||||||
|
|
||||||
$rows = array_map(
|
$rows = array_map(
|
||||||
function ($row) use ($idSantri, $tanggal, $isPulang, $isiAlpa) {
|
function ($row) use ($idSantri, $tanggal, $isPulang, $isiAlpa) {
|
||||||
// Override jika santri sedang kepulangan
|
|
||||||
$statusFinal = $isPulang ? 'Pulang' : $row['status'];
|
$statusFinal = $isPulang ? 'Pulang' : $row['status'];
|
||||||
|
|
||||||
// Jangan isi Alpa jika opsi tidak aktif
|
|
||||||
if (!$isiAlpa && $statusFinal === 'Alpa' && !$row['matched']) {
|
if (!$isiAlpa && $statusFinal === 'Alpa' && !$row['matched']) {
|
||||||
$statusFinal = null;
|
$statusFinal = null;
|
||||||
}
|
}
|
||||||
|
|
@ -168,26 +161,18 @@ function ($row) use ($idSantri, $tanggal, $isPulang, $isiAlpa) {
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if ($rec) {
|
if ($rec) {
|
||||||
// getRawOriginal bypass Eloquent datetime cast
|
|
||||||
$rawWaktu = $rec->getRawOriginal('waktu_absen');
|
$rawWaktu = $rec->getRawOriginal('waktu_absen');
|
||||||
$existing = [
|
$existing = [
|
||||||
'status' => $rec->status,
|
'status' => $rec->status,
|
||||||
'waktu' => $rawWaktu
|
'waktu' => $rawWaktu ? substr($rawWaktu, 0, 5) : null,
|
||||||
? substr($rawWaktu, 0, 5) : null,
|
|
||||||
'metode' => $rec->metode_absen ?? 'Manual',
|
'metode' => $rec->metode_absen ?? 'Manual',
|
||||||
];
|
];
|
||||||
|
|
||||||
// PENTING: Jika mesin TIDAK punya scan untuk kegiatan
|
|
||||||
// ini (matched=false, status=Alpa), jangan override
|
|
||||||
// data manual yang sudah ada. "Tidak ada scan" ≠ "Alpa".
|
|
||||||
// Pertahankan data lama secara otomatis.
|
|
||||||
if (!$row['matched'] && $statusFinal === 'Alpa') {
|
if (!$row['matched'] && $statusFinal === 'Alpa') {
|
||||||
// Tidak override — pakai data existing
|
// Tidak ada scan = tidak override data manual
|
||||||
$statusFinal = $rec->status;
|
$statusFinal = $rec->status;
|
||||||
$isConflict = false;
|
$isConflict = false;
|
||||||
} else {
|
} else {
|
||||||
// Konflik hanya jika mesin MEMANG punya scan
|
|
||||||
// (matched=true) tapi statusnya beda dari manual
|
|
||||||
$isConflict = ($rec->metode_absen !== 'Import_Mesin')
|
$isConflict = ($rec->metode_absen !== 'Import_Mesin')
|
||||||
&& ($rec->status !== $statusFinal)
|
&& ($rec->status !== $statusFinal)
|
||||||
&& $statusFinal !== null;
|
&& $statusFinal !== null;
|
||||||
|
|
@ -222,15 +207,11 @@ function ($row) use ($idSantri, $tanggal, $isPulang, $isiAlpa) {
|
||||||
<=> [$b['tanggal'], $b['nama_web'] ?? $b['nama_mesin']]
|
<=> [$b['tanggal'], $b['nama_web'] ?? $b['nama_mesin']]
|
||||||
);
|
);
|
||||||
|
|
||||||
// ── Simpan ke session lalu REDIRECT ke showPreview ────
|
// ── Simpan ke session lalu redirect (PRG pattern) ─────
|
||||||
// Ini adalah PRG Pattern (Post-Redirect-Get):
|
|
||||||
// POST /import/preview → proses → session → redirect
|
|
||||||
// GET /import/preview → ambil dari session → tampilkan view
|
|
||||||
// Sehingga refresh halaman tidak error MethodNotAllowed
|
|
||||||
session([
|
session([
|
||||||
'eppos_hasil' => $hasilEnriched,
|
'eppos_hasil' => $hasilEnriched,
|
||||||
'tol_sebelum' => $tolSebelum,
|
'tol_sebelum' => $tolSebelum, // nilai dari form
|
||||||
'tol_sesudah' => $tolSesudah,
|
'tol_sesudah' => $tolSesudah, // nilai dari form
|
||||||
'isi_alpa' => $isiAlpa,
|
'isi_alpa' => $isiAlpa,
|
||||||
'conflict_strategy' => $conflictStrategy,
|
'conflict_strategy' => $conflictStrategy,
|
||||||
]);
|
]);
|
||||||
|
|
@ -245,12 +226,12 @@ public function showPreview()
|
||||||
{
|
{
|
||||||
$hasilEnriched = session('eppos_hasil');
|
$hasilEnriched = session('eppos_hasil');
|
||||||
|
|
||||||
// Jika session kosong (user buka langsung tanpa upload)
|
|
||||||
if (empty($hasilEnriched)) {
|
if (empty($hasilEnriched)) {
|
||||||
return redirect()->route('admin.mesin.import.index')
|
return redirect()->route('admin.mesin.import.index')
|
||||||
->with('error', 'Tidak ada data preview. Silakan upload file GLog terlebih dahulu.');
|
->with('error', 'Tidak ada data preview. Silakan upload file GLog terlebih dahulu.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ambil toleransi dari session (nilai yang dipakai saat matching)
|
||||||
$tolSebelum = session('tol_sebelum', 15);
|
$tolSebelum = session('tol_sebelum', 15);
|
||||||
$tolSesudah = session('tol_sesudah', 10);
|
$tolSesudah = session('tol_sesudah', 10);
|
||||||
$isiAlpa = session('isi_alpa', true);
|
$isiAlpa = session('isi_alpa', true);
|
||||||
|
|
@ -259,7 +240,6 @@ public function showPreview()
|
||||||
$tanggalList = array_unique(array_column($hasilEnriched, 'tanggal'));
|
$tanggalList = array_unique(array_column($hasilEnriched, 'tanggal'));
|
||||||
sort($tanggalList);
|
sort($tanggalList);
|
||||||
|
|
||||||
// Debug: kumpulkan info scan yang tidak cocok untuk ditampilkan
|
|
||||||
$debugScans = [];
|
$debugScans = [];
|
||||||
foreach ($hasilEnriched as $h) {
|
foreach ($hasilEnriched as $h) {
|
||||||
if (!empty($h['unmatched_scans'])) {
|
if (!empty($h['unmatched_scans'])) {
|
||||||
|
|
@ -330,15 +310,14 @@ public function store(Request $request)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alpa tanpa scan (matched=false) + sudah ada data existing
|
// Alpa tanpa scan + sudah ada data existing → pertahankan
|
||||||
// → pertahankan data lama, jangan simpan Alpa
|
if (!$row['matched'] && $row['status_final'] === 'Alpa'
|
||||||
if (!$row['matched'] && $row['status_final'] === 'Alpa' && !empty($row['existing'])) {
|
&& !empty($row['existing'])) {
|
||||||
$counters['skipped']++;
|
$counters['skipped']++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jika mesin tidak punya scan dan statusFinal = status existing
|
// Status sama dengan existing → tidak perlu update
|
||||||
// (artinya sudah diset ke status existing di preview), skip
|
|
||||||
if (!$row['matched'] && !empty($row['existing'])
|
if (!$row['matched'] && !empty($row['existing'])
|
||||||
&& $row['status_final'] === $row['existing']['status']) {
|
&& $row['status_final'] === $row['existing']['status']) {
|
||||||
$counters['skipped']++;
|
$counters['skipped']++;
|
||||||
|
|
@ -350,7 +329,7 @@ public function store(Request $request)
|
||||||
$isConflict = $row['is_conflict'] ?? false;
|
$isConflict = $row['is_conflict'] ?? false;
|
||||||
|
|
||||||
if (!$hasExisting) {
|
if (!$hasExisting) {
|
||||||
// Belum ada data → langsung buat
|
// Belum ada data → buat baru
|
||||||
AbsensiKegiatan::create([
|
AbsensiKegiatan::create([
|
||||||
'kegiatan_id' => $row['kegiatan_id'],
|
'kegiatan_id' => $row['kegiatan_id'],
|
||||||
'id_santri' => $dayData['id_santri'],
|
'id_santri' => $dayData['id_santri'],
|
||||||
|
|
@ -367,20 +346,18 @@ public function store(Request $request)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ada data existing tapi tidak konflik (status sama)
|
// Ada existing tapi tidak konflik → skip
|
||||||
// → skip, tidak perlu diubah
|
|
||||||
if (!$isConflict) {
|
if (!$isConflict) {
|
||||||
$counters['skipped']++;
|
$counters['skipped']++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ada konflik → lihat strategi bulk dulu, baru per-cell
|
// Ada konflik → cek strategi
|
||||||
$choice = ($bulkStrategy !== 'manual')
|
$choice = ($bulkStrategy !== 'manual')
|
||||||
? $bulkStrategy
|
? $bulkStrategy
|
||||||
: ($choices[$key] ?? null);
|
: ($choices[$key] ?? null);
|
||||||
|
|
||||||
if ($choice === 'mesin') {
|
if ($choice === 'mesin') {
|
||||||
// Admin pilih: pakai data mesin
|
|
||||||
AbsensiKegiatan::where('kegiatan_id', $row['kegiatan_id'])
|
AbsensiKegiatan::where('kegiatan_id', $row['kegiatan_id'])
|
||||||
->where('id_santri', $dayData['id_santri'])
|
->where('id_santri', $dayData['id_santri'])
|
||||||
->whereDate('tanggal', $dayData['tanggal'])
|
->whereDate('tanggal', $dayData['tanggal'])
|
||||||
|
|
@ -402,8 +379,7 @@ public function store(Request $request)
|
||||||
]);
|
]);
|
||||||
$counters['updated']++;
|
$counters['updated']++;
|
||||||
} else {
|
} else {
|
||||||
// Admin pilih: pertahankan data lama
|
// Pertahankan data lama
|
||||||
// Tidak melakukan apa-apa
|
|
||||||
$counters['kept']++;
|
$counters['kept']++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -428,7 +404,10 @@ public function store(Request $request)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hapus session setelah berhasil
|
// Hapus session setelah berhasil
|
||||||
session()->forget(['eppos_hasil', 'tol_sebelum', 'tol_sesudah', 'isi_alpa', 'conflict_strategy']);
|
session()->forget([
|
||||||
|
'eppos_hasil', 'tol_sebelum', 'tol_sesudah',
|
||||||
|
'isi_alpa', 'conflict_strategy',
|
||||||
|
]);
|
||||||
|
|
||||||
$msg = "Import selesai! "
|
$msg = "Import selesai! "
|
||||||
. "{$counters['created']} data baru tersimpan, "
|
. "{$counters['created']} data baru tersimpan, "
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
class KegiatanController extends Controller
|
class KegiatanController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Dashboard Kegiatan Hari Ini (ENHANCED)
|
* Dashboard Kegiatan Hari Ini
|
||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
|
|
@ -55,13 +55,72 @@ public function index(Request $request)
|
||||||
}
|
}
|
||||||
|
|
||||||
$kegiatanHariIni = $query->orderBy('waktu_mulai')->get();
|
$kegiatanHariIni = $query->orderBy('waktu_mulai')->get();
|
||||||
|
|
||||||
|
// ── Total santri aktif (dipakai sebagai denominator kegiatan umum) ──────
|
||||||
$totalSantriAktif = Santri::where('status', 'Aktif')->count();
|
$totalSantriAktif = Santri::where('status', 'Aktif')->count();
|
||||||
|
|
||||||
$kegiatanHariIni->each(function ($kegiatan) use ($totalSantriAktif, $selectedDate) {
|
// ── Pre-load semua santri aktif beserta kelas mereka (1 query) ────────────
|
||||||
$totalAbsensi = $kegiatan->absensis->count();
|
// Ini dipakai untuk menghitung "berapa santri yang seharusnya hadir" per kegiatan
|
||||||
$hadir = $kegiatan->absensis->where('status', 'Hadir')->count();
|
$allSantriAktif = Santri::where('status', 'Aktif')
|
||||||
$persenKehadiran = $totalAbsensi > 0 ? round(($hadir / $totalAbsensi) * 100) : 0;
|
->with('kelasSantri')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$kegiatanHariIni->each(function ($kegiatan) use ($totalSantriAktif, $selectedDate, $allSantriAktif) {
|
||||||
|
$absensis = $kegiatan->absensis; // sudah di-eager-load
|
||||||
|
$totalAbsensi = $absensis->count();
|
||||||
|
|
||||||
|
// ── FIX 1: Terlambat = hadir (masuk), bukan alpha ──────────────────
|
||||||
|
$hadirEfektif = $absensis->whereIn('status', ['Hadir', 'Terlambat'])->count();
|
||||||
|
$terlambat = $absensis->where('status', 'Terlambat')->count();
|
||||||
|
$izin = $absensis->where('status', 'Izin')->count();
|
||||||
|
$sakit = $absensis->where('status', 'Sakit')->count();
|
||||||
|
$alpa = $absensis->where('status', 'Alpa')->count();
|
||||||
|
|
||||||
|
// ── FIX 2: Denominator = jumlah santri yg seharusnya ikut kegiatan ini ──
|
||||||
|
if ($kegiatan->kelasKegiatan->isEmpty()) {
|
||||||
|
// Kegiatan Umum → semua santri aktif
|
||||||
|
$totalSantriKegiatan = $totalSantriAktif;
|
||||||
|
} else {
|
||||||
|
// Kegiatan Khusus → hitung santri yang terdaftar di kelas kegiatan
|
||||||
|
$kelasIds = $kegiatan->kelasKegiatan->pluck('id')->toArray();
|
||||||
|
$totalSantriKegiatan = $allSantriAktif->filter(function ($s) use ($kelasIds) {
|
||||||
|
return $s->kelasSantri->whereIn('id_kelas', $kelasIds)->count() > 0;
|
||||||
|
})->count();
|
||||||
|
// Fallback jika tidak ada santri terdaftar di kelas
|
||||||
|
if ($totalSantriKegiatan === 0) $totalSantriKegiatan = $totalSantriAktif;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── FIX 3: Persentase berdasarkan total santri kegiatan, bukan yg sudah absen ──
|
||||||
|
$persenKehadiran = $totalSantriKegiatan > 0
|
||||||
|
? round(($hadirEfektif / $totalSantriKegiatan) * 100)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
// ── FIX 4: Info per kelas — berapa kelas sudah/belum input ───────────
|
||||||
|
$infoPerKelas = collect();
|
||||||
|
if (!$kegiatan->kelasKegiatan->isEmpty()) {
|
||||||
|
$absensiByKelas = $absensis->groupBy(function ($ab) {
|
||||||
|
// group berdasarkan kelas santri yg hadir (ambil kelas pertama yg sesuai)
|
||||||
|
return $ab->santri->kelas_name ?? 'Tanpa Kelas';
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach ($kegiatan->kelasKegiatan as $kls) {
|
||||||
|
$kelasId = $kls->id;
|
||||||
|
$santriDiKelas = $allSantriAktif->filter(function ($s) use ($kelasId) {
|
||||||
|
return $s->kelasSantri->where('id_kelas', $kelasId)->count() > 0;
|
||||||
|
})->count();
|
||||||
|
|
||||||
|
// Berapa dari kelas ini yang sudah diinput absensi hari ini
|
||||||
|
// Cek dari absensis: santri yg ada di kelas ini
|
||||||
|
$sudahInputKelas = 0; // akan diisi di blade via data yg dikirim
|
||||||
|
|
||||||
|
$infoPerKelas->push([
|
||||||
|
'nama' => $kls->nama_kelas,
|
||||||
|
'total_santri' => $santriDiKelas,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Status kegiatan (belum / berlangsung / selesai) ─────────────────
|
||||||
$now = Carbon::now();
|
$now = Carbon::now();
|
||||||
$waktuMulaiStr = is_string($kegiatan->waktu_mulai) ? $kegiatan->waktu_mulai : $kegiatan->waktu_mulai->format('H:i');
|
$waktuMulaiStr = is_string($kegiatan->waktu_mulai) ? $kegiatan->waktu_mulai : $kegiatan->waktu_mulai->format('H:i');
|
||||||
$waktuSelesaiStr = is_string($kegiatan->waktu_selesai) ? $kegiatan->waktu_selesai : $kegiatan->waktu_selesai->format('H:i');
|
$waktuSelesaiStr = is_string($kegiatan->waktu_selesai) ? $kegiatan->waktu_selesai : $kegiatan->waktu_selesai->format('H:i');
|
||||||
|
|
@ -78,10 +137,19 @@ public function index(Request $request)
|
||||||
$status = 'selesai';
|
$status = 'selesai';
|
||||||
}
|
}
|
||||||
|
|
||||||
$kegiatan->total_hadir = $hadir;
|
// Set semua property ke object kegiatan
|
||||||
$kegiatan->total_absensi = $totalAbsensi;
|
$kegiatan->total_hadir = $hadirEfektif; // hadir + terlambat
|
||||||
|
$kegiatan->total_hadir_murni = $absensis->where('status', 'Hadir')->count();
|
||||||
|
$kegiatan->total_terlambat = $terlambat;
|
||||||
|
$kegiatan->total_izin = $izin;
|
||||||
|
$kegiatan->total_sakit = $sakit;
|
||||||
|
$kegiatan->total_alpa = $alpa;
|
||||||
|
$kegiatan->total_absensi = $totalAbsensi; // sudah diinput
|
||||||
|
$kegiatan->total_santri_kegiatan = $totalSantriKegiatan; // seharusnya hadir
|
||||||
|
$kegiatan->belum_absen = max(0, $totalSantriKegiatan - $totalAbsensi);
|
||||||
$kegiatan->persen_kehadiran = $persenKehadiran;
|
$kegiatan->persen_kehadiran = $persenKehadiran;
|
||||||
$kegiatan->status_kegiatan = $status;
|
$kegiatan->status_kegiatan = $status;
|
||||||
|
$kegiatan->info_per_kelas = $infoPerKelas;
|
||||||
});
|
});
|
||||||
|
|
||||||
$totalKegiatanHariIni = $kegiatanHariIni->count();
|
$totalKegiatanHariIni = $kegiatanHariIni->count();
|
||||||
|
|
@ -102,7 +170,9 @@ public function index(Request $request)
|
||||||
$abs = AbsensiKegiatan::where('kegiatan_id', $kg->kegiatan_id)
|
$abs = AbsensiKegiatan::where('kegiatan_id', $kg->kegiatan_id)
|
||||||
->whereDate('tanggal', $lastWeekDate->format('Y-m-d'))->get();
|
->whereDate('tanggal', $lastWeekDate->format('Y-m-d'))->get();
|
||||||
if ($abs->count() > 0) {
|
if ($abs->count() > 0) {
|
||||||
$totalPersen += ($abs->where('status', 'Hadir')->count() / $abs->count()) * 100;
|
// FIX: hitung hadir + terlambat, bukan hadir saja
|
||||||
|
$hadirCount = $abs->whereIn('status', ['Hadir', 'Terlambat'])->count();
|
||||||
|
$totalPersen += ($hadirCount / $abs->count()) * 100;
|
||||||
$count++;
|
$count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -139,9 +209,10 @@ private function generateInsights($kegiatanHariIni, $totalSantriAktif, $selected
|
||||||
foreach ($kegiatanHariIni as $kegiatan) {
|
foreach ($kegiatanHariIni as $kegiatan) {
|
||||||
if ($kegiatan->total_absensi > 0 && $kegiatan->persen_kehadiran < 70) {
|
if ($kegiatan->total_absensi > 0 && $kegiatan->persen_kehadiran < 70) {
|
||||||
$insights[] = [
|
$insights[] = [
|
||||||
'type' => 'warning', 'icon' => 'exclamation-triangle',
|
'type' => 'warning',
|
||||||
|
'icon' => 'exclamation-triangle',
|
||||||
'message' => "Kegiatan {$kegiatan->nama_kegiatan} kehadiran rendah ({$kegiatan->persen_kehadiran}%)",
|
'message' => "Kegiatan {$kegiatan->nama_kegiatan} kehadiran rendah ({$kegiatan->persen_kehadiran}%)",
|
||||||
'detail' => "{$kegiatan->total_hadir} dari {$kegiatan->total_absensi} santri hadir",
|
'detail' => "{$kegiatan->total_hadir} hadir dari {$kegiatan->total_santri_kegiatan} santri",
|
||||||
'action_url' => route('admin.absensi-kegiatan.input', $kegiatan->kegiatan_id) . '?tanggal=' . $selectedDate->format('Y-m-d'),
|
'action_url' => route('admin.absensi-kegiatan.input', $kegiatan->kegiatan_id) . '?tanggal=' . $selectedDate->format('Y-m-d'),
|
||||||
'action_text' => 'Input Absensi',
|
'action_text' => 'Input Absensi',
|
||||||
];
|
];
|
||||||
|
|
@ -151,9 +222,12 @@ private function generateInsights($kegiatanHariIni, $totalSantriAktif, $selected
|
||||||
foreach ($kegiatanHariIni as $kegiatan) {
|
foreach ($kegiatanHariIni as $kegiatan) {
|
||||||
if ($kegiatan->persen_kehadiran == 100 && $kegiatan->total_absensi > 0) {
|
if ($kegiatan->persen_kehadiran == 100 && $kegiatan->total_absensi > 0) {
|
||||||
$insights[] = [
|
$insights[] = [
|
||||||
'type' => 'success', 'icon' => 'check-circle',
|
'type' => 'success',
|
||||||
|
'icon' => 'check-circle',
|
||||||
'message' => "Perfect! {$kegiatan->nama_kegiatan} kehadiran 100%",
|
'message' => "Perfect! {$kegiatan->nama_kegiatan} kehadiran 100%",
|
||||||
'detail' => 'Semua santri hadir', 'action_url' => null, 'action_text' => null,
|
'detail' => "Semua {$kegiatan->total_santri_kegiatan} santri hadir",
|
||||||
|
'action_url' => null,
|
||||||
|
'action_text' => null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -161,9 +235,10 @@ private function generateInsights($kegiatanHariIni, $totalSantriAktif, $selected
|
||||||
$kegiatanLive = $kegiatanHariIni->where('status_kegiatan', 'berlangsung')->first();
|
$kegiatanLive = $kegiatanHariIni->where('status_kegiatan', 'berlangsung')->first();
|
||||||
if ($kegiatanLive) {
|
if ($kegiatanLive) {
|
||||||
$insights[] = [
|
$insights[] = [
|
||||||
'type' => 'info', 'icon' => 'clock',
|
'type' => 'info',
|
||||||
|
'icon' => 'clock',
|
||||||
'message' => "Kegiatan {$kegiatanLive->nama_kegiatan} sedang berlangsung",
|
'message' => "Kegiatan {$kegiatanLive->nama_kegiatan} sedang berlangsung",
|
||||||
'detail' => "Progress absensi: {$kegiatanLive->persen_kehadiran}%",
|
'detail' => "Progress absensi: {$kegiatanLive->total_absensi}/{$kegiatanLive->total_santri_kegiatan} santri ({$kegiatanLive->persen_kehadiran}%)",
|
||||||
'action_url' => route('admin.absensi-kegiatan.input', $kegiatanLive->kegiatan_id) . '?tanggal=' . $selectedDate->format('Y-m-d'),
|
'action_url' => route('admin.absensi-kegiatan.input', $kegiatanLive->kegiatan_id) . '?tanggal=' . $selectedDate->format('Y-m-d'),
|
||||||
'action_text' => 'Input Absensi Sekarang',
|
'action_text' => 'Input Absensi Sekarang',
|
||||||
];
|
];
|
||||||
|
|
@ -173,9 +248,10 @@ private function generateInsights($kegiatanHariIni, $totalSantriAktif, $selected
|
||||||
if ($kegiatan->status_kegiatan == 'selesai' && $kegiatan->total_absensi == 0) {
|
if ($kegiatan->status_kegiatan == 'selesai' && $kegiatan->total_absensi == 0) {
|
||||||
$waktuSelesai = is_string($kegiatan->waktu_selesai) ? $kegiatan->waktu_selesai : $kegiatan->waktu_selesai->format('H:i');
|
$waktuSelesai = is_string($kegiatan->waktu_selesai) ? $kegiatan->waktu_selesai : $kegiatan->waktu_selesai->format('H:i');
|
||||||
$insights[] = [
|
$insights[] = [
|
||||||
'type' => 'danger', 'icon' => 'exclamation-circle',
|
'type' => 'danger',
|
||||||
|
'icon' => 'exclamation-circle',
|
||||||
'message' => "Kegiatan {$kegiatan->nama_kegiatan} belum input absensi",
|
'message' => "Kegiatan {$kegiatan->nama_kegiatan} belum input absensi",
|
||||||
'detail' => "Sudah selesai pukul {$waktuSelesai}",
|
'detail' => "Sudah selesai pukul {$waktuSelesai}, {$kegiatan->total_santri_kegiatan} santri belum diinput",
|
||||||
'action_url' => route('admin.absensi-kegiatan.input', $kegiatan->kegiatan_id) . '?tanggal=' . $selectedDate->format('Y-m-d'),
|
'action_url' => route('admin.absensi-kegiatan.input', $kegiatan->kegiatan_id) . '?tanggal=' . $selectedDate->format('Y-m-d'),
|
||||||
'action_text' => 'Input Sekarang',
|
'action_text' => 'Input Sekarang',
|
||||||
];
|
];
|
||||||
|
|
@ -187,6 +263,7 @@ private function generateInsights($kegiatanHariIni, $totalSantriAktif, $selected
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate Heatmap Data (30 hari terakhir)
|
* Generate Heatmap Data (30 hari terakhir)
|
||||||
|
* FIX: hitung hadir + terlambat, bukan hadir saja
|
||||||
*/
|
*/
|
||||||
private function generateHeatmapData()
|
private function generateHeatmapData()
|
||||||
{
|
{
|
||||||
|
|
@ -199,7 +276,7 @@ private function generateHeatmapData()
|
||||||
$absensi = AbsensiKegiatan::whereDate('tanggal', $dateStr)->get();
|
$absensi = AbsensiKegiatan::whereDate('tanggal', $dateStr)->get();
|
||||||
|
|
||||||
$percentage = $absensi->count() > 0
|
$percentage = $absensi->count() > 0
|
||||||
? round(($absensi->where('status', 'Hadir')->count() / $absensi->count()) * 100, 1)
|
? round(($absensi->whereIn('status', ['Hadir', 'Terlambat'])->count() / $absensi->count()) * 100, 1)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
$heatmapData[] = [
|
$heatmapData[] = [
|
||||||
|
|
@ -225,6 +302,7 @@ private function getHeatmapLevel($percentage)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AJAX: Get Detail Kegiatan untuk Modal
|
* AJAX: Get Detail Kegiatan untuk Modal
|
||||||
|
* FIX: persen_hadir juga ikut hitung Terlambat
|
||||||
*/
|
*/
|
||||||
public function getDetailModal($kegiatan_id, Request $request)
|
public function getDetailModal($kegiatan_id, Request $request)
|
||||||
{
|
{
|
||||||
|
|
@ -239,7 +317,7 @@ public function getDetailModal($kegiatan_id, Request $request)
|
||||||
|
|
||||||
$isUmum = $kegiatan->isForAllClasses();
|
$isUmum = $kegiatan->isForAllClasses();
|
||||||
|
|
||||||
// Grup absensi per kelas kegiatan (khusus) atau kelas_name (umum)
|
// Grup absensi per kelas
|
||||||
if ($isUmum) {
|
if ($isUmum) {
|
||||||
$absensiPerKelas = $absensis->groupBy(fn($item) => $item->santri->kelas_name ?? 'Belum Ada Kelas')->sortKeys();
|
$absensiPerKelas = $absensis->groupBy(fn($item) => $item->santri->kelas_name ?? 'Belum Ada Kelas')->sortKeys();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -248,33 +326,75 @@ public function getDetailModal($kegiatan_id, Request $request)
|
||||||
$filtered = $absensis->filter(fn($item) => $item->santri->kelasSantri->contains('id_kelas', $kelas->id));
|
$filtered = $absensis->filter(fn($item) => $item->santri->kelasSantri->contains('id_kelas', $kelas->id));
|
||||||
if ($filtered->count() > 0) $absensiPerKelas[$kelas->nama_kelas] = $filtered;
|
if ($filtered->count() > 0) $absensiPerKelas[$kelas->nama_kelas] = $filtered;
|
||||||
}
|
}
|
||||||
// Sisanya yang tidak cocok kelas manapun
|
|
||||||
$placedIds = $absensiPerKelas->flatten()->pluck('id')->toArray();
|
$placedIds = $absensiPerKelas->flatten()->pluck('id')->toArray();
|
||||||
$lainnya = $absensis->filter(fn($item) => !$absensiPerKelas->flatten()->contains('id', $item->id));
|
$lainnya = $absensis->filter(fn($item) => !in_array($item->id, $placedIds));
|
||||||
if ($lainnya->count() > 0) $absensiPerKelas['Kelas Lain'] = $lainnya;
|
if ($lainnya->count() > 0) $absensiPerKelas['Kelas Lain'] = $lainnya;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIX: hadir efektif = Hadir + Terlambat
|
||||||
|
$hadirEfektif = $absensis->whereIn('status', ['Hadir', 'Terlambat'])->count();
|
||||||
|
|
||||||
|
// Total santri yang seharusnya hadir
|
||||||
|
if ($isUmum) {
|
||||||
|
$totalSantri = Santri::where('status', 'Aktif')->count();
|
||||||
|
} else {
|
||||||
|
$kelasIds = $kegiatan->kelasKegiatan->pluck('id')->toArray();
|
||||||
|
$totalSantri = Santri::where('status', 'Aktif')
|
||||||
|
->whereHas('kelasSantri', fn($q) => $q->whereIn('id_kelas', $kelasIds))
|
||||||
|
->count();
|
||||||
|
if ($totalSantri === 0) $totalSantri = Santri::where('status', 'Aktif')->count();
|
||||||
|
}
|
||||||
|
|
||||||
$stats = [
|
$stats = [
|
||||||
'hadir' => $absensis->where('status', 'Hadir')->count(),
|
'hadir' => $absensis->where('status', 'Hadir')->count(),
|
||||||
'terlambat' => $absensis->where('status', 'Terlambat')->count(),
|
'terlambat' => $absensis->where('status', 'Terlambat')->count(),
|
||||||
|
'hadir_efektif'=> $hadirEfektif, // hadir + terlambat
|
||||||
'izin' => $absensis->where('status', 'Izin')->count(),
|
'izin' => $absensis->where('status', 'Izin')->count(),
|
||||||
'sakit' => $absensis->where('status', 'Sakit')->count(),
|
'sakit' => $absensis->where('status', 'Sakit')->count(),
|
||||||
'alpa' => $absensis->where('status', 'Alpa')->count(),
|
'alpa' => $absensis->where('status', 'Alpa')->count(),
|
||||||
];
|
];
|
||||||
$totalSantri = Santri::where('status', 'Aktif')->count();
|
|
||||||
|
|
||||||
$stats['belum_absen'] = max(0, $totalSantri - $absensis->count());
|
$stats['belum_absen'] = max(0, $totalSantri - $absensis->count());
|
||||||
$stats['sudah_absen'] = $absensis->count();
|
$stats['sudah_absen'] = $absensis->count();
|
||||||
$stats['total'] = $totalSantri;
|
$stats['total'] = $totalSantri;
|
||||||
$stats['persen_hadir'] = $totalSantri > 0 ? round(($stats['hadir'] / $totalSantri) * 100, 1) : 0;
|
// FIX: persen hadir pakai hadir_efektif bukan hadir saja
|
||||||
|
$stats['persen_hadir'] = $totalSantri > 0
|
||||||
|
? round(($hadirEfektif / $totalSantri) * 100, 1)
|
||||||
|
: 0;
|
||||||
|
|
||||||
// Daftar santri belum absen, di-group per kelas kegiatan (khusus) atau kelasPrimary (umum)
|
// ── Info per kelas untuk modal: sudah/belum input ───────────────────────
|
||||||
|
$infoKelasModal = collect();
|
||||||
|
if (!$isUmum) {
|
||||||
|
$allSantriAktif = Santri::where('status', 'Aktif')->with('kelasSantri')->get();
|
||||||
|
foreach ($kegiatan->kelasKegiatan as $kls) {
|
||||||
|
$kelasId = $kls->id;
|
||||||
|
$santriDiKelas = $allSantriAktif->filter(fn($s) => $s->kelasSantri->where('id_kelas', $kelasId)->count() > 0)->count();
|
||||||
|
$sudahInputKelas = $absensis->filter(fn($ab) =>
|
||||||
|
$ab->santri->kelasSantri->contains('id_kelas', $kelasId)
|
||||||
|
)->count();
|
||||||
|
$infoKelasModal->push([
|
||||||
|
'nama' => $kls->nama_kelas,
|
||||||
|
'total_santri' => $santriDiKelas,
|
||||||
|
'sudah_input' => $sudahInputKelas,
|
||||||
|
'belum_input' => max(0, $santriDiKelas - $sudahInputKelas),
|
||||||
|
'sudah_semua' => $sudahInputKelas >= $santriDiKelas && $santriDiKelas > 0,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Daftar santri belum absen
|
||||||
$idSantriSudahAbsen = $absensis->pluck('id_santri')->toArray();
|
$idSantriSudahAbsen = $absensis->pluck('id_santri')->toArray();
|
||||||
$allBelumAbsen = Santri::where('status', 'Aktif')
|
$belumQuery = Santri::where('status', 'Aktif')
|
||||||
->whereNotIn('id_santri', $idSantriSudahAbsen)
|
->whereNotIn('id_santri', $idSantriSudahAbsen)
|
||||||
->with(['kelasSantri.kelas', 'kelasPrimary.kelas'])
|
->with(['kelasSantri.kelas', 'kelasPrimary.kelas'])
|
||||||
->orderBy('nama_lengkap')
|
->orderBy('nama_lengkap');
|
||||||
->get();
|
|
||||||
|
if (!$isUmum) {
|
||||||
|
$kelasIds = $kegiatan->kelasKegiatan->pluck('id')->toArray();
|
||||||
|
$belumQuery->whereHas('kelasSantri', fn($q) => $q->whereIn('id_kelas', $kelasIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
$allBelumAbsen = $belumQuery->get();
|
||||||
|
|
||||||
if ($isUmum) {
|
if ($isUmum) {
|
||||||
$santriBelumAbsenPerKelas = $allBelumAbsen->groupBy(function($s) {
|
$santriBelumAbsenPerKelas = $allBelumAbsen->groupBy(function($s) {
|
||||||
|
|
@ -295,9 +415,12 @@ public function getDetailModal($kegiatan_id, Request $request)
|
||||||
if ($lainnyaBelum->count() > 0) $santriBelumAbsenPerKelas['Kelas Lain'] = $lainnyaBelum;
|
if ($lainnyaBelum->count() > 0) $santriBelumAbsenPerKelas['Kelas Lain'] = $lainnyaBelum;
|
||||||
}
|
}
|
||||||
|
|
||||||
$santriBelumAbsen = $allBelumAbsen; // kept for count reference
|
$santriBelumAbsen = $allBelumAbsen;
|
||||||
|
|
||||||
return view('admin.kegiatan.data.partials.detail-modal', compact('kegiatan', 'absensis', 'absensiPerKelas', 'stats', 'tanggal', 'santriBelumAbsen', 'santriBelumAbsenPerKelas'));
|
return view('admin.kegiatan.data.partials.detail-modal', compact(
|
||||||
|
'kegiatan', 'absensis', 'absensiPerKelas', 'stats', 'tanggal',
|
||||||
|
'santriBelumAbsen', 'santriBelumAbsenPerKelas', 'infoKelasModal'
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -421,12 +544,6 @@ public function edit(Kegiatan $kegiatan)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update kegiatan — smart multi-hari
|
* Update kegiatan — smart multi-hari
|
||||||
*
|
|
||||||
* Logika:
|
|
||||||
* - Cari semua kegiatan "saudara" = nama_kegiatan + kategori_id LAMA yang sama
|
|
||||||
* - Hari yang DIPILIH & sudah ada di saudara → UPDATE kegiatan saudara tsb
|
|
||||||
* - Hari yang DIPILIH tapi belum ada di saudara → BUAT kegiatan baru
|
|
||||||
* - Hari yang TIDAK DIPILIH → tidak disentuh sama sekali
|
|
||||||
*/
|
*/
|
||||||
public function update(Request $request, Kegiatan $kegiatan)
|
public function update(Request $request, Kegiatan $kegiatan)
|
||||||
{
|
{
|
||||||
|
|
@ -451,28 +568,23 @@ public function update(Request $request, Kegiatan $kegiatan)
|
||||||
|
|
||||||
$hariDipilih = $validated['hari'];
|
$hariDipilih = $validated['hari'];
|
||||||
$kelasIds = $request->input('kelas_ids', []);
|
$kelasIds = $request->input('kelas_ids', []);
|
||||||
|
|
||||||
// Data dasar tanpa hari & kelas_ids
|
|
||||||
$baseData = collect($validated)->except(['hari', 'kelas_ids'])->toArray();
|
$baseData = collect($validated)->except(['hari', 'kelas_ids'])->toArray();
|
||||||
|
|
||||||
// Cari semua saudara berdasarkan nama + kategori LAMA (sebelum diubah)
|
|
||||||
$saudara = Kegiatan::where('nama_kegiatan', $kegiatan->nama_kegiatan)
|
$saudara = Kegiatan::where('nama_kegiatan', $kegiatan->nama_kegiatan)
|
||||||
->where('kategori_id', $kegiatan->kategori_id)
|
->where('kategori_id', $kegiatan->kategori_id)
|
||||||
->get()
|
->get()
|
||||||
->keyBy('hari'); // ['Senin' => obj, 'Rabu' => obj, ...]
|
->keyBy('hari');
|
||||||
|
|
||||||
$updatedCount = 0;
|
$updatedCount = 0;
|
||||||
$createdCount = 0;
|
$createdCount = 0;
|
||||||
|
|
||||||
foreach ($hariDipilih as $hari) {
|
foreach ($hariDipilih as $hari) {
|
||||||
if ($saudara->has($hari)) {
|
if ($saudara->has($hari)) {
|
||||||
// Kegiatan di hari ini sudah ada → update
|
|
||||||
$target = $saudara->get($hari);
|
$target = $saudara->get($hari);
|
||||||
$target->update(array_merge($baseData, ['hari' => $hari]));
|
$target->update(array_merge($baseData, ['hari' => $hari]));
|
||||||
$target->assignKelas($kelasIds);
|
$target->assignKelas($kelasIds);
|
||||||
$updatedCount++;
|
$updatedCount++;
|
||||||
} else {
|
} else {
|
||||||
// Belum ada kegiatan di hari ini → buat baru
|
|
||||||
$newKg = Kegiatan::create(array_merge($baseData, ['hari' => $hari]));
|
$newKg = Kegiatan::create(array_merge($baseData, ['hari' => $hari]));
|
||||||
$newKg->assignKelas($kelasIds);
|
$newKg->assignKelas($kelasIds);
|
||||||
$createdCount++;
|
$createdCount++;
|
||||||
|
|
|
||||||
|
|
@ -290,6 +290,10 @@ public function kenaikanProcess(Request $request)
|
||||||
$kelasAsal = Kelas::findOrFail($request->id_kelas_asal);
|
$kelasAsal = Kelas::findOrFail($request->id_kelas_asal);
|
||||||
$kelasTujuan = Kelas::findOrFail($request->id_kelas_tujuan);
|
$kelasTujuan = Kelas::findOrFail($request->id_kelas_tujuan);
|
||||||
|
|
||||||
|
// Ambil semua id kelas yang satu kelompok dengan kelas asal
|
||||||
|
$kelasSeKelompok = Kelas::where('id_kelompok', $kelasAsal->id_kelompok)
|
||||||
|
->pluck('id');
|
||||||
|
|
||||||
$santriIds = Santri::whereHas('kelasSantri', fn($q) => $q->where('id_kelas', $request->id_kelas_asal))
|
$santriIds = Santri::whereHas('kelasSantri', fn($q) => $q->where('id_kelas', $request->id_kelas_asal))
|
||||||
->where('status', 'Aktif')
|
->where('status', 'Aktif')
|
||||||
->pluck('id_santri');
|
->pluck('id_santri');
|
||||||
|
|
@ -304,24 +308,23 @@ public function kenaikanProcess(Request $request)
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
try {
|
try {
|
||||||
foreach ($santriIds as $idSantri) {
|
foreach ($santriIds as $idSantri) {
|
||||||
$record = SantriKelas::where('id_santri', $idSantri)
|
// Ambil record kelas asal
|
||||||
|
$recordAsal = SantriKelas::where('id_santri', $idSantri)
|
||||||
->where('id_kelas', $kelasAsal->id)
|
->where('id_kelas', $kelasAsal->id)
|
||||||
->orderBy('tahun_ajaran', 'desc')
|
->orderBy('tahun_ajaran', 'desc')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (!$record) continue;
|
if (!$recordAsal) continue;
|
||||||
|
|
||||||
// Cek duplikasi: jika sudah ada di kelas tujuan + tahun_ajaran sama, hapus record lama
|
// Hapus record lain milik santri ini yang satu kelompok dengan kelas asal
|
||||||
$sudahAda = SantriKelas::where('id_santri', $idSantri)
|
// (kecuali record asal itu sendiri, karena akan kita update)
|
||||||
->where('id_kelas', $kelasTujuan->id)
|
SantriKelas::where('id_santri', $idSantri)
|
||||||
->where('tahun_ajaran', $record->tahun_ajaran)
|
->whereIn('id_kelas', $kelasSeKelompok)
|
||||||
->exists();
|
->where('id', '!=', $recordAsal->id)
|
||||||
|
->delete();
|
||||||
|
|
||||||
if ($sudahAda) {
|
// Pindahkan record kelas asal ke kelas tujuan
|
||||||
$record->delete();
|
$recordAsal->update(['id_kelas' => $kelasTujuan->id]);
|
||||||
} else {
|
|
||||||
$record->update(['id_kelas' => $kelasTujuan->id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$processed++;
|
$processed++;
|
||||||
}
|
}
|
||||||
|
|
@ -353,29 +356,32 @@ public function kenaikanProcessSelected(Request $request)
|
||||||
$kelasAsal = Kelas::findOrFail($request->id_kelas_asal);
|
$kelasAsal = Kelas::findOrFail($request->id_kelas_asal);
|
||||||
$kelasTujuan = Kelas::findOrFail($request->id_kelas_tujuan);
|
$kelasTujuan = Kelas::findOrFail($request->id_kelas_tujuan);
|
||||||
|
|
||||||
|
// Ambil semua id kelas yang satu kelompok dengan kelas asal
|
||||||
|
$kelasSeKelompok = Kelas::where('id_kelompok', $kelasAsal->id_kelompok)
|
||||||
|
->pluck('id');
|
||||||
|
|
||||||
$processed = 0;
|
$processed = 0;
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
try {
|
try {
|
||||||
foreach ($request->santri_ids as $idSantri) {
|
foreach ($request->santri_ids as $idSantri) {
|
||||||
$record = SantriKelas::where('id_santri', $idSantri)
|
// Ambil record kelas asal
|
||||||
|
$recordAsal = SantriKelas::where('id_santri', $idSantri)
|
||||||
->where('id_kelas', $kelasAsal->id)
|
->where('id_kelas', $kelasAsal->id)
|
||||||
->orderBy('tahun_ajaran', 'desc')
|
->orderBy('tahun_ajaran', 'desc')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (!$record) continue;
|
if (!$recordAsal) continue;
|
||||||
|
|
||||||
// Cek duplikasi: jika sudah ada di kelas tujuan + tahun_ajaran sama, hapus record lama
|
// Hapus record lain milik santri ini yang satu kelompok dengan kelas asal
|
||||||
$sudahAda = SantriKelas::where('id_santri', $idSantri)
|
// (kecuali record asal itu sendiri, karena akan kita update)
|
||||||
->where('id_kelas', $kelasTujuan->id)
|
SantriKelas::where('id_santri', $idSantri)
|
||||||
->where('tahun_ajaran', $record->tahun_ajaran)
|
->whereIn('id_kelas', $kelasSeKelompok)
|
||||||
->exists();
|
->where('id', '!=', $recordAsal->id)
|
||||||
|
->delete();
|
||||||
|
|
||||||
if ($sudahAda) {
|
// Pindahkan record kelas asal ke kelas tujuan
|
||||||
$record->delete();
|
$recordAsal->update(['id_kelas' => $kelasTujuan->id]);
|
||||||
} else {
|
|
||||||
$record->update(['id_kelas' => $kelasTujuan->id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$processed++;
|
$processed++;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -8,282 +8,321 @@
|
||||||
use App\Models\KategoriKegiatan;
|
use App\Models\KategoriKegiatan;
|
||||||
use App\Models\Santri;
|
use App\Models\Santri;
|
||||||
use App\Models\Kelas;
|
use App\Models\Kelas;
|
||||||
use App\Models\KelompokKelas;
|
|
||||||
use App\Models\SantriKelas;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
class RiwayatKegiatanController extends Controller
|
class RiwayatKegiatanController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Halaman utama riwayat kegiatan & absensi
|
* Halaman utama riwayat — default: HARI INI
|
||||||
|
*
|
||||||
|
* Mode hari_ini → flat list kegiatan (paginated cards)
|
||||||
|
* Mode minggu_ini / custom → grouped by actual date, tiap tanggal = 1 tabel
|
||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
// Query untuk mendapatkan kegiatan dengan statistik absensi
|
$hariMap = [
|
||||||
$query = Kegiatan::with(['kategori', 'kelasKegiatan.kelompok'])
|
'Monday' => 'Senin', 'Tuesday' => 'Selasa', 'Wednesday' => 'Rabu',
|
||||||
->withCount(['absensis as total_absensi'])
|
'Thursday' => 'Kamis', 'Friday' => 'Jumat', 'Saturday' => 'Sabtu',
|
||||||
->withCount(['absensis as hadir' => function($q) {
|
'Sunday' => 'Ahad',
|
||||||
$q->where('status', 'Hadir');
|
|
||||||
}])
|
|
||||||
->withCount(['absensis as izin' => function($q) {
|
|
||||||
$q->where('status', 'Izin');
|
|
||||||
}])
|
|
||||||
->withCount(['absensis as sakit' => function($q) {
|
|
||||||
$q->where('status', 'Sakit');
|
|
||||||
}])
|
|
||||||
->withCount(['absensis as alpa' => function($q) {
|
|
||||||
$q->where('status', 'Alpa');
|
|
||||||
}]);
|
|
||||||
|
|
||||||
// Filter Kategori
|
|
||||||
if ($request->filled('kategori_id')) {
|
|
||||||
$query->where('kategori_id', $request->kategori_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter Tanggal untuk absensi
|
|
||||||
if ($request->filled('tanggal_dari') || $request->filled('tanggal_sampai') || $request->filled('bulan')) {
|
|
||||||
$query->whereHas('absensis', function($q) use ($request) {
|
|
||||||
if ($request->filled('tanggal_dari')) {
|
|
||||||
$q->whereDate('tanggal', '>=', $request->tanggal_dari);
|
|
||||||
}
|
|
||||||
if ($request->filled('tanggal_sampai')) {
|
|
||||||
$q->whereDate('tanggal', '<=', $request->tanggal_sampai);
|
|
||||||
}
|
|
||||||
if ($request->filled('bulan')) {
|
|
||||||
$q->whereMonth('tanggal', date('m', strtotime($request->bulan)))
|
|
||||||
->whereYear('tanggal', date('Y', strtotime($request->bulan)));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$kegiatans = $query->orderBy('nama_kegiatan')
|
|
||||||
->paginate(15)
|
|
||||||
->appends(request()->query());
|
|
||||||
|
|
||||||
// Data untuk filter
|
|
||||||
$kategoris = KategoriKegiatan::select('kategori_id', 'nama_kategori')->get();
|
|
||||||
|
|
||||||
return view('admin.kegiatan.riwayat.index', compact('kegiatans', 'kategoris'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Riwayat kehadiran per santri (detail)
|
|
||||||
*/
|
|
||||||
public function detailSantri($id_santri)
|
|
||||||
{
|
|
||||||
$santri = Santri::where('id_santri', $id_santri)->firstOrFail();
|
|
||||||
|
|
||||||
// Statistik per santri
|
|
||||||
$stats = AbsensiKegiatan::where('id_santri', $id_santri)
|
|
||||||
->select('status', DB::raw('count(*) as total'))
|
|
||||||
->groupBy('status')
|
|
||||||
->pluck('total', 'status')
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
// Total kehadiran per kategori
|
|
||||||
$statsByKategori = AbsensiKegiatan::where('id_santri', $id_santri)
|
|
||||||
->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();
|
|
||||||
|
|
||||||
// Riwayat 30 hari terakhir
|
|
||||||
$riwayat30Hari = AbsensiKegiatan::where('id_santri', $id_santri)
|
|
||||||
->whereDate('tanggal', '>=', now()->subDays(30))
|
|
||||||
->select(
|
|
||||||
DB::raw('DATE(tanggal) as tanggal'),
|
|
||||||
DB::raw('SUM(CASE WHEN status = "Hadir" THEN 1 ELSE 0 END) as hadir'),
|
|
||||||
DB::raw('COUNT(*) as total')
|
|
||||||
)
|
|
||||||
->groupBy('tanggal')
|
|
||||||
->orderBy('tanggal', 'asc')
|
|
||||||
->get();
|
|
||||||
|
|
||||||
// Riwayat lengkap
|
|
||||||
$riwayats = AbsensiKegiatan::with('kegiatan.kategori')
|
|
||||||
->where('id_santri', $id_santri)
|
|
||||||
->orderBy('tanggal', 'desc')
|
|
||||||
->paginate(15);
|
|
||||||
|
|
||||||
// Kehadiran per kelas santri
|
|
||||||
$statsByKelasSantri = $santri->kelasSantri()
|
|
||||||
->with('kelas.kelompok')
|
|
||||||
->get()
|
|
||||||
->map(function($sk) use ($id_santri) {
|
|
||||||
$kehadiran = AbsensiKegiatan::where('id_santri', $id_santri)
|
|
||||||
->whereHas('kegiatan', function($q) use ($sk) {
|
|
||||||
$q->whereHas('kelasKegiatan', function($q2) use ($sk) {
|
|
||||||
$q2->where('id_kelas', $sk->id_kelas);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
->selectRaw('
|
|
||||||
COUNT(*) as total,
|
|
||||||
SUM(CASE WHEN status = "Hadir" THEN 1 ELSE 0 END) as hadir
|
|
||||||
')
|
|
||||||
->first();
|
|
||||||
|
|
||||||
return [
|
|
||||||
'kelas' => $sk->kelas->nama_kelas,
|
|
||||||
'kelompok' => $sk->kelas->kelompok->nama_kelompok,
|
|
||||||
'total' => $kehadiran->total ?? 0,
|
|
||||||
'hadir' => $kehadiran->hadir ?? 0,
|
|
||||||
'persen' => ($kehadiran->total ?? 0) > 0 ? round((($kehadiran->hadir ?? 0) / $kehadiran->total) * 100, 1) : 0,
|
|
||||||
];
|
];
|
||||||
});
|
|
||||||
|
|
||||||
return view('admin.kegiatan.riwayat.detail-santri', compact(
|
// ── Tentukan mode & rentang tanggal ───────────────────────────────────
|
||||||
'santri',
|
$mode = $request->get('mode', 'hari_ini');
|
||||||
'stats',
|
|
||||||
'statsByKategori',
|
if ($mode === 'minggu_ini') {
|
||||||
'riwayat30Hari',
|
$dari = now()->startOfWeek(Carbon::MONDAY)->format('Y-m-d');
|
||||||
'riwayats',
|
$sampai = now()->endOfWeek(Carbon::SUNDAY)->format('Y-m-d');
|
||||||
'statsByKelasSantri'
|
$tanggal = null;
|
||||||
|
} elseif ($mode === 'custom') {
|
||||||
|
$dari = $request->get('dari', now()->subDays(6)->format('Y-m-d'));
|
||||||
|
$sampai = $request->get('sampai', now()->format('Y-m-d'));
|
||||||
|
if ($dari > $sampai) { [$dari, $sampai] = [$sampai, $dari]; }
|
||||||
|
$tanggal = null;
|
||||||
|
} else {
|
||||||
|
$mode = 'hari_ini';
|
||||||
|
$tanggal = $request->get('tanggal', now()->format('Y-m-d'));
|
||||||
|
$dari = $tanggal;
|
||||||
|
$sampai = $tanggal;
|
||||||
|
}
|
||||||
|
|
||||||
|
$kategoris = KategoriKegiatan::select('kategori_id', 'nama_kategori')->orderBy('nama_kategori')->get();
|
||||||
|
$kategoriId = $request->get('kategori_id', '');
|
||||||
|
|
||||||
|
// ── Label periode ─────────────────────────────────────────────────────
|
||||||
|
if ($mode === 'hari_ini') {
|
||||||
|
$periodeLabel = Carbon::parse($dari)->locale('id')->isoFormat('dddd, D MMMM Y');
|
||||||
|
} elseif ($mode === 'minggu_ini') {
|
||||||
|
$periodeLabel = Carbon::parse($dari)->locale('id')->isoFormat('D MMM') . ' – '
|
||||||
|
. Carbon::parse($sampai)->locale('id')->isoFormat('D MMM Y');
|
||||||
|
} else {
|
||||||
|
$periodeLabel = Carbon::parse($dari)->locale('id')->isoFormat('D MMM Y') . ' – '
|
||||||
|
. Carbon::parse($sampai)->locale('id')->isoFormat('D MMM Y');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════════
|
||||||
|
// MODE HARI INI — flat list kegiatan (paginated)
|
||||||
|
// ═══════════════════════════════════════════════════════════════════
|
||||||
|
if ($mode === 'hari_ini') {
|
||||||
|
$hariDipilih = $hariMap[Carbon::parse($dari)->format('l')] ?? null;
|
||||||
|
|
||||||
|
$baseQuery = Kegiatan::with(['kategori', 'kelasKegiatan.kelompok'])
|
||||||
|
->when($hariDipilih, fn($q) => $q->where('hari', $hariDipilih))
|
||||||
|
->when($kategoriId, fn($q) => $q->where('kategori_id', $kategoriId))
|
||||||
|
->withCount([
|
||||||
|
'absensis as total_absensi' => fn($q) => $q->whereDate('tanggal', $dari),
|
||||||
|
'absensis as hadir' => fn($q) => $q->where('status', 'Hadir')->whereDate('tanggal', $dari),
|
||||||
|
'absensis as terlambat' => fn($q) => $q->where('status', 'Terlambat')->whereDate('tanggal', $dari),
|
||||||
|
'absensis as izin' => fn($q) => $q->where('status', 'Izin')->whereDate('tanggal', $dari),
|
||||||
|
'absensis as sakit' => fn($q) => $q->where('status', 'Sakit')->whereDate('tanggal', $dari),
|
||||||
|
'absensis as alpa' => fn($q) => $q->where('status', 'Alpa')->whereDate('tanggal', $dari),
|
||||||
|
'absensis as pulang' => fn($q) => $q->where('status', 'Pulang')->whereDate('tanggal', $dari),
|
||||||
|
])
|
||||||
|
->orderBy('waktu_mulai');
|
||||||
|
|
||||||
|
$kegiatans = (clone $baseQuery)->paginate(20)->appends($request->query());
|
||||||
|
$kegiatanPerTanggal = null;
|
||||||
|
|
||||||
|
$allItems = (clone $baseQuery)->get();
|
||||||
|
$summary = [
|
||||||
|
'hadir' => $allItems->sum('hadir') + $allItems->sum('terlambat'),
|
||||||
|
'terlambat' => $allItems->sum('terlambat'),
|
||||||
|
'izin' => $allItems->sum('izin'),
|
||||||
|
'sakit' => $allItems->sum('sakit'),
|
||||||
|
'alpa' => $allItems->sum('alpa'),
|
||||||
|
'total_absensi' => $allItems->sum('total_absensi'),
|
||||||
|
'jumlah_kegiatan' => $allItems->count(),
|
||||||
|
'jumlah_hari' => 1,
|
||||||
|
];
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════════
|
||||||
|
// MODE MULTI-HARI — grouped by actual date
|
||||||
|
// ═══════════════════════════════════════════════════════════════════
|
||||||
|
} else {
|
||||||
|
$kegiatans = null;
|
||||||
|
|
||||||
|
// Ambil semua tanggal yang ada absensi dalam range (terbaru dulu)
|
||||||
|
$tanggalList = AbsensiKegiatan::selectRaw('DATE(tanggal) as tgl')
|
||||||
|
->whereDate('tanggal', '>=', $dari)
|
||||||
|
->whereDate('tanggal', '<=', $sampai)
|
||||||
|
->when($kategoriId, fn($q) => $q->whereHas('kegiatan', fn($qq) => $qq->where('kategori_id', $kategoriId)))
|
||||||
|
->groupBy('tgl')
|
||||||
|
->orderBy('tgl', 'desc')
|
||||||
|
->pluck('tgl');
|
||||||
|
|
||||||
|
// Untuk tiap tanggal: kegiatan + stats khusus tanggal itu saja
|
||||||
|
$kegiatanPerTanggal = collect();
|
||||||
|
foreach ($tanggalList as $tgl) {
|
||||||
|
$hariIndo = $hariMap[Carbon::parse($tgl)->format('l')] ?? null;
|
||||||
|
|
||||||
|
$items = Kegiatan::with(['kategori', 'kelasKegiatan.kelompok'])
|
||||||
|
->when($hariIndo, fn($q) => $q->where('hari', $hariIndo))
|
||||||
|
->when($kategoriId, fn($q) => $q->where('kategori_id', $kategoriId))
|
||||||
|
->whereHas('absensis', fn($q) => $q->whereDate('tanggal', $tgl))
|
||||||
|
->withCount([
|
||||||
|
'absensis as total_absensi' => fn($q) => $q->whereDate('tanggal', $tgl),
|
||||||
|
'absensis as hadir' => fn($q) => $q->where('status', 'Hadir')->whereDate('tanggal', $tgl),
|
||||||
|
'absensis as terlambat' => fn($q) => $q->where('status', 'Terlambat')->whereDate('tanggal', $tgl),
|
||||||
|
'absensis as izin' => fn($q) => $q->where('status', 'Izin')->whereDate('tanggal', $tgl),
|
||||||
|
'absensis as sakit' => fn($q) => $q->where('status', 'Sakit')->whereDate('tanggal', $tgl),
|
||||||
|
'absensis as alpa' => fn($q) => $q->where('status', 'Alpa')->whereDate('tanggal', $tgl),
|
||||||
|
'absensis as pulang' => fn($q) => $q->where('status', 'Pulang')->whereDate('tanggal', $tgl),
|
||||||
|
])
|
||||||
|
->orderBy('waktu_mulai')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
if ($items->count() > 0) {
|
||||||
|
$kegiatanPerTanggal[$tgl] = $items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$allKeg = $kegiatanPerTanggal->flatten();
|
||||||
|
$summary = [
|
||||||
|
'hadir' => $allKeg->sum('hadir') + $allKeg->sum('terlambat'),
|
||||||
|
'terlambat' => $allKeg->sum('terlambat'),
|
||||||
|
'izin' => $allKeg->sum('izin'),
|
||||||
|
'sakit' => $allKeg->sum('sakit'),
|
||||||
|
'alpa' => $allKeg->sum('alpa'),
|
||||||
|
'total_absensi' => $allKeg->sum('total_absensi'),
|
||||||
|
'jumlah_kegiatan' => $allKeg->count(),
|
||||||
|
'jumlah_hari' => $kegiatanPerTanggal->count(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('admin.kegiatan.riwayat.index', compact(
|
||||||
|
'kegiatans', 'kegiatanPerTanggal', 'kategoris', 'summary', 'mode',
|
||||||
|
'dari', 'sampai', 'tanggal', 'periodeLabel', 'kategoriId'
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show detail riwayat per kegiatan
|
* Detail riwayat per kegiatan — santri per kelas + filter
|
||||||
*/
|
*/
|
||||||
public function show($id, Request $request)
|
public function show($id, Request $request)
|
||||||
{
|
{
|
||||||
$kegiatan = Kegiatan::with(['kategori', 'kelasKegiatan.kelompok'])
|
$kegiatan = Kegiatan::with(['kategori', 'kelasKegiatan.kelompok'])
|
||||||
->findOrFail($id);
|
->findOrFail($id);
|
||||||
|
|
||||||
// Query riwayat absensi untuk kegiatan ini
|
// ── Ambil parameter periode dari index ────────────────────────────────
|
||||||
|
$mode = $request->get('mode', 'hari_ini');
|
||||||
|
$dari = $request->get('dari', now()->format('Y-m-d'));
|
||||||
|
$sampai = $request->get('sampai', now()->format('Y-m-d'));
|
||||||
|
$tanggal = $request->get('tanggal', now()->format('Y-m-d'));
|
||||||
|
|
||||||
|
if ($mode === 'hari_ini') {
|
||||||
|
$dari = $tanggal;
|
||||||
|
$sampai = $tanggal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Query absensi ─────────────────────────────────────────────────────
|
||||||
$query = AbsensiKegiatan::with(['santri.kelasSantri.kelas.kelompok'])
|
$query = AbsensiKegiatan::with(['santri.kelasSantri.kelas.kelompok'])
|
||||||
->where('kegiatan_id', $kegiatan->kegiatan_id);
|
->where('kegiatan_id', $kegiatan->kegiatan_id)
|
||||||
|
->whereDate('tanggal', '>=', $dari)
|
||||||
|
->whereDate('tanggal', '<=', $sampai);
|
||||||
|
|
||||||
// Filter Santri
|
if ($request->filled('id_santri')) $query->where('id_santri', $request->id_santri);
|
||||||
if ($request->filled('id_santri')) {
|
if ($request->filled('id_kelas')) $query->whereHas('santri.kelasSantri', fn($q) => $q->where('id_kelas', $request->id_kelas));
|
||||||
$query->where('id_santri', $request->id_santri);
|
if ($request->filled('status')) $query->where('status', $request->status);
|
||||||
}
|
if ($request->filled('tanggal_spesifik')) $query->whereDate('tanggal', $request->tanggal_spesifik);
|
||||||
|
|
||||||
// Filter Kelas
|
$riwayats = $query->orderBy('tanggal', 'desc')->orderBy('waktu_absen')->paginate(50)->appends($request->query());
|
||||||
|
|
||||||
|
// ── Statistik ─────────────────────────────────────────────────────────
|
||||||
|
$statsQuery = AbsensiKegiatan::where('kegiatan_id', $kegiatan->kegiatan_id)
|
||||||
|
->whereDate('tanggal', '>=', $dari)->whereDate('tanggal', '<=', $sampai);
|
||||||
if ($request->filled('id_kelas')) {
|
if ($request->filled('id_kelas')) {
|
||||||
$query->whereHas('santri.kelasSantri', function($q) use ($request) {
|
$statsQuery->whereHas('santri.kelasSantri', fn($q) => $q->where('id_kelas', $request->id_kelas));
|
||||||
$q->where('id_kelas', $request->id_kelas);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter Status
|
|
||||||
if ($request->filled('status')) {
|
|
||||||
$query->where('status', $request->status);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter Tanggal
|
|
||||||
if ($request->filled('tanggal_dari')) {
|
|
||||||
$query->whereDate('tanggal', '>=', $request->tanggal_dari);
|
|
||||||
}
|
|
||||||
if ($request->filled('tanggal_sampai')) {
|
|
||||||
$query->whereDate('tanggal', '<=', $request->tanggal_sampai);
|
|
||||||
}
|
|
||||||
if ($request->filled('bulan')) {
|
|
||||||
$query->whereMonth('tanggal', date('m', strtotime($request->bulan)))
|
|
||||||
->whereYear('tanggal', date('Y', strtotime($request->bulan)));
|
|
||||||
}
|
|
||||||
|
|
||||||
$riwayats = $query->orderBy('tanggal', 'desc')
|
|
||||||
->orderBy('waktu_absen', 'desc')
|
|
||||||
->paginate(20)
|
|
||||||
->appends(request()->query());
|
|
||||||
|
|
||||||
// Data untuk filter
|
|
||||||
$santris = Santri::where('status', 'Aktif')
|
|
||||||
->select('id_santri', 'nama_lengkap')
|
|
||||||
->orderBy('nama_lengkap')
|
|
||||||
->get();
|
|
||||||
|
|
||||||
$kelasList = Kelas::active()->ordered()->with('kelompok')->get();
|
|
||||||
|
|
||||||
// Statistik untuk kegiatan ini (sesuai filter)
|
|
||||||
$statsQuery = AbsensiKegiatan::where('kegiatan_id', $kegiatan->kegiatan_id);
|
|
||||||
if ($request->filled('tanggal_dari')) {
|
|
||||||
$statsQuery->whereDate('tanggal', '>=', $request->tanggal_dari);
|
|
||||||
}
|
|
||||||
if ($request->filled('tanggal_sampai')) {
|
|
||||||
$statsQuery->whereDate('tanggal', '<=', $request->tanggal_sampai);
|
|
||||||
}
|
|
||||||
if ($request->filled('bulan')) {
|
|
||||||
$statsQuery->whereMonth('tanggal', date('m', strtotime($request->bulan)))
|
|
||||||
->whereYear('tanggal', date('Y', strtotime($request->bulan)));
|
|
||||||
}
|
|
||||||
if ($request->filled('id_kelas')) {
|
|
||||||
$statsQuery->whereHas('santri.kelasSantri', function($q) use ($request) {
|
|
||||||
$q->where('id_kelas', $request->id_kelas);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
$stats = $statsQuery->select('status', DB::raw('count(*) as total'))
|
$stats = $statsQuery->select('status', DB::raw('count(*) as total'))
|
||||||
->groupBy('status')
|
->groupBy('status')->pluck('total', 'status')->toArray();
|
||||||
->pluck('total', 'status')
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
// Hitung total SEMUA santri aktif
|
// ── Total santri yang seharusnya hadir ────────────────────────────────
|
||||||
|
if ($kegiatan->kelasKegiatan->isEmpty()) {
|
||||||
$totalSantriEligible = Santri::where('status', 'Aktif')->count();
|
$totalSantriEligible = Santri::where('status', 'Aktif')->count();
|
||||||
|
} else {
|
||||||
|
$kelasIds = $kegiatan->kelasKegiatan->pluck('id')->toArray();
|
||||||
|
$totalSantriEligible = Santri::where('status', 'Aktif')
|
||||||
|
->whereHas('kelasSantri', fn($q) => $q->whereIn('id_kelas', $kelasIds))
|
||||||
|
->count();
|
||||||
|
if ($totalSantriEligible === 0) $totalSantriEligible = Santri::where('status', 'Aktif')->count();
|
||||||
|
}
|
||||||
|
|
||||||
$totalRecorded = array_sum($stats);
|
$totalRecorded = array_sum($stats);
|
||||||
$hadirCount = ($stats['Hadir'] ?? 0) + ($stats['Terlambat'] ?? 0);
|
$hadirCount = ($stats['Hadir'] ?? 0) + ($stats['Terlambat'] ?? 0);
|
||||||
$persenHadir = $totalSantriEligible > 0 ? round($hadirCount / $totalSantriEligible * 100, 1) : 0;
|
$persenHadir = $totalSantriEligible > 0 ? round($hadirCount / $totalSantriEligible * 100, 1) : 0;
|
||||||
|
|
||||||
|
// ── Filter dropdown ───────────────────────────────────────────────────
|
||||||
|
$santris = Santri::where('status', 'Aktif')->select('id_santri', 'nama_lengkap')->orderBy('nama_lengkap')->get();
|
||||||
|
$kelasList = Kelas::active()->ordered()->with('kelompok')->get();
|
||||||
|
|
||||||
|
// ── Label periode ─────────────────────────────────────────────────────
|
||||||
|
if ($mode === 'hari_ini') {
|
||||||
|
$periodeLabel = Carbon::parse($dari)->locale('id')->isoFormat('dddd, D MMMM Y');
|
||||||
|
} else {
|
||||||
|
$periodeLabel = Carbon::parse($dari)->locale('id')->isoFormat('D MMM Y')
|
||||||
|
. ' – '
|
||||||
|
. Carbon::parse($sampai)->locale('id')->isoFormat('D MMM Y');
|
||||||
|
}
|
||||||
|
|
||||||
return view('admin.kegiatan.riwayat.show', compact(
|
return view('admin.kegiatan.riwayat.show', compact(
|
||||||
'kegiatan',
|
'kegiatan', 'riwayats', 'santris', 'kelasList', 'stats',
|
||||||
'riwayats',
|
'totalSantriEligible', 'totalRecorded', 'persenHadir',
|
||||||
'santris',
|
'mode', 'dari', 'sampai', 'tanggal', 'periodeLabel'
|
||||||
'kelasList',
|
|
||||||
'stats',
|
|
||||||
'totalSantriEligible',
|
|
||||||
'totalRecorded',
|
|
||||||
'persenHadir'
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit riwayat absensi
|
* Riwayat kehadiran per santri — tabbed per kategori
|
||||||
*/
|
*/
|
||||||
|
public function detailSantri($id_santri, Request $request)
|
||||||
|
{
|
||||||
|
$santri = Santri::where('id_santri', $id_santri)->firstOrFail();
|
||||||
|
|
||||||
|
// ── Statistik ringkasan (Terlambat = Hadir, bukan Alpa) ──────────────
|
||||||
|
$rawStats = AbsensiKegiatan::where('id_santri', $id_santri)
|
||||||
|
->select('status', DB::raw('count(*) as total'))
|
||||||
|
->groupBy('status')->pluck('total', 'status')->toArray();
|
||||||
|
|
||||||
|
// Hadir efektif = Hadir + Terlambat
|
||||||
|
$stats = $rawStats;
|
||||||
|
$stats['_hadir_efektif'] = ($rawStats['Hadir'] ?? 0) + ($rawStats['Terlambat'] ?? 0);
|
||||||
|
|
||||||
|
// ── Tren 30 hari — Hadir efektif (Hadir + Terlambat) ─────────────────
|
||||||
|
$riwayat30Hari = AbsensiKegiatan::where('id_santri', $id_santri)
|
||||||
|
->whereDate('tanggal', '>=', now()->subDays(29))
|
||||||
|
->select(
|
||||||
|
DB::raw('DATE(tanggal) as tanggal'),
|
||||||
|
DB::raw('SUM(CASE WHEN status IN ("Hadir","Terlambat") THEN 1 ELSE 0 END) as hadir'),
|
||||||
|
DB::raw('COUNT(*) as total')
|
||||||
|
)
|
||||||
|
->groupBy('tanggal')->orderBy('tanggal', 'asc')->get();
|
||||||
|
|
||||||
|
// ── Daftar semua kategori yang punya riwayat untuk santri ini ─────────
|
||||||
|
$kategoriList = AbsensiKegiatan::where('id_santri', $id_santri)
|
||||||
|
->join('kegiatans', 'absensi_kegiatans.kegiatan_id', '=', 'kegiatans.kegiatan_id')
|
||||||
|
->join('kategori_kegiatans', 'kegiatans.kategori_id', '=', 'kategori_kegiatans.kategori_id')
|
||||||
|
->select(
|
||||||
|
'kategori_kegiatans.kategori_id',
|
||||||
|
'kategori_kegiatans.nama_kategori',
|
||||||
|
DB::raw('COUNT(*) as total'),
|
||||||
|
DB::raw('SUM(CASE WHEN absensi_kegiatans.status IN ("Hadir","Terlambat") THEN 1 ELSE 0 END) as hadir_efektif')
|
||||||
|
)
|
||||||
|
->groupBy('kategori_kegiatans.kategori_id', 'kategori_kegiatans.nama_kategori')
|
||||||
|
->orderBy('kategori_kegiatans.nama_kategori')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
// ── Tab aktif & per_page ───────────────────────────────────────────────
|
||||||
|
$activeKategori = $request->get('tab_kat', $kategoriList->first()?->kategori_id ?? '');
|
||||||
|
|
||||||
|
// per_page: 15 | 50 | 100 | 'all' (semua data, tanpa paginasi)
|
||||||
|
$perPageRaw = $request->get('per_page', 15);
|
||||||
|
$showAll = ($perPageRaw === 'all');
|
||||||
|
$perPage = $showAll ? 'all' : (in_array((int)$perPageRaw, [15, 50, 100]) ? (int)$perPageRaw : 15);
|
||||||
|
|
||||||
|
// ── Riwayat untuk tab aktif ────────────────────────────────────────────
|
||||||
|
$riwayatsQuery = AbsensiKegiatan::with('kegiatan.kategori')
|
||||||
|
->where('id_santri', $id_santri)
|
||||||
|
->whereHas('kegiatan', fn($q) => $q->where('kategori_id', $activeKategori))
|
||||||
|
->orderBy('tanggal', 'desc');
|
||||||
|
|
||||||
|
if ($showAll) {
|
||||||
|
// Wrap sebagai LengthAwarePaginator manual agar view tetap konsisten
|
||||||
|
$allItems = $riwayatsQuery->get();
|
||||||
|
$riwayats = new \Illuminate\Pagination\LengthAwarePaginator(
|
||||||
|
$allItems, $allItems->count(), max($allItems->count(), 1), 1,
|
||||||
|
['path' => $request->url(), 'query' => $request->query()]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$riwayats = $riwayatsQuery->paginate($perPage)->appends($request->query());
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('admin.kegiatan.riwayat.detail-santri', compact(
|
||||||
|
'santri', 'stats', 'riwayat30Hari', 'riwayats',
|
||||||
|
'kategoriList', 'activeKategori', 'perPage', 'showAll'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
public function edit(AbsensiKegiatan $riwayat)
|
public function edit(AbsensiKegiatan $riwayat)
|
||||||
{
|
{
|
||||||
$riwayat->load(['santri', 'kegiatan']);
|
$riwayat->load(['santri', 'kegiatan']);
|
||||||
return view('admin.kegiatan.riwayat.edit', compact('riwayat'));
|
return view('admin.kegiatan.riwayat.edit', compact('riwayat'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update riwayat absensi
|
|
||||||
*/
|
|
||||||
public function update(Request $request, AbsensiKegiatan $riwayat)
|
public function update(Request $request, AbsensiKegiatan $riwayat)
|
||||||
{
|
{
|
||||||
$validated = $request->validate([
|
$validated = $request->validate([
|
||||||
'status' => 'required|in:Hadir,Izin,Sakit,Alpa',
|
'status' => 'required|in:Hadir,Izin,Sakit,Alpa,Terlambat,Pulang',
|
||||||
'waktu_absen' => 'nullable|date_format:H:i',
|
'waktu_absen' => 'nullable|date_format:H:i',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$riwayat->update($validated);
|
$riwayat->update($validated);
|
||||||
|
return redirect()->route('admin.riwayat-kegiatan.index')->with('success', 'Riwayat absensi berhasil diperbarui.');
|
||||||
return redirect()->route('admin.riwayat-kegiatan.index')
|
|
||||||
->with('success', 'Riwayat absensi berhasil diperbarui.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Hapus riwayat absensi
|
|
||||||
*/
|
|
||||||
public function destroy(AbsensiKegiatan $riwayat)
|
public function destroy(AbsensiKegiatan $riwayat)
|
||||||
{
|
{
|
||||||
$nama = $riwayat->santri->nama_lengkap;
|
$nama = $riwayat->santri->nama_lengkap;
|
||||||
$riwayat->delete();
|
$riwayat->delete();
|
||||||
|
return redirect()->route('admin.riwayat-kegiatan.index')->with('success', "Riwayat absensi $nama berhasil dihapus.");
|
||||||
return redirect()->route('admin.riwayat-kegiatan.index')
|
|
||||||
->with('success', "Riwayat absensi $nama berhasil dihapus.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export/Cetak laporan (opsional - bisa dikembangkan)
|
|
||||||
*/
|
|
||||||
public function exportPdf(Request $request)
|
|
||||||
{
|
|
||||||
// Implementasi export PDF jika diperlukan
|
|
||||||
return response()->json(['message' => 'Fitur export sedang dikembangkan']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -19,7 +19,9 @@ class UserController extends Controller
|
||||||
*/
|
*/
|
||||||
public function santriAccounts()
|
public function santriAccounts()
|
||||||
{
|
{
|
||||||
$users = SantriAccount::where('role', 'santri')->with('santri')->get();
|
$users = SantriAccount::where('role', 'santri')
|
||||||
|
->with(['santri:id_santri,nama_lengkap,nis,nomor_hp_ortu'])
|
||||||
|
->get();
|
||||||
|
|
||||||
$santris_tanpa_akun = Santri::whereDoesntHave('santriAccount', function ($q) {
|
$santris_tanpa_akun = Santri::whereDoesntHave('santriAccount', function ($q) {
|
||||||
$q->where('role', 'santri');
|
$q->where('role', 'santri');
|
||||||
|
|
@ -109,7 +111,9 @@ public function destroySantriAccount(string $id)
|
||||||
*/
|
*/
|
||||||
public function waliAccounts()
|
public function waliAccounts()
|
||||||
{
|
{
|
||||||
$users = SantriAccount::where('role', 'wali')->with('santri')->get();
|
$users = SantriAccount::where('role', 'wali')
|
||||||
|
->with(['santri:id_santri,nama_lengkap,nis,nama_orang_tua,nomor_hp_ortu'])
|
||||||
|
->get();
|
||||||
|
|
||||||
$santris_tanpa_wali = Santri::whereDoesntHave('santriAccount', function ($q) {
|
$santris_tanpa_wali = Santri::whereDoesntHave('santriAccount', function ($q) {
|
||||||
$q->where('role', 'wali');
|
$q->where('role', 'wali');
|
||||||
|
|
|
||||||
|
|
@ -2,39 +2,6 @@
|
||||||
/**
|
/**
|
||||||
* EpposGLogParser.php — versi 2
|
* EpposGLogParser.php — versi 2
|
||||||
* app/Services/EpposGLogParser.php
|
* app/Services/EpposGLogParser.php
|
||||||
*
|
|
||||||
* ═══════════════════════════════════════════════════════════════
|
|
||||||
* PERUBAHAN UTAMA dari versi 1:
|
|
||||||
* IOMd TIDAK lagi diabaikan. Setiap slot di shift mesin
|
|
||||||
* (JK1 Masuk, JK1 Pulang, JK2 Masuk, JK2 Pulang, Lb Masuk, Lb Pulang)
|
|
||||||
* bisa dipetakan ke kegiatan web yang BERBEDA.
|
|
||||||
*
|
|
||||||
* CONTOH MESIN SHOLAT:
|
|
||||||
* JK1 Masuk (IOMd=2) jam 04:00 → Shubuh
|
|
||||||
* JK1 Pulang (IOMd=4) jam 05:00 → Dhuhur
|
|
||||||
* JK2 Masuk (IOMd=2) jam 11:45 → Ashar
|
|
||||||
* JK2 Pulang (IOMd=4) jam 12:20 → Maghrib
|
|
||||||
* Lb Masuk (IOMd=2) jam 15:05 → Isya
|
|
||||||
*
|
|
||||||
* CONTOH MESIN NGAJI:
|
|
||||||
* JK1 Masuk (IOMd=2) jam 05:00 → Ngaji Shubuh
|
|
||||||
* JK1 Pulang (IOMd=4) jam 06:00 → sekolah
|
|
||||||
* JK2 Masuk (IOMd=2) jam 13:00 → Ngaji Siang
|
|
||||||
* JK2 Pulang (IOMd=4) jam 15:00 → Ngaji Maghrib
|
|
||||||
* Lb Masuk (IOMd=2) jam 18:00 → Ngaji Malam
|
|
||||||
*
|
|
||||||
* ═══════════════════════════════════════════════════════════════
|
|
||||||
* FORMAT GLOG.TXT (Tab-Separated):
|
|
||||||
* No | Mchn | EnNo | Name | Mode | IOMd | DateTime
|
|
||||||
* 000001 | 1 | 000000001 | helga faisa | 1 | 2 | 2026/02/28 04:05:00
|
|
||||||
*
|
|
||||||
* IOMd=2 → scan MASUK (Check In)
|
|
||||||
* IOMd=4 → scan PULANG (Check Out)
|
|
||||||
*
|
|
||||||
* FORMAT INFO.XLS:
|
|
||||||
* Sheet "Shift" → No.Shift | JK1 Msuk | JK1 Kluar | JK2 Msuk | JK2 Kluar | Lb Msuk | Lb Kluar
|
|
||||||
* Sheet "Jadwal" → No | Nama | Departemen | Shift
|
|
||||||
* ═══════════════════════════════════════════════════════════════
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
@ -44,22 +11,18 @@
|
||||||
|
|
||||||
class EpposGLogParser
|
class EpposGLogParser
|
||||||
{
|
{
|
||||||
// IOMd values dari mesin Eppos
|
|
||||||
const IOMD_MASUK = 2;
|
const IOMD_MASUK = 2;
|
||||||
const IOMD_PULANG = 4;
|
const IOMD_PULANG = 4;
|
||||||
|
|
||||||
// 6 slot per shift (nama slot → key di array shift)
|
|
||||||
// Urutan ini penting untuk matching prioritas
|
|
||||||
const SLOT_KEYS = [
|
const SLOT_KEYS = [
|
||||||
'jk1_msuk', // JK1 Masuk (IOMd=2)
|
'jk1_msuk',
|
||||||
'jk1_kluar', // JK1 Pulang (IOMd=4)
|
'jk1_kluar',
|
||||||
'jk2_msuk', // JK2 Masuk (IOMd=2)
|
'jk2_msuk',
|
||||||
'jk2_kluar', // JK2 Pulang (IOMd=4)
|
'jk2_kluar',
|
||||||
'lb_msuk', // Lembur Masuk (IOMd=2)
|
'lb_msuk',
|
||||||
'lb_kluar', // Lembur Pulang (IOMd=4)
|
'lb_kluar',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Masing-masing slot → IOMd yang diharapkan
|
|
||||||
const SLOT_IOMD = [
|
const SLOT_IOMD = [
|
||||||
'jk1_msuk' => self::IOMD_MASUK,
|
'jk1_msuk' => self::IOMD_MASUK,
|
||||||
'jk1_kluar' => self::IOMD_PULANG,
|
'jk1_kluar' => self::IOMD_PULANG,
|
||||||
|
|
@ -73,25 +36,6 @@ class EpposGLogParser
|
||||||
// PARSE INFO.XLS
|
// PARSE INFO.XLS
|
||||||
// ─────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse INFO.XLS → konfigurasi shift dan daftar santri di mesin
|
|
||||||
*
|
|
||||||
* @return array [
|
|
||||||
* 'shifts' => [
|
|
||||||
* 1 => [
|
|
||||||
* 'jk1_msuk' => '04:00',
|
|
||||||
* 'jk1_kluar' => '05:00',
|
|
||||||
* 'jk2_msuk' => '11:45',
|
|
||||||
* 'jk2_kluar' => '12:20',
|
|
||||||
* 'lb_msuk' => '15:05',
|
|
||||||
* 'lb_kluar' => null, // null = slot tidak dipakai
|
|
||||||
* ],
|
|
||||||
* ],
|
|
||||||
* 'jadwal' => [
|
|
||||||
* '1' => ['nama'=>'helga faisa', 'dept'=>'Office', 'shift'=>1],
|
|
||||||
* ]
|
|
||||||
* ]
|
|
||||||
*/
|
|
||||||
public function parseInfoFile(string $path): array
|
public function parseInfoFile(string $path): array
|
||||||
{
|
{
|
||||||
$spreadsheet = IOFactory::load($path);
|
$spreadsheet = IOFactory::load($path);
|
||||||
|
|
@ -105,7 +49,6 @@ public function parseInfoFile(string $path): array
|
||||||
private function parseShifts($sheet): array
|
private function parseShifts($sheet): array
|
||||||
{
|
{
|
||||||
$shifts = [];
|
$shifts = [];
|
||||||
// Kolom: A=No, B=JK1 Msuk, C=JK1 Kluar, D=JK2 Msuk, E=JK2 Kluar, F=Lb Msuk, G=Lb Kluar
|
|
||||||
for ($row = 6; $row <= $sheet->getHighestRow(); $row++) {
|
for ($row = 6; $row <= $sheet->getHighestRow(); $row++) {
|
||||||
$no = $sheet->getCell("A{$row}")->getValue();
|
$no = $sheet->getCell("A{$row}")->getValue();
|
||||||
if (!is_numeric($no)) continue;
|
if (!is_numeric($no)) continue;
|
||||||
|
|
@ -119,7 +62,6 @@ private function parseShifts($sheet): array
|
||||||
'lb_kluar' => $this->readTime($sheet->getCell("G{$row}")->getValue()),
|
'lb_kluar' => $this->readTime($sheet->getCell("G{$row}")->getValue()),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Skip shift yang semua slot-nya kosong
|
|
||||||
$adaIsi = array_filter($s);
|
$adaIsi = array_filter($s);
|
||||||
if (empty($adaIsi)) continue;
|
if (empty($adaIsi)) continue;
|
||||||
|
|
||||||
|
|
@ -146,23 +88,9 @@ private function parseJadwal($sheet): array
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────
|
||||||
// PARSE GLOG.TXT ← PERUBAHAN UTAMA: simpan IOMd per scan
|
// PARSE GLOG.TXT
|
||||||
// ─────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse GLog.txt → semua record scan, TERMASUK IOMd
|
|
||||||
*
|
|
||||||
* @return array [
|
|
||||||
* [
|
|
||||||
* 'id_mesin' => '1',
|
|
||||||
* 'nama_mesin' => 'helga faisa',
|
|
||||||
* 'tanggal' => '2026-02-28',
|
|
||||||
* 'jam' => '04:05',
|
|
||||||
* 'iomd' => 2, // ← BARU: 2=Masuk, 4=Pulang
|
|
||||||
* 'dt_raw' => '2026/02/28 04:05:00',
|
|
||||||
* ],
|
|
||||||
* ]
|
|
||||||
*/
|
|
||||||
public function parseGLog(string $path): array
|
public function parseGLog(string $path): array
|
||||||
{
|
{
|
||||||
$content = file_get_contents($path);
|
$content = file_get_contents($path);
|
||||||
|
|
@ -177,29 +105,26 @@ public function parseGLog(string $path): array
|
||||||
$cols = explode("\t", $line);
|
$cols = explode("\t", $line);
|
||||||
$cols = array_values(array_filter(array_map('trim', $cols), fn($v) => $v !== ''));
|
$cols = array_values(array_filter(array_map('trim', $cols), fn($v) => $v !== ''));
|
||||||
|
|
||||||
// Minimal 7 kolom: No | Mchn | EnNo | Name | Mode | IOMd | DateTime
|
|
||||||
if (count($cols) < 7) continue;
|
if (count($cols) < 7) continue;
|
||||||
if ($cols[0] === 'No') continue; // header
|
if ($cols[0] === 'No') continue;
|
||||||
|
|
||||||
$enno = $cols[2] ?? '';
|
$enno = $cols[2] ?? '';
|
||||||
$namaMesin = $cols[3] ?? '';
|
$namaMesin = $cols[3] ?? '';
|
||||||
$iomdRaw = $cols[5] ?? ''; // kolom ke-6 (index 5)
|
$iomdRaw = $cols[5] ?? '';
|
||||||
$dtRaw = $cols[6] ?? '';
|
$dtRaw = $cols[6] ?? '';
|
||||||
|
|
||||||
if (!is_numeric(ltrim($enno, '0') ?: '0')) continue;
|
if (!is_numeric(ltrim($enno, '0') ?: '0')) continue;
|
||||||
if (empty($dtRaw)) continue;
|
if (empty($dtRaw)) continue;
|
||||||
|
|
||||||
// IOMd: harus 2 atau 4
|
|
||||||
$iomd = (int)$iomdRaw;
|
$iomd = (int)$iomdRaw;
|
||||||
if (!in_array($iomd, [self::IOMD_MASUK, self::IOMD_PULANG])) continue;
|
if (!in_array($iomd, [self::IOMD_MASUK, self::IOMD_PULANG])) continue;
|
||||||
|
|
||||||
// Parse DateTime
|
|
||||||
$dtRaw = preg_replace('/\s+/', ' ', trim($dtRaw));
|
$dtRaw = preg_replace('/\s+/', ' ', trim($dtRaw));
|
||||||
$parts = explode(' ', $dtRaw);
|
$parts = explode(' ', $dtRaw);
|
||||||
if (count($parts) < 2) continue;
|
if (count($parts) < 2) continue;
|
||||||
|
|
||||||
$tglStr = $parts[0]; // "2026/02/28"
|
$tglStr = $parts[0];
|
||||||
$jamStr = substr($parts[1], 0, 5); // "04:05"
|
$jamStr = substr($parts[1], 0, 5);
|
||||||
|
|
||||||
if (!preg_match('/^\d{4}\/\d{2}\/\d{2}$/', $tglStr)) continue;
|
if (!preg_match('/^\d{4}\/\d{2}\/\d{2}$/', $tglStr)) continue;
|
||||||
if (!preg_match('/^\d{2}:\d{2}$/', $jamStr)) continue;
|
if (!preg_match('/^\d{2}:\d{2}$/', $jamStr)) continue;
|
||||||
|
|
@ -212,7 +137,7 @@ public function parseGLog(string $path): array
|
||||||
'nama_mesin' => trim($namaMesin),
|
'nama_mesin' => trim($namaMesin),
|
||||||
'tanggal' => $tanggal,
|
'tanggal' => $tanggal,
|
||||||
'jam' => $jamStr,
|
'jam' => $jamStr,
|
||||||
'iomd' => $iomd, // ← BARU
|
'iomd' => $iomd,
|
||||||
'dt_raw' => $dtRaw,
|
'dt_raw' => $dtRaw,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
@ -221,25 +146,9 @@ public function parseGLog(string $path): array
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────
|
||||||
// GROUP BY DAY ← PERUBAHAN: scans sekarang simpan iomd
|
// GROUP BY DAY
|
||||||
// ─────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/**
|
|
||||||
* Kelompokkan per (id_mesin + tanggal)
|
|
||||||
* scans sekarang array of ['jam'=>'04:05','iomd'=>2]
|
|
||||||
*
|
|
||||||
* @return array [
|
|
||||||
* '1_2026-02-28' => [
|
|
||||||
* 'id_mesin' => '1',
|
|
||||||
* 'nama_mesin' => 'helga faisa',
|
|
||||||
* 'tanggal' => '2026-02-28',
|
|
||||||
* 'scans' => [
|
|
||||||
* ['jam'=>'04:05','iomd'=>2],
|
|
||||||
* ['jam'=>'05:10','iomd'=>4],
|
|
||||||
* ],
|
|
||||||
* ],
|
|
||||||
* ]
|
|
||||||
*/
|
|
||||||
public function groupGLogByDay(array $records): array
|
public function groupGLogByDay(array $records): array
|
||||||
{
|
{
|
||||||
$grouped = [];
|
$grouped = [];
|
||||||
|
|
@ -256,7 +165,6 @@ public function groupGLogByDay(array $records): array
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hindari duplikat jam+iomd yang persis sama
|
|
||||||
$duplikat = array_filter(
|
$duplikat = array_filter(
|
||||||
$grouped[$key]['scans'],
|
$grouped[$key]['scans'],
|
||||||
fn($s) => $s['jam'] === $r['jam'] && $s['iomd'] === $r['iomd']
|
fn($s) => $s['jam'] === $r['jam'] && $s['iomd'] === $r['iomd']
|
||||||
|
|
@ -269,7 +177,6 @@ public function groupGLogByDay(array $records): array
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort scan berurutan berdasarkan jam
|
|
||||||
foreach ($grouped as &$g) {
|
foreach ($grouped as &$g) {
|
||||||
usort($g['scans'], fn($a, $b) => strcmp($a['jam'], $b['jam']));
|
usort($g['scans'], fn($a, $b) => strcmp($a['jam'], $b['jam']));
|
||||||
}
|
}
|
||||||
|
|
@ -278,32 +185,27 @@ public function groupGLogByDay(array $records): array
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────
|
||||||
// MATCH TO KEGIATAN ← PERUBAHAN UTAMA
|
// MATCH TO KEGIATAN
|
||||||
// ─────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cocokkan setiap scan ke kegiatan web.
|
* Cocokkan setiap scan ke kegiatan web.
|
||||||
*
|
*
|
||||||
* LOGIKA BARU (pakai IOMd):
|
* STATUS Hadir / Terlambat ditentukan berdasarkan $tolSesudah:
|
||||||
* ──────────────────────────────────────────────────────────
|
* ─────────────────────────────────────────────────────────────
|
||||||
* 1. Ambil shift santri dari infoData['jadwal']
|
* scan <= waktu_mulai + $tolSesudah → Hadir
|
||||||
* 2. Buat "slot windows" dari shift tersebut:
|
* scan > waktu_mulai + $tolSesudah → Terlambat
|
||||||
* Setiap slot (jk1_msuk, jk1_kluar, dst) punya jam + IOMd
|
|
||||||
* 3. Untuk setiap scan (jam + iomd):
|
|
||||||
* a. Cari slot yang IOMd-nya cocok DAN jam scan masuk window ±toleransi
|
|
||||||
* b. Dari slot yang cocok, cari kegiatan web hari ini yang waktunya paling dekat
|
|
||||||
* 4. Hasilkan baris per kegiatan: Hadir / Terlambat / Alpa
|
|
||||||
*
|
*
|
||||||
* FALLBACK (tanpa IOMd, jika infoData kosong):
|
* Contoh: tolSesudah=30, kegiatan mulai 04:00
|
||||||
* Jika santri tidak ada di infoData (baru daftar, seperti firda),
|
* Scan 04:07 (+7 menit) → Hadir ✅ (7 ≤ 30)
|
||||||
* cocokkan hanya berdasarkan jam (abaikan IOMd) dengan toleransi lebih sempit.
|
* Scan 04:35 (+35 menit) → Terlambat ⏰ (35 > 30)
|
||||||
* ──────────────────────────────────────────────────────────
|
* ─────────────────────────────────────────────────────────────
|
||||||
*
|
*
|
||||||
* @param array $glogGrouped Output groupGLogByDay()
|
* @param array $glogGrouped Output groupGLogByDay()
|
||||||
* @param array $infoData Output parseInfoFile() — ['shifts'=>[...],'jadwal'=>[...]]
|
* @param array $infoData Output parseInfoFile()
|
||||||
* @param array $kegiatans Dari DB: [['kegiatan_id','nama','hari','waktu_mulai','waktu_selesai'],...]
|
* @param array $kegiatans Dari DB
|
||||||
* @param int $tolSebelum Menit toleransi SEBELUM waktu_mulai kegiatan
|
* @param int $tolSebelum Menit toleransi SEBELUM waktu_mulai (window masuk)
|
||||||
* @param int $tolSesudah Menit toleransi SESUDAH waktu_selesai kegiatan
|
* @param int $tolSesudah Menit toleransi SESUDAH waktu_mulai (Hadir/Terlambat cut-off)
|
||||||
*/
|
*/
|
||||||
public function matchToKegiatan(
|
public function matchToKegiatan(
|
||||||
array $glogGrouped,
|
array $glogGrouped,
|
||||||
|
|
@ -317,31 +219,26 @@ public function matchToKegiatan(
|
||||||
foreach ($glogGrouped as $dayData) {
|
foreach ($glogGrouped as $dayData) {
|
||||||
$tanggal = $dayData['tanggal'];
|
$tanggal = $dayData['tanggal'];
|
||||||
$idMesin = $dayData['id_mesin'];
|
$idMesin = $dayData['id_mesin'];
|
||||||
$scans = $dayData['scans']; // [['jam'=>'04:05','iomd'=>2], ...]
|
$scans = $dayData['scans'];
|
||||||
$hari = $this->tanggalToHari($tanggal);
|
$hari = $this->tanggalToHari($tanggal);
|
||||||
|
|
||||||
// Kegiatan hari ini dari web
|
|
||||||
$kegHariIni = array_values(
|
$kegHariIni = array_values(
|
||||||
array_filter($kegiatans, fn($k) => $k['hari'] === $hari)
|
array_filter($kegiatans, fn($k) => $k['hari'] === $hari)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Info shift santri ini dari INFO.XLS
|
|
||||||
$jadwalInfo = $infoData['jadwal'][$idMesin] ?? null;
|
$jadwalInfo = $infoData['jadwal'][$idMesin] ?? null;
|
||||||
$nomorShift = $jadwalInfo ? ($jadwalInfo['shift'] ?? 1) : null;
|
$nomorShift = $jadwalInfo ? ($jadwalInfo['shift'] ?? 1) : null;
|
||||||
$shiftData = ($nomorShift && isset($infoData['shifts'][$nomorShift]))
|
$shiftData = ($nomorShift && isset($infoData['shifts'][$nomorShift]))
|
||||||
? $infoData['shifts'][$nomorShift]
|
? $infoData['shifts'][$nomorShift]
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
// Build slot windows dari shift santri
|
|
||||||
// slotWindows: [ ['slot'=>'jk1_msuk','jam'=>'04:00','iomd'=>2], ... ]
|
|
||||||
$slotWindows = $shiftData
|
$slotWindows = $shiftData
|
||||||
? $this->buildSlotWindows($shiftData)
|
? $this->buildSlotWindows($shiftData)
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
// ── Matching ────────────────────────────────────────────
|
$matchedKg = [];
|
||||||
$matchedKg = []; // kegiatan_id → true (sudah dapat scan)
|
$usedScans = [];
|
||||||
$usedScans = []; // index scan yang sudah dipakai
|
$rowMap = [];
|
||||||
$rowMap = []; // kegiatan_id → result row
|
|
||||||
|
|
||||||
foreach ($scans as $idx => $scan) {
|
foreach ($scans as $idx => $scan) {
|
||||||
$scanJam = $scan['jam'];
|
$scanJam = $scan['jam'];
|
||||||
|
|
@ -353,11 +250,10 @@ public function matchToKegiatan(
|
||||||
$bestSlot = null;
|
$bestSlot = null;
|
||||||
|
|
||||||
if (!empty($slotWindows)) {
|
if (!empty($slotWindows)) {
|
||||||
// ── MODE UTAMA: pakai IOMd dari shift ──────────────
|
// ── MODE UTAMA: cocokkan pakai IOMd dari shift ──────
|
||||||
// Langkah 1: cari slot yang IOMd-nya cocok DAN jam dalam window
|
|
||||||
foreach ($slotWindows as $sw) {
|
foreach ($slotWindows as $sw) {
|
||||||
if ($sw['iomd'] !== $scanIomd) continue; // IOMd harus cocok
|
if ($sw['iomd'] !== $scanIomd) continue;
|
||||||
if ($sw['jam'] === null) continue; // slot tidak diset
|
if ($sw['jam'] === null) continue;
|
||||||
|
|
||||||
$slotMnt = $this->toMinutes($sw['jam']);
|
$slotMnt = $this->toMinutes($sw['jam']);
|
||||||
$windowMulai = $slotMnt - $tolSebelum;
|
$windowMulai = $slotMnt - $tolSebelum;
|
||||||
|
|
@ -365,7 +261,6 @@ public function matchToKegiatan(
|
||||||
|
|
||||||
if ($scanMnt < $windowMulai || $scanMnt > $windowAkhir) continue;
|
if ($scanMnt < $windowMulai || $scanMnt > $windowAkhir) continue;
|
||||||
|
|
||||||
// Slot cocok — sekarang cari kegiatan web yang paling dekat
|
|
||||||
foreach ($kegHariIni as $kg) {
|
foreach ($kegHariIni as $kg) {
|
||||||
if (isset($matchedKg[$kg['kegiatan_id']])) continue;
|
if (isset($matchedKg[$kg['kegiatan_id']])) continue;
|
||||||
|
|
||||||
|
|
@ -374,7 +269,6 @@ public function matchToKegiatan(
|
||||||
$kgWindowMul = $kgMulaiMnt - $tolSebelum;
|
$kgWindowMul = $kgMulaiMnt - $tolSebelum;
|
||||||
$kgWindowAkh = $kgSelesaiMnt + $tolSesudah;
|
$kgWindowAkh = $kgSelesaiMnt + $tolSesudah;
|
||||||
|
|
||||||
// Jam slot harus masuk window kegiatan
|
|
||||||
if ($slotMnt < $kgWindowMul || $slotMnt > $kgWindowAkh) continue;
|
if ($slotMnt < $kgWindowMul || $slotMnt > $kgWindowAkh) continue;
|
||||||
|
|
||||||
$selisih = abs($slotMnt - $kgMulaiMnt);
|
$selisih = abs($slotMnt - $kgMulaiMnt);
|
||||||
|
|
@ -386,16 +280,12 @@ public function matchToKegiatan(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ── FALLBACK: shifts kosong, matching hanya berdasarkan jam ──
|
// ── FALLBACK: shifts kosong, matching hanya berdasar jam ──
|
||||||
// Pakai toleransi penuh (bukan dikurangi)
|
|
||||||
// Cari kegiatan yang paling dekat jamnya dengan scan
|
|
||||||
foreach ($kegHariIni as $kg) {
|
foreach ($kegHariIni as $kg) {
|
||||||
if (isset($matchedKg[$kg['kegiatan_id']])) continue;
|
if (isset($matchedKg[$kg['kegiatan_id']])) continue;
|
||||||
|
|
||||||
$kgMulaiMnt = $this->toMinutes($kg['waktu_mulai']);
|
$kgMulaiMnt = $this->toMinutes($kg['waktu_mulai']);
|
||||||
$kgSelesaiMnt = $this->toMinutes($kg['waktu_selesai'] ?: $kg['waktu_mulai']);
|
$kgSelesaiMnt = $this->toMinutes($kg['waktu_selesai'] ?: $kg['waktu_mulai']);
|
||||||
|
|
||||||
// Window: tolSebelum menit sebelum mulai s/d tolSesudah menit setelah selesai
|
|
||||||
$kgWindowMul = $kgMulaiMnt - $tolSebelum;
|
$kgWindowMul = $kgMulaiMnt - $tolSebelum;
|
||||||
$kgWindowAkh = $kgSelesaiMnt + $tolSesudah;
|
$kgWindowAkh = $kgSelesaiMnt + $tolSesudah;
|
||||||
|
|
||||||
|
|
@ -409,15 +299,20 @@ public function matchToKegiatan(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Simpan hasil match ────────────────────────────
|
|
||||||
if ($bestKg) {
|
if ($bestKg) {
|
||||||
$kgMulaiMnt = $this->toMinutes($bestKg['waktu_mulai']);
|
$kgMulaiMnt = $this->toMinutes($bestKg['waktu_mulai']);
|
||||||
|
|
||||||
// Grace period: scan sampai 5 menit setelah mulai → masih Hadir
|
|
||||||
// Lebih dari 5 menit → Terlambat
|
|
||||||
$graceMnt = 5;
|
|
||||||
$selisih = $scanMnt - $kgMulaiMnt;
|
$selisih = $scanMnt - $kgMulaiMnt;
|
||||||
$status = $selisih <= $graceMnt ? 'Hadir' : 'Terlambat';
|
|
||||||
|
// ─────────────────────────────────────────────────────
|
||||||
|
// STATUS Hadir vs Terlambat:
|
||||||
|
// Hadir → scan tiba SEBELUM atau tepat waktu +$tolSesudah menit
|
||||||
|
// Terlambat → scan tiba LEBIH dari $tolSesudah menit setelah mulai
|
||||||
|
//
|
||||||
|
// Dengan begitu: toleransi dari form LANGSUNG menentukan batas
|
||||||
|
// Hadir/Terlambat — tidak ada nilai hardcode di sini.
|
||||||
|
// ─────────────────────────────────────────────────────
|
||||||
|
$status = $selisih <= $tolSesudah ? 'Hadir' : 'Terlambat';
|
||||||
|
$selisihTampil = $selisih > 0 ? $selisih : 0; // menit telat (hanya jika positif)
|
||||||
|
|
||||||
$matchedKg[$bestKg['kegiatan_id']] = true;
|
$matchedKg[$bestKg['kegiatan_id']] = true;
|
||||||
$usedScans[] = $idx;
|
$usedScans[] = $idx;
|
||||||
|
|
@ -430,13 +325,13 @@ public function matchToKegiatan(
|
||||||
'iomd_scan' => $scanIomd,
|
'iomd_scan' => $scanIomd,
|
||||||
'label_iomd' => $scanIomd === self::IOMD_MASUK ? 'Masuk' : 'Pulang',
|
'label_iomd' => $scanIomd === self::IOMD_MASUK ? 'Masuk' : 'Pulang',
|
||||||
'status' => $status,
|
'status' => $status,
|
||||||
'selisih_menit' => max(0, $selisih - $graceMnt), // hanya menit yg melebihi grace
|
'selisih_menit' => $selisihTampil,
|
||||||
'matched' => true,
|
'matched' => true,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Isi Alpa untuk kegiatan tanpa scan ───────────────
|
// ── Alpa untuk kegiatan tanpa scan ───────────────────
|
||||||
foreach ($kegHariIni as $kg) {
|
foreach ($kegHariIni as $kg) {
|
||||||
if (!isset($rowMap[$kg['kegiatan_id']])) {
|
if (!isset($rowMap[$kg['kegiatan_id']])) {
|
||||||
$rowMap[$kg['kegiatan_id']] = [
|
$rowMap[$kg['kegiatan_id']] = [
|
||||||
|
|
@ -453,11 +348,11 @@ public function matchToKegiatan(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan yang tidak cocok ke kegiatan apapun
|
|
||||||
$unmatchedScans = [];
|
$unmatchedScans = [];
|
||||||
foreach ($scans as $idx => $scan) {
|
foreach ($scans as $idx => $scan) {
|
||||||
if (!in_array($idx, $usedScans)) {
|
if (!in_array($idx, $usedScans)) {
|
||||||
$unmatchedScans[] = $scan['jam'] . ' (' . ($scan['iomd'] === 2 ? 'Masuk' : 'Pulang') . ')';
|
$unmatchedScans[] = $scan['jam']
|
||||||
|
. ' (' . ($scan['iomd'] === 2 ? 'Masuk' : 'Pulang') . ')';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -470,7 +365,7 @@ public function matchToKegiatan(
|
||||||
'hari' => $hari,
|
'hari' => $hari,
|
||||||
'all_scans' => $scans,
|
'all_scans' => $scans,
|
||||||
'unmatched_scans' => $unmatchedScans,
|
'unmatched_scans' => $unmatchedScans,
|
||||||
'shift_dipakai' => $nomorShift, // ← BARU: untuk debug di preview
|
'shift_dipakai' => $nomorShift,
|
||||||
'rows' => $rows,
|
'rows' => $rows,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
@ -479,22 +374,9 @@ public function matchToKegiatan(
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────
|
||||||
// BUILD SLOT WINDOWS dari data shift
|
// BUILD SLOT WINDOWS
|
||||||
// ─────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/**
|
|
||||||
* Dari satu shift, buat array slot windows yang bisa dicocokkan dengan scan.
|
|
||||||
*
|
|
||||||
* @param array $shiftData ['jk1_msuk'=>'04:00','jk1_kluar'=>'05:00', ...]
|
|
||||||
* @return array [
|
|
||||||
* ['slot'=>'jk1_msuk', 'jam'=>'04:00', 'iomd'=>2],
|
|
||||||
* ['slot'=>'jk1_kluar', 'jam'=>'05:00', 'iomd'=>4],
|
|
||||||
* ['slot'=>'jk2_msuk', 'jam'=>'11:45', 'iomd'=>2],
|
|
||||||
* ['slot'=>'jk2_kluar', 'jam'=>'12:20', 'iomd'=>4],
|
|
||||||
* ['slot'=>'lb_msuk', 'jam'=>'15:05', 'iomd'=>2],
|
|
||||||
* ['slot'=>'lb_kluar', 'jam'=>null, 'iomd'=>4], // null = tidak dipakai
|
|
||||||
* ]
|
|
||||||
*/
|
|
||||||
private function buildSlotWindows(array $shiftData): array
|
private function buildSlotWindows(array $shiftData): array
|
||||||
{
|
{
|
||||||
$windows = [];
|
$windows = [];
|
||||||
|
|
@ -532,9 +414,6 @@ public function tanggalToHari(string $tanggal): string
|
||||||
][Carbon::parse($tanggal)->format('l')] ?? 'Senin';
|
][Carbon::parse($tanggal)->format('l')] ?? 'Senin';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Baca nilai jam dari Excel — bisa berupa string "05:00" atau float (serial Excel)
|
|
||||||
*/
|
|
||||||
private function readTime($val): ?string
|
private function readTime($val): ?string
|
||||||
{
|
{
|
||||||
if ($val === null || $val === '') return null;
|
if ($val === null || $val === '') return null;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Http\Kernel;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
define('LARAVEL_START', microtime(true));
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Check If The Application Is Under Maintenance
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| If the application is in maintenance / demo mode via the "down" command
|
||||||
|
| we will load this file so that any pre-rendered content can be shown
|
||||||
|
| instead of starting the framework, which could cause an exception.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
|
||||||
|
require $maintenance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Register The Auto Loader
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Composer provides a convenient, automatically generated class loader for
|
||||||
|
| this application. We just need to utilize it! We'll simply require it
|
||||||
|
| into the script here so we don't need to manually load our classes.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
require __DIR__.'/../vendor/autoload.php';
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Run The Application
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Once we have the application, we can handle the incoming request using
|
||||||
|
| the application's HTTP kernel. Then, we will send the response back
|
||||||
|
| to this client's browser, allowing them to enjoy our application.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
$app = require_once __DIR__.'/../bootstrap/app.php';
|
||||||
|
|
||||||
|
$kernel = $app->make(Kernel::class);
|
||||||
|
|
||||||
|
$response = $kernel->handle(
|
||||||
|
$request = Request::capture()
|
||||||
|
)->send();
|
||||||
|
|
||||||
|
$kernel->terminate($request, $response);
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -461,7 +461,10 @@ .main-content-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
transition: margin-left 0.3s ease;
|
transition: margin-left 0.3s ease;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-header {
|
.main-header {
|
||||||
|
|
@ -497,8 +500,11 @@ .sidebar-toggle-btn:hover {
|
||||||
.main-content {
|
.main-content {
|
||||||
padding: clamp(10px, 1.2vw, 16px);
|
padding: clamp(10px, 1.2vw, 16px);
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
transition: opacity 0.3s ease-in;
|
transition: opacity 0.3s ease-in;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================
|
/* ===================================
|
||||||
|
|
@ -632,6 +638,9 @@ .content-box {
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
box-shadow: var(--shadow-sm);
|
box-shadow: var(--shadow-sm);
|
||||||
border: 1px solid var(--primary-light);
|
border: 1px solid var(--primary-light);
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================
|
/* ===================================
|
||||||
|
|
@ -682,6 +691,10 @@ .alert {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
animation: slideInDown 0.4s ease;
|
animation: slideInDown 0.4s ease;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-success {
|
.alert-success {
|
||||||
|
|
@ -1056,6 +1069,7 @@ .table-wrapper {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-wrapper .data-table {
|
.table-wrapper .data-table {
|
||||||
|
|
@ -2147,7 +2161,7 @@ @media (max-width: 480px) {
|
||||||
/* 5-column KPI row */
|
/* 5-column KPI row */
|
||||||
.row-cards-5 {
|
.row-cards-5 {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(5, 1fr);
|
grid-template-columns: repeat(auto-fit, minmax(min(140px, 100%), 1fr));
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
@ -2165,6 +2179,7 @@ .dash-grid-2 {
|
||||||
grid-template-columns: 3fr 2fr;
|
grid-template-columns: 3fr 2fr;
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Chart containers */
|
/* Chart containers */
|
||||||
|
|
@ -2184,6 +2199,8 @@ .chart-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart-container-sm {
|
.chart-container-sm {
|
||||||
|
|
@ -2330,15 +2347,24 @@ @media (max-width: 768px) {
|
||||||
.row-cards-5 {
|
.row-cards-5 {
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
}
|
}
|
||||||
|
.dash-fin-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
.chart-container {
|
||||||
|
height: 180px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
.row-cards-5 {
|
.row-cards-5 {
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: 1fr 1fr;
|
||||||
}
|
}
|
||||||
.spp-summary {
|
.spp-summary {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
.chart-container {
|
||||||
|
height: 160px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================
|
/* ===================================
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 277 KiB |
|
|
@ -216,91 +216,6 @@
|
||||||
border-color:#6FBA9D; background:#fff; box-shadow:0 0 0 3px rgba(111,186,157,.1);
|
border-color:#6FBA9D; background:#fff; box-shadow:0 0 0 3px rgba(111,186,157,.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Demo Account Button ── */
|
|
||||||
.lg-demo-btn {
|
|
||||||
display:flex; align-items:center; justify-content:center; gap:8px;
|
|
||||||
margin-top:10px; padding:9px;
|
|
||||||
background:transparent; border:1.5px dashed #A8D8C6; border-radius:10px;
|
|
||||||
font-size:.76rem; font-weight:600; color:#8AADA0; cursor:pointer;
|
|
||||||
font-family:inherit; width:100%;
|
|
||||||
transition:all .2s;
|
|
||||||
}
|
|
||||||
.lg-demo-btn:hover { border-color:#6FBA9D; color:#3D8A6E; background:#EBF7F2; }
|
|
||||||
|
|
||||||
/* ── Modal Overlay ── */
|
|
||||||
.lg-modal-overlay {
|
|
||||||
position:fixed; inset:0; z-index:9999;
|
|
||||||
background:rgba(15,33,24,.45); backdrop-filter:blur(4px);
|
|
||||||
display:flex; align-items:center; justify-content:center;
|
|
||||||
opacity:0; pointer-events:none; transition:opacity .25s ease;
|
|
||||||
}
|
|
||||||
.lg-modal-overlay.open { opacity:1; pointer-events:all; }
|
|
||||||
|
|
||||||
/* ── Modal Box ── */
|
|
||||||
.lg-modal {
|
|
||||||
background:#fff; border-radius:20px; padding:32px 28px;
|
|
||||||
width:100%; max-width:380px; position:relative;
|
|
||||||
box-shadow:0 20px 60px rgba(15,33,24,.18);
|
|
||||||
transform:translateY(16px) scale(.97); transition:transform .25s ease;
|
|
||||||
}
|
|
||||||
.lg-modal-overlay.open .lg-modal { transform:translateY(0) scale(1); }
|
|
||||||
.lg-modal::before {
|
|
||||||
content:''; position:absolute; top:0; left:0; right:0; height:3px;
|
|
||||||
background:linear-gradient(90deg,#6FBA9D,#A8D8C6,#6FBA9D);
|
|
||||||
border-radius:20px 20px 0 0;
|
|
||||||
}
|
|
||||||
.lg-modal-close {
|
|
||||||
position:absolute; top:14px; right:16px;
|
|
||||||
background:none; border:none; font-size:1.1rem;
|
|
||||||
color:#B8D4C8; cursor:pointer; line-height:1;
|
|
||||||
transition:color .2s;
|
|
||||||
}
|
|
||||||
.lg-modal-close:hover { color:#3D8A6E; }
|
|
||||||
.lg-modal-ico {
|
|
||||||
width:44px; height:44px; border-radius:12px; background:#EBF7F2;
|
|
||||||
display:flex; align-items:center; justify-content:center;
|
|
||||||
color:#3D8A6E; font-size:1rem; margin-bottom:14px;
|
|
||||||
}
|
|
||||||
.lg-modal-title {
|
|
||||||
font-family:'DM Serif Display',serif;
|
|
||||||
font-size:1.35rem; color:#0F2118; margin-bottom:4px;
|
|
||||||
}
|
|
||||||
.lg-modal-sub { font-size:.75rem; color:#8AADA0; margin-bottom:20px; line-height:1.5; }
|
|
||||||
.lg-demo-table { width:100%; border-collapse:collapse; }
|
|
||||||
.lg-demo-table thead tr th {
|
|
||||||
font-size:.64rem; font-weight:700; letter-spacing:1.2px;
|
|
||||||
text-transform:uppercase; color:#8AADA0;
|
|
||||||
padding:0 10px 8px; text-align:left;
|
|
||||||
border-bottom:1px solid #EBF7F2;
|
|
||||||
}
|
|
||||||
.lg-demo-table tbody tr { transition:background .15s; }
|
|
||||||
.lg-demo-table tbody tr:hover { background:#F4FCF8; }
|
|
||||||
.lg-demo-table tbody tr td {
|
|
||||||
padding:10px 10px; font-size:.78rem; color:#2A4235;
|
|
||||||
border-bottom:1px solid #F0FAF5; vertical-align:middle;
|
|
||||||
}
|
|
||||||
.lg-demo-table tbody tr:last-child td { border-bottom:none; }
|
|
||||||
.lg-role-badge {
|
|
||||||
display:inline-block; padding:2px 8px;
|
|
||||||
border-radius:20px; font-size:.66rem; font-weight:700;
|
|
||||||
letter-spacing:.5px;
|
|
||||||
}
|
|
||||||
.badge-super { background:#FFF3E0; color:#E65100; }
|
|
||||||
.badge-akademik { background:#E3F2FD; color:#1565C0; }
|
|
||||||
.badge-pamong { background:#F3E5F5; color:#6A1B9A; }
|
|
||||||
.badge-santri { background:#E8F5E9; color:#2E7D32; }
|
|
||||||
.lg-copy-btn {
|
|
||||||
background:none; border:none; color:#A8D8C6; cursor:pointer;
|
|
||||||
font-size:.72rem; padding:2px 4px; border-radius:4px;
|
|
||||||
transition:color .2s;
|
|
||||||
}
|
|
||||||
.lg-copy-btn:hover { color:#3D8A6E; }
|
|
||||||
.lg-modal-note {
|
|
||||||
margin-top:16px; padding:10px 12px;
|
|
||||||
background:#FFFBF0; border-left:3px solid #FFD54F;
|
|
||||||
border-radius:8px; font-size:.72rem; color:#795548; line-height:1.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive */
|
/* Responsive */
|
||||||
@media (max-width: 900px) {
|
@media (max-width: 900px) {
|
||||||
.lg-layout { gap:48px; padding:32px 36px; }
|
.lg-layout { gap:48px; padding:32px 36px; }
|
||||||
|
|
@ -444,11 +359,6 @@
|
||||||
<i class="fas fa-user-graduate"></i> Login sebagai Santri / Wali
|
<i class="fas fa-user-graduate"></i> Login sebagai Santri / Wali
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
{{-- ── Tombol Akun Demo (tambahan) ── --}}
|
|
||||||
<button type="button" class="lg-demo-btn" id="lgDemoBtn">
|
|
||||||
<i class="fas fa-info-circle"></i> Lihat Akun Demo untuk Pengujian
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -456,76 +366,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ── Modal Akun Demo ── --}}
|
|
||||||
<div class="lg-modal-overlay" id="lgDemoOverlay">
|
|
||||||
<div class="lg-modal">
|
|
||||||
<button class="lg-modal-close" id="lgModalClose" aria-label="Tutup">
|
|
||||||
<i class="fas fa-times"></i>
|
|
||||||
</button>
|
|
||||||
<div class="lg-modal-ico"><i class="fas fa-users"></i></div>
|
|
||||||
<div class="lg-modal-title">Akun Demo</div>
|
|
||||||
|
|
||||||
<table class="lg-demo-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Role</th>
|
|
||||||
<th>Email / Username</th>
|
|
||||||
<th>Password</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td><span class="lg-role-badge badge-super">Superadmin</span></td>
|
|
||||||
<td style="font-size:.72rem;">helga.faisa06@gmail.com</td>
|
|
||||||
<td style="font-size:.72rem;">Admin123_</td>
|
|
||||||
<td>
|
|
||||||
<button class="lg-copy-btn" onclick="lgCopy('helga.faisa06@gmail.com','Admin123_')" title="Isi otomatis">
|
|
||||||
<i class="fas fa-arrow-right"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><span class="lg-role-badge badge-akademik">Akademik</span></td>
|
|
||||||
<td style="font-size:.72rem;">akademik@test.com</td>
|
|
||||||
<td style="font-size:.72rem;">password123</td>
|
|
||||||
<td>
|
|
||||||
<button class="lg-copy-btn" onclick="lgCopy('akademik@test.com','password123')" title="Isi otomatis">
|
|
||||||
<i class="fas fa-arrow-right"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><span class="lg-role-badge badge-pamong">Pamong</span></td>
|
|
||||||
<td style="font-size:.72rem;">pamong@test.com</td>
|
|
||||||
<td style="font-size:.72rem;">password123</td>
|
|
||||||
<td>
|
|
||||||
<button class="lg-copy-btn" onclick="lgCopy('pamong@test.com','password123')" title="Isi otomatis">
|
|
||||||
<i class="fas fa-arrow-right"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><span class="lg-role-badge badge-santri">Santri</span></td>
|
|
||||||
<td style="font-size:.72rem;">Helga Faisa</td>
|
|
||||||
<td style="font-size:.72rem;">s001</td>
|
|
||||||
<td>
|
|
||||||
<button class="lg-copy-btn" onclick="lgCopy('Helga Faisa','s001')" title="Isi otomatis">
|
|
||||||
<i class="fas fa-arrow-right"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div class="lg-modal-note">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
Klik <i class="fas fa-arrow-right"></i> untuk mengisi form login otomatis.
|
|
||||||
Akun santri dapat digunakan di halaman login santri.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Toggle password
|
// Toggle password
|
||||||
|
|
@ -581,33 +421,6 @@
|
||||||
if (e.key === 'Enter') { e.preventDefault(); p.focus(); }
|
if (e.key === 'Enter') { e.preventDefault(); p.focus(); }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Demo Modal ──
|
|
||||||
const demoBtn = document.getElementById('lgDemoBtn');
|
|
||||||
const overlay = document.getElementById('lgDemoOverlay');
|
|
||||||
const modalClose = document.getElementById('lgModalClose');
|
|
||||||
|
|
||||||
function openModal() { overlay.classList.add('open'); }
|
|
||||||
function closeModal() { overlay.classList.remove('open'); }
|
|
||||||
|
|
||||||
if (demoBtn) demoBtn.addEventListener('click', openModal);
|
|
||||||
if (modalClose) modalClose.addEventListener('click', closeModal);
|
|
||||||
if (overlay) overlay.addEventListener('click', function(e) {
|
|
||||||
if (e.target === overlay) closeModal();
|
|
||||||
});
|
});
|
||||||
document.addEventListener('keydown', function(e) {
|
|
||||||
if (e.key === 'Escape') closeModal();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Auto-fill form dari modal
|
|
||||||
function lgCopy(email, pass) {
|
|
||||||
const u = document.getElementById('username');
|
|
||||||
const p = document.getElementById('password');
|
|
||||||
if (u) u.value = email;
|
|
||||||
if (p) p.value = pass;
|
|
||||||
document.getElementById('lgDemoOverlay').classList.remove('open');
|
|
||||||
if (u) u.focus();
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
@ -3,25 +3,102 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Rapor Capaian - {{ $santri->nama_lengkap }} - {{ $semester->nama_semester }}</title>
|
<title>Capaian Materi — {{ $santri->nama_lengkap }}</title>
|
||||||
<style>
|
<style>
|
||||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
/* ── RESET & BASE ── */
|
||||||
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #333; background: #fff; padding: 20px; font-size: 11pt; }
|
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
|
||||||
.rapor-header { text-align: center; padding-bottom: 20px; border-bottom: 3px double #6FBA9D; margin-bottom: 24px; }
|
body {
|
||||||
.rapor-header h1 { font-size: 16pt; color: #2e7d32; margin-bottom: 4px; }
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
.rapor-header h2 { font-size: 12pt; color: #555; font-weight: 400; margin-bottom: 8px; }
|
color: #222;
|
||||||
.rapor-header .subtitle { font-size: 10pt; color: #888; }
|
background: #fff;
|
||||||
|
font-size: 10.5pt;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
.info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0; margin-bottom: 24px; background: #f8faf9; border-radius: 8px; padding: 16px; border: 1px solid #e0e0e0; }
|
/* ── SCREEN WRAPPER ── */
|
||||||
.info-item { padding: 4px 0; font-size: 10pt; }
|
.page-wrap {
|
||||||
.info-item .label { color: #888; display: inline-block; width: 130px; }
|
max-width: 210mm;
|
||||||
.info-item .value { font-weight: 600; color: #333; }
|
margin: 0 auto;
|
||||||
|
padding: 16mm 14mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── PRINT BUTTON (screen only) ── */
|
||||||
|
.print-btn {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 24px;
|
||||||
|
right: 24px;
|
||||||
|
background: #6FBA9D;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
padding: 11px 22px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 10.5pt;
|
||||||
|
font-weight: 700;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 4px 14px rgba(111,186,157,.45);
|
||||||
|
z-index: 999;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 7px;
|
||||||
|
}
|
||||||
|
.print-btn:hover { background: #5EA98C; }
|
||||||
|
|
||||||
|
/* ════════════════════════════
|
||||||
|
HEADER
|
||||||
|
════════════════════════════ */
|
||||||
|
.rapor-header {
|
||||||
|
text-align: center;
|
||||||
|
padding-bottom: 14px;
|
||||||
|
border-bottom: 3px double #6FBA9D;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
break-inside: avoid;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
.rapor-header h1 { font-size: 15pt; color: #2e7d32; margin-bottom: 3px; letter-spacing: .5px; }
|
||||||
|
.rapor-header h2 { font-size: 11pt; color: #555; font-weight: 400; margin-bottom: 6px; }
|
||||||
|
.rapor-header .subtitle { font-size: 9.5pt; color: #888; }
|
||||||
|
|
||||||
|
/* ════════════════════════════
|
||||||
|
INFO SANTRI
|
||||||
|
════════════════════════════ */
|
||||||
|
.info-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 3px 20px;
|
||||||
|
background: #f7faf8;
|
||||||
|
border: 1px solid #dde8e3;
|
||||||
|
border-radius: 7px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
break-inside: avoid;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
.info-item { font-size: 9.5pt; padding: 2px 0; }
|
||||||
|
.info-item .label { color: #888; display: inline-block; width: 124px; }
|
||||||
|
.info-item .value { font-weight: 600; color: #222; }
|
||||||
|
|
||||||
|
/* ════════════════════════════
|
||||||
|
SUMMARY BOXES
|
||||||
|
════════════════════════════ */
|
||||||
|
.summary-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 22px;
|
||||||
|
break-inside: avoid;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
.summary-box {
|
||||||
|
text-align: center;
|
||||||
|
padding: 12px 8px;
|
||||||
|
border-radius: 7px;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
.summary-box .sb-val { font-size: 17pt; font-weight: 800; line-height: 1.1; }
|
||||||
|
.summary-box .sb-label { font-size: 7.5pt; color: #888; text-transform: uppercase; letter-spacing: .5px; margin-top: 3px; }
|
||||||
|
.summary-box .sb-comp { font-size: 8pt; margin-top: 4px; }
|
||||||
|
|
||||||
.summary-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 24px; }
|
|
||||||
.summary-box { text-align: center; padding: 14px 10px; border-radius: 8px; border: 1px solid #e0e0e0; }
|
|
||||||
.summary-box .sb-val { font-size: 18pt; font-weight: 800; }
|
|
||||||
.summary-box .sb-label { font-size: 8pt; color: #888; text-transform: uppercase; letter-spacing: 0.5px; margin-top: 2px; }
|
|
||||||
.sb-green { border-color: #c8e6c9; background: #f1f8e9; }
|
.sb-green { border-color: #c8e6c9; background: #f1f8e9; }
|
||||||
.sb-green .sb-val { color: #2e7d32; }
|
.sb-green .sb-val { color: #2e7d32; }
|
||||||
.sb-blue { border-color: #bbdefb; background: #e3f2fd; }
|
.sb-blue { border-color: #bbdefb; background: #e3f2fd; }
|
||||||
|
|
@ -31,82 +108,253 @@
|
||||||
.sb-red { border-color: #ffcdd2; background: #fbe9e7; }
|
.sb-red { border-color: #ffcdd2; background: #fbe9e7; }
|
||||||
.sb-red .sb-val { color: #c62828; }
|
.sb-red .sb-val { color: #c62828; }
|
||||||
|
|
||||||
h3 { font-size: 12pt; color: #2e7d32; margin-bottom: 12px; padding-bottom: 6px; border-bottom: 2px solid #e8f5e9; }
|
.comp-up { color: #2e7d32; }
|
||||||
|
.comp-down { color: #c62828; }
|
||||||
|
.comp-same { color: #999; }
|
||||||
|
|
||||||
|
/* ════════════════════════════
|
||||||
|
SECTION HEADINGS
|
||||||
|
════════════════════════════ */
|
||||||
|
.section-title {
|
||||||
|
font-size: 11pt;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #2e7d32;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-left: 4px solid #6FBA9D;
|
||||||
|
background: #f1f8e9;
|
||||||
|
border-radius: 0 5px 5px 0;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
/* Judul selalu ikut tabel di bawahnya */
|
||||||
|
break-after: avoid;
|
||||||
|
page-break-after: avoid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ════════════════════════════
|
||||||
|
TABLES
|
||||||
|
════════════════════════════ */
|
||||||
|
.tbl-wrap {
|
||||||
|
margin-bottom: 22px;
|
||||||
|
/* Bungkus tabel agar tidak terpotong (berlaku jika tabel kecil) */
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
font-size: 9pt;
|
||||||
|
/* Header tabel muncul ulang di setiap halaman baru */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header tabel muncul di setiap halaman */
|
||||||
|
thead { display: table-header-group; }
|
||||||
|
tfoot { display: table-footer-group; }
|
||||||
|
|
||||||
|
th {
|
||||||
|
background: #e8f5e9;
|
||||||
|
color: #1b5e20;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 7px 6px;
|
||||||
|
text-align: left;
|
||||||
|
border: 1px solid #c8e6c9;
|
||||||
|
font-size: 8pt;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: .3px;
|
||||||
|
/* Judul kolom jangan terpotong */
|
||||||
|
page-break-inside: avoid;
|
||||||
|
break-inside: avoid;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 6px 6px;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
table { width: 100%; border-collapse: collapse; margin-bottom: 24px; font-size: 9.5pt; }
|
|
||||||
th { background: #e8f5e9; color: #2e7d32; font-weight: 700; padding: 8px 6px; text-align: left; border: 1px solid #c8e6c9; font-size: 8.5pt; text-transform: uppercase; letter-spacing: 0.3px; }
|
|
||||||
td { padding: 7px 6px; border: 1px solid #e0e0e0; }
|
|
||||||
tbody tr:nth-child(even) { background: #fafafa; }
|
tbody tr:nth-child(even) { background: #fafafa; }
|
||||||
tbody tr:hover { background: #f1f8e9; }
|
|
||||||
|
|
||||||
.progress-cell { width: 100px; }
|
/* KUNCI: setiap baris tabel tidak terpotong di tengah */
|
||||||
.prog-bar-mini { height: 8px; background: #e8e8e8; border-radius: 4px; overflow: hidden; }
|
tbody tr {
|
||||||
|
break-inside: avoid;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Progress bar mini ── */
|
||||||
|
.prog-bar-mini {
|
||||||
|
height: 7px;
|
||||||
|
background: #eee;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
min-width: 70px;
|
||||||
|
}
|
||||||
.prog-fill-mini { height: 100%; border-radius: 4px; }
|
.prog-fill-mini { height: 100%; border-radius: 4px; }
|
||||||
|
|
||||||
.badge-sm { display: inline-block; padding: 2px 8px; border-radius: 10px; font-size: 8pt; font-weight: 600; }
|
/* ── Badges ── */
|
||||||
|
.badge-sm {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 7px;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 8pt;
|
||||||
|
font-weight: 600;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
.badge-success { background: #e8f5e9; color: #2e7d32; }
|
.badge-success { background: #e8f5e9; color: #2e7d32; }
|
||||||
.badge-warning { background: #fff8e1; color: #f57f17; }
|
.badge-warning { background: #fff8e1; color: #f57f17; }
|
||||||
.badge-danger { background: #fbe9e7; color: #c62828; }
|
.badge-danger { background: #fbe9e7; color: #c62828; }
|
||||||
.badge-info { background: #e3f2fd; color: #1565c0; }
|
.badge-info { background: #e3f2fd; color: #1565c0; }
|
||||||
|
|
||||||
.comparison { font-size: 8.5pt; margin-top: 2px; }
|
/* ════════════════════════════
|
||||||
.comp-up { color: #2e7d32; } .comp-down { color: #c62828; } .comp-same { color: #999; }
|
CATATAN BOX
|
||||||
|
════════════════════════════ */
|
||||||
|
.catatan-section {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 22px;
|
||||||
|
break-inside: avoid;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
.catatan-box {
|
||||||
|
background: #f7faf8;
|
||||||
|
border: 1px solid #dde8e3;
|
||||||
|
border-radius: 7px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
break-inside: avoid;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
.catatan-box h4 { font-size: 9pt; color: #555; margin-bottom: 8px; font-weight: 600; }
|
||||||
|
.catatan-line { border-bottom: 1px dotted #ccc; height: 22px; }
|
||||||
|
|
||||||
.kategori-section { margin-bottom: 20px; }
|
/* ════════════════════════════
|
||||||
.kategori-header { display: flex; justify-content: space-between; align-items: center; padding: 8px 12px; border-radius: 6px; margin-bottom: 8px; }
|
TANDA TANGAN
|
||||||
.kat-alquran { background: linear-gradient(90deg, #e8f5e9, #f1f8e9); }
|
════════════════════════════ */
|
||||||
.kat-hadist { background: linear-gradient(90deg, #e3f2fd, #e8f4fd); }
|
.ttd-section {
|
||||||
.kat-tambahan { background: linear-gradient(90deg, #fffde7, #fff8e1); }
|
display: flex;
|
||||||
|
justify-content: flex-end; /* dorong ke kanan */
|
||||||
|
margin-top: 24px;
|
||||||
|
break-inside: avoid;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
.ttd-inner {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 32px;
|
||||||
|
min-width: 360px;
|
||||||
|
}
|
||||||
|
.ttd-col { text-align: center; }
|
||||||
|
.ttd-col .ttd-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.ttd-col .ttd-kota { font-size: 9pt; color: #555; }
|
||||||
|
.ttd-col .ttd-menget { font-size: 9pt; color: #555; }
|
||||||
|
.ttd-col .ttd-space { height: 56px; }
|
||||||
|
.ttd-col .ttd-line {
|
||||||
|
border-top: 1px solid #333;
|
||||||
|
display: block;
|
||||||
|
padding-top: 4px;
|
||||||
|
font-size: 9pt;
|
||||||
|
color: #555;
|
||||||
|
letter-spacing: .5px;
|
||||||
|
}
|
||||||
|
|
||||||
.catatan-box { background: #f5f8f6; border: 1px solid #e0e0e0; border-radius: 8px; padding: 16px; margin-bottom: 24px; }
|
/* ════════════════════════════
|
||||||
.catatan-box h4 { font-size: 10pt; color: #555; margin-bottom: 8px; }
|
FOOTER
|
||||||
.catatan-lines { min-height: 60px; }
|
════════════════════════════ */
|
||||||
.catatan-line { border-bottom: 1px dotted #ccc; height: 24px; }
|
.rapor-footer {
|
||||||
|
text-align: center;
|
||||||
.footer { text-align: center; padding-top: 20px; border-top: 2px solid #e0e0e0; margin-top: 30px; font-size: 9pt; color: #999; }
|
padding-top: 16px;
|
||||||
|
margin-top: 20px;
|
||||||
.print-btn { position: fixed; bottom: 20px; right: 20px; background: #6FBA9D; color: #fff; border: none; padding: 12px 24px; border-radius: 8px; font-size: 11pt; font-weight: 600; cursor: pointer; box-shadow: 0 4px 12px rgba(111,186,157,0.4); z-index: 999; }
|
border-top: 1px solid #e0e0e0;
|
||||||
.print-btn:hover { background: #5EA98C; }
|
font-size: 8.5pt;
|
||||||
|
color: #aaa;
|
||||||
|
break-inside: avoid;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ════════════════════════════
|
||||||
|
PRINT RULES
|
||||||
|
════════════════════════════ */
|
||||||
@media print {
|
@media print {
|
||||||
body { padding: 10mm; }
|
body { background: #fff; }
|
||||||
.print-btn { display: none !important; }
|
|
||||||
|
/*
|
||||||
|
* margin: 0 di @page menghilangkan area header/footer bawaan browser
|
||||||
|
* (tempat browser mencetak URL, judul, tanggal).
|
||||||
|
* Padding halaman ditangani oleh .page-wrap.
|
||||||
|
*/
|
||||||
|
@page {
|
||||||
|
size: A4 portrait;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-wrap { padding: 10mm 12mm; max-width: 100%; }
|
||||||
|
|
||||||
|
.print-btn,
|
||||||
.no-print { display: none !important; }
|
.no-print { display: none !important; }
|
||||||
@page { margin: 10mm; size: A4; }
|
|
||||||
|
/* Pastikan bagian-bagian penting tidak terpotong */
|
||||||
|
.rapor-header,
|
||||||
|
.info-grid,
|
||||||
|
.summary-row,
|
||||||
|
.section-title,
|
||||||
|
.catatan-section,
|
||||||
|
.catatan-box,
|
||||||
|
.ttd-section,
|
||||||
|
.rapor-footer { break-inside: avoid; page-break-inside: avoid; }
|
||||||
|
|
||||||
|
/* Tabel boleh melintasi halaman TAPI baris tidak boleh terpotong */
|
||||||
|
table { break-inside: auto; page-break-inside: auto; }
|
||||||
|
thead { display: table-header-group; }
|
||||||
|
tbody tr {
|
||||||
|
break-inside: avoid !important;
|
||||||
|
page-break-inside: avoid !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Judul section tidak boleh tertinggal sendirian di bawah halaman */
|
||||||
|
.section-title {
|
||||||
|
break-after: avoid !important;
|
||||||
|
page-break-after: avoid !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<button class="print-btn no-print" onclick="window.print()">
|
<button class="print-btn no-print" onclick="window.print()">
|
||||||
<i>🖨️</i> Cetak / Simpan PDF
|
🖨️ Cetak / Simpan PDF
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{{-- HEADER --}}
|
<div class="page-wrap">
|
||||||
|
|
||||||
|
{{-- ── HEADER ── --}}
|
||||||
<div class="rapor-header">
|
<div class="rapor-header">
|
||||||
<h1>RAPOR CAPAIAN AL-QUR'AN & HADIST</h1>
|
<h1>CAPAIAN MATERI</h1>
|
||||||
<h2>Pondok Pesantren PKPPS</h2>
|
<h2>Pondok Pesantren Riyadlul Jannah</h2>
|
||||||
<div class="subtitle">{{ $semester->nama_semester }} — Tahun Ajaran {{ $semester->tahun_ajaran }}</div>
|
<div class="subtitle">{{ $semester->nama_semester }} — Tahun Ajaran {{ $semester->tahun_ajaran }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- INFO SANTRI --}}
|
{{-- ── INFO SANTRI ── --}}
|
||||||
<div class="info-grid">
|
<div class="info-grid">
|
||||||
<div class="info-item"><span class="label">Nama Lengkap</span><span class="value">{{ $santri->nama_lengkap }}</span></div>
|
<div class="info-item"><span class="label">Nama Lengkap</span><span class="value">{{ $santri->nama_lengkap }}</span></div>
|
||||||
<div class="info-item"><span class="label">NIS</span><span class="value">{{ $santri->nis }}</span></div>
|
<div class="info-item"><span class="label">NIS</span><span class="value">{{ $santri->nis }}</span></div>
|
||||||
<div class="info-item"><span class="label">Kelas</span><span class="value">{{ $santri->kelas }}</span></div>
|
<div class="info-item"><span class="label">Kelas</span><span class="value">{{ $santri->kelas }}</span></div>
|
||||||
<div class="info-item"><span class="label">Status</span><span class="value">{{ $santri->status }}</span></div>
|
<div class="info-item"><span class="label">Status</span><span class="value">{{ $santri->status }}</span></div>
|
||||||
<div class="info-item"><span class="label">Semester</span><span class="value">{{ $semester->nama_semester }}</span></div>
|
<div class="info-item"><span class="label">Semester</span><span class="value">{{ $semester->nama_semester }}</span></div>
|
||||||
<div class="info-item"><span class="label">Tanggal Cetak</span> <span class="value">{{ now()->format('d F Y') }}</span></div>
|
<div class="info-item"><span class="label">Tanggal Cetak</span><span class="value">{{ now()->translatedFormat('d F Y') }}</span></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- SUMMARY --}}
|
{{-- ── SUMMARY ── --}}
|
||||||
<div class="summary-row">
|
<div class="summary-row">
|
||||||
<div class="summary-box sb-green">
|
<div class="summary-box sb-green">
|
||||||
<div class="sb-val">{{ number_format($avgProgress, 1) }}%</div>
|
<div class="sb-val">{{ number_format($avgProgress, 1) }}%</div>
|
||||||
<div class="sb-label">Rata-rata Progress</div>
|
<div class="sb-label">Rata-rata Progress</div>
|
||||||
@if($prevSemester)
|
@if($prevSemester)
|
||||||
<div class="comparison {{ $avgProgress >= $avgPrev ? 'comp-up' : 'comp-down' }}">
|
@php $delta = $avgProgress - $avgPrev; @endphp
|
||||||
{{ $avgProgress >= $avgPrev ? '▲' : '▼' }} {{ number_format(abs($avgProgress - $avgPrev), 1) }}% dari {{ $prevSemester->nama_semester }}
|
<div class="sb-comp {{ $delta >= 0 ? 'comp-up' : 'comp-down' }}">
|
||||||
|
{{ $delta >= 0 ? '▲' : '▼' }} {{ number_format(abs($delta), 1) }}%
|
||||||
|
<span style="font-size:7.5pt;color:#999;display:block;">dari {{ $prevSemester->nama_semester }}</span>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -124,21 +372,23 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- PROGRESS PER KATEGORI --}}
|
{{-- ── RINGKASAN PER KATEGORI ── --}}
|
||||||
<h3>Ringkasan Per Kategori</h3>
|
<div class="section-title">Ringkasan Per Kategori</div>
|
||||||
|
<div class="tbl-wrap">
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Kategori</th>
|
<th style="width:28%;">Kategori</th>
|
||||||
<th style="text-align:center;">Jumlah Materi</th>
|
<th style="width:12%;text-align:center;">Jml Materi</th>
|
||||||
<th style="text-align:center;">Selesai</th>
|
<th style="width:10%;text-align:center;">Selesai</th>
|
||||||
<th style="text-align:center;">Rata-rata Progress</th>
|
<th style="width:18%;text-align:center;">Rata-rata Progress</th>
|
||||||
<th style="text-align:center;">Semester Lalu</th>
|
<th style="width:15%;text-align:center;">Semester Lalu</th>
|
||||||
<th style="text-align:center;">Perubahan</th>
|
<th style="width:17%;text-align:center;">Perubahan</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach($perKategori as $kat => $data)
|
@foreach($perKategori as $kat => $data)
|
||||||
|
@php $change = $data['avg'] - $data['prev']; @endphp
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{{ $kat }}</strong></td>
|
<td><strong>{{ $kat }}</strong></td>
|
||||||
<td style="text-align:center;">{{ $data['count'] }}</td>
|
<td style="text-align:center;">{{ $data['count'] }}</td>
|
||||||
|
|
@ -150,7 +400,6 @@
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:center;">{{ number_format($data['prev'], 1) }}%</td>
|
<td style="text-align:center;">{{ number_format($data['prev'], 1) }}%</td>
|
||||||
<td style="text-align:center;">
|
<td style="text-align:center;">
|
||||||
@php $change = $data['avg'] - $data['prev']; @endphp
|
|
||||||
<span class="{{ $change > 0 ? 'comp-up' : ($change < 0 ? 'comp-down' : 'comp-same') }}">
|
<span class="{{ $change > 0 ? 'comp-up' : ($change < 0 ? 'comp-down' : 'comp-same') }}">
|
||||||
{{ $change > 0 ? '+' : '' }}{{ number_format($change, 1) }}%
|
{{ $change > 0 ? '+' : '' }}{{ number_format($change, 1) }}%
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -159,20 +408,22 @@
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{-- DETAIL PER MATERI --}}
|
{{-- ── DETAIL PER MATERI ── --}}
|
||||||
<h3>Detail Progress Per Materi</h3>
|
<div class="section-title">Detail Progress Per Materi</div>
|
||||||
|
<div class="tbl-wrap">
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width:5%;">No</th>
|
<th style="width:4%;text-align:center;">No</th>
|
||||||
<th style="width:25%;">Nama Materi</th>
|
<th style="width:24%;">Nama Materi</th>
|
||||||
<th style="width:12%;">Kategori</th>
|
<th style="width:13%;">Kategori</th>
|
||||||
<th style="width:10%;">Halaman</th>
|
<th style="width:9%;text-align:center;">Halaman</th>
|
||||||
<th class="progress-cell" style="width:15%;">Progress</th>
|
<th style="width:14%;">Progress</th>
|
||||||
<th style="width:10%;">Persentase</th>
|
<th style="width:9%;text-align:center;">%</th>
|
||||||
<th style="width:10%;">Sem. Lalu</th>
|
<th style="width:12%;text-align:center;">Sem. Lalu</th>
|
||||||
<th style="width:13%;">Catatan</th>
|
<th style="width:15%;">Catatan</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
@ -181,85 +432,74 @@
|
||||||
$prevCap = $prevCapaians->where('id_materi', $cap->id_materi)->first();
|
$prevCap = $prevCapaians->where('id_materi', $cap->id_materi)->first();
|
||||||
$prevPct = $prevCap ? floatval($prevCap->persentase) : 0;
|
$prevPct = $prevCap ? floatval($prevCap->persentase) : 0;
|
||||||
$changePct = floatval($cap->persentase) - $prevPct;
|
$changePct = floatval($cap->persentase) - $prevPct;
|
||||||
|
$pct = min(floatval($cap->persentase), 100);
|
||||||
|
$barColor = $pct >= 80 ? '#66bb6a' : ($pct >= 50 ? '#ffa726' : '#ef5350');
|
||||||
|
$pctColor = $pct >= 100 ? '#2e7d32' : ($pct >= 50 ? '#f57f17' : '#c62828');
|
||||||
@endphp
|
@endphp
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align:center;">{{ $idx + 1 }}</td>
|
<td style="text-align:center;">{{ $idx + 1 }}</td>
|
||||||
<td><strong>{{ $cap->materi->nama_kitab }}</strong></td>
|
<td><strong>{{ $cap->materi->nama_kitab }}</strong></td>
|
||||||
<td>
|
<td>
|
||||||
<span class="badge-sm {{ $cap->materi->kategori == 'Al-Qur\'an' ? 'badge-success' : ($cap->materi->kategori == 'Hadist' ? 'badge-info' : 'badge-warning') }}">
|
<span class="badge-sm {{ $cap->materi->kategori === "Al-Qur'an" ? 'badge-success' : ($cap->materi->kategori === 'Hadist' ? 'badge-info' : 'badge-warning') }}">
|
||||||
{{ $cap->materi->kategori }}
|
{{ $cap->materi->kategori }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td style="font-size:8.5pt;">{{ $cap->halaman_selesai ?: '-' }}</td>
|
<td style="text-align:center;font-size:8.5pt;">{{ $cap->halaman_selesai ?: '—' }}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="prog-bar-mini">
|
<div class="prog-bar-mini">
|
||||||
<div class="prog-fill-mini" style="width:{{ min($cap->persentase, 100) }}%;background:{{ $cap->persentase >= 80 ? '#66bb6a' : ($cap->persentase >= 50 ? '#ffa726' : '#ef5350') }};"></div>
|
<div class="prog-fill-mini" style="width:{{ $pct }}%;background:{{ $barColor }};"></div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:center;">
|
<td style="text-align:center;">
|
||||||
<strong style="color:{{ $cap->persentase >= 100 ? '#2e7d32' : ($cap->persentase >= 50 ? '#f57f17' : '#c62828') }};">
|
<strong style="color:{{ $pctColor }};">{{ number_format($cap->persentase, 1) }}%</strong>
|
||||||
{{ number_format($cap->persentase, 1) }}%
|
|
||||||
</strong>
|
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:center;">
|
<td style="text-align:center;">
|
||||||
{{ number_format($prevPct, 1) }}%
|
{{ number_format($prevPct, 1) }}%
|
||||||
<div class="{{ $changePct > 0 ? 'comp-up' : ($changePct < 0 ? 'comp-down' : 'comp-same') }}" style="font-size:8pt;">
|
<div class="{{ $changePct > 0 ? 'comp-up' : ($changePct < 0 ? 'comp-down' : 'comp-same') }}" style="font-size:7.5pt;">
|
||||||
{{ $changePct > 0 ? '+' : '' }}{{ number_format($changePct, 1) }}%
|
{{ $changePct > 0 ? '+' : '' }}{{ number_format($changePct, 1) }}%
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td style="font-size:8pt;">{{ $cap->catatan ?: '-' }}</td>
|
<td style="font-size:8pt;color:#555;">{{ $cap->catatan ?: '—' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="8" style="text-align:center;color:#999;padding:20px;">Belum ada data capaian untuk semester ini</td>
|
<td colspan="8" style="text-align:center;color:#999;padding:18px;">
|
||||||
|
Belum ada data capaian untuk semester ini.
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{-- CATATAN & REKOMENDASI --}}
|
{{-- ── CATATAN & TARGET ── --}}
|
||||||
|
<div class="catatan-section">
|
||||||
<div class="catatan-box">
|
<div class="catatan-box">
|
||||||
<h4>Catatan / Rekomendasi Ustadz:</h4>
|
<h4>Catatan / Rekomendasi Ustadz:</h4>
|
||||||
<div class="catatan-lines">
|
|
||||||
<div class="catatan-line"></div>
|
<div class="catatan-line"></div>
|
||||||
<div class="catatan-line"></div>
|
<div class="catatan-line"></div>
|
||||||
<div class="catatan-line"></div>
|
<div class="catatan-line"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- TARGET SEMESTER DEPAN --}}
|
|
||||||
<div class="catatan-box">
|
<div class="catatan-box">
|
||||||
<h4>Target Semester Depan:</h4>
|
<h4>Target Semester Depan:</h4>
|
||||||
<div class="catatan-lines">
|
<div class="catatan-line"></div>
|
||||||
<div class="catatan-line"></div>
|
<div class="catatan-line"></div>
|
||||||
<div class="catatan-line"></div>
|
<div class="catatan-line"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- TANDA TANGAN --}}
|
{{-- ── TANDA TANGAN ── --}}
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:40px;margin-top:30px;">
|
<div class="ttd-section">
|
||||||
<div style="text-align:center;">
|
<div style="display:flex; justify-content:flex-end;">
|
||||||
<div style="font-size:9pt;color:#555;">Mengetahui,</div>
|
<div class="ttd-col">
|
||||||
<div style="font-size:10pt;font-weight:600;margin-top:4px;">Pimpinan Pondok</div>
|
<div style="font-size:9pt;color:#555;">Mengetahui, ...............................</div>
|
||||||
<div style="height:60px;"></div>
|
<div class="ttd-space"></div>
|
||||||
<div style="border-top:1px solid #333;display:inline-block;padding-top:4px;min-width:180px;font-size:9.5pt;">
|
<div class=>( ................................................ )</div>
|
||||||
(.................................)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="text-align:center;">
|
|
||||||
<div style="font-size:9pt;color:#555;">{{ now()->format('d F Y') }}</div>
|
|
||||||
<div style="font-size:10pt;font-weight:600;margin-top:4px;">Ustadz Pengampu</div>
|
|
||||||
<div style="height:60px;"></div>
|
|
||||||
<div style="border-top:1px solid #333;display:inline-block;padding-top:4px;min-width:180px;font-size:9.5pt;">
|
|
||||||
(.................................)
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- FOOTER --}}
|
</div>{{-- /page-wrap --}}
|
||||||
<div class="footer">
|
|
||||||
Rapor ini dicetak secara otomatis oleh Sistem Informasi Manajemen PKPPS pada {{ now()->format('d F Y H:i') }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- 2 panel grid --}}
|
{{-- 2 panel grid --}}
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:16px;">
|
<div class="dash-fin-grid">
|
||||||
|
|
||||||
{{-- ── Panel Kiri: Status SPP ── --}}
|
{{-- ── Panel Kiri: Status SPP ── --}}
|
||||||
<div class="content-box" style="display:flex;flex-direction:column;gap:0;">
|
<div class="content-box" style="display:flex;flex-direction:column;gap:0;">
|
||||||
|
|
@ -93,15 +93,15 @@
|
||||||
{{-- Quick links --}}
|
{{-- Quick links --}}
|
||||||
<div style="display:flex;gap:6px;flex-wrap:wrap;margin-top:auto;">
|
<div style="display:flex;gap:6px;flex-wrap:wrap;margin-top:auto;">
|
||||||
<a href="{{ route('admin.pembayaran-spp.index', ['tab'=>'belum-bayar','bulan'=>date('n'),'tahun'=>date('Y')]) }}"
|
<a href="{{ route('admin.pembayaran-spp.index', ['tab'=>'belum-bayar','bulan'=>date('n'),'tahun'=>date('Y')]) }}"
|
||||||
class="btn btn-danger btn-sm" style="flex:1;justify-content:center;">
|
class="btn btn-danger btn-sm" style="flex:1 1 0;min-width:0;justify-content:center;">
|
||||||
<i class="fas fa-exclamation-circle"></i> Belum ({{ $spp['belum'] ?? 0 }})
|
<i class="fas fa-exclamation-circle"></i> Belum ({{ $spp['belum'] ?? 0 }})
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ route('admin.pembayaran-spp.generate') }}"
|
<a href="{{ route('admin.pembayaran-spp.generate') }}"
|
||||||
class="btn btn-warning btn-sm" style="flex:1;justify-content:center;">
|
class="btn btn-warning btn-sm" style="flex:1 1 0;min-width:0;justify-content:center;">
|
||||||
<i class="fas fa-cogs"></i> Generate
|
<i class="fas fa-cogs"></i> Generate
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ route('admin.pembayaran-spp.index', ['tab'=>'sudah-bayar','bulan'=>date('n'),'tahun'=>date('Y')]) }}"
|
<a href="{{ route('admin.pembayaran-spp.index', ['tab'=>'sudah-bayar','bulan'=>date('n'),'tahun'=>date('Y')]) }}"
|
||||||
class="btn btn-success btn-sm" style="flex:1;justify-content:center;">
|
class="btn btn-success btn-sm" style="flex:1 1 0;min-width:0;justify-content:center;">
|
||||||
<i class="fas fa-check-circle"></i> Lunas ({{ $spp['lunas'] ?? 0 }})
|
<i class="fas fa-check-circle"></i> Lunas ({{ $spp['lunas'] ?? 0 }})
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -178,13 +178,13 @@ class="btn btn-success btn-sm" style="flex:1;justify-content:center;">
|
||||||
<div style="padding:11px 14px;border-radius:var(--border-radius-sm);margin-bottom:14px;
|
<div style="padding:11px 14px;border-radius:var(--border-radius-sm);margin-bottom:14px;
|
||||||
background:{{ $sisaKas >= 0 ? 'linear-gradient(135deg,#E8F7F2,#D4F1E3)' : 'linear-gradient(135deg,#FFE8EA,#FFD5D8)' }};
|
background:{{ $sisaKas >= 0 ? 'linear-gradient(135deg,#E8F7F2,#D4F1E3)' : 'linear-gradient(135deg,#FFE8EA,#FFD5D8)' }};
|
||||||
border-left:4px solid {{ $sisaKas >= 0 ? 'var(--success-color)' : 'var(--danger-color)' }};
|
border-left:4px solid {{ $sisaKas >= 0 ? 'var(--success-color)' : 'var(--danger-color)' }};
|
||||||
display:flex;justify-content:space-between;align-items:center;">
|
display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:6px;">
|
||||||
<span style="font-size:.75rem;font-weight:700;color:var(--text-color);display:flex;align-items:center;gap:6px;">
|
<span style="font-size:.75rem;font-weight:700;color:var(--text-color);display:flex;align-items:center;gap:6px;">
|
||||||
<i class="fas fa-{{ $sisaKas >= 0 ? 'piggy-bank' : 'exclamation-triangle' }}"
|
<i class="fas fa-{{ $sisaKas >= 0 ? 'piggy-bank' : 'exclamation-triangle' }}"
|
||||||
style="color:{{ $sisaKas >= 0 ? 'var(--success-color)' : 'var(--danger-color)' }};"></i>
|
style="color:{{ $sisaKas >= 0 ? 'var(--success-color)' : 'var(--danger-color)' }};"></i>
|
||||||
Sisa Kas Bulan Ini
|
Sisa Kas Bulan Ini
|
||||||
</span>
|
</span>
|
||||||
<strong style="font-size:1rem;font-weight:800;color:{{ $sisaKas >= 0 ? 'var(--success-color)' : 'var(--danger-color)' }};">
|
<strong style="font-size:1rem;font-weight:800;color:{{ $sisaKas >= 0 ? 'var(--success-color)' : 'var(--danger-color)' }};word-break:break-all;">
|
||||||
{{ $sisaKas >= 0 ? '+' : '' }}Rp {{ number_format($sisaKas,0,',','.') }}
|
{{ $sisaKas >= 0 ? '+' : '' }}Rp {{ number_format($sisaKas,0,',','.') }}
|
||||||
</strong>
|
</strong>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -192,11 +192,11 @@ class="btn btn-success btn-sm" style="flex:1;justify-content:center;">
|
||||||
{{-- Quick links --}}
|
{{-- Quick links --}}
|
||||||
<div style="display:flex;gap:6px;flex-wrap:wrap;margin-top:auto;">
|
<div style="display:flex;gap:6px;flex-wrap:wrap;margin-top:auto;">
|
||||||
<a href="{{ route('admin.keuangan.index') }}"
|
<a href="{{ route('admin.keuangan.index') }}"
|
||||||
class="btn btn-info btn-sm" style="flex:1;justify-content:center;">
|
class="btn btn-info btn-sm" style="flex:1 1 0;min-width:0;justify-content:center;">
|
||||||
<i class="fas fa-book-open"></i> Buku Kas
|
<i class="fas fa-book-open"></i> Buku Kas
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ route('admin.keuangan.laporan', ['bulan'=>date('n'),'tahun'=>date('Y')]) }}"
|
<a href="{{ route('admin.keuangan.laporan', ['bulan'=>date('n'),'tahun'=>date('Y')]) }}"
|
||||||
class="btn btn-warning btn-sm" style="flex:1;justify-content:center;">
|
class="btn btn-warning btn-sm" style="flex:1 1 0;min-width:0;justify-content:center;">
|
||||||
<i class="fas fa-chart-bar"></i> Laporan
|
<i class="fas fa-chart-bar"></i> Laporan
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -42,16 +42,11 @@
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.dash-fin-grid { grid-template-columns: 1fr; }
|
.dash-fin-grid { grid-template-columns: 1fr; }
|
||||||
}
|
}
|
||||||
@media (max-width: 1024px) {
|
|
||||||
.row-cards-5 { grid-template-columns: repeat(3,1fr); }
|
|
||||||
}
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
.row-cards-5 { grid-template-columns: repeat(2,1fr); }
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
{{-- ───────── 1. KPI CARDS ───────── --}}
|
{{-- ───────── 1. KPI CARDS ───────── --}}
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ class="btn btn-sm btn-success"
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ============================================================ --}}
|
{{-- ============================================================ --}}
|
||||||
{{-- 2. DAY TABS (Senin - Ahad) --}}
|
{{-- 2. DAY TABS --}}
|
||||||
{{-- ============================================================ --}}
|
{{-- ============================================================ --}}
|
||||||
<div class="content-box">
|
<div class="content-box">
|
||||||
<div class="day-tabs">
|
<div class="day-tabs">
|
||||||
|
|
@ -122,9 +122,7 @@ class="day-tab {{ $isActive ? 'active' : '' }} {{ $isToday ? 'today-tab' : '' }}
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ======================================================== --}}
|
{{-- FILTER BAR --}}
|
||||||
{{-- 3. FILTER BAR (Tanggal + Kategori + Kelas + Aksi) --}}
|
|
||||||
{{-- ======================================================== --}}
|
|
||||||
<form method="GET" action="{{ route('admin.kegiatan.index') }}" id="filterForm" class="filter-form-inline" style="margin-top: 10px;">
|
<form method="GET" action="{{ route('admin.kegiatan.index') }}" id="filterForm" class="filter-form-inline" style="margin-top: 10px;">
|
||||||
<input type="hidden" name="kelas" id="kelasInput" value="{{ $selectedKelasId }}">
|
<input type="hidden" name="kelas" id="kelasInput" value="{{ $selectedKelasId }}">
|
||||||
|
|
||||||
|
|
@ -179,20 +177,11 @@ class="day-tab {{ $isActive ? 'active' : '' }} {{ $isToday ? 'today-tab' : '' }}
|
||||||
<button type="button" class="btn btn-sm btn-secondary" onclick="nextDay()">
|
<button type="button" class="btn btn-sm btn-secondary" onclick="nextDay()">
|
||||||
<i class="fas fa-chevron-right"></i>
|
<i class="fas fa-chevron-right"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{{-- <div style="margin-left: auto; display: flex; gap: 8px;">
|
|
||||||
<a href="{{ route('admin.kategori-kegiatan.index') }}" class="btn btn-info btn-sm">
|
|
||||||
<i class="fas fa-tags"></i> Kategori
|
|
||||||
</a>
|
|
||||||
<a href="{{ route('admin.kegiatan.jadwal') }}" class="btn btn-info btn-sm">
|
|
||||||
<i class="fas fa-list"></i> Semua Jadwal
|
|
||||||
</a>
|
|
||||||
</div> --}}
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ============================================================ --}}
|
{{-- ============================================================ --}}
|
||||||
{{-- 4. INSIGHTS PANEL --}}
|
{{-- 3. INSIGHTS PANEL --}}
|
||||||
{{-- ============================================================ --}}
|
{{-- ============================================================ --}}
|
||||||
@if(count($insights) > 0)
|
@if(count($insights) > 0)
|
||||||
<div class="content-box" style="margin-top: 14px;">
|
<div class="content-box" style="margin-top: 14px;">
|
||||||
|
|
@ -218,7 +207,7 @@ class="day-tab {{ $isActive ? 'active' : '' }} {{ $isToday ? 'today-tab' : '' }}
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
{{-- ============================================================ --}}
|
{{-- ============================================================ --}}
|
||||||
{{-- 5. MAIN LAYOUT: Kegiatan Cards (2/3) + Heatmap (1/3) --}}
|
{{-- 4. MAIN LAYOUT: Kegiatan Cards + Heatmap --}}
|
||||||
{{-- ============================================================ --}}
|
{{-- ============================================================ --}}
|
||||||
<div class="layout-kegiatan" style="margin-top: 14px;">
|
<div class="layout-kegiatan" style="margin-top: 14px;">
|
||||||
|
|
||||||
|
|
@ -227,6 +216,21 @@ class="day-tab {{ $isActive ? 'active' : '' }} {{ $isToday ? 'today-tab' : '' }}
|
||||||
@if($kegiatanHariIni->count() > 0)
|
@if($kegiatanHariIni->count() > 0)
|
||||||
<div class="kegiatan-list">
|
<div class="kegiatan-list">
|
||||||
@foreach($kegiatanHariIni as $kegiatan)
|
@foreach($kegiatanHariIni as $kegiatan)
|
||||||
|
@php
|
||||||
|
$persen = $kegiatan->persen_kehadiran;
|
||||||
|
$totalSantri = $kegiatan->total_santri_kegiatan;
|
||||||
|
$totalHadir = $kegiatan->total_hadir; // hadir + terlambat
|
||||||
|
$totalInput = $kegiatan->total_absensi; // sudah diinput (semua status)
|
||||||
|
$belumAbsen = $kegiatan->belum_absen; // belum diinput sama sekali
|
||||||
|
$terlambat = $kegiatan->total_terlambat;
|
||||||
|
$isUmum = $kegiatan->kelasKegiatan->isEmpty();
|
||||||
|
|
||||||
|
// Warna progress bar
|
||||||
|
$pClass = $persen >= 85 ? 'p-success' : ($persen >= 70 ? 'p-warning' : ($persen >= 50 ? 'p-orange' : 'p-danger'));
|
||||||
|
|
||||||
|
// Hitung per kelas: sudah input berapa
|
||||||
|
$infoPerKelas = $kegiatan->info_per_kelas ?? collect();
|
||||||
|
@endphp
|
||||||
<div class="kegiatan-card">
|
<div class="kegiatan-card">
|
||||||
<div class="kegiatan-card-header">
|
<div class="kegiatan-card-header">
|
||||||
<div class="kegiatan-info">
|
<div class="kegiatan-info">
|
||||||
|
|
@ -252,7 +256,7 @@ class="day-tab {{ $isActive ? 'active' : '' }} {{ $isToday ? 'today-tab' : '' }}
|
||||||
@endif
|
@endif
|
||||||
<span>
|
<span>
|
||||||
<i class="fas fa-layer-group"></i>
|
<i class="fas fa-layer-group"></i>
|
||||||
@if($kegiatan->kelasKegiatan->isEmpty())
|
@if($isUmum)
|
||||||
<span class="badge badge-secondary">Kegiatan Umum</span>
|
<span class="badge badge-secondary">Kegiatan Umum</span>
|
||||||
@else
|
@else
|
||||||
{{ $kegiatan->kelasKegiatan->pluck('nama_kelas')->implode(', ') }}
|
{{ $kegiatan->kelasKegiatan->pluck('nama_kelas')->implode(', ') }}
|
||||||
|
|
@ -271,29 +275,147 @@ class="day-tab {{ $isActive ? 'active' : '' }} {{ $isToday ? 'today-tab' : '' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Progress Bar --}}
|
{{-- ============================================ --}}
|
||||||
@php
|
{{-- PROGRESS KEHADIRAN — DIPERBAIKI --}}
|
||||||
$persen = $kegiatan->persen_kehadiran;
|
{{-- ============================================ --}}
|
||||||
$pClass = $persen >= 85 ? 'p-success' : ($persen >= 70 ? 'p-warning' : ($persen >= 50 ? 'p-orange' : 'p-danger'));
|
|
||||||
$denominator = $kegiatan->total_absensi > 0 ? $kegiatan->total_absensi : $totalSantriAktif;
|
|
||||||
@endphp
|
|
||||||
<div class="kegiatan-progress">
|
<div class="kegiatan-progress">
|
||||||
<div class="kegiatan-progress-header">
|
|
||||||
|
{{-- Baris judul + angka utama --}}
|
||||||
|
<div class="kegiatan-progress-header" style="margin-bottom: 4px;">
|
||||||
<span style="font-weight: 500;">
|
<span style="font-weight: 500;">
|
||||||
<i class="fas fa-users"></i> Kehadiran
|
<i class="fas fa-users"></i> Kehadiran
|
||||||
|
{{-- Keterangan terlambat = hadir --}}
|
||||||
|
@if($terlambat > 0)
|
||||||
|
<span style="font-size: 0.78rem; color: #FF9800; font-weight: 400; margin-left: 4px;">
|
||||||
|
(termasuk {{ $terlambat }} terlambat)
|
||||||
</span>
|
</span>
|
||||||
<span style="font-weight: 700;">
|
@endif
|
||||||
{{ $kegiatan->total_hadir }}/{{ $denominator }}
|
</span>
|
||||||
({{ $persen }}%)
|
<span style="font-weight: 700; font-size: 1rem; color: {{ $persen >= 85 ? '#059669' : ($persen >= 70 ? '#d97706' : '#dc2626') }};">
|
||||||
|
{{ $totalHadir }}/{{ $totalSantri }} santri
|
||||||
|
<span style="font-size: 0.85rem;">({{ $persen }}%)</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="kegiatan-progress-bar">
|
|
||||||
<div class="kegiatan-progress-fill {{ $pClass }}"
|
{{-- Sub-info: sudah diinput vs belum --}}
|
||||||
data-width="{{ $persen }}">
|
<div style="display: flex; gap: 12px; margin-bottom: 6px; font-size: 0.78rem; flex-wrap: wrap;">
|
||||||
{{ $persen }}%
|
<span style="color: #059669;">
|
||||||
</div>
|
<i class="fas fa-check"></i>
|
||||||
|
Sudah diinput: <strong>{{ $totalInput }}</strong> santri
|
||||||
|
</span>
|
||||||
|
@if($belumAbsen > 0)
|
||||||
|
<span style="color: #dc2626;">
|
||||||
|
<i class="fas fa-hourglass-half"></i>
|
||||||
|
Belum absen: <strong>{{ $belumAbsen }}</strong> santri
|
||||||
|
</span>
|
||||||
|
@else
|
||||||
|
<span style="color: #059669;">
|
||||||
|
<i class="fas fa-check-double"></i>
|
||||||
|
Semua sudah diinput
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Progress bar multi-warna --}}
|
||||||
|
@php
|
||||||
|
$hadirMurni = $kegiatan->total_hadir_murni ?? ($totalHadir - $terlambat);
|
||||||
|
$alpa = $kegiatan->total_alpa ?? 0;
|
||||||
|
$izin = $kegiatan->total_izin ?? 0;
|
||||||
|
$sakit = $kegiatan->total_sakit ?? 0;
|
||||||
|
|
||||||
|
$pctHadir = $totalSantri > 0 ? round($hadirMurni / $totalSantri * 100) : 0;
|
||||||
|
$pctTlmbat = $totalSantri > 0 ? round($terlambat / $totalSantri * 100) : 0;
|
||||||
|
$pctIzin = $totalSantri > 0 ? round($izin / $totalSantri * 100) : 0;
|
||||||
|
$pctSakit = $totalSantri > 0 ? round($sakit / $totalSantri * 100) : 0;
|
||||||
|
$pctAlpa = $totalSantri > 0 ? round($alpa / $totalSantri * 100) : 0;
|
||||||
|
$pctBelum = $totalSantri > 0 ? round($belumAbsen / $totalSantri * 100) : 0;
|
||||||
|
@endphp
|
||||||
|
<div style="height: 22px; background: #f3f4f6; border-radius: 11px; overflow: hidden; display: flex; margin-bottom: 6px;">
|
||||||
|
@if($pctHadir > 0)
|
||||||
|
<div style="width:{{ $pctHadir }}%; background:#22c55e; display:flex; align-items:center; justify-content:center; color:white; font-size:0.7rem; font-weight:700;"
|
||||||
|
title="Hadir: {{ $hadirMurni }}">{{ $hadirMurni > 0 && $pctHadir > 5 ? $hadirMurni : '' }}</div>
|
||||||
|
@endif
|
||||||
|
@if($pctTlmbat > 0)
|
||||||
|
<div style="width:{{ $pctTlmbat }}%; background:#FF9800; display:flex; align-items:center; justify-content:center; color:white; font-size:0.7rem; font-weight:700;"
|
||||||
|
title="Terlambat : {{ $terlambat }}">{{ $terlambat > 0 && $pctTlmbat > 5 ? $terlambat : '' }}</div>
|
||||||
|
@endif
|
||||||
|
@if($pctIzin > 0)
|
||||||
|
<div style="width:{{ $pctIzin }}%; background:#f59e0b; display:flex; align-items:center; justify-content:center; color:white; font-size:0.7rem; font-weight:700;"
|
||||||
|
title="Izin: {{ $izin }}">{{ $izin > 0 && $pctIzin > 5 ? $izin : '' }}</div>
|
||||||
|
@endif
|
||||||
|
@if($pctSakit > 0)
|
||||||
|
<div style="width:{{ $pctSakit }}%; background:#3b82f6; display:flex; align-items:center; justify-content:center; color:white; font-size:0.7rem; font-weight:700;"
|
||||||
|
title="Sakit: {{ $sakit }}">{{ $sakit > 0 && $pctSakit > 5 ? $sakit : '' }}</div>
|
||||||
|
@endif
|
||||||
|
@if($pctAlpa > 0)
|
||||||
|
<div style="width:{{ $pctAlpa }}%; background:#ef4444; display:flex; align-items:center; justify-content:center; color:white; font-size:0.7rem; font-weight:700;"
|
||||||
|
title="Alpa: {{ $alpa }}">{{ $alpa > 0 && $pctAlpa > 5 ? $alpa : '' }}</div>
|
||||||
|
@endif
|
||||||
|
@if($pctBelum > 0)
|
||||||
|
<div style="width:{{ $pctBelum }}%; background:#d1d5db; display:flex; align-items:center; justify-content:center; color:#6b7280; font-size:0.7rem; font-weight:700;"
|
||||||
|
title="Belum absen: {{ $belumAbsen }}">{{ $belumAbsen > 0 && $pctBelum > 5 ? $belumAbsen : '' }}</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Legend bar --}}
|
||||||
|
<div style="display:flex; gap:10px; flex-wrap:wrap; font-size:0.72rem; color:#6b7280; margin-bottom: 6px;">
|
||||||
|
@if($hadirMurni > 0)
|
||||||
|
<span><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:#22c55e;margin-right:2px;"></span>Hadir</span>
|
||||||
|
@endif
|
||||||
|
@if($terlambat > 0)
|
||||||
|
<span><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:#FF9800;margin-right:2px;"></span>Terlambat</span>
|
||||||
|
@endif
|
||||||
|
@if($izin > 0)
|
||||||
|
<span><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:#f59e0b;margin-right:2px;"></span>Izin</span>
|
||||||
|
@endif
|
||||||
|
@if($sakit > 0)
|
||||||
|
<span><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:#3b82f6;margin-right:2px;"></span>Sakit</span>
|
||||||
|
@endif
|
||||||
|
@if($alpa > 0)
|
||||||
|
<span><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:#ef4444;margin-right:2px;"></span>Alpa</span>
|
||||||
|
@endif
|
||||||
|
@if($belumAbsen > 0)
|
||||||
|
<span><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:#d1d5db;margin-right:2px;"></span>Belum absen</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Info per kelas (khusus kegiatan dengan beberapa kelas) --}}
|
||||||
|
@if(!$isUmum && $infoPerKelas->count() > 1)
|
||||||
|
<div style="margin-top: 8px; padding: 8px 10px; background: #f8fafc; border-radius: 8px; border: 1px solid #e2e8f0;">
|
||||||
|
<div style="font-size: 0.75rem; font-weight: 600; color: #475569; margin-bottom: 5px;">
|
||||||
|
<i class="fas fa-school"></i> Status per Kelas:
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; flex-wrap: wrap; gap: 6px;">
|
||||||
|
@foreach($infoPerKelas as $infoKls)
|
||||||
|
@php
|
||||||
|
// Hitung santri kelas ini yg sudah diinput dari data absensis
|
||||||
|
$sudahKelas = $kegiatan->absensis->filter(function($ab) use ($infoKls) {
|
||||||
|
return ($ab->santri->kelas_name ?? '') === $infoKls['nama'];
|
||||||
|
})->count();
|
||||||
|
$totalKls = $infoKls['total_santri'];
|
||||||
|
$belumKls = max(0, $totalKls - $sudahKelas);
|
||||||
|
$sudahSemua = $belumKls === 0 && $totalKls > 0;
|
||||||
|
@endphp
|
||||||
|
<div style="display: flex; align-items: center; gap: 4px; padding: 3px 8px;
|
||||||
|
background: {{ $sudahSemua ? '#dcfce7' : ($sudahKelas > 0 ? '#fef9c3' : '#f1f5f9') }};
|
||||||
|
border: 1px solid {{ $sudahSemua ? '#86efac' : ($sudahKelas > 0 ? '#fde68a' : '#e2e8f0') }};
|
||||||
|
border-radius: 6px; font-size: 0.72rem;">
|
||||||
|
<i class="fas fa-{{ $sudahSemua ? 'check-circle' : ($sudahKelas > 0 ? 'minus-circle' : 'circle') }}"
|
||||||
|
style="color: {{ $sudahSemua ? '#16a34a' : ($sudahKelas > 0 ? '#ca8a04' : '#94a3b8') }};"></i>
|
||||||
|
<span style="font-weight: 600;">{{ $infoKls['nama'] }}</span>
|
||||||
|
<span style="color: #64748b;">
|
||||||
|
{{ $sudahKelas }}/{{ $totalKls }}
|
||||||
|
@if(!$sudahSemua && $belumKls > 0)
|
||||||
|
<span style="color: #dc2626;">({{ $belumKls }} belum)</span>
|
||||||
|
@endif
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
</div>{{-- end kegiatan-progress --}}
|
||||||
|
|
||||||
{{-- Actions --}}
|
{{-- Actions --}}
|
||||||
<div class="kegiatan-actions">
|
<div class="kegiatan-actions">
|
||||||
|
|
@ -338,7 +460,6 @@ class="btn btn-sm btn-secondary">
|
||||||
<span>Kalender Kehadiran</span>
|
<span>Kalender Kehadiran</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Month/Year Selector --}}
|
|
||||||
<div class="filter-form-inline" style="margin-bottom: 12px;">
|
<div class="filter-form-inline" style="margin-bottom: 12px;">
|
||||||
<button type="button" class="btn btn-sm btn-secondary" style="padding: 4px 8px;"
|
<button type="button" class="btn btn-sm btn-secondary" style="padding: 4px 8px;"
|
||||||
onclick="changeHeatmapMonth(-1)">
|
onclick="changeHeatmapMonth(-1)">
|
||||||
|
|
@ -418,7 +539,7 @@ class="btn btn-sm btn-secondary">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ============================================================ --}}
|
{{-- ============================================================ --}}
|
||||||
{{-- 6. MODAL DETAIL ABSENSI (AJAX) --}}
|
{{-- 5. MODAL DETAIL ABSENSI (AJAX) --}}
|
||||||
{{-- ============================================================ --}}
|
{{-- ============================================================ --}}
|
||||||
<div id="detailModal" class="modal-kegiatan">
|
<div id="detailModal" class="modal-kegiatan">
|
||||||
<div class="modal-kegiatan-panel">
|
<div class="modal-kegiatan-panel">
|
||||||
|
|
@ -439,14 +560,12 @@ class="btn btn-sm btn-secondary">
|
||||||
{{-- JAVASCRIPT --}}
|
{{-- JAVASCRIPT --}}
|
||||||
{{-- ============================================================ --}}
|
{{-- ============================================================ --}}
|
||||||
<script>
|
<script>
|
||||||
// -- Date Navigation --
|
|
||||||
function setToday() {
|
function setToday() {
|
||||||
var dateInput = document.querySelector('input[name="tanggal"]');
|
|
||||||
var now = new Date();
|
var now = new Date();
|
||||||
var y = now.getFullYear();
|
var y = now.getFullYear();
|
||||||
var m = ('0' + (now.getMonth() + 1)).slice(-2);
|
var m = ('0' + (now.getMonth() + 1)).slice(-2);
|
||||||
var d = ('0' + now.getDate()).slice(-2);
|
var d = ('0' + now.getDate()).slice(-2);
|
||||||
dateInput.value = y + '-' + m + '-' + d;
|
document.querySelector('input[name="tanggal"]').value = y + '-' + m + '-' + d;
|
||||||
document.getElementById('filterForm').submit();
|
document.getElementById('filterForm').submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -469,7 +588,6 @@ function goToDate(date) {
|
||||||
document.getElementById('filterForm').submit();
|
document.getElementById('filterForm').submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Show Detail Modal (AJAX) --
|
|
||||||
function showDetailModal(kegiatanId, tanggal) {
|
function showDetailModal(kegiatanId, tanggal) {
|
||||||
var modal = document.getElementById('detailModal');
|
var modal = document.getElementById('detailModal');
|
||||||
var modalBody = document.getElementById('modalBody');
|
var modalBody = document.getElementById('modalBody');
|
||||||
|
|
@ -479,7 +597,7 @@ function showDetailModal(kegiatanId, tanggal) {
|
||||||
var url = baseUrl.replace(':id', kegiatanId) + '?tanggal=' + tanggal;
|
var url = baseUrl.replace(':id', kegiatanId) + '?tanggal=' + tanggal;
|
||||||
|
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(function(response) { return response.text(); })
|
.then(function(r) { return r.text(); })
|
||||||
.then(function(html) { modalBody.innerHTML = html; })
|
.then(function(html) { modalBody.innerHTML = html; })
|
||||||
.catch(function() {
|
.catch(function() {
|
||||||
modalBody.innerHTML =
|
modalBody.innerHTML =
|
||||||
|
|
@ -496,7 +614,6 @@ function closeModal() {
|
||||||
document.getElementById('detailModal').classList.remove('active');
|
document.getElementById('detailModal').classList.remove('active');
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Close modal on backdrop / Escape --
|
|
||||||
window.onclick = function(event) {
|
window.onclick = function(event) {
|
||||||
var modal = document.getElementById('detailModal');
|
var modal = document.getElementById('detailModal');
|
||||||
if (event.target === modal) { closeModal(); }
|
if (event.target === modal) { closeModal(); }
|
||||||
|
|
@ -505,73 +622,55 @@ function closeModal() {
|
||||||
if (event.key === 'Escape') { closeModal(); }
|
if (event.key === 'Escape') { closeModal(); }
|
||||||
});
|
});
|
||||||
|
|
||||||
// -- Progress bar width animation --
|
|
||||||
document.querySelectorAll('.kegiatan-progress-fill[data-width]').forEach(function(el) {
|
|
||||||
el.style.width = el.getAttribute('data-width') + '%';
|
|
||||||
});
|
|
||||||
|
|
||||||
// -- Heatmap: delegated click for cells --
|
|
||||||
document.getElementById('heatmapGrid').addEventListener('click', function(e) {
|
document.getElementById('heatmapGrid').addEventListener('click', function(e) {
|
||||||
var cell = e.target.closest('.heatmap-cell');
|
var cell = e.target.closest('.heatmap-cell');
|
||||||
if (cell && cell.dataset.date) {
|
if (cell && cell.dataset.date) { goToDate(cell.dataset.date); }
|
||||||
goToDate(cell.dataset.date);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// -- Heatmap: month navigation --
|
|
||||||
function changeHeatmapMonth(delta) {
|
function changeHeatmapMonth(delta) {
|
||||||
var monthSelect = document.getElementById('heatmapMonth');
|
var monthSelect = document.getElementById('heatmapMonth');
|
||||||
var yearSelect = document.getElementById('heatmapYear');
|
var yearSelect = document.getElementById('heatmapYear');
|
||||||
var month = parseInt(monthSelect.value) + delta;
|
var month = parseInt(monthSelect.value) + delta;
|
||||||
var year = parseInt(yearSelect.value);
|
var year = parseInt(yearSelect.value);
|
||||||
|
|
||||||
if (month > 12) { month = 1; year++; }
|
if (month > 12) { month = 1; year++; }
|
||||||
else if (month < 1) { month = 12; year--; }
|
else if (month < 1) { month = 12; year--; }
|
||||||
|
|
||||||
monthSelect.value = month;
|
monthSelect.value = month;
|
||||||
yearSelect.value = year;
|
yearSelect.value = year;
|
||||||
updateHeatmap();
|
updateHeatmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Heatmap: AJAX reload --
|
|
||||||
function updateHeatmap() {
|
function updateHeatmap() {
|
||||||
var month = document.getElementById('heatmapMonth').value;
|
var month = document.getElementById('heatmapMonth').value;
|
||||||
var year = document.getElementById('heatmapYear').value;
|
var year = document.getElementById('heatmapYear').value;
|
||||||
var kelasId = document.getElementById('kelasInput').value;
|
var kelasId = document.getElementById('kelasInput').value;
|
||||||
|
|
||||||
var monthNames = [
|
var monthNames = ['Januari','Februari','Maret','April','Mei','Juni',
|
||||||
'Januari','Februari','Maret','April','Mei','Juni',
|
'Juli','Agustus','September','Oktober','November','Desember'];
|
||||||
'Juli','Agustus','September','Oktober','November','Desember'
|
|
||||||
];
|
|
||||||
document.getElementById('heatmapMonthName').textContent = monthNames[month - 1] + ' ' + year;
|
document.getElementById('heatmapMonthName').textContent = monthNames[month - 1] + ' ' + year;
|
||||||
|
|
||||||
var url = '{{ route("admin.kegiatan.index") }}' +
|
var url = '{{ route("admin.kegiatan.index") }}' +
|
||||||
'?heatmap=1&month=' + month + '&year=' + year + '&kelas=' + kelasId;
|
'?heatmap=1&month=' + month + '&year=' + year + '&kelas=' + kelasId;
|
||||||
|
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(function(response) { return response.json(); })
|
.then(function(r) { return r.json(); })
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
var grid = document.getElementById('heatmapGrid');
|
var grid = document.getElementById('heatmapGrid');
|
||||||
grid.innerHTML = '';
|
grid.innerHTML = '';
|
||||||
|
|
||||||
// -- Empty cells for first week alignment --
|
|
||||||
var firstDay = new Date(year, month - 1, 1).getDay();
|
var firstDay = new Date(year, month - 1, 1).getDay();
|
||||||
var startDay = firstDay === 0 ? 6 : firstDay - 1;
|
var startDay = firstDay === 0 ? 6 : firstDay - 1;
|
||||||
var i;
|
for (var i = 0; i < startDay; i++) {
|
||||||
for (i = 0; i < startDay; i++) {
|
|
||||||
var empty = document.createElement('div');
|
var empty = document.createElement('div');
|
||||||
empty.className = 'heatmap-cell';
|
empty.className = 'heatmap-cell';
|
||||||
empty.style.visibility = 'hidden';
|
empty.style.visibility = 'hidden';
|
||||||
grid.appendChild(empty);
|
grid.appendChild(empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Render calendar cells --
|
|
||||||
data.heatmapData.forEach(function(day) {
|
data.heatmapData.forEach(function(day) {
|
||||||
var cell = document.createElement('div');
|
var cell = document.createElement('div');
|
||||||
var date = new Date(day.date);
|
var date = new Date(day.date);
|
||||||
var today = new Date();
|
var today = new Date();
|
||||||
var isToday = date.toDateString() === today.toDateString();
|
var isToday = date.toDateString() === today.toDateString();
|
||||||
|
|
||||||
cell.className = 'heatmap-cell heatmap-level-' + day.level + (isToday ? ' today' : '');
|
cell.className = 'heatmap-cell heatmap-level-' + day.level + (isToday ? ' today' : '');
|
||||||
cell.setAttribute('data-date', day.date);
|
cell.setAttribute('data-date', day.date);
|
||||||
cell.setAttribute('data-percentage', day.percentage);
|
cell.setAttribute('data-percentage', day.percentage);
|
||||||
|
|
@ -581,9 +680,7 @@ function updateHeatmap() {
|
||||||
grid.appendChild(cell);
|
grid.appendChild(cell);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(function(err) {
|
.catch(function(err) { console.error('Error loading heatmap:', err); });
|
||||||
console.error('Error loading heatmap:', err);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,233 +0,0 @@
|
||||||
@extends('layouts.app')
|
|
||||||
|
|
||||||
@section('content')
|
|
||||||
<style>
|
|
||||||
.chart-box { background: #fff; border-radius: 12px; padding: 14px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); margin-bottom: 14px; }
|
|
||||||
.chart-box h4 { margin: 0 0 16px; color: var(--primary-dark); font-size: 1rem; }
|
|
||||||
.mini-kpi { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; margin-bottom: 14px; }
|
|
||||||
.mini-kpi-card { padding: 16px; border-radius: 10px; text-align: center; }
|
|
||||||
.mini-kpi-card.hadir { background: #ECFDF5; color: #065F46; }
|
|
||||||
.mini-kpi-card.izin { background: #FFFBEB; color: #92400E; }
|
|
||||||
.mini-kpi-card.sakit { background: #EFF6FF; color: #1E40AF; }
|
|
||||||
.mini-kpi-card.alpa { background: #FEF2F2; color: #991B1B; }
|
|
||||||
.mini-kpi-val { font-size: 1.6rem; font-weight: 700; }
|
|
||||||
.mini-kpi-label { font-size: 0.78rem; margin-top: 4px; }
|
|
||||||
.progress-bar-lg { background: #e9ecef; border-radius: 10px; height: 24px; overflow: hidden; margin: 12px 0; }
|
|
||||||
.progress-bar-lg .fill { height: 100%; border-radius: 10px; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 0.82rem; font-weight: 600; }
|
|
||||||
.insight-box { padding: 12px 16px; border-radius: 8px; margin-bottom: 8px; display: flex; align-items: flex-start; gap: 10px; font-size: 0.85rem; }
|
|
||||||
.insight-box.i-success { background: #ECFDF5; color: #065F46; }
|
|
||||||
.insight-box.i-warning { background: #FFFBEB; color: #92400E; }
|
|
||||||
.insight-box.i-danger { background: #FEF2F2; color: #991B1B; }
|
|
||||||
.insight-box.i-info { background: #EFF6FF; color: #1E40AF; }
|
|
||||||
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
|
|
||||||
@media(max-width:768px){ .two-col { grid-template-columns: 1fr; } }
|
|
||||||
.text-center { text-align: center; }
|
|
||||||
.progress-inline { display: flex; align-items: center; gap: 8px; }
|
|
||||||
.progress-bar-mini { flex: 1; background: #e9ecef; border-radius: 8px; height: 8px; overflow: hidden; max-width: 120px; }
|
|
||||||
.progress-bar-mini .fill { height: 100%; border-radius: 8px; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-search-plus"></i> Analisis Kegiatan</h2>
|
|
||||||
<a href="{{ route('admin.laporan-kegiatan.index') }}" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Header Kegiatan --}}
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<div style="display:flex; justify-content:space-between; align-items:flex-start; flex-wrap:wrap; gap:12px;">
|
|
||||||
<div>
|
|
||||||
<h3 style="margin:0 0 6px; color:var(--primary-dark);">{{ $kegiatan->nama_kegiatan }}</h3>
|
|
||||||
<p style="margin:0; font-size:0.85rem; color:var(--text-light);">
|
|
||||||
<span class="badge badge-info">{{ $kegiatan->kategori->nama_kategori ?? '-' }}</span>
|
|
||||||
<i class="fas fa-clock" style="margin-left:12px;"></i> {{ $kegiatan->waktu_lengkap }}
|
|
||||||
<i class="fas fa-calendar" style="margin-left:12px;"></i> {{ $kegiatan->hari }}
|
|
||||||
</p>
|
|
||||||
@if(!$kegiatan->isForAllClasses())
|
|
||||||
<p style="margin:4px 0 0; font-size:0.82rem;">
|
|
||||||
<i class="fas fa-school"></i> Kelas:
|
|
||||||
@foreach($kegiatan->kelasKegiatan as $kk)
|
|
||||||
<span class="badge badge-success">{{ $kk->nama_kelas }}</span>
|
|
||||||
@endforeach
|
|
||||||
</p>
|
|
||||||
@else
|
|
||||||
<p style="margin:4px 0 0; font-size:0.82rem;"><i class="fas fa-globe"></i> Kegiatan Umum (Semua Kelas)</p>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
<div style="text-align:right;">
|
|
||||||
<p style="margin:0; font-size:0.82rem; color:var(--text-light);">Periode: <strong>{{ $periodeLabel }}</strong></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Mini KPI --}}
|
|
||||||
<div class="mini-kpi">
|
|
||||||
<div class="mini-kpi-card hadir">
|
|
||||||
<div class="mini-kpi-val">{{ $stats->hadir ?? 0 }}</div>
|
|
||||||
<div class="mini-kpi-label"><i class="fas fa-check"></i> Hadir</div>
|
|
||||||
</div>
|
|
||||||
<div class="mini-kpi-card izin">
|
|
||||||
<div class="mini-kpi-val">{{ $stats->izin ?? 0 }}</div>
|
|
||||||
<div class="mini-kpi-label"><i class="fas fa-info-circle"></i> Izin</div>
|
|
||||||
</div>
|
|
||||||
<div class="mini-kpi-card sakit">
|
|
||||||
<div class="mini-kpi-val">{{ $stats->sakit ?? 0 }}</div>
|
|
||||||
<div class="mini-kpi-label"><i class="fas fa-heartbeat"></i> Sakit</div>
|
|
||||||
</div>
|
|
||||||
<div class="mini-kpi-card alpa">
|
|
||||||
<div class="mini-kpi-val">{{ $stats->alpa ?? 0 }}</div>
|
|
||||||
<div class="mini-kpi-label"><i class="fas fa-times"></i> Alpa</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Overall Progress --}}
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<h4 style="margin:0 0 8px;"><i class="fas fa-percentage"></i> Rata-rata Kehadiran</h4>
|
|
||||||
@php $statsPersen = $stats->persen ?? 0; @endphp
|
|
||||||
<div class="progress-bar-lg">
|
|
||||||
<div class="fill" style="width:{{ $statsPersen }}%; background:{{ $statsPersen >= 85 ? '#10B981' : ($statsPersen >= 70 ? '#FBBF24' : '#EF4444') }};">
|
|
||||||
{{ $statsPersen }}%
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="two-col">
|
|
||||||
{{-- Trend Chart --}}
|
|
||||||
<div class="chart-box">
|
|
||||||
<h4><i class="fas fa-chart-line"></i> Trend 4 Minggu Terakhir</h4>
|
|
||||||
<div style="height:250px;">
|
|
||||||
<canvas id="kegiatanTrendChart"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Punctuality --}}
|
|
||||||
<div class="chart-box">
|
|
||||||
<h4><i class="fas fa-stopwatch"></i> Ketepatan Waktu (RFID)</h4>
|
|
||||||
@if($punctuality && $punctuality->total > 0)
|
|
||||||
<div style="height:250px;">
|
|
||||||
<canvas id="punctualityChart"></canvas>
|
|
||||||
</div>
|
|
||||||
<div style="margin-top:12px; font-size:0.82rem; color:var(--text-light); text-align:center;">
|
|
||||||
{{ $punctuality->tepat_waktu ?? 0 }} tepat waktu, {{ $punctuality->terlambat ?? 0 }} terlambat dari {{ $punctuality->total }} total
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
<div class="insight-box i-info"><i class="fas fa-info-circle"></i> Belum ada data RFID untuk analisis ketepatan waktu.</div>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Breakdown Per Kelas --}}
|
|
||||||
@if(!empty($breakdownPerKelas) && count($breakdownPerKelas) > 0)
|
|
||||||
<div class="chart-box">
|
|
||||||
<h4><i class="fas fa-school"></i> Breakdown Per Kelas</h4>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table" style="font-size:0.85rem;">
|
|
||||||
<thead><tr><th>Kelas</th><th class="text-center">Total</th><th class="text-center">Hadir</th><th class="text-center" style="min-width:180px;">% Kehadiran</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach($breakdownPerKelas as $bk)
|
|
||||||
<tr style="{{ $bk['persen'] < 70 ? 'background:#FEF2F2;' : '' }}">
|
|
||||||
<td><strong>{{ $bk['kelas'] }}</strong></td>
|
|
||||||
<td class="text-center">{{ $bk['total'] }}</td>
|
|
||||||
<td class="text-center"><span class="badge badge-success">{{ $bk['hadir'] }}</span></td>
|
|
||||||
<td class="text-center">
|
|
||||||
<div class="progress-inline" style="justify-content:center;">
|
|
||||||
<div class="progress-bar-mini"><div class="fill" style="width:{{ $bk['persen'] }}%; background:{{ $bk['persen'] >= 85 ? '#10B981' : ($bk['persen'] >= 70 ? '#FBBF24' : '#EF4444') }};"></div></div>
|
|
||||||
<strong>{{ $bk['persen'] }}%</strong>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
{{-- Santri Tidak Pernah Hadir --}}
|
|
||||||
@if($santriTidakPernahHadir && $santriTidakPernahHadir->count() > 0)
|
|
||||||
<div class="chart-box">
|
|
||||||
<h4><i class="fas fa-user-times" style="color:#EF4444;"></i> Santri Tidak Pernah Hadir</h4>
|
|
||||||
<div style="display:flex; flex-wrap:wrap; gap:8px;">
|
|
||||||
@foreach($santriTidakPernahHadir as $sth)
|
|
||||||
<a href="{{ route('admin.laporan-kegiatan.detail-santri', $sth->id_santri) }}" class="badge badge-danger" style="padding:6px 12px; font-size:0.82rem; text-decoration:none;">
|
|
||||||
{{ $sth->santri->nama_lengkap ?? $sth->id_santri }}
|
|
||||||
</a>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
{{-- Insights & Rekomendasi --}}
|
|
||||||
@if(!empty($insights))
|
|
||||||
<div class="chart-box">
|
|
||||||
<h4><i class="fas fa-lightbulb"></i> Insight & Rekomendasi</h4>
|
|
||||||
@foreach($insights as $insight)
|
|
||||||
<div class="insight-box i-{{ $insight['type'] }}">
|
|
||||||
<i class="{{ $insight['icon'] }}"></i>
|
|
||||||
{{ $insight['text'] }}
|
|
||||||
</div>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
{{-- Actions --}}
|
|
||||||
<div class="content-box" style="display:flex; gap:8px; flex-wrap:wrap;">
|
|
||||||
<a href="{{ route('admin.absensi-kegiatan.rekap', $kegiatan->kegiatan_id) }}" class="btn btn-info">
|
|
||||||
<i class="fas fa-list"></i> Rekap Absensi
|
|
||||||
</a>
|
|
||||||
<button onclick="window.print()" class="btn btn-secondary"><i class="fas fa-print"></i> Cetak</button>
|
|
||||||
<a href="{{ route('admin.laporan-kegiatan.index') }}" class="btn btn-secondary"><i class="fas fa-arrow-left"></i> Kembali</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
|
||||||
<script>
|
|
||||||
// Trend Chart
|
|
||||||
const trend = @json($trend);
|
|
||||||
new Chart(document.getElementById('kegiatanTrendChart'), {
|
|
||||||
type: 'line',
|
|
||||||
data: {
|
|
||||||
labels: trend.map(t => t.label),
|
|
||||||
datasets: [{
|
|
||||||
label: '% Kehadiran',
|
|
||||||
data: trend.map(t => t.persen),
|
|
||||||
borderColor: '#3B82F6',
|
|
||||||
backgroundColor: 'rgba(59,130,246,0.1)',
|
|
||||||
tension: 0.4, fill: true, pointRadius: 6,
|
|
||||||
pointBackgroundColor: trend.map(t => t.persen >= 85 ? '#10B981' : (t.persen >= 70 ? '#FBBF24' : '#EF4444')),
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true, maintainAspectRatio: false,
|
|
||||||
plugins: { legend: { display: false }, tooltip: { callbacks: { label: ctx => ctx.raw + '%' } } },
|
|
||||||
scales: { y: { min: 0, max: 100, ticks: { callback: v => v + '%' } }, x: { grid: { display: false } } }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Punctuality Pie
|
|
||||||
@if($punctuality && $punctuality->total > 0)
|
|
||||||
new Chart(document.getElementById('punctualityChart'), {
|
|
||||||
type: 'doughnut',
|
|
||||||
data: {
|
|
||||||
labels: ['Tepat Waktu', 'Terlambat'],
|
|
||||||
datasets: [{
|
|
||||||
data: [{{ $punctuality->tepat_waktu ?? 0 }}, {{ $punctuality->terlambat ?? 0 }}],
|
|
||||||
backgroundColor: ['#10B981', '#EF4444'],
|
|
||||||
borderWidth: 2, hoverOffset: 8
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true, maintainAspectRatio: false,
|
|
||||||
plugins: { legend: { position: 'bottom', labels: { usePointStyle: true } } }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@endif
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
@media print {
|
|
||||||
.btn, button { display: none !important; }
|
|
||||||
.chart-box, .content-box { box-shadow: none !important; border: 1px solid #e2e8f0; page-break-inside: avoid; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@endsection
|
|
||||||
|
|
@ -1,234 +0,0 @@
|
||||||
@extends('layouts.app')
|
|
||||||
|
|
||||||
@section('content')
|
|
||||||
<style>
|
|
||||||
.detail-header { display: flex; gap: 20px; align-items: flex-start; margin-bottom: 14px; }
|
|
||||||
.detail-avatar { width: 80px; height: 80px; border-radius: 50%; background: linear-gradient(135deg, #10B981, #34D399); display: flex; align-items: center; justify-content: center; color: #fff; font-size: 2rem; font-weight: 700; flex-shrink: 0; }
|
|
||||||
.detail-info h3 { margin: 0 0 4px; color: var(--primary-dark); }
|
|
||||||
.detail-info p { margin: 0; font-size: 0.85rem; color: var(--text-light); }
|
|
||||||
.mini-kpi { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; margin-bottom: 14px; }
|
|
||||||
.mini-kpi-card { padding: 16px; border-radius: 10px; text-align: center; }
|
|
||||||
.mini-kpi-card.hadir { background: #ECFDF5; color: #065F46; }
|
|
||||||
.mini-kpi-card.izin { background: #FFFBEB; color: #92400E; }
|
|
||||||
.mini-kpi-card.sakit { background: #EFF6FF; color: #1E40AF; }
|
|
||||||
.mini-kpi-card.alpa { background: #FEF2F2; color: #991B1B; }
|
|
||||||
.mini-kpi-val { font-size: 1.6rem; font-weight: 700; }
|
|
||||||
.mini-kpi-label { font-size: 0.78rem; margin-top: 4px; }
|
|
||||||
.chart-box { background: #fff; border-radius: 12px; padding: 14px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); margin-bottom: 14px; }
|
|
||||||
.chart-box h4 { margin: 0 0 16px; color: var(--primary-dark); font-size: 1rem; }
|
|
||||||
.progress-bar-lg { background: #e9ecef; border-radius: 10px; height: 24px; overflow: hidden; margin: 12px 0; }
|
|
||||||
.progress-bar-lg .fill { height: 100%; border-radius: 10px; transition: width 0.5s; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 0.82rem; font-weight: 600; }
|
|
||||||
.insight-box { padding: 12px 16px; border-radius: 8px; margin-bottom: 8px; display: flex; align-items: flex-start; gap: 10px; font-size: 0.85rem; }
|
|
||||||
.insight-box.i-success { background: #ECFDF5; color: #065F46; }
|
|
||||||
.insight-box.i-warning { background: #FFFBEB; color: #92400E; }
|
|
||||||
.insight-box.i-danger { background: #FEF2F2; color: #991B1B; }
|
|
||||||
.insight-box.i-info { background: #EFF6FF; color: #1E40AF; }
|
|
||||||
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
|
|
||||||
@media(max-width:768px){ .two-col { grid-template-columns: 1fr; } }
|
|
||||||
.progress-inline { display: flex; align-items: center; gap: 8px; }
|
|
||||||
.progress-bar-mini { flex: 1; background: #e9ecef; border-radius: 8px; height: 8px; overflow: hidden; max-width: 120px; }
|
|
||||||
.progress-bar-mini .fill { height: 100%; border-radius: 8px; }
|
|
||||||
.text-center { text-align: center; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-user-chart"></i> Detail Kehadiran Santri</h2>
|
|
||||||
<a href="{{ route('admin.laporan-kegiatan.index', request()->query()) }}" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Header --}}
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<div class="detail-header">
|
|
||||||
<div class="detail-avatar">{{ strtoupper(substr($santri->nama_lengkap, 0, 1)) }}</div>
|
|
||||||
<div class="detail-info">
|
|
||||||
<h3>{{ $santri->nama_lengkap }}</h3>
|
|
||||||
<p><i class="fas fa-id-card"></i> {{ $santri->id_santri }}</p>
|
|
||||||
@if($santri->kelasSantri && $santri->kelasSantri->count() > 0)
|
|
||||||
<p><i class="fas fa-school"></i>
|
|
||||||
@foreach($santri->kelasSantri as $ks)
|
|
||||||
<span class="badge badge-info">{{ $ks->kelas->nama_kelas ?? '-' }}</span>
|
|
||||||
@endforeach
|
|
||||||
</p>
|
|
||||||
@endif
|
|
||||||
<p style="margin-top:4px;"><i class="fas fa-calendar"></i> Periode: <strong>{{ $periodeLabel }}</strong></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Mini KPI --}}
|
|
||||||
<div class="mini-kpi">
|
|
||||||
<div class="mini-kpi-card hadir">
|
|
||||||
<div class="mini-kpi-val">{{ $stats->hadir ?? 0 }}</div>
|
|
||||||
<div class="mini-kpi-label"><i class="fas fa-check"></i> Hadir</div>
|
|
||||||
</div>
|
|
||||||
<div class="mini-kpi-card izin">
|
|
||||||
<div class="mini-kpi-val">{{ $stats->izin ?? 0 }}</div>
|
|
||||||
<div class="mini-kpi-label"><i class="fas fa-info-circle"></i> Izin</div>
|
|
||||||
</div>
|
|
||||||
<div class="mini-kpi-card sakit">
|
|
||||||
<div class="mini-kpi-val">{{ $stats->sakit ?? 0 }}</div>
|
|
||||||
<div class="mini-kpi-label"><i class="fas fa-heartbeat"></i> Sakit</div>
|
|
||||||
</div>
|
|
||||||
<div class="mini-kpi-card alpa">
|
|
||||||
<div class="mini-kpi-val">{{ $stats->alpa ?? 0 }}</div>
|
|
||||||
<div class="mini-kpi-label"><i class="fas fa-times"></i> Alpa</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Overall Progress --}}
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<h4 style="margin:0 0 8px; font-size:0.95rem;"><i class="fas fa-chart-bar"></i> Kehadiran Keseluruhan</h4>
|
|
||||||
<div class="progress-bar-lg">
|
|
||||||
<div class="fill" style="width:{{ $persenKehadiran }}%; background:{{ $persenKehadiran >= 85 ? '#10B981' : ($persenKehadiran >= 70 ? '#FBBF24' : '#EF4444') }};">
|
|
||||||
{{ $persenKehadiran }}%
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@if($persenKehadiran >= 85)
|
|
||||||
<div class="insight-box i-success"><i class="fas fa-star"></i> Kehadiran sangat baik. Pertahankan!</div>
|
|
||||||
@elseif($persenKehadiran >= 70)
|
|
||||||
<div class="insight-box i-warning"><i class="fas fa-exclamation-triangle"></i> Kehadiran cukup, perlu ditingkatkan.</div>
|
|
||||||
@else
|
|
||||||
<div class="insight-box i-danger"><i class="fas fa-times-circle"></i> Kehadiran di bawah standar. Perlu perhatian khusus.</div>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="two-col">
|
|
||||||
{{-- Trend 4 Minggu --}}
|
|
||||||
<div class="chart-box">
|
|
||||||
<h4><i class="fas fa-chart-line"></i> Trend 4 Minggu Terakhir</h4>
|
|
||||||
<div style="height:220px;">
|
|
||||||
<canvas id="santriTrendChart"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Insights --}}
|
|
||||||
<div class="chart-box">
|
|
||||||
<h4><i class="fas fa-lightbulb"></i> Insight</h4>
|
|
||||||
@if($kegiatanBolos)
|
|
||||||
<div class="insight-box i-danger">
|
|
||||||
<i class="fas fa-user-times"></i>
|
|
||||||
Paling sering Alpa di kegiatan: <strong>{{ $kegiatanBolos->kegiatan->nama_kegiatan ?? '-' }}</strong> ({{ $kegiatanBolos->total_alpa }}x)
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
@if($streak > 0)
|
|
||||||
<div class="insight-box i-success">
|
|
||||||
<i class="fas fa-fire"></i>
|
|
||||||
Streak kehadiran beruntun: <strong>{{ $streak }} kegiatan</strong> ðŸâ€Â¥
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
@if(($stats->total ?? 0) > 0)
|
|
||||||
<div class="insight-box i-info">
|
|
||||||
<i class="fas fa-calculator"></i>
|
|
||||||
Total tercatat: {{ $stats->total }} absensi ({{ $stats->hadir }} hadir, {{ $stats->alpa }} alpa)
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Kehadiran Per Kegiatan --}}
|
|
||||||
<div class="chart-box">
|
|
||||||
<h4><i class="fas fa-tasks"></i> Kehadiran Per Kegiatan</h4>
|
|
||||||
@if($perKegiatan->count() > 0)
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table" style="font-size:0.85rem;">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>No</th><th>Kegiatan</th>
|
|
||||||
<th class="text-center">Hadir</th><th class="text-center">Izin</th>
|
|
||||||
<th class="text-center">Sakit</th><th class="text-center">Alpa</th>
|
|
||||||
<th class="text-center" style="min-width:180px;">% Kehadiran</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach($perKegiatan as $i => $kg)
|
|
||||||
<tr style="{{ $kg->persen < 70 ? 'background:#FEF2F2;' : '' }}">
|
|
||||||
<td>{{ $i + 1 }}</td>
|
|
||||||
<td><strong>{{ $kg->nama_kegiatan }}</strong></td>
|
|
||||||
<td class="text-center"><span class="badge badge-success">{{ $kg->hadir }}</span></td>
|
|
||||||
<td class="text-center"><span class="badge badge-warning">{{ $kg->izin }}</span></td>
|
|
||||||
<td class="text-center"><span class="badge badge-info">{{ $kg->sakit }}</span></td>
|
|
||||||
<td class="text-center"><span class="badge badge-danger">{{ $kg->alpa }}</span></td>
|
|
||||||
<td class="text-center">
|
|
||||||
<div class="progress-inline" style="justify-content:center;">
|
|
||||||
<div class="progress-bar-mini"><div class="fill" style="width:{{ $kg->persen }}%; background:{{ $kg->persen >= 85 ? '#10B981' : ($kg->persen >= 70 ? '#FBBF24' : '#EF4444') }};"></div></div>
|
|
||||||
<strong style="color:{{ $kg->persen >= 85 ? '#10B981' : ($kg->persen >= 70 ? '#92400E' : '#EF4444') }};">{{ $kg->persen }}%</strong>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
<p style="color:var(--text-light); font-size:0.85rem;">Belum ada data kehadiran per kegiatan.</p>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Riwayat Terbaru --}}
|
|
||||||
<div class="chart-box">
|
|
||||||
<h4><i class="fas fa-history"></i> Riwayat Absensi Terbaru</h4>
|
|
||||||
@if($riwayatTerbaru->count() > 0)
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table" style="font-size:0.85rem;">
|
|
||||||
<thead><tr><th>Tanggal</th><th>Kegiatan</th><th>Kategori</th><th class="text-center">Status</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach($riwayatTerbaru as $r)
|
|
||||||
<tr>
|
|
||||||
<td>{{ $r->tanggal->format('d/m/Y') }}</td>
|
|
||||||
<td>{{ $r->kegiatan->nama_kegiatan ?? '-' }}</td>
|
|
||||||
<td>{{ $r->kegiatan->kategori->nama_kategori ?? '-' }}</td>
|
|
||||||
<td class="text-center">{!! $r->status_badge !!}</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
<p style="color:var(--text-light);">Belum ada riwayat.</p>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Actions --}}
|
|
||||||
<div class="content-box" style="display:flex; gap:8px; flex-wrap:wrap;">
|
|
||||||
<a href="{{ route('admin.riwayat-kegiatan.detail-santri', $santri->id_santri) }}" class="btn btn-info">
|
|
||||||
<i class="fas fa-history"></i> Riwayat Lengkap
|
|
||||||
</a>
|
|
||||||
<button onclick="window.print()" class="btn btn-secondary"><i class="fas fa-print"></i> Cetak Laporan</button>
|
|
||||||
<a href="{{ route('admin.laporan-kegiatan.index') }}" class="btn btn-secondary"><i class="fas fa-arrow-left"></i> Kembali ke Laporan</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
|
||||||
<script>
|
|
||||||
const trend = @json($trend);
|
|
||||||
new Chart(document.getElementById('santriTrendChart'), {
|
|
||||||
type: 'line',
|
|
||||||
data: {
|
|
||||||
labels: trend.map(t => t.label),
|
|
||||||
datasets: [{
|
|
||||||
label: '% Kehadiran',
|
|
||||||
data: trend.map(t => t.persen),
|
|
||||||
borderColor: '#3B82F6',
|
|
||||||
backgroundColor: 'rgba(59,130,246,0.1)',
|
|
||||||
tension: 0.4,
|
|
||||||
fill: true,
|
|
||||||
pointRadius: 6,
|
|
||||||
pointBackgroundColor: trend.map(t => t.persen >= 85 ? '#10B981' : (t.persen >= 70 ? '#FBBF24' : '#EF4444')),
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true, maintainAspectRatio: false,
|
|
||||||
plugins: { legend: { display: false }, tooltip: { callbacks: { label: ctx => ctx.raw + '%' } } },
|
|
||||||
scales: { y: { min: 0, max: 100, ticks: { callback: v => v + '%' } }, x: { grid: { display: false } } }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
@media print {
|
|
||||||
.btn, button, .page-header .btn { display: none !important; }
|
|
||||||
.chart-box, .content-box { box-shadow: none !important; border: 1px solid #e2e8f0; page-break-inside: avoid; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@endsection
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -10,14 +10,24 @@
|
||||||
|
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2><i class="fas fa-user-clock"></i> Santri Perlu Perhatian</h2>
|
<h2><i class="fas fa-user-clock"></i> Santri Perlu Perhatian</h2>
|
||||||
<a href="{{ route('admin.laporan-kegiatan.index') }}" class="btn btn-secondary">
|
<a href="{{ route('admin.laporan-kegiatan.index', request()->only('periode','tanggal_dari','tanggal_sampai')) }}"
|
||||||
|
class="btn btn-secondary">
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- Konteks header --}}
|
||||||
<div class="content-box" style="margin-bottom:14px;">
|
<div class="content-box" style="margin-bottom:14px;">
|
||||||
<p style="margin:0; color:var(--text-light); font-size:0.85rem;">
|
<p style="margin:0;font-size:.88rem;color:var(--text-light);">
|
||||||
<i class="fas fa-info-circle"></i> Daftar santri dengan kehadiran <70% dalam periode <strong>{{ $periodeLabel }}</strong>
|
<i class="fas fa-info-circle"></i>
|
||||||
|
Menampilkan <strong>{{ $santris->total() }} santri</strong>
|
||||||
|
dari <strong>{{ $totalSantriAktif }} santri aktif</strong>
|
||||||
|
yang kehadiran efektifnya <70%
|
||||||
|
dalam periode <strong>{{ $periodeLabel }}</strong>.
|
||||||
|
<br>
|
||||||
|
<span style="font-size:.8rem;opacity:.8;">
|
||||||
|
<i class="fas fa-clock"></i> Terlambat dihitung sebagai Hadir efektif.
|
||||||
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -25,13 +35,15 @@
|
||||||
<div class="content-box" style="margin-bottom:14px;">
|
<div class="content-box" style="margin-bottom:14px;">
|
||||||
<form method="GET" style="display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;">
|
<form method="GET" style="display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;">
|
||||||
<input type="hidden" name="periode" value="{{ request('periode','bulan_ini') }}">
|
<input type="hidden" name="periode" value="{{ request('periode','bulan_ini') }}">
|
||||||
|
<input type="hidden" name="tanggal_dari" value="{{ request('tanggal_dari') }}">
|
||||||
|
<input type="hidden" name="tanggal_sampai" value="{{ request('tanggal_sampai') }}">
|
||||||
<div class="form-group" style="margin:0;">
|
<div class="form-group" style="margin:0;">
|
||||||
<label style="font-size:0.82rem;">Filter Kelas</label>
|
<label style="font-size:.82rem;">Filter Kelas</label>
|
||||||
<select name="id_kelas" class="form-control" style="min-width:180px;">
|
<select name="id_kelas" class="form-control" style="min-width:180px;">
|
||||||
<option value="">-- Semua Kelas --</option>
|
<option value="">-- Semua Kelas --</option>
|
||||||
@foreach($kelasList as $k)
|
@foreach($kelasList as $k)
|
||||||
<option value="{{ $k->id }}" {{ request('id_kelas')==$k->id?'selected':'' }}>
|
<option value="{{ $k->id }}" {{ request('id_kelas')==$k->id?'selected':'' }}>
|
||||||
{{ $k->kelompok->nama_kelompok ?? '' }} - {{ $k->nama_kelas }}
|
{{ $k->kelompok->nama_kelompok ?? '' }} – {{ $k->nama_kelas }}
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -43,18 +55,24 @@
|
||||||
<div class="content-box">
|
<div class="content-box">
|
||||||
@if($santris->count() > 0)
|
@if($santris->count() > 0)
|
||||||
<div class="table-wrapper">
|
<div class="table-wrapper">
|
||||||
<table class="data-table" style="font-size:0.85rem;">
|
<table class="data-table" style="font-size:.84rem;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>No</th>
|
<th>No</th>
|
||||||
<th>ID Santri</th>
|
|
||||||
<th>Nama</th>
|
<th>Nama</th>
|
||||||
<th class="text-center">Total</th>
|
<th class="text-center">Total Sesi</th>
|
||||||
<th class="text-center">Hadir</th>
|
<th class="text-center">
|
||||||
|
Hadir Efektif
|
||||||
|
<span style="display:block;font-weight:400;font-size:.73rem;color:#9CA3AF;">(Hadir+Terlambat)</span>
|
||||||
|
</th>
|
||||||
|
<th class="text-center">Terlambat</th>
|
||||||
<th class="text-center">Alpa</th>
|
<th class="text-center">Alpa</th>
|
||||||
<th class="text-center">Izin</th>
|
<th class="text-center">Izin</th>
|
||||||
<th class="text-center">Sakit</th>
|
<th class="text-center">Sakit</th>
|
||||||
<th class="text-center" style="min-width:180px;">% Kehadiran</th>
|
<th class="text-center" style="min-width:180px;">
|
||||||
|
% Kehadiran
|
||||||
|
<span style="display:block;font-weight:400;font-size:.73rem;color:#9CA3AF;">(hadir / total sesi)</span>
|
||||||
|
</th>
|
||||||
<th>Aksi</th>
|
<th>Aksi</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
@ -62,22 +80,48 @@
|
||||||
@foreach($santris as $i => $s)
|
@foreach($santris as $i => $s)
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ $santris->firstItem() + $i }}</td>
|
<td>{{ $santris->firstItem() + $i }}</td>
|
||||||
<td><code>{{ $s->id_santri }}</code></td>
|
<td>
|
||||||
<td><strong>{{ $s->nama_lengkap }}</strong></td>
|
<strong>{{ $s->nama_lengkap }}</strong>
|
||||||
|
<div style="font-size:.75rem;color:#9CA3AF;"><code>{{ $s->id_santri }}</code></div>
|
||||||
|
</td>
|
||||||
<td class="text-center">{{ $s->total }}</td>
|
<td class="text-center">{{ $s->total }}</td>
|
||||||
<td class="text-center"><span class="badge badge-success">{{ $s->hadir }}</span></td>
|
<td class="text-center">
|
||||||
<td class="text-center"><span class="badge badge-danger">{{ $s->alpa }}</span></td>
|
<span class="badge badge-success">{{ $s->hadir }}</span>
|
||||||
<td class="text-center"><span class="badge badge-warning">{{ $s->izin }}</span></td>
|
</td>
|
||||||
<td class="text-center"><span class="badge badge-info">{{ $s->sakit }}</span></td>
|
<td class="text-center">
|
||||||
|
@if(($s->terlambat ?? 0) > 0)
|
||||||
|
<span class="badge badge-warning">{{ $s->terlambat }}</span>
|
||||||
|
@else
|
||||||
|
<span style="color:#9CA3AF;">0</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<span class="badge badge-danger">{{ $s->alpa }}</span>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<span class="badge badge-warning">{{ $s->izin }}</span>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<span class="badge badge-info">{{ $s->sakit }}</span>
|
||||||
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<div class="progress-inline" style="justify-content:center;">
|
<div class="progress-inline" style="justify-content:center;">
|
||||||
<div class="progress-bar-mini"><div class="fill" style="width:{{ $s->persen }}%; background:#EF4444;"></div></div>
|
<div class="progress-bar-mini">
|
||||||
|
<div class="fill" style="width:{{ $s->persen }}%;background:#EF4444;"></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
<strong style="color:#EF4444;">{{ $s->persen }}%</strong>
|
<strong style="color:#EF4444;">{{ $s->persen }}%</strong>
|
||||||
|
{{-- Konteks X dari Y --}}
|
||||||
|
<div style="font-size:.72rem;color:#9CA3AF;">
|
||||||
|
{{ $s->hadir }} dari {{ $s->total }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ route('admin.laporan-kegiatan.detail-santri', $s->id_santri) }}" class="btn btn-sm btn-info" title="Detail">
|
<a href="{{ route('admin.riwayat-kegiatan.detail-santri', $s->id_santri) }}"
|
||||||
<i class="fas fa-eye"></i>
|
class="btn btn-sm btn-info" title="Lihat Riwayat Lengkap">
|
||||||
|
<i class="fas fa-history"></i> Riwayat
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -85,13 +129,10 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="margin-top:16px;">{{ $santris->links() }}</div>
|
||||||
<div style="margin-top:16px;">
|
|
||||||
{{ $santris->links() }}
|
|
||||||
</div>
|
|
||||||
@else
|
@else
|
||||||
<div class="empty-state">
|
<div class="empty-state">
|
||||||
<i class="fas fa-check-circle" style="color:#10B981;"></i>
|
<i class="fas fa-check-circle" style="color:#10B981;font-size:2rem;"></i>
|
||||||
<h3>Alhamdulillah!</h3>
|
<h3>Alhamdulillah!</h3>
|
||||||
<p>Tidak ada santri dengan kehadiran di bawah 70%.</p>
|
<p>Tidak ada santri dengan kehadiran di bawah 70%.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
{{-- resources/views/admin/kegiatan/riwayat/_card.blade.php --}}
|
||||||
|
{{-- Diinclude dari index.blade.php --}}
|
||||||
|
@php
|
||||||
|
$totalSantri = $kegiatan->total_absensi;
|
||||||
|
$hdr = $kegiatan->hadir ?? 0;
|
||||||
|
$tlb = $kegiatan->terlambat ?? 0;
|
||||||
|
$izn = $kegiatan->izin ?? 0;
|
||||||
|
$skt = $kegiatan->sakit ?? 0;
|
||||||
|
$alp = $kegiatan->alpa ?? 0;
|
||||||
|
$plg = $kegiatan->pulang ?? 0;
|
||||||
|
$tot = $kegiatan->total_absensi ?? 0;
|
||||||
|
|
||||||
|
$pct = fn($n) => $tot > 0 ? round($n / $tot * 100) : 0;
|
||||||
|
|
||||||
|
$isUmum = $kegiatan->kelasKegiatan->isEmpty();
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<div class="rw-card">
|
||||||
|
|
||||||
|
{{-- Header --}}
|
||||||
|
<div class="rw-card-head">
|
||||||
|
<div style="flex: 1; min-width: 0;">
|
||||||
|
<div class="rw-card-title">
|
||||||
|
<i class="fas fa-clipboard-list"></i>
|
||||||
|
{{ $kegiatan->nama_kegiatan }}
|
||||||
|
</div>
|
||||||
|
<div class="rw-card-meta">
|
||||||
|
<span><i class="fas fa-clock"></i>
|
||||||
|
{{ date('H:i', strtotime($kegiatan->waktu_mulai)) }}–{{ date('H:i', strtotime($kegiatan->waktu_selesai)) }}
|
||||||
|
</span>
|
||||||
|
<span class="rw-kat-tag"><i class="fas fa-tag"></i> {{ $kegiatan->kategori->nama_kategori }}</span>
|
||||||
|
@if($isUmum)
|
||||||
|
<span class="rw-umum-tag"><i class="fas fa-globe"></i> Umum</span>
|
||||||
|
@else
|
||||||
|
@foreach($kegiatan->kelasKegiatan->take(3) as $kls)
|
||||||
|
<span class="rw-kelas-tag">{{ $kls->nama_kelas }}</span>
|
||||||
|
@endforeach
|
||||||
|
@if($kegiatan->kelasKegiatan->count() > 3)
|
||||||
|
<span class="rw-umum-tag">+{{ $kegiatan->kelasKegiatan->count() - 3 }} kelas</span>
|
||||||
|
@endif
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Hari badge (jika mode hari ini) --}}
|
||||||
|
@if(isset($passParams) && $passParams['mode'] === 'hari_ini')
|
||||||
|
<div style="font-size: 0.75rem; color: var(--primary-color); font-weight: 700;
|
||||||
|
background: #f0fdf4; padding: 4px 10px; border-radius: 20px; border: 1px solid #bbf7d0;
|
||||||
|
white-space: nowrap; flex-shrink: 0;">
|
||||||
|
<i class="fas fa-calendar-day"></i> {{ $kegiatan->hari }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Body: stats --}}
|
||||||
|
<div class="rw-card-body">
|
||||||
|
@if($tot > 0)
|
||||||
|
{{-- Chips --}}
|
||||||
|
<div class="rw-stats-row">
|
||||||
|
@if($hdr > 0) <span class="rw-chip hadir"><i class="fas fa-check"></i> {{ $hdr }} Hadir</span> @endif
|
||||||
|
@if($tlb > 0) <span class="rw-chip terlambat"><i class="fas fa-clock"></i> {{ $tlb }} Terlambat</span> @endif
|
||||||
|
@if($izn > 0) <span class="rw-chip izin"><i class="fas fa-envelope"></i> {{ $izn }} Izin</span> @endif
|
||||||
|
@if($skt > 0) <span class="rw-chip sakit"><i class="fas fa-heartbeat"></i> {{ $skt }} Sakit</span> @endif
|
||||||
|
@if($alp > 0) <span class="rw-chip alpa"><i class="fas fa-times"></i> {{ $alp }} Alpa</span> @endif
|
||||||
|
@if($plg > 0) <span class="rw-chip pulang"><i class="fas fa-home"></i> {{ $plg }} Pulang</span> @endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Progress bar --}}
|
||||||
|
<div class="rw-progress-wrap">
|
||||||
|
@if($hdr > 0) <div class="rw-prog-hadir" style="width:{{ $pct($hdr) }}%;" title="Hadir {{ $hdr }}"></div> @endif
|
||||||
|
@if($tlb > 0) <div class="rw-prog-terlambat" style="width:{{ $pct($tlb) }}%;" title="Terlambat {{ $tlb }}"></div> @endif
|
||||||
|
@if($izn > 0) <div class="rw-prog-izin" style="width:{{ $pct($izn) }}%;" title="Izin {{ $izn }}"></div> @endif
|
||||||
|
@if($skt > 0) <div class="rw-prog-sakit" style="width:{{ $pct($skt) }}%;" title="Sakit {{ $skt }}"></div> @endif
|
||||||
|
@if($alp > 0) <div class="rw-prog-alpa" style="width:{{ $pct($alp) }}%;" title="Alpa {{ $alp }}"></div> @endif
|
||||||
|
@if($plg > 0) <div class="rw-prog-pulang" style="width:{{ $pct($plg) }}%;" title="Pulang {{ $plg }}"></div> @endif
|
||||||
|
</div>
|
||||||
|
<div style="font-size: 0.74rem; color: #94a3b8;">
|
||||||
|
Total tercatat: <strong style="color:#374151;">{{ $tot }}</strong> santri
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<span class="rw-chip none"><i class="fas fa-inbox"></i> Belum ada data absensi</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Footer --}}
|
||||||
|
<div class="rw-card-foot">
|
||||||
|
<div class="rw-total-txt">
|
||||||
|
@if($tot > 0)
|
||||||
|
<i class="fas fa-users" style="color:var(--primary-color);"></i>
|
||||||
|
<strong>{{ $hdr + $tlb }}</strong> hadir dari <strong>{{ $tot }}</strong> tercatat
|
||||||
|
@else
|
||||||
|
<span style="color:#cbd5e1;"><i class="fas fa-info-circle"></i> Belum ada absensi diinput</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@php
|
||||||
|
$detailParams = array_merge($passParams ?? [], ['kategori_id' => request('kategori_id')]);
|
||||||
|
@endphp
|
||||||
|
<a href="{{ route('admin.riwayat-kegiatan.show', $kegiatan->id) }}?{{ http_build_query($detailParams) }}"
|
||||||
|
class="btn-rw-detail">
|
||||||
|
<i class="fas fa-users"></i> Lihat Santri
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -2,228 +2,406 @@
|
||||||
@extends('layouts.app')
|
@extends('layouts.app')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="page-header">
|
<style>
|
||||||
<h2><i class="fas fa-user-clock"></i> Riwayat Kehadiran: {{ $santri->nama_lengkap }}</h2>
|
/* =====================================================
|
||||||
</div>
|
DETAIL SANTRI — Riwayat Kehadiran
|
||||||
|
===================================================== */
|
||||||
|
|
||||||
<!-- Info Santri -->
|
.ds-header { display:flex; justify-content:space-between; align-items:flex-start; gap:12px;
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
margin-bottom:18px; flex-wrap:wrap; }
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
.ds-header h2 { margin:0; font-size:1.3rem; color:var(--primary-dark); display:flex; align-items:center; gap:9px; }
|
||||||
<div>
|
|
||||||
<h3 style="margin: 0; color: var(--primary-color);">{{ $santri->nama_lengkap }}</h3>
|
/* Info santri */
|
||||||
<p style="margin: 5px 0 0 0; color: var(--text-light);">
|
.ds-info-box { background:#fff; border-radius:12px; padding:16px 20px; margin-bottom:14px;
|
||||||
ID: <strong>{{ $santri->id_santri }}</strong> |
|
box-shadow:0 2px 10px rgba(0,0,0,0.06); display:flex; justify-content:space-between;
|
||||||
Kelas: <strong>{{ $santri->kelas }}</strong> |
|
align-items:center; flex-wrap:wrap; gap:12px; }
|
||||||
Status: <span class="badge badge-success">{{ $santri->status }}</span>
|
.ds-info-box h3 { margin:0 0 5px; color:var(--primary-color); font-size:1.1rem; }
|
||||||
</p>
|
.ds-info-meta { font-size:0.83rem; color:#64748b; display:flex; flex-wrap:wrap; gap:10px; }
|
||||||
</div>
|
.ds-info-meta span { display:inline-flex; align-items:center; gap:4px; }
|
||||||
<a href="{{ route('admin.riwayat-kegiatan.index') }}" class="btn btn-secondary">
|
|
||||||
|
/* KPI cards */
|
||||||
|
.ds-kpi-grid { display:grid; grid-template-columns:repeat(5,1fr); gap:10px; margin-bottom:14px; }
|
||||||
|
@media(max-width:900px) { .ds-kpi-grid { grid-template-columns:repeat(3,1fr); } }
|
||||||
|
@media(max-width:540px) { .ds-kpi-grid { grid-template-columns:repeat(2,1fr); } }
|
||||||
|
|
||||||
|
.ds-kpi { background:#fff; border-radius:10px; padding:12px 14px;
|
||||||
|
box-shadow:0 2px 8px rgba(0,0,0,0.06); display:flex; align-items:center; gap:10px; }
|
||||||
|
.ds-kpi .ico { width:36px; height:36px; border-radius:9px; display:flex; align-items:center;
|
||||||
|
justify-content:center; font-size:1.1rem; flex-shrink:0; }
|
||||||
|
.ds-kpi.hadir .ico { background:#d1fae5; color:#065f46; }
|
||||||
|
.ds-kpi.terlambat .ico { background:#fff3e0; color:#e65100; }
|
||||||
|
.ds-kpi.izin .ico { background:#fef3c7; color:#92400e; }
|
||||||
|
.ds-kpi.sakit .ico { background:#dbeafe; color:#1e40af; }
|
||||||
|
.ds-kpi.alpa .ico { background:#fee2e2; color:#991b1b; }
|
||||||
|
.ds-kpi .cnt { font-size:1.4rem; font-weight:800; color:var(--primary-dark); line-height:1; }
|
||||||
|
.ds-kpi .lbl { font-size:0.74rem; color:#94a3b8; margin-top:2px; }
|
||||||
|
|
||||||
|
/* Terlambat note */
|
||||||
|
.ds-terlambat-note { font-size:0.76rem; color:#6b7280; background:#fff7ed; border:1px solid #fed7aa;
|
||||||
|
border-radius:8px; padding:6px 12px; margin-bottom:14px;
|
||||||
|
display:flex; align-items:center; gap:6px; }
|
||||||
|
.ds-terlambat-note i { color:#ea580c; }
|
||||||
|
|
||||||
|
/* Tren chart box */
|
||||||
|
.ds-chart-box { background:#fff; border-radius:12px; padding:16px 18px; margin-bottom:14px;
|
||||||
|
box-shadow:0 2px 10px rgba(0,0,0,0.06); }
|
||||||
|
.ds-chart-box h4 { margin:0 0 14px; color:var(--primary-color); font-size:0.95rem;
|
||||||
|
display:flex; align-items:center; gap:7px; }
|
||||||
|
|
||||||
|
/* Riwayat lengkap dengan tabs */
|
||||||
|
.ds-riwayat-box { background:#fff; border-radius:12px; overflow:hidden; margin-bottom:14px;
|
||||||
|
box-shadow:0 2px 10px rgba(0,0,0,0.06); }
|
||||||
|
.ds-riwayat-head { padding:14px 18px 0; border-bottom:2px solid #f1f5f9; }
|
||||||
|
.ds-riwayat-head h4 { margin:0 0 12px; color:var(--primary-dark); font-size:0.95rem;
|
||||||
|
display:flex; align-items:center; gap:7px; }
|
||||||
|
|
||||||
|
/* Tabs */
|
||||||
|
.ds-tabs { display:flex; gap:0; overflow-x:auto; -webkit-overflow-scrolling:touch; }
|
||||||
|
.ds-tabs::-webkit-scrollbar { height:0; }
|
||||||
|
.ds-tab { padding:9px 16px; font-size:0.82rem; font-weight:600; border:none; background:transparent;
|
||||||
|
cursor:pointer; white-space:nowrap; color:#64748b; border-bottom:3px solid transparent;
|
||||||
|
transition:all 0.15s; text-decoration:none; display:inline-flex; align-items:center; gap:6px; }
|
||||||
|
.ds-tab:hover { color:var(--primary-color); background:#f0fdf4; }
|
||||||
|
.ds-tab.active { color:var(--primary-color); border-bottom-color:var(--primary-color); background:#f0fdf4; }
|
||||||
|
.ds-tab .tab-cnt { background:#e8f7f2; color:var(--primary-color); padding:1px 7px; border-radius:10px;
|
||||||
|
font-size:0.72rem; font-weight:700; }
|
||||||
|
.ds-tab.active .tab-cnt { background:var(--primary-color); color:#fff; }
|
||||||
|
.ds-tab .tab-hadir { background:#d1fae5; color:#065f46; padding:1px 7px; border-radius:10px;
|
||||||
|
font-size:0.7rem; font-weight:700; }
|
||||||
|
|
||||||
|
/* Per-page toolbar */
|
||||||
|
.ds-toolbar { display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap;
|
||||||
|
gap:8px; padding:10px 18px; background:#fafafa; border-bottom:1px solid #f1f5f9; }
|
||||||
|
.ds-toolbar-left { font-size:0.8rem; color:#64748b; }
|
||||||
|
.ds-toolbar-right { display:flex; align-items:center; gap:8px; font-size:0.8rem; color:#64748b; }
|
||||||
|
.ds-perpage-group { display:flex; gap:4px; }
|
||||||
|
.ds-pp-btn { padding:4px 10px; border:1.5px solid #e2e8f0; border-radius:6px; background:#fff;
|
||||||
|
font-size:0.78rem; font-weight:600; color:#64748b; cursor:pointer;
|
||||||
|
text-decoration:none; transition:all 0.15s; }
|
||||||
|
.ds-pp-btn:hover { border-color:var(--primary-color); color:var(--primary-color); }
|
||||||
|
.ds-pp-btn.active { background:var(--primary-color); color:#fff; border-color:var(--primary-color); }
|
||||||
|
|
||||||
|
/* Table */
|
||||||
|
.ds-table-wrap { overflow-x:auto; }
|
||||||
|
.ds-table { width:100%; border-collapse:collapse; min-width:540px; }
|
||||||
|
.ds-table thead th { padding:9px 14px; text-align:left; font-size:0.78rem; font-weight:600;
|
||||||
|
color:#64748b; background:#f8fafc; border-bottom:1px solid #e2e8f0; }
|
||||||
|
.ds-table tbody td { padding:9px 14px; font-size:0.83rem; border-bottom:1px solid #f8fafc; vertical-align:middle; }
|
||||||
|
.ds-table tbody tr:last-child td { border-bottom:none; }
|
||||||
|
.ds-table tbody tr:hover { background:#f8fafc; }
|
||||||
|
|
||||||
|
/* Status badges (inline fallback jika status_badge tidak ada) */
|
||||||
|
.s-hadir { background:#d1fae5; color:#065f46; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
||||||
|
.s-terlambat { background:#fff3e0; color:#e65100; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
||||||
|
.s-izin { background:#fef3c7; color:#92400e; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
||||||
|
.s-sakit { background:#dbeafe; color:#1e40af; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
||||||
|
.s-alpa { background:#fee2e2; color:#991b1b; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
||||||
|
.s-pulang { background:#f3e8ff; color:#6b21a8; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
||||||
|
|
||||||
|
/* Button back */
|
||||||
|
.btn-ds-back { padding:8px 16px; background:#6b7280; color:#fff; border-radius:8px; font-size:0.82rem;
|
||||||
|
font-weight:600; text-decoration:none; display:inline-flex; align-items:center; gap:6px;
|
||||||
|
transition:background 0.18s; }
|
||||||
|
.btn-ds-back:hover { background:#4b5563; color:#fff; }
|
||||||
|
|
||||||
|
/* Empty */
|
||||||
|
.ds-empty { text-align:center; padding:30px; color:#94a3b8; }
|
||||||
|
.ds-empty i { font-size:2.5rem; display:block; margin-bottom:10px; opacity:0.35; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
@php
|
||||||
|
$totalHadirEfektif = $stats['_hadir_efektif'] ?? 0;
|
||||||
|
$totalHadir = $stats['Hadir'] ?? 0;
|
||||||
|
$totalTerlambat = $stats['Terlambat'] ?? 0;
|
||||||
|
$totalIzin = $stats['Izin'] ?? 0;
|
||||||
|
$totalSakit = $stats['Sakit'] ?? 0;
|
||||||
|
$totalAlpa = $stats['Alpa'] ?? 0;
|
||||||
|
|
||||||
|
$persenHadir = ($totalHadirEfektif + $totalIzin + $totalSakit + $totalAlpa) > 0
|
||||||
|
? round($totalHadirEfektif / ($totalHadirEfektif + $totalIzin + $totalSakit + $totalAlpa) * 100, 1)
|
||||||
|
: 0;
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
{{-- Header --}}
|
||||||
|
<div class="ds-header">
|
||||||
|
<h2><i class="fas fa-user-clock" style="color:var(--primary-color);"></i>
|
||||||
|
Riwayat Kehadiran: {{ $santri->nama_lengkap }}
|
||||||
|
</h2>
|
||||||
|
<a href="{{ route('admin.riwayat-kegiatan.index') }}" class="btn-ds-back">
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Statistik Cards -->
|
{{-- Info Santri --}}
|
||||||
<div class="row-cards">
|
<div class="ds-info-box">
|
||||||
<div class="card card-success">
|
<div>
|
||||||
<h3>Total Hadir</h3>
|
<h3>{{ $santri->nama_lengkap }}</h3>
|
||||||
<div class="card-value">{{ $stats['Hadir'] ?? 0 }}</div>
|
<div class="ds-info-meta">
|
||||||
<i class="fas fa-check-circle card-icon"></i>
|
<span><i class="fas fa-id-card"></i> <strong>{{ $santri->id_santri }}</strong></span>
|
||||||
|
<span><i class="fas fa-school"></i> {{ $santri->kelas }}</span>
|
||||||
|
<span><i class="fas fa-circle" style="font-size:0.5rem; color:#22c55e;"></i>
|
||||||
|
<span class="badge badge-success" style="font-size:0.76rem;">{{ $santri->status }}</span>
|
||||||
|
</span>
|
||||||
|
@if($persenHadir > 0)
|
||||||
|
<span style="font-weight:700; color:{{ $persenHadir >= 85 ? '#059669' : ($persenHadir >= 70 ? '#d97706' : '#dc2626') }};">
|
||||||
|
<i class="fas fa-chart-pie"></i> Kehadiran {{ $persenHadir }}%
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="card card-warning">
|
|
||||||
<h3>Total Izin</h3>
|
|
||||||
<div class="card-value">{{ $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">{{ $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">{{ $stats['Alpa'] ?? 0 }}</div>
|
|
||||||
<i class="fas fa-times-circle card-icon"></i>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Grafik Kehadiran Per Kategori -->
|
{{-- Catatan logika Terlambat --}}
|
||||||
@if($statsByKategori->count() > 0)
|
@if($totalTerlambat > 0)
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
<div class="ds-terlambat-note">
|
||||||
<h3 style="margin: 0 0 20px 0; color: var(--primary-color);">
|
<i class="fas fa-info-circle"></i>
|
||||||
<i class="fas fa-chart-bar"></i> Kehadiran Per Kategori
|
<strong>{{ $totalTerlambat }}x Terlambat</strong> dihitung sebagai <strong>Hadir</strong> (bukan Alpa).
|
||||||
</h3>
|
Total hadir efektif: <strong>{{ $totalHadirEfektif }}</strong> kali
|
||||||
<canvas id="chartKategori" style="max-height: 300px;"></canvas>
|
({{ $totalHadir }} hadir tepat waktu + {{ $totalTerlambat }} terlambat).
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<!-- Grafik Tren 30 Hari -->
|
{{-- KPI Cards --}}
|
||||||
|
<div class="ds-kpi-grid">
|
||||||
|
<div class="ds-kpi hadir">
|
||||||
|
<div class="ico"><i class="fas fa-check-circle"></i></div>
|
||||||
|
<div>
|
||||||
|
<div class="cnt">{{ $totalHadirEfektif }}</div>
|
||||||
|
<div class="lbl">Hadir Efektif</div>
|
||||||
|
@if($totalTerlambat > 0)
|
||||||
|
<div style="font-size:0.68rem; color:#94a3b8;">{{ $totalHadir }}+{{ $totalTerlambat }}tl</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ds-kpi terlambat">
|
||||||
|
<div class="ico"><i class="fas fa-clock"></i></div>
|
||||||
|
<div><div class="cnt">{{ $totalTerlambat }}</div><div class="lbl">Terlambat</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="ds-kpi izin">
|
||||||
|
<div class="ico"><i class="fas fa-envelope"></i></div>
|
||||||
|
<div><div class="cnt">{{ $totalIzin }}</div><div class="lbl">Izin</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="ds-kpi sakit">
|
||||||
|
<div class="ico"><i class="fas fa-heartbeat"></i></div>
|
||||||
|
<div><div class="cnt">{{ $totalSakit }}</div><div class="lbl">Sakit</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="ds-kpi alpa">
|
||||||
|
<div class="ico"><i class="fas fa-times-circle"></i></div>
|
||||||
|
<div><div class="cnt">{{ $totalAlpa }}</div><div class="lbl">Alpa</div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Tren 30 Hari --}}
|
||||||
@if($riwayat30Hari->count() > 0)
|
@if($riwayat30Hari->count() > 0)
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
<div class="ds-chart-box">
|
||||||
<h3 style="margin: 0 0 20px 0; color: var(--primary-color);">
|
<h4><i class="fas fa-chart-line"></i> Tren Kehadiran 30 Hari Terakhir
|
||||||
<i class="fas fa-chart-line"></i> Tren Kehadiran 30 Hari Terakhir
|
<span style="font-size:0.76rem; font-weight:400; color:#94a3b8; margin-left:4px;">
|
||||||
</h3>
|
(Hadir + Terlambat)
|
||||||
<canvas id="chartTren" style="max-height: 250px;"></canvas>
|
</span>
|
||||||
|
</h4>
|
||||||
|
<canvas id="chartTren" style="max-height:220px;"></canvas>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<!-- Kehadiran Per Kelas Santri -->
|
{{-- ── RIWAYAT LENGKAP (Tabbed per Kategori) ──────────────────────────────── --}}
|
||||||
@if($statsByKelasSantri->count() > 0)
|
<div class="ds-riwayat-box">
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
<div class="ds-riwayat-head">
|
||||||
<h3 style="margin: 0 0 20px 0; color: var(--primary-color);">
|
<h4><i class="fas fa-list-alt" style="color:var(--primary-color);"></i> Riwayat Lengkap per Kategori</h4>
|
||||||
<i class="fas fa-layer-group"></i> Kehadiran Per Kelas
|
|
||||||
</h3>
|
@if($kategoriList->count() > 0)
|
||||||
<div class="table-wrapper">
|
{{-- Tab list --}}
|
||||||
<table class="data-table">
|
<div class="ds-tabs" role="tablist">
|
||||||
|
@foreach($kategoriList as $kat)
|
||||||
|
@php
|
||||||
|
$tabParams = array_merge(request()->query(), [
|
||||||
|
'tab_kat' => $kat->kategori_id,
|
||||||
|
'per_page' => $perPage,
|
||||||
|
'page' => 1,
|
||||||
|
]);
|
||||||
|
$isActive = ($activeKategori == $kat->kategori_id);
|
||||||
|
$pctKat = $kat->total > 0 ? round($kat->hadir_efektif / $kat->total * 100) : 0;
|
||||||
|
@endphp
|
||||||
|
<a href="{{ route('admin.riwayat-kegiatan.detail-santri', $santri->id_santri) }}?{{ http_build_query($tabParams) }}"
|
||||||
|
class="ds-tab {{ $isActive ? 'active' : '' }}"
|
||||||
|
role="tab">
|
||||||
|
<i class="fas fa-tag" style="font-size:0.72rem;"></i>
|
||||||
|
{{ $kat->nama_kategori }}
|
||||||
|
<span class="tab-cnt">{{ $kat->total }}</span>
|
||||||
|
@if($kat->hadir_efektif > 0)
|
||||||
|
<span class="tab-hadir" title="Hadir efektif">{{ $pctKat }}%</span>
|
||||||
|
@endif
|
||||||
|
</a>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if($riwayats->count() > 0)
|
||||||
|
|
||||||
|
{{-- Toolbar: info + per-page --}}
|
||||||
|
<div class="ds-toolbar">
|
||||||
|
<div class="ds-toolbar-left">
|
||||||
|
@if(!$showAll)
|
||||||
|
Menampilkan
|
||||||
|
<strong>{{ $riwayats->firstItem() }}–{{ $riwayats->lastItem() }}</strong>
|
||||||
|
dari <strong>{{ $riwayats->total() }}</strong> riwayat
|
||||||
|
@else
|
||||||
|
Menampilkan <strong>semua {{ $riwayats->total() }}</strong> riwayat
|
||||||
|
@endif
|
||||||
|
@php $activeKat = $kategoriList->firstWhere('kategori_id', $activeKategori); @endphp
|
||||||
|
@if($activeKat)
|
||||||
|
— <span style="color:var(--primary-color); font-weight:600;">{{ $activeKat->nama_kategori }}</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
<div class="ds-toolbar-right">
|
||||||
|
Tampilkan:
|
||||||
|
<div class="ds-perpage-group">
|
||||||
|
@foreach([15, 50, 100] as $pp)
|
||||||
|
@php $ppParams = array_merge(request()->query(), ['per_page' => $pp, 'page' => 1]); @endphp
|
||||||
|
<a href="{{ route('admin.riwayat-kegiatan.detail-santri', $santri->id_santri) }}?{{ http_build_query($ppParams) }}"
|
||||||
|
class="ds-pp-btn {{ (!$showAll && $perPage == $pp) ? 'active' : '' }}">
|
||||||
|
{{ $pp }}
|
||||||
|
</a>
|
||||||
|
@endforeach
|
||||||
|
{{-- Semua --}}
|
||||||
|
@php $allParams = array_merge(request()->query(), ['per_page' => 'all', 'page' => 1]); @endphp
|
||||||
|
<a href="{{ route('admin.riwayat-kegiatan.detail-santri', $santri->id_santri) }}?{{ http_build_query($allParams) }}"
|
||||||
|
class="ds-pp-btn {{ $showAll ? 'active' : '' }}"
|
||||||
|
title="Tampilkan semua data sekaligus (bisa lambat jika data banyak)">
|
||||||
|
Semua
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Table --}}
|
||||||
|
<div class="ds-table-wrap">
|
||||||
|
<table class="ds-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Kelompok</th>
|
<th style="width:50px;">No</th>
|
||||||
<th>Kelas</th>
|
<th style="width:110px;">Tanggal</th>
|
||||||
<th style="width: 120px; text-align: center;">Total Kegiatan</th>
|
<th>Nama Kegiatan</th>
|
||||||
<th style="width: 120px; text-align: center;">Hadir</th>
|
<th style="width:115px; text-align:center;">Status</th>
|
||||||
<th style="width: 150px; text-align: center;">Persentase</th>
|
<th style="width:90px; text-align:center;">Waktu</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach($statsByKelasSantri as $stat)
|
@foreach($riwayats as $idx => $riwayat)
|
||||||
<tr>
|
<tr>
|
||||||
<td><span class="badge badge-info">{{ $stat['kelompok'] }}</span></td>
|
<td style="color:#94a3b8; font-size:0.78rem;">{{ $riwayats->firstItem() + $idx }}</td>
|
||||||
<td><strong>{{ $stat['kelas'] }}</strong></td>
|
<td style="font-size:0.81rem; color:#64748b;">
|
||||||
<td class="text-center">{{ $stat['total'] }}</td>
|
{{ $riwayat->tanggal->format('d/m/Y') }}
|
||||||
<td class="text-center"><strong>{{ $stat['hadir'] }}</strong></td>
|
<div style="font-size:0.71rem; color:#94a3b8;">
|
||||||
<td class="text-center">
|
{{ $riwayat->tanggal->locale('id')->isoFormat('ddd') }}
|
||||||
<div style="display: flex; align-items: center; gap: 10px;">
|
|
||||||
<div style="flex: 1; background: #e9ecef; border-radius: 10px; height: 20px; overflow: hidden;">
|
|
||||||
<div style="background:
|
|
||||||
@if($stat['persen'] >= 85) var(--success-color)
|
|
||||||
@elseif($stat['persen'] >= 70) var(--warning-color)
|
|
||||||
@else var(--danger-color)
|
|
||||||
@endif;
|
|
||||||
height: 100%; width: {{ $stat['persen'] }}%;
|
|
||||||
transition: width 0.3s ease;">
|
|
||||||
</div>
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong style="font-size:0.85rem;">{{ $riwayat->kegiatan->nama_kegiatan }}</strong>
|
||||||
|
<div style="font-size:0.74rem; color:#94a3b8; margin-top:1px;">
|
||||||
|
<i class="fas fa-clock"></i>
|
||||||
|
{{ date('H:i', strtotime($riwayat->kegiatan->waktu_mulai)) }}–{{ date('H:i', strtotime($riwayat->kegiatan->waktu_selesai)) }}
|
||||||
</div>
|
</div>
|
||||||
<strong style="min-width: 45px;">{{ $stat['persen'] }}%</strong>
|
</td>
|
||||||
</div>
|
<td style="text-align:center;">
|
||||||
|
@if(method_exists($riwayat, 'getStatusBadgeAttribute') || isset($riwayat->status_badge))
|
||||||
|
{!! $riwayat->status_badge !!}
|
||||||
|
@else
|
||||||
|
@php $st = $riwayat->status; @endphp
|
||||||
|
<span class="s-{{ strtolower($st) }}">{{ $st }}</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td style="text-align:center; font-size:0.81rem; color:#64748b;">
|
||||||
|
{{ $riwayat->waktu_absen ? date('H:i', strtotime($riwayat->waktu_absen)) : '–' }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<!-- Riwayat Lengkap -->
|
{{-- Pagination (disembunyikan jika mode Semua) --}}
|
||||||
<div class="content-box">
|
@if(!$showAll && $riwayats->lastPage() > 1)
|
||||||
<h3 style="margin: 0 0 20px 0; color: var(--primary-color);">
|
<div style="padding:12px 16px;">
|
||||||
<i class="fas fa-list"></i> Riwayat Lengkap
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
@if($riwayats->count() > 0)
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 50px;">No</th>
|
|
||||||
<th style="width: 120px;">Tanggal</th>
|
|
||||||
<th>Kegiatan</th>
|
|
||||||
<th style="width: 150px;">Kategori</th>
|
|
||||||
<th style="width: 130px; text-align: center;">Status</th>
|
|
||||||
<th style="width: 100px;">Waktu</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach($riwayats as $index => $riwayat)
|
|
||||||
<tr>
|
|
||||||
<td>{{ $riwayats->firstItem() + $index }}</td>
|
|
||||||
<td>{{ $riwayat->tanggal->format('d/m/Y') }}</td>
|
|
||||||
<td>{{ $riwayat->kegiatan->nama_kegiatan }}</td>
|
|
||||||
<td>{{ $riwayat->kegiatan->kategori->nama_kategori }}</td>
|
|
||||||
<td class="text-center">{!! $riwayat->status_badge !!}</td>
|
|
||||||
<td>{{ $riwayat->waktu_absen ? date('H:i', strtotime($riwayat->waktu_absen)) : '-' }}</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="margin-top: 14px;">
|
|
||||||
{{ $riwayats->links() }}
|
{{ $riwayats->links() }}
|
||||||
</div>
|
</div>
|
||||||
@else
|
@elseif($showAll)
|
||||||
<div class="empty-state">
|
<div style="padding:10px 16px; font-size:0.78rem; color:#94a3b8; background:#fafafa; border-top:1px solid #f1f5f9;">
|
||||||
|
<i class="fas fa-info-circle"></i> Semua <strong>{{ $riwayats->total() }}</strong> data ditampilkan.
|
||||||
|
|
||||||
|
@php $backPaged = array_merge(request()->query(), ['per_page' => 15, 'page' => 1]); @endphp
|
||||||
|
<a href="{{ route('admin.riwayat-kegiatan.detail-santri', $santri->id_santri) }}?{{ http_build_query($backPaged) }}"
|
||||||
|
style="color:var(--primary-color);">Kembali ke paginasi</a>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@elseif($kategoriList->count() > 0)
|
||||||
|
<div class="ds-empty">
|
||||||
<i class="fas fa-inbox"></i>
|
<i class="fas fa-inbox"></i>
|
||||||
<h3>Belum Ada Riwayat</h3>
|
<p>Belum ada riwayat untuk kategori ini.</p>
|
||||||
<p>Santri ini belum memiliki riwayat kehadiran.</p>
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="ds-empty">
|
||||||
|
<i class="fas fa-inbox"></i>
|
||||||
|
<p>Santri ini belum memiliki riwayat kehadiran apapun.</p>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
{{-- ── CHART JS ─────────────────────────────────────────────────────────────── --}}
|
||||||
|
|
||||||
@if($statsByKategori->count() > 0)
|
|
||||||
<script>
|
|
||||||
// Chart Kehadiran Per Kategori
|
|
||||||
const ctxKategori = document.getElementById('chartKategori');
|
|
||||||
new Chart(ctxKategori, {
|
|
||||||
type: 'bar',
|
|
||||||
data: {
|
|
||||||
labels: {!! json_encode($statsByKategori->pluck('nama_kategori')) !!},
|
|
||||||
datasets: [{
|
|
||||||
label: 'Hadir',
|
|
||||||
data: {!! json_encode($statsByKategori->pluck('hadir')) !!},
|
|
||||||
backgroundColor: '#6FBA9D',
|
|
||||||
borderWidth: 0
|
|
||||||
}, {
|
|
||||||
label: 'Total Kegiatan',
|
|
||||||
data: {!! json_encode($statsByKategori->pluck('total')) !!},
|
|
||||||
backgroundColor: '#E0F0EC',
|
|
||||||
borderWidth: 0
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: true,
|
|
||||||
plugins: {
|
|
||||||
legend: { position: 'bottom' }
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: { beginAtZero: true, ticks: { stepSize: 1 } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if($riwayat30Hari->count() > 0)
|
@if($riwayat30Hari->count() > 0)
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
<script>
|
<script>
|
||||||
// Chart Tren 30 Hari
|
(function() {
|
||||||
const ctxTren = document.getElementById('chartTren');
|
var ctx = document.getElementById('chartTren');
|
||||||
new Chart(ctxTren, {
|
if (!ctx) return;
|
||||||
|
|
||||||
|
var labels = {!! json_encode($riwayat30Hari->pluck('tanggal')->map(fn($d) => date('d/m', strtotime($d)))) !!};
|
||||||
|
var hadir = {!! json_encode($riwayat30Hari->pluck('hadir')) !!};
|
||||||
|
var total = {!! json_encode($riwayat30Hari->pluck('total')) !!};
|
||||||
|
|
||||||
|
new Chart(ctx, {
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: {
|
data: {
|
||||||
labels: {!! json_encode($riwayat30Hari->pluck('tanggal')->map(fn($d) => date('d/m', strtotime($d)))) !!},
|
labels: labels,
|
||||||
datasets: [{
|
datasets: [
|
||||||
label: 'Hadir',
|
{
|
||||||
data: {!! json_encode($riwayat30Hari->pluck('hadir')) !!},
|
label: 'Hadir (termasuk terlambat)',
|
||||||
|
data: hadir,
|
||||||
borderColor: '#6FBA9D',
|
borderColor: '#6FBA9D',
|
||||||
backgroundColor: 'rgba(111, 186, 157, 0.1)',
|
backgroundColor: 'rgba(111,186,157,0.12)',
|
||||||
tension: 0.4,
|
tension: 0.4,
|
||||||
fill: true
|
fill: true,
|
||||||
}]
|
pointRadius: 4,
|
||||||
|
pointBackgroundColor: '#6FBA9D',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Total Kegiatan',
|
||||||
|
data: total,
|
||||||
|
borderColor: '#cbd5e1',
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderDash: [5, 5],
|
||||||
|
tension: 0.4,
|
||||||
|
fill: false,
|
||||||
|
pointRadius: 0,
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
maintainAspectRatio: true,
|
maintainAspectRatio: true,
|
||||||
|
interaction: { mode: 'index', intersect: false },
|
||||||
plugins: {
|
plugins: {
|
||||||
legend: { display: false }
|
legend: { position: 'bottom', labels: { boxWidth: 12, font: { size: 11 } } }
|
||||||
},
|
},
|
||||||
scales: {
|
scales: {
|
||||||
y: { beginAtZero: true, ticks: { stepSize: 1 } }
|
y: { beginAtZero: true, ticks: { stepSize: 1 }, grid: { color: '#f1f5f9' } },
|
||||||
|
x: { grid: { display: false }, ticks: { font: { size: 10 } } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
@ -3,292 +3,459 @@
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<style>
|
<style>
|
||||||
.day-group { margin-bottom: 18px; background: #fff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); overflow: hidden; }
|
/* ============================================================
|
||||||
.day-header { background: linear-gradient(135deg, #f0fdf4 0%, #E8F7F2 100%); padding: 13px 18px; display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #E8F7F2; cursor: pointer; transition: background 0.2s; user-select: none; }
|
RIWAYAT KEGIATAN — INDEX (v3)
|
||||||
.day-header:hover{ background: linear-gradient(135deg, #E8F7F2 0%, #d1f2e8 100%); }
|
============================================================ */
|
||||||
.day-title { font-weight: 700; font-size: 1rem; color: var(--primary-dark); display: flex; align-items: center; gap: 8px; }
|
|
||||||
.day-title i { color: var(--primary-color); }
|
|
||||||
.day-meta { display: flex; gap: 10px; align-items: center; }
|
|
||||||
.day-count { background: var(--primary-color); color: #fff; padding: 3px 10px; border-radius: 20px; font-size: 0.78rem; font-weight: 600; }
|
|
||||||
.toggle-icon { transition: transform 0.3s; font-size: 0.85rem; color: #94a3b8; }
|
|
||||||
.toggle-icon.collapsed { transform: rotate(-90deg); }
|
|
||||||
.day-body { overflow: hidden; }
|
|
||||||
.day-body table { width: 100%; border-collapse: collapse; }
|
|
||||||
.day-body thead { background: #f8fafc; }
|
|
||||||
.day-body th { padding: 9px 14px; text-align: left; font-weight: 600; font-size: 0.8rem; color: #64748b; border-bottom: 1px solid #e2e8f0; }
|
|
||||||
.day-body td { padding: 10px 14px; font-size: 0.85rem; border-bottom: 1px solid #f1f5f9; vertical-align: middle; }
|
|
||||||
.day-body tbody tr:last-child td { border-bottom: none; }
|
|
||||||
.day-body tbody tr:hover { background: #f8fafc; }
|
|
||||||
|
|
||||||
.stat-chips { display: flex; gap: 5px; flex-wrap: wrap; }
|
.rw-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:16px; flex-wrap:wrap; gap:10px; }
|
||||||
.chip { padding: 2px 8px; border-radius: 10px; font-size: 0.74rem; font-weight: 600; display: inline-flex; align-items: center; gap: 3px; }
|
.rw-header h2 { margin:0; font-size:1.35rem; color:var(--primary-dark); display:flex; align-items:center; gap:9px; }
|
||||||
.chip-hadir { background: #D1FAE5; color: #065F46; }
|
.rw-header h2 i { color:var(--primary-color); }
|
||||||
.chip-terlambat { background: #FFF3E0; color: #E65100; }
|
|
||||||
.chip-izin { background: #FEF3C7; color: #92400E; }
|
|
||||||
.chip-sakit { background: #DBEAFE; color: #1E40AF; }
|
|
||||||
.chip-alpa { background: #FEE2E2; color: #991B1B; }
|
|
||||||
.chip-pulang { background: #F3E8FF; color: #6B21A8; }
|
|
||||||
.chip-none { background: #F1F5F9; color: #94a3b8; }
|
|
||||||
.kelas-tag { display: inline-block; background: #E8F7F2; color: var(--primary-dark); padding: 2px 7px; border-radius: 8px; font-size: 0.74rem; margin: 2px 2px 0 0; }
|
|
||||||
.umum-tag { display: inline-block; background: #F1F5F9; color: #64748b; padding: 2px 7px; border-radius: 8px; font-size: 0.74rem; }
|
|
||||||
.btn-detail { padding: 5px 12px; background: var(--primary-color); color: #fff; border: none; border-radius: 6px; font-size: 0.8rem; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; transition: all 0.2s; }
|
|
||||||
.btn-detail:hover { background: #059669; color: #fff; transform: translateY(-1px); }
|
|
||||||
|
|
||||||
.filter-box { background: #fff; padding: 14px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); margin-bottom: 14px; }
|
/* Filter */
|
||||||
.filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px; }
|
.rw-filter { background:#fff; border-radius:12px; box-shadow:0 2px 10px rgba(0,0,0,.06); padding:14px 18px; margin-bottom:14px; }
|
||||||
.form-group { margin: 0; }
|
.rw-mode-tabs { display:flex; gap:6px; margin-bottom:14px; flex-wrap:wrap; }
|
||||||
.form-group label { display: block; font-size: 0.85rem; margin-bottom: 5px; color: var(--text-light); font-weight: 500; }
|
.rw-tab { padding:7px 18px; border-radius:22px; border:1.5px solid #e2e8f0; background:#fff;
|
||||||
.form-control { width: 100%; padding: 8px 12px; border: 1px solid #e2e8f0; border-radius: 8px; font-size: 0.85rem; }
|
font-size:0.82rem; font-weight:600; cursor:pointer; text-decoration:none;
|
||||||
.btn-filter { background: var(--primary-color); color: #fff; border: none; padding: 9px 16px; border-radius: 8px; cursor: pointer; font-size: 0.85rem; display: inline-flex; align-items: center; gap: 6px; transition: all 0.2s; }
|
color:#64748b; transition:all .18s; display:inline-flex; align-items:center; gap:6px; }
|
||||||
.btn-filter:hover { background: #059669; transform: translateY(-1px); }
|
.rw-tab:hover { border-color:var(--primary-color); color:var(--primary-color); background:#f0fdf4; }
|
||||||
.btn-reset { background: #6B7280; color: #fff; border: none; padding: 9px 12px; border-radius: 8px; cursor: pointer; font-size: 0.85rem; display: inline-flex; align-items: center; gap: 6px; text-decoration: none; }
|
.rw-tab.active { background:var(--primary-color); color:#fff; border-color:var(--primary-color); box-shadow:0 2px 8px rgba(16,185,129,.25); }
|
||||||
.btn-reset:hover { background: #4B5563; }
|
.rw-filter-row { display:flex; gap:10px; align-items:flex-end; flex-wrap:wrap; }
|
||||||
|
.rw-fg { display:flex; flex-direction:column; gap:4px; }
|
||||||
|
.rw-fg label { font-size:0.78rem; font-weight:600; color:#64748b; }
|
||||||
|
.rw-fg .form-control { padding:7px 11px; font-size:0.84rem; border:1.5px solid #e2e8f0; border-radius:8px; }
|
||||||
|
.rw-fg .form-control:focus { border-color:var(--primary-color); outline:none; }
|
||||||
|
.btn-rw-apply { background:var(--primary-color); color:#fff; border:none; padding:8px 18px; border-radius:8px;
|
||||||
|
font-size:0.84rem; font-weight:600; cursor:pointer; display:inline-flex; align-items:center; gap:6px;
|
||||||
|
align-self:flex-end; white-space:nowrap; }
|
||||||
|
.btn-rw-apply:hover { background:#059669; }
|
||||||
|
.btn-rw-reset { background:#f1f5f9; color:#64748b; border:1.5px solid #e2e8f0; padding:8px 12px; border-radius:8px;
|
||||||
|
font-size:0.84rem; font-weight:600; text-decoration:none;
|
||||||
|
display:inline-flex; align-items:center; gap:6px; align-self:flex-end; }
|
||||||
|
.btn-rw-reset:hover { background:#e2e8f0; }
|
||||||
|
|
||||||
.period-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
|
/* Periode label */
|
||||||
.period-tab { padding: 5px 14px; border-radius: 20px; border: 1px solid #e2e8f0; background: #fff; font-size: 0.82rem; cursor: pointer; text-decoration: none; color: var(--text-dark); transition: all 0.2s; display: inline-flex; align-items: center; gap: 5px; }
|
.rw-periode { background:linear-gradient(90deg,#f0fdf4,#e8f7f2); border-left:3px solid var(--primary-color);
|
||||||
.period-tab:hover, .period-tab.active { background: var(--primary-color); color: #fff; border-color: var(--primary-color); }
|
border-radius:8px; padding:9px 14px; margin-bottom:14px; font-size:0.84rem; color:#374151;
|
||||||
|
display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
|
||||||
|
.rw-periode i { color:var(--primary-color); }
|
||||||
|
|
||||||
.periode-info { font-size: 0.82rem; color: var(--text-light); margin-bottom: 12px; padding: 8px 12px; background: #f0fdf4; border-radius: 8px; border-left: 3px solid var(--primary-color); }
|
/* KPI strip */
|
||||||
.periode-info strong { color: var(--primary-color); }
|
.rw-kpi-strip { display:grid; grid-template-columns:repeat(auto-fit,minmax(105px,1fr)); gap:8px; margin-bottom:14px; }
|
||||||
|
.rw-kpi { background:#fff; border-radius:10px; padding:11px 14px; box-shadow:0 2px 8px rgba(0,0,0,.05); text-align:center; }
|
||||||
|
.rw-kpi-val { font-size:1.45rem; font-weight:800; line-height:1; }
|
||||||
|
.rw-kpi-lbl { font-size:0.73rem; color:#94a3b8; margin-top:4px; font-weight:500; }
|
||||||
|
.rw-kpi-sub { font-size:0.68rem; color:#cbd5e1; margin-top:2px; }
|
||||||
|
|
||||||
.empty-state { text-align: center; padding: 44px 14px; color: var(--text-light); background: #fff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
|
/* Per-date block */
|
||||||
.empty-state i { font-size: 3.5rem; margin-bottom: 14px; opacity: 0.3; display: block; }
|
.rw-date-block { margin-bottom:20px; }
|
||||||
.empty-state h3 { margin: 0 0 6px; }
|
.rw-date-header { display:flex; align-items:center; gap:10px; padding:10px 16px; flex-wrap:wrap;
|
||||||
|
background:linear-gradient(90deg,var(--primary-color),#0ea574);
|
||||||
|
border-radius:10px 10px 0 0; color:#fff; }
|
||||||
|
.rw-date-today { background:linear-gradient(90deg,#0ea574,#059669); }
|
||||||
|
.dh-date { font-size:1rem; font-weight:700; }
|
||||||
|
.dh-hari { background:rgba(255,255,255,.22); padding:2px 10px; border-radius:12px; font-size:0.78rem; font-weight:600; }
|
||||||
|
.dh-count { margin-left:auto; font-size:0.78rem; background:rgba(255,255,255,.2); padding:3px 10px; border-radius:12px; }
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
/* Table */
|
||||||
.day-header { flex-direction: column; align-items: flex-start; gap: 6px; }
|
.rw-tbl-wrap { background:#fff; border-radius:0 0 10px 10px; box-shadow:0 3px 12px rgba(0,0,0,.07); overflow-x:auto; }
|
||||||
.day-body th:nth-child(3), .day-body td:nth-child(3),
|
.rw-table { width:100%; border-collapse:collapse; min-width:680px; }
|
||||||
.day-body th:nth-child(4), .day-body td:nth-child(4) { display: none; }
|
.rw-table thead th { padding:9px 13px; text-align:left; font-size:0.78rem; font-weight:700;
|
||||||
|
color:#475569; background:#f8fafc; border-bottom:1.5px solid #e2e8f0; white-space:nowrap; }
|
||||||
|
.rw-table tbody td { padding:9px 13px; font-size:0.83rem; border-bottom:1px solid #f8fafc; vertical-align:middle; }
|
||||||
|
.rw-table tbody tr:last-child td { border-bottom:none; }
|
||||||
|
.rw-table tbody tr:hover { background:#f8fafc; }
|
||||||
|
.rw-table tfoot td { padding:8px 13px; }
|
||||||
|
|
||||||
|
/* Tags */
|
||||||
|
.rw-kelas-tag { background:#e8f7f2; color:var(--primary-dark); padding:2px 7px; border-radius:6px; font-size:.72rem; font-weight:600; margin-right:2px; display:inline-block; }
|
||||||
|
.rw-umum-tag { background:#f1f5f9; color:#64748b; padding:2px 7px; border-radius:6px; font-size:.72rem; font-weight:600; display:inline-block; }
|
||||||
|
.rw-kat-tag { background:#dbeafe; color:#1e40af; padding:2px 7px; border-radius:6px; font-size:.72rem; font-weight:600; display:inline-block; }
|
||||||
|
|
||||||
|
/* Mini progress */
|
||||||
|
.rw-mini-prog { height:6px; background:#f1f5f9; border-radius:3px; overflow:hidden; display:flex; min-width:70px; }
|
||||||
|
|
||||||
|
/* Button table */
|
||||||
|
.btn-tbl-detail { padding:5px 11px; background:var(--primary-color); color:#fff; border:none; border-radius:6px;
|
||||||
|
font-size:0.76rem; font-weight:600; text-decoration:none; display:inline-flex; align-items:center; gap:4px; white-space:nowrap; }
|
||||||
|
.btn-tbl-detail:hover { background:#059669; color:#fff; }
|
||||||
|
|
||||||
|
/* Cards (hari_ini) */
|
||||||
|
.rw-card { background:#fff; border-radius:12px; box-shadow:0 2px 10px rgba(0,0,0,.06); border:1px solid #f0f0f0; overflow:hidden; margin-bottom:10px; }
|
||||||
|
.rw-card:hover { box-shadow:0 4px 18px rgba(0,0,0,.1); }
|
||||||
|
.rw-card-head { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; padding:14px 18px 10px; border-bottom:1px solid #f1f5f9; flex-wrap:wrap; }
|
||||||
|
.rw-card-title { font-size:1rem; font-weight:700; color:var(--primary-dark); margin:0 0 5px; display:flex; align-items:center; gap:8px; }
|
||||||
|
.rw-card-meta { display:flex; gap:10px; flex-wrap:wrap; font-size:.8rem; color:#64748b; align-items:center; }
|
||||||
|
.rw-card-meta span{ display:inline-flex; align-items:center; gap:4px; }
|
||||||
|
.rw-status { padding:4px 12px; border-radius:20px; font-size:.76rem; font-weight:700; white-space:nowrap; flex-shrink:0; display:inline-flex; align-items:center; gap:5px; }
|
||||||
|
.rw-status.belum { background:#f1f5f9; color:#64748b; }
|
||||||
|
.rw-status.selesai{ background:#d1fae5; color:#065f46; }
|
||||||
|
.rw-status.brlgs { background:#fef9c3; color:#854d0e; }
|
||||||
|
.rw-card-body { padding:10px 18px 14px; }
|
||||||
|
.rw-stats-row { display:flex; gap:6px; flex-wrap:wrap; align-items:center; margin-bottom:10px; }
|
||||||
|
.rw-chip { padding:4px 10px; border-radius:10px; font-size:.76rem; font-weight:700; display:inline-flex; align-items:center; gap:4px; }
|
||||||
|
.rw-chip.hadir { background:#d1fae5; color:#065f46; }
|
||||||
|
.rw-chip.terlambat{ background:#fff3e0; color:#e65100; }
|
||||||
|
.rw-chip.izin { background:#fef3c7; color:#92400e; }
|
||||||
|
.rw-chip.sakit { background:#dbeafe; color:#1e40af; }
|
||||||
|
.rw-chip.alpa { background:#fee2e2; color:#991b1b; }
|
||||||
|
.rw-chip.pulang { background:#f3e8ff; color:#6b21a8; }
|
||||||
|
.rw-chip.none { background:#f1f5f9; color:#94a3b8; }
|
||||||
|
.rw-progress-wrap { height:8px; background:#f1f5f9; border-radius:4px; overflow:hidden; display:flex; margin-bottom:6px; }
|
||||||
|
.rw-prog-hadir { background:#22c55e; }
|
||||||
|
.rw-prog-terlambat{ background:#FF9800; }
|
||||||
|
.rw-prog-izin { background:#f59e0b; }
|
||||||
|
.rw-prog-sakit { background:#3b82f6; }
|
||||||
|
.rw-prog-alpa { background:#ef4444; }
|
||||||
|
.rw-prog-pulang { background:#a855f7; }
|
||||||
|
.rw-prog-belum { background:#e2e8f0; }
|
||||||
|
.rw-card-foot { display:flex; align-items:center; justify-content:space-between; padding:8px 18px; background:#fafafa; border-top:1px solid #f1f5f9; flex-wrap:wrap; gap:8px; }
|
||||||
|
.rw-total-txt { font-size:.78rem; color:#94a3b8; }
|
||||||
|
.rw-total-txt strong { color:#374151; }
|
||||||
|
.btn-rw-detail { padding:6px 16px; background:var(--primary-color); color:#fff; border:none; border-radius:7px; font-size:.82rem; font-weight:600; text-decoration:none; display:inline-flex; align-items:center; gap:5px; }
|
||||||
|
.btn-rw-detail:hover { background:#059669; color:#fff; }
|
||||||
|
|
||||||
|
/* Empty */
|
||||||
|
.rw-empty { text-align:center; padding:48px 20px; background:#fff; border-radius:12px; box-shadow:0 2px 10px rgba(0,0,0,.06); }
|
||||||
|
.rw-empty i { font-size:3rem; color:#cbd5e1; display:block; margin-bottom:12px; }
|
||||||
|
.rw-empty h3 { margin:0 0 6px; color:var(--primary-dark); }
|
||||||
|
.rw-empty p { margin:0; color:var(--text-light); font-size:.88rem; }
|
||||||
|
|
||||||
|
@media(max-width:640px) {
|
||||||
|
.rw-filter-row { flex-direction:column; }
|
||||||
|
.rw-fg { width:100%; }
|
||||||
|
.rw-fg .form-control { width:100%; }
|
||||||
|
.btn-rw-apply,.btn-rw-reset { width:100%; justify-content:center; }
|
||||||
|
.rw-kpi-strip { grid-template-columns:repeat(3,1fr); }
|
||||||
|
.dh-count { display:none; }
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@php
|
@php
|
||||||
// Default: minggu ini
|
$mode = $mode ?? 'hari_ini';
|
||||||
$defaultDari = now()->startOfWeek(\Carbon\Carbon::MONDAY)->format('Y-m-d');
|
$dari = $dari ?? now()->format('Y-m-d');
|
||||||
$defaultSampai = now()->endOfWeek(\Carbon\Carbon::SUNDAY)->format('Y-m-d');
|
$sampai = $sampai ?? now()->format('Y-m-d');
|
||||||
|
$tanggal = $tanggal ?? now()->format('Y-m-d');
|
||||||
|
$kategoriId = $kategoriId ?? '';
|
||||||
|
$passParams = ['mode' => $mode, 'dari' => $dari, 'sampai' => $sampai, 'tanggal' => $tanggal];
|
||||||
|
|
||||||
$activeDari = request('tanggal_dari', $defaultDari);
|
$totalAbsensi = $summary['total_absensi'] ?? 0;
|
||||||
$activeSampai = request('tanggal_sampai', $defaultSampai);
|
$totalHadir = $summary['hadir'] ?? 0;
|
||||||
$activeKategori = request('kategori_id', '');
|
$pctHadirGlbl = $totalAbsensi > 0 ? round($totalHadir / $totalAbsensi * 100, 1) : 0;
|
||||||
$activeBulan = request('bulan', '');
|
|
||||||
|
|
||||||
// Label periode
|
|
||||||
if ($activeBulan) {
|
|
||||||
$periodeLabel = 'Bulan ' . \Carbon\Carbon::parse($activeBulan . '-01')->locale('id')->isoFormat('MMMM Y');
|
|
||||||
} else {
|
|
||||||
$periodeLabel = \Carbon\Carbon::parse($activeDari)->locale('id')->isoFormat('D MMM Y')
|
|
||||||
. ' – '
|
|
||||||
. \Carbon\Carbon::parse($activeSampai)->locale('id')->isoFormat('D MMM Y');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cek shortcut aktif
|
|
||||||
$isMingguIni = !$activeBulan
|
|
||||||
&& $activeDari == $defaultDari
|
|
||||||
&& $activeSampai == $defaultSampai;
|
|
||||||
|
|
||||||
$isBulanIni = !$activeBulan
|
|
||||||
&& $activeDari == now()->startOfMonth()->format('Y-m-d')
|
|
||||||
&& $activeSampai == now()->endOfMonth()->format('Y-m-d');
|
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<div class="page-header">
|
{{-- PAGE HEADER --}}
|
||||||
<h2><i class="fas fa-history"></i> Riwayat Kegiatan & Absensi</h2>
|
<div class="rw-header">
|
||||||
|
<h2><i class="fas fa-history"></i> Riwayat Kegiatan & Absensi</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if(session('success'))
|
{{-- FILTER --}}
|
||||||
<div class="alert alert-success">
|
<div class="rw-filter">
|
||||||
<i class="fas fa-check-circle"></i> {{ session('success') }}
|
<div class="rw-mode-tabs">
|
||||||
</div>
|
<a href="{{ route('admin.riwayat-kegiatan.index', ['mode'=>'hari_ini','tanggal'=>$tanggal]) }}"
|
||||||
@endif
|
class="rw-tab {{ $mode==='hari_ini'?'active':'' }}">
|
||||||
|
<i class="fas fa-calendar-day"></i> Hari Ini
|
||||||
{{-- Filter --}}
|
</a>
|
||||||
<div class="filter-box">
|
<a href="{{ route('admin.riwayat-kegiatan.index', ['mode'=>'minggu_ini']) }}"
|
||||||
|
class="rw-tab {{ $mode==='minggu_ini'?'active':'' }}">
|
||||||
{{-- Shortcut tabs --}}
|
|
||||||
<div class="period-tabs">
|
|
||||||
<a href="{{ route('admin.riwayat-kegiatan.index', ['tanggal_dari' => $defaultDari, 'tanggal_sampai' => $defaultSampai, 'kategori_id' => $activeKategori]) }}"
|
|
||||||
class="period-tab {{ $isMingguIni ? 'active' : '' }}">
|
|
||||||
<i class="fas fa-calendar-week"></i> Minggu Ini
|
<i class="fas fa-calendar-week"></i> Minggu Ini
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ route('admin.riwayat-kegiatan.index', ['tanggal_dari' => now()->startOfMonth()->format('Y-m-d'), 'tanggal_sampai' => now()->endOfMonth()->format('Y-m-d'), 'kategori_id' => $activeKategori]) }}"
|
<a href="{{ route('admin.riwayat-kegiatan.index', ['mode'=>'custom','dari'=>$dari,'sampai'=>$sampai]) }}"
|
||||||
class="period-tab {{ $isBulanIni ? 'active' : '' }}">
|
class="rw-tab {{ $mode==='custom'?'active':'' }}">
|
||||||
<i class="fas fa-calendar-alt"></i> Bulan Ini
|
<i class="fas fa-sliders-h"></i> Rentang Tanggal
|
||||||
</a>
|
|
||||||
<a href="{{ route('admin.riwayat-kegiatan.index') }}"
|
|
||||||
class="period-tab {{ !$isMingguIni && !$isBulanIni ? 'active' : '' }}"
|
|
||||||
style="{{ !$isMingguIni && !$isBulanIni ? '' : 'display:none' }}">
|
|
||||||
<i class="fas fa-filter"></i> Custom
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form method="GET">
|
<form method="GET" action="{{ route('admin.riwayat-kegiatan.index') }}">
|
||||||
<div class="filter-grid">
|
|
||||||
<div class="form-group">
|
@if($mode === 'hari_ini')
|
||||||
<label for="kategori_id">Kategori</label>
|
<input type="hidden" name="mode" value="hari_ini">
|
||||||
<select name="kategori_id" id="kategori_id" class="form-control">
|
<div class="rw-filter-row">
|
||||||
<option value="">-- Semua Kategori --</option>
|
<div class="rw-fg">
|
||||||
|
<label><i class="fas fa-calendar-alt"></i> Tanggal</label>
|
||||||
|
<input type="date" name="tanggal" class="form-control" value="{{ $tanggal }}" style="max-width:180px;">
|
||||||
|
</div>
|
||||||
|
<div class="rw-fg">
|
||||||
|
<label><i class="fas fa-tag"></i> Kategori</label>
|
||||||
|
<select name="kategori_id" class="form-control" style="max-width:200px;">
|
||||||
|
<option value="">Semua Kategori</option>
|
||||||
@foreach($kategoris as $k)
|
@foreach($kategoris as $k)
|
||||||
<option value="{{ $k->kategori_id }}" {{ $activeKategori == $k->kategori_id ? 'selected' : '' }}>
|
<option value="{{ $k->kategori_id }}" {{ $kategoriId==$k->kategori_id?'selected':'' }}>{{ $k->nama_kategori }}</option>
|
||||||
{{ $k->nama_kategori }}
|
|
||||||
</option>
|
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<button type="submit" class="btn-rw-apply"><i class="fas fa-search"></i> Tampilkan</button>
|
||||||
<label for="tanggal_dari">Tanggal Dari</label>
|
<a href="{{ route('admin.riwayat-kegiatan.index') }}" class="btn-rw-reset"><i class="fas fa-undo"></i> Reset</a>
|
||||||
<input type="date" name="tanggal_dari" id="tanggal_dari" class="form-control" value="{{ $activeDari }}">
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<label for="tanggal_sampai">Tanggal Sampai</label>
|
@elseif($mode === 'minggu_ini')
|
||||||
<input type="date" name="tanggal_sampai" id="tanggal_sampai" class="form-control" value="{{ $activeSampai }}">
|
<input type="hidden" name="mode" value="minggu_ini">
|
||||||
|
<div class="rw-filter-row">
|
||||||
|
<div class="rw-fg">
|
||||||
|
<label><i class="fas fa-tag"></i> Kategori</label>
|
||||||
|
<select name="kategori_id" class="form-control" style="max-width:200px;">
|
||||||
|
<option value="">Semua Kategori</option>
|
||||||
|
@foreach($kategoris as $k)
|
||||||
|
<option value="{{ $k->kategori_id }}" {{ $kategoriId==$k->kategori_id?'selected':'' }}>{{ $k->nama_kategori }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<button type="submit" class="btn-rw-apply"><i class="fas fa-search"></i> Tampilkan</button>
|
||||||
<label for="bulan">Atau Pilih Bulan</label>
|
<a href="{{ route('admin.riwayat-kegiatan.index', ['mode'=>'minggu_ini']) }}" class="btn-rw-reset"><i class="fas fa-undo"></i> Reset</a>
|
||||||
<input type="month" name="bulan" id="bulan" class="form-control" value="{{ $activeBulan }}">
|
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; align-items: flex-end; gap: 10px;">
|
|
||||||
<button type="submit" class="btn-filter" style="flex: 1;">
|
@else
|
||||||
<i class="fas fa-filter"></i> Filter
|
<input type="hidden" name="mode" value="custom">
|
||||||
</button>
|
<div class="rw-filter-row">
|
||||||
<a href="{{ route('admin.riwayat-kegiatan.index') }}" class="btn-reset" title="Reset ke minggu ini">
|
<div class="rw-fg">
|
||||||
<i class="fas fa-undo"></i>
|
<label><i class="fas fa-calendar-alt"></i> Dari Tanggal</label>
|
||||||
</a>
|
<input type="date" name="dari" class="form-control" value="{{ $dari }}" style="max-width:180px;" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="rw-fg">
|
||||||
|
<label><i class="fas fa-calendar-alt"></i> Sampai Tanggal</label>
|
||||||
|
<input type="date" name="sampai" class="form-control" value="{{ $sampai }}" style="max-width:180px;" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="rw-fg">
|
||||||
|
<label><i class="fas fa-tag"></i> Kategori</label>
|
||||||
|
<select name="kategori_id" class="form-control" style="max-width:200px;">
|
||||||
|
<option value="">Semua Kategori</option>
|
||||||
|
@foreach($kategoris as $k)
|
||||||
|
<option value="{{ $k->kategori_id }}" {{ $kategoriId==$k->kategori_id?'selected':'' }}>{{ $k->nama_kategori }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn-rw-apply"><i class="fas fa-search"></i> Tampilkan</button>
|
||||||
|
<a href="{{ route('admin.riwayat-kegiatan.index', ['mode'=>'custom']) }}" class="btn-rw-reset"><i class="fas fa-undo"></i> Reset</a>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Info periode --}}
|
{{-- PERIODE LABEL --}}
|
||||||
<p class="periode-info">
|
<div class="rw-periode">
|
||||||
<i class="fas fa-calendar-check"></i> Menampilkan kegiatan periode: <strong>{{ $periodeLabel }}</strong>
|
<i class="fas fa-calendar-check"></i>
|
||||||
|
Menampilkan: <strong>{{ $periodeLabel }}</strong>
|
||||||
|
@if($mode !== 'hari_ini' && ($summary['jumlah_hari'] ?? 0) > 0)
|
||||||
|
<span style="color:#94a3b8;">·</span>
|
||||||
|
<strong style="color:var(--primary-color);">{{ $summary['jumlah_hari'] }}</strong> hari aktif
|
||||||
|
<span style="color:#94a3b8;">·</span>
|
||||||
|
<strong style="color:var(--primary-color);">{{ $summary['jumlah_kegiatan'] }}</strong> sesi
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- KPI STRIP --}}
|
||||||
|
@if($totalAbsensi > 0)
|
||||||
|
<div class="rw-kpi-strip">
|
||||||
|
<div class="rw-kpi">
|
||||||
|
<div class="rw-kpi-val" style="color:#065f46;">{{ $summary['hadir'] }}</div>
|
||||||
|
<div class="rw-kpi-lbl"><i class="fas fa-check" style="color:#22c55e;"></i> Hadir Efektif</div>
|
||||||
|
@if($summary['terlambat'] > 0)
|
||||||
|
<div class="rw-kpi-sub">+{{ $summary['terlambat'] }} terlambat</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
<div class="rw-kpi">
|
||||||
|
<div class="rw-kpi-val" style="color:#e65100;">{{ $summary['terlambat'] }}</div>
|
||||||
|
<div class="rw-kpi-lbl"><i class="fas fa-clock" style="color:#FF9800;"></i> Terlambat</div>
|
||||||
|
</div>
|
||||||
|
<div class="rw-kpi">
|
||||||
|
<div class="rw-kpi-val" style="color:#92400e;">{{ $summary['izin'] }}</div>
|
||||||
|
<div class="rw-kpi-lbl"><i class="fas fa-envelope" style="color:#f59e0b;"></i> Izin</div>
|
||||||
|
</div>
|
||||||
|
<div class="rw-kpi">
|
||||||
|
<div class="rw-kpi-val" style="color:#1e40af;">{{ $summary['sakit'] }}</div>
|
||||||
|
<div class="rw-kpi-lbl"><i class="fas fa-heartbeat" style="color:#3b82f6;"></i> Sakit</div>
|
||||||
|
</div>
|
||||||
|
<div class="rw-kpi">
|
||||||
|
<div class="rw-kpi-val" style="color:#991b1b;">{{ $summary['alpa'] }}</div>
|
||||||
|
<div class="rw-kpi-lbl"><i class="fas fa-times-circle" style="color:#ef4444;"></i> Alpa</div>
|
||||||
|
</div>
|
||||||
|
<div class="rw-kpi" style="border-top:2px solid var(--primary-color);">
|
||||||
|
<div class="rw-kpi-val" style="color:{{ $pctHadirGlbl>=85?'#059669':($pctHadirGlbl>=70?'#d97706':'#dc2626') }};">{{ $pctHadirGlbl }}%</div>
|
||||||
|
<div class="rw-kpi-lbl"><i class="fas fa-chart-pie" style="color:var(--primary-color);"></i> Rata-rata</div>
|
||||||
|
<div class="rw-kpi-sub">dari {{ $totalAbsensi }} tercatat
|
||||||
|
@if($mode !== 'hari_ini' && ($summary['jumlah_kegiatan']??0) > 0)
|
||||||
|
· {{ $summary['jumlah_kegiatan'] }} sesi
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- ════════════════════════════════════════════════════
|
||||||
|
MODE HARI INI → Cards
|
||||||
|
════════════════════════════════════════════════════ --}}
|
||||||
|
@if($mode === 'hari_ini')
|
||||||
|
|
||||||
|
@if($kegiatans && $kegiatans->count() > 0)
|
||||||
|
@foreach($kegiatans as $kegiatan)
|
||||||
|
@include('admin.kegiatan.riwayat._card', ['kegiatan' => $kegiatan, 'passParams' => $passParams])
|
||||||
|
@endforeach
|
||||||
|
<div style="margin-top:16px;">{!! $kegiatans->appends(request()->query())->links('pagination::simple-bootstrap-4') !!}</div>
|
||||||
|
@else
|
||||||
|
<div class="rw-empty">
|
||||||
|
<i class="fas fa-calendar-times"></i>
|
||||||
|
<h3>Tidak Ada Kegiatan</h3>
|
||||||
|
<p>Tidak ada kegiatan pada <strong>{{ $periodeLabel }}</strong>.</p>
|
||||||
|
<p style="margin-top:8px; font-size:.82rem;">
|
||||||
|
Coba tanggal lain atau lihat <a href="{{ route('admin.riwayat-kegiatan.index', ['mode'=>'minggu_ini']) }}" style="color:var(--primary-color);">riwayat minggu ini</a>.
|
||||||
</p>
|
</p>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
@if($kegiatans->count() > 0)
|
{{-- ════════════════════════════════════════════════════
|
||||||
|
MODE MULTI-HARI → Tabel per Tanggal
|
||||||
|
════════════════════════════════════════════════════ --}}
|
||||||
|
@else
|
||||||
|
|
||||||
|
@if($kegiatanPerTanggal && $kegiatanPerTanggal->count() > 0)
|
||||||
|
|
||||||
|
@foreach($kegiatanPerTanggal as $tgl => $items)
|
||||||
@php
|
@php
|
||||||
$hariOrder = ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu', 'Ahad'];
|
$tglCarbon = \Carbon\Carbon::parse($tgl);
|
||||||
$grouped = $kegiatans->getCollection()->groupBy('hari');
|
$isHariIni = ($tgl === now()->format('Y-m-d'));
|
||||||
|
$hariLabel = $tglCarbon->locale('id')->isoFormat('dddd');
|
||||||
|
$tglLabel = $tglCarbon->locale('id')->isoFormat('D MMMM Y');
|
||||||
|
$tglHadir = $items->sum('hadir') + $items->sum('terlambat');
|
||||||
|
$tglTotal = $items->sum('total_absensi');
|
||||||
|
$tglPct = $tglTotal > 0 ? round($tglHadir / $tglTotal * 100) : 0;
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
@foreach($hariOrder as $hari)
|
<div class="rw-date-block">
|
||||||
@if($grouped->has($hari))
|
<div class="rw-date-header {{ $isHariIni ? 'rw-date-today' : '' }}">
|
||||||
@php $items = $grouped[$hari]; @endphp
|
<span class="dh-date">{{ $tglLabel }}</span>
|
||||||
<div class="day-group">
|
<span class="dh-hari">{{ $hariLabel }}{{ $isHariIni ? ' · Hari Ini' : '' }}</span>
|
||||||
<div class="day-header" onclick="toggleDay(this)">
|
<span class="dh-count">
|
||||||
<div class="day-title">
|
{{ $items->count() }} kegiatan
|
||||||
<i class="fas fa-calendar-day"></i> {{ $hari }}
|
·
|
||||||
</div>
|
<strong>{{ $tglHadir }}</strong>/{{ $tglTotal }} hadir
|
||||||
<div class="day-meta">
|
@if($tglTotal > 0)
|
||||||
<span class="day-count">{{ $items->count() }} kegiatan</span>
|
<span style="background:rgba(255,255,255,.15); padding:1px 7px; border-radius:8px; margin-left:4px;">{{ $tglPct }}%</span>
|
||||||
<i class="fas fa-chevron-down toggle-icon"></i>
|
@endif
|
||||||
</div>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="day-body">
|
<div class="rw-tbl-wrap">
|
||||||
<table>
|
<table class="rw-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 40px;">No</th>
|
<th style="width:36px; text-align:center;">No</th>
|
||||||
<th>Nama Kegiatan</th>
|
<th>Nama Kegiatan</th>
|
||||||
<th style="width: 110px;">Waktu</th>
|
<th style="width:95px;">Waktu</th>
|
||||||
<th>Kelas</th>
|
<th style="width:110px;">Kategori</th>
|
||||||
<th style="width: 130px;">Kategori</th>
|
<th style="width:140px;">Kelas</th>
|
||||||
<th style="width: 250px; text-align: center;">Statistik Absensi</th>
|
<th style="width:58px; text-align:center; color:#22c55e;" title="Hadir efektif (termasuk terlambat)">Hadir</th>
|
||||||
<th style="width: 90px; text-align: center;">Aksi</th>
|
<th style="width:52px; text-align:center; color:#FF9800;" title="Terlambat">Tlbt</th>
|
||||||
|
<th style="width:48px; text-align:center; color:#f59e0b;" title="Izin">Izin</th>
|
||||||
|
<th style="width:48px; text-align:center; color:#3b82f6;" title="Sakit">Skt</th>
|
||||||
|
<th style="width:48px; text-align:center; color:#ef4444;" title="Alpa">Alpa</th>
|
||||||
|
<th style="width:90px;">Progress</th>
|
||||||
|
<th style="width:88px; text-align:center;">Aksi</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach($items as $i => $kegiatan)
|
@foreach($items as $idx => $kegiatan)
|
||||||
|
@php
|
||||||
|
$hadirEfektif = $kegiatan->hadir + $kegiatan->terlambat;
|
||||||
|
$totalKeg = $kegiatan->total_absensi;
|
||||||
|
$kelasNames = $kegiatan->kelasKegiatan->pluck('nama_kelas');
|
||||||
|
$isUmum = $kelasNames->isEmpty();
|
||||||
|
@endphp
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ $i + 1 }}</td>
|
<td style="color:#94a3b8; font-size:.76rem; text-align:center;">{{ $idx + 1 }}</td>
|
||||||
<td><strong>{{ $kegiatan->nama_kegiatan }}</strong></td>
|
<td>
|
||||||
<td style="white-space: nowrap; color: #64748b; font-size: 0.82rem;">
|
<div style="font-weight:700; font-size:.87rem; color:var(--primary-dark);">{{ $kegiatan->nama_kegiatan }}</div>
|
||||||
<i class="fas fa-clock" style="color: var(--primary-color);"></i>
|
</td>
|
||||||
{{ date('H:i', strtotime($kegiatan->waktu_mulai)) }}–{{ date('H:i', strtotime($kegiatan->waktu_selesai)) }}
|
<td style="font-size:.79rem; color:#64748b; white-space:nowrap;">
|
||||||
|
{{ date('H:i', strtotime($kegiatan->waktu_mulai)) }}<br>
|
||||||
|
<span style="color:#94a3b8; font-size:.7rem;">s/d {{ date('H:i', strtotime($kegiatan->waktu_selesai)) }}</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@if($kegiatan->kelasKegiatan->isEmpty())
|
@if($kegiatan->kategori)
|
||||||
<span class="umum-tag"><i class="fas fa-globe"></i> Umum</span>
|
<span class="rw-kat-tag">{{ $kegiatan->kategori->nama_kategori }}</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if($isUmum)
|
||||||
|
<span class="rw-umum-tag"><i class="fas fa-globe-asia"></i> Umum</span>
|
||||||
@else
|
@else
|
||||||
@foreach($kegiatan->kelasKegiatan->take(3) as $kls)
|
@foreach($kelasNames->take(2) as $kn)
|
||||||
<span class="kelas-tag">{{ $kls->nama_kelas }}</span>
|
<span class="rw-kelas-tag">{{ $kn }}</span>
|
||||||
@endforeach
|
@endforeach
|
||||||
@if($kegiatan->kelasKegiatan->count() > 3)
|
@if($kelasNames->count() > 2)
|
||||||
<span class="umum-tag">+{{ $kegiatan->kelasKegiatan->count() - 3 }}</span>
|
<span class="rw-umum-tag">+{{ $kelasNames->count()-2 }}</span>
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
|
<td style="text-align:center; font-weight:700; color:#065f46;">{{ $hadirEfektif ?: '–' }}</td>
|
||||||
|
<td style="text-align:center; color:#e65100;">{{ $kegiatan->terlambat ?: '–' }}</td>
|
||||||
|
<td style="text-align:center; color:#92400e;">{{ $kegiatan->izin ?: '–' }}</td>
|
||||||
|
<td style="text-align:center; color:#1e40af;">{{ $kegiatan->sakit ?: '–' }}</td>
|
||||||
|
<td style="text-align:center; color:#991b1b; font-weight:700;">{{ $kegiatan->alpa ?: '–' }}</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="badge badge-success">{{ $kegiatan->kategori->nama_kategori }}</span>
|
@if($totalKeg > 0)
|
||||||
</td>
|
@php
|
||||||
<td style="text-align: center;">
|
$segs = [
|
||||||
@if($kegiatan->total_absensi > 0)
|
['w'=>round($kegiatan->hadir/$totalKeg*100), 'c'=>'#22c55e'],
|
||||||
<div class="stat-chips" style="justify-content: center;">
|
['w'=>round($kegiatan->terlambat/$totalKeg*100), 'c'=>'#FF9800'],
|
||||||
@if($kegiatan->hadir > 0)
|
['w'=>round($kegiatan->izin/$totalKeg*100), 'c'=>'#f59e0b'],
|
||||||
<span class="chip chip-hadir"><i class="fas fa-check"></i> {{ $kegiatan->hadir }}</span>
|
['w'=>round($kegiatan->sakit/$totalKeg*100), 'c'=>'#3b82f6'],
|
||||||
@endif
|
['w'=>round($kegiatan->alpa/$totalKeg*100), 'c'=>'#ef4444'],
|
||||||
@if(($kegiatan->terlambat ?? 0) > 0)
|
];
|
||||||
<span class="chip chip-terlambat"><i class="fas fa-clock"></i> {{ $kegiatan->terlambat }}</span>
|
@endphp
|
||||||
@endif
|
<div class="rw-mini-prog">
|
||||||
@if($kegiatan->izin > 0)
|
@foreach($segs as $s)
|
||||||
<span class="chip chip-izin"><i class="fas fa-envelope"></i> {{ $kegiatan->izin }}</span>
|
@if($s['w'] > 0)<div style="width:{{ $s['w'] }}%;background:{{ $s['c'] }};"></div>@endif
|
||||||
@endif
|
@endforeach
|
||||||
@if($kegiatan->sakit > 0)
|
|
||||||
<span class="chip chip-sakit"><i class="fas fa-heartbeat"></i> {{ $kegiatan->sakit }}</span>
|
|
||||||
@endif
|
|
||||||
@if($kegiatan->alpa > 0)
|
|
||||||
<span class="chip chip-alpa"><i class="fas fa-times"></i> {{ $kegiatan->alpa }}</span>
|
|
||||||
@endif
|
|
||||||
@if(($kegiatan->pulang ?? 0) > 0)
|
|
||||||
<span class="chip chip-pulang"><i class="fas fa-home"></i> {{ $kegiatan->pulang }}</span>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
<div style="font-size: 0.74rem; color: #94a3b8; margin-top: 3px;">
|
|
||||||
Total: {{ $kegiatan->total_absensi }}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div style="font-size:.67rem; color:#94a3b8; margin-top:2px;">{{ $hadirEfektif }}/{{ $totalKeg }}</div>
|
||||||
@else
|
@else
|
||||||
<span class="chip chip-none">Belum ada data</span>
|
<span style="color:#cbd5e1; font-size:.76rem;">–</span>
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:center;">
|
<td style="text-align:center;">
|
||||||
{{-- Teruskan parameter periode ke halaman detail --}}
|
<a href="{{ route('admin.riwayat-kegiatan.show', $kegiatan->id) }}?mode=hari_ini&tanggal={{ $tgl }}&dari={{ $tgl }}&sampai={{ $tgl }}"
|
||||||
<a href="{{ route('admin.riwayat-kegiatan.show', $kegiatan->id) }}?tanggal_dari={{ $activeDari }}&tanggal_sampai={{ $activeSampai }}"
|
class="btn-tbl-detail">
|
||||||
class="btn-detail">
|
<i class="fas fa-users"></i> Santri
|
||||||
<i class="fas fa-eye"></i> Detail
|
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@if($items->count() > 1)
|
||||||
|
<tfoot>
|
||||||
|
<tr style="background:#f0fdf4; border-top:1.5px solid #bbf7d0;">
|
||||||
|
<td colspan="5" style="font-size:.78rem; font-weight:700; color:#065f46; padding:8px 13px;">
|
||||||
|
<i class="fas fa-layer-group"></i> Total {{ $tglLabel }}
|
||||||
|
</td>
|
||||||
|
<td style="text-align:center; font-weight:800; color:#065f46;">{{ $tglHadir }}</td>
|
||||||
|
<td style="text-align:center; font-weight:700; color:#e65100;">{{ $items->sum('terlambat') }}</td>
|
||||||
|
<td style="text-align:center; font-weight:700; color:#92400e;">{{ $items->sum('izin') }}</td>
|
||||||
|
<td style="text-align:center; font-weight:700; color:#1e40af;">{{ $items->sum('sakit') }}</td>
|
||||||
|
<td style="text-align:center; font-weight:700; color:#991b1b;">{{ $items->sum('alpa') }}</td>
|
||||||
|
<td colspan="2" style="font-size:.75rem; color:#94a3b8; padding:8px 13px;">
|
||||||
|
{{ $tglTotal }} tercatat · {{ $tglPct }}% hadir
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
@endif
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
<div class="pagination" style="margin-top: 16px;">
|
|
||||||
{!! $kegiatans->appends(request()->query())->links('pagination::simple-bootstrap-4') !!}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@else
|
@else
|
||||||
<div class="empty-state">
|
<div class="rw-empty">
|
||||||
<i class="fas fa-inbox"></i>
|
<i class="fas fa-calendar-times"></i>
|
||||||
<h3>Tidak Ada Data</h3>
|
<h3>Tidak Ada Data Absensi</h3>
|
||||||
<p>Tidak ada kegiatan pada periode <strong>{{ $periodeLabel }}</strong>.</p>
|
<p>Tidak ada absensi yang tercatat pada periode <strong>{{ $periodeLabel }}</strong>.</p>
|
||||||
|
@if($mode === 'custom')
|
||||||
|
<p style="margin-top:8px; font-size:.82rem; color:#6b7280;">
|
||||||
|
Pastikan rentang tanggal sudah benar dan ada data absensi di periode tersebut.
|
||||||
|
</p>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<script>
|
@endif
|
||||||
function toggleDay(header) {
|
|
||||||
var body = header.nextElementSibling;
|
|
||||||
var icon = header.querySelector('.toggle-icon');
|
|
||||||
if (body.style.display === 'none') {
|
|
||||||
body.style.display = 'block';
|
|
||||||
icon.classList.remove('collapsed');
|
|
||||||
} else {
|
|
||||||
body.style.display = 'none';
|
|
||||||
icon.classList.add('collapsed');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
@ -3,237 +3,265 @@
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<style>
|
<style>
|
||||||
.page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; }
|
/* ====================================================
|
||||||
.page-header h2 { margin: 0; color: var(--primary-dark); font-size: 1.5rem; display: flex; align-items: center; gap: 10px; }
|
RIWAYAT KEGIATAN — SHOW (detail per kegiatan)
|
||||||
.btn-back { padding: 8px 16px; background: #6B7280; color: #fff; border: none; border-radius: 8px; font-size: 0.85rem; text-decoration: none; display: inline-flex; align-items: center; gap: 6px; transition: background 0.2s; }
|
==================================================== */
|
||||||
.btn-back:hover { background: #4B5563; color: #fff; }
|
.rv-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px;
|
||||||
|
margin-bottom: 18px; flex-wrap: wrap; }
|
||||||
|
.rv-header h2 { margin: 0; font-size: 1.3rem; color: var(--primary-dark); display: flex; align-items: center; gap: 9px; }
|
||||||
|
.btn-rv-back { padding: 8px 16px; background: #6b7280; color: #fff; border-radius: 8px; font-size: 0.83rem;
|
||||||
|
font-weight: 600; text-decoration: none; display: inline-flex; align-items: center; gap: 6px;
|
||||||
|
transition: background 0.18s; white-space: nowrap; }
|
||||||
|
.btn-rv-back:hover { background: #4b5563; color: #fff; }
|
||||||
|
|
||||||
.info-box-header { background: linear-gradient(135deg, var(--primary-color), #059669); color: #fff; padding: 20px 24px; border-radius: 12px; margin-bottom: 14px; box-shadow: 0 4px 12px rgba(16,185,129,0.2); }
|
/* Info kegiatan banner */
|
||||||
.info-box-header h3 { margin: 0 0 6px; font-size: 1.3rem; display: flex; align-items: center; gap: 10px; }
|
.rv-banner { background: linear-gradient(135deg, var(--primary-color), #059669); color: #fff;
|
||||||
.info-box-header .meta { opacity: 0.9; font-size: 0.88rem; display: flex; flex-wrap: wrap; gap: 12px; margin-top: 6px; }
|
border-radius: 12px; padding: 18px 22px; margin-bottom: 14px;
|
||||||
.info-box-header .periode-tag { background: rgba(255,255,255,0.2); padding: 3px 10px; border-radius: 20px; font-size: 0.8rem; display: inline-flex; align-items: center; gap: 5px; }
|
box-shadow: 0 4px 14px rgba(16,185,129,0.22); }
|
||||||
|
.rv-banner h3 { margin: 0 0 8px; font-size: 1.15rem; display: flex; align-items: center; gap: 9px; }
|
||||||
|
.rv-banner .meta { display: flex; flex-wrap: wrap; gap: 10px; font-size: 0.83rem; opacity: 0.92; }
|
||||||
|
.rv-banner .meta span { display: inline-flex; align-items: center; gap: 5px; }
|
||||||
|
.rv-periode-pill { background: rgba(255,255,255,0.22); padding: 3px 11px; border-radius: 20px;
|
||||||
|
font-size: 0.78rem; font-weight: 600; display: inline-flex; align-items: center; gap: 5px; }
|
||||||
|
|
||||||
/* 6 KPI cards */
|
/* Total santri ringkasan */
|
||||||
.stats-row {
|
.rv-total-box { background: #fff; border-radius: 12px; padding: 14px 18px; margin-bottom: 14px;
|
||||||
display: grid;
|
box-shadow: 0 2px 10px rgba(0,0,0,0.06); border-left: 4px solid #2563eb; }
|
||||||
grid-template-columns: repeat(6, 1fr);
|
.rv-total-head { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 10px; }
|
||||||
gap: 12px;
|
.rv-total-pct { font-size: 1.6rem; font-weight: 800; line-height: 1; }
|
||||||
margin-bottom: 14px;
|
|
||||||
}
|
|
||||||
@media (max-width: 1100px) { .stats-row { grid-template-columns: repeat(3, 1fr); } }
|
|
||||||
@media (max-width: 600px) { .stats-row { grid-template-columns: repeat(2, 1fr); } }
|
|
||||||
|
|
||||||
.stat-card { background: #fff; padding: 14px 12px; border-radius: 10px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); display: flex; align-items: center; gap: 12px; }
|
/* KPI cards (6 status) */
|
||||||
.stat-card .icon { font-size: 1.4rem; width: 40px; height: 40px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; border-radius: 10px; }
|
.rv-kpi-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 10px; margin-bottom: 14px; }
|
||||||
.stat-card.hadir .icon { background: #D1FAE5; color: #065F46; }
|
@media (max-width: 1000px) { .rv-kpi-grid { grid-template-columns: repeat(3, 1fr); } }
|
||||||
.stat-card.terlambat .icon { background: #FFF3E0; color: #E65100; }
|
@media (max-width: 580px) { .rv-kpi-grid { grid-template-columns: repeat(2, 1fr); } }
|
||||||
.stat-card.izin .icon { background: #FEF3C7; color: #92400E; }
|
|
||||||
.stat-card.sakit .icon { background: #DBEAFE; color: #1E40AF; }
|
|
||||||
.stat-card.alpa .icon { background: #FEE2E2; color: #991B1B; }
|
|
||||||
.stat-card.pulang .icon { background: #F3E8FF; color: #6B21A8; }
|
|
||||||
.stat-card .content { flex: 1; min-width: 0; }
|
|
||||||
.stat-card .label { font-size: 0.78rem; color: var(--text-light); margin-bottom: 2px; }
|
|
||||||
.stat-card .value { font-size: 1.5rem; font-weight: 700; color: var(--primary-dark); line-height: 1.2; }
|
|
||||||
|
|
||||||
.filter-box { background: #fff; padding: 14px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); margin-bottom: 14px; }
|
.rv-kpi { background: #fff; border-radius: 10px; padding: 12px 14px; box-shadow: 0 2px 8px rgba(0,0,0,0.06);
|
||||||
.filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px; }
|
display: flex; align-items: center; gap: 10px; }
|
||||||
.form-group { margin: 0; }
|
.rv-kpi .ico { width: 36px; height: 36px; border-radius: 9px; display: flex; align-items: center; justify-content: center;
|
||||||
.form-group label { display: block; font-size: 0.85rem; margin-bottom: 5px; color: var(--text-light); font-weight: 500; }
|
font-size: 1.1rem; flex-shrink: 0; }
|
||||||
.form-control { width: 100%; padding: 8px 12px; border: 1px solid #e2e8f0; border-radius: 8px; font-size: 0.85rem; }
|
.rv-kpi.hadir .ico { background: #d1fae5; color: #065f46; }
|
||||||
.btn-filter { background: var(--primary-color); color: #fff; border: none; padding: 9px 16px; border-radius: 8px; cursor: pointer; font-size: 0.85rem; display: inline-flex; align-items: center; gap: 6px; transition: all 0.2s; }
|
.rv-kpi.terlambat .ico { background: #fff3e0; color: #e65100; }
|
||||||
.btn-filter:hover { background: #059669; }
|
.rv-kpi.izin .ico { background: #fef3c7; color: #92400e; }
|
||||||
.btn-reset { background: #6B7280; color: #fff; border: none; padding: 9px 12px; border-radius: 8px; font-size: 0.85rem; display: inline-flex; align-items: center; gap: 6px; text-decoration: none; }
|
.rv-kpi.sakit .ico { background: #dbeafe; color: #1e40af; }
|
||||||
.btn-reset:hover { background: #4B5563; color: #fff; }
|
.rv-kpi.alpa .ico { background: #fee2e2; color: #991b1b; }
|
||||||
|
.rv-kpi.pulang .ico { background: #f3e8ff; color: #6b21a8; }
|
||||||
|
.rv-kpi .cnt { font-size: 1.4rem; font-weight: 800; color: var(--primary-dark); line-height: 1; }
|
||||||
|
.rv-kpi .lbl { font-size: 0.75rem; color: #94a3b8; margin-top: 2px; }
|
||||||
|
|
||||||
.day-group { margin-bottom: 18px; background: #fff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); overflow: hidden; }
|
/* Filter box */
|
||||||
.day-header { background: linear-gradient(135deg, #f0fdf4 0%, #E8F7F2 100%); padding: 14px 18px; display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #E8F7F2; cursor: pointer; transition: background 0.2s; user-select: none; }
|
.rv-filter { background: #fff; border-radius: 10px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
||||||
.day-header:hover { background: linear-gradient(135deg, #E8F7F2 0%, #d1f2e8 100%); }
|
padding: 12px 16px; margin-bottom: 14px; }
|
||||||
.day-title { font-weight: 700; font-size: 1rem; color: var(--primary-dark); display: flex; align-items: center; gap: 8px; }
|
.rv-filter-row { display: flex; gap: 9px; align-items: flex-end; flex-wrap: wrap; }
|
||||||
.day-title i { color: var(--primary-color); }
|
.rv-fg { display: flex; flex-direction: column; gap: 4px; }
|
||||||
.day-stats { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
|
.rv-fg label { font-size: 0.77rem; font-weight: 600; color: #64748b; }
|
||||||
.mini-badge { padding: 4px 10px; border-radius: 20px; font-size: 0.75rem; font-weight: 600; display: inline-flex; align-items: center; gap: 4px; }
|
.rv-fg select, .rv-fg input { padding: 7px 10px; font-size: 0.83rem; border: 1.5px solid #e2e8f0; border-radius: 7px; }
|
||||||
.mini-badge.hadir { background: #D1FAE5; color: #065F46; }
|
.rv-fg select:focus, .rv-fg input:focus { border-color: var(--primary-color); outline: none; }
|
||||||
.mini-badge.terlambat { background: #FFF3E0; color: #E65100; }
|
.btn-rv-filter { background: var(--primary-color); color: #fff; border: none; padding: 8px 16px; border-radius: 7px;
|
||||||
.mini-badge.izin { background: #FEF3C7; color: #92400E; }
|
font-size: 0.82rem; font-weight: 600; cursor: pointer; display: inline-flex; align-items: center;
|
||||||
.mini-badge.sakit { background: #DBEAFE; color: #1E40AF; }
|
gap: 5px; align-self: flex-end; transition: background 0.18s; }
|
||||||
.mini-badge.alpa { background: #FEE2E2; color: #991B1B; }
|
.btn-rv-filter:hover { background: #059669; }
|
||||||
.mini-badge.pulang { background: #F3E8FF; color: #6B21A8; }
|
.btn-rv-clear { background: #f1f5f9; color: #64748b; border: 1.5px solid #e2e8f0; padding: 8px 10px; border-radius: 7px;
|
||||||
.day-body table { width: 100%; border-collapse: collapse; }
|
font-size: 0.82rem; font-weight: 600; text-decoration: none; display: inline-flex; align-items: center;
|
||||||
.day-body table thead { background: #f8fafc; }
|
gap: 5px; align-self: flex-end; transition: all 0.18s; }
|
||||||
.day-body table th { padding: 10px 14px; text-align: left; font-weight: 600; font-size: 0.82rem; color: #64748b; border-bottom: 1px solid #e2e8f0; }
|
.btn-rv-clear:hover { background: #e2e8f0; color: #374151; }
|
||||||
.day-body table td { padding: 9px 14px; font-size: 0.85rem; border-bottom: 1px solid #f1f5f9; }
|
|
||||||
.day-body table tbody tr:last-child td { border-bottom: none; }
|
|
||||||
.day-body table tbody tr:hover { background: #f8fafc; }
|
|
||||||
.toggle-icon { transition: transform 0.3s; font-size: 0.85rem; color: #94a3b8; }
|
|
||||||
.toggle-icon.collapsed { transform: rotate(-90deg); }
|
|
||||||
|
|
||||||
.empty-state { text-align: center; padding: 36px 20px; color: var(--text-light); background: #fff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
|
/* Day group */
|
||||||
.empty-state i { font-size: 3.5rem; margin-bottom: 14px; opacity: 0.3; display: block; }
|
.rv-day-group { background: #fff; border-radius: 12px; box-shadow: 0 2px 10px rgba(0,0,0,0.06);
|
||||||
|
overflow: hidden; margin-bottom: 16px; border: 1px solid #f0f0f0; }
|
||||||
|
.rv-day-head { background: linear-gradient(135deg, #f0fdf4, #e8f7f2); padding: 13px 18px;
|
||||||
|
display: flex; justify-content: space-between; align-items: center;
|
||||||
|
border-bottom: 2px solid #e8f7f2; cursor: pointer; user-select: none;
|
||||||
|
transition: background 0.18s; }
|
||||||
|
.rv-day-head:hover{ background: linear-gradient(135deg, #e8f7f2, #d1f2e8); }
|
||||||
|
.rv-day-title { font-weight: 700; font-size: 0.95rem; color: var(--primary-dark);
|
||||||
|
display: flex; align-items: center; gap: 8px; }
|
||||||
|
.rv-day-badges { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
|
||||||
|
.rv-mini { padding: 3px 10px; border-radius: 18px; font-size: 0.74rem; font-weight: 700;
|
||||||
|
display: inline-flex; align-items: center; gap: 4px; }
|
||||||
|
.rv-mini.hadir { background: #d1fae5; color: #065f46; }
|
||||||
|
.rv-mini.terlambat{ background: #fff3e0; color: #e65100; }
|
||||||
|
.rv-mini.izin { background: #fef3c7; color: #92400e; }
|
||||||
|
.rv-mini.sakit { background: #dbeafe; color: #1e40af; }
|
||||||
|
.rv-mini.alpa { background: #fee2e2; color: #991b1b; }
|
||||||
|
.rv-mini.pulang { background: #f3e8ff; color: #6b21a8; }
|
||||||
|
.rv-toggle { color: #94a3b8; transition: transform 0.25s; font-size: 0.82rem; flex-shrink: 0; }
|
||||||
|
.rv-toggle.closed { transform: rotate(-90deg); }
|
||||||
|
|
||||||
.pagination { display: flex; justify-content: center; align-items: center; gap: 6px; margin-top: 14px; }
|
/* Kelas sub-header */
|
||||||
.pagination a, .pagination span { padding: 6px 12px; border: 1px solid #e2e8f0; border-radius: 6px; font-size: 0.82rem; text-decoration: none; color: var(--text-dark); transition: all 0.2s; }
|
.rv-kelas-subhead { background: linear-gradient(90deg, #f0fdf4, #e8f5e9); padding: 8px 16px;
|
||||||
.pagination a:hover { background: var(--primary-color); color: #fff; border-color: var(--primary-color); }
|
display: flex; justify-content: space-between; align-items: center;
|
||||||
.pagination .active { background: var(--primary-color); color: #fff; border-color: var(--primary-color); font-weight: 600; }
|
border-bottom: 1px solid #e2e8f0; }
|
||||||
.pagination .disabled { color: #cbd5e1; cursor: not-allowed; }
|
.rv-kelas-subhead .name { font-size: 0.85rem; font-weight: 700; color: #065f46;
|
||||||
|
display: flex; align-items: center; gap: 6px; }
|
||||||
|
.rv-kelas-subhead .cnt { background: #6fbaa5; color: #fff; padding: 2px 10px; border-radius: 10px;
|
||||||
|
font-size: 0.74rem; font-weight: 700; }
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
/* Table santri */
|
||||||
.day-header { flex-direction: column; align-items: flex-start; gap: 8px; }
|
.rv-table { width: 100%; border-collapse: collapse; }
|
||||||
.day-body table th:nth-child(2), .day-body table td:nth-child(2) { display: none; }
|
.rv-table thead th { padding: 9px 14px; text-align: left; font-size: 0.79rem; font-weight: 600;
|
||||||
.day-body table th:nth-child(7), .day-body table td:nth-child(7) { display: none; }
|
color: #64748b; background: #f8fafc; border-bottom: 1px solid #e2e8f0; }
|
||||||
}
|
.rv-table tbody td { padding: 9px 14px; font-size: 0.84rem; border-bottom: 1px solid #f8fafc;
|
||||||
|
vertical-align: middle; }
|
||||||
|
.rv-table tbody tr:last-child td { border-bottom: none; }
|
||||||
|
.rv-table tbody tr:hover { background: #f8fafc; }
|
||||||
|
|
||||||
|
/* Santri name link */
|
||||||
|
.rv-santri-link { color: var(--primary-color); text-decoration: none; font-weight: 600;
|
||||||
|
display: inline-flex; align-items: center; gap: 5px; transition: color 0.15s; }
|
||||||
|
.rv-santri-link:hover { color: #059669; text-decoration: underline; }
|
||||||
|
.btn-rv-history { padding: 3px 10px; background: #f0fdf4; color: var(--primary-color);
|
||||||
|
border: 1px solid #bbf7d0; border-radius: 6px; font-size: 0.74rem; font-weight: 600;
|
||||||
|
text-decoration: none; display: inline-flex; align-items: center; gap: 4px;
|
||||||
|
transition: all 0.15s; white-space: nowrap; }
|
||||||
|
.btn-rv-history:hover { background: var(--primary-color); color: #fff; border-color: var(--primary-color); }
|
||||||
|
|
||||||
|
/* Metode badges */
|
||||||
|
.rv-rfid { background: #dbeafe; color: #1e40af; padding: 3px 9px; border-radius: 9px; font-size: 0.74rem; font-weight: 700; }
|
||||||
|
.rv-mesin { background: #ede9fe; color: #6b21a8; padding: 3px 9px; border-radius: 9px; font-size: 0.74rem; font-weight: 700; }
|
||||||
|
.rv-manual { background: #f1f5f9; color: #374151; padding: 3px 9px; border-radius: 9px; font-size: 0.74rem; font-weight: 700; }
|
||||||
|
|
||||||
|
/* Progress bar reuse */
|
||||||
|
.rv-prog-wrap { height: 16px; background: #f3f4f6; border-radius: 8px; overflow: hidden; display: flex; }
|
||||||
|
|
||||||
|
/* Empty */
|
||||||
|
.rv-empty { text-align: center; padding: 36px 20px; color: #94a3b8; background: #fff;
|
||||||
|
border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
|
||||||
|
.rv-empty i { font-size: 2.8rem; margin-bottom: 10px; display: block; opacity: 0.35; }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@php
|
@php
|
||||||
// Ambil range dari query string (diteruskan dari index)
|
$mode = $mode ?? 'hari_ini';
|
||||||
$defaultDari = now()->startOfWeek(\Carbon\Carbon::MONDAY)->format('Y-m-d');
|
$dari = $dari ?? now()->format('Y-m-d');
|
||||||
$defaultSampai = now()->endOfWeek(\Carbon\Carbon::SUNDAY)->format('Y-m-d');
|
$sampai = $sampai ?? now()->format('Y-m-d');
|
||||||
$filterDari = request('tanggal_dari', $defaultDari);
|
$tanggal = $tanggal ?? now()->format('Y-m-d');
|
||||||
$filterSampai = request('tanggal_sampai', $defaultSampai);
|
|
||||||
$filterBulan = request('bulan', '');
|
|
||||||
|
|
||||||
if ($filterBulan) {
|
|
||||||
$periodeLabel = 'Bulan ' . \Carbon\Carbon::parse($filterBulan . '-01')->locale('id')->isoFormat('MMMM Y');
|
|
||||||
} else {
|
|
||||||
$periodeLabel = \Carbon\Carbon::parse($filterDari)->locale('id')->isoFormat('D MMM Y')
|
|
||||||
. ' – '
|
|
||||||
. \Carbon\Carbon::parse($filterSampai)->locale('id')->isoFormat('D MMM Y');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hitung KPI dari data yang sudah difilter (semua halaman, bukan hanya halaman ini)
|
|
||||||
// $stats sudah dihitung di controller berdasarkan filter — gunakan langsung
|
|
||||||
// Tapi jika controller belum menghitung per filter, hitung dari koleksi paginator saat ini
|
|
||||||
// Gunakan $stats dari controller jika ada, fallback ke hitung manual
|
|
||||||
$statsHadir = $stats['Hadir'] ?? 0;
|
$statsHadir = $stats['Hadir'] ?? 0;
|
||||||
$statsTerlambat = $stats['Terlambat'] ?? 0;
|
$statsTerlambat = $stats['Terlambat'] ?? 0;
|
||||||
$statsIzin = $stats['Izin'] ?? 0;
|
$statsIzin = $stats['Izin'] ?? 0;
|
||||||
$statsSakit = $stats['Sakit'] ?? 0;
|
$statsSakit = $stats['Sakit'] ?? 0;
|
||||||
$statsAlpa = $stats['Alpa'] ?? 0;
|
$statsAlpa = $stats['Alpa'] ?? 0;
|
||||||
$statsPulang = $stats['Pulang'] ?? 0;
|
$statsPulang = $stats['Pulang'] ?? 0;
|
||||||
|
|
||||||
|
$backParams = ['mode' => $mode, 'dari' => $dari, 'sampai' => $sampai, 'tanggal' => $tanggal];
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<div class="page-header">
|
{{-- ── HEADER ───────────────────────────────────────────────────────────────── --}}
|
||||||
<h2><i class="fas fa-file-alt"></i> Detail Riwayat: {{ $kegiatan->nama_kegiatan }}</h2>
|
<div class="rv-header">
|
||||||
<a href="{{ route('admin.riwayat-kegiatan.index', ['tanggal_dari' => $filterDari, 'tanggal_sampai' => $filterSampai]) }}"
|
<h2><i class="fas fa-file-alt" style="color:var(--primary-color);"></i>
|
||||||
class="btn-back">
|
{{ $kegiatan->nama_kegiatan }}
|
||||||
|
</h2>
|
||||||
|
<a href="{{ route('admin.riwayat-kegiatan.index', $backParams) }}" class="btn-rv-back">
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Info Kegiatan --}}
|
{{-- ── BANNER INFO ──────────────────────────────────────────────────────────── --}}
|
||||||
<div class="info-box-header">
|
<div class="rv-banner">
|
||||||
<h3><i class="fas fa-clipboard-check"></i> {{ $kegiatan->nama_kegiatan }}</h3>
|
<h3><i class="fas fa-clipboard-check"></i> {{ $kegiatan->nama_kegiatan }}</h3>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
<span><i class="fas fa-tag"></i> {{ $kegiatan->kategori->nama_kategori }}</span>
|
<span><i class="fas fa-tag"></i> {{ $kegiatan->kategori->nama_kategori }}</span>
|
||||||
<span><i class="fas fa-clock"></i> {{ date('H:i', strtotime($kegiatan->waktu_mulai)) }} - {{ date('H:i', strtotime($kegiatan->waktu_selesai)) }}</span>
|
<span><i class="fas fa-clock"></i> {{ date('H:i', strtotime($kegiatan->waktu_mulai)) }} – {{ date('H:i', strtotime($kegiatan->waktu_selesai)) }}</span>
|
||||||
<span><i class="fas fa-calendar-day"></i> {{ $kegiatan->hari }}</span>
|
<span><i class="fas fa-calendar-day"></i> {{ $kegiatan->hari }}</span>
|
||||||
@if($kegiatan->kelasKegiatan->count() > 0)
|
@if($kegiatan->kelasKegiatan->count() > 0)
|
||||||
<span><i class="fas fa-users"></i> {{ $kegiatan->kelasKegiatan->pluck('nama_kelas')->implode(', ') }}</span>
|
<span><i class="fas fa-users"></i> {{ $kegiatan->kelasKegiatan->pluck('nama_kelas')->implode(', ') }}</span>
|
||||||
@else
|
@else
|
||||||
<span><i class="fas fa-globe"></i> Umum</span>
|
<span><i class="fas fa-globe"></i> Kegiatan Umum</span>
|
||||||
@endif
|
@endif
|
||||||
<span class="periode-tag"><i class="fas fa-calendar-check"></i> {{ $periodeLabel }}</span>
|
<span class="rv-periode-pill"><i class="fas fa-calendar-check"></i> {{ $periodeLabel }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Ringkasan Total Santri --}}
|
{{-- ── TOTAL SANTRI RINGKASAN ───────────────────────────────────────────────── --}}
|
||||||
@if(isset($totalSantriEligible))
|
@if(isset($totalSantriEligible))
|
||||||
<div style="background: #fff; border-radius: 12px; padding: 16px 20px; margin-bottom: 14px; box-shadow: 0 2px 12px rgba(0,0,0,0.06); border-left: 4px solid #2563eb;">
|
<div class="rv-total-box">
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 10px;">
|
<div class="rv-total-head">
|
||||||
<div>
|
<div>
|
||||||
<h4 style="margin: 0; font-size: 1rem; color: #1a2332;">
|
<div style="font-size:0.95rem; font-weight:700; color:#1a2332; margin-bottom:4px;">
|
||||||
<i class="fas fa-users" style="color: #2563eb;"></i> Total Semua Santri: <strong>{{ $totalSantriEligible }}</strong>
|
<i class="fas fa-users" style="color:#2563eb;"></i>
|
||||||
</h4>
|
Total Santri Seharusnya Hadir: <strong>{{ $totalSantriEligible }}</strong>
|
||||||
<p style="margin: 4px 0 0; font-size: 0.84rem; color: #6b7280;">
|
</div>
|
||||||
Sudah absen: <strong style="color: #059669;">{{ $totalRecorded }}</strong>
|
<div style="font-size:0.82rem; color:#6b7280;">
|
||||||
|
Sudah tercatat: <strong style="color:#059669;">{{ $totalRecorded }}</strong>
|
||||||
·
|
·
|
||||||
Belum absen: <strong style="color: {{ ($totalSantriEligible - $totalRecorded) > 0 ? '#dc2626' : '#059669' }};">{{ max(0, $totalSantriEligible - $totalRecorded) }}</strong>
|
Belum tercatat:
|
||||||
</p>
|
<strong style="color:{{ ($totalSantriEligible - $totalRecorded) > 0 ? '#dc2626' : '#059669' }};">
|
||||||
|
{{ max(0, $totalSantriEligible - $totalRecorded) }}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="text-align:right;">
|
<div style="text-align:right;">
|
||||||
<div style="font-size: 1.5rem; font-weight: 800; color: {{ $persenHadir >= 85 ? '#059669' : ($persenHadir >= 70 ? '#d97706' : '#dc2626') }};">
|
<div class="rv-total-pct"
|
||||||
|
style="color:{{ $persenHadir >= 85 ? '#059669' : ($persenHadir >= 70 ? '#d97706' : '#dc2626') }};">
|
||||||
{{ $persenHadir }}%
|
{{ $persenHadir }}%
|
||||||
</div>
|
</div>
|
||||||
<div style="font-size: 0.78rem; color: #6b7280;">Kehadiran</div>
|
<div style="font-size:0.74rem; color:#6b7280;">Kehadiran</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{-- Progress bar --}}
|
|
||||||
@php
|
@php
|
||||||
$pctSudah = $totalSantriEligible > 0 ? round($totalRecorded / $totalSantriEligible * 100, 1) : 0;
|
$pctSudah = $totalSantriEligible > 0 ? round($totalRecorded / $totalSantriEligible * 100, 1) : 0;
|
||||||
$pctBelumRiwayat = 100 - $pctSudah;
|
$pctBlm = 100 - $pctSudah;
|
||||||
@endphp
|
@endphp
|
||||||
<div style="height: 24px; background: #f3f4f6; border-radius: 12px; overflow: hidden; display: flex;">
|
<div class="rv-prog-wrap">
|
||||||
@if($pctSudah > 0)
|
@if($pctSudah > 0)
|
||||||
<div style="width: {{ $pctSudah }}%; background: linear-gradient(90deg, #22c55e, #16a34a); display: flex; align-items: center; justify-content: center; color: white; font-size: 0.73rem; font-weight: 700;" title="Sudah Absen: {{ $totalRecorded }}">
|
<div style="width:{{ $pctSudah }}%; background:linear-gradient(90deg,#22c55e,#16a34a);
|
||||||
{{ $totalRecorded }}
|
display:flex; align-items:center; justify-content:center;
|
||||||
|
color:white; font-size:0.72rem; font-weight:700;">
|
||||||
|
{{ $totalRecorded > 0 && $pctSudah > 8 ? $totalRecorded : '' }}
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@if($pctBelumRiwayat > 0 && ($totalSantriEligible - $totalRecorded) > 0)
|
@if($pctBlm > 0 && ($totalSantriEligible - $totalRecorded) > 0)
|
||||||
<div style="width: {{ $pctBelumRiwayat }}%; background: #d1d5db; display: flex; align-items: center; justify-content: center; color: #6b7280; font-size: 0.73rem; font-weight: 700;" title="Belum Absen: {{ $totalSantriEligible - $totalRecorded }}">
|
<div style="width:{{ $pctBlm }}%; background:#d1d5db;
|
||||||
{{ $totalSantriEligible - $totalRecorded }}
|
display:flex; align-items:center; justify-content:center;
|
||||||
|
color:#6b7280; font-size:0.72rem; font-weight:700;">
|
||||||
|
{{ ($totalSantriEligible - $totalRecorded) > 0 && $pctBlm > 8 ? ($totalSantriEligible - $totalRecorded) : '' }}
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
{{-- 6 KPI Cards --}}
|
{{-- ── 6 KPI CARDS ─────────────────────────────────────────────────────────── --}}
|
||||||
<div class="stats-row">
|
<div class="rv-kpi-grid">
|
||||||
<div class="stat-card hadir">
|
<div class="rv-kpi hadir">
|
||||||
<div class="icon"><i class="fas fa-check-circle"></i></div>
|
<div class="ico"><i class="fas fa-check-circle"></i></div>
|
||||||
<div class="content">
|
<div><div class="cnt">{{ $statsHadir }}</div><div class="lbl">Hadir</div></div>
|
||||||
<div class="label">Hadir</div>
|
|
||||||
<div class="value">{{ $statsHadir }}</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="rv-kpi terlambat">
|
||||||
|
<div class="ico"><i class="fas fa-clock"></i></div>
|
||||||
|
<div><div class="cnt">{{ $statsTerlambat }}</div><div class="lbl">Terlambat</div></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-card terlambat">
|
<div class="rv-kpi izin">
|
||||||
<div class="icon"><i class="fas fa-clock"></i></div>
|
<div class="ico"><i class="fas fa-envelope"></i></div>
|
||||||
<div class="content">
|
<div><div class="cnt">{{ $statsIzin }}</div><div class="lbl">Izin</div></div>
|
||||||
<div class="label">Terlambat</div>
|
|
||||||
<div class="value">{{ $statsTerlambat }}</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="rv-kpi sakit">
|
||||||
|
<div class="ico"><i class="fas fa-heartbeat"></i></div>
|
||||||
|
<div><div class="cnt">{{ $statsSakit }}</div><div class="lbl">Sakit</div></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-card izin">
|
<div class="rv-kpi alpa">
|
||||||
<div class="icon"><i class="fas fa-envelope"></i></div>
|
<div class="ico"><i class="fas fa-times-circle"></i></div>
|
||||||
<div class="content">
|
<div><div class="cnt">{{ $statsAlpa }}</div><div class="lbl">Alpa</div></div>
|
||||||
<div class="label">Izin</div>
|
|
||||||
<div class="value">{{ $statsIzin }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card sakit">
|
|
||||||
<div class="icon"><i class="fas fa-heartbeat"></i></div>
|
|
||||||
<div class="content">
|
|
||||||
<div class="label">Sakit</div>
|
|
||||||
<div class="value">{{ $statsSakit }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card alpa">
|
|
||||||
<div class="icon"><i class="fas fa-times-circle"></i></div>
|
|
||||||
<div class="content">
|
|
||||||
<div class="label">Alpa</div>
|
|
||||||
<div class="value">{{ $statsAlpa }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card pulang">
|
|
||||||
<div class="icon"><i class="fas fa-home"></i></div>
|
|
||||||
<div class="content">
|
|
||||||
<div class="label">Pulang</div>
|
|
||||||
<div class="value">{{ $statsPulang }}</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="rv-kpi pulang">
|
||||||
|
<div class="ico"><i class="fas fa-home"></i></div>
|
||||||
|
<div><div class="cnt">{{ $statsPulang }}</div><div class="lbl">Pulang</div></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Filter --}}
|
{{-- ── FILTER ───────────────────────────────────────────────────────────────── --}}
|
||||||
<div class="filter-box">
|
<div class="rv-filter">
|
||||||
<form method="GET">
|
<form method="GET">
|
||||||
{{-- Pertahankan range periode dari index --}}
|
{{-- Pertahankan parameter periode --}}
|
||||||
<input type="hidden" name="tanggal_dari" value="{{ $filterDari }}">
|
<input type="hidden" name="mode" value="{{ $mode }}">
|
||||||
<input type="hidden" name="tanggal_sampai" value="{{ $filterSampai }}">
|
<input type="hidden" name="dari" value="{{ $dari }}">
|
||||||
|
<input type="hidden" name="sampai" value="{{ $sampai }}">
|
||||||
|
<input type="hidden" name="tanggal" value="{{ $tanggal }}">
|
||||||
|
|
||||||
<div class="filter-grid">
|
<div class="rv-filter-row">
|
||||||
<div class="form-group">
|
<div class="rv-fg">
|
||||||
<label for="id_santri">Santri</label>
|
<label><i class="fas fa-user"></i> Cari Santri</label>
|
||||||
<select name="id_santri" id="id_santri" class="form-control">
|
<select name="id_santri" style="min-width:200px;">
|
||||||
<option value="">-- Semua Santri --</option>
|
<option value="">Semua Santri</option>
|
||||||
@foreach($santris as $s)
|
@foreach($santris as $s)
|
||||||
<option value="{{ $s->id_santri }}" {{ request('id_santri') == $s->id_santri ? 'selected' : '' }}>
|
<option value="{{ $s->id_santri }}" {{ request('id_santri') == $s->id_santri ? 'selected' : '' }}>
|
||||||
{{ $s->nama_lengkap }}
|
{{ $s->nama_lengkap }}
|
||||||
|
|
@ -242,13 +270,13 @@ class="btn-back">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="rv-fg">
|
||||||
<label for="id_kelas">Kelas</label>
|
<label><i class="fas fa-school"></i> Kelas</label>
|
||||||
<select name="id_kelas" id="id_kelas" class="form-control">
|
<select name="id_kelas" style="min-width:160px;">
|
||||||
<option value="">-- Semua Kelas --</option>
|
<option value="">Semua Kelas</option>
|
||||||
@foreach($kelasList->groupBy('kelompok.nama_kelompok') as $kelompokNama => $kelasList_group)
|
@foreach($kelasList->groupBy('kelompok.nama_kelompok') as $grpNama => $grpKelas)
|
||||||
<optgroup label="{{ $kelompokNama }}">
|
<optgroup label="{{ $grpNama }}">
|
||||||
@foreach($kelasList_group as $kelas)
|
@foreach($grpKelas as $kelas)
|
||||||
<option value="{{ $kelas->id }}" {{ request('id_kelas') == $kelas->id ? 'selected' : '' }}>
|
<option value="{{ $kelas->id }}" {{ request('id_kelas') == $kelas->id ? 'selected' : '' }}>
|
||||||
{{ $kelas->nama_kelas }}
|
{{ $kelas->nama_kelas }}
|
||||||
</option>
|
</option>
|
||||||
|
|
@ -258,197 +286,204 @@ class="btn-back">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="rv-fg">
|
||||||
<label for="status">Status</label>
|
<label><i class="fas fa-filter"></i> Status</label>
|
||||||
<select name="status" id="status" class="form-control">
|
<select name="status" style="min-width:140px;">
|
||||||
<option value="">-- Semua Status --</option>
|
<option value="">Semua Status</option>
|
||||||
<option value="Hadir" {{ request('status') == 'Hadir' ? 'selected' : '' }}>Hadir</option>
|
@foreach(['Hadir','Terlambat','Izin','Sakit','Alpa','Pulang'] as $st)
|
||||||
<option value="Terlambat" {{ request('status') == 'Terlambat' ? 'selected' : '' }}>Terlambat</option>
|
<option value="{{ $st }}" {{ request('status') == $st ? 'selected' : '' }}>{{ $st }}</option>
|
||||||
<option value="Izin" {{ request('status') == 'Izin' ? 'selected' : '' }}>Izin</option>
|
@endforeach
|
||||||
<option value="Sakit" {{ request('status') == 'Sakit' ? 'selected' : '' }}>Sakit</option>
|
|
||||||
<option value="Alpa" {{ request('status') == 'Alpa' ? 'selected' : '' }}>Alpa</option>
|
|
||||||
<option value="Pulang" {{ request('status') == 'Pulang' ? 'selected' : '' }}>Pulang</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
@if($mode !== 'hari_ini')
|
||||||
<label for="tanggal_spesifik">Filter Tanggal Spesifik</label>
|
<div class="rv-fg">
|
||||||
<input type="date" name="tanggal_spesifik" id="tanggal_spesifik" class="form-control"
|
<label><i class="fas fa-calendar"></i> Tanggal Spesifik</label>
|
||||||
|
<input type="date" name="tanggal_spesifik"
|
||||||
value="{{ request('tanggal_spesifik') }}"
|
value="{{ request('tanggal_spesifik') }}"
|
||||||
min="{{ $filterDari }}" max="{{ $filterSampai }}">
|
min="{{ $dari }}" max="{{ $sampai }}">
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div style="display: flex; align-items: flex-end; gap: 10px;">
|
<button type="submit" class="btn-rv-filter">
|
||||||
<button type="submit" class="btn-filter" style="flex: 1;">
|
|
||||||
<i class="fas fa-filter"></i> Filter
|
<i class="fas fa-filter"></i> Filter
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@if(request()->hasAny(['id_santri','id_kelas','status','tanggal_spesifik']))
|
@if(request()->hasAny(['id_santri','id_kelas','status','tanggal_spesifik']))
|
||||||
<a href="{{ route('admin.riwayat-kegiatan.show', $kegiatan->id) }}?tanggal_dari={{ $filterDari }}&tanggal_sampai={{ $filterSampai }}"
|
<a href="{{ route('admin.riwayat-kegiatan.show', $kegiatan->id) }}?{{ http_build_query(['mode'=>$mode,'dari'=>$dari,'sampai'=>$sampai,'tanggal'=>$tanggal]) }}"
|
||||||
class="btn-reset">
|
class="btn-rv-clear">
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-times"></i> Hapus Filter
|
||||||
</a>
|
</a>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Tabel Riwayat — Grouped by Tanggal --}}
|
{{-- ── TABEL RIWAYAT DIKELOMPOK PER TANGGAL ────────────────────────────────── --}}
|
||||||
@if($riwayats->count() > 0)
|
@if($riwayats->count() > 0)
|
||||||
|
|
||||||
@php
|
@php
|
||||||
$grouped = $riwayats->getCollection()->groupBy(function($item) {
|
$grouped = $riwayats->getCollection()->groupBy(fn($item) => $item->tanggal->format('Y-m-d'))->sortKeysDesc();
|
||||||
return $item->tanggal->format('Y-m-d');
|
$isUmum = $kegiatan->kelasKegiatan->isEmpty();
|
||||||
})->sortKeysDesc();
|
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
@foreach($grouped as $tanggal => $records)
|
@foreach($grouped as $tanggal => $records)
|
||||||
@php
|
@php
|
||||||
$tglCarbon = \Carbon\Carbon::parse($tanggal);
|
$tglC = \Carbon\Carbon::parse($tanggal);
|
||||||
$hariIndo = $tglCarbon->locale('id')->isoFormat('dddd');
|
$hariStr = $tglC->locale('id')->isoFormat('dddd');
|
||||||
$tglFormatted = $tglCarbon->locale('id')->isoFormat('D MMMM Y');
|
$tglStr = $tglC->locale('id')->isoFormat('D MMMM Y');
|
||||||
|
|
||||||
$dayHadir = $records->where('status', 'Hadir')->count();
|
$dHadir = $records->where('status','Hadir')->count();
|
||||||
$dayTerlambat = $records->where('status', 'Terlambat')->count();
|
$dTerlambat = $records->where('status','Terlambat')->count();
|
||||||
$dayIzin = $records->where('status', 'Izin')->count();
|
$dIzin = $records->where('status','Izin')->count();
|
||||||
$daySakit = $records->where('status', 'Sakit')->count();
|
$dSakit = $records->where('status','Sakit')->count();
|
||||||
$dayAlpa = $records->where('status', 'Alpa')->count();
|
$dAlpa = $records->where('status','Alpa')->count();
|
||||||
$dayPulang = $records->where('status', 'Pulang')->count();
|
$dPulang = $records->where('status','Pulang')->count();
|
||||||
$dayTotal = $records->count();
|
$dTotal = $records->count();
|
||||||
|
|
||||||
// Group per kelas kegiatan (khusus) atau kelas_name santri (umum)
|
// Kelompok per kelas (sama seperti show sebelumnya)
|
||||||
$isUmum = $kegiatan->kelasKegiatan->isEmpty();
|
|
||||||
if ($isUmum) {
|
if ($isUmum) {
|
||||||
$recordsPerKelas = $records->groupBy(fn($r) =>
|
$perKelas = $records->groupBy(fn($r) =>
|
||||||
optional(optional($r->santri->kelasSantri->first())->kelas)->nama_kelas ?? 'Tanpa Kelas'
|
optional(optional($r->santri->kelasSantri->first())->kelas)->nama_kelas ?? 'Tanpa Kelas'
|
||||||
)->sortKeys();
|
)->sortKeys();
|
||||||
} else {
|
} else {
|
||||||
$recordsPerKelas = collect();
|
$perKelas = collect();
|
||||||
$placedIds = [];
|
$placedIds = [];
|
||||||
foreach ($kegiatan->kelasKegiatan as $kls) {
|
foreach ($kegiatan->kelasKegiatan as $kls) {
|
||||||
$inKelas = $records->filter(function($r) use ($kls, &$placedIds) {
|
$inKls = $records->filter(function($r) use ($kls, &$placedIds) {
|
||||||
if (in_array($r->id, $placedIds)) return false;
|
if (in_array($r->id, $placedIds)) return false;
|
||||||
return $r->santri->kelasSantri->contains('id_kelas', $kls->id);
|
return $r->santri->kelasSantri->contains('id_kelas', $kls->id);
|
||||||
});
|
});
|
||||||
foreach ($inKelas as $r) $placedIds[] = $r->id;
|
foreach ($inKls as $r) $placedIds[] = $r->id;
|
||||||
if ($inKelas->count() > 0) $recordsPerKelas[$kls->nama_kelas] = $inKelas;
|
if ($inKls->count() > 0) $perKelas[$kls->nama_kelas] = $inKls;
|
||||||
}
|
}
|
||||||
$lainnya = $records->filter(fn($r) => !in_array($r->id, $placedIds));
|
$lainnya = $records->filter(fn($r) => !in_array($r->id, $placedIds));
|
||||||
if ($lainnya->count() > 0) $recordsPerKelas['Kelas Lain'] = $lainnya;
|
if ($lainnya->count() > 0) $perKelas['Kelas Lain'] = $lainnya;
|
||||||
}
|
}
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<div class="day-group">
|
<div class="rv-day-group">
|
||||||
<div class="day-header" onclick="toggleDay(this)">
|
|
||||||
<div class="day-title">
|
{{-- Day header --}}
|
||||||
<i class="fas fa-calendar-day"></i>
|
<div class="rv-day-head" onclick="toggleDay(this)">
|
||||||
{{ $hariIndo }}, {{ $tglFormatted }}
|
<div class="rv-day-title">
|
||||||
<span style="font-weight: 400; font-size: 0.85rem; color: #94a3b8; margin-left: 4px;">({{ $dayTotal }} santri)</span>
|
<i class="fas fa-calendar-day" style="color:var(--primary-color);"></i>
|
||||||
|
{{ $hariStr }}, {{ $tglStr }}
|
||||||
|
<span style="font-weight:400; font-size:0.82rem; color:#94a3b8;">({{ $dTotal }} santri)</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="day-stats">
|
<div class="rv-day-badges">
|
||||||
@if($dayHadir > 0)
|
@if($dHadir > 0) <span class="rv-mini hadir"><i class="fas fa-check"></i> {{ $dHadir }}</span> @endif
|
||||||
<span class="mini-badge hadir"><i class="fas fa-check"></i> {{ $dayHadir }}</span>
|
@if($dTerlambat > 0) <span class="rv-mini terlambat"><i class="fas fa-clock"></i> {{ $dTerlambat }}</span> @endif
|
||||||
@endif
|
@if($dIzin > 0) <span class="rv-mini izin"><i class="fas fa-envelope"></i> {{ $dIzin }}</span> @endif
|
||||||
@if($dayTerlambat > 0)
|
@if($dSakit > 0) <span class="rv-mini sakit"><i class="fas fa-heartbeat"></i> {{ $dSakit }}</span> @endif
|
||||||
<span class="mini-badge terlambat"><i class="fas fa-clock"></i> {{ $dayTerlambat }}</span>
|
@if($dAlpa > 0) <span class="rv-mini alpa"><i class="fas fa-times"></i> {{ $dAlpa }}</span> @endif
|
||||||
@endif
|
@if($dPulang > 0) <span class="rv-mini pulang"><i class="fas fa-home"></i> {{ $dPulang }}</span> @endif
|
||||||
@if($dayIzin > 0)
|
<i class="fas fa-chevron-down rv-toggle"></i>
|
||||||
<span class="mini-badge izin"><i class="fas fa-envelope"></i> {{ $dayIzin }}</span>
|
|
||||||
@endif
|
|
||||||
@if($daySakit > 0)
|
|
||||||
<span class="mini-badge sakit"><i class="fas fa-heartbeat"></i> {{ $daySakit }}</span>
|
|
||||||
@endif
|
|
||||||
@if($dayAlpa > 0)
|
|
||||||
<span class="mini-badge alpa"><i class="fas fa-times"></i> {{ $dayAlpa }}</span>
|
|
||||||
@endif
|
|
||||||
@if($dayPulang > 0)
|
|
||||||
<span class="mini-badge pulang"><i class="fas fa-home"></i> {{ $dayPulang }}</span>
|
|
||||||
@endif
|
|
||||||
<i class="fas fa-chevron-down toggle-icon"></i>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="day-body">
|
|
||||||
@foreach($recordsPerKelas as $namaKelas => $kelasRecords)
|
{{-- Day body --}}
|
||||||
<div style="background: linear-gradient(135deg, #f0fdf4, #e8f5e9); padding: 8px 18px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #e2e8f0;">
|
<div class="rv-day-body">
|
||||||
<span style="font-size: 0.85rem; font-weight: 600; color: #065f46;">
|
@foreach($perKelas as $namaKelas => $kelasRecords)
|
||||||
|
|
||||||
|
{{-- Kelas sub-header --}}
|
||||||
|
<div class="rv-kelas-subhead">
|
||||||
|
<div class="name">
|
||||||
<i class="fas fa-school"></i> {{ $namaKelas }}
|
<i class="fas fa-school"></i> {{ $namaKelas }}
|
||||||
</span>
|
|
||||||
<span style="background: #6FBAA5; color: white; padding: 2px 10px; border-radius: 10px; font-size: 0.75rem; font-weight: 600;">
|
|
||||||
{{ $kelasRecords->count() }} santri
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<table>
|
<span class="cnt">{{ $kelasRecords->count() }} santri</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Santri table --}}
|
||||||
|
<table class="rv-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 45px;">No</th>
|
<th style="width:40px;">No</th>
|
||||||
<th style="width: 90px;">ID Santri</th>
|
<th style="width:90px;">ID</th>
|
||||||
<th>Nama Santri</th>
|
<th>Nama Santri</th>
|
||||||
<th style="width: 90px; text-align: center;">Status</th>
|
<th style="width:100px; text-align:center;">Status</th>
|
||||||
<th style="width: 80px; text-align: center;">Waktu</th>
|
<th style="width:75px; text-align:center;">Waktu</th>
|
||||||
<th style="width: 80px;">Metode</th>
|
<th style="width:85px;">Metode</th>
|
||||||
|
<th style="width:110px; text-align:center;">Riwayat</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach($kelasRecords->values() as $index => $riwayat)
|
@foreach($kelasRecords->values() as $idx => $riwayat)
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ $index + 1 }}</td>
|
<td style="color:#94a3b8; font-size:0.78rem;">{{ $idx + 1 }}</td>
|
||||||
<td><strong>{{ $riwayat->id_santri }}</strong></td>
|
<td>
|
||||||
|
<span style="font-size:0.78rem; font-weight:700; color:#64748b;">
|
||||||
|
{{ $riwayat->id_santri }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ route('admin.riwayat-kegiatan.detail-santri', $riwayat->id_santri) }}"
|
<a href="{{ route('admin.riwayat-kegiatan.detail-santri', $riwayat->id_santri) }}"
|
||||||
style="color: var(--primary-color); text-decoration: none; font-weight: 500;">
|
class="rv-santri-link">
|
||||||
|
<i class="fas fa-user" style="font-size:0.75rem; opacity:0.6;"></i>
|
||||||
{{ $riwayat->santri->nama_lengkap }}
|
{{ $riwayat->santri->nama_lengkap }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align: center;">{!! $riwayat->status_badge !!}</td>
|
|
||||||
<td style="text-align:center;">
|
<td style="text-align:center;">
|
||||||
{{ $riwayat->waktu_absen ? \Carbon\Carbon::parse($riwayat->waktu_absen)->format('H:i') : '-' }}
|
{!! $riwayat->status_badge !!}
|
||||||
|
</td>
|
||||||
|
<td style="text-align:center; font-size:0.8rem; color:#64748b;">
|
||||||
|
{{ $riwayat->waktu_absen ? \Carbon\Carbon::parse($riwayat->waktu_absen)->format('H:i') : '–' }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@if($riwayat->metode_absen == 'RFID')
|
@if($riwayat->metode_absen === 'RFID')
|
||||||
<span style="background: #DBEAFE; color: #1E40AF; padding: 3px 8px; border-radius: 10px; font-size: 0.75rem; font-weight: 600;">
|
<span class="rv-rfid"><i class="fas fa-id-card"></i> RFID</span>
|
||||||
<i class="fas fa-id-card"></i> RFID
|
@elseif($riwayat->metode_absen === 'Import_Mesin')
|
||||||
</span>
|
<span class="rv-mesin"><i class="fas fa-desktop"></i> Mesin</span>
|
||||||
@elseif($riwayat->metode_absen == 'Import_Mesin')
|
|
||||||
<span style="background: #EDE9FE; color: #6B21A8; padding: 3px 8px; border-radius: 10px; font-size: 0.75rem; font-weight: 600;">
|
|
||||||
<i class="fas fa-desktop"></i> Mesin
|
|
||||||
</span>
|
|
||||||
@else
|
@else
|
||||||
<span style="background: #E5E7EB; color: #374151; padding: 3px 8px; border-radius: 10px; font-size: 0.75rem; font-weight: 600;">
|
<span class="rv-manual"><i class="fas fa-hand-pointer"></i> Manual</span>
|
||||||
<i class="fas fa-hand-pointer"></i> Manual
|
|
||||||
</span>
|
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
|
<td style="text-align:center;">
|
||||||
|
<a href="{{ route('admin.riwayat-kegiatan.detail-santri', $riwayat->id_santri) }}"
|
||||||
|
class="btn-rv-history" title="Lihat seluruh riwayat {{ $riwayat->santri->nama_lengkap }}">
|
||||||
|
<i class="fas fa-chart-line"></i> Riwayat
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>{{-- end rv-day-body --}}
|
||||||
</div>
|
</div>{{-- end rv-day-group --}}
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
<div class="pagination">
|
<div style="margin-top:14px;">
|
||||||
{!! $riwayats->appends(request()->query())->links('pagination::simple-bootstrap-4') !!}
|
{!! $riwayats->appends(request()->query())->links('pagination::simple-bootstrap-4') !!}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@else
|
@else
|
||||||
<div class="empty-state">
|
<div class="rv-empty">
|
||||||
<i class="fas fa-inbox"></i>
|
<i class="fas fa-inbox"></i>
|
||||||
<h3>Tidak Ada Riwayat</h3>
|
<h3>Tidak Ada Data</h3>
|
||||||
<p>Tidak ada data absensi untuk periode <strong>{{ $periodeLabel }}</strong>.</p>
|
<p>Tidak ada riwayat absensi untuk periode <strong>{{ $periodeLabel }}</strong>.</p>
|
||||||
|
@if(request()->hasAny(['id_santri','id_kelas','status','tanggal_spesifik']))
|
||||||
|
<p style="margin-top:8px; font-size:0.82rem;">
|
||||||
|
Coba
|
||||||
|
<a href="{{ route('admin.riwayat-kegiatan.show', $kegiatan->id) }}?{{ http_build_query(['mode'=>$mode,'dari'=>$dari,'sampai'=>$sampai,'tanggal'=>$tanggal]) }}"
|
||||||
|
style="color:var(--primary-color);">hapus filter</a>
|
||||||
|
untuk melihat semua data.
|
||||||
|
</p>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function toggleDay(header) {
|
function toggleDay(header) {
|
||||||
var body = header.nextElementSibling;
|
var body = header.nextElementSibling;
|
||||||
var icon = header.querySelector('.toggle-icon');
|
var icon = header.querySelector('.rv-toggle');
|
||||||
if (body.style.display === 'none') {
|
if (body.style.display === 'none') {
|
||||||
body.style.display = 'block';
|
body.style.display = 'block';
|
||||||
icon.classList.remove('collapsed');
|
icon.classList.remove('closed');
|
||||||
} else {
|
} else {
|
||||||
body.style.display = 'none';
|
body.style.display = 'none';
|
||||||
icon.classList.add('collapsed');
|
icon.classList.add('closed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,6 @@
|
||||||
<p style="margin: 5px 0;"><strong>Sisa Kuota:</strong> <span id="sisaKuota" class="badge">-</span></p>
|
<p style="margin: 5px 0;"><strong>Sisa Kuota:</strong> <span id="sisaKuota" class="badge">-</span></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Progress Bar Kuota --}}
|
|
||||||
<div style="margin-top: 15px;">
|
<div style="margin-top: 15px;">
|
||||||
<label style="font-size: 0.9rem; color: #7F8C8D; margin-bottom: 5px;">Penggunaan Kuota:</label>
|
<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 style="width: 100%; height: 20px; background: #E0F0EC; border-radius: 10px; overflow: hidden; position: relative;">
|
||||||
|
|
@ -76,10 +74,9 @@
|
||||||
</div>
|
</div>
|
||||||
<small id="progressText" style="color: #7F8C8D; margin-top: 5px; display: block;">0% dari kuota terpakai</small>
|
<small id="progressText" style="color: #7F8C8D; margin-top: 5px; display: block;">0% dari kuota terpakai</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="warningOverLimit" style="display: none; margin-top: 15px; padding: 12px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; color: #856404;">
|
<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>
|
<i class="fas fa-exclamation-triangle"></i>
|
||||||
<strong>âš ï¸ PERHATIAN:</strong> <span id="warningText"></span>
|
<strong>PERHATIAN:</strong> <span id="warningText"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -89,32 +86,22 @@
|
||||||
<i class="fas fa-calendar-alt form-icon"></i>
|
<i class="fas fa-calendar-alt form-icon"></i>
|
||||||
Tanggal Pulang <span style="color: #dc3545;">*</span>
|
Tanggal Pulang <span style="color: #dc3545;">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input type="date"
|
<input type="date" name="tanggal_pulang" id="tanggal_pulang" class="form-control"
|
||||||
name="tanggal_pulang"
|
value="{{ old('tanggal_pulang', date('Y-m-d')) }}" min="{{ date('Y-m-d') }}" required>
|
||||||
id="tanggal_pulang"
|
|
||||||
class="form-control"
|
|
||||||
value="{{ old('tanggal_pulang', date('Y-m-d')) }}"
|
|
||||||
min="{{ date('Y-m-d') }}"
|
|
||||||
required>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="tanggal_kembali">
|
<label for="tanggal_kembali">
|
||||||
<i class="fas fa-calendar-check form-icon"></i>
|
<i class="fas fa-calendar-check form-icon"></i>
|
||||||
Tanggal Kembali <span style="color: #dc3545;">*</span>
|
Tanggal Kembali <span style="color: #dc3545;">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input type="date"
|
<input type="date" name="tanggal_kembali" id="tanggal_kembali" class="form-control"
|
||||||
name="tanggal_kembali"
|
value="{{ old('tanggal_kembali') }}" required>
|
||||||
id="tanggal_kembali"
|
|
||||||
class="form-control"
|
|
||||||
value="{{ old('tanggal_kembali') }}"
|
|
||||||
required>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Info Durasi Izin --}}
|
{{-- Info Durasi Izin --}}
|
||||||
<div id="durasiInfo" style="display: none; background: #fff3e0; padding: 14px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #ff9800;">
|
<div id="durasiInfo" style="display: none; background: #fff3e0; padding: 14px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #ff9800;">
|
||||||
<h4 style="margin-top: 0; color: #2C3E50;">â±ï¸ Detail Durasi Izin</h4>
|
<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: 11px;">
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 11px;">
|
||||||
<div style="text-align: center; padding: 15px; background: white; border-radius: 8px;">
|
<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 style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Durasi Izin</div>
|
||||||
|
|
@ -134,7 +121,7 @@ class="form-control"
|
||||||
</div>
|
</div>
|
||||||
<div id="warningDurasi" style="display: none; margin-top: 15px; padding: 12px; background: #ffebee; border: 1px solid #ffcdd2; border-radius: 6px; color: #c62828;">
|
<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>
|
<i class="fas fa-exclamation-circle"></i>
|
||||||
<strong>âš ï¸ PERHATIAN:</strong> <span id="warningDurasiMessage"></span>
|
<strong>PERHATIAN:</strong> <span id="warningDurasiMessage"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -143,12 +130,8 @@ class="form-control"
|
||||||
<i class="fas fa-comment-alt form-icon"></i>
|
<i class="fas fa-comment-alt form-icon"></i>
|
||||||
Alasan Kepulangan <span style="color: #dc3545;">*</span>
|
Alasan Kepulangan <span style="color: #dc3545;">*</span>
|
||||||
</label>
|
</label>
|
||||||
<textarea name="alasan"
|
<textarea name="alasan" id="alasan" class="form-control" rows="4"
|
||||||
id="alasan"
|
placeholder="Jelaskan alasan kepulangan" required>{{ old('alasan') }}</textarea>
|
||||||
class="form-control"
|
|
||||||
rows="4"
|
|
||||||
placeholder="Jelaskan alasan kepulangan"
|
|
||||||
required>{{ old('alasan') }}</textarea>
|
|
||||||
<small style="color: #7F8C8D; margin-top: 5px; display: block;">
|
<small style="color: #7F8C8D; margin-top: 5px; display: block;">
|
||||||
<span id="charCount">0</span>/500 karakter
|
<span id="charCount">0</span>/500 karakter
|
||||||
</small>
|
</small>
|
||||||
|
|
@ -172,16 +155,13 @@ class="form-control"
|
||||||
<div class="modal fade" id="overLimitModal" tabindex="-1" style="display: none;">
|
<div class="modal fade" id="overLimitModal" tabindex="-1" style="display: none;">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
||||||
<div style="margin-bottom: 14px;">
|
<div style="margin-bottom: 14px;"><h3 style="margin: 0; color: #2C3E50;">Konfirmasi Izin Melebihi Batas</h3></div>
|
||||||
<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;">
|
<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>
|
<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>
|
<h4 style="margin: 10px 0; color: #856404;">Peringatan!</h4>
|
||||||
<p id="overLimitMessage" style="margin: 0; color: #856404;"></p>
|
<p id="overLimitMessage" style="margin: 0; color: #856404;"></p>
|
||||||
</div>
|
</div>
|
||||||
<p style="margin: 15px 0;">Izin tetap bisa diproses, tetapi santri ini akan <strong>melebihi kuota maksimal</strong>.</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: 14px;">
|
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('overLimitModal')">Batal</button>
|
<button type="button" class="btn btn-secondary" onclick="closeModal('overLimitModal')">Batal</button>
|
||||||
<button type="button" class="btn btn-warning" id="confirmOverLimit" style="background: #ff9800; border-color: #ff9800;">
|
<button type="button" class="btn btn-warning" id="confirmOverLimit" style="background: #ff9800; border-color: #ff9800;">
|
||||||
|
|
@ -199,14 +179,18 @@ class="form-control"
|
||||||
.badge { display: inline-block; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; font-weight: 600; }
|
.badge { display: inline-block; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; font-weight: 600; }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
{{-- ✅ FIX: Definisikan URL API dari Laravel, bukan hardcode --}}
|
||||||
|
<script>
|
||||||
|
const KEPULANGAN_API_URL = "{{ url('admin/kepulangan/api/santri') }}";
|
||||||
|
const KUOTA_MAKSIMAL = {{ $settings->kuota_maksimal }};
|
||||||
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let currentSantriData = null;
|
let currentSantriData = null;
|
||||||
let isOverLimit = false;
|
let isOverLimit = false;
|
||||||
|
|
||||||
// Load santri data when selected
|
|
||||||
document.getElementById('id_santri').addEventListener('change', function() {
|
document.getElementById('id_santri').addEventListener('change', function() {
|
||||||
const santriId = this.value;
|
const santriId = this.value;
|
||||||
|
|
||||||
if (!santriId) {
|
if (!santriId) {
|
||||||
document.getElementById('santriInfo').style.display = 'none';
|
document.getElementById('santriInfo').style.display = 'none';
|
||||||
currentSantriData = null;
|
currentSantriData = null;
|
||||||
|
|
@ -216,16 +200,12 @@ class="form-control"
|
||||||
|
|
||||||
const infoDiv = document.getElementById('santriInfo');
|
const infoDiv = document.getElementById('santriInfo');
|
||||||
infoDiv.style.display = 'block';
|
infoDiv.style.display = 'block';
|
||||||
|
|
||||||
// Show loading state
|
|
||||||
infoDiv.innerHTML = '<div style="text-align: center; padding: 14px;"><i class="fas fa-spinner fa-spin"></i> Memuat data santri...</div>';
|
infoDiv.innerHTML = '<div style="text-align: center; padding: 14px;"><i class="fas fa-spinner fa-spin"></i> Memuat data santri...</div>';
|
||||||
|
|
||||||
// PERBAIKAN: Proper error handling untuk API
|
// ✅ FIX: pakai KEPULANGAN_API_URL dari Laravel
|
||||||
fetch(`/admin/kepulangan/api/santri/${santriId}`)
|
fetch(`${KEPULANGAN_API_URL}/${santriId}`)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!response.ok) {
|
if (!response.ok) throw new Error('Network response was not ok');
|
||||||
throw new Error('Network response was not ok');
|
|
||||||
}
|
|
||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
|
|
@ -243,70 +223,52 @@ class="form-control"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// PERBAIKAN: Function untuk show error
|
|
||||||
function showError(message) {
|
function showError(message) {
|
||||||
const infoDiv = document.getElementById('santriInfo');
|
const infoDiv = document.getElementById('santriInfo');
|
||||||
infoDiv.innerHTML = `
|
infoDiv.innerHTML = `
|
||||||
<div style="padding: 15px; background: #ffebee; border: 1px solid #ffcdd2; border-radius: 6px; color: #c62828;">
|
<div style="padding: 15px; background: #ffebee; border: 1px solid #ffcdd2; border-radius: 6px; color: #c62828;">
|
||||||
<i class="fas fa-exclamation-circle"></i>
|
<i class="fas fa-exclamation-circle"></i> <strong>Error:</strong> ${message}
|
||||||
<strong>Error:</strong> ${message}
|
</div>`;
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
currentSantriData = null;
|
currentSantriData = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSantriInfo(data) {
|
function updateSantriInfo(data) {
|
||||||
const santri = data.santri;
|
const santri = data.santri;
|
||||||
const kuota = data.penggunaan_izin;
|
const kuota = data.penggunaan_izin;
|
||||||
|
|
||||||
// Rebuild HTML structure
|
|
||||||
const infoDiv = document.getElementById('santriInfo');
|
const infoDiv = document.getElementById('santriInfo');
|
||||||
infoDiv.innerHTML = `
|
infoDiv.innerHTML = `
|
||||||
<h4 style="margin-top: 0; color: #2C3E50;">Informasi Santri & Kuota</h4>
|
<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 style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px;">
|
||||||
<div>
|
<div>
|
||||||
<p style="margin: 5px 0;"><strong>Nama:</strong> <span id="santriNama">${santri.nama_lengkap}</span></p>
|
<p style="margin: 5px 0;"><strong>Nama:</strong> ${santri.nama_lengkap}</p>
|
||||||
<p style="margin: 5px 0;"><strong>Kelas:</strong> <span id="santriKelas">${santri.kelas}</span></p>
|
<p style="margin: 5px 0;"><strong>Kelas:</strong> ${santri.kelas}</p>
|
||||||
<p style="margin: 5px 0;"><strong>Periode:</strong> <span id="santriPeriode">${kuota.periode_mulai} - ${kuota.periode_akhir}</span></p>
|
<p style="margin: 5px 0;"><strong>Periode:</strong> ${kuota.periode_mulai} - ${kuota.periode_akhir}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p style="margin: 5px 0;"><strong>Kuota Maksimal:</strong> <span id="kuotaMaksimal">${kuota.kuota_maksimal} hari</span></p>
|
<p style="margin: 5px 0;"><strong>Kuota Maksimal:</strong> ${kuota.kuota_maksimal} hari</p>
|
||||||
<p style="margin: 5px 0;"><strong>Total Terpakai:</strong> <span id="totalTerpakai" class="badge" style="background: ${getBadgeColor(kuota.badge_color)}; color: ${kuota.badge_color === 'warning' ? '#000' : 'white'};">${kuota.total_terpakai} hari</span></p>
|
<p style="margin: 5px 0;"><strong>Total Terpakai:</strong> <span style="display:inline-block;background:${getBadgeColor(kuota.badge_color)};color:${kuota.badge_color==='warning'?'#000':'white'};padding:4px 10px;border-radius:4px;font-weight:600;">${kuota.total_terpakai} hari</span></p>
|
||||||
<p style="margin: 5px 0;"><strong>Sisa Kuota:</strong> <span id="sisaKuota" class="badge" style="background: ${getBadgeColor(kuota.badge_color)}; color: ${kuota.badge_color === 'warning' ? '#000' : 'white'};">${kuota.sisa_kuota} hari</span></p>
|
<p style="margin: 5px 0;"><strong>Sisa Kuota:</strong> <span style="display:inline-block;background:${getBadgeColor(kuota.badge_color)};color:${kuota.badge_color==='warning'?'#000':'white'};padding:4px 10px;border-radius:4px;font-weight:600;">${kuota.sisa_kuota} hari</span></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="margin-top: 15px;">
|
<div style="margin-top: 15px;">
|
||||||
<label style="font-size: 0.9rem; color: #7F8C8D; margin-bottom: 5px;">Penggunaan Kuota:</label>
|
<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 style="width: 100%; height: 20px; background: #E0F0EC; border-radius: 10px; overflow: hidden;">
|
||||||
<div id="progressBar" style="height: 100%; width: ${Math.min(100, kuota.persentase)}%; background: ${getProgressColor(kuota.persentase)}; transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.75rem; font-weight: 600;">${kuota.persentase}%</div>
|
<div style="height:100%;width:${Math.min(100,kuota.persentase)}%;background:${getProgressColor(kuota.persentase)};display:flex;align-items:center;justify-content:center;color:white;font-size:0.75rem;font-weight:600;">${kuota.persentase}%</div>
|
||||||
</div>
|
</div>
|
||||||
<small id="progressText" style="color: #7F8C8D; margin-top: 5px; display: block;">${kuota.persentase}% dari kuota terpakai</small>
|
<small style="color: #7F8C8D; margin-top: 5px; display: block;">${kuota.persentase}% dari kuota terpakai</small>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="display:${kuota.status==='melebihi'?'block':'none'};margin-top:15px;padding:12px;background:#fff3cd;border:1px solid #ffeaa7;border-radius:6px;color:#856404;">
|
||||||
<div id="warningOverLimit" style="display: ${kuota.status === 'melebihi' ? 'block' : '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>PERHATIAN:</strong> Santri ini sudah melebihi kuota ${kuota.kuota_maksimal} hari! Total terpakai: ${kuota.total_terpakai} hari.
|
||||||
<i class="fas fa-exclamation-triangle"></i>
|
</div>`;
|
||||||
<strong>âš ï¸ PERHATIAN:</strong> <span id="warningText">Santri ini sudah melebihi kuota ${kuota.kuota_maksimal} hari per tahun! Total terpakai: ${kuota.total_terpakai} hari.</span>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBadgeColor(badge) {
|
function getBadgeColor(badge) {
|
||||||
const colors = {
|
return { 'success': '#28a745', 'warning': '#ffc107', 'danger': '#dc3545' }[badge] || '#6c757d';
|
||||||
'success': '#28a745',
|
}
|
||||||
'warning': '#ffc107',
|
function getProgressColor(p) {
|
||||||
'danger': '#dc3545'
|
return p >= 100 ? '#dc3545' : p >= 80 ? '#ffc107' : '#28a745';
|
||||||
};
|
|
||||||
return colors[badge] || '#6c757d';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getProgressColor(persentase) {
|
|
||||||
if (persentase >= 100) return '#dc3545';
|
|
||||||
if (persentase >= 80) return '#ffc107';
|
|
||||||
return '#28a745';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate durasi when dates change
|
|
||||||
document.getElementById('tanggal_pulang').addEventListener('change', calculateDurasi);
|
document.getElementById('tanggal_pulang').addEventListener('change', calculateDurasi);
|
||||||
document.getElementById('tanggal_kembali').addEventListener('change', calculateDurasi);
|
document.getElementById('tanggal_kembali').addEventListener('change', calculateDurasi);
|
||||||
|
|
||||||
|
|
@ -314,168 +276,96 @@ function calculateDurasi() {
|
||||||
const tanggalPulang = document.getElementById('tanggal_pulang').value;
|
const tanggalPulang = document.getElementById('tanggal_pulang').value;
|
||||||
const tanggalKembali = document.getElementById('tanggal_kembali').value;
|
const tanggalKembali = document.getElementById('tanggal_kembali').value;
|
||||||
const durasiInfoDiv = document.getElementById('durasiInfo');
|
const durasiInfoDiv = document.getElementById('durasiInfo');
|
||||||
|
if (!tanggalPulang || !tanggalKembali) { durasiInfoDiv.style.display = 'none'; return; }
|
||||||
if (!tanggalPulang || !tanggalKembali) {
|
|
||||||
durasiInfoDiv.style.display = 'none';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const startDate = new Date(tanggalPulang);
|
const startDate = new Date(tanggalPulang);
|
||||||
const endDate = new Date(tanggalKembali);
|
const endDate = new Date(tanggalKembali);
|
||||||
|
if (endDate <= startDate) { durasiInfoDiv.style.display = 'none'; return; }
|
||||||
if (endDate <= startDate) {
|
const diffDays = Math.ceil(Math.abs(endDate - startDate) / (1000 * 60 * 60 * 24)) + 1;
|
||||||
durasiInfoDiv.style.display = 'none';
|
|
||||||
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';
|
durasiInfoDiv.style.display = 'block';
|
||||||
|
|
||||||
// Update durasi
|
|
||||||
document.getElementById('durasiHari').textContent = diffDays;
|
document.getElementById('durasiHari').textContent = diffDays;
|
||||||
|
|
||||||
let totalSetelah = diffDays;
|
let totalSetelah = diffDays;
|
||||||
let sisaSetelah = {{ $settings->kuota_maksimal }} - diffDays;
|
let sisaSetelah = KUOTA_MAKSIMAL - diffDays;
|
||||||
let showWarning = false;
|
let showWarning = false, warningMessage = '';
|
||||||
let warningMessage = '';
|
|
||||||
|
|
||||||
if (currentSantriData) {
|
if (currentSantriData) {
|
||||||
const currentUsage = currentSantriData.penggunaan_izin.total_terpakai;
|
const currentUsage = currentSantriData.penggunaan_izin.total_terpakai;
|
||||||
const kuotaMaks = currentSantriData.penggunaan_izin.kuota_maksimal;
|
const kuotaMaks = currentSantriData.penggunaan_izin.kuota_maksimal;
|
||||||
|
|
||||||
totalSetelah = currentUsage + diffDays;
|
totalSetelah = currentUsage + diffDays;
|
||||||
sisaSetelah = kuotaMaks - totalSetelah;
|
sisaSetelah = kuotaMaks - totalSetelah;
|
||||||
|
|
||||||
// Update nilai
|
|
||||||
document.getElementById('totalSetelahIzin').textContent = totalSetelah;
|
document.getElementById('totalSetelahIzin').textContent = totalSetelah;
|
||||||
document.getElementById('sisaKuotaSetelah').textContent = Math.max(0, sisaSetelah);
|
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) {
|
if (totalSetelah > kuotaMaks) {
|
||||||
totalSetelahEl.style.color = '#dc3545';
|
document.getElementById('totalSetelahIzin').style.color = '#dc3545';
|
||||||
sisaSetelahEl.style.color = '#dc3545';
|
document.getElementById('sisaKuotaSetelah').style.color = '#dc3545';
|
||||||
showWarning = true;
|
showWarning = true;
|
||||||
warningMessage = `Izin ini akan melebihi batas ${kuotaMaks} hari per tahun (Total setelah izin: ${totalSetelah} hari, Kelebihan: ${totalSetelah - kuotaMaks} hari)`;
|
warningMessage = `Izin ini akan melebihi batas ${kuotaMaks} hari (Total setelah izin: ${totalSetelah} hari, Kelebihan: ${totalSetelah - kuotaMaks} hari)`;
|
||||||
isOverLimit = true;
|
isOverLimit = true;
|
||||||
} else if (totalSetelah >= kuotaMaks * 0.8) {
|
} else if (totalSetelah >= kuotaMaks * 0.8) {
|
||||||
totalSetelahEl.style.color = '#ff9800';
|
document.getElementById('totalSetelahIzin').style.color = '#ff9800';
|
||||||
sisaSetelahEl.style.color = '#ff9800';
|
document.getElementById('sisaKuotaSetelah').style.color = '#ff9800';
|
||||||
showWarning = true;
|
showWarning = true;
|
||||||
warningMessage = `Perhatian: Kuota hampir habis! Sisa kuota setelah izin ini hanya ${sisaSetelah} hari.`;
|
warningMessage = `Kuota hampir habis! Sisa kuota setelah izin ini hanya ${sisaSetelah} hari.`;
|
||||||
isOverLimit = false;
|
isOverLimit = false;
|
||||||
} else {
|
} else {
|
||||||
totalSetelahEl.style.color = '#2196f3';
|
document.getElementById('totalSetelahIzin').style.color = '#2196f3';
|
||||||
sisaSetelahEl.style.color = '#28a745';
|
document.getElementById('sisaKuotaSetelah').style.color = '#28a745';
|
||||||
showWarning = false;
|
showWarning = false; isOverLimit = false;
|
||||||
isOverLimit = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tampilkan warning durasi
|
|
||||||
const warningDiv = document.getElementById('warningDurasi');
|
const warningDiv = document.getElementById('warningDurasi');
|
||||||
const warningMessageEl = document.getElementById('warningDurasiMessage');
|
warningDiv.style.display = showWarning ? 'block' : 'none';
|
||||||
if (showWarning) {
|
if (showWarning) document.getElementById('warningDurasiMessage').textContent = warningMessage;
|
||||||
warningDiv.style.display = 'block';
|
|
||||||
warningMessageEl.textContent = warningMessage;
|
|
||||||
} else {
|
|
||||||
warningDiv.style.display = 'none';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Character counter (PERBAIKAN: Tidak ada validasi minimal)
|
|
||||||
document.getElementById('alasan').addEventListener('input', function() {
|
document.getElementById('alasan').addEventListener('input', function() {
|
||||||
const current = this.value.length;
|
|
||||||
const counter = document.getElementById('charCount');
|
const counter = document.getElementById('charCount');
|
||||||
counter.textContent = current;
|
counter.textContent = this.value.length;
|
||||||
|
counter.style.color = this.value.length > 500 ? 'red' : '#7F8C8D';
|
||||||
if (current > 500) {
|
|
||||||
counter.style.color = 'red';
|
|
||||||
} else {
|
|
||||||
counter.style.color = '#7F8C8D';
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Form submission with over limit confirmation
|
|
||||||
document.getElementById('kepulanganForm').addEventListener('submit', function(e) {
|
document.getElementById('kepulanganForm').addEventListener('submit', function(e) {
|
||||||
if (isOverLimit) {
|
if (isOverLimit) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
const msg = document.getElementById('warningDurasiMessage')?.textContent || 'Izin ini akan melebihi batas kuota';
|
||||||
const warningMessageEl = document.getElementById('warningDurasiMessage');
|
document.getElementById('overLimitMessage').textContent = msg;
|
||||||
const message = warningMessageEl ? warningMessageEl.textContent : 'Izin ini akan melebihi batas kuota per tahun';
|
|
||||||
document.getElementById('overLimitMessage').textContent = message;
|
|
||||||
|
|
||||||
document.getElementById('overLimitModal').style.display = 'flex';
|
document.getElementById('overLimitModal').style.display = 'flex';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Confirm over limit submission
|
|
||||||
document.getElementById('confirmOverLimit').addEventListener('click', function() {
|
document.getElementById('confirmOverLimit').addEventListener('click', function() {
|
||||||
closeModal('overLimitModal');
|
closeModal('overLimitModal');
|
||||||
isOverLimit = false;
|
isOverLimit = false;
|
||||||
document.getElementById('kepulanganForm').submit();
|
document.getElementById('kepulanganForm').submit();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Auto-set minimum tanggal_kembali
|
|
||||||
document.getElementById('tanggal_pulang').addEventListener('change', function() {
|
document.getElementById('tanggal_pulang').addEventListener('change', function() {
|
||||||
const pulangDate = new Date(this.value);
|
const pulangDate = new Date(this.value);
|
||||||
pulangDate.setDate(pulangDate.getDate() + 1);
|
pulangDate.setDate(pulangDate.getDate() + 1);
|
||||||
|
const minKembali = pulangDate.toISOString().split('T')[0];
|
||||||
const minKembaliDate = pulangDate.toISOString().split('T')[0];
|
document.getElementById('tanggal_kembali').min = minKembali;
|
||||||
document.getElementById('tanggal_kembali').min = minKembaliDate;
|
|
||||||
|
|
||||||
const currentKembali = document.getElementById('tanggal_kembali').value;
|
const currentKembali = document.getElementById('tanggal_kembali').value;
|
||||||
if (currentKembali && currentKembali <= this.value) {
|
if (currentKembali && currentKembali <= this.value) document.getElementById('tanggal_kembali').value = minKembali;
|
||||||
document.getElementById('tanggal_kembali').value = minKembaliDate;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
const today = new Date().toISOString().split('T')[0];
|
|
||||||
document.getElementById('tanggal_pulang').min = today;
|
|
||||||
|
|
||||||
const alasanField = document.getElementById('alasan');
|
|
||||||
document.getElementById('charCount').textContent = alasanField.value.length;
|
|
||||||
|
|
||||||
calculateDurasi();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Form reset handler
|
|
||||||
document.querySelector('button[type="reset"]').addEventListener('click', function() {
|
document.querySelector('button[type="reset"]').addEventListener('click', function() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.getElementById('santriInfo').style.display = 'none';
|
document.getElementById('santriInfo').style.display = 'none';
|
||||||
document.getElementById('durasiInfo').style.display = 'none';
|
document.getElementById('durasiInfo').style.display = 'none';
|
||||||
currentSantriData = null;
|
currentSantriData = null; isOverLimit = false;
|
||||||
isOverLimit = false;
|
|
||||||
document.getElementById('charCount').textContent = '0';
|
document.getElementById('charCount').textContent = '0';
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Helper functions
|
function closeModal(modalId) { document.getElementById(modalId).style.display = 'none'; }
|
||||||
function closeModal(modalId) {
|
|
||||||
document.getElementById(modalId).style.display = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close modal on ESC
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
document.addEventListener('keydown', function(e) {
|
document.getElementById('tanggal_pulang').min = new Date().toISOString().split('T')[0];
|
||||||
if (e.key === 'Escape') {
|
document.getElementById('charCount').textContent = document.getElementById('alasan').value.length;
|
||||||
document.querySelectorAll('.modal.fade').forEach(modal => modal.style.display = 'none');
|
calculateDurasi();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Close modal on outside click
|
document.addEventListener('keydown', e => { if (e.key === 'Escape') document.querySelectorAll('.modal.fade').forEach(m => m.style.display = 'none'); });
|
||||||
document.querySelectorAll('.modal.fade').forEach(modal => {
|
document.querySelectorAll('.modal.fade').forEach(modal => {
|
||||||
modal.addEventListener('click', function(e) {
|
modal.addEventListener('click', function(e) { if (e.target === this) this.style.display = 'none'; });
|
||||||
if (e.target === this) {
|
|
||||||
this.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
@ -104,8 +104,6 @@
|
||||||
<a href="{{ route('admin.kepulangan.create') }}" class="btn btn-primary">
|
<a href="{{ route('admin.kepulangan.create') }}" class="btn btn-primary">
|
||||||
<i class="fas fa-plus"></i> Tambah Izin Kepulangan
|
<i class="fas fa-plus"></i> Tambah Izin Kepulangan
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
{{-- TOMBOL PENGAJUAN MOBILE (BARU) --}}
|
|
||||||
<a href="{{ route('admin.kepulangan.pengajuan') }}" class="btn btn-warning">
|
<a href="{{ route('admin.kepulangan.pengajuan') }}" class="btn btn-warning">
|
||||||
<i class="fas fa-mobile-alt"></i> Pengajuan izin
|
<i class="fas fa-mobile-alt"></i> Pengajuan izin
|
||||||
@if($pendingPengajuan > 0)
|
@if($pendingPengajuan > 0)
|
||||||
|
|
@ -121,14 +119,8 @@
|
||||||
<form method="GET" action="{{ route('admin.kepulangan.index') }}" id="filterForm" style="margin-bottom: 14px;">
|
<form method="GET" action="{{ route('admin.kepulangan.index') }}" id="filterForm" style="margin-bottom: 14px;">
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px; align-items: end;">
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px; align-items: end;">
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
<div class="form-group" style="margin-bottom: 0;">
|
||||||
<input type="text"
|
<input type="text" name="search" class="form-control" placeholder="Cari nama, ID, atau alasan..." value="{{ request('search') }}" id="searchInput">
|
||||||
name="search"
|
|
||||||
class="form-control"
|
|
||||||
placeholder="Cari nama, ID, atau alasan..."
|
|
||||||
value="{{ request('search') }}"
|
|
||||||
id="searchInput">
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
<div class="form-group" style="margin-bottom: 0;">
|
||||||
<select name="status" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
<select name="status" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
||||||
<option value="">Semua Status</option>
|
<option value="">Semua Status</option>
|
||||||
|
|
@ -138,18 +130,14 @@ class="form-control"
|
||||||
<option value="Selesai" {{ request('status') == 'Selesai' ? 'selected' : '' }}>Selesai</option>
|
<option value="Selesai" {{ request('status') == 'Selesai' ? 'selected' : '' }}>Selesai</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
<div class="form-group" style="margin-bottom: 0;">
|
||||||
<select name="tahun" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
<select name="tahun" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
||||||
<option value="">Semua Tahun</option>
|
<option value="">Semua Tahun</option>
|
||||||
@foreach($tahunList as $tahun)
|
@foreach($tahunList as $tahun)
|
||||||
<option value="{{ $tahun }}" {{ request('tahun') == $tahun ? 'selected' : '' }}>
|
<option value="{{ $tahun }}" {{ request('tahun') == $tahun ? 'selected' : '' }}>{{ $tahun }}</option>
|
||||||
{{ $tahun }}
|
|
||||||
</option>
|
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
<div class="form-group" style="margin-bottom: 0;">
|
||||||
<select name="bulan" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
<select name="bulan" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
||||||
<option value="">Semua Bulan</option>
|
<option value="">Semua Bulan</option>
|
||||||
|
|
@ -160,19 +148,14 @@ class="form-control"
|
||||||
@endfor
|
@endfor
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: flex; gap: 10px;">
|
<div style="display: flex; gap: 10px;">
|
||||||
<button type="submit" class="btn btn-primary">
|
<button type="submit" class="btn btn-primary"><i class="fas fa-search"></i> Filter</button>
|
||||||
<i class="fas fa-search"></i> Filter
|
<a href="{{ route('admin.kepulangan.index') }}" class="btn btn-secondary"><i class="fas fa-redo"></i> Reset</a>
|
||||||
</button>
|
|
||||||
<a href="{{ route('admin.kepulangan.index') }}" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-redo"></i> Reset
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{{-- Data Table (SAMA SEPERTI SEBELUMNYA) --}}
|
{{-- Data Table --}}
|
||||||
<div style="overflow-x: auto;">
|
<div style="overflow-x: auto;">
|
||||||
<div class="table-wrapper">
|
<div class="table-wrapper">
|
||||||
<table class="data-table">
|
<table class="data-table">
|
||||||
|
|
@ -199,8 +182,7 @@ class="form-control"
|
||||||
<td>
|
<td>
|
||||||
<strong>{{ $item->id_kepulangan }}</strong>
|
<strong>{{ $item->id_kepulangan }}</strong>
|
||||||
@if($isOverLimit)
|
@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;"
|
<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">
|
||||||
title="Over Limit: {{ $totalHariTerpakai }} hari">
|
|
||||||
<i class="fas fa-exclamation-triangle"></i>
|
<i class="fas fa-exclamation-triangle"></i>
|
||||||
</span>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
|
|
@ -208,9 +190,7 @@ class="form-control"
|
||||||
<td>
|
<td>
|
||||||
<div>
|
<div>
|
||||||
<strong>{{ $item->santri->nama_lengkap ?? 'N/A' }}</strong><br>
|
<strong>{{ $item->santri->nama_lengkap ?? 'N/A' }}</strong><br>
|
||||||
<small style="color: #7F8C8D;">
|
<small style="color: #7F8C8D;">{{ $item->santri->id_santri ?? '' }} | {{ $item->santri->kelas ?? '' }}</small>
|
||||||
{{ $item->santri->id_santri ?? '' }} | {{ $item->santri->kelas ?? '' }}
|
|
||||||
</small>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ $item->tanggal_pulang_formatted }}</td>
|
<td>{{ $item->tanggal_pulang_formatted }}</td>
|
||||||
|
|
@ -224,11 +204,7 @@ class="form-control"
|
||||||
@php
|
@php
|
||||||
$kuotaSantri = \App\Models\Kepulangan::getSisaKuotaSantri($item->id_santri);
|
$kuotaSantri = \App\Models\Kepulangan::getSisaKuotaSantri($item->id_santri);
|
||||||
$badgeColor = $kuotaSantri['badge_color'];
|
$badgeColor = $kuotaSantri['badge_color'];
|
||||||
$badgeColors = [
|
$badgeColors = ['success' => '#28a745', 'warning' => '#ffc107', 'danger' => '#dc3545'];
|
||||||
'success' => '#28a745',
|
|
||||||
'warning' => '#ffc107',
|
|
||||||
'danger' => '#dc3545'
|
|
||||||
];
|
|
||||||
$bgColor = $badgeColors[$badgeColor] ?? '#6c757d';
|
$bgColor = $badgeColors[$badgeColor] ?? '#6c757d';
|
||||||
$textColor = $badgeColor == 'warning' ? '#000' : '#fff';
|
$textColor = $badgeColor == 'warning' ? '#000' : '#fff';
|
||||||
@endphp
|
@endphp
|
||||||
|
|
@ -267,49 +243,32 @@ class="form-control"
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<div style="display: flex; gap: 5px; justify-content: center; flex-wrap: wrap;">
|
<div style="display: flex; gap: 5px; justify-content: center; flex-wrap: wrap;">
|
||||||
<a href="{{ route('admin.kepulangan.show', $item->id_kepulangan) }}"
|
<a href="{{ route('admin.kepulangan.show', $item->id_kepulangan) }}" class="btn btn-sm btn-primary" title="Detail">
|
||||||
class="btn btn-sm btn-primary" title="Detail">
|
|
||||||
<i class="fas fa-eye"></i>
|
<i class="fas fa-eye"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@if($item->status == 'Menunggu')
|
@if($item->status == 'Menunggu')
|
||||||
<a href="{{ route('admin.kepulangan.edit', $item->id_kepulangan) }}"
|
<a href="{{ route('admin.kepulangan.edit', $item->id_kepulangan) }}" class="btn btn-sm btn-warning" title="Edit">
|
||||||
class="btn btn-sm btn-warning" title="Edit">
|
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
<button type="button"
|
<button type="button" class="btn btn-sm btn-success" onclick="approveKepulangan('{{ $item->id_kepulangan }}')" title="Setujui">
|
||||||
class="btn btn-sm btn-success"
|
|
||||||
onclick="approveKepulangan('{{ $item->id_kepulangan }}')"
|
|
||||||
title="Setujui">
|
|
||||||
<i class="fas fa-check"></i>
|
<i class="fas fa-check"></i>
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button type="button" class="btn btn-sm btn-danger" onclick="rejectKepulangan('{{ $item->id_kepulangan }}')" title="Tolak">
|
||||||
class="btn btn-sm btn-danger"
|
|
||||||
onclick="rejectKepulangan('{{ $item->id_kepulangan }}')"
|
|
||||||
title="Tolak">
|
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-times"></i>
|
||||||
</button>
|
</button>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if($item->status == 'Disetujui')
|
@if($item->status == 'Disetujui')
|
||||||
<a href="{{ route('admin.kepulangan.print', $item->id_kepulangan) }}"
|
<a href="{{ route('admin.kepulangan.print', $item->id_kepulangan) }}" class="btn btn-sm btn-secondary" target="_blank" title="Cetak Surat">
|
||||||
class="btn btn-sm btn-secondary"
|
|
||||||
target="_blank" title="Cetak Surat">
|
|
||||||
<i class="fas fa-print"></i>
|
<i class="fas fa-print"></i>
|
||||||
</a>
|
</a>
|
||||||
<button type="button"
|
<button type="button" class="btn btn-sm btn-success"
|
||||||
class="btn btn-sm btn-success"
|
|
||||||
onclick="completeKepulangan('{{ $item->id_kepulangan }}', '{{ $item->santri->nama_lengkap }}', '{{ $item->tanggal_pulang->format('Y-m-d') }}', '{{ $item->tanggal_kembali->format('Y-m-d') }}', {{ $item->durasi_izin }})"
|
onclick="completeKepulangan('{{ $item->id_kepulangan }}', '{{ $item->santri->nama_lengkap }}', '{{ $item->tanggal_pulang->format('Y-m-d') }}', '{{ $item->tanggal_kembali->format('Y-m-d') }}', {{ $item->durasi_izin }})"
|
||||||
title="Selesaikan">
|
title="Selesaikan">
|
||||||
<i class="fas fa-check-double"></i>
|
<i class="fas fa-check-double"></i>
|
||||||
</button>
|
</button>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if(in_array($item->status, ['Menunggu', 'Ditolak', 'Selesai']))
|
@if(in_array($item->status, ['Menunggu', 'Ditolak', 'Selesai']))
|
||||||
<button type="button"
|
<button type="button" class="btn btn-sm btn-danger" onclick="deleteKepulangan('{{ $item->id_kepulangan }}')" title="Hapus">
|
||||||
class="btn btn-sm btn-danger"
|
|
||||||
onclick="deleteKepulangan('{{ $item->id_kepulangan }}')"
|
|
||||||
title="Hapus">
|
|
||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
@endif
|
@endif
|
||||||
|
|
@ -332,13 +291,8 @@ class="btn btn-sm btn-danger"
|
||||||
{{-- Pagination --}}
|
{{-- Pagination --}}
|
||||||
@if($kepulangan->hasPages())
|
@if($kepulangan->hasPages())
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 14px; flex-wrap: wrap; gap: 11px;">
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 14px; flex-wrap: wrap; gap: 11px;">
|
||||||
<div>
|
<div>Menampilkan {{ $kepulangan->firstItem() ?? 0 }} - {{ $kepulangan->lastItem() ?? 0 }} dari {{ $kepulangan->total() }} data</div>
|
||||||
Menampilkan {{ $kepulangan->firstItem() ?? 0 }} - {{ $kepulangan->lastItem() ?? 0 }}
|
<div>{{ $kepulangan->appends(request()->query())->links() }}</div>
|
||||||
dari {{ $kepulangan->total() }} data
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{ $kepulangan->appends(request()->query())->links() }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -349,19 +303,14 @@ class="btn btn-sm btn-danger"
|
||||||
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
||||||
<form id="approveForm">
|
<form id="approveForm">
|
||||||
@csrf
|
@csrf
|
||||||
<div style="margin-bottom: 14px;">
|
<div style="margin-bottom: 14px;"><h3 style="margin: 0; color: #2C3E50;">Setujui Izin Kepulangan</h3></div>
|
||||||
<h3 style="margin: 0; color: #2C3E50;">Setujui Izin Kepulangan</h3>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Catatan (Opsional):</label>
|
<label>Catatan (Opsional):</label>
|
||||||
<textarea name="catatan" class="form-control" rows="3"
|
<textarea name="catatan" class="form-control" rows="3" placeholder="Tambahkan catatan untuk persetujuan ini..."></textarea>
|
||||||
placeholder="Tambahkan catatan untuk persetujuan ini..."></textarea>
|
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('approveModal')">Batal</button>
|
<button type="button" class="btn btn-secondary" onclick="closeModal('approveModal')">Batal</button>
|
||||||
<button type="submit" class="btn btn-success">
|
<button type="submit" class="btn btn-success"><i class="fas fa-check"></i> Setujui</button>
|
||||||
<i class="fas fa-check"></i> Setujui
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -374,19 +323,14 @@ class="btn btn-sm btn-danger"
|
||||||
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
||||||
<form id="rejectForm">
|
<form id="rejectForm">
|
||||||
@csrf
|
@csrf
|
||||||
<div style="margin-bottom: 14px;">
|
<div style="margin-bottom: 14px;"><h3 style="margin: 0; color: #2C3E50;">Tolak Izin Kepulangan</h3></div>
|
||||||
<h3 style="margin: 0; color: #2C3E50;">Tolak Izin Kepulangan</h3>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Alasan Penolakan: <span style="color: #dc3545;">*</span></label>
|
<label>Alasan Penolakan: <span style="color: #dc3545;">*</span></label>
|
||||||
<textarea name="alasan_penolakan" class="form-control" rows="3"
|
<textarea name="alasan_penolakan" class="form-control" rows="3" placeholder="Jelaskan alasan penolakan..." required></textarea>
|
||||||
placeholder="Jelaskan alasan penolakan..." required></textarea>
|
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('rejectModal')">Batal</button>
|
<button type="button" class="btn btn-secondary" onclick="closeModal('rejectModal')">Batal</button>
|
||||||
<button type="submit" class="btn btn-danger">
|
<button type="submit" class="btn btn-danger"><i class="fas fa-times"></i> Tolak</button>
|
||||||
<i class="fas fa-times"></i> Tolak
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -397,34 +341,26 @@ class="btn btn-sm btn-danger"
|
||||||
<div class="modal fade" id="deleteModal" tabindex="-1" style="display: none;">
|
<div class="modal fade" id="deleteModal" tabindex="-1" style="display: none;">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
||||||
<div style="margin-bottom: 14px;">
|
<div style="margin-bottom: 14px;"><h3 style="margin: 0; color: #2C3E50;">Konfirmasi Hapus</h3></div>
|
||||||
<h3 style="margin: 0; color: #2C3E50;">Konfirmasi Hapus</h3>
|
|
||||||
</div>
|
|
||||||
<p>Apakah Anda yakin ingin menghapus data kepulangan ini?</p>
|
<p>Apakah Anda yakin ingin menghapus data kepulangan ini?</p>
|
||||||
<p style="color: #dc3545; font-size: 0.9rem;">Data yang sudah dihapus tidak dapat dikembalikan.</p>
|
<p style="color: #dc3545; font-size: 0.9rem;">Data yang sudah dihapus tidak dapat dikembalikan.</p>
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('deleteModal')">Batal</button>
|
<button type="button" class="btn btn-secondary" onclick="closeModal('deleteModal')">Batal</button>
|
||||||
<button type="button" class="btn btn-danger" id="confirmDeleteBtn">
|
<button type="button" class="btn btn-danger" id="confirmDeleteBtn"><i class="fas fa-trash"></i> Hapus</button>
|
||||||
<i class="fas fa-trash"></i> Hapus
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Modal Complete (Selesaikan Kepulangan) --}}
|
{{-- Modal Complete --}}
|
||||||
<div class="modal fade" id="completeModal" tabindex="-1" style="display: none;">
|
<div class="modal fade" id="completeModal" tabindex="-1" style="display: none;">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
||||||
<form id="completeForm">
|
<form id="completeForm">
|
||||||
@csrf
|
@csrf
|
||||||
<div style="margin-bottom: 14px;">
|
<div style="margin-bottom: 14px;">
|
||||||
<h3 style="margin: 0; color: #2C3E50;">
|
<h3 style="margin: 0; color: #2C3E50;"><i class="fas fa-check-circle" style="color: #28a745;"></i> Selesaikan Kepulangan</h3>
|
||||||
<i class="fas fa-check-circle" style="color: #28a745;"></i>
|
|
||||||
Selesaikan Kepulangan
|
|
||||||
</h3>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="background: #E8F7F2; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #6FBA9D;">
|
<div style="background: #E8F7F2; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #6FBA9D;">
|
||||||
<p style="margin: 5px 0;"><strong>ID Kepulangan:</strong> <span id="completeIdKepulangan"></span></p>
|
<p style="margin: 5px 0;"><strong>ID Kepulangan:</strong> <span id="completeIdKepulangan"></span></p>
|
||||||
<p style="margin: 5px 0;"><strong>Santri:</strong> <span id="completeNamaSantri"></span></p>
|
<p style="margin: 5px 0;"><strong>Santri:</strong> <span id="completeNamaSantri"></span></p>
|
||||||
|
|
@ -432,32 +368,20 @@ class="btn btn-sm btn-danger"
|
||||||
<p style="margin: 5px 0;"><strong>Rencana Kembali:</strong> <span id="completeTanggalKembaliRencana"></span></p>
|
<p style="margin: 5px 0;"><strong>Rencana Kembali:</strong> <span id="completeTanggalKembaliRencana"></span></p>
|
||||||
<p style="margin: 5px 0;"><strong>Durasi Rencana:</strong> <span id="completeDurasiRencana"></span> hari</p>
|
<p style="margin: 5px 0;"><strong>Durasi Rencana:</strong> <span id="completeDurasiRencana"></span> hari</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="tanggal_kembali_aktual">
|
<label for="tanggal_kembali_aktual">
|
||||||
<i class="fas fa-calendar-check"></i>
|
<i class="fas fa-calendar-check"></i> Tanggal Kembali Aktual <span style="color: #dc3545;">*</span>
|
||||||
Tanggal Kembali Aktual <span style="color: #dc3545;">*</span>
|
|
||||||
</label>
|
</label>
|
||||||
<input type="date"
|
<input type="date" name="tanggal_kembali_aktual" id="tanggal_kembali_aktual" class="form-control" required>
|
||||||
name="tanggal_kembali_aktual"
|
<small style="color: #7F8C8D; margin-top: 5px; display: block;">Masukkan tanggal santri kembali ke pesantren.</small>
|
||||||
id="tanggal_kembali_aktual"
|
|
||||||
class="form-control"
|
|
||||||
required>
|
|
||||||
<small style="color: #7F8C8D; margin-top: 5px; display: block;">
|
|
||||||
Masukkan tanggal santri kembali ke pesantren. Jika pulang lebih cepat, kuota akan disesuaikan otomatis.
|
|
||||||
</small>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="durasiAktualInfo" style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #007bff; display: none;">
|
<div id="durasiAktualInfo" style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #007bff; display: none;">
|
||||||
<p style="margin: 0;"><strong>Durasi Aktual:</strong> <span id="durasiAktual" style="font-weight: 600; color: #007bff;">-</span> hari</p>
|
<p style="margin: 0;"><strong>Durasi Aktual:</strong> <span id="durasiAktual" style="font-weight: 600; color: #007bff;">-</span> hari</p>
|
||||||
<p style="margin: 5px 0 0 0; font-size: 0.9rem; color: #7F8C8D;" id="selisihInfo"></p>
|
<p style="margin: 5px 0 0 0; font-size: 0.9rem; color: #7F8C8D;" id="selisihInfo"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('completeModal')">Batal</button>
|
<button type="button" class="btn btn-secondary" onclick="closeModal('completeModal')">Batal</button>
|
||||||
<button type="submit" class="btn btn-success">
|
<button type="submit" class="btn btn-success"><i class="fas fa-check"></i> Selesaikan</button>
|
||||||
<i class="fas fa-check"></i> Selesaikan
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -468,26 +392,26 @@ 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.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 { max-width: 500px; width: 90%; margin: auto; }
|
||||||
.modal-content { max-height: 90vh; overflow-y: auto; }
|
.modal-content { max-height: 90vh; overflow-y: auto; }
|
||||||
|
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
|
||||||
@keyframes pulse {
|
|
||||||
0%, 100% { opacity: 1; }
|
|
||||||
50% { opacity: 0.5; }
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
{{-- ✅ FIX: Definisikan semua URL dari Laravel, bukan hardcode di JS --}}
|
||||||
|
<script>
|
||||||
|
const KEPULANGAN_BASE_URL = "{{ url('admin/kepulangan') }}";
|
||||||
|
const CSRF_TOKEN = "{{ csrf_token() }}";
|
||||||
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let currentActionId = null;
|
let currentActionId = null;
|
||||||
|
|
||||||
// Auto submit search dengan debounce
|
// Auto submit search
|
||||||
let searchTimeout;
|
let searchTimeout;
|
||||||
document.getElementById('searchInput')?.addEventListener('input', function() {
|
document.getElementById('searchInput')?.addEventListener('input', function() {
|
||||||
clearTimeout(searchTimeout);
|
clearTimeout(searchTimeout);
|
||||||
searchTimeout = setTimeout(() => {
|
searchTimeout = setTimeout(() => document.getElementById('filterForm').submit(), 500);
|
||||||
document.getElementById('filterForm').submit();
|
|
||||||
}, 500);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Approve
|
// ===== APPROVE =====
|
||||||
function approveKepulangan(id) {
|
function approveKepulangan(id) {
|
||||||
currentActionId = id;
|
currentActionId = id;
|
||||||
document.getElementById('approveModal').style.display = 'flex';
|
document.getElementById('approveModal').style.display = 'flex';
|
||||||
|
|
@ -498,33 +422,25 @@ function approveKepulangan(id) {
|
||||||
const formData = new FormData(this);
|
const formData = new FormData(this);
|
||||||
const submitBtn = this.querySelector('button[type="submit"]');
|
const submitBtn = this.querySelector('button[type="submit"]');
|
||||||
const originalText = submitBtn.innerHTML;
|
const originalText = submitBtn.innerHTML;
|
||||||
|
|
||||||
submitBtn.disabled = true;
|
submitBtn.disabled = true;
|
||||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
||||||
|
|
||||||
fetch(`/admin/kepulangan/${currentActionId}/approve`, {
|
// ✅ FIX: pakai KEPULANGAN_BASE_URL
|
||||||
|
fetch(`${KEPULANGAN_BASE_URL}/${currentActionId}/approve`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' }
|
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) { closeModal('approveModal'); showAlert('success', data.message); setTimeout(() => location.reload(), 1000); }
|
||||||
closeModal('approveModal');
|
else showAlert('danger', data.message);
|
||||||
showAlert('success', data.message);
|
|
||||||
setTimeout(() => window.location.reload(), 1000);
|
|
||||||
} else {
|
|
||||||
showAlert('danger', data.message);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(error => showAlert('danger', 'Error: ' + error.message))
|
.catch(e => showAlert('danger', 'Error: ' + e.message))
|
||||||
.finally(() => {
|
.finally(() => { submitBtn.disabled = false; submitBtn.innerHTML = originalText; });
|
||||||
submitBtn.disabled = false;
|
|
||||||
submitBtn.innerHTML = originalText;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reject
|
// ===== REJECT =====
|
||||||
function rejectKepulangan(id) {
|
function rejectKepulangan(id) {
|
||||||
currentActionId = id;
|
currentActionId = id;
|
||||||
document.getElementById('rejectModal').style.display = 'flex';
|
document.getElementById('rejectModal').style.display = 'flex';
|
||||||
|
|
@ -535,150 +451,92 @@ function rejectKepulangan(id) {
|
||||||
const formData = new FormData(this);
|
const formData = new FormData(this);
|
||||||
const submitBtn = this.querySelector('button[type="submit"]');
|
const submitBtn = this.querySelector('button[type="submit"]');
|
||||||
const originalText = submitBtn.innerHTML;
|
const originalText = submitBtn.innerHTML;
|
||||||
|
|
||||||
submitBtn.disabled = true;
|
submitBtn.disabled = true;
|
||||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
||||||
|
|
||||||
fetch(`/admin/kepulangan/${currentActionId}/reject`, {
|
// ✅ FIX: pakai KEPULANGAN_BASE_URL
|
||||||
|
fetch(`${KEPULANGAN_BASE_URL}/${currentActionId}/reject`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' }
|
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) { closeModal('rejectModal'); showAlert('success', data.message); setTimeout(() => location.reload(), 1000); }
|
||||||
closeModal('rejectModal');
|
else showAlert('danger', data.message);
|
||||||
showAlert('success', data.message);
|
|
||||||
setTimeout(() => window.location.reload(), 1000);
|
|
||||||
} else {
|
|
||||||
showAlert('danger', data.message);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(error => showAlert('danger', 'Error: ' + error.message))
|
.catch(e => showAlert('danger', 'Error: ' + e.message))
|
||||||
.finally(() => {
|
.finally(() => { submitBtn.disabled = false; submitBtn.innerHTML = originalText; });
|
||||||
submitBtn.disabled = false;
|
|
||||||
submitBtn.innerHTML = originalText;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Complete (Selesaikan Kepulangan)
|
// ===== COMPLETE =====
|
||||||
let currentCompleteData = {};
|
let currentCompleteData = {};
|
||||||
|
|
||||||
function completeKepulangan(id, namaSantri, tanggalPulang, tanggalKembaliRencana, durasiRencana) {
|
function completeKepulangan(id, namaSantri, tanggalPulang, tanggalKembaliRencana, durasiRencana) {
|
||||||
currentCompleteData = {
|
currentCompleteData = { id, namaSantri, tanggalPulang, tanggalKembaliRencana, durasiRencana };
|
||||||
id: id,
|
|
||||||
namaSantri: namaSantri,
|
|
||||||
tanggalPulang: tanggalPulang,
|
|
||||||
tanggalKembaliRencana: tanggalKembaliRencana,
|
|
||||||
durasiRencana: durasiRencana
|
|
||||||
};
|
|
||||||
|
|
||||||
// Populate modal
|
|
||||||
document.getElementById('completeIdKepulangan').textContent = id;
|
document.getElementById('completeIdKepulangan').textContent = id;
|
||||||
document.getElementById('completeNamaSantri').textContent = namaSantri;
|
document.getElementById('completeNamaSantri').textContent = namaSantri;
|
||||||
document.getElementById('completeTanggalPulang').textContent = formatTanggal(tanggalPulang);
|
document.getElementById('completeTanggalPulang').textContent = formatTanggal(tanggalPulang);
|
||||||
document.getElementById('completeTanggalKembaliRencana').textContent = formatTanggal(tanggalKembaliRencana);
|
document.getElementById('completeTanggalKembaliRencana').textContent = formatTanggal(tanggalKembaliRencana);
|
||||||
document.getElementById('completeDurasiRencana').textContent = durasiRencana;
|
document.getElementById('completeDurasiRencana').textContent = durasiRencana;
|
||||||
|
|
||||||
// Set default tanggal kembali aktual = hari ini
|
|
||||||
const today = new Date().toISOString().split('T')[0];
|
const today = new Date().toISOString().split('T')[0];
|
||||||
document.getElementById('tanggal_kembali_aktual').value = today;
|
document.getElementById('tanggal_kembali_aktual').value = today;
|
||||||
document.getElementById('tanggal_kembali_aktual').min = tanggalPulang;
|
document.getElementById('tanggal_kembali_aktual').min = tanggalPulang;
|
||||||
|
|
||||||
// Hitung durasi aktual
|
|
||||||
calculateDurasiAktual();
|
calculateDurasiAktual();
|
||||||
|
|
||||||
// Show modal
|
|
||||||
document.getElementById('completeModal').style.display = 'flex';
|
document.getElementById('completeModal').style.display = 'flex';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate durasi aktual
|
|
||||||
function calculateDurasiAktual() {
|
function calculateDurasiAktual() {
|
||||||
const tanggalPulang = currentCompleteData.tanggalPulang;
|
|
||||||
const tanggalKembaliAktual = document.getElementById('tanggal_kembali_aktual').value;
|
const tanggalKembaliAktual = document.getElementById('tanggal_kembali_aktual').value;
|
||||||
|
if (!tanggalKembaliAktual || !currentCompleteData.tanggalPulang) return;
|
||||||
if (!tanggalKembaliAktual) return;
|
const startDate = new Date(currentCompleteData.tanggalPulang);
|
||||||
|
|
||||||
const startDate = new Date(tanggalPulang);
|
|
||||||
const endDate = new Date(tanggalKembaliAktual);
|
const endDate = new Date(tanggalKembaliAktual);
|
||||||
|
if (endDate < startDate) { document.getElementById('durasiAktualInfo').style.display = 'none'; return; }
|
||||||
if (endDate < startDate) {
|
const durasiAktual = Math.ceil(Math.abs(endDate - startDate) / (1000 * 60 * 60 * 24)) + 1;
|
||||||
document.getElementById('durasiAktualInfo').style.display = 'none';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const diffTime = Math.abs(endDate - startDate);
|
|
||||||
const durasiAktual = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1;
|
|
||||||
const durasiRencana = currentCompleteData.durasiRencana;
|
const durasiRencana = currentCompleteData.durasiRencana;
|
||||||
|
|
||||||
document.getElementById('durasiAktual').textContent = durasiAktual;
|
document.getElementById('durasiAktual').textContent = durasiAktual;
|
||||||
document.getElementById('durasiAktualInfo').style.display = 'block';
|
document.getElementById('durasiAktualInfo').style.display = 'block';
|
||||||
|
let selisihText = '', selisihColor = '#007bff';
|
||||||
// Show selisih
|
|
||||||
let selisihText = '';
|
|
||||||
let selisihColor = '#007bff';
|
|
||||||
|
|
||||||
if (durasiAktual < durasiRencana) {
|
if (durasiAktual < durasiRencana) {
|
||||||
const selisih = durasiRencana - durasiAktual;
|
selisihText = `Santri pulang ${durasiRencana - durasiAktual} hari lebih cepat. Kuota akan berkurang ${durasiAktual} hari.`;
|
||||||
selisihText = `✅ Santri pulang ${selisih} hari lebih cepat dari rencana. Kuota akan berkurang ${durasiAktual} hari.`;
|
|
||||||
selisihColor = '#28a745';
|
selisihColor = '#28a745';
|
||||||
} else if (durasiAktual > durasiRencana) {
|
} else if (durasiAktual > durasiRencana) {
|
||||||
const selisih = durasiAktual - durasiRencana;
|
selisihText = `Santri pulang ${durasiAktual - durasiRencana} hari lebih lambat. Kuota akan bertambah.`;
|
||||||
selisihText = `⚠︠Santri pulang ${selisih} hari lebih lambat dari rencana. Kuota akan bertambah ${selisih} hari.`;
|
|
||||||
selisihColor = '#ffc107';
|
selisihColor = '#ffc107';
|
||||||
} else {
|
} else {
|
||||||
selisihText = `✓ Sesuai rencana (${durasiAktual} hari).`;
|
selisihText = `Sesuai rencana (${durasiAktual} hari).`;
|
||||||
selisihColor = '#007bff';
|
|
||||||
}
|
}
|
||||||
|
document.getElementById('selisihInfo').textContent = selisihText;
|
||||||
const selisihInfo = document.getElementById('selisihInfo');
|
document.getElementById('selisihInfo').style.color = selisihColor;
|
||||||
selisihInfo.textContent = selisihText;
|
|
||||||
selisihInfo.style.color = selisihColor;
|
|
||||||
document.getElementById('durasiAktual').style.color = selisihColor;
|
document.getElementById('durasiAktual').style.color = selisihColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event listener untuk tanggal kembali aktual
|
|
||||||
document.getElementById('tanggal_kembali_aktual')?.addEventListener('change', calculateDurasiAktual);
|
document.getElementById('tanggal_kembali_aktual')?.addEventListener('change', calculateDurasiAktual);
|
||||||
|
|
||||||
// Submit form complete
|
|
||||||
document.getElementById('completeForm')?.addEventListener('submit', function(e) {
|
document.getElementById('completeForm')?.addEventListener('submit', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const formData = new FormData(this);
|
const formData = new FormData(this);
|
||||||
const submitBtn = this.querySelector('button[type="submit"]');
|
const submitBtn = this.querySelector('button[type="submit"]');
|
||||||
const originalText = submitBtn.innerHTML;
|
const originalText = submitBtn.innerHTML;
|
||||||
|
|
||||||
submitBtn.disabled = true;
|
submitBtn.disabled = true;
|
||||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
||||||
|
|
||||||
fetch(`/admin/kepulangan/${currentCompleteData.id}/complete`, {
|
// ✅ FIX: pakai KEPULANGAN_BASE_URL
|
||||||
|
fetch(`${KEPULANGAN_BASE_URL}/${currentCompleteData.id}/complete`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' }
|
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) { closeModal('completeModal'); showAlert('success', data.message); setTimeout(() => location.reload(), 1500); }
|
||||||
closeModal('completeModal');
|
else showAlert('danger', data.message);
|
||||||
showAlert('success', data.message);
|
|
||||||
setTimeout(() => window.location.reload(), 1500);
|
|
||||||
} else {
|
|
||||||
showAlert('danger', data.message);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(error => showAlert('danger', 'Error: ' + error.message))
|
.catch(e => showAlert('danger', 'Error: ' + e.message))
|
||||||
.finally(() => {
|
.finally(() => { submitBtn.disabled = false; submitBtn.innerHTML = originalText; });
|
||||||
submitBtn.disabled = false;
|
|
||||||
submitBtn.innerHTML = originalText;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Helper: Format tanggal
|
// ===== DELETE =====
|
||||||
function formatTanggal(dateString) {
|
|
||||||
const options = { year: 'numeric', month: 'long', day: 'numeric' };
|
|
||||||
return new Date(dateString).toLocaleDateString('id-ID', options);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete
|
|
||||||
function deleteKepulangan(id) {
|
function deleteKepulangan(id) {
|
||||||
currentActionId = id;
|
currentActionId = id;
|
||||||
document.getElementById('deleteModal').style.display = 'flex';
|
document.getElementById('deleteModal').style.display = 'flex';
|
||||||
|
|
@ -687,61 +545,39 @@ function deleteKepulangan(id) {
|
||||||
document.getElementById('confirmDeleteBtn').addEventListener('click', function() {
|
document.getElementById('confirmDeleteBtn').addEventListener('click', function() {
|
||||||
const btn = this;
|
const btn = this;
|
||||||
const originalText = btn.innerHTML;
|
const originalText = btn.innerHTML;
|
||||||
|
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Menghapus...';
|
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Menghapus...';
|
||||||
|
|
||||||
fetch(`/admin/kepulangan/${currentActionId}`, {
|
// ✅ FIX: pakai KEPULANGAN_BASE_URL
|
||||||
|
fetch(`${KEPULANGAN_BASE_URL}/${currentActionId}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' }
|
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) { closeModal('deleteModal'); showAlert('success', data.message); setTimeout(() => location.reload(), 1000); }
|
||||||
closeModal('deleteModal');
|
else showAlert('danger', data.message);
|
||||||
showAlert('success', data.message);
|
|
||||||
setTimeout(() => window.location.reload(), 1000);
|
|
||||||
} else {
|
|
||||||
showAlert('danger', data.message);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(error => showAlert('danger', 'Error: ' + error.message))
|
.catch(e => showAlert('danger', 'Error: ' + e.message))
|
||||||
.finally(() => {
|
.finally(() => { btn.disabled = false; btn.innerHTML = originalText; });
|
||||||
btn.disabled = false;
|
|
||||||
btn.innerHTML = originalText;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Helper functions
|
// ===== HELPERS =====
|
||||||
function closeModal(modalId) {
|
function formatTanggal(dateString) {
|
||||||
document.getElementById(modalId).style.display = 'none';
|
return new Date(dateString).toLocaleDateString('id-ID', { year: 'numeric', month: 'long', day: 'numeric' });
|
||||||
}
|
}
|
||||||
|
function closeModal(modalId) { document.getElementById(modalId).style.display = 'none'; }
|
||||||
function showAlert(type, message) {
|
function showAlert(type, message) {
|
||||||
const alertDiv = document.createElement('div');
|
const alertDiv = document.createElement('div');
|
||||||
alertDiv.className = `alert alert-${type}`;
|
alertDiv.className = `alert alert-${type}`;
|
||||||
alertDiv.innerHTML = `<i class="fas fa-${type === 'success' ? 'check' : 'exclamation'}-circle"></i> ${message}`;
|
alertDiv.innerHTML = `<i class="fas fa-${type === 'success' ? 'check' : 'exclamation'}-circle"></i> ${message}`;
|
||||||
|
document.querySelector('.page-header').insertAdjacentElement('afterend', alertDiv);
|
||||||
const pageHeader = document.querySelector('.page-header');
|
|
||||||
pageHeader.insertAdjacentElement('afterend', alertDiv);
|
|
||||||
|
|
||||||
setTimeout(() => alertDiv.remove(), 5000);
|
setTimeout(() => alertDiv.remove(), 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close modals on ESC
|
document.addEventListener('keydown', e => { if (e.key === 'Escape') document.querySelectorAll('.modal.fade').forEach(m => m.style.display = 'none'); });
|
||||||
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 => {
|
document.querySelectorAll('.modal.fade').forEach(modal => {
|
||||||
modal.addEventListener('click', function(e) {
|
modal.addEventListener('click', function(e) { if (e.target === this) this.style.display = 'none'; });
|
||||||
if (e.target === this) {
|
|
||||||
this.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
@ -13,17 +13,17 @@
|
||||||
<div style="background: linear-gradient(135deg, #ff5252 0%, #f48fb1 100%); color: white; padding: 14px; border-radius: 12px; margin-bottom: 14px;">
|
<div style="background: linear-gradient(135deg, #ff5252 0%, #f48fb1 100%); color: white; padding: 14px; border-radius: 12px; margin-bottom: 14px;">
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 20px; align-items: center;">
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 20px; align-items: center;">
|
||||||
<div>
|
<div>
|
||||||
<h4 style="margin: 0 0 5px 0; opacity: 0.9;">⚠︠Total Santri Over Limit</h4>
|
<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>
|
<p style="margin: 0; font-size: 2rem; font-weight: 700;">{{ $santriList->count() }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4 style="margin: 0 0 5px 0; opacity: 0.9;">📅 Periode Kuota</h4>
|
<h4 style="margin: 0 0 5px 0; opacity: 0.9;">Periode Kuota</h4>
|
||||||
<p style="margin: 0; font-size: 1.1rem; font-weight: 600;">
|
<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') }}
|
{{ $settings->periode_mulai->format('d M Y') }} - {{ $settings->periode_akhir->format('d M Y') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4 style="margin: 0 0 5px 0; opacity: 0.9;">📊Kuota Maksimal</h4>
|
<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>
|
<p style="margin: 0; font-size: 1.1rem; font-weight: 600;">{{ $settings->kuota_maksimal }} Hari / Tahun</p>
|
||||||
</div>
|
</div>
|
||||||
<div style="text-align: right;">
|
<div style="text-align: right;">
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
{{-- Alert Info --}}
|
{{-- Alert Info --}}
|
||||||
<div style="background: #fff3cd; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #ffc107;">
|
<div style="background: #fff3cd; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #ffc107;">
|
||||||
<strong>ℹ︠Informasi:</strong>
|
<strong>Informasi:</strong>
|
||||||
<p style="margin: 10px 0 0 0;">
|
<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.
|
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.
|
Santri tetap bisa mengajukan izin, namun akan mendapat peringatan visual.
|
||||||
|
|
@ -131,7 +131,7 @@ class="btn btn-sm btn-warning"
|
||||||
|
|
||||||
{{-- Summary Statistics --}}
|
{{-- Summary Statistics --}}
|
||||||
<div style="margin-top: 22px; padding: 14px; background: #f8f9fa; border-radius: 8px;">
|
<div style="margin-top: 22px; padding: 14px; background: #f8f9fa; border-radius: 8px;">
|
||||||
<h4 style="margin: 0 0 15px 0; color: #2C3E50;">📊Ringkasan Statistik</h4>
|
<h4 style="margin: 0 0 15px 0; color: #2C3E50;">Ringkasan Statistik</h4>
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 20px;">
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 20px;">
|
||||||
<div style="text-align: center; padding: 15px; background: white; border-radius: 8px; border: 2px solid #dc3545;">
|
<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: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Total Santri Over Limit</div>
|
||||||
|
|
|
||||||
|
|
@ -164,15 +164,16 @@ class="form-control"
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<div style="display: flex; gap: 5px; justify-content: center; flex-wrap: wrap;">
|
<div style="display: flex; gap: 5px; justify-content: center; flex-wrap: wrap;">
|
||||||
@if($item->status == 'Menunggu')
|
@if($item->status == 'Menunggu')
|
||||||
|
{{-- ✅ FIX: kirim URL dari route() helper sebagai parameter --}}
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="btn btn-sm btn-success"
|
class="btn btn-sm btn-success"
|
||||||
onclick="approvePengajuan({{ $item->id }})"
|
onclick="approvePengajuan({{ $item->id }}, '{{ route('admin.kepulangan.pengajuan.approve', $item->id) }}')"
|
||||||
title="Setujui">
|
title="Setujui">
|
||||||
<i class="fas fa-check"></i> Setujui
|
<i class="fas fa-check"></i> Setujui
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="btn btn-sm btn-danger"
|
class="btn btn-sm btn-danger"
|
||||||
onclick="rejectPengajuan({{ $item->id }})"
|
onclick="rejectPengajuan({{ $item->id }}, '{{ route('admin.kepulangan.pengajuan.reject', $item->id) }}')"
|
||||||
title="Tolak">
|
title="Tolak">
|
||||||
<i class="fas fa-times"></i> Tolak
|
<i class="fas fa-times"></i> Tolak
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -296,12 +297,19 @@ class="btn btn-sm btn-danger"
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
{{-- ✅ FIX: CSRF token tersimpan di variabel JS, bukan di dalam fetch --}}
|
||||||
<script>
|
<script>
|
||||||
let currentPengajuanId = null;
|
const CSRF_TOKEN = "{{ csrf_token() }}";
|
||||||
|
</script>
|
||||||
|
|
||||||
// Approve
|
<script>
|
||||||
function approvePengajuan(id) {
|
let currentApproveUrl = null;
|
||||||
currentPengajuanId = id;
|
let currentRejectUrl = null;
|
||||||
|
|
||||||
|
// ===== APPROVE =====
|
||||||
|
// ✅ FIX: terima routeUrl dari blade, simpan di variabel, pakai saat submit
|
||||||
|
function approvePengajuan(id, routeUrl) {
|
||||||
|
currentApproveUrl = routeUrl;
|
||||||
document.getElementById('approveModal').style.display = 'flex';
|
document.getElementById('approveModal').style.display = 'flex';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,12 +322,20 @@ function approvePengajuan(id) {
|
||||||
submitBtn.disabled = true;
|
submitBtn.disabled = true;
|
||||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
||||||
|
|
||||||
fetch(`/admin/kepulangan/pengajuan/${currentPengajuanId}/approve`, {
|
// ✅ FIX: pakai currentApproveUrl yang sudah di-set dari route() blade
|
||||||
|
fetch(currentApproveUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' }
|
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
// ✅ FIX: cek content-type sebelum parse JSON agar error HTML tidak merusak
|
||||||
|
const contentType = response.headers.get('content-type');
|
||||||
|
if (!contentType || !contentType.includes('application/json')) {
|
||||||
|
throw new Error('Response bukan JSON. Kemungkinan terjadi error server (500/404).');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
closeModal('approveModal');
|
closeModal('approveModal');
|
||||||
|
|
@ -336,9 +352,10 @@ function approvePengajuan(id) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reject
|
// ===== REJECT =====
|
||||||
function rejectPengajuan(id) {
|
// ✅ FIX: terima routeUrl dari blade, simpan di variabel, pakai saat submit
|
||||||
currentPengajuanId = id;
|
function rejectPengajuan(id, routeUrl) {
|
||||||
|
currentRejectUrl = routeUrl;
|
||||||
document.getElementById('rejectModal').style.display = 'flex';
|
document.getElementById('rejectModal').style.display = 'flex';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -351,12 +368,20 @@ function rejectPengajuan(id) {
|
||||||
submitBtn.disabled = true;
|
submitBtn.disabled = true;
|
||||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
||||||
|
|
||||||
fetch(`/admin/kepulangan/pengajuan/${currentPengajuanId}/reject`, {
|
// ✅ FIX: pakai currentRejectUrl yang sudah di-set dari route() blade
|
||||||
|
fetch(currentRejectUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' }
|
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
// ✅ FIX: cek content-type sebelum parse JSON
|
||||||
|
const contentType = response.headers.get('content-type');
|
||||||
|
if (!contentType || !contentType.includes('application/json')) {
|
||||||
|
throw new Error('Response bukan JSON. Kemungkinan terjadi error server (500/404).');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
closeModal('rejectModal');
|
closeModal('rejectModal');
|
||||||
|
|
@ -373,7 +398,7 @@ function rejectPengajuan(id) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Helper functions
|
// ===== HELPERS =====
|
||||||
function closeModal(modalId) {
|
function closeModal(modalId) {
|
||||||
document.getElementById(modalId).style.display = 'none';
|
document.getElementById(modalId).style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,19 +67,19 @@
|
||||||
<td>
|
<td>
|
||||||
@if($kepulangan->is_aktif)
|
@if($kepulangan->is_aktif)
|
||||||
<span style="display: inline-block; background: #28a745; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;">
|
<span style="display: inline-block; background: #28a745; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;">
|
||||||
ðŸÂ Sedang Izin
|
Sedang Izin
|
||||||
</span>
|
</span>
|
||||||
@elseif($kepulangan->is_terlambat)
|
@elseif($kepulangan->is_terlambat)
|
||||||
<span style="display: inline-block; background: #dc3545; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;">
|
<span style="display: inline-block; background: #dc3545; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;">
|
||||||
â° Terlambat Kembali
|
Terlambat Kembali
|
||||||
</span>
|
</span>
|
||||||
@elseif($kepulangan->status == 'Selesai')
|
@elseif($kepulangan->status == 'Selesai')
|
||||||
<span style="display: inline-block; background: #6c757d; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;">
|
<span style="display: inline-block; background: #6c757d; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;">
|
||||||
✅ Sudah Selesai
|
Sudah Selesai
|
||||||
</span>
|
</span>
|
||||||
@else
|
@else
|
||||||
<span style="display: inline-block; background: #81C6E8; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;">
|
<span style="display: inline-block; background: #81C6E8; color: white; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;">
|
||||||
📅 Belum Dimulai
|
Belum Dimulai
|
||||||
</span>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
|
|
|
||||||
|
|
@ -243,10 +243,16 @@ class="btn btn-danger btn-sm"
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- ✅ FIX: Simpan base URL dari Laravel agar tidak hardcode di JS --}}
|
||||||
|
<script>
|
||||||
|
const BASE_URL = "{{ url('admin/kesehatan-santri') }}";
|
||||||
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function keluarUkp(id, namaSantri, tanggalMasuk) {
|
function keluarUkp(id, namaSantri, tanggalMasuk) {
|
||||||
document.getElementById('modalNamaSantri').value = namaSantri;
|
document.getElementById('modalNamaSantri').value = namaSantri;
|
||||||
document.getElementById('keluarUkpForm').action = `/admin/kesehatan-santri/${id}/keluar-ukp`;
|
// ✅ FIX: Gunakan BASE_URL dari Laravel, bukan hardcode path
|
||||||
|
document.getElementById('keluarUkpForm').action = BASE_URL + '/' + id + '/keluar-ukp';
|
||||||
document.getElementById('tanggal_keluar').value = new Date().toISOString().split('T')[0];
|
document.getElementById('tanggal_keluar').value = new Date().toISOString().split('T')[0];
|
||||||
document.getElementById('tanggal_keluar').min = tanggalMasuk;
|
document.getElementById('tanggal_keluar').min = tanggalMasuk;
|
||||||
document.getElementById('tanggal_keluar').max = new Date().toISOString().split('T')[0];
|
document.getElementById('tanggal_keluar').max = new Date().toISOString().split('T')[0];
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="opacity: 0.95;">
|
<div style="opacity: 0.95;">
|
||||||
<strong>Status:</strong> {{ $santri->status_badge }}<br>
|
<strong>Status:</strong> {!! $santri->status_badge !!}<br>
|
||||||
<strong>NIS:</strong> {{ $santri->nis ?: '-' }}
|
<strong>NIS:</strong> {{ $santri->nis ?: '-' }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -269,7 +269,7 @@ class="btn btn-success"
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Action Buttons (Fixed at Bottom) -->
|
<!-- Action Buttons -->
|
||||||
<div class="content-box" style="background: linear-gradient(135deg, #F8FBF9 0%, #E8F7F2 100%); border-top: 3px solid var(--primary-color);">
|
<div class="content-box" style="background: linear-gradient(135deg, #F8FBF9 0%, #E8F7F2 100%); border-top: 3px solid var(--primary-color);">
|
||||||
<h4 style="color: var(--primary-color); margin-bottom: 15px;">
|
<h4 style="color: var(--primary-color); margin-bottom: 15px;">
|
||||||
<i class="fas fa-tools"></i> Aksi Tersedia
|
<i class="fas fa-tools"></i> Aksi Tersedia
|
||||||
|
|
@ -289,7 +289,7 @@ class="btn btn-primary">
|
||||||
<form action="{{ route('admin.kesehatan-santri.destroy', $kesehatanSantri) }}"
|
<form action="{{ route('admin.kesehatan-santri.destroy', $kesehatanSantri) }}"
|
||||||
method="POST"
|
method="POST"
|
||||||
style="display: inline;"
|
style="display: inline;"
|
||||||
onsubmit="return confirm('⚠︠Yakin ingin menghapus data kesehatan ini?\n\nData yang dihapus tidak dapat dikembalikan!')">
|
onsubmit="return confirm('Yakin ingin menghapus data kesehatan ini?\n\nData yang dihapus tidak dapat dikembalikan!')">
|
||||||
@csrf
|
@csrf
|
||||||
@method('DELETE')
|
@method('DELETE')
|
||||||
<button type="submit" class="btn btn-danger">
|
<button type="submit" class="btn btn-danger">
|
||||||
|
|
@ -312,7 +312,6 @@ class="btn btn-primary">
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="table-wrapper">
|
<div class="table-wrapper">
|
||||||
|
|
||||||
<table class="data-table">
|
<table class="data-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -362,7 +361,6 @@ class="btn btn-primary btn-sm">
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="text-align: center; margin-top: 14px;">
|
<div style="text-align: center; margin-top: 14px;">
|
||||||
|
|
@ -424,43 +422,28 @@ class="btn btn-primary">
|
||||||
from { opacity: 0; }
|
from { opacity: 0; }
|
||||||
to { opacity: 1; }
|
to { opacity: 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes slideDown {
|
@keyframes slideDown {
|
||||||
from {
|
from { opacity: 0; transform: translate(-50%, -60%); }
|
||||||
opacity: 0;
|
to { opacity: 1; transform: translate(-50%, -50%); }
|
||||||
transform: translate(-50%, -60%);
|
|
||||||
}
|
}
|
||||||
to {
|
.info-item { transition: all 0.3s ease; }
|
||||||
opacity: 1;
|
.info-item:hover { transform: translateX(5px); }
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-item {
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-item:hover {
|
|
||||||
transform: translateX(5px);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive adjustments */
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
#keluarUkpModal > div {
|
#keluarUkpModal > div { min-width: 90%; padding: 14px; }
|
||||||
min-width: 90%;
|
.page-header h2 { font-size: 1.3rem; }
|
||||||
padding: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-header h2 {
|
|
||||||
font-size: 1.3rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
{{-- ✅ FIX: Simpan base URL dari Laravel agar tidak hardcode di JS --}}
|
||||||
|
<script>
|
||||||
|
const BASE_URL = "{{ url('admin/kesehatan-santri') }}";
|
||||||
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function keluarUkp(id, namaSantri, tanggalMasuk) {
|
function keluarUkp(id, namaSantri, tanggalMasuk) {
|
||||||
document.getElementById('modalNamaSantri').value = namaSantri;
|
document.getElementById('modalNamaSantri').value = namaSantri;
|
||||||
document.getElementById('keluarUkpForm').action = `/admin/kesehatan-santri/${id}/keluar-ukp`;
|
// ✅ FIX: Gunakan BASE_URL dari Laravel, bukan hardcode path
|
||||||
|
document.getElementById('keluarUkpForm').action = BASE_URL + '/' + id + '/keluar-ukp';
|
||||||
document.getElementById('tanggal_keluar').value = new Date().toISOString().split('T')[0];
|
document.getElementById('tanggal_keluar').value = new Date().toISOString().split('T')[0];
|
||||||
document.getElementById('tanggal_keluar').min = tanggalMasuk;
|
document.getElementById('tanggal_keluar').min = tanggalMasuk;
|
||||||
document.getElementById('tanggal_keluar').max = new Date().toISOString().split('T')[0];
|
document.getElementById('tanggal_keluar').max = new Date().toISOString().split('T')[0];
|
||||||
|
|
@ -471,18 +454,12 @@ function closeKeluarUkpModal() {
|
||||||
document.getElementById('keluarUkpModal').style.display = 'none';
|
document.getElementById('keluarUkpModal').style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close modal when clicking outside
|
|
||||||
document.getElementById('keluarUkpModal').addEventListener('click', function(e) {
|
document.getElementById('keluarUkpModal').addEventListener('click', function(e) {
|
||||||
if (e.target === this) {
|
if (e.target === this) closeKeluarUkpModal();
|
||||||
closeKeluarUkpModal();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Close modal with Escape key
|
|
||||||
document.addEventListener('keydown', function(e) {
|
document.addEventListener('keydown', function(e) {
|
||||||
if (e.key === 'Escape') {
|
if (e.key === 'Escape') closeKeluarUkpModal();
|
||||||
closeKeluarUkpModal();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,18 @@
|
||||||
'Sakit' => ['bg'=>'#E0F2FE','c'=>'#0C4A6E','ic'=>'🏥'],
|
'Sakit' => ['bg'=>'#E0F2FE','c'=>'#0C4A6E','ic'=>'🏥'],
|
||||||
];
|
];
|
||||||
|
|
||||||
// ── 1. Kolom kegiatan: UNIK, diurutkan waktu_mulai ───────────────────────────
|
// ── 1. Kelompokkan data per tanggal → per santri ─────────────────────────────
|
||||||
$kegiatanCols = collect($hasilEnriched)
|
$byTanggal = [];
|
||||||
|
foreach ($hasilEnriched as $h) {
|
||||||
|
$tgl = $h['tanggal'];
|
||||||
|
$byTanggal[$tgl][] = $h;
|
||||||
|
}
|
||||||
|
ksort($byTanggal);
|
||||||
|
|
||||||
|
// ── 2. Buat kolom kegiatan UNIK per tanggal, diurutkan waktu_mulai ───────────
|
||||||
|
$kegiatanByTanggal = [];
|
||||||
|
foreach ($byTanggal as $tgl => $santriList) {
|
||||||
|
$cols = collect($santriList)
|
||||||
->flatMap(fn($h) => $h['rows'])
|
->flatMap(fn($h) => $h['rows'])
|
||||||
->unique('kegiatan_id')
|
->unique('kegiatan_id')
|
||||||
->sortBy('waktu_mulai')
|
->sortBy('waktu_mulai')
|
||||||
|
|
@ -25,37 +35,21 @@
|
||||||
'nama' => $r['nama_kegiatan'],
|
'nama' => $r['nama_kegiatan'],
|
||||||
'waktu_mulai' => $r['waktu_mulai'],
|
'waktu_mulai' => $r['waktu_mulai'],
|
||||||
]);
|
]);
|
||||||
|
$kegiatanByTanggal[$tgl] = $cols;
|
||||||
// ── 2. Susun data: [tanggal][id_santri_or_mesin] = data ──────────────────────
|
|
||||||
$byTanggalSantri = [];
|
|
||||||
$santriList = []; // untuk urutan santri konsisten
|
|
||||||
|
|
||||||
foreach ($hasilEnriched as $h) {
|
|
||||||
$tgl = $h['tanggal'];
|
|
||||||
$key = $h['id_santri'] ?? ('__'.$h['id_mesin']);
|
|
||||||
$byTanggalSantri[$tgl][$key] = $h;
|
|
||||||
|
|
||||||
if (!isset($santriList[$key])) {
|
|
||||||
$santriList[$key] = [
|
|
||||||
'nama' => $h['nama_web'] ?? $h['nama_mesin'],
|
|
||||||
'kelas' => $h['kelas'] ?? '-',
|
|
||||||
'status' => $h['match_status'],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ksort($byTanggalSantri);
|
|
||||||
|
|
||||||
// ── 3. Statistik ─────────────────────────────────────────────────────────────
|
// ── 3. Statistik global ──────────────────────────────────────────────────────
|
||||||
$allRows = collect($hasilEnriched)->flatMap(fn($h) => $h['rows']);
|
$allRows = collect($hasilEnriched)->flatMap(fn($h) => $h['rows']);
|
||||||
$totalKonflik = $allRows->where('is_conflict', true)->count();
|
$totalKonflik = $allRows->where('is_conflict', true)->count();
|
||||||
$hadir = $allRows->where('status_final','Hadir')->count();
|
$hadirTotal = $allRows->where('status_final','Hadir')->count();
|
||||||
$terlambat = $allRows->where('status_final','Terlambat')->count();
|
$terlambatTotal = $allRows->where('status_final','Terlambat')->count();
|
||||||
$alpa = $allRows->where('status_final','Alpa')->count();
|
$alpaTotal = $allRows->where('status_final','Alpa')->count();
|
||||||
$notMapped = collect($hasilEnriched)->where('match_status','NOT_MAPPED')->count();
|
$notMapped = collect($hasilEnriched)->where('match_status','NOT_MAPPED')->count();
|
||||||
|
$totalSantri = collect($hasilEnriched)->unique(fn($h) => $h['id_santri'] ?? $h['id_mesin'])->count();
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* Sticky top bar */
|
/* ── Top sticky bar ───────────────────────────────── */
|
||||||
.top-bar {
|
.top-bar {
|
||||||
position: sticky; top: 0; z-index: 50;
|
position: sticky; top: 0; z-index: 50;
|
||||||
background: #0F172A; color: #F1F5F9;
|
background: #0F172A; color: #F1F5F9;
|
||||||
|
|
@ -80,41 +74,61 @@
|
||||||
color: #fff; white-space: nowrap; transition: background .2s;
|
color: #fff; white-space: nowrap; transition: background .2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Matrix table */
|
/* ── Per-day block ────────────────────────────────── */
|
||||||
.wrap { overflow-x: auto }
|
.day-block {
|
||||||
.mx { border-collapse: collapse; font-size: 12px; width: 100% }
|
margin: 14px 14px 0;
|
||||||
.mx th, .mx td {
|
border-radius: 12px;
|
||||||
border: 1px solid #E5E7EB; padding: 0;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
box-shadow: 0 2px 10px rgba(0,0,0,.08);
|
||||||
|
border: 1px solid #E5E7EB;
|
||||||
}
|
}
|
||||||
/* Sticky kolom tanggal + nama */
|
.day-block:last-child { margin-bottom: 14px; }
|
||||||
.col-tgl {
|
|
||||||
position: sticky; left: 0; z-index: 4;
|
.day-header {
|
||||||
background: #F8FAFC; min-width: 90px;
|
background: #1E293B;
|
||||||
border-right: 2px solid #CBD5E1;
|
color: #F1F5F9;
|
||||||
padding: 6px 10px; font-size: 11px;
|
padding: 10px 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
.col-nama {
|
.day-header .hari-nama {
|
||||||
position: sticky; left: 90px; z-index: 4;
|
font-size: 10px; color: #64748B;
|
||||||
background: #F8FAFC; min-width: 130px;
|
text-transform: uppercase; letter-spacing: 1px;
|
||||||
border-right: 2px solid #CBD5E1;
|
|
||||||
padding: 6px 10px;
|
|
||||||
}
|
}
|
||||||
/* Header kegiatan (rotate) */
|
.day-header .tgl-label {
|
||||||
.th-wrap {
|
font-weight: 700; font-size: 16px; margin-top: 1px;
|
||||||
writing-mode: vertical-rl;
|
|
||||||
transform: rotate(180deg);
|
|
||||||
display: flex; align-items: center; justify-content: flex-end;
|
|
||||||
gap: 2px; height: 80px; padding: 5px 6px;
|
|
||||||
}
|
}
|
||||||
/* Status pill */
|
.day-badge {
|
||||||
|
border-radius: 6px; padding: 3px 10px;
|
||||||
|
font-size: 11px; font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Tabel per hari ───────────────────────────────── */
|
||||||
|
.tbl-day { border-collapse: collapse; font-size: 12px; width: 100% }
|
||||||
|
.tbl-day th, .tbl-day td {
|
||||||
|
border: 1px solid #E5E7EB;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.th-no { width: 36px; text-align: center; padding: 8px 4px !important; }
|
||||||
|
.th-nama { min-width: 150px; padding: 8px 10px !important; text-align: left; }
|
||||||
|
.th-kelas { min-width: 80px; padding: 8px 10px !important; text-align: left; }
|
||||||
|
.th-keg { min-width: 90px; vertical-align: bottom; }
|
||||||
|
.th-keg-inner {
|
||||||
|
padding: 6px 8px 6px;
|
||||||
|
display: flex; flex-direction: column; align-items: center;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Status pill ──────────────────────────────────── */
|
||||||
.pill {
|
.pill {
|
||||||
display: inline-block; border-radius: 8px;
|
display: inline-block; border-radius: 8px;
|
||||||
padding: 2px 6px; font-size: 10px; font-weight: 700;
|
padding: 2px 7px; font-size: 10px; font-weight: 700;
|
||||||
}
|
}
|
||||||
/* Konflik cell */
|
|
||||||
.conf-cell { background: #FFF5F5 !important; border: 2px solid #FCA5A5 !important }
|
/* ── Konflik cell ─────────────────────────────────── */
|
||||||
.conf-wrap { display: flex; flex-direction: column }
|
.conf-wrap { display: flex; flex-direction: column; }
|
||||||
.conf-opt {
|
.conf-opt {
|
||||||
padding: 4px 8px; cursor: pointer;
|
padding: 4px 8px; cursor: pointer;
|
||||||
font-size: 11px; display: flex; align-items: center; gap: 4px;
|
font-size: 11px; display: flex; align-items: center; gap: 4px;
|
||||||
|
|
@ -124,27 +138,12 @@
|
||||||
.conf-opt:hover { background: #F8FAFC }
|
.conf-opt:hover { background: #F8FAFC }
|
||||||
.sel-m { background: #DCFCE7 !important }
|
.sel-m { background: #DCFCE7 !important }
|
||||||
.sel-e { background: #DBEAFE !important }
|
.sel-e { background: #DBEAFE !important }
|
||||||
/* Date separator row */
|
|
||||||
.date-sep td {
|
|
||||||
background: #1E293B; color: #94A3B8; font-weight: 700;
|
|
||||||
font-size: 11px; padding: 5px 12px; border-bottom: 2px solid #334155;
|
|
||||||
}
|
|
||||||
/* Alternating santri rows */
|
|
||||||
.row-alt { background: #FAFAFA }
|
|
||||||
/* Sticky header */
|
|
||||||
.th-sticky {
|
|
||||||
position: sticky; top: 52px; z-index: 6;
|
|
||||||
background: #1E293B;
|
|
||||||
}
|
|
||||||
.th-tgl { position: sticky; left: 0; z-index: 8 }
|
|
||||||
.th-nama { position: sticky; left: 90px; z-index: 8 }
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<form action="{{ route('admin.mesin.import.store') }}" method="POST" id="frm">
|
<form action="{{ route('admin.mesin.import.store') }}" method="POST" id="frm">
|
||||||
@csrf
|
@csrf
|
||||||
<input type="hidden" name="conflict_strategy" value="manual" id="stratInput">
|
<input type="hidden" name="conflict_strategy" value="manual" id="stratInput">
|
||||||
|
|
||||||
{{-- Error flash --}}
|
|
||||||
@if(session('error'))
|
@if(session('error'))
|
||||||
<div style="background:#FEE2E2;border:1px solid #FCA5A5;border-left:4px solid #DC2626;
|
<div style="background:#FEE2E2;border:1px solid #FCA5A5;border-left:4px solid #DC2626;
|
||||||
padding:12px 16px;font-size:13px;color:#991B1B">
|
padding:12px 16px;font-size:13px;color:#991B1B">
|
||||||
|
|
@ -152,14 +151,15 @@
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
{{-- ── TOP BAR ──────────────────────────────────────────────────────────────── --}}
|
{{-- ══ TOP BAR ═════════════════════════════════════════════════════════════ --}}
|
||||||
<div class="top-bar">
|
<div class="top-bar">
|
||||||
<div style="flex:1;min-width:160px">
|
<div style="flex:1;min-width:200px">
|
||||||
<div style="color:#64748B;font-size:10px;text-transform:uppercase;letter-spacing:1px">
|
<div style="color:#64748B;font-size:10px;text-transform:uppercase;letter-spacing:1px">
|
||||||
Preview Import
|
Preview Import
|
||||||
</div>
|
</div>
|
||||||
<div style="font-weight:700;font-size:14px;margin-top:1px">
|
<div style="font-weight:700;font-size:14px;margin-top:1px">
|
||||||
{{ count($santriList) }} santri
|
{{ $totalSantri }} santri ·
|
||||||
|
{{ count($byTanggal) }} hari
|
||||||
@if($totalKonflik > 0)
|
@if($totalKonflik > 0)
|
||||||
· <span style="color:#FCA5A5" id="lbl">
|
· <span style="color:#FCA5A5" id="lbl">
|
||||||
⚡ <span id="cnt">{{ $totalKonflik }}</span> konflik perlu diselesaikan
|
⚡ <span id="cnt">{{ $totalKonflik }}</span> konflik perlu diselesaikan
|
||||||
|
|
@ -170,15 +170,22 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- Toleransi — tampilkan nilai DARI form, bukan hardcode --}}
|
||||||
|
<div style="background:#1E3A5F;border:1px solid #2D5A8E;border-radius:8px;
|
||||||
|
padding:5px 12px;font-size:11px;color:#93C5FD;white-space:nowrap">
|
||||||
|
⏱ Toleransi: <strong style="color:#BFDBFE">{{ $tolSebelum }}m</strong> sebelum
|
||||||
|
/ <strong style="color:#BFDBFE">{{ $tolSesudah }}m</strong> sesudah
|
||||||
|
</div>
|
||||||
|
|
||||||
{{-- Stat chips --}}
|
{{-- Stat chips --}}
|
||||||
<div class="chip" style="background:#DCFCE7;color:#166534">
|
<div class="chip" style="background:#DCFCE7;color:#166534">
|
||||||
<span class="n">{{ $hadir }}</span>Hadir
|
<span class="n">{{ $hadirTotal }}</span>Hadir
|
||||||
</div>
|
</div>
|
||||||
<div class="chip" style="background:#FEF9C3;color:#92400E">
|
<div class="chip" style="background:#FEF9C3;color:#92400E">
|
||||||
<span class="n">{{ $terlambat }}</span>Telat
|
<span class="n">{{ $terlambatTotal }}</span>Telat
|
||||||
</div>
|
</div>
|
||||||
<div class="chip" style="background:#FEE2E2;color:#991B1B">
|
<div class="chip" style="background:#FEE2E2;color:#991B1B">
|
||||||
<span class="n">{{ $alpa }}</span>Alpa
|
<span class="n">{{ $alpaTotal }}</span>Alpa
|
||||||
</div>
|
</div>
|
||||||
@if($totalKonflik > 0)
|
@if($totalKonflik > 0)
|
||||||
<div class="chip" style="background:#FEE2E2;color:#DC2626">
|
<div class="chip" style="background:#FEE2E2;color:#DC2626">
|
||||||
|
|
@ -191,18 +198,22 @@
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
{{-- Conflict actions --}}
|
{{-- Konflik: bulk actions --}}
|
||||||
@if($totalKonflik > 0)
|
@if($totalKonflik > 0)
|
||||||
<div style="display:flex;flex-direction:column;gap:3px;font-size:11px;color:#94A3B8">
|
<div style="display:flex;flex-direction:column;gap:3px;font-size:11px;color:#94A3B8">
|
||||||
Konflik:
|
Konflik:
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn-act" style="background:#DCFCE7;color:#166534"
|
<button type="button" class="btn-act" style="background:#DCFCE7;color:#166534"
|
||||||
onclick="resolveAll('m');document.getElementById('stratInput').value='mesin'">👆 Mesin</button>
|
onclick="resolveAll('m');document.getElementById('stratInput').value='mesin'">
|
||||||
|
👆 Semua Mesin
|
||||||
|
</button>
|
||||||
<button type="button" class="btn-act" style="background:#DBEAFE;color:#1D4ED8"
|
<button type="button" class="btn-act" style="background:#DBEAFE;color:#1D4ED8"
|
||||||
onclick="resolveAll('e');document.getElementById('stratInput').value='exist'">🔒 Lama</button>
|
onclick="resolveAll('e');document.getElementById('stratInput').value='exist'">
|
||||||
|
🔒 Semua Lama
|
||||||
|
</button>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
{{-- Save --}}
|
{{-- Simpan --}}
|
||||||
<button type="button" class="btn-save" id="saveBtn"
|
<button type="button" class="btn-save" id="saveBtn"
|
||||||
style="background:{{ $totalKonflik > 0 ? '#64748B' : 'linear-gradient(135deg,#166534,#22C55E)' }}"
|
style="background:{{ $totalKonflik > 0 ? '#64748B' : 'linear-gradient(135deg,#166534,#22C55E)' }}"
|
||||||
{{ $totalKonflik > 0 ? 'disabled' : '' }}
|
{{ $totalKonflik > 0 ? 'disabled' : '' }}
|
||||||
|
|
@ -218,7 +229,7 @@ class="btn-act" style="background:#374151;color:#F1F5F9;text-decoration:none">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Legenda --}}
|
{{-- Legenda --}}
|
||||||
<div style="display:flex;gap:8px;flex-wrap:wrap;padding:8px 16px;
|
<div style="display:flex;gap:8px;flex-wrap:wrap;padding:8px 14px;
|
||||||
background:#F8FAFC;border-bottom:1px solid #E5E7EB;font-size:11px">
|
background:#F8FAFC;border-bottom:1px solid #E5E7EB;font-size:11px">
|
||||||
<span style="color:#6B7280;font-weight:600">Status:</span>
|
<span style="color:#6B7280;font-weight:600">Status:</span>
|
||||||
@foreach($statusStyle as $st => $s)
|
@foreach($statusStyle as $st => $s)
|
||||||
|
|
@ -227,44 +238,84 @@ class="btn-act" style="background:#374151;color:#F1F5F9;text-decoration:none">
|
||||||
</span>
|
</span>
|
||||||
@endforeach
|
@endforeach
|
||||||
<span style="color:#9CA3AF;margin-left:4px">| — = tidak ada data</span>
|
<span style="color:#9CA3AF;margin-left:4px">| — = tidak ada data</span>
|
||||||
<span style="border:2px solid #FCA5A5;border-radius:4px;padding:1px 6px;color:#991B1B">
|
<span style="border:2px solid #FCA5A5;border-radius:4px;padding:1px 6px;color:#991B1B">⚡ Konflik</span>
|
||||||
⚡ Konflik
|
<span style="color:#9CA3AF">= pilih salah satu</span>
|
||||||
</span>
|
|
||||||
<span style="color:#9CA3AF">= ada data berbeda, pilih salah satu</span>
|
|
||||||
@if($notMapped > 0)
|
@if($notMapped > 0)
|
||||||
<span style="margin-left:auto">
|
<span style="margin-left:auto">
|
||||||
⚠️ {{ $notMapped }} belum dipetakan →
|
⚠️ {{ $notMapped }} belum dipetakan →
|
||||||
<a href="{{ route('admin.mesin.mapping-santri.index') }}" target="_blank">
|
<a href="{{ route('admin.mesin.mapping-santri.index') }}" target="_blank">Lengkapi Mapping</a>
|
||||||
Lengkapi Mapping
|
|
||||||
</a>
|
|
||||||
</span>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ── MATRIX TABLE ──────────────────────────────────────────────────────────── --}}
|
{{-- ══ TABEL PER HARI ══════════════════════════════════════════════════════ --}}
|
||||||
<div class="wrap">
|
@foreach($byTanggal as $tgl => $santriListRaw)
|
||||||
<table class="mx">
|
@php
|
||||||
|
// Urutkan santri berdasarkan nama
|
||||||
|
$santriListSorted = collect($santriListRaw)
|
||||||
|
->sortBy(fn($h) => $h['nama_web'] ?? $h['nama_mesin'])
|
||||||
|
->values()
|
||||||
|
->all();
|
||||||
|
|
||||||
{{-- Sticky header --}}
|
$tglCarbon = Carbon::parse($tgl);
|
||||||
|
$namaHari = $tglCarbon->locale('id')->isoFormat('dddd');
|
||||||
|
$tglFormatted = $tglCarbon->locale('id')->isoFormat('D MMMM Y');
|
||||||
|
|
||||||
|
$kegiatanHariIni = $kegiatanByTanggal[$tgl];
|
||||||
|
|
||||||
|
// Statistik untuk hari ini
|
||||||
|
$rowsHari = collect($santriListSorted)->flatMap(fn($h) => $h['rows']);
|
||||||
|
$hadirHari = $rowsHari->where('status_final','Hadir')->count();
|
||||||
|
$telambatHari = $rowsHari->where('status_final','Terlambat')->count();
|
||||||
|
$alpaHari = $rowsHari->where('status_final','Alpa')->count();
|
||||||
|
$konflikHari = $rowsHari->where('is_conflict',true)->count();
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<div class="day-block">
|
||||||
|
|
||||||
|
{{-- Header Tanggal --}}
|
||||||
|
<div class="day-header">
|
||||||
|
<div>
|
||||||
|
<div class="hari-nama">{{ $namaHari }}</div>
|
||||||
|
<div class="tgl-label">{{ $tglFormatted }}</div>
|
||||||
|
</div>
|
||||||
|
<div style="margin-left:auto;display:flex;gap:6px;flex-wrap:wrap;align-items:center">
|
||||||
|
<span class="day-badge" style="background:#DCFCE7;color:#166534">✅ {{ $hadirHari }} Hadir</span>
|
||||||
|
@if($telambatHari > 0)
|
||||||
|
<span class="day-badge" style="background:#FEF9C3;color:#92400E">⏰ {{ $telambatHari }} Terlambat</span>
|
||||||
|
@endif
|
||||||
|
<span class="day-badge" style="background:#FEE2E2;color:#991B1B">❌ {{ $alpaHari }} Alpa</span>
|
||||||
|
@if($konflikHari > 0)
|
||||||
|
<span class="day-badge" style="background:#FEE2E2;color:#DC2626">⚡ {{ $konflikHari }} Konflik</span>
|
||||||
|
@endif
|
||||||
|
<span class="day-badge" style="background:#334155;color:#94A3B8">
|
||||||
|
👥 {{ count($santriListSorted) }} santri
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Tabel hari ini --}}
|
||||||
|
<div style="overflow-x:auto">
|
||||||
|
<table class="tbl-day">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr style="background:#F1F5F9">
|
||||||
{{-- Tanggal header --}}
|
<th class="th-no"
|
||||||
<th class="th-sticky th-tgl"
|
style="border:1px solid #E2E8F0;color:#6B7280;font-size:10px;font-weight:700">
|
||||||
style="min-width:90px;padding:8px 10px;text-align:left;
|
No
|
||||||
color:#94A3B8;font-size:10px;border-right:2px solid #334155">
|
|
||||||
Tanggal
|
|
||||||
</th>
|
</th>
|
||||||
{{-- Nama header --}}
|
<th class="th-nama"
|
||||||
<th class="th-sticky th-nama"
|
style="border:1px solid #E2E8F0;color:#374151;font-size:11px;font-weight:700;border-right:2px solid #CBD5E1">
|
||||||
style="min-width:130px;padding:8px 10px;text-align:left;
|
Nama Santri
|
||||||
color:#94A3B8;font-size:10px;border-right:2px solid #334155">
|
|
||||||
Santri
|
|
||||||
</th>
|
</th>
|
||||||
{{-- Kolom kegiatan — UNIK, diurutkan waktu --}}
|
<th class="th-kelas"
|
||||||
@foreach($kegiatanCols as $kg)
|
style="border:1px solid #E2E8F0;color:#374151;font-size:11px;font-weight:700;border-right:2px solid #CBD5E1">
|
||||||
<th class="th-sticky" style="min-width:70px;vertical-align:bottom">
|
Kelas
|
||||||
<div class="th-wrap">
|
</th>
|
||||||
<span style="color:#F1F5F9;font-size:10px;font-weight:600">
|
@foreach($kegiatanHariIni as $kg)
|
||||||
|
<th class="th-keg" style="border:1px solid #E2E8F0">
|
||||||
|
<div class="th-keg-inner">
|
||||||
|
<span style="color:#1E293B;font-size:11px;font-weight:600;
|
||||||
|
white-space:normal;text-align:center;line-height:1.3">
|
||||||
{{ $kg['nama'] }}
|
{{ $kg['nama'] }}
|
||||||
</span>
|
</span>
|
||||||
<span style="color:#64748B;font-size:9px">
|
<span style="color:#64748B;font-size:9px">
|
||||||
|
|
@ -275,96 +326,97 @@ class="btn-act" style="background:#374151;color:#F1F5F9;text-decoration:none">
|
||||||
@endforeach
|
@endforeach
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
{{-- Body: iterasi per tanggal, lalu per santri --}}
|
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach($byTanggalSantri as $tgl => $santriRows)
|
@foreach($santriListSorted as $idx => $h)
|
||||||
|
|
||||||
@php
|
@php
|
||||||
$tglCarbon = Carbon::parse($tgl);
|
$rowBg = ($idx % 2 === 0) ? '#ffffff' : '#F9FAFB';
|
||||||
$tglLabel = $tglCarbon->locale('id')->isoFormat('ddd, D MMM');
|
if ($h['match_status'] === 'NOT_MAPPED') $rowBg = '#FFF5F5';
|
||||||
$isOdd = ($loop->index % 2 === 1);
|
|
||||||
@endphp
|
|
||||||
|
|
||||||
{{-- Setiap tanggal: satu baris per santri --}}
|
|
||||||
@foreach($santriList as $key => $info)
|
|
||||||
@php
|
|
||||||
$data = $santriRows[$key] ?? null;
|
|
||||||
$rowBg = ($loop->index % 2 === 0) ? 'white' : '#FAFAFA';
|
|
||||||
if ($data && $data['match_status'] === 'NOT_MAPPED') $rowBg = '#FFF5F5';
|
|
||||||
@endphp
|
@endphp
|
||||||
<tr style="background:{{ $rowBg }}">
|
<tr style="background:{{ $rowBg }}">
|
||||||
|
|
||||||
{{-- Kolom Tanggal (hanya tampil di baris pertama per tanggal) --}}
|
{{-- No --}}
|
||||||
<td class="col-tgl" style="background:{{ $rowBg }}">
|
<td style="text-align:center;padding:6px 4px;
|
||||||
@if($loop->first)
|
color:#9CA3AF;font-size:11px;border:1px solid #E5E7EB">
|
||||||
<strong style="color:#1E293B">{{ $tglLabel }}</strong>
|
{{ $idx + 1 }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{{-- Nama --}}
|
||||||
|
<td style="padding:6px 10px;border:1px solid #E5E7EB;border-right:2px solid #CBD5E1">
|
||||||
|
@if($h['match_status'] === 'NOT_MAPPED')
|
||||||
|
<div style="font-weight:700;color:#DC2626;font-size:11px">⚠ BELUM MAP</div>
|
||||||
|
<div style="color:#9CA3AF;font-size:10px">{{ $h['nama_mesin'] }}</div>
|
||||||
|
@else
|
||||||
|
<div style="font-weight:600;color:#1F2937;font-size:12px">
|
||||||
|
{{ $h['nama_web'] ?? $h['nama_mesin'] }}
|
||||||
|
</div>
|
||||||
|
@if($h['is_pulang'] ?? false)
|
||||||
|
<div style="font-size:9px;color:#9A3412;background:#FFF7ED;
|
||||||
|
border-radius:4px;padding:1px 5px;display:inline-block;margin-top:1px">
|
||||||
|
🏠 Sedang Pulang
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
{{-- Kolom Nama --}}
|
{{-- Kelas --}}
|
||||||
<td class="col-nama" style="background:{{ $rowBg }}">
|
<td style="padding:6px 10px;border:1px solid #E5E7EB;border-right:2px solid #CBD5E1;
|
||||||
@if($info['status'] === 'NOT_MAPPED')
|
color:#6B7280;font-size:11px">
|
||||||
<div style="font-size:10px;font-weight:700;color:#DC2626">⚠ BELUM MAP</div>
|
{{ $h['kelas'] ?? '-' }}
|
||||||
<div style="font-size:10px;color:#9CA3AF">{{ $info['nama'] }}</div>
|
|
||||||
@else
|
|
||||||
<div style="font-weight:600;color:#1F2937;font-size:12px">
|
|
||||||
{{ $info['nama'] }}
|
|
||||||
</div>
|
|
||||||
<div style="font-size:10px;color:#9CA3AF">{{ $info['kelas'] }}</div>
|
|
||||||
@endif
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
{{-- Kolom per kegiatan --}}
|
{{-- Kolom per kegiatan --}}
|
||||||
@foreach($kegiatanCols as $kg)
|
@foreach($kegiatanHariIni as $kg)
|
||||||
@php
|
@php
|
||||||
$row = $data
|
$row = collect($h['rows'])->firstWhere('kegiatan_id', $kg['kegiatan_id']);
|
||||||
? collect($data['rows'])->firstWhere('kegiatan_id', $kg['kegiatan_id'])
|
|
||||||
: null;
|
|
||||||
$sf = $row['status_final'] ?? null;
|
$sf = $row['status_final'] ?? null;
|
||||||
$st = $sf ? ($statusStyle[$sf] ?? null) : null;
|
$st = $sf ? ($statusStyle[$sf] ?? null) : null;
|
||||||
$isConf = $row['is_conflict'] ?? false;
|
$isConf = $row['is_conflict'] ?? false;
|
||||||
$key2 = "{$kg['kegiatan_id']}_{$data['id_santri']}_{$tgl}";
|
$cKey = "{$kg['kegiatan_id']}_{$h['id_santri']}_{$tgl}";
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<td style="padding:0;text-align:center;vertical-align:middle;min-width:70px"
|
<td style="padding:0;text-align:center;vertical-align:middle;
|
||||||
class="{{ $isConf ? 'conf-cell' : '' }}">
|
border:1px solid {{ $isConf ? '#FCA5A5' : '#E5E7EB' }};
|
||||||
|
{{ $isConf ? 'background:#FFF5F5;border-width:2px;' : '' }}">
|
||||||
|
|
||||||
@if(!$data || !$row || $sf === null)
|
@if(!$row || $sf === null)
|
||||||
{{-- Tidak ada data --}}
|
{{-- Tidak ada data --}}
|
||||||
<span style="color:#D1D5DB">—</span>
|
<span style="color:#D1D5DB;font-size:14px">—</span>
|
||||||
|
|
||||||
@elseif($isConf)
|
@elseif($isConf)
|
||||||
{{-- ── KONFLIK: 2 pilihan ── --}}
|
{{-- ── KONFLIK: 2 pilihan ────────── --}}
|
||||||
@php
|
@php
|
||||||
$ex = $row['existing'];
|
$ex = $row['existing'];
|
||||||
$exSt = $statusStyle[$ex['status']] ?? ['bg'=>'#F9FAFB','c'=>'#6B7280','ic'=>'?'];
|
$exSt = $statusStyle[$ex['status']] ?? ['bg'=>'#F9FAFB','c'=>'#6B7280','ic'=>'?'];
|
||||||
@endphp
|
@endphp
|
||||||
<div class="conf-wrap" data-key="{{ $key2 }}">
|
<div class="conf-wrap" data-key="{{ $cKey }}">
|
||||||
{{-- Pilihan mesin --}}
|
{{-- Pilihan: pakai data mesin --}}
|
||||||
<div class="conf-opt" data-ch="m" onclick="pick('{{ $key2 }}','m',this)">
|
<div class="conf-opt" data-ch="m"
|
||||||
<input type="radio" name="conflict_choices[{{ $key2 }}]"
|
onclick="pick('{{ $cKey }}','m',this)">
|
||||||
value="mesin" id="cm_{{ $key2 }}" style="display:none">
|
<input type="radio" name="conflict_choices[{{ $cKey }}]"
|
||||||
|
value="mesin" id="cm_{{ $cKey }}" style="display:none">
|
||||||
<span>👆</span>
|
<span>👆</span>
|
||||||
<div>
|
<div>
|
||||||
<span class="pill" style="background:{{$st['bg']}};color:{{$st['c']}}">
|
<span class="pill"
|
||||||
|
style="background:{{$st['bg']}};color:{{$st['c']}}">
|
||||||
{{$st['ic']}} {{$sf}}
|
{{$st['ic']}} {{$sf}}
|
||||||
</span>
|
</span>
|
||||||
<div style="font-size:9px;color:#6B7280">
|
<div style="font-size:9px;color:#6B7280;margin-top:1px">
|
||||||
Mesin · {{ $row['jam_scan'] ?? '-' }}
|
Mesin · {{ $row['jam_scan'] ?? '-' }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{-- Pilihan lama --}}
|
{{-- Pilihan: pertahankan data lama --}}
|
||||||
<div class="conf-opt" data-ch="e" onclick="pick('{{ $key2 }}','e',this)">
|
<div class="conf-opt" data-ch="e"
|
||||||
<input type="radio" name="conflict_choices[{{ $key2 }}]"
|
onclick="pick('{{ $cKey }}','e',this)">
|
||||||
value="exist" id="ce_{{ $key2 }}" style="display:none">
|
<input type="radio" name="conflict_choices[{{ $cKey }}]"
|
||||||
|
value="exist" id="ce_{{ $cKey }}" style="display:none">
|
||||||
<span>🔒</span>
|
<span>🔒</span>
|
||||||
<div>
|
<div>
|
||||||
<span class="pill" style="background:{{$exSt['bg']}};color:{{$exSt['c']}}">
|
<span class="pill"
|
||||||
|
style="background:{{$exSt['bg']}};color:{{$exSt['c']}}">
|
||||||
{{$exSt['ic']}} {{$ex['status']}}
|
{{$exSt['ic']}} {{$ex['status']}}
|
||||||
</span>
|
</span>
|
||||||
<div style="font-size:9px;color:#6B7280">
|
<div style="font-size:9px;color:#6B7280;margin-top:1px">
|
||||||
{{ $ex['metode'] ?? 'Manual' }}
|
{{ $ex['metode'] ?? 'Manual' }}
|
||||||
@if($ex['waktu']) · {{ substr($ex['waktu'],0,5) }} @endif
|
@if($ex['waktu']) · {{ substr($ex['waktu'],0,5) }} @endif
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -377,13 +429,15 @@ class="{{ $isConf ? 'conf-cell' : '' }}">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@else
|
@else
|
||||||
{{-- ── Normal ── --}}
|
{{-- ── Normal ─────────────────────── --}}
|
||||||
<div style="padding:5px 3px">
|
<div style="padding:6px 4px">
|
||||||
|
@if($st)
|
||||||
<span class="pill" style="background:{{$st['bg']}};color:{{$st['c']}}">
|
<span class="pill" style="background:{{$st['bg']}};color:{{$st['c']}}">
|
||||||
{{$st['ic']}} {{$sf}}
|
{{$st['ic']}} {{$sf}}
|
||||||
</span>
|
</span>
|
||||||
@if($row['jam_scan'])
|
@endif
|
||||||
<div style="font-size:9px;color:#9CA3AF;margin-top:1px">
|
@if(!empty($row['jam_scan']))
|
||||||
|
<div style="font-size:9px;color:#9CA3AF;margin-top:2px">
|
||||||
{{ $row['jam_scan'] }}
|
{{ $row['jam_scan'] }}
|
||||||
@if(($row['selisih_menit'] ?? 0) > 0)
|
@if(($row['selisih_menit'] ?? 0) > 0)
|
||||||
<span style="color:#F59E0B">+{{ $row['selisih_menit'] }}m</span>
|
<span style="color:#F59E0B">+{{ $row['selisih_menit'] }}m</span>
|
||||||
|
|
@ -394,43 +448,40 @@ class="{{ $isConf ? 'conf-cell' : '' }}">
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
||||||
{{-- Repeat header di bawah untuk tabel panjang --}}
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<th style="background:#1E293B;color:#94A3B8;font-size:10px;
|
|
||||||
padding:6px 10px;border-right:2px solid #334155;
|
|
||||||
position:sticky;left:0">Tanggal</th>
|
|
||||||
<th style="background:#1E293B;color:#94A3B8;font-size:10px;
|
|
||||||
padding:6px 10px;border-right:2px solid #334155;
|
|
||||||
position:sticky;left:90px">Santri</th>
|
|
||||||
@foreach($kegiatanCols as $kg)
|
|
||||||
<th style="background:#1E293B;color:#94A3B8;font-size:9px;padding:4px 6px">
|
|
||||||
{{ $kg['nama'] }}
|
|
||||||
</th>
|
|
||||||
@endforeach
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
{{-- Footer per hari: ringkasan kegiatan --}}
|
||||||
|
<div style="background:#F8FAFC;padding:6px 14px;font-size:10px;color:#6B7280;
|
||||||
|
border-top:1px solid #E5E7EB;display:flex;gap:10px;flex-wrap:wrap">
|
||||||
|
@foreach($kegiatanHariIni as $kg)
|
||||||
|
<span>📌 {{ $kg['nama'] }} ({{ $kg['waktu_mulai'] }})</span>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{-- end day-block --}}
|
||||||
|
|
||||||
{{-- Footer stats --}}
|
@endforeach
|
||||||
<div style="padding:8px 16px;background:#F8FAFC;border-top:1px solid #E5E7EB;
|
{{-- end foreach $byTanggal --}}
|
||||||
font-size:11px;color:#6B7280;display:flex;gap:12px;flex-wrap:wrap">
|
|
||||||
<span>📊 {{ count($santriList) }} santri · {{ count($byTanggalSantri) }} hari</span>
|
{{-- ══ FOOTER GLOBAL ═══════════════════════════════════════════════════════ --}}
|
||||||
<span>✅ {{ $hadir }} Hadir</span>
|
<div style="padding:10px 16px;background:#1E293B;
|
||||||
<span>⏰ {{ $terlambat }} Terlambat</span>
|
font-size:11px;color:#94A3B8;display:flex;gap:14px;flex-wrap:wrap;
|
||||||
<span>❌ {{ $alpa }} Alpa</span>
|
margin-top:0;position:sticky;bottom:0;z-index:40;
|
||||||
|
box-shadow:0 -2px 8px rgba(0,0,0,.2)">
|
||||||
|
<span>📊 {{ $totalSantri }} santri · {{ count($byTanggal) }} hari</span>
|
||||||
|
<span style="color:#86EFAC">✅ {{ $hadirTotal }} Hadir</span>
|
||||||
|
<span style="color:#FDE68A">⏰ {{ $terlambatTotal }} Terlambat</span>
|
||||||
|
<span style="color:#FCA5A5">❌ {{ $alpaTotal }} Alpa</span>
|
||||||
@if($totalKonflik > 0)
|
@if($totalKonflik > 0)
|
||||||
<span style="color:#DC2626">⚡ {{ $totalKonflik }} Konflik</span>
|
<span style="color:#F87171">⚡ <span id="footer-konflik">{{ $totalKonflik }}</span> Konflik</span>
|
||||||
@endif
|
@endif
|
||||||
<span style="margin-left:auto">
|
{{-- Tampilkan toleransi dari form, bukan hardcode --}}
|
||||||
Toleransi: {{ $tolSebelum }}m sebelum / {{ $tolSesudah }}m sesudah
|
<span style="margin-left:auto;color:#93C5FD">
|
||||||
|
⏱ Toleransi: {{ $tolSebelum }}m sebelum / {{ $tolSesudah }}m sesudah
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -473,18 +524,22 @@ function updateUI() {
|
||||||
const btn = document.getElementById('saveBtn');
|
const btn = document.getElementById('saveBtn');
|
||||||
const lbl = document.getElementById('lbl');
|
const lbl = document.getElementById('lbl');
|
||||||
const chip = document.getElementById('chip');
|
const chip = document.getElementById('chip');
|
||||||
|
const fk = document.getElementById('footer-konflik');
|
||||||
|
|
||||||
if (rem <= 0) {
|
if (rem <= 0) {
|
||||||
btn.disabled = false;
|
btn.disabled = false;
|
||||||
btn.style.background = 'linear-gradient(135deg,#166534,#22C55E)';
|
btn.style.background = 'linear-gradient(135deg,#166534,#22C55E)';
|
||||||
btn.textContent = '💾 Simpan ke Database';
|
btn.textContent = '💾 Simpan ke Database';
|
||||||
if (lbl) lbl.innerHTML = '<span style="color:#86EFAC">✅ Semua konflik selesai</span>';
|
if (lbl) lbl.innerHTML = '<span style="color:#86EFAC">✅ Semua konflik selesai</span>';
|
||||||
if (chip) chip.textContent = '0';
|
if (chip) chip.textContent = '0';
|
||||||
|
if (fk) fk.textContent = '0';
|
||||||
} else {
|
} else {
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
btn.style.background = '#64748B';
|
btn.style.background = '#64748B';
|
||||||
btn.textContent = '⏳ Selesaikan ' + rem + ' konflik';
|
btn.textContent = '⏳ Selesaikan ' + rem + ' konflik';
|
||||||
if (lbl) lbl.innerHTML = '<span style="color:#FCA5A5">⚡ <span id="cnt">' + rem + '</span> konflik</span>';
|
if (lbl) lbl.innerHTML = '<span style="color:#FCA5A5">⚡ <span id="cnt">' + rem + '</span> konflik</span>';
|
||||||
if (chip) chip.textContent = rem;
|
if (chip) chip.textContent = rem;
|
||||||
|
if (fk) fk.textContent = rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h1>PONDOK PESANTREN PKPPS</h1>
|
<h1>PKPPS RIYADLUL JANNAH</h1>
|
||||||
<h2>LAPORAN PEMBAYARAN SPP SANTRI</h2>
|
<h2>LAPORAN PEMBAYARAN SPP SANTRI</h2>
|
||||||
<p>Tanggal Cetak: {{ date('d F Y, H:i') }} WIB</p>
|
<p>Tanggal Cetak: {{ date('d F Y, H:i') }} WIB</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -150,9 +150,5 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<div class="footer">
|
|
||||||
<p>© {{ date('Y') }} Pondok Pesantren PKPPS. Laporan dicetak otomatis oleh sistem.</p>
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -55,9 +55,9 @@
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h1>PONDOK PESANTREN PKPPS</h1>
|
<h1>PKPPS RIYADLUL JANNAH</h1>
|
||||||
<h2>LAPORAN PEMBAYARAN SPP</h2>
|
<h2>LAPORAN PEMBAYARAN SPP</h2>
|
||||||
<p>Tanggal Cetak: {{ date('d F Y, H:i') }} WIB</p>
|
<p>Tanggal Cetak: {{ date('d F Y') }} WIB</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Info Filter -->
|
<!-- Info Filter -->
|
||||||
|
|
@ -159,11 +159,6 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<div class="footer">
|
|
||||||
<p>© {{ date('Y') }} Pondok Pesantren PKPPS. Laporan dicetak otomatis oleh sistem.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Auto print saat load (opsional)
|
// Auto print saat load (opsional)
|
||||||
// window.onload = function() { window.print(); }
|
// window.onload = function() { window.print(); }
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
<div class="content-box">
|
<div class="content-box">
|
||||||
|
|
||||||
{{-- ── Filter ── --}}
|
{{-- ── Filter ── --}}
|
||||||
<div style="background:#f8f9fa;padding:14px;border-radius:8px;margin-bottom:14px;">
|
<div style="background:#f8f9fa;padding:14px;border-radius:8px;margin-bottom:14px;">
|
||||||
<form method="GET" action="{{ route('admin.pembayaran-spp.index') }}" style="display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end;">
|
<form method="GET" action="{{ route('admin.pembayaran-spp.index') }}" style="display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end;">
|
||||||
<input type="hidden" name="tab" value="{{ $tab }}">
|
<input type="hidden" name="tab" value="{{ $tab }}">
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ── KPI Cards ── --}}
|
{{-- ── KPI Cards ── --}}
|
||||||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:10px;margin-bottom:14px;">
|
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:10px;margin-bottom:14px;">
|
||||||
<div class="kpi-card" style="background:linear-gradient(135deg,#667eea,#764ba2);">
|
<div class="kpi-card" style="background:linear-gradient(135deg,#667eea,#764ba2);">
|
||||||
<div><div class="kpi-label">Total Santri Aktif</div><div class="kpi-val">{{ $totalSantriAll }}</div><div class="kpi-sub">Periode ini</div></div>
|
<div><div class="kpi-label">Total Santri Aktif</div><div class="kpi-val">{{ $totalSantriAll }}</div><div class="kpi-sub">Periode ini</div></div>
|
||||||
|
|
@ -90,7 +90,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ── Tab Navigation ── --}}
|
{{-- ── Tab Navigation ── --}}
|
||||||
<div style="display:flex;gap:6px;margin-bottom:14px;border-bottom:2px solid #e0e0e0;flex-wrap:wrap;">
|
<div style="display:flex;gap:6px;margin-bottom:14px;border-bottom:2px solid #e0e0e0;flex-wrap:wrap;">
|
||||||
<a href="{{ route('admin.pembayaran-spp.index', array_merge(request()->except('tab'),['tab'=>'belum-bayar'])) }}"
|
<a href="{{ route('admin.pembayaran-spp.index', array_merge(request()->except('tab'),['tab'=>'belum-bayar'])) }}"
|
||||||
class="spp-tab {{ $tab==='belum-bayar'?'spp-tab-danger':'spp-tab-outline-danger' }}">
|
class="spp-tab {{ $tab==='belum-bayar'?'spp-tab-danger':'spp-tab-outline-danger' }}">
|
||||||
|
|
@ -109,7 +109,7 @@ class="spp-tab {{ $tab==='sudah-bayar'?'spp-tab-success':'spp-tab-outline-succes
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ── Action Buttons ── --}}
|
{{-- ── Action Buttons ── --}}
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:14px;flex-wrap:wrap;gap:8px;">
|
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:14px;flex-wrap:wrap;gap:8px;">
|
||||||
<div style="display:flex;gap:8px;flex-wrap:wrap;">
|
<div style="display:flex;gap:8px;flex-wrap:wrap;">
|
||||||
<a href="{{ route('admin.pembayaran-spp.generate') }}" class="btn btn-warning btn-sm"><i class="fas fa-cogs"></i> Generate SPP</a>
|
<a href="{{ route('admin.pembayaran-spp.generate') }}" class="btn btn-warning btn-sm"><i class="fas fa-cogs"></i> Generate SPP</a>
|
||||||
|
|
@ -118,11 +118,11 @@ class="spp-tab {{ $tab==='sudah-bayar'?'spp-tab-success':'spp-tab-outline-succes
|
||||||
</div>
|
</div>
|
||||||
<div style="font-size:11px;color:#666;">
|
<div style="font-size:11px;color:#666;">
|
||||||
Periode: <strong>{{ $bulanIndo[$bulan]??'' }} {{ $tahun }}</strong>
|
Periode: <strong>{{ $bulanIndo[$bulan]??'' }} {{ $tahun }}</strong>
|
||||||
@if($tab==='sudah-bayar') · <i class="fas fa-sort-amount-down"></i> Terbaru bayar di atas @endif
|
@if($tab==='sudah-bayar') · <i class="fas fa-sort-amount-down"></i> Terbaru bayar di atas @endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ── Table ── --}}
|
{{-- ── Table ── --}}
|
||||||
<div style="overflow-x:auto;">
|
<div style="overflow-x:auto;">
|
||||||
<div class="table-wrapper">
|
<div class="table-wrapper">
|
||||||
<table class="data-table">
|
<table class="data-table">
|
||||||
|
|
@ -195,7 +195,7 @@ class="spp-tab {{ $tab==='sudah-bayar'?'spp-tab-success':'spp-tab-outline-succes
|
||||||
</td>
|
</td>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
{{-- ── Aksi (1 baris, tombol ikon) ── --}}
|
{{-- ── Aksi (1 baris, tombol ikon) ── --}}
|
||||||
<td class="text-center" style="white-space:nowrap;">
|
<td class="text-center" style="white-space:nowrap;">
|
||||||
@if($item['pembayaran'])
|
@if($item['pembayaran'])
|
||||||
{{-- Riwayat selalu ada --}}
|
{{-- Riwayat selalu ada --}}
|
||||||
|
|
@ -206,8 +206,15 @@ class="spp-tab {{ $tab==='sudah-bayar'?'spp-tab-success':'spp-tab-outline-succes
|
||||||
<a href="{{ route('admin.pembayaran-spp.edit',$item['pembayaran']->id) }}" class="btn btn-sm btn-warning" title="Edit"><i class="fas fa-edit"></i></a>
|
<a href="{{ route('admin.pembayaran-spp.edit',$item['pembayaran']->id) }}" class="btn btn-sm btn-warning" title="Edit"><i class="fas fa-edit"></i></a>
|
||||||
|
|
||||||
@elseif($tab==='cicilan')
|
@elseif($tab==='cicilan')
|
||||||
|
{{-- ✅ FIX: gunakan route() helper, bukan hardcode URL --}}
|
||||||
<button type="button" class="btn btn-sm btn-purple" title="Catat Cicilan"
|
<button type="button" class="btn btn-sm btn-purple" title="Catat Cicilan"
|
||||||
onclick="bukaCatatCicilan({{ $item['pembayaran']->id }},'{{ addslashes($item['nama_lengkap']) }}',{{ $item['nominal'] }},{{ $item['pembayaran']->nominal_terbayar }})">
|
onclick="bukaCatatCicilan(
|
||||||
|
{{ $item['pembayaran']->id }},
|
||||||
|
'{{ addslashes($item['nama_lengkap']) }}',
|
||||||
|
{{ $item['nominal'] }},
|
||||||
|
{{ $item['pembayaran']->nominal_terbayar }},
|
||||||
|
'{{ route('admin.pembayaran-spp.cicilan', $item['pembayaran']->id) }}'
|
||||||
|
)">
|
||||||
<i class="fas fa-coins"></i>
|
<i class="fas fa-coins"></i>
|
||||||
</button>
|
</button>
|
||||||
<form action="{{ route('admin.pembayaran-spp.bayar',$item['pembayaran']->id) }}" method="POST" style="display:inline;"
|
<form action="{{ route('admin.pembayaran-spp.bayar',$item['pembayaran']->id) }}" method="POST" style="display:inline;"
|
||||||
|
|
@ -223,8 +230,15 @@ class="spp-tab {{ $tab==='sudah-bayar'?'spp-tab-success':'spp-tab-outline-succes
|
||||||
@csrf
|
@csrf
|
||||||
<button type="submit" class="btn btn-sm btn-success" title="Tandai Lunas"><i class="fas fa-check"></i></button>
|
<button type="submit" class="btn btn-sm btn-success" title="Tandai Lunas"><i class="fas fa-check"></i></button>
|
||||||
</form>
|
</form>
|
||||||
|
{{-- ✅ FIX: gunakan route() helper, bukan hardcode URL --}}
|
||||||
<button type="button" class="btn btn-sm btn-purple" title="Catat Cicilan"
|
<button type="button" class="btn btn-sm btn-purple" title="Catat Cicilan"
|
||||||
onclick="bukaCatatCicilan({{ $item['pembayaran']->id }},'{{ addslashes($item['nama_lengkap']) }}',{{ $item['nominal'] }},0)">
|
onclick="bukaCatatCicilan(
|
||||||
|
{{ $item['pembayaran']->id }},
|
||||||
|
'{{ addslashes($item['nama_lengkap']) }}',
|
||||||
|
{{ $item['nominal'] }},
|
||||||
|
0,
|
||||||
|
'{{ route('admin.pembayaran-spp.cicilan', $item['pembayaran']->id) }}'
|
||||||
|
)">
|
||||||
<i class="fas fa-coins"></i>
|
<i class="fas fa-coins"></i>
|
||||||
</button>
|
</button>
|
||||||
<a href="{{ route('admin.pembayaran-spp.edit',$item['pembayaran']->id) }}" class="btn btn-sm btn-warning" title="Edit"><i class="fas fa-edit"></i></a>
|
<a href="{{ route('admin.pembayaran-spp.edit',$item['pembayaran']->id) }}" class="btn btn-sm btn-warning" title="Edit"><i class="fas fa-edit"></i></a>
|
||||||
|
|
@ -253,7 +267,7 @@ class="btn btn-sm btn-primary" title="Buat Tagihan"><i class="fas fa-plus"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ── Pagination ── --}}
|
{{-- ── Pagination ── --}}
|
||||||
@if($totalPages>1)
|
@if($totalPages>1)
|
||||||
<div style="margin-top:14px;display:flex;justify-content:center;align-items:center;gap:10px;">
|
<div style="margin-top:14px;display:flex;justify-content:center;align-items:center;gap:10px;">
|
||||||
@if($currentPage>1)
|
@if($currentPage>1)
|
||||||
|
|
@ -267,7 +281,7 @@ class="btn btn-sm btn-primary" title="Buat Tagihan"><i class="fas fa-plus"></i>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ── Modal Catat Cicilan ── --}}
|
{{-- ── Modal Catat Cicilan ── --}}
|
||||||
<div id="modalCicilan" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:9999;align-items:center;justify-content:center;">
|
<div id="modalCicilan" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:9999;align-items:center;justify-content:center;">
|
||||||
<div style="background:#fff;border-radius:12px;padding:24px;width:100%;max-width:400px;box-shadow:0 20px 60px rgba(0,0,0,.3);margin:16px;">
|
<div style="background:#fff;border-radius:12px;padding:24px;width:100%;max-width:400px;box-shadow:0 20px 60px rgba(0,0,0,.3);margin:16px;">
|
||||||
<h4 style="margin:0 0 4px;"><i class="fas fa-coins" style="color:#9c27b0;"></i> Catat Cicilan</h4>
|
<h4 style="margin:0 0 4px;"><i class="fas fa-coins" style="color:#9c27b0;"></i> Catat Cicilan</h4>
|
||||||
|
|
@ -305,7 +319,6 @@ class="btn btn-sm btn-primary" title="Buat Tagihan"><i class="fas fa-plus"></i>
|
||||||
.kpi-sub { font-size:11px;opacity:.8; }
|
.kpi-sub { font-size:11px;opacity:.8; }
|
||||||
.kpi-icon { font-size:26px;opacity:.25; }
|
.kpi-icon { font-size:26px;opacity:.25; }
|
||||||
/* Tabs */
|
/* Tabs */
|
||||||
|
|
||||||
.spp-tab {
|
.spp-tab {
|
||||||
display:inline-flex; align-items:center; gap:6px;
|
display:inline-flex; align-items:center; gap:6px;
|
||||||
padding:8px 14px; border-radius:8px 8px 0 0;
|
padding:8px 14px; border-radius:8px 8px 0 0;
|
||||||
|
|
@ -350,19 +363,26 @@ class="btn btn-sm btn-primary" title="Buat Tagihan"><i class="fas fa-plus"></i>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function fmt(n) { return 'Rp ' + parseInt(n).toLocaleString('id-ID'); }
|
function fmt(n) { return 'Rp ' + parseInt(n).toLocaleString('id-ID'); }
|
||||||
function bukaCatatCicilan(id, nama, tagihan, terbayar) {
|
|
||||||
|
{{-- ✅ FIX: parameter ke-5 sekarang menerima URL dari route() helper Laravel --}}
|
||||||
|
function bukaCatatCicilan(id, nama, tagihan, terbayar, routeUrl) {
|
||||||
document.getElementById('modalNama').textContent = nama;
|
document.getElementById('modalNama').textContent = nama;
|
||||||
document.getElementById('mTagihan').textContent = fmt(tagihan);
|
document.getElementById('mTagihan').textContent = fmt(tagihan);
|
||||||
document.getElementById('mTerbayar').textContent = fmt(terbayar);
|
document.getElementById('mTerbayar').textContent = fmt(terbayar);
|
||||||
document.getElementById('mSisa').textContent = fmt(tagihan - terbayar);
|
document.getElementById('mSisa').textContent = fmt(tagihan - terbayar);
|
||||||
document.getElementById('inputNominal').max = tagihan - terbayar;
|
document.getElementById('inputNominal').max = tagihan - terbayar;
|
||||||
document.getElementById('formCicilan').action = '/admin/pembayaran-spp/' + id + '/cicilan';
|
|
||||||
|
{{-- ✅ FIX: set action dari routeUrl yang sudah di-generate oleh blade, bukan hardcode --}}
|
||||||
|
document.getElementById('formCicilan').action = routeUrl;
|
||||||
|
|
||||||
var modal = document.getElementById('modalCicilan');
|
var modal = document.getElementById('modalCicilan');
|
||||||
modal.style.display = 'flex';
|
modal.style.display = 'flex';
|
||||||
}
|
}
|
||||||
|
|
||||||
function tutupModal() {
|
function tutupModal() {
|
||||||
document.getElementById('modalCicilan').style.display = 'none';
|
document.getElementById('modalCicilan').style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('modalCicilan').addEventListener('click', function(e) {
|
document.getElementById('modalCicilan').addEventListener('click', function(e) {
|
||||||
if (e.target === this) tutupModal();
|
if (e.target === this) tutupModal();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -50,39 +50,12 @@
|
||||||
<i class="fas fa-print"></i> Cetak Laporan
|
<i class="fas fa-print"></i> Cetak Laporan
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Laporan Per Santri -->
|
|
||||||
<div class="card card-success hover-lift">
|
|
||||||
<h3>Laporan Per Santri</h3>
|
|
||||||
<p style="margin: 10px 0; color: var(--text-light);">
|
|
||||||
Cetak laporan pembayaran SPP untuk santri tertentu
|
|
||||||
</p>
|
|
||||||
<form action="{{ route('admin.pembayaran-spp.cetak-laporan-santri', ':id') }}" method="GET" id="form-santri" target="_blank">
|
|
||||||
<div class="form-group">
|
|
||||||
<label><i class="fas fa-user form-icon"></i> Pilih Santri</label>
|
|
||||||
<select name="id_santri" id="select-santri" class="form-control" required>
|
|
||||||
<option value="">-- Pilih Santri --</option>
|
|
||||||
@foreach(\App\Models\Santri::orderBy('nama_lengkap')->get() as $santri)
|
|
||||||
<option value="{{ $santri->id_santri }}">
|
|
||||||
{{ $santri->nama_lengkap }} ({{ $santri->id_santri }})
|
|
||||||
</option>
|
|
||||||
@endforeach
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-success hover-shadow" style="width: 100%;">
|
|
||||||
<i class="fas fa-print"></i> Cetak Laporan Santri
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content-box" style="margin-top: 25px;">
|
<div class="content-box" style="margin-top: 25px;">
|
||||||
<a href="{{ route('admin.pembayaran-spp.index') }}" class="btn btn-secondary">
|
<a href="{{ route('admin.pembayaran-spp.index') }}" class="btn btn-secondary">
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
<script>
|
<script>
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,34 @@
|
||||||
<td>{{ $user->santri->nama_lengkap ?? '-' }}</td>
|
<td>{{ $user->santri->nama_lengkap ?? '-' }}</td>
|
||||||
<td>{{ $user->santri->nis ?? '-' }}</td>
|
<td>{{ $user->santri->nis ?? '-' }}</td>
|
||||||
<td><code>{{ $user->username }}</code></td>
|
<td><code>{{ $user->username }}</code></td>
|
||||||
<td>
|
<td style="white-space:nowrap;">
|
||||||
|
{{-- Tombol Kirim WA --}}
|
||||||
|
@if($user->santri && $user->santri->nomor_hp_ortu)
|
||||||
|
@php
|
||||||
|
$noHp = preg_replace('/[^0-9]/', '', $user->santri->nomor_hp_ortu);
|
||||||
|
if (str_starts_with($noHp, '0')) {
|
||||||
|
$noHp = '62' . substr($noHp, 1);
|
||||||
|
}
|
||||||
|
$pesan = rawurlencode(
|
||||||
|
"Halo, berikut informasi akun website PKPPS Riyadlul Jannah atas nama {$user->santri->nama_lengkap}.\n\n"
|
||||||
|
. "Username: {$user->username}\n"
|
||||||
|
. "Password: {$user->santri->nis}\n\n"
|
||||||
|
. "Silakan gunakan informasi di atas untuk login ke portal web PKPPS Riyadlul Jannah."
|
||||||
|
);
|
||||||
|
@endphp
|
||||||
|
<a href="https://wa.me/{{ $noHp }}?text={{ $pesan }}"
|
||||||
|
target="_blank"
|
||||||
|
class="btn btn-sm btn-success"
|
||||||
|
title="Kirim info akun via WhatsApp">
|
||||||
|
<i class="fas fa-share-alt"></i> Kirim
|
||||||
|
</a>
|
||||||
|
@else
|
||||||
|
<span class="text-muted" title="Nomor HP ortu belum diisi">
|
||||||
|
<i class="fas fa-share-alt"></i> -
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- Tombol Hapus --}}
|
||||||
<form action="{{ route('admin.users.santri_destroy', $user->id) }}"
|
<form action="{{ route('admin.users.santri_destroy', $user->id) }}"
|
||||||
method="POST" style="display:inline;"
|
method="POST" style="display:inline;"
|
||||||
onsubmit="return confirm('Yakin hapus akun santri {{ $user->santri->nama_lengkap ?? '' }}?')">
|
onsubmit="return confirm('Yakin hapus akun santri {{ $user->santri->nama_lengkap ?? '' }}?')">
|
||||||
|
|
@ -82,7 +109,6 @@
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<div class="table-wrapper">
|
<div class="table-wrapper">
|
||||||
|
|
||||||
<table class="data-table">
|
<table class="data-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -130,7 +156,6 @@
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
@ -48,7 +48,34 @@
|
||||||
<td>{{ $user->santri->nama_orang_tua ?? '-' }}</td>
|
<td>{{ $user->santri->nama_orang_tua ?? '-' }}</td>
|
||||||
<td>{{ $user->santri->nis ?? '-' }}</td>
|
<td>{{ $user->santri->nis ?? '-' }}</td>
|
||||||
<td><code>{{ $user->username }}</code></td>
|
<td><code>{{ $user->username }}</code></td>
|
||||||
<td>
|
<td style="white-space:nowrap;">
|
||||||
|
{{-- Tombol Kirim WA --}}
|
||||||
|
@if($user->santri && $user->santri->nomor_hp_ortu)
|
||||||
|
@php
|
||||||
|
$noHp = preg_replace('/[^0-9]/', '', $user->santri->nomor_hp_ortu);
|
||||||
|
if (str_starts_with($noHp, '0')) {
|
||||||
|
$noHp = '62' . substr($noHp, 1);
|
||||||
|
}
|
||||||
|
$pesan = rawurlencode(
|
||||||
|
"Halo, berikut informasi akun mobile app PKPPS Riyadlul Jannah untuk wali dari {$user->santri->nama_lengkap}.\n\n"
|
||||||
|
. "Username: {$user->username}\n"
|
||||||
|
. "Password: {$user->santri->nis}\n\n"
|
||||||
|
. "Silakan gunakan informasi di atas untuk login ke aplikasi mobile PKPPS Riyadlul Jannah"
|
||||||
|
);
|
||||||
|
@endphp
|
||||||
|
<a href="https://wa.me/{{ $noHp }}?text={{ $pesan }}"
|
||||||
|
target="_blank"
|
||||||
|
class="btn btn-sm btn-success"
|
||||||
|
title="Kirim info akun via WhatsApp">
|
||||||
|
<i class="fas fa-share-alt"></i> Kirim
|
||||||
|
</a>
|
||||||
|
@else
|
||||||
|
<span class="text-muted" title="Nomor HP ortu belum diisi">
|
||||||
|
<i class="fas fa-share-alt"></i> -
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- Tombol Hapus --}}
|
||||||
<form action="{{ route('admin.users.wali_destroy', $user->id) }}"
|
<form action="{{ route('admin.users.wali_destroy', $user->id) }}"
|
||||||
method="POST" style="display:inline;"
|
method="POST" style="display:inline;"
|
||||||
onsubmit="return confirm('Yakin hapus akun wali {{ $user->santri->nama_lengkap ?? '' }}?')">
|
onsubmit="return confirm('Yakin hapus akun wali {{ $user->santri->nama_lengkap ?? '' }}?')">
|
||||||
|
|
@ -86,8 +113,6 @@
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@php
|
@php
|
||||||
// Kumpulkan nama ortu yang sudah dipakai di akun existing
|
|
||||||
// untuk preview username yang akan dibuat
|
|
||||||
$namaOrtuSudahAda = \App\Models\SantriAccount::where('role', 'wali')
|
$namaOrtuSudahAda = \App\Models\SantriAccount::where('role', 'wali')
|
||||||
->pluck('username')
|
->pluck('username')
|
||||||
->toArray();
|
->toArray();
|
||||||
|
|
@ -95,7 +120,6 @@
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<div class="table-wrapper">
|
<div class="table-wrapper">
|
||||||
|
|
||||||
<table class="data-table">
|
<table class="data-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -111,7 +135,6 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
@forelse ($santris_tanpa_wali as $santri)
|
@forelse ($santris_tanpa_wali as $santri)
|
||||||
@php
|
@php
|
||||||
// Preview username: sama persis dgn logika resolveUsernameWali() di controller
|
|
||||||
$previewUsername = null;
|
$previewUsername = null;
|
||||||
if ($santri->nama_orang_tua) {
|
if ($santri->nama_orang_tua) {
|
||||||
$usernameDefault = $santri->nama_orang_tua;
|
$usernameDefault = $santri->nama_orang_tua;
|
||||||
|
|
@ -172,7 +195,6 @@
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
@ -48,7 +48,12 @@
|
||||||
.kg-badge.fire { background:linear-gradient(135deg,#f59e0b,#f97316); border:none; }
|
.kg-badge.fire { background:linear-gradient(135deg,#f59e0b,#f97316); border:none; }
|
||||||
|
|
||||||
/* ── KPI CARDS ── */
|
/* ── KPI CARDS ── */
|
||||||
.kg-kpi-row { display:grid; grid-template-columns:repeat(5,1fr); gap:10px; margin-bottom:16px; }
|
.kg-kpi-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(5, 1fr);
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
.kg-kpi { background:white; border-radius:12px; padding:14px 12px; box-shadow:var(--sh); text-align:center; border-top:3px solid transparent; transition:transform 0.18s,box-shadow 0.18s; }
|
.kg-kpi { background:white; border-radius:12px; padding:14px 12px; box-shadow:var(--sh); text-align:center; border-top:3px solid transparent; transition:transform 0.18s,box-shadow 0.18s; }
|
||||||
.kg-kpi:hover { transform:translateY(-3px); box-shadow:var(--shl); }
|
.kg-kpi:hover { transform:translateY(-3px); box-shadow:var(--shl); }
|
||||||
.kg-kpi.c-green { border-top-color:#2bbd8e; }
|
.kg-kpi.c-green { border-top-color:#2bbd8e; }
|
||||||
|
|
@ -87,8 +92,8 @@
|
||||||
.kg-preset-btn { padding:6px 12px; border:1.5px solid var(--br); border-radius:8px; background:white; font-size:0.79rem; font-weight:600; color:var(--mu); cursor:pointer; transition:all 0.15s; white-space:nowrap; }
|
.kg-preset-btn { padding:6px 12px; border:1.5px solid var(--br); border-radius:8px; background:white; font-size:0.79rem; font-weight:600; color:var(--mu); cursor:pointer; transition:all 0.15s; white-space:nowrap; }
|
||||||
.kg-preset-btn:hover { border-color:var(--m); color:var(--g); background:var(--sf); }
|
.kg-preset-btn:hover { border-color:var(--m); color:var(--g); background:var(--sf); }
|
||||||
.kg-preset-btn.active { border-color:var(--g); background:var(--g); color:white; }
|
.kg-preset-btn.active { border-color:var(--g); background:var(--g); color:white; }
|
||||||
.kg-date-range { display:flex; align-items:center; gap:5px; }
|
.kg-date-range { display:flex; align-items:center; gap:5px; flex-wrap:wrap; }
|
||||||
.kg-date-range input[type=date] { padding:6px 9px; border:1.5px solid var(--br); border-radius:8px; font-size:0.8rem; color:var(--tx); background:white; }
|
.kg-date-range input[type=date] { padding:6px 9px; border:1.5px solid var(--br); border-radius:8px; font-size:0.8rem; color:var(--tx); background:white; min-width:0; max-width:140px; width:100%; }
|
||||||
.kg-date-range input[type=date]:focus { outline:none; border-color:var(--m); }
|
.kg-date-range input[type=date]:focus { outline:none; border-color:var(--m); }
|
||||||
.kg-date-range span { color:var(--mu); font-size:0.79rem; font-weight:600; }
|
.kg-date-range span { color:var(--mu); font-size:0.79rem; font-weight:600; }
|
||||||
.kg-apply-btn { padding:7px 15px; background:var(--g); color:white; border:none; border-radius:8px; font-size:0.81rem; font-weight:700; cursor:pointer; display:inline-flex; align-items:center; gap:5px; }
|
.kg-apply-btn { padding:7px 15px; background:var(--g); color:white; border:none; border-radius:8px; font-size:0.81rem; font-weight:700; cursor:pointer; display:inline-flex; align-items:center; gap:5px; }
|
||||||
|
|
@ -100,7 +105,7 @@
|
||||||
.kg-jadwal-group { margin-bottom:14px; }
|
.kg-jadwal-group { margin-bottom:14px; }
|
||||||
.kg-hari-label { font-size:0.77rem; font-weight:700; text-transform:uppercase; letter-spacing:0.8px; color:var(--g); padding:5px 11px; background:var(--sf); border-radius:8px; margin-bottom:8px; display:inline-flex; align-items:center; gap:5px; }
|
.kg-hari-label { font-size:0.77rem; font-weight:700; text-transform:uppercase; letter-spacing:0.8px; color:var(--g); padding:5px 11px; background:var(--sf); border-radius:8px; margin-bottom:8px; display:inline-flex; align-items:center; gap:5px; }
|
||||||
.kg-hari-label.today-label { background:var(--g); color:white; }
|
.kg-hari-label.today-label { background:var(--g); color:white; }
|
||||||
.kg-jadwal-card { background:white; border-radius:11px; padding:13px 15px; box-shadow:var(--sh); display:flex; align-items:center; gap:12px; border-left:4px solid var(--br); margin-bottom:7px; transition:transform 0.16s; }
|
.kg-jadwal-card { background:white; border-radius:11px; padding:13px 15px; box-shadow:var(--sh); display:flex; align-items:center; gap:12px; border-left:4px solid var(--br); margin-bottom:7px; transition:transform 0.16s; flex-wrap:wrap; }
|
||||||
.kg-jadwal-card:hover { transform:translateX(3px); }
|
.kg-jadwal-card:hover { transform:translateX(3px); }
|
||||||
.kg-jadwal-card.s-hadir { border-left-color:#2bbd8e; }
|
.kg-jadwal-card.s-hadir { border-left-color:#2bbd8e; }
|
||||||
.kg-jadwal-card.s-terlambat { border-left-color:#f59e0b; }
|
.kg-jadwal-card.s-terlambat { border-left-color:#f59e0b; }
|
||||||
|
|
@ -109,7 +114,7 @@
|
||||||
.kg-jadwal-card.s-alpa { border-left-color:#e53e3e; }
|
.kg-jadwal-card.s-alpa { border-left-color:#e53e3e; }
|
||||||
.kg-jadwal-card.s-pulang { border-left-color:#0d9488; }
|
.kg-jadwal-card.s-pulang { border-left-color:#0d9488; }
|
||||||
.kg-jadwal-card.s-belum { border-left-color:#f5a623; }
|
.kg-jadwal-card.s-belum { border-left-color:#f5a623; }
|
||||||
.kg-time { min-width:58px; text-align:center; }
|
.kg-time { min-width:58px; text-align:center; flex-shrink:0; }
|
||||||
.kg-time-main { font-size:0.93rem; font-weight:700; color:var(--g); }
|
.kg-time-main { font-size:0.93rem; font-weight:700; color:var(--g); }
|
||||||
.kg-time-end { font-size:0.71rem; color:var(--mu); font-weight:500; }
|
.kg-time-end { font-size:0.71rem; color:var(--mu); font-weight:500; }
|
||||||
.kg-divider { width:1px; height:34px; background:var(--br); flex-shrink:0; }
|
.kg-divider { width:1px; height:34px; background:var(--br); flex-shrink:0; }
|
||||||
|
|
@ -126,7 +131,7 @@
|
||||||
.kg-detail-btn:hover { background:#155c47; }
|
.kg-detail-btn:hover { background:#155c47; }
|
||||||
|
|
||||||
/* Pill status */
|
/* Pill status */
|
||||||
.kpill { padding:3px 11px; border-radius:20px; font-size:0.75rem; font-weight:700; flex-shrink:0; }
|
.kpill { padding:3px 11px; border-radius:20px; font-size:0.75rem; font-weight:700; flex-shrink:0; white-space:nowrap; }
|
||||||
.kpill.hadir { background:#d1fae5; color:#065f46; }
|
.kpill.hadir { background:#d1fae5; color:#065f46; }
|
||||||
.kpill.terlambat { background:#fef3c7; color:#92400e; }
|
.kpill.terlambat { background:#fef3c7; color:#92400e; }
|
||||||
.kpill.belum { background:#fef3c7; color:#92400e; }
|
.kpill.belum { background:#fef3c7; color:#92400e; }
|
||||||
|
|
@ -140,6 +145,17 @@
|
||||||
.kg-chart-box { background:white; border-radius:12px; padding:18px; box-shadow:var(--sh); }
|
.kg-chart-box { background:white; border-radius:12px; padding:18px; box-shadow:var(--sh); }
|
||||||
.kg-chart-title { font-size:0.86rem; font-weight:700; color:var(--tx); margin-bottom:14px; display:flex; align-items:center; gap:6px; }
|
.kg-chart-title { font-size:0.86rem; font-weight:700; color:var(--tx); margin-bottom:14px; display:flex; align-items:center; gap:6px; }
|
||||||
|
|
||||||
|
/* ── ABSENSI TERBARU + KALENDER GRID ──
|
||||||
|
Ini yang diperbaiki: pakai class bukan inline style
|
||||||
|
agar bisa di-override via media query */
|
||||||
|
.kg-recent-cal-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 220px;
|
||||||
|
gap: 14px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── RECENT ABSENSI ── */
|
/* ── RECENT ABSENSI ── */
|
||||||
.kg-recent-list { display:flex; flex-direction:column; gap:6px; }
|
.kg-recent-list { display:flex; flex-direction:column; gap:6px; }
|
||||||
.kg-recent-item {
|
.kg-recent-item {
|
||||||
|
|
@ -172,7 +188,10 @@
|
||||||
.kg-recent-date { font-size:0.69rem; color:var(--mu); opacity:0.7; margin-top:3px; }
|
.kg-recent-date { font-size:0.69rem; color:var(--mu); opacity:0.7; margin-top:3px; }
|
||||||
|
|
||||||
/* ── MINI CALENDAR ── */
|
/* ── MINI CALENDAR ── */
|
||||||
.kg-cal-mini { width:220px; flex-shrink:0; }
|
.kg-cal-mini {
|
||||||
|
flex-shrink: 0;
|
||||||
|
/* width dikontrol oleh grid-column di atas, tidak perlu fixed width */
|
||||||
|
}
|
||||||
.kg-cal-mini-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:2px; }
|
.kg-cal-mini-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:2px; }
|
||||||
.kg-cal-mini-dname { text-align:center; font-size:0.6rem; font-weight:700; color:var(--mu); padding-bottom:3px; text-transform:uppercase; }
|
.kg-cal-mini-dname { text-align:center; font-size:0.6rem; font-weight:700; color:var(--mu); padding-bottom:3px; text-transform:uppercase; }
|
||||||
.kg-cal-mini-cell { aspect-ratio:1; border-radius:4px; display:flex; align-items:center; justify-content:center; font-size:0.63rem; font-weight:600; cursor:default; transition:transform 0.1s; }
|
.kg-cal-mini-cell { aspect-ratio:1; border-radius:4px; display:flex; align-items:center; justify-content:center; font-size:0.63rem; font-weight:600; cursor:default; transition:transform 0.1s; }
|
||||||
|
|
@ -189,9 +208,84 @@
|
||||||
.kg-empty { text-align:center; padding:36px 20px; color:var(--mu); background:white; border-radius:12px; box-shadow:var(--sh); }
|
.kg-empty { text-align:center; padding:36px 20px; color:var(--mu); background:white; border-radius:12px; box-shadow:var(--sh); }
|
||||||
.kg-empty i { font-size:2.8rem; opacity:0.2; display:block; margin-bottom:10px; }
|
.kg-empty i { font-size:2.8rem; opacity:0.2; display:block; margin-bottom:10px; }
|
||||||
|
|
||||||
@media (max-width:768px) {
|
/* ════════════════════════════════════
|
||||||
|
RESPONSIVE
|
||||||
|
════════════════════════════════════ */
|
||||||
|
|
||||||
|
/* Tablet (≤ 900px) */
|
||||||
|
@media (max-width: 900px) {
|
||||||
.kg-kpi-row { grid-template-columns: repeat(3, 1fr); }
|
.kg-kpi-row { grid-template-columns: repeat(3, 1fr); }
|
||||||
|
|
||||||
|
/* Kalender turun ke bawah absensi terbaru */
|
||||||
|
.kg-recent-cal-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Kalender full width saat di bawah */
|
||||||
|
.kg-cal-mini {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grid kalender isi penuh */
|
||||||
|
.kg-cal-mini-grid {
|
||||||
|
max-width: 320px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tablet kecil / HP landscape (≤ 768px) */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.kg-kpi-row { grid-template-columns: repeat(3, 1fr); gap: 8px; }
|
||||||
.kg-stat-grid { grid-template-columns: 1fr; }
|
.kg-stat-grid { grid-template-columns: 1fr; }
|
||||||
|
.kg-hero { padding: 18px 16px 16px; }
|
||||||
|
.kg-hero-title { font-size: 1.05rem; }
|
||||||
|
|
||||||
|
.kg-tab-filter { padding: 10px 12px; gap: 6px; }
|
||||||
|
.kg-fg { width: 100%; }
|
||||||
|
.kg-date-range { width: 100%; }
|
||||||
|
.kg-date-range input[type=date] { flex: 1; max-width: none; }
|
||||||
|
.kg-apply-btn { width: 100%; justify-content: center; }
|
||||||
|
.kg-filter-label { width: 100%; justify-content: center; }
|
||||||
|
|
||||||
|
/* Jadwal card: susun vertikal di HP */
|
||||||
|
.kg-jadwal-card { gap: 8px; }
|
||||||
|
.kg-divider { display: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HP portrait (≤ 480px) */
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.kg-kpi-row {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nilai KPI sedikit lebih kecil biar muat */
|
||||||
|
.kg-kpi-v { font-size: 1.35rem; }
|
||||||
|
.kg-kpi-l { font-size: 0.66rem; }
|
||||||
|
.kg-kpi { padding: 11px 8px; }
|
||||||
|
.kg-kpi-ic { width: 30px; height: 30px; font-size: 0.8rem; }
|
||||||
|
|
||||||
|
.kg-hero { padding: 14px 13px 13px; }
|
||||||
|
.kg-hero-title { font-size: 0.95rem; }
|
||||||
|
.kg-hero-sub { font-size: 0.77rem; }
|
||||||
|
|
||||||
|
/* Recent item: sembunyikan icon di HP kecil agar nama tidak terpotong */
|
||||||
|
.kg-recent-ic { display: none; }
|
||||||
|
.kg-recent-item { gap: 8px; padding: 8px 10px; }
|
||||||
|
.kg-recent-name { font-size: 0.8rem; }
|
||||||
|
.kg-recent-meta { font-size: 0.67rem; gap: 5px; }
|
||||||
|
.kpill { font-size: 0.68rem; padding: 2px 7px; }
|
||||||
|
|
||||||
|
.kg-chart-box { padding: 13px; }
|
||||||
|
.kg-jadwal-card { padding: 10px 12px; }
|
||||||
|
.kg-jname { font-size: 0.82rem; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sangat kecil (≤ 360px) */
|
||||||
|
@media (max-width: 360px) {
|
||||||
|
.kg-kpi-row { grid-template-columns: repeat(2, 1fr); gap: 6px; }
|
||||||
|
.kg-kpi-v { font-size: 1.2rem; }
|
||||||
|
.kg-kpi { padding: 9px 6px; }
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
@ -254,7 +348,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ── TABS — 2 tab saja ── --}}
|
{{-- ── TABS ── --}}
|
||||||
<div class="kg-tabs">
|
<div class="kg-tabs">
|
||||||
<button class="kg-tab {{ $activeTab === 'statistik' ? 'active' : '' }}" onclick="switchTab('statistik',this)">
|
<button class="kg-tab {{ $activeTab === 'statistik' ? 'active' : '' }}" onclick="switchTab('statistik',this)">
|
||||||
<i class="fas fa-chart-bar"></i> Statistik
|
<i class="fas fa-chart-bar"></i> Statistik
|
||||||
|
|
@ -309,7 +403,9 @@
|
||||||
<div class="kg-chart-box">
|
<div class="kg-chart-box">
|
||||||
<div class="kg-chart-title">
|
<div class="kg-chart-title">
|
||||||
<i class="fas fa-chart-line" style="color:var(--m);"></i> Tren Kehadiran
|
<i class="fas fa-chart-line" style="color:var(--m);"></i> Tren Kehadiran
|
||||||
<span style="margin-left:auto;font-size:0.73rem;color:var(--mu);font-weight:500;">{{ $diffDays<=31?'Harian':'Mingguan' }}</span>
|
<span style="margin-left:auto;font-size:0.73rem;color:var(--mu);font-weight:500;">
|
||||||
|
{{ $diffDays <= 31 ? 'Harian' : 'Mingguan' }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<canvas id="chartTren" style="max-height:220px;"></canvas>
|
<canvas id="chartTren" style="max-height:220px;"></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -319,8 +415,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Absensi Terbaru + Kalender --}}
|
{{-- ── Absensi Terbaru + Kalender ──
|
||||||
<div style="display:grid; grid-template-columns:1fr auto; gap:14px; margin-bottom:14px; align-items:start;">
|
Pakai class .kg-recent-cal-grid (bukan inline style)
|
||||||
|
agar breakpoint CSS bisa meng-override ke 1 kolom --}}
|
||||||
|
<div class="kg-recent-cal-grid">
|
||||||
|
|
||||||
{{-- Catatan Absensi Terbaru --}}
|
{{-- Catatan Absensi Terbaru --}}
|
||||||
<div class="kg-chart-box" style="min-width:0;">
|
<div class="kg-chart-box" style="min-width:0;">
|
||||||
|
|
@ -457,7 +555,9 @@
|
||||||
<div class="kg-jadwal-group">
|
<div class="kg-jadwal-group">
|
||||||
<div class="kg-hari-label {{ $hari === $hariIni ? 'today-label' : '' }}">
|
<div class="kg-hari-label {{ $hari === $hariIni ? 'today-label' : '' }}">
|
||||||
<i class="fas fa-calendar-day"></i> {{ $hari }}
|
<i class="fas fa-calendar-day"></i> {{ $hari }}
|
||||||
@if($hari === $hariIni) <span style="font-size:0.66rem;opacity:0.85;">(Hari Ini)</span> @endif
|
@if($hari === $hariIni)
|
||||||
|
<span style="font-size:0.66rem;opacity:0.85;">(Hari Ini)</span>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@foreach($jadwals as $jadwal)
|
@foreach($jadwals as $jadwal)
|
||||||
@php
|
@php
|
||||||
|
|
@ -481,7 +581,6 @@
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{-- Status pill --}}
|
|
||||||
@if($statusAbsen)
|
@if($statusAbsen)
|
||||||
<span class="kpill {{ strtolower($statusAbsen) }}">
|
<span class="kpill {{ strtolower($statusAbsen) }}">
|
||||||
@if($statusAbsen === 'Terlambat') <i class="fas fa-clock"></i>
|
@if($statusAbsen === 'Terlambat') <i class="fas fa-clock"></i>
|
||||||
|
|
@ -492,7 +591,6 @@
|
||||||
@elseif($hari === $hariIni)
|
@elseif($hari === $hariIni)
|
||||||
<span class="kpill belum"><i class="fas fa-hourglass-half"></i> Belum</span>
|
<span class="kpill belum"><i class="fas fa-hourglass-half"></i> Belum</span>
|
||||||
@endif
|
@endif
|
||||||
{{-- Tombol Detail → ke show() --}}
|
|
||||||
<a href="{{ route('santri.kegiatan.show', $jadwal->kegiatan_id) }}?from_tab=jadwal"
|
<a href="{{ route('santri.kegiatan.show', $jadwal->kegiatan_id) }}?from_tab=jadwal"
|
||||||
class="kg-detail-btn">
|
class="kg-detail-btn">
|
||||||
<i class="fas fa-chart-bar"></i> Detail
|
<i class="fas fa-chart-bar"></i> Detail
|
||||||
|
|
@ -511,7 +609,6 @@ class="kg-detail-btn">
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
// ── TAB SWITCHER ─────────────────────────────────
|
|
||||||
function switchTab(name, el) {
|
function switchTab(name, el) {
|
||||||
document.querySelectorAll('.kg-tab').forEach(t => t.classList.remove('active'));
|
document.querySelectorAll('.kg-tab').forEach(t => t.classList.remove('active'));
|
||||||
document.querySelectorAll('.kg-panel').forEach(p => p.classList.remove('active'));
|
document.querySelectorAll('.kg-panel').forEach(p => p.classList.remove('active'));
|
||||||
|
|
@ -520,7 +617,6 @@ function switchTab(name, el) {
|
||||||
if (name === 'statistik' && !window._chartsInit) { initCharts(); window._chartsInit = true; }
|
if (name === 'statistik' && !window._chartsInit) { initCharts(); window._chartsInit = true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── PRESET SETTER ────────────────────────────────
|
|
||||||
function setPreset(scope, val) {
|
function setPreset(scope, val) {
|
||||||
document.querySelectorAll('#' + scope + 'Presets .kg-preset-btn').forEach(b => b.classList.remove('active'));
|
document.querySelectorAll('#' + scope + 'Presets .kg-preset-btn').forEach(b => b.classList.remove('active'));
|
||||||
event.target.classList.add('active');
|
event.target.classList.add('active');
|
||||||
|
|
@ -539,7 +635,6 @@ function setCustom(scope) {
|
||||||
document.querySelectorAll('#' + scope + 'Presets .kg-preset-btn').forEach(b => b.classList.remove('active'));
|
document.querySelectorAll('#' + scope + 'Presets .kg-preset-btn').forEach(b => b.classList.remove('active'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── CHARTS ───────────────────────────────────────
|
|
||||||
function initCharts() {
|
function initCharts() {
|
||||||
const trenLabels = @json(collect($dataGrafik)->pluck('label'));
|
const trenLabels = @json(collect($dataGrafik)->pluck('label'));
|
||||||
const trenHadir = @json(collect($dataGrafik)->pluck('hadir'));
|
const trenHadir = @json(collect($dataGrafik)->pluck('hadir'));
|
||||||
|
|
@ -611,7 +706,6 @@ function initCharts() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── INIT ─────────────────────────────────────────
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
var tab = new URLSearchParams(window.location.search).get('tab') || 'statistik';
|
var tab = new URLSearchParams(window.location.search).get('tab') || 'statistik';
|
||||||
var map = { statistik: 0, jadwal: 1 };
|
var map = { statistik: 0, jadwal: 1 };
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
a:4:{s:6:"_token";s:40:"Rogr1HsMSukvmYR2m3b7pPraVOehwZvcU2GYYNaA";s:9:"_previous";a:1:{s:3:"url";s:44:"http://127.0.0.1:8000/admin/laporan-kegiatan";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}s:50:"login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d";i:1;}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
a:3:{s:6:"_token";s:40:"z2Q3wuWmkF9oCYl0WHpsIaXywzR0FjwyltHaEHA1";s:9:"_previous";a:1:{s:3:"url";s:34:"http://127.0.0.1:8000/santri/login";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
a:4:{s:6:"_token";s:40:"TiMKyzlAzRLRL9vdvNjuuT4zMOD7QGCBKyJKG7lC";s:3:"url";a:1:{s:8:"intended";s:58:"http://localhost/admin/laporan-kegiatan?periode=minggu_ini";}s:9:"_previous";a:1:{s:3:"url";s:58:"http://localhost/admin/laporan-kegiatan?periode=minggu_ini";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}
|
||||||
|
|
@ -1 +1 @@
|
||||||
a:3:{s:6:"_token";s:40:"TPUzTdhC3a0zTqKnoC2h8FNhcf5pYPmSXvPiSVKO";s:6:"_flash";a:2:{s:3:"new";a:0:{}s:3:"old";a:0:{}}s:9:"_previous";a:1:{s:3:"url";s:33:"http://127.0.0.1:8000/admin/login";}}
|
a:3:{s:6:"_token";s:40:"38E76quLNOyMUAX08jBlb63KKtrUj910NO6H7reC";s:6:"_flash";a:2:{s:3:"new";a:0:{}s:3:"old";a:0:{}}s:9:"_previous";a:1:{s:3:"url";s:33:"http://127.0.0.1:8000/admin/login";}}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
a:4:{s:6:"_token";s:40:"JkoSzSFooBHlizoZQ1QgxXKBUyzQsoduDjvLAUrc";s:9:"_previous";a:1:{s:3:"url";s:38:"http://127.0.0.1:8000/admin/kepulangan";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}s:50:"login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d";i:1;}
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
a:3:{s:6:"_token";s:40:"sl0M4vZdqyldTB5GLbTu6mj3iC3fdQImAkTcALm1";s:6:"_flash";a:2:{s:3:"new";a:0:{}s:3:"old";a:0:{}}s:9:"_previous";a:1:{s:3:"url";s:34:"http://127.0.0.1:8000/santri/login";}}
|
|
||||||
|
|
@ -1,285 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<style>
|
|
||||||
.access-hero {
|
|
||||||
border-radius: 14px;
|
|
||||||
padding: 24px 28px;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 20px;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.access-hero.open { background: linear-gradient(135deg, #e8f5e9, #c8e6c9); border: 2px solid #66bb6a; }
|
|
||||||
.access-hero.closed { background: linear-gradient(135deg, #fff3e0, #ffe0b2); border: 2px solid #ffa726; }
|
|
||||||
.access-hero .ah-icon { font-size: 3.5rem; flex-shrink: 0; }
|
|
||||||
.access-hero h3 { margin: 0 0 5px; font-size: 1.15rem; }
|
|
||||||
.access-hero p { margin: 0; font-size: 0.85rem; color: #555; }
|
|
||||||
|
|
||||||
.status-badge-big {
|
|
||||||
display: inline-flex; align-items: center; gap: 8px;
|
|
||||||
padding: 8px 22px; border-radius: 25px; font-weight: 800;
|
|
||||||
font-size: 1rem; margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.status-badge-big.open { background: #2e7d32; color: #fff; }
|
|
||||||
.status-badge-big.closed { background: #e65100; color: #fff; }
|
|
||||||
|
|
||||||
.info-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
|
||||||
gap: 12px;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
.info-box {
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 14px 16px;
|
|
||||||
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
|
|
||||||
border-left: 4px solid;
|
|
||||||
}
|
|
||||||
.info-box .ib-label { font-size: 0.72rem; color: #999; text-transform: uppercase; margin-bottom: 4px; }
|
|
||||||
.info-box .ib-val { font-size: 0.92rem; font-weight: 700; color: #333; }
|
|
||||||
|
|
||||||
.form-card {
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 22px;
|
|
||||||
box-shadow: 0 2px 12px rgba(0,0,0,0.06);
|
|
||||||
margin-bottom: 16px;
|
|
||||||
border: 1px solid #e8f0ec;
|
|
||||||
}
|
|
||||||
.form-card h4 { margin: 0 0 16px; color: var(--primary-dark); font-size: 1rem; }
|
|
||||||
|
|
||||||
.toggle-btn {
|
|
||||||
display: inline-flex; align-items: center; gap: 8px;
|
|
||||||
padding: 11px 28px; border-radius: 10px; border: none;
|
|
||||||
font-weight: 700; font-size: 0.9rem; cursor: pointer;
|
|
||||||
transition: all .2s;
|
|
||||||
}
|
|
||||||
.toggle-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(0,0,0,0.15); }
|
|
||||||
.toggle-btn.open-btn { background: linear-gradient(135deg, #43a047, #2e7d32); color: #fff; }
|
|
||||||
.toggle-btn.close-btn { background: linear-gradient(135deg, #ef5350, #c62828); color: #fff; }
|
|
||||||
|
|
||||||
.countdown-bar {
|
|
||||||
height: 10px; background: #f0f0f0;
|
|
||||||
border-radius: 20px; overflow: hidden; margin-top: 8px;
|
|
||||||
}
|
|
||||||
.countdown-fill {
|
|
||||||
height: 100%; border-radius: 20px;
|
|
||||||
background: linear-gradient(90deg, #66bb6a, #2e7d32);
|
|
||||||
transition: width .5s;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="page-header" style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:10px;">
|
|
||||||
<h2><i class="fas fa-unlock-alt"></i> Kelola Akses Input Capaian Santri</h2>
|
|
||||||
<a href="<?php echo e(route('admin.capaian.index')); ?>" class="btn btn-secondary" style="padding:7px 16px;">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
|
||||||
</a>
|
|
||||||
</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="access-hero <?php echo e($isOpen ? 'open' : 'closed'); ?>">
|
|
||||||
<div class="ah-icon"><?php echo e($isOpen ? '🔓' : '🔒'); ?></div>
|
|
||||||
<div style="flex:1;">
|
|
||||||
<div class="status-badge-big <?php echo e($isOpen ? 'open' : 'closed'); ?>">
|
|
||||||
<i class="fas fa-<?php echo e($isOpen ? 'lock-open' : 'lock'); ?>"></i>
|
|
||||||
<?php echo e($isOpen ? 'AKSES DIBUKA' : 'AKSES DITUTUP'); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<h3>
|
|
||||||
<?php if($isOpen): ?>
|
|
||||||
Santri sedang bisa menginputkan capaian mereka
|
|
||||||
<?php else: ?>
|
|
||||||
Santri belum bisa menginputkan capaian
|
|
||||||
<?php endif; ?>
|
|
||||||
</h3>
|
|
||||||
<p>
|
|
||||||
<?php if($isOpen): ?>
|
|
||||||
Dibuka oleh <strong><?php echo e($config['opened_by'] ?? '-'); ?></strong>
|
|
||||||
pada <?php echo e($config['opened_at'] ? \Carbon\Carbon::parse($config['opened_at'])->isoFormat('D MMM YYYY, HH:mm') : '-'); ?>
|
|
||||||
|
|
||||||
<?php if($config['id_semester']): ?>
|
|
||||||
• Semester: <strong><?php echo e(\App\Models\Semester::where('id_semester', $config['id_semester'])->value('nama_semester') ?? '-'); ?></strong>
|
|
||||||
<?php else: ?>
|
|
||||||
• Semua semester diizinkan
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($sisaWaktu): ?>
|
|
||||||
• Sisa waktu: <strong><?php echo e($sisaWaktu); ?></strong>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php else: ?>
|
|
||||||
<?php if($config['closed_at']): ?>
|
|
||||||
Ditutup pada <?php echo e(\Carbon\Carbon::parse($config['closed_at'])->isoFormat('D MMM YYYY, HH:mm')); ?>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
Belum pernah dibuka
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
</p>
|
|
||||||
<?php if(!empty($config['catatan'])): ?>
|
|
||||||
<p style="margin-top:6px;font-style:italic;"><i class="fas fa-sticky-note"></i> "<?php echo e($config['catatan']); ?>"</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="info-row">
|
|
||||||
<div class="info-box" style="border-color:#66bb6a;">
|
|
||||||
<div class="ib-label">Status</div>
|
|
||||||
<div class="ib-val" style="color:<?php echo e($isOpen ? '#2e7d32' : '#c62828'); ?>;">
|
|
||||||
<i class="fas fa-<?php echo e($isOpen ? 'check-circle' : 'times-circle'); ?>"></i>
|
|
||||||
<?php echo e($isOpen ? 'Terbuka' : 'Tertutup'); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="info-box" style="border-color:#81C6E8;">
|
|
||||||
<div class="ib-label">Dibuka Oleh</div>
|
|
||||||
<div class="ib-val"><?php echo e($config['opened_by'] ?? '-'); ?></div>
|
|
||||||
</div>
|
|
||||||
<div class="info-box" style="border-color:#FFD56B;">
|
|
||||||
<div class="ib-label">Semester</div>
|
|
||||||
<div class="ib-val">
|
|
||||||
<?php if($config['id_semester']): ?>
|
|
||||||
<?php echo e(\App\Models\Semester::where('id_semester', $config['id_semester'])->value('nama_semester') ?? '-'); ?>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
Semua Semester
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="info-box" style="border-color:#B39DDB;">
|
|
||||||
<div class="ib-label">Auto-Close</div>
|
|
||||||
<div class="ib-val">
|
|
||||||
<?php if($config['auto_close_at']): ?>
|
|
||||||
<?php echo e(\Carbon\Carbon::parse($config['auto_close_at'])->isoFormat('D MMM HH:mm')); ?>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
Manual
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:18px;">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="form-card">
|
|
||||||
<h4 style="color:#2e7d32;"><i class="fas fa-lock-open"></i> Buka Akses Input Capaian</h4>
|
|
||||||
|
|
||||||
<form method="POST" action="<?php echo e(route('admin.capaian.akses-santri.buka')); ?>">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom:12px;">
|
|
||||||
<label style="font-size:.83rem;font-weight:600;color:#555;display:block;margin-bottom:4px;">
|
|
||||||
<i class="fas fa-calendar-alt"></i> Semester yang Dibuka
|
|
||||||
</label>
|
|
||||||
<select name="id_semester" class="form-control" style="font-size:.84rem;">
|
|
||||||
<option value="">-- Semua Semester --</option>
|
|
||||||
<?php $__currentLoopData = $semesters; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $sem): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($sem->id_semester); ?>"
|
|
||||||
<?php echo e(($semesterAktif && $sem->id_semester == $semesterAktif->id_semester) ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($sem->nama_semester); ?><?php echo e($sem->is_active ? ' ★ (Aktif)' : ''); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
<small style="color:#999;font-size:.74rem;">Kosongkan = santri bisa input di semua semester</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom:12px;">
|
|
||||||
<label style="font-size:.83rem;font-weight:600;color:#555;display:block;margin-bottom:4px;">
|
|
||||||
<i class="fas fa-clock"></i> Durasi Otomatis Tutup (opsional)
|
|
||||||
</label>
|
|
||||||
<div style="display:flex;align-items:center;gap:8px;">
|
|
||||||
<input type="number" name="durasi_jam" min="1" max="720"
|
|
||||||
class="form-control" style="width:110px;font-size:.84rem;"
|
|
||||||
placeholder="cth: 24">
|
|
||||||
<span style="font-size:.84rem;color:#555;">jam</span>
|
|
||||||
</div>
|
|
||||||
<small style="color:#999;font-size:.74rem;">Kosongkan = harus ditutup manual oleh admin</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom:16px;">
|
|
||||||
<label style="font-size:.83rem;font-weight:600;color:#555;display:block;margin-bottom:4px;">
|
|
||||||
<i class="fas fa-sticky-note"></i> Catatan untuk Santri (opsional)
|
|
||||||
</label>
|
|
||||||
<input type="text" name="catatan" class="form-control" style="font-size:.84rem;"
|
|
||||||
placeholder="cth: Deadline input: Jumat 17.00 WIB" maxlength="255">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="toggle-btn open-btn">
|
|
||||||
<i class="fas fa-lock-open"></i> Buka Akses Sekarang
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="form-card">
|
|
||||||
<h4 style="color:#c62828;"><i class="fas fa-lock"></i> Tutup Akses Input Capaian</h4>
|
|
||||||
|
|
||||||
<?php if($isOpen): ?>
|
|
||||||
<div style="background:#fbe9e7;border-radius:9px;padding:14px;margin-bottom:16px;">
|
|
||||||
<p style="margin:0;font-size:.84rem;color:#555;">
|
|
||||||
<i class="fas fa-info-circle" style="color:#ef5350;"></i>
|
|
||||||
Saat ini akses <strong>sedang dibuka</strong>. Klik tombol di bawah untuk menutup akses input capaian santri segera.
|
|
||||||
</p>
|
|
||||||
<?php if($sisaWaktu): ?>
|
|
||||||
<p style="margin:8px 0 0;font-size:.8rem;color:#777;">
|
|
||||||
<i class="fas fa-hourglass-half"></i> Sisa waktu auto-close: <strong><?php echo e($sisaWaktu); ?></strong>
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form method="POST" action="<?php echo e(route('admin.capaian.akses-santri.tutup')); ?>"
|
|
||||||
onsubmit="return confirm('Yakin ingin menutup akses input capaian santri?')">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<button type="submit" class="toggle-btn close-btn">
|
|
||||||
<i class="fas fa-lock"></i> Tutup Akses Sekarang
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
<?php else: ?>
|
|
||||||
<div style="background:#f5f5f5;border-radius:9px;padding:14px;text-align:center;color:#aaa;">
|
|
||||||
<i class="fas fa-lock" style="font-size:2rem;display:block;margin-bottom:8px;"></i>
|
|
||||||
Akses saat ini sudah tertutup.<br>
|
|
||||||
<span style="font-size:.8rem;">Gunakan form di sebelah kiri untuk membuka akses.</span>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="form-card" style="background:#f0f9ff;border:1px solid #b3e0ff;">
|
|
||||||
<h4 style="color:#0277bd;"><i class="fas fa-info-circle"></i> Alur Penggunaan</h4>
|
|
||||||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px;font-size:.83rem;color:#555;">
|
|
||||||
<div style="display:flex;gap:10px;">
|
|
||||||
<div style="background:#1565c0;color:#fff;width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:800;flex-shrink:0;">1</div>
|
|
||||||
<div><strong>Admin membuka akses</strong><br>Pilih semester & opsional durasi waktu lalu klik "Buka Akses".</div>
|
|
||||||
</div>
|
|
||||||
<div style="display:flex;gap:10px;">
|
|
||||||
<div style="background:#2e7d32;color:#fff;width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:800;flex-shrink:0;">2</div>
|
|
||||||
<div><strong>Santri input capaian</strong><br>Santri login ke web-nya dan bisa input capaian sesuai materi kelasnya.</div>
|
|
||||||
</div>
|
|
||||||
<div style="display:flex;gap:10px;">
|
|
||||||
<div style="background:#e65100;color:#fff;width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:800;flex-shrink:0;">3</div>
|
|
||||||
<div><strong>Data langsung masuk</strong><br>Data capaian santri langsung terlihat di dashboard admin & riwayat santri.</div>
|
|
||||||
</div>
|
|
||||||
<div style="display:flex;gap:10px;">
|
|
||||||
<div style="background:#6a1b9a;color:#fff;width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:800;flex-shrink:0;">4</div>
|
|
||||||
<div><strong>Admin menutup akses</strong><br>Setelah selesai, tutup akses manual atau biarkan auto-close berjalan.</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/capaian/akses-santri.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,274 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Riwayat Pelanggaran'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-history"></i> Riwayat Pelanggaran Santri</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Alert Messages -->
|
|
||||||
<?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; ?>
|
|
||||||
|
|
||||||
<!-- Statistik Cards -->
|
|
||||||
<div class="row-cards">
|
|
||||||
<div class="card card-primary">
|
|
||||||
<h3><i class="fas fa-list"></i> Total Pelanggaran</h3>
|
|
||||||
<div class="card-value"><?php echo e($totalPelanggaran); ?></div>
|
|
||||||
<p style="margin: 0; color: var(--text-light);">Semua Riwayat</p>
|
|
||||||
<i class="fas fa-clipboard-list card-icon"></i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card card-warning">
|
|
||||||
<h3><i class="fas fa-calendar-alt"></i> Bulan Ini</h3>
|
|
||||||
<div class="card-value"><?php echo e($pelanggaranBulanIni); ?></div>
|
|
||||||
<p style="margin: 0; color: var(--text-light);"><?php echo e(\Carbon\Carbon::now()->format('F Y')); ?></p>
|
|
||||||
<i class="fas fa-calendar-check card-icon"></i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card card-danger">
|
|
||||||
<h3><i class="fas fa-star"></i> Total Poin</h3>
|
|
||||||
<div class="card-value"><?php echo e($totalPoin); ?></div>
|
|
||||||
<p style="margin: 0; color: var(--text-light);">Akumulasi Poin</p>
|
|
||||||
<i class="fas fa-fire card-icon"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Filter & Search -->
|
|
||||||
<div class="content-box" style="margin-bottom: 22px;">
|
|
||||||
<h3 style="margin-bottom: 14px; color: var(--primary-color);">
|
|
||||||
<i class="fas fa-filter"></i> Filter & Pencarian
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.riwayat-pelanggaran.index')); ?>">
|
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px; margin-bottom: 14px;">
|
|
||||||
<!-- Search -->
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<label for="search">
|
|
||||||
<i class="fas fa-search form-icon"></i>
|
|
||||||
Pencarian
|
|
||||||
</label>
|
|
||||||
<input type="text"
|
|
||||||
name="search"
|
|
||||||
id="search"
|
|
||||||
class="form-control"
|
|
||||||
value="<?php echo e(request('search')); ?>"
|
|
||||||
placeholder="Cari santri, kategori...">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Filter Santri -->
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<label for="id_santri">
|
|
||||||
<i class="fas fa-user form-icon"></i>
|
|
||||||
Santri
|
|
||||||
</label>
|
|
||||||
<select name="id_santri" id="id_santri" class="form-control">
|
|
||||||
<option value="">-- Semua 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(request('id_santri') == $santri->id_santri ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($santri->nama_lengkap); ?> (<?php echo e($santri->id_santri); ?>)
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Filter Kategori -->
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<label for="id_kategori">
|
|
||||||
<i class="fas fa-tags form-icon"></i>
|
|
||||||
Kategori
|
|
||||||
</label>
|
|
||||||
<select name="id_kategori" id="id_kategori" class="form-control">
|
|
||||||
<option value="">-- Semua Kategori --</option>
|
|
||||||
<?php $__currentLoopData = $kategoriList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kategori): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($kategori->id_kategori); ?>"
|
|
||||||
<?php echo e(request('id_kategori') == $kategori->id_kategori ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($kategori->nama_pelanggaran); ?> (<?php echo e($kategori->poin); ?> poin)
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Tanggal Mulai -->
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<label for="tanggal_mulai">
|
|
||||||
<i class="fas fa-calendar form-icon"></i>
|
|
||||||
Tanggal Mulai
|
|
||||||
</label>
|
|
||||||
<input type="date"
|
|
||||||
name="tanggal_mulai"
|
|
||||||
id="tanggal_mulai"
|
|
||||||
class="form-control"
|
|
||||||
value="<?php echo e(request('tanggal_mulai')); ?>">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Tanggal Selesai -->
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<label for="tanggal_selesai">
|
|
||||||
<i class="fas fa-calendar-check form-icon"></i>
|
|
||||||
Tanggal Selesai
|
|
||||||
</label>
|
|
||||||
<input type="date"
|
|
||||||
name="tanggal_selesai"
|
|
||||||
id="tanggal_selesai"
|
|
||||||
class="form-control"
|
|
||||||
value="<?php echo e(request('tanggal_selesai')); ?>">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
<i class="fas fa-search"></i> Cari
|
|
||||||
</button>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-pelanggaran.index')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-redo"></i> Reset
|
|
||||||
</a>
|
|
||||||
<label style="display: inline-flex; align-items: center; margin-left: 20px;">
|
|
||||||
<input type="checkbox" name="bulan_ini" value="1" <?php echo e(request('bulan_ini') ? 'checked' : ''); ?> style="margin-right: 8px;">
|
|
||||||
<span>Bulan Ini Saja</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Tabel Data -->
|
|
||||||
<div class="content-box">
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px;">
|
|
||||||
<h3 style="margin: 0; color: var(--primary-color);">
|
|
||||||
<i class="fas fa-table"></i> Daftar Riwayat Pelanggaran
|
|
||||||
</h3>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-pelanggaran.create')); ?>" class="btn btn-primary">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Riwayat
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($data->isNotEmpty()): ?>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 50px;">No</th>
|
|
||||||
<th style="width: 110px;">ID Riwayat</th>
|
|
||||||
<th style="width: 120px;">Tanggal</th>
|
|
||||||
<th>Santri</th>
|
|
||||||
<th>Kategori Pelanggaran</th>
|
|
||||||
<th style="width: 100px; text-align: center;">Poin</th>
|
|
||||||
<th style="width: 200px; text-align: center;">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $data; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($data->firstItem() + $index); ?></td>
|
|
||||||
<td>
|
|
||||||
<span class="badge badge-secondary"><?php echo e($item->id_riwayat); ?></span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<i class="fas fa-calendar" style="color: var(--text-light);"></i>
|
|
||||||
<?php echo e(\Carbon\Carbon::parse($item->tanggal)->format('d M Y')); ?>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($item->santri): ?>
|
|
||||||
<strong><?php echo e($item->santri->nama_lengkap); ?></strong><br>
|
|
||||||
<small style="color: var(--text-light);">
|
|
||||||
<i class="fas fa-id-card"></i> <?php echo e($item->id_santri); ?>
|
|
||||||
|
|
||||||
</small>
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="color: var(--danger-color);">Santri tidak ditemukan</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($item->kategori): ?>
|
|
||||||
<strong><?php echo e($item->kategori->nama_pelanggaran); ?></strong><br>
|
|
||||||
<small style="color: var(--text-light);">
|
|
||||||
<i class="fas fa-tag"></i> <?php echo e($item->id_kategori); ?>
|
|
||||||
|
|
||||||
</small>
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="color: var(--danger-color);">Kategori tidak ditemukan</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<span class="badge badge-danger" style="font-size: 1em; padding: 8px 12px;">
|
|
||||||
<i class="fas fa-fire"></i> <?php echo e($item->poin); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<div style="display: flex; justify-content: center; gap: 8px;">
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-pelanggaran.show', $item)); ?>"
|
|
||||||
class="btn btn-sm btn-success"
|
|
||||||
title="Detail">
|
|
||||||
<i class="fas fa-eye"></i>
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-pelanggaran.edit', $item)); ?>"
|
|
||||||
class="btn btn-sm btn-warning"
|
|
||||||
title="Edit">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
<form action="<?php echo e(route('admin.riwayat-pelanggaran.destroy', $item)); ?>"
|
|
||||||
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-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>
|
|
||||||
|
|
||||||
<!-- Pagination -->
|
|
||||||
<div style="margin-top: 14px;">
|
|
||||||
<?php echo e($data->links()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-folder-open"></i>
|
|
||||||
<h3>Belum ada riwayat pelanggaran</h3>
|
|
||||||
<p>Silakan tambah riwayat pelanggaran baru menggunakan tombol di atas.</p>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-pelanggaran.create')); ?>" class="btn btn-primary">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Riwayat
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// Auto hide alerts after 5 seconds
|
|
||||||
setTimeout(function() {
|
|
||||||
const alerts = document.querySelectorAll('.alert');
|
|
||||||
alerts.forEach(alert => {
|
|
||||||
alert.style.transition = 'opacity 0.5s';
|
|
||||||
alert.style.opacity = '0';
|
|
||||||
setTimeout(() => alert.remove(), 500);
|
|
||||||
});
|
|
||||||
}, 5000);
|
|
||||||
</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/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,196 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-calendar-alt"></i> Jadwal Kegiatan Santri</h2>
|
|
||||||
<div style="display: flex; gap: 8px;">
|
|
||||||
<a href="<?php echo e(route('admin.kegiatan.create')); ?>" class="btn btn-success btn-sm">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Kegiatan
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.kategori-kegiatan.index')); ?>" class="btn btn-info btn-sm">
|
|
||||||
<i class="fas fa-tags"></i> Kategori
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</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; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<form method="GET" class="filter-form-inline">
|
|
||||||
<div class="filter-form-inline" style="gap: 8px;">
|
|
||||||
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
|
||||||
<i class="fas fa-calendar-day"></i> Hari:
|
|
||||||
</label>
|
|
||||||
<select name="hari" class="form-control" onchange="this.form.submit()" style="max-width: 160px;">
|
|
||||||
<option value="">Semua Hari</option>
|
|
||||||
<?php $__currentLoopData = $hariList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $hari): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($hari); ?>" <?php echo e(request('hari') == $hari ? 'selected' : ''); ?>><?php echo e($hari); ?></option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="filter-form-inline" style="gap: 8px;">
|
|
||||||
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
|
||||||
<i class="fas fa-tags"></i> Kategori:
|
|
||||||
</label>
|
|
||||||
<select name="kategori_id" class="form-control" onchange="this.form.submit()" style="max-width: 180px;">
|
|
||||||
<option value="">Semua 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(request('kategori_id') == $kat->kategori_id ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($kat->nama_kategori); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="filter-form-inline" style="gap: 8px;">
|
|
||||||
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
|
||||||
<i class="fas fa-school"></i> Kelas:
|
|
||||||
</label>
|
|
||||||
<select name="kelas_id" class="form-control" onchange="this.form.submit()" style="max-width: 200px;">
|
|
||||||
<option value="">Semua Kelas</option>
|
|
||||||
<option value="umum" <?php echo e(request('kelas_id') === 'umum' ? 'selected' : ''); ?>>Kegiatan Umum</option>
|
|
||||||
<?php $__currentLoopData = $kelasList->groupBy('kelompok.nama_kelompok'); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelompokNama => $kelasGroup): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<optgroup label="<?php echo e($kelompokNama); ?>">
|
|
||||||
<?php $__currentLoopData = $kelasGroup; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($kelas->id); ?>" <?php echo e(request('kelas_id') == $kelas->id ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($kelas->nama_kelas); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</optgroup>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="filter-form-inline" style="gap: 8px;">
|
|
||||||
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
|
||||||
<i class="fas fa-search"></i>
|
|
||||||
</label>
|
|
||||||
<input type="text" name="search" class="form-control" placeholder="Cari kegiatan..."
|
|
||||||
value="<?php echo e(request('search')); ?>" style="max-width: 180px;">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary btn-sm">
|
|
||||||
<i class="fas fa-filter"></i> Filter
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<?php if(request()->hasAny(['hari', 'kategori_id', 'kelas_id', 'search'])): ?>
|
|
||||||
<a href="<?php echo e(route('admin.kegiatan.jadwal')); ?>" class="btn btn-secondary btn-sm">
|
|
||||||
<i class="fas fa-times"></i> Reset
|
|
||||||
</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$kegiatanPerHari = $kegiatans->groupBy('hari');
|
|
||||||
$urutanHari = ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu', 'Ahad'];
|
|
||||||
?>
|
|
||||||
|
|
||||||
<?php if($kegiatans->count() > 0): ?>
|
|
||||||
<?php $__currentLoopData = $urutanHari; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $hari): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$kegiatanHari = $kegiatanPerHari->get($hari, collect());
|
|
||||||
?>
|
|
||||||
<?php if($kegiatanHari->count() > 0): ?>
|
|
||||||
<div class="content-box" style="margin-bottom: 16px;">
|
|
||||||
<h4 style="margin: 0 0 14px; color: var(--primary-color); display: flex; align-items: center; gap: 8px;">
|
|
||||||
<i class="fas fa-calendar-day"></i> <?php echo e($hari); ?>
|
|
||||||
|
|
||||||
<span class="badge badge-primary"><?php echo e($kegiatanHari->count()); ?> kegiatan</span>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<div class="table-wrapper">
|
|
||||||
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 50px;">No</th>
|
|
||||||
<th>Nama Kegiatan</th>
|
|
||||||
<th style="width: 130px;">Waktu</th>
|
|
||||||
<th style="width: 140px;">Kategori</th>
|
|
||||||
<th>Kelas</th>
|
|
||||||
<th style="width: 100px;">Materi</th>
|
|
||||||
<th style="width: 120px; text-align: center;">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $kegiatanHari->sortBy('waktu_mulai'); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $kegiatan): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($index + 1); ?></td>
|
|
||||||
<td><strong><?php echo e($kegiatan->nama_kegiatan); ?></strong></td>
|
|
||||||
<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))); ?>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span class="badge badge-info"><?php echo e($kegiatan->kategori->nama_kategori); ?></span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($kegiatan->kelasKegiatan->isEmpty()): ?>
|
|
||||||
<span class="badge badge-secondary"><i class="fas fa-users"></i> Umum</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<?php $__currentLoopData = $kegiatan->kelasKegiatan->take(3); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kls): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<span class="badge badge-primary"><?php echo e($kls->nama_kelas); ?></span>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php if($kegiatan->kelasKegiatan->count() > 3): ?>
|
|
||||||
<span class="badge badge-light">+<?php echo e($kegiatan->kelasKegiatan->count() - 3); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td><?php echo e(Str::limit($kegiatan->materi, 30) ?: '-'); ?></td>
|
|
||||||
<td class="text-center">
|
|
||||||
<div style="display: flex; gap: 4px; justify-content: center;">
|
|
||||||
<a href="<?php echo e(route('admin.kegiatan.edit', $kegiatan)); ?>" class="btn btn-sm btn-warning" title="Edit">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.kegiatan.show', $kegiatan)); ?>" class="btn btn-sm btn-info" title="Detail">
|
|
||||||
<i class="fas fa-eye"></i>
|
|
||||||
</a>
|
|
||||||
<form action="<?php echo e(route('admin.kegiatan.destroy', $kegiatan)); ?>" method="POST"
|
|
||||||
onsubmit="return confirm('Yakin hapus kegiatan ini?');" style="display: inline;">
|
|
||||||
<?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>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
|
|
||||||
<div style="margin-top: 14px;">
|
|
||||||
<?php echo e($kegiatans->links()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-calendar-times"></i>
|
|
||||||
<h3>Belum Ada Jadwal Kegiatan</h3>
|
|
||||||
<p>Silakan tambahkan kegiatan terlebih dahulu.</p>
|
|
||||||
<a href="<?php echo e(route('admin.kegiatan.create')); ?>" class="btn btn-success">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Kegiatan
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?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/data/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -0,0 +1,417 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<?php $__env->startSection('content'); ?>
|
||||||
|
<style>
|
||||||
|
/* =====================================================
|
||||||
|
DETAIL SANTRI — Riwayat Kehadiran
|
||||||
|
===================================================== */
|
||||||
|
|
||||||
|
.ds-header { display:flex; justify-content:space-between; align-items:flex-start; gap:12px;
|
||||||
|
margin-bottom:18px; flex-wrap:wrap; }
|
||||||
|
.ds-header h2 { margin:0; font-size:1.3rem; color:var(--primary-dark); display:flex; align-items:center; gap:9px; }
|
||||||
|
|
||||||
|
/* Info santri */
|
||||||
|
.ds-info-box { background:#fff; border-radius:12px; padding:16px 20px; margin-bottom:14px;
|
||||||
|
box-shadow:0 2px 10px rgba(0,0,0,0.06); display:flex; justify-content:space-between;
|
||||||
|
align-items:center; flex-wrap:wrap; gap:12px; }
|
||||||
|
.ds-info-box h3 { margin:0 0 5px; color:var(--primary-color); font-size:1.1rem; }
|
||||||
|
.ds-info-meta { font-size:0.83rem; color:#64748b; display:flex; flex-wrap:wrap; gap:10px; }
|
||||||
|
.ds-info-meta span { display:inline-flex; align-items:center; gap:4px; }
|
||||||
|
|
||||||
|
/* KPI cards */
|
||||||
|
.ds-kpi-grid { display:grid; grid-template-columns:repeat(5,1fr); gap:10px; margin-bottom:14px; }
|
||||||
|
@media(max-width:900px) { .ds-kpi-grid { grid-template-columns:repeat(3,1fr); } }
|
||||||
|
@media(max-width:540px) { .ds-kpi-grid { grid-template-columns:repeat(2,1fr); } }
|
||||||
|
|
||||||
|
.ds-kpi { background:#fff; border-radius:10px; padding:12px 14px;
|
||||||
|
box-shadow:0 2px 8px rgba(0,0,0,0.06); display:flex; align-items:center; gap:10px; }
|
||||||
|
.ds-kpi .ico { width:36px; height:36px; border-radius:9px; display:flex; align-items:center;
|
||||||
|
justify-content:center; font-size:1.1rem; flex-shrink:0; }
|
||||||
|
.ds-kpi.hadir .ico { background:#d1fae5; color:#065f46; }
|
||||||
|
.ds-kpi.terlambat .ico { background:#fff3e0; color:#e65100; }
|
||||||
|
.ds-kpi.izin .ico { background:#fef3c7; color:#92400e; }
|
||||||
|
.ds-kpi.sakit .ico { background:#dbeafe; color:#1e40af; }
|
||||||
|
.ds-kpi.alpa .ico { background:#fee2e2; color:#991b1b; }
|
||||||
|
.ds-kpi .cnt { font-size:1.4rem; font-weight:800; color:var(--primary-dark); line-height:1; }
|
||||||
|
.ds-kpi .lbl { font-size:0.74rem; color:#94a3b8; margin-top:2px; }
|
||||||
|
|
||||||
|
/* Terlambat note */
|
||||||
|
.ds-terlambat-note { font-size:0.76rem; color:#6b7280; background:#fff7ed; border:1px solid #fed7aa;
|
||||||
|
border-radius:8px; padding:6px 12px; margin-bottom:14px;
|
||||||
|
display:flex; align-items:center; gap:6px; }
|
||||||
|
.ds-terlambat-note i { color:#ea580c; }
|
||||||
|
|
||||||
|
/* Tren chart box */
|
||||||
|
.ds-chart-box { background:#fff; border-radius:12px; padding:16px 18px; margin-bottom:14px;
|
||||||
|
box-shadow:0 2px 10px rgba(0,0,0,0.06); }
|
||||||
|
.ds-chart-box h4 { margin:0 0 14px; color:var(--primary-color); font-size:0.95rem;
|
||||||
|
display:flex; align-items:center; gap:7px; }
|
||||||
|
|
||||||
|
/* Riwayat lengkap dengan tabs */
|
||||||
|
.ds-riwayat-box { background:#fff; border-radius:12px; overflow:hidden; margin-bottom:14px;
|
||||||
|
box-shadow:0 2px 10px rgba(0,0,0,0.06); }
|
||||||
|
.ds-riwayat-head { padding:14px 18px 0; border-bottom:2px solid #f1f5f9; }
|
||||||
|
.ds-riwayat-head h4 { margin:0 0 12px; color:var(--primary-dark); font-size:0.95rem;
|
||||||
|
display:flex; align-items:center; gap:7px; }
|
||||||
|
|
||||||
|
/* Tabs */
|
||||||
|
.ds-tabs { display:flex; gap:0; overflow-x:auto; -webkit-overflow-scrolling:touch; }
|
||||||
|
.ds-tabs::-webkit-scrollbar { height:0; }
|
||||||
|
.ds-tab { padding:9px 16px; font-size:0.82rem; font-weight:600; border:none; background:transparent;
|
||||||
|
cursor:pointer; white-space:nowrap; color:#64748b; border-bottom:3px solid transparent;
|
||||||
|
transition:all 0.15s; text-decoration:none; display:inline-flex; align-items:center; gap:6px; }
|
||||||
|
.ds-tab:hover { color:var(--primary-color); background:#f0fdf4; }
|
||||||
|
.ds-tab.active { color:var(--primary-color); border-bottom-color:var(--primary-color); background:#f0fdf4; }
|
||||||
|
.ds-tab .tab-cnt { background:#e8f7f2; color:var(--primary-color); padding:1px 7px; border-radius:10px;
|
||||||
|
font-size:0.72rem; font-weight:700; }
|
||||||
|
.ds-tab.active .tab-cnt { background:var(--primary-color); color:#fff; }
|
||||||
|
.ds-tab .tab-hadir { background:#d1fae5; color:#065f46; padding:1px 7px; border-radius:10px;
|
||||||
|
font-size:0.7rem; font-weight:700; }
|
||||||
|
|
||||||
|
/* Per-page toolbar */
|
||||||
|
.ds-toolbar { display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap;
|
||||||
|
gap:8px; padding:10px 18px; background:#fafafa; border-bottom:1px solid #f1f5f9; }
|
||||||
|
.ds-toolbar-left { font-size:0.8rem; color:#64748b; }
|
||||||
|
.ds-toolbar-right { display:flex; align-items:center; gap:8px; font-size:0.8rem; color:#64748b; }
|
||||||
|
.ds-perpage-group { display:flex; gap:4px; }
|
||||||
|
.ds-pp-btn { padding:4px 10px; border:1.5px solid #e2e8f0; border-radius:6px; background:#fff;
|
||||||
|
font-size:0.78rem; font-weight:600; color:#64748b; cursor:pointer;
|
||||||
|
text-decoration:none; transition:all 0.15s; }
|
||||||
|
.ds-pp-btn:hover { border-color:var(--primary-color); color:var(--primary-color); }
|
||||||
|
.ds-pp-btn.active { background:var(--primary-color); color:#fff; border-color:var(--primary-color); }
|
||||||
|
|
||||||
|
/* Table */
|
||||||
|
.ds-table-wrap { overflow-x:auto; }
|
||||||
|
.ds-table { width:100%; border-collapse:collapse; min-width:540px; }
|
||||||
|
.ds-table thead th { padding:9px 14px; text-align:left; font-size:0.78rem; font-weight:600;
|
||||||
|
color:#64748b; background:#f8fafc; border-bottom:1px solid #e2e8f0; }
|
||||||
|
.ds-table tbody td { padding:9px 14px; font-size:0.83rem; border-bottom:1px solid #f8fafc; vertical-align:middle; }
|
||||||
|
.ds-table tbody tr:last-child td { border-bottom:none; }
|
||||||
|
.ds-table tbody tr:hover { background:#f8fafc; }
|
||||||
|
|
||||||
|
/* Status badges (inline fallback jika status_badge tidak ada) */
|
||||||
|
.s-hadir { background:#d1fae5; color:#065f46; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
||||||
|
.s-terlambat { background:#fff3e0; color:#e65100; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
||||||
|
.s-izin { background:#fef3c7; color:#92400e; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
||||||
|
.s-sakit { background:#dbeafe; color:#1e40af; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
||||||
|
.s-alpa { background:#fee2e2; color:#991b1b; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
||||||
|
.s-pulang { background:#f3e8ff; color:#6b21a8; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
||||||
|
|
||||||
|
/* Button back */
|
||||||
|
.btn-ds-back { padding:8px 16px; background:#6b7280; color:#fff; border-radius:8px; font-size:0.82rem;
|
||||||
|
font-weight:600; text-decoration:none; display:inline-flex; align-items:center; gap:6px;
|
||||||
|
transition:background 0.18s; }
|
||||||
|
.btn-ds-back:hover { background:#4b5563; color:#fff; }
|
||||||
|
|
||||||
|
/* Empty */
|
||||||
|
.ds-empty { text-align:center; padding:30px; color:#94a3b8; }
|
||||||
|
.ds-empty i { font-size:2.5rem; display:block; margin-bottom:10px; opacity:0.35; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$totalHadirEfektif = $stats['_hadir_efektif'] ?? 0;
|
||||||
|
$totalHadir = $stats['Hadir'] ?? 0;
|
||||||
|
$totalTerlambat = $stats['Terlambat'] ?? 0;
|
||||||
|
$totalIzin = $stats['Izin'] ?? 0;
|
||||||
|
$totalSakit = $stats['Sakit'] ?? 0;
|
||||||
|
$totalAlpa = $stats['Alpa'] ?? 0;
|
||||||
|
|
||||||
|
$persenHadir = ($totalHadirEfektif + $totalIzin + $totalSakit + $totalAlpa) > 0
|
||||||
|
? round($totalHadirEfektif / ($totalHadirEfektif + $totalIzin + $totalSakit + $totalAlpa) * 100, 1)
|
||||||
|
: 0;
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="ds-header">
|
||||||
|
<h2><i class="fas fa-user-clock" style="color:var(--primary-color);"></i>
|
||||||
|
Riwayat Kehadiran: <?php echo e($santri->nama_lengkap); ?>
|
||||||
|
|
||||||
|
</h2>
|
||||||
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.index')); ?>" class="btn-ds-back">
|
||||||
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="ds-info-box">
|
||||||
|
<div>
|
||||||
|
<h3><?php echo e($santri->nama_lengkap); ?></h3>
|
||||||
|
<div class="ds-info-meta">
|
||||||
|
<span><i class="fas fa-id-card"></i> <strong><?php echo e($santri->id_santri); ?></strong></span>
|
||||||
|
<span><i class="fas fa-school"></i> <?php echo e($santri->kelas); ?></span>
|
||||||
|
<span><i class="fas fa-circle" style="font-size:0.5rem; color:#22c55e;"></i>
|
||||||
|
<span class="badge badge-success" style="font-size:0.76rem;"><?php echo e($santri->status); ?></span>
|
||||||
|
</span>
|
||||||
|
<?php if($persenHadir > 0): ?>
|
||||||
|
<span style="font-weight:700; color:<?php echo e($persenHadir >= 85 ? '#059669' : ($persenHadir >= 70 ? '#d97706' : '#dc2626')); ?>;">
|
||||||
|
<i class="fas fa-chart-pie"></i> Kehadiran <?php echo e($persenHadir); ?>%
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<?php if($totalTerlambat > 0): ?>
|
||||||
|
<div class="ds-terlambat-note">
|
||||||
|
<i class="fas fa-info-circle"></i>
|
||||||
|
<strong><?php echo e($totalTerlambat); ?>x Terlambat</strong> dihitung sebagai <strong>Hadir</strong> (bukan Alpa).
|
||||||
|
Total hadir efektif: <strong><?php echo e($totalHadirEfektif); ?></strong> kali
|
||||||
|
(<?php echo e($totalHadir); ?> hadir tepat waktu + <?php echo e($totalTerlambat); ?> terlambat).
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="ds-kpi-grid">
|
||||||
|
<div class="ds-kpi hadir">
|
||||||
|
<div class="ico"><i class="fas fa-check-circle"></i></div>
|
||||||
|
<div>
|
||||||
|
<div class="cnt"><?php echo e($totalHadirEfektif); ?></div>
|
||||||
|
<div class="lbl">Hadir Efektif</div>
|
||||||
|
<?php if($totalTerlambat > 0): ?>
|
||||||
|
<div style="font-size:0.68rem; color:#94a3b8;"><?php echo e($totalHadir); ?>+<?php echo e($totalTerlambat); ?>tl</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ds-kpi terlambat">
|
||||||
|
<div class="ico"><i class="fas fa-clock"></i></div>
|
||||||
|
<div><div class="cnt"><?php echo e($totalTerlambat); ?></div><div class="lbl">Terlambat</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="ds-kpi izin">
|
||||||
|
<div class="ico"><i class="fas fa-envelope"></i></div>
|
||||||
|
<div><div class="cnt"><?php echo e($totalIzin); ?></div><div class="lbl">Izin</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="ds-kpi sakit">
|
||||||
|
<div class="ico"><i class="fas fa-heartbeat"></i></div>
|
||||||
|
<div><div class="cnt"><?php echo e($totalSakit); ?></div><div class="lbl">Sakit</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="ds-kpi alpa">
|
||||||
|
<div class="ico"><i class="fas fa-times-circle"></i></div>
|
||||||
|
<div><div class="cnt"><?php echo e($totalAlpa); ?></div><div class="lbl">Alpa</div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<?php if($riwayat30Hari->count() > 0): ?>
|
||||||
|
<div class="ds-chart-box">
|
||||||
|
<h4><i class="fas fa-chart-line"></i> Tren Kehadiran 30 Hari Terakhir
|
||||||
|
<span style="font-size:0.76rem; font-weight:400; color:#94a3b8; margin-left:4px;">
|
||||||
|
(Hadir + Terlambat)
|
||||||
|
</span>
|
||||||
|
</h4>
|
||||||
|
<canvas id="chartTren" style="max-height:220px;"></canvas>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="ds-riwayat-box">
|
||||||
|
<div class="ds-riwayat-head">
|
||||||
|
<h4><i class="fas fa-list-alt" style="color:var(--primary-color);"></i> Riwayat Lengkap per Kategori</h4>
|
||||||
|
|
||||||
|
<?php if($kategoriList->count() > 0): ?>
|
||||||
|
|
||||||
|
<div class="ds-tabs" role="tablist">
|
||||||
|
<?php $__currentLoopData = $kategoriList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kat): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<?php
|
||||||
|
$tabParams = array_merge(request()->query(), [
|
||||||
|
'tab_kat' => $kat->kategori_id,
|
||||||
|
'per_page' => $perPage,
|
||||||
|
'page' => 1,
|
||||||
|
]);
|
||||||
|
$isActive = ($activeKategori == $kat->kategori_id);
|
||||||
|
$pctKat = $kat->total > 0 ? round($kat->hadir_efektif / $kat->total * 100) : 0;
|
||||||
|
?>
|
||||||
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.detail-santri', $santri->id_santri)); ?>?<?php echo e(http_build_query($tabParams)); ?>"
|
||||||
|
class="ds-tab <?php echo e($isActive ? 'active' : ''); ?>"
|
||||||
|
role="tab">
|
||||||
|
<i class="fas fa-tag" style="font-size:0.72rem;"></i>
|
||||||
|
<?php echo e($kat->nama_kategori); ?>
|
||||||
|
|
||||||
|
<span class="tab-cnt"><?php echo e($kat->total); ?></span>
|
||||||
|
<?php if($kat->hadir_efektif > 0): ?>
|
||||||
|
<span class="tab-hadir" title="Hadir efektif"><?php echo e($pctKat); ?>%</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</a>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if($riwayats->count() > 0): ?>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="ds-toolbar">
|
||||||
|
<div class="ds-toolbar-left">
|
||||||
|
<?php if(!$showAll): ?>
|
||||||
|
Menampilkan
|
||||||
|
<strong><?php echo e($riwayats->firstItem()); ?>–<?php echo e($riwayats->lastItem()); ?></strong>
|
||||||
|
dari <strong><?php echo e($riwayats->total()); ?></strong> riwayat
|
||||||
|
<?php else: ?>
|
||||||
|
Menampilkan <strong>semua <?php echo e($riwayats->total()); ?></strong> riwayat
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php $activeKat = $kategoriList->firstWhere('kategori_id', $activeKategori); ?>
|
||||||
|
<?php if($activeKat): ?>
|
||||||
|
— <span style="color:var(--primary-color); font-weight:600;"><?php echo e($activeKat->nama_kategori); ?></span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<div class="ds-toolbar-right">
|
||||||
|
Tampilkan:
|
||||||
|
<div class="ds-perpage-group">
|
||||||
|
<?php $__currentLoopData = [15, 50, 100]; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $pp): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<?php $ppParams = array_merge(request()->query(), ['per_page' => $pp, 'page' => 1]); ?>
|
||||||
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.detail-santri', $santri->id_santri)); ?>?<?php echo e(http_build_query($ppParams)); ?>"
|
||||||
|
class="ds-pp-btn <?php echo e((!$showAll && $perPage == $pp) ? 'active' : ''); ?>">
|
||||||
|
<?php echo e($pp); ?>
|
||||||
|
|
||||||
|
</a>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
|
||||||
|
<?php $allParams = array_merge(request()->query(), ['per_page' => 'all', 'page' => 1]); ?>
|
||||||
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.detail-santri', $santri->id_santri)); ?>?<?php echo e(http_build_query($allParams)); ?>"
|
||||||
|
class="ds-pp-btn <?php echo e($showAll ? 'active' : ''); ?>"
|
||||||
|
title="Tampilkan semua data sekaligus (bisa lambat jika data banyak)">
|
||||||
|
Semua
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="ds-table-wrap">
|
||||||
|
<table class="ds-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width:50px;">No</th>
|
||||||
|
<th style="width:110px;">Tanggal</th>
|
||||||
|
<th>Nama Kegiatan</th>
|
||||||
|
<th style="width:115px; text-align:center;">Status</th>
|
||||||
|
<th style="width:90px; text-align:center;">Waktu</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php $__currentLoopData = $riwayats; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $idx => $riwayat): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<tr>
|
||||||
|
<td style="color:#94a3b8; font-size:0.78rem;"><?php echo e($riwayats->firstItem() + $idx); ?></td>
|
||||||
|
<td style="font-size:0.81rem; color:#64748b;">
|
||||||
|
<?php echo e($riwayat->tanggal->format('d/m/Y')); ?>
|
||||||
|
|
||||||
|
<div style="font-size:0.71rem; color:#94a3b8;">
|
||||||
|
<?php echo e($riwayat->tanggal->locale('id')->isoFormat('ddd')); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong style="font-size:0.85rem;"><?php echo e($riwayat->kegiatan->nama_kegiatan); ?></strong>
|
||||||
|
<div style="font-size:0.74rem; color:#94a3b8; margin-top:1px;">
|
||||||
|
<i class="fas fa-clock"></i>
|
||||||
|
<?php echo e(date('H:i', strtotime($riwayat->kegiatan->waktu_mulai))); ?>–<?php echo e(date('H:i', strtotime($riwayat->kegiatan->waktu_selesai))); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td style="text-align:center;">
|
||||||
|
<?php if(method_exists($riwayat, 'getStatusBadgeAttribute') || isset($riwayat->status_badge)): ?>
|
||||||
|
<?php echo $riwayat->status_badge; ?>
|
||||||
|
|
||||||
|
<?php else: ?>
|
||||||
|
<?php $st = $riwayat->status; ?>
|
||||||
|
<span class="s-<?php echo e(strtolower($st)); ?>"><?php echo e($st); ?></span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td style="text-align:center; font-size:0.81rem; color:#64748b;">
|
||||||
|
<?php echo e($riwayat->waktu_absen ? date('H:i', strtotime($riwayat->waktu_absen)) : '–'); ?>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<?php if(!$showAll && $riwayats->lastPage() > 1): ?>
|
||||||
|
<div style="padding:12px 16px;">
|
||||||
|
<?php echo e($riwayats->links()); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<?php elseif($showAll): ?>
|
||||||
|
<div style="padding:10px 16px; font-size:0.78rem; color:#94a3b8; background:#fafafa; border-top:1px solid #f1f5f9;">
|
||||||
|
<i class="fas fa-info-circle"></i> Semua <strong><?php echo e($riwayats->total()); ?></strong> data ditampilkan.
|
||||||
|
|
||||||
|
<?php $backPaged = array_merge(request()->query(), ['per_page' => 15, 'page' => 1]); ?>
|
||||||
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.detail-santri', $santri->id_santri)); ?>?<?php echo e(http_build_query($backPaged)); ?>"
|
||||||
|
style="color:var(--primary-color);">Kembali ke paginasi</a>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php elseif($kategoriList->count() > 0): ?>
|
||||||
|
<div class="ds-empty">
|
||||||
|
<i class="fas fa-inbox"></i>
|
||||||
|
<p>Belum ada riwayat untuk kategori ini.</p>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="ds-empty">
|
||||||
|
<i class="fas fa-inbox"></i>
|
||||||
|
<p>Santri ini belum memiliki riwayat kehadiran apapun.</p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<?php if($riwayat30Hari->count() > 0): ?>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
var ctx = document.getElementById('chartTren');
|
||||||
|
if (!ctx) return;
|
||||||
|
|
||||||
|
var labels = <?php echo json_encode($riwayat30Hari->pluck('tanggal')->map(fn($d) => date('d/m', strtotime($d)))); ?>;
|
||||||
|
var hadir = <?php echo json_encode($riwayat30Hari->pluck('hadir')); ?>;
|
||||||
|
var total = <?php echo json_encode($riwayat30Hari->pluck('total')); ?>;
|
||||||
|
|
||||||
|
new Chart(ctx, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: labels,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Hadir (termasuk terlambat)',
|
||||||
|
data: hadir,
|
||||||
|
borderColor: '#6FBA9D',
|
||||||
|
backgroundColor: 'rgba(111,186,157,0.12)',
|
||||||
|
tension: 0.4,
|
||||||
|
fill: true,
|
||||||
|
pointRadius: 4,
|
||||||
|
pointBackgroundColor: '#6FBA9D',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Total Kegiatan',
|
||||||
|
data: total,
|
||||||
|
borderColor: '#cbd5e1',
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderDash: [5, 5],
|
||||||
|
tension: 0.4,
|
||||||
|
fill: false,
|
||||||
|
pointRadius: 0,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: true,
|
||||||
|
interaction: { mode: 'index', intersect: false },
|
||||||
|
plugins: {
|
||||||
|
legend: { position: 'bottom', labels: { boxWidth: 12, font: { size: 11 } } }
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
y: { beginAtZero: true, ticks: { stepSize: 1 }, grid: { color: '#f1f5f9' } },
|
||||||
|
x: { grid: { display: false }, ticks: { font: { size: 10 } } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</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/detail-santri.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Klasifikasi Pelanggaran'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-tags"></i> Klasifikasi Pelanggaran</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="display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px;">
|
|
||||||
<h3 style="margin: 0; color: var(--primary-color);">
|
|
||||||
<i class="fas fa-list"></i> Daftar Klasifikasi
|
|
||||||
</h3>
|
|
||||||
<div style="display: flex; gap: 10px;">
|
|
||||||
<a href="<?php echo e(route('admin.kategori-pelanggaran.index')); ?>" class="btn btn-info">
|
|
||||||
<i class="fas fa-list-ul"></i> Kategori Pelanggaran
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.klasifikasi-pelanggaran.create')); ?>" class="btn btn-primary">
|
|
||||||
<i class="fas fa-plus-circle"></i> Tambah Klasifikasi
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($data->isNotEmpty()): ?>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 50px;">No</th>
|
|
||||||
<th style="width: 100px;">ID</th>
|
|
||||||
<th>Nama Klasifikasi</th>
|
|
||||||
<th style="width: 120px; text-align: center;">Jumlah Pelanggaran</th>
|
|
||||||
<th style="width: 80px; text-align: center;">Urutan</th>
|
|
||||||
<th style="width: 100px; text-align: center;">Status</th>
|
|
||||||
<th style="width: 200px; text-align: center;">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $data; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($index + 1); ?></td>
|
|
||||||
<td><span class="badge badge-primary"><?php echo e($item->id_klasifikasi); ?></span></td>
|
|
||||||
<td>
|
|
||||||
<strong><?php echo e($item->nama_klasifikasi); ?></strong>
|
|
||||||
<?php if($item->deskripsi): ?>
|
|
||||||
<br><small style="color: var(--text-light);"><?php echo e(Str::limit($item->deskripsi, 80)); ?></small>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<span class="badge badge-info"><?php echo e($item->pelanggarans_count); ?></span>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;"><?php echo e($item->urutan); ?></td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<?php if($item->is_active): ?>
|
|
||||||
<span class="badge badge-success">Aktif</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="badge badge-secondary">Nonaktif</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<div style="display: flex; justify-content: center; gap: 8px;">
|
|
||||||
<a href="<?php echo e(route('admin.klasifikasi-pelanggaran.show', $item)); ?>"
|
|
||||||
class="btn btn-sm btn-success"
|
|
||||||
title="Detail">
|
|
||||||
<i class="fas fa-eye"></i>
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.klasifikasi-pelanggaran.edit', $item)); ?>"
|
|
||||||
class="btn btn-sm btn-warning"
|
|
||||||
title="Edit">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
<form action="<?php echo e(route('admin.klasifikasi-pelanggaran.destroy', $item)); ?>"
|
|
||||||
method="POST"
|
|
||||||
style="display: inline;"
|
|
||||||
onsubmit="return confirm('Yakin ingin menghapus?');">
|
|
||||||
<?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>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-folder-open"></i>
|
|
||||||
<h3>Belum ada klasifikasi</h3>
|
|
||||||
<p>Mulai dengan menambahkan klasifikasi pelanggaran.</p>
|
|
||||||
<a href="<?php echo e(route('admin.klasifikasi-pelanggaran.create')); ?>" class="btn btn-primary">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Klasifikasi
|
|
||||||
</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/klasifikasi_pelanggaran/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,600 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<?php
|
|
||||||
// -- Day-tab calculations --
|
|
||||||
$isoDay = $selectedDate->dayOfWeekIso;
|
|
||||||
$monOfWeek = $selectedDate->copy()->subDays($isoDay - 1);
|
|
||||||
$hariMapTab = [
|
|
||||||
'Senin' => 'Senin','Selasa' => 'Selasa','Rabu' => 'Rabu',
|
|
||||||
'Kamis' => 'Kamis','Jumat' => 'Jumat','Sabtu' => 'Sabtu','Minggu' => 'Ahad'
|
|
||||||
];
|
|
||||||
$activeTab = $hariMapTab[$selectedDate->locale('id')->isoFormat('dddd')] ?? 'Senin';
|
|
||||||
$todayHari = $hariMapTab[now()->locale('id')->isoFormat('dddd')] ?? 'Senin';
|
|
||||||
|
|
||||||
$tabHari = [
|
|
||||||
['nama' => 'Senin', 'offset' => 0],
|
|
||||||
['nama' => 'Selasa', 'offset' => 1],
|
|
||||||
['nama' => 'Rabu', 'offset' => 2],
|
|
||||||
['nama' => 'Kamis', 'offset' => 3],
|
|
||||||
['nama' => 'Jumat', 'offset' => 4],
|
|
||||||
['nama' => 'Sabtu', 'offset' => 5],
|
|
||||||
['nama' => 'Minggu', 'offset' => 6],
|
|
||||||
];
|
|
||||||
|
|
||||||
$kelompokGroups = $kelasList->groupBy('kelompok.nama_kelompok');
|
|
||||||
?>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="page-header" style="display:flex; align-items:center; justify-content:space-between;">
|
|
||||||
<h2><i class="fas fa-tachometer-alt"></i> Dashboard Absensi</h2>
|
|
||||||
|
|
||||||
<div style="display:flex; gap:8px;">
|
|
||||||
<a href="<?php echo e(route('admin.mesin.mapping-santri.index')); ?>"
|
|
||||||
class="btn btn-sm btn-secondary">
|
|
||||||
<i class="fas fa-link"></i> Mapping Fingerprint
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.mesin.import.index')); ?>"
|
|
||||||
class="btn btn-sm btn-success"
|
|
||||||
style="background:#0F7B6C; border-color:#0F7B6C;">
|
|
||||||
<i class="fas fa-file-import"></i> Import
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p style="color: var(--text-light); margin-top: 5px; margin-bottom: 14px;">
|
|
||||||
<?php echo e($selectedDate->locale('id')->isoFormat('dddd, D MMMM Y')); ?>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<?php if(session('success')): ?>
|
|
||||||
<div class="alert alert-success">
|
|
||||||
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kpi-grid-kegiatan">
|
|
||||||
<div class="kpi-kegiatan bg-primary">
|
|
||||||
<i class="fas fa-calendar-day kpi-icon"></i>
|
|
||||||
<div class="kpi-value"><?php echo e($totalKegiatanHariIni); ?></div>
|
|
||||||
<div class="kpi-label">Total Kegiatan</div>
|
|
||||||
<div class="kpi-sub">
|
|
||||||
<i class="fas fa-<?php echo e($comparisonTotal >= 0 ? 'arrow-up' : 'arrow-down'); ?>"></i>
|
|
||||||
<?php echo e(abs($comparisonTotal)); ?> vs minggu lalu
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="kpi-kegiatan bg-success">
|
|
||||||
<i class="fas fa-check-circle kpi-icon"></i>
|
|
||||||
<div class="kpi-value"><?php echo e($kegiatanSelesai); ?></div>
|
|
||||||
<div class="kpi-label">Kegiatan Selesai</div>
|
|
||||||
<div class="kpi-sub">dari <?php echo e($totalKegiatanHariIni); ?> kegiatan</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="kpi-kegiatan bg-warning">
|
|
||||||
<i class="fas fa-chart-line kpi-icon"></i>
|
|
||||||
<div class="kpi-value"><?php echo e($avgKehadiran); ?>%</div>
|
|
||||||
<div class="kpi-label">Rata-rata Kehadiran</div>
|
|
||||||
<div class="kpi-sub">
|
|
||||||
<i class="fas fa-<?php echo e($comparisonAvg >= 0 ? 'arrow-up' : 'arrow-down'); ?>"></i>
|
|
||||||
<?php echo e(abs($comparisonAvg)); ?>% vs minggu lalu
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="kpi-kegiatan bg-info">
|
|
||||||
<i class="fas fa-clock kpi-icon"></i>
|
|
||||||
<div class="kpi-value"><?php echo e($kegiatanBerlangsung); ?></div>
|
|
||||||
<div class="kpi-label">Sedang Berlangsung</div>
|
|
||||||
<?php if($kegiatanBerlangsung > 0): ?>
|
|
||||||
<div class="kpi-sub"><i class="fas fa-circle" style="color: #90ee90;"></i> Live Now</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="kpi-sub">Tidak ada kegiatan</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<div class="day-tabs">
|
|
||||||
<?php $__currentLoopData = $tabHari; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $tab): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$tabDate = $monOfWeek->copy()->addDays($tab['offset']);
|
|
||||||
$tabDateStr = $tabDate->format('Y-m-d');
|
|
||||||
$isActive = ($activeTab === $tab['nama']);
|
|
||||||
$isToday = ($todayHari === $tab['nama'] && now()->format('W') === $selectedDate->format('W'));
|
|
||||||
$params = array_merge(
|
|
||||||
request()->only(['kelas', 'kategori_id']),
|
|
||||||
['tanggal' => $tabDateStr]
|
|
||||||
);
|
|
||||||
?>
|
|
||||||
<a href="<?php echo e(route('admin.kegiatan.index', $params)); ?>"
|
|
||||||
class="day-tab <?php echo e($isActive ? 'active' : ''); ?> <?php echo e($isToday ? 'today-tab' : ''); ?>">
|
|
||||||
<span class="day-name"><?php echo e($tab['nama']); ?></span>
|
|
||||||
<span class="day-date"><?php echo e($tabDate->format('d/m')); ?></span>
|
|
||||||
</a>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.kegiatan.index')); ?>" id="filterForm" class="filter-form-inline" style="margin-top: 10px;">
|
|
||||||
<input type="hidden" name="kelas" id="kelasInput" value="<?php echo e($selectedKelasId); ?>">
|
|
||||||
|
|
||||||
<div class="filter-form-inline" style="gap: 8px;">
|
|
||||||
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
|
||||||
<i class="fas fa-calendar"></i> Tanggal:
|
|
||||||
</label>
|
|
||||||
<input type="date" name="tanggal" class="form-control"
|
|
||||||
value="<?php echo e($selectedDate->format('Y-m-d')); ?>"
|
|
||||||
onchange="this.form.submit()" style="max-width: 170px;">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="filter-form-inline" style="gap: 8px;">
|
|
||||||
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
|
||||||
<i class="fas fa-tags"></i> Kategori:
|
|
||||||
</label>
|
|
||||||
<select name="kategori_id" class="form-control" onchange="this.form.submit()" style="max-width: 180px;">
|
|
||||||
<option value="">Semua 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(request('kategori_id') == $kat->kategori_id ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($kat->nama_kategori); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="filter-form-inline" style="gap: 8px;">
|
|
||||||
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
|
||||||
<i class="fas fa-school"></i> Kelas:
|
|
||||||
</label>
|
|
||||||
<select name="kelas" class="form-control" onchange="this.form.submit()" style="max-width: 200px;">
|
|
||||||
<option value="">Semua Kelas</option>
|
|
||||||
<option value="umum" <?php echo e($selectedKelasId === 'umum' ? 'selected' : ''); ?>>Kegiatan Umum</option>
|
|
||||||
<?php $__currentLoopData = $kelompokGroups; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelompokNama => $kelasGroup): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<optgroup label="<?php echo e($kelompokNama); ?>">
|
|
||||||
<?php $__currentLoopData = $kelasGroup; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($kelas->id); ?>" <?php echo e($selectedKelasId == $kelas->id ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($kelas->nama_kelas); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</optgroup>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-sm btn-primary" onclick="setToday()">
|
|
||||||
<i class="fas fa-calendar-day"></i> Hari Ini
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-secondary" onclick="prevDay()">
|
|
||||||
<i class="fas fa-chevron-left"></i>
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-secondary" onclick="nextDay()">
|
|
||||||
<i class="fas fa-chevron-right"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php if(count($insights) > 0): ?>
|
|
||||||
<div class="content-box" style="margin-top: 14px;">
|
|
||||||
<h4 style="margin: 0 0 12px; color: var(--primary-color);">
|
|
||||||
<i class="fas fa-lightbulb"></i> Insight Hari Ini
|
|
||||||
</h4>
|
|
||||||
<?php $__currentLoopData = $insights; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $insight): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div class="insight-item <?php echo e($insight['type']); ?>">
|
|
||||||
<div class="insight-content">
|
|
||||||
<div class="insight-message">
|
|
||||||
<i class="fas fa-<?php echo e($insight['icon']); ?>"></i> <?php echo e($insight['message']); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="insight-detail"><?php echo e($insight['detail']); ?></div>
|
|
||||||
</div>
|
|
||||||
<?php if($insight['action_url']): ?>
|
|
||||||
<a href="<?php echo e($insight['action_url']); ?>" class="btn btn-sm btn-<?php echo e($insight['type']); ?>">
|
|
||||||
<?php echo e($insight['action_text']); ?>
|
|
||||||
|
|
||||||
</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="layout-kegiatan" style="margin-top: 14px;">
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<?php if($kegiatanHariIni->count() > 0): ?>
|
|
||||||
<div class="kegiatan-list">
|
|
||||||
<?php $__currentLoopData = $kegiatanHariIni; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kegiatan): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div class="kegiatan-card">
|
|
||||||
<div class="kegiatan-card-header">
|
|
||||||
<div class="kegiatan-info">
|
|
||||||
<h3 class="kegiatan-title">
|
|
||||||
<i class="fas fa-calendar" style="color: var(--primary-color);"></i>
|
|
||||||
<?php echo e($kegiatan->nama_kegiatan); ?>
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
<div class="kegiatan-meta">
|
|
||||||
<span>
|
|
||||||
<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))); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<span class="badge badge-info">
|
|
||||||
<i class="fas fa-tag"></i>
|
|
||||||
<?php echo e($kegiatan->kategori->nama_kategori); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<?php if($kegiatan->materi): ?>
|
|
||||||
<span>
|
|
||||||
<i class="fas fa-book"></i>
|
|
||||||
<?php echo e(Str::limit($kegiatan->materi, 40)); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<span>
|
|
||||||
<i class="fas fa-layer-group"></i>
|
|
||||||
<?php if($kegiatan->kelasKegiatan->isEmpty()): ?>
|
|
||||||
<span class="badge badge-secondary">Kegiatan Umum</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<?php echo e($kegiatan->kelasKegiatan->pluck('nama_kelas')->implode(', ')); ?>
|
|
||||||
|
|
||||||
<?php endif; ?>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span class="status-badge status-<?php echo e($kegiatan->status_kegiatan); ?>">
|
|
||||||
<?php if($kegiatan->status_kegiatan == 'belum'): ?>
|
|
||||||
<i class="fas fa-hourglass-start"></i> Belum Dimulai
|
|
||||||
<?php elseif($kegiatan->status_kegiatan == 'berlangsung'): ?>
|
|
||||||
<i class="fas fa-play-circle"></i> Berlangsung
|
|
||||||
<?php else: ?>
|
|
||||||
<i class="fas fa-check-circle"></i> Selesai
|
|
||||||
<?php endif; ?>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$persen = $kegiatan->persen_kehadiran;
|
|
||||||
$pClass = $persen >= 85 ? 'p-success' : ($persen >= 70 ? 'p-warning' : ($persen >= 50 ? 'p-orange' : 'p-danger'));
|
|
||||||
$denominator = $kegiatan->total_absensi > 0 ? $kegiatan->total_absensi : $totalSantriAktif;
|
|
||||||
?>
|
|
||||||
<div class="kegiatan-progress">
|
|
||||||
<div class="kegiatan-progress-header">
|
|
||||||
<span style="font-weight: 500;">
|
|
||||||
<i class="fas fa-users"></i> Kehadiran
|
|
||||||
</span>
|
|
||||||
<span style="font-weight: 700;">
|
|
||||||
<?php echo e($kegiatan->total_hadir); ?>/<?php echo e($denominator); ?>
|
|
||||||
|
|
||||||
(<?php echo e($persen); ?>%)
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="kegiatan-progress-bar">
|
|
||||||
<div class="kegiatan-progress-fill <?php echo e($pClass); ?>"
|
|
||||||
data-width="<?php echo e($persen); ?>">
|
|
||||||
<?php echo e($persen); ?>%
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kegiatan-actions">
|
|
||||||
<a href="<?php echo e(route('admin.absensi-kegiatan.input', $kegiatan->kegiatan_id)); ?>?tanggal=<?php echo e($selectedDate->format('Y-m-d')); ?>"
|
|
||||||
class="btn btn-sm btn-primary">
|
|
||||||
<i class="fas fa-clipboard-check"></i> Input Absensi
|
|
||||||
</a>
|
|
||||||
<button type="button" class="btn btn-sm btn-info"
|
|
||||||
data-id="<?php echo e($kegiatan->kegiatan_id); ?>"
|
|
||||||
data-tanggal="<?php echo e($selectedDate->format('Y-m-d')); ?>"
|
|
||||||
onclick="showDetailModal(this.getAttribute('data-id'), this.getAttribute('data-tanggal'))">
|
|
||||||
<i class="fas fa-eye"></i> Lihat Detail
|
|
||||||
</button>
|
|
||||||
<a href="<?php echo e(route('admin.absensi-kegiatan.rekap', $kegiatan->kegiatan_id)); ?>?tanggal=<?php echo e($selectedDate->format('Y-m-d')); ?>"
|
|
||||||
class="btn btn-sm btn-secondary">
|
|
||||||
<i class="fas fa-chart-bar"></i> Rekap
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-calendar-times"></i>
|
|
||||||
<h3>Tidak Ada Kegiatan Dijadwalkan</h3>
|
|
||||||
<p>Tidak ada kegiatan untuk
|
|
||||||
<?php echo e($selectedKelasId ? 'kelas ini' : 'hari ini'); ?>
|
|
||||||
|
|
||||||
pada <?php echo e($selectedDate->locale('id')->isoFormat('dddd, D MMMM Y')); ?>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
<a href="<?php echo e(route('admin.kegiatan.create')); ?>" class="btn btn-success">
|
|
||||||
<i class="fas fa-plus"></i> Buat Kegiatan Baru
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div class="heatmap-calendar">
|
|
||||||
<div class="heatmap-header">
|
|
||||||
<i class="fas fa-calendar-alt"></i>
|
|
||||||
<span>Kalender Kehadiran</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="filter-form-inline" style="margin-bottom: 12px;">
|
|
||||||
<button type="button" class="btn btn-sm btn-secondary" style="padding: 4px 8px;"
|
|
||||||
onclick="changeHeatmapMonth(-1)">
|
|
||||||
<i class="fas fa-chevron-left"></i>
|
|
||||||
</button>
|
|
||||||
<select id="heatmapMonth" onchange="updateHeatmap()" class="form-control" style="flex: 1;">
|
|
||||||
<?php for($m = 1; $m <= 12; $m++): ?>
|
|
||||||
<option value="<?php echo e($m); ?>" <?php echo e($m == now()->month ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e(\Carbon\Carbon::create(null, $m, 1)->locale('id')->isoFormat('MMMM')); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endfor; ?>
|
|
||||||
</select>
|
|
||||||
<select id="heatmapYear" onchange="updateHeatmap()" class="form-control" style="width: 80px;">
|
|
||||||
<?php for($y = now()->year - 2; $y <= now()->year + 1; $y++): ?>
|
|
||||||
<option value="<?php echo e($y); ?>" <?php echo e($y == now()->year ? 'selected' : ''); ?>><?php echo e($y); ?></option>
|
|
||||||
<?php endfor; ?>
|
|
||||||
</select>
|
|
||||||
<button type="button" class="btn btn-sm btn-secondary" style="padding: 4px 8px;"
|
|
||||||
onclick="changeHeatmapMonth(1)">
|
|
||||||
<i class="fas fa-chevron-right"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="text-align: center; font-weight: 600; color: var(--primary-color); margin-bottom: 10px;"
|
|
||||||
id="heatmapMonthName">
|
|
||||||
<?php echo e(now()->locale('id')->isoFormat('MMMM Y')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="heatmap-days">
|
|
||||||
<div class="heatmap-day-label">Sen</div>
|
|
||||||
<div class="heatmap-day-label">Sel</div>
|
|
||||||
<div class="heatmap-day-label">Rab</div>
|
|
||||||
<div class="heatmap-day-label">Kam</div>
|
|
||||||
<div class="heatmap-day-label">Jum</div>
|
|
||||||
<div class="heatmap-day-label">Sab</div>
|
|
||||||
<div class="heatmap-day-label">Ahd</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="heatmap-grid" id="heatmapGrid">
|
|
||||||
<?php $__currentLoopData = $heatmapData; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $day): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div class="heatmap-cell heatmap-level-<?php echo e($day['level']); ?> <?php echo e($day['is_today'] ? 'today' : ''); ?>"
|
|
||||||
data-date="<?php echo e($day['date']); ?>"
|
|
||||||
data-percentage="<?php echo e($day['percentage']); ?>"
|
|
||||||
title="<?php echo e(\Carbon\Carbon::parse($day['date'])->locale('id')->isoFormat('dddd, D MMM Y')); ?>: <?php echo e($day['percentage']); ?>%">
|
|
||||||
<?php echo e(\Carbon\Carbon::parse($day['date'])->format('j')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="heatmap-legend">
|
|
||||||
<div class="heatmap-legend-title">Legend:</div>
|
|
||||||
<div class="heatmap-legend-items">
|
|
||||||
<div class="heatmap-legend-item">
|
|
||||||
<div class="heatmap-legend-box heatmap-level-4"></div>
|
|
||||||
<span>>90%</span>
|
|
||||||
</div>
|
|
||||||
<div class="heatmap-legend-item">
|
|
||||||
<div class="heatmap-legend-box heatmap-level-3"></div>
|
|
||||||
<span>80-90%</span>
|
|
||||||
</div>
|
|
||||||
<div class="heatmap-legend-item">
|
|
||||||
<div class="heatmap-legend-box heatmap-level-2"></div>
|
|
||||||
<span>70-80%</span>
|
|
||||||
</div>
|
|
||||||
<div class="heatmap-legend-item">
|
|
||||||
<div class="heatmap-legend-box heatmap-level-1"></div>
|
|
||||||
<span><70%</span>
|
|
||||||
</div>
|
|
||||||
<div class="heatmap-legend-item">
|
|
||||||
<div class="heatmap-legend-box heatmap-level-0"></div>
|
|
||||||
<span>No data</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="detailModal" class="modal-kegiatan">
|
|
||||||
<div class="modal-kegiatan-panel">
|
|
||||||
<div class="modal-kegiatan-head">
|
|
||||||
<h3><i class="fas fa-info-circle"></i> Detail Absensi Kegiatan</h3>
|
|
||||||
<button class="modal-kegiatan-close" onclick="closeModal()">×</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-kegiatan-body" id="modalBody">
|
|
||||||
<div style="text-align: center; padding: 22px;">
|
|
||||||
<i class="fas fa-spinner fa-spin" style="font-size: 2rem; color: var(--primary-color);"></i>
|
|
||||||
<p style="margin-top: 10px;">Memuat data...</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// -- Date Navigation --
|
|
||||||
function setToday() {
|
|
||||||
var dateInput = document.querySelector('input[name="tanggal"]');
|
|
||||||
var now = new Date();
|
|
||||||
var y = now.getFullYear();
|
|
||||||
var m = ('0' + (now.getMonth() + 1)).slice(-2);
|
|
||||||
var d = ('0' + now.getDate()).slice(-2);
|
|
||||||
dateInput.value = y + '-' + m + '-' + d;
|
|
||||||
document.getElementById('filterForm').submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
function prevDay() {
|
|
||||||
var currentDate = new Date('<?php echo e($selectedDate->format("Y-m-d")); ?>');
|
|
||||||
currentDate.setDate(currentDate.getDate() - 1);
|
|
||||||
document.querySelector('input[name="tanggal"]').value = currentDate.toISOString().split('T')[0];
|
|
||||||
document.getElementById('filterForm').submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
function nextDay() {
|
|
||||||
var currentDate = new Date('<?php echo e($selectedDate->format("Y-m-d")); ?>');
|
|
||||||
currentDate.setDate(currentDate.getDate() + 1);
|
|
||||||
document.querySelector('input[name="tanggal"]').value = currentDate.toISOString().split('T')[0];
|
|
||||||
document.getElementById('filterForm').submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
function goToDate(date) {
|
|
||||||
document.querySelector('input[name="tanggal"]').value = date;
|
|
||||||
document.getElementById('filterForm').submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Show Detail Modal (AJAX) --
|
|
||||||
function showDetailModal(kegiatanId, tanggal) {
|
|
||||||
var modal = document.getElementById('detailModal');
|
|
||||||
var modalBody = document.getElementById('modalBody');
|
|
||||||
modal.classList.add('active');
|
|
||||||
|
|
||||||
var baseUrl = '<?php echo e(route("admin.kegiatan.detail-modal", ":id")); ?>';
|
|
||||||
var url = baseUrl.replace(':id', kegiatanId) + '?tanggal=' + tanggal;
|
|
||||||
|
|
||||||
fetch(url)
|
|
||||||
.then(function(response) { return response.text(); })
|
|
||||||
.then(function(html) { modalBody.innerHTML = html; })
|
|
||||||
.catch(function() {
|
|
||||||
modalBody.innerHTML =
|
|
||||||
'<div style="text-align:center;padding:22px;">' +
|
|
||||||
'<i class="fas fa-exclamation-circle" style="font-size:2.2rem;color:var(--danger-color);"></i>' +
|
|
||||||
'<h4 style="margin:20px 0 10px;color:var(--danger-color);">Gagal Memuat Data</h4>' +
|
|
||||||
'<p style="color:var(--text-light);">Terjadi kesalahan saat memuat detail absensi.</p>' +
|
|
||||||
'<button class="btn btn-primary" onclick="closeModal()">Tutup</button>' +
|
|
||||||
'</div>';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeModal() {
|
|
||||||
document.getElementById('detailModal').classList.remove('active');
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Close modal on backdrop / Escape --
|
|
||||||
window.onclick = function(event) {
|
|
||||||
var modal = document.getElementById('detailModal');
|
|
||||||
if (event.target === modal) { closeModal(); }
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', function(event) {
|
|
||||||
if (event.key === 'Escape') { closeModal(); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// -- Progress bar width animation --
|
|
||||||
document.querySelectorAll('.kegiatan-progress-fill[data-width]').forEach(function(el) {
|
|
||||||
el.style.width = el.getAttribute('data-width') + '%';
|
|
||||||
});
|
|
||||||
|
|
||||||
// -- Heatmap: delegated click for cells --
|
|
||||||
document.getElementById('heatmapGrid').addEventListener('click', function(e) {
|
|
||||||
var cell = e.target.closest('.heatmap-cell');
|
|
||||||
if (cell && cell.dataset.date) {
|
|
||||||
goToDate(cell.dataset.date);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// -- Heatmap: month navigation --
|
|
||||||
function changeHeatmapMonth(delta) {
|
|
||||||
var monthSelect = document.getElementById('heatmapMonth');
|
|
||||||
var yearSelect = document.getElementById('heatmapYear');
|
|
||||||
var month = parseInt(monthSelect.value) + delta;
|
|
||||||
var year = parseInt(yearSelect.value);
|
|
||||||
|
|
||||||
if (month > 12) { month = 1; year++; }
|
|
||||||
else if (month < 1) { month = 12; year--; }
|
|
||||||
|
|
||||||
monthSelect.value = month;
|
|
||||||
yearSelect.value = year;
|
|
||||||
updateHeatmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Heatmap: AJAX reload --
|
|
||||||
function updateHeatmap() {
|
|
||||||
var month = document.getElementById('heatmapMonth').value;
|
|
||||||
var year = document.getElementById('heatmapYear').value;
|
|
||||||
var kelasId = document.getElementById('kelasInput').value;
|
|
||||||
|
|
||||||
var monthNames = [
|
|
||||||
'Januari','Februari','Maret','April','Mei','Juni',
|
|
||||||
'Juli','Agustus','September','Oktober','November','Desember'
|
|
||||||
];
|
|
||||||
document.getElementById('heatmapMonthName').textContent = monthNames[month - 1] + ' ' + year;
|
|
||||||
|
|
||||||
var url = '<?php echo e(route("admin.kegiatan.index")); ?>' +
|
|
||||||
'?heatmap=1&month=' + month + '&year=' + year + '&kelas=' + kelasId;
|
|
||||||
|
|
||||||
fetch(url)
|
|
||||||
.then(function(response) { return response.json(); })
|
|
||||||
.then(function(data) {
|
|
||||||
var grid = document.getElementById('heatmapGrid');
|
|
||||||
grid.innerHTML = '';
|
|
||||||
|
|
||||||
// -- Empty cells for first week alignment --
|
|
||||||
var firstDay = new Date(year, month - 1, 1).getDay();
|
|
||||||
var startDay = firstDay === 0 ? 6 : firstDay - 1;
|
|
||||||
var i;
|
|
||||||
for (i = 0; i < startDay; i++) {
|
|
||||||
var empty = document.createElement('div');
|
|
||||||
empty.className = 'heatmap-cell';
|
|
||||||
empty.style.visibility = 'hidden';
|
|
||||||
grid.appendChild(empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Render calendar cells --
|
|
||||||
data.heatmapData.forEach(function(day) {
|
|
||||||
var cell = document.createElement('div');
|
|
||||||
var date = new Date(day.date);
|
|
||||||
var today = new Date();
|
|
||||||
var isToday = date.toDateString() === today.toDateString();
|
|
||||||
|
|
||||||
cell.className = 'heatmap-cell heatmap-level-' + day.level + (isToday ? ' today' : '');
|
|
||||||
cell.setAttribute('data-date', day.date);
|
|
||||||
cell.setAttribute('data-percentage', day.percentage);
|
|
||||||
cell.setAttribute('title', day.title);
|
|
||||||
cell.onclick = function() { goToDate(day.date); };
|
|
||||||
cell.textContent = date.getDate();
|
|
||||||
grid.appendChild(cell);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(function(err) {
|
|
||||||
console.error('Error loading heatmap:', err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</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/data/dashboard.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Pembinaan & Sanksi'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-book-open"></i> Tata Tertib</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="display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px;">
|
|
||||||
<h3 style="margin: 0; color: var(--primary-color);">
|
|
||||||
<i class="fas fa-list"></i> Daftar Konten
|
|
||||||
</h3>
|
|
||||||
<div style="display: flex; gap: 10px;">
|
|
||||||
<a href="<?php echo e(route('admin.pembinaan-sanksi.create')); ?>" class="btn btn-primary">
|
|
||||||
<i class="fas fa-plus-circle"></i> Tambah Konten
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($data->isNotEmpty()): ?>
|
|
||||||
<div class="alert alert-info" style="margin-bottom: 14px;">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
<strong>Info:</strong> Konten akan ditampilkan sesuai urutan. Drag atau ubah nomor urutan untuk mengatur tampilan.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="table-wrapper">
|
|
||||||
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 50px;">No</th>
|
|
||||||
<th style="width: 100px;">ID</th>
|
|
||||||
<th>Judul</th>
|
|
||||||
<th style="width: 300px;">Preview Konten</th>
|
|
||||||
<th style="width: 80px; text-align: center;">Urutan</th>
|
|
||||||
<th style="width: 100px; text-align: center;">Status</th>
|
|
||||||
<th style="width: 200px; text-align: center;">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $data; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($index + 1); ?></td>
|
|
||||||
<td><span class="badge badge-primary"><?php echo e($item->id_pembinaan); ?></span></td>
|
|
||||||
<td>
|
|
||||||
<strong style="font-size: 1.05em;"><?php echo e($item->judul); ?></strong><br>
|
|
||||||
<small style="color: var(--text-light);">
|
|
||||||
<i class="fas fa-clock"></i> Diubah: <?php echo e($item->updated_at->diffForHumans()); ?>
|
|
||||||
|
|
||||||
</small>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div style="max-height: 60px; overflow: hidden; color: var(--text-light); font-size: 0.9em; line-height: 1.5;">
|
|
||||||
<?php echo e(Str::limit(strip_tags($item->konten), 100)); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<span class="badge badge-info" style="font-size: 1em;"><?php echo e($item->urutan); ?></span>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<?php if($item->is_active): ?>
|
|
||||||
<span class="badge badge-success">
|
|
||||||
<i class="fas fa-check-circle"></i> Aktif
|
|
||||||
</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="badge badge-secondary">
|
|
||||||
<i class="fas fa-times-circle"></i> Nonaktif
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<div style="display: flex; justify-content: center; gap: 8px;">
|
|
||||||
<a href="<?php echo e(route('admin.pembinaan-sanksi.show', $item)); ?>"
|
|
||||||
class="btn btn-sm btn-success"
|
|
||||||
title="Detail & Preview">
|
|
||||||
<i class="fas fa-eye"></i>
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.pembinaan-sanksi.edit', $item)); ?>"
|
|
||||||
class="btn btn-sm btn-warning"
|
|
||||||
title="Edit Konten">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
<form action="<?php echo e(route('admin.pembinaan-sanksi.destroy', $item)); ?>"
|
|
||||||
method="POST"
|
|
||||||
style="display: inline;"
|
|
||||||
onsubmit="return confirm('Yakin ingin menghapus konten \'<?php echo e($item->judul); ?>\'?\n\nKonten yang dihapus tidak dapat dikembalikan.');">
|
|
||||||
<?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>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-folder-open"></i>
|
|
||||||
<h3>Belum ada konten</h3>
|
|
||||||
<p>Mulai dengan menambahkan konten baru menggunakan Rich Text Editor.</p>
|
|
||||||
<p style="color: var(--text-light); margin-bottom: 14px;">
|
|
||||||
Anda dapat membuat peraturan, tata tertib, pembinaan, atau sanksi dengan format yang rapi.
|
|
||||||
</p>
|
|
||||||
<a href="<?php echo e(route('admin.pembinaan-sanksi.create')); ?>" class="btn btn-primary">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Konten Pertama
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
setTimeout(function() {
|
|
||||||
const alerts = document.querySelectorAll('.alert');
|
|
||||||
alerts.forEach(alert => {
|
|
||||||
alert.style.transition = 'opacity 0.5s';
|
|
||||||
alert.style.opacity = '0';
|
|
||||||
setTimeout(() => alert.remove(), 500);
|
|
||||||
});
|
|
||||||
}, 5000);
|
|
||||||
</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/pembinaan_sanksi/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$totalSantri = $kegiatan->total_absensi;
|
||||||
|
$hdr = $kegiatan->hadir ?? 0;
|
||||||
|
$tlb = $kegiatan->terlambat ?? 0;
|
||||||
|
$izn = $kegiatan->izin ?? 0;
|
||||||
|
$skt = $kegiatan->sakit ?? 0;
|
||||||
|
$alp = $kegiatan->alpa ?? 0;
|
||||||
|
$plg = $kegiatan->pulang ?? 0;
|
||||||
|
$tot = $kegiatan->total_absensi ?? 0;
|
||||||
|
|
||||||
|
$pct = fn($n) => $tot > 0 ? round($n / $tot * 100) : 0;
|
||||||
|
|
||||||
|
$isUmum = $kegiatan->kelasKegiatan->isEmpty();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="rw-card">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="rw-card-head">
|
||||||
|
<div style="flex: 1; min-width: 0;">
|
||||||
|
<div class="rw-card-title">
|
||||||
|
<i class="fas fa-clipboard-list"></i>
|
||||||
|
<?php echo e($kegiatan->nama_kegiatan); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="rw-card-meta">
|
||||||
|
<span><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))); ?>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
<span class="rw-kat-tag"><i class="fas fa-tag"></i> <?php echo e($kegiatan->kategori->nama_kategori); ?></span>
|
||||||
|
<?php if($isUmum): ?>
|
||||||
|
<span class="rw-umum-tag"><i class="fas fa-globe"></i> Umum</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php $__currentLoopData = $kegiatan->kelasKegiatan->take(3); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kls): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<span class="rw-kelas-tag"><?php echo e($kls->nama_kelas); ?></span>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<?php if($kegiatan->kelasKegiatan->count() > 3): ?>
|
||||||
|
<span class="rw-umum-tag">+<?php echo e($kegiatan->kelasKegiatan->count() - 3); ?> kelas</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<?php if(isset($passParams) && $passParams['mode'] === 'hari_ini'): ?>
|
||||||
|
<div style="font-size: 0.75rem; color: var(--primary-color); font-weight: 700;
|
||||||
|
background: #f0fdf4; padding: 4px 10px; border-radius: 20px; border: 1px solid #bbf7d0;
|
||||||
|
white-space: nowrap; flex-shrink: 0;">
|
||||||
|
<i class="fas fa-calendar-day"></i> <?php echo e($kegiatan->hari); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="rw-card-body">
|
||||||
|
<?php if($tot > 0): ?>
|
||||||
|
|
||||||
|
<div class="rw-stats-row">
|
||||||
|
<?php if($hdr > 0): ?> <span class="rw-chip hadir"><i class="fas fa-check"></i> <?php echo e($hdr); ?> Hadir</span> <?php endif; ?>
|
||||||
|
<?php if($tlb > 0): ?> <span class="rw-chip terlambat"><i class="fas fa-clock"></i> <?php echo e($tlb); ?> Terlambat</span> <?php endif; ?>
|
||||||
|
<?php if($izn > 0): ?> <span class="rw-chip izin"><i class="fas fa-envelope"></i> <?php echo e($izn); ?> Izin</span> <?php endif; ?>
|
||||||
|
<?php if($skt > 0): ?> <span class="rw-chip sakit"><i class="fas fa-heartbeat"></i> <?php echo e($skt); ?> Sakit</span> <?php endif; ?>
|
||||||
|
<?php if($alp > 0): ?> <span class="rw-chip alpa"><i class="fas fa-times"></i> <?php echo e($alp); ?> Alpa</span> <?php endif; ?>
|
||||||
|
<?php if($plg > 0): ?> <span class="rw-chip pulang"><i class="fas fa-home"></i> <?php echo e($plg); ?> Pulang</span> <?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="rw-progress-wrap">
|
||||||
|
<?php if($hdr > 0): ?> <div class="rw-prog-hadir" style="width:<?php echo e($pct($hdr)); ?>%;" title="Hadir <?php echo e($hdr); ?>"></div> <?php endif; ?>
|
||||||
|
<?php if($tlb > 0): ?> <div class="rw-prog-terlambat" style="width:<?php echo e($pct($tlb)); ?>%;" title="Terlambat <?php echo e($tlb); ?>"></div> <?php endif; ?>
|
||||||
|
<?php if($izn > 0): ?> <div class="rw-prog-izin" style="width:<?php echo e($pct($izn)); ?>%;" title="Izin <?php echo e($izn); ?>"></div> <?php endif; ?>
|
||||||
|
<?php if($skt > 0): ?> <div class="rw-prog-sakit" style="width:<?php echo e($pct($skt)); ?>%;" title="Sakit <?php echo e($skt); ?>"></div> <?php endif; ?>
|
||||||
|
<?php if($alp > 0): ?> <div class="rw-prog-alpa" style="width:<?php echo e($pct($alp)); ?>%;" title="Alpa <?php echo e($alp); ?>"></div> <?php endif; ?>
|
||||||
|
<?php if($plg > 0): ?> <div class="rw-prog-pulang" style="width:<?php echo e($pct($plg)); ?>%;" title="Pulang <?php echo e($plg); ?>"></div> <?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<div style="font-size: 0.74rem; color: #94a3b8;">
|
||||||
|
Total tercatat: <strong style="color:#374151;"><?php echo e($tot); ?></strong> santri
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="rw-chip none"><i class="fas fa-inbox"></i> Belum ada data absensi</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="rw-card-foot">
|
||||||
|
<div class="rw-total-txt">
|
||||||
|
<?php if($tot > 0): ?>
|
||||||
|
<i class="fas fa-users" style="color:var(--primary-color);"></i>
|
||||||
|
<strong><?php echo e($hdr + $tlb); ?></strong> hadir dari <strong><?php echo e($tot); ?></strong> tercatat
|
||||||
|
<?php else: ?>
|
||||||
|
<span style="color:#cbd5e1;"><i class="fas fa-info-circle"></i> Belum ada absensi diinput</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$detailParams = array_merge($passParams ?? [], ['kategori_id' => request('kategori_id')]);
|
||||||
|
?>
|
||||||
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.show', $kegiatan->id)); ?>?<?php echo e(http_build_query($detailParams)); ?>"
|
||||||
|
class="btn-rw-detail">
|
||||||
|
<i class="fas fa-users"></i> Lihat Santri
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/riwayat/_card.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -1,330 +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>
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$tingkatPoin = '';
|
|
||||||
$warnaPoin = '';
|
|
||||||
if ($totalPoin >= 50) {
|
|
||||||
$tingkatPoin = 'Berat';
|
|
||||||
$warnaPoin = 'var(--danger-color)';
|
|
||||||
} elseif ($totalPoin >= 20) {
|
|
||||||
$tingkatPoin = 'Sedang';
|
|
||||||
$warnaPoin = '#e67e22';
|
|
||||||
} elseif ($totalPoin > 0) {
|
|
||||||
$tingkatPoin = 'Ringan';
|
|
||||||
$warnaPoin = 'var(--warning-color)';
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<?php if($totalPoin >= 50): ?>
|
|
||||||
<div style="background: linear-gradient(135deg, #dc3545 0%, #a71d2a 100%); color: white; padding: 16px 20px; border-radius: var(--border-radius); margin-bottom: 18px; display: flex; align-items: center; gap: 14px; box-shadow: 0 4px 15px rgba(220,53,69,0.3);">
|
|
||||||
<i class="fas fa-exclamation-triangle" style="font-size: 2em; opacity: 0.9;"></i>
|
|
||||||
<div>
|
|
||||||
<strong style="font-size: 1.05em;">âš ï¸ Perhatian! Akumulasi poin Anda sudah tinggi (<?php echo e($totalPoin); ?> poin)</strong><br>
|
|
||||||
<span style="opacity: 0.9; font-size: 0.9em;">Harap segera hubungi pengurus pondok untuk konsultasi dan penyelesaian kafaroh yang ada.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php elseif($totalPoin >= 20): ?>
|
|
||||||
<div style="background: linear-gradient(135deg, #e67e22 0%, #ca6f1e 100%); color: white; padding: 16px 20px; border-radius: var(--border-radius); margin-bottom: 18px; display: flex; align-items: center; gap: 14px; box-shadow: 0 4px 15px rgba(230,126,34,0.3);">
|
|
||||||
<i class="fas fa-exclamation-circle" style="font-size: 2em; opacity: 0.9;"></i>
|
|
||||||
<div>
|
|
||||||
<strong style="font-size: 1.05em;">Catatan: Poin pelanggaran Anda mulai bertambah (<?php echo e($totalPoin); ?> poin)</strong><br>
|
|
||||||
<span style="opacity: 0.9; font-size: 0.9em;">Jaga perilaku dan taati peraturan pondok agar poin tidak terus bertambah.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="row-cards">
|
|
||||||
<div class="card card-danger">
|
|
||||||
<h3>Total Pelanggaran</h3>
|
|
||||||
<div class="card-value"><?php echo e($totalPelanggaran); ?></div>
|
|
||||||
<p style="margin: 4px 0 0; color: var(--text-light); font-size: 0.85em;">Sepanjang waktu</p>
|
|
||||||
<i class="fas fa-clipboard-list card-icon"></i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card card-warning">
|
|
||||||
<h3>Total Poin</h3>
|
|
||||||
<div class="card-value"><?php echo e($totalPoin); ?></div>
|
|
||||||
<p style="margin: 4px 0 0; color: var(--text-light); font-size: 0.85em;">
|
|
||||||
<?php if($tingkatPoin): ?>
|
|
||||||
Tingkat: <strong><?php echo e($tingkatPoin); ?></strong>
|
|
||||||
<?php else: ?>
|
|
||||||
Belum ada poin
|
|
||||||
<?php endif; ?>
|
|
||||||
</p>
|
|
||||||
<i class="fas fa-star card-icon"></i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card card-info">
|
|
||||||
<h3>Bulan Ini</h3>
|
|
||||||
<div class="card-value"><?php echo e($pelanggaranBulanIni); ?></div>
|
|
||||||
<p style="margin: 4px 0 0; color: var(--text-light); font-size: 0.85em;"><?php echo e(\Carbon\Carbon::now()->isoFormat('MMMM YYYY')); ?></p>
|
|
||||||
<i class="fas fa-calendar-alt card-icon"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($totalPoin > 0): ?>
|
|
||||||
<div class="content-box" style="margin-bottom: 18px;">
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
|
|
||||||
<h4 style="margin: 0; color: var(--primary-color);">
|
|
||||||
<i class="fas fa-chart-bar"></i> Akumulasi Poin Pelanggaran
|
|
||||||
</h4>
|
|
||||||
<span style="font-size: 0.85em; color: var(--text-light);">Batas perhatian: 20 poin | Batas berat: 50 poin</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$maxPoin = max(50, $totalPoin); // skala dinamis
|
|
||||||
$persenBar = min(100, round(($totalPoin / $maxPoin) * 100));
|
|
||||||
if ($totalPoin < 20) {
|
|
||||||
$colorBar = 'var(--success-color)';
|
|
||||||
} elseif ($totalPoin < 50) {
|
|
||||||
$colorBar = '#e67e22';
|
|
||||||
} else {
|
|
||||||
$colorBar = 'var(--danger-color)';
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div style="background: #f0f0f0; border-radius: 50px; height: 22px; overflow: hidden; position: relative; margin-bottom: 8px;">
|
|
||||||
|
|
||||||
<div style="position: absolute; left: <?php echo e(round((20 / $maxPoin) * 100)); ?>%; top: 0; bottom: 0; width: 2px; background: rgba(0,0,0,0.2); z-index: 1;"></div>
|
|
||||||
|
|
||||||
<?php if($maxPoin >= 50): ?>
|
|
||||||
<div style="position: absolute; left: <?php echo e(round((50 / $maxPoin) * 100)); ?>%; top: 0; bottom: 0; width: 2px; background: rgba(0,0,0,0.2); z-index: 1;"></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<div style="height: 100%; width: <?php echo e($persenBar); ?>%; background: <?php echo e($colorBar); ?>; border-radius: 50px; transition: width 0.8s ease; display: flex; align-items: center; justify-content: flex-end; padding-right: 10px;">
|
|
||||||
<span style="color: white; font-size: 0.78em; font-weight: 700; white-space: nowrap;"><?php echo e($totalPoin); ?> poin</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display: flex; justify-content: space-between; font-size: 0.78em; color: var(--text-light);">
|
|
||||||
<span>0</span>
|
|
||||||
<span style="margin-left: <?php echo e(round((20/$maxPoin)*100)); ?>%">20</span>
|
|
||||||
<?php if($maxPoin >= 50): ?><span>50+</span><?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 11px;">
|
|
||||||
<form method="GET" action="<?php echo e(route('santri.pelanggaran.index')); ?>" style="display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end;">
|
|
||||||
<div>
|
|
||||||
<label style="font-size: 0.82em; color: var(--text-light); display: block; margin-bottom: 4px;">
|
|
||||||
<i class="fas fa-calendar-day"></i> Tanggal Mulai
|
|
||||||
</label>
|
|
||||||
<input type="date" name="tanggal_mulai" class="form-control" style="width: auto;"
|
|
||||||
value="<?php echo e(request('tanggal_mulai')); ?>">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label style="font-size: 0.82em; color: var(--text-light); display: block; margin-bottom: 4px;">
|
|
||||||
<i class="fas fa-calendar-check"></i> Tanggal Selesai
|
|
||||||
</label>
|
|
||||||
<input type="date" name="tanggal_selesai" class="form-control" style="width: auto;"
|
|
||||||
value="<?php echo e(request('tanggal_selesai')); ?>">
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; gap: 8px; padding-top: 2px;">
|
|
||||||
<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-sm <?php echo e(request('bulan_ini') ? 'btn-info' : 'btn-secondary'); ?>"
|
|
||||||
style="<?php echo e(request('bulan_ini') ? '' : 'border: 1px solid var(--primary-color); color: var(--primary-color); background: transparent;'); ?>">
|
|
||||||
<i class="fas fa-calendar-check"></i> Bulan Ini
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div style="display: flex; gap: 8px; flex-wrap: wrap;">
|
|
||||||
<a href="<?php echo e(route('santri.pelanggaran.kategori')); ?>" class="btn btn-warning btn-sm">
|
|
||||||
<i class="fas fa-list-ul"></i> Kategori & Poin
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('santri.pembinaan.index')); ?>" class="btn btn-sm"
|
|
||||||
style="background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark, #1a4980) 100%);
|
|
||||||
color: white; border: none;">
|
|
||||||
<i class="fas fa-book-open"></i> Pembinaan & Sanksi
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px;">
|
|
||||||
<h3 style="margin: 0; color: var(--primary-color);">
|
|
||||||
<i class="fas fa-history"></i> Daftar Riwayat Pelanggaran
|
|
||||||
</h3>
|
|
||||||
<?php if(request()->hasAny(['tanggal_mulai', 'tanggal_selesai', 'bulan_ini'])): ?>
|
|
||||||
<span class="badge badge-info" style="font-size: 0.85em;">
|
|
||||||
<i class="fas fa-filter"></i> Filter aktif — <?php echo e($riwayat->total()); ?> data
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($riwayat->count() > 0): ?>
|
|
||||||
<div style="overflow-x: auto;">
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 5%;">No</th>
|
|
||||||
<th style="width: 10%;">ID</th>
|
|
||||||
<th style="width: 13%;">Tanggal</th>
|
|
||||||
<th style="width: 28%;">Jenis Pelanggaran</th>
|
|
||||||
<th style="width: 9%; text-align: center;">Poin</th>
|
|
||||||
<th style="width: 25%;">Keterangan</th>
|
|
||||||
<th style="width: 10%; text-align: center;">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $riwayat; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr style="transition: background 0.2s;">
|
|
||||||
<td><?php echo e($riwayat->firstItem() + $index); ?></td>
|
|
||||||
<td>
|
|
||||||
<span class="badge badge-secondary" style="font-size: 0.8em;">
|
|
||||||
<?php echo e($item->id_riwayat); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div style="white-space: nowrap;">
|
|
||||||
<i class="fas fa-calendar-day" style="color: var(--text-light); font-size: 0.85em;"></i>
|
|
||||||
<span style="font-size: 0.9em;"><?php echo e(\Carbon\Carbon::parse($item->tanggal)->isoFormat('D MMM YYYY')); ?></span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<strong><?php echo e($item->kategori->nama_pelanggaran ?? '-'); ?></strong>
|
|
||||||
<?php if($item->kategori && $item->kategori->id_kategori): ?>
|
|
||||||
<br><small style="color: var(--text-light);">
|
|
||||||
<i class="fas fa-tag"></i> <?php echo e($item->kategori->id_kategori); ?>
|
|
||||||
|
|
||||||
</small>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<?php $poin = $item->poin; ?>
|
|
||||||
<span class="badge badge-danger"
|
|
||||||
style="font-size: 0.9em; padding: 5px 10px;
|
|
||||||
<?php echo e($poin >= 20 ? 'background: linear-gradient(135deg, #dc3545, #a71d2a);' : ''); ?>">
|
|
||||||
<i class="fas fa-fire"></i> <?php echo e($poin); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($item->keterangan): ?>
|
|
||||||
<div style="max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
||||||
font-size: 0.88em; color: var(--text-color);"
|
|
||||||
title="<?php echo e($item->keterangan); ?>">
|
|
||||||
<?php echo e($item->keterangan); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="color: var(--text-light); font-size: 0.85em; font-style: italic;">Tidak ada keterangan</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: 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>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="margin-top: 14px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;">
|
|
||||||
<p style="margin: 0; color: var(--text-light); font-size: 0.88em;">
|
|
||||||
Menampilkan <?php echo e($riwayat->firstItem()); ?>-<?php echo e($riwayat->lastItem()); ?> dari <?php echo e($riwayat->total()); ?> data
|
|
||||||
</p>
|
|
||||||
<?php echo e($riwayat->links()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-check-circle" style="color: var(--success-color);"></i>
|
|
||||||
<h3>Tidak Ada Riwayat Pelanggaran</h3>
|
|
||||||
<?php if(request()->hasAny(['tanggal_mulai', 'tanggal_selesai', 'bulan_ini'])): ?>
|
|
||||||
<p>Tidak ditemukan data dengan filter yang dipilih.</p>
|
|
||||||
<a href="<?php echo e(route('santri.pelanggaran.index')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-redo"></i> Hapus Filter
|
|
||||||
</a>
|
|
||||||
<?php else: ?>
|
|
||||||
<p>Alhamdulillah, Anda belum memiliki catatan pelanggaran. Pertahankan!</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($totalPelanggaran > 0): ?>
|
|
||||||
<div class="content-box" style="margin-top: 18px;">
|
|
||||||
<h3 style="margin-bottom: 18px; color: var(--primary-color);">
|
|
||||||
<i class="fas fa-chart-pie"></i> Ringkasan Analisis
|
|
||||||
</h3>
|
|
||||||
<div class="grid-auto-fill">
|
|
||||||
|
|
||||||
<div style="background: var(--primary-light); padding: 16px; border-radius: var(--border-radius-sm); text-align: center;">
|
|
||||||
<i class="fas fa-calculator" style="font-size: 1.8em; color: var(--primary-color); margin-bottom: 8px;"></i>
|
|
||||||
<div style="font-size: 1.6em; font-weight: 700; color: var(--primary-dark);">
|
|
||||||
<?php echo e($totalPelanggaran > 0 ? number_format($totalPoin / $totalPelanggaran, 1) : 0); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<p style="margin: 4px 0 0; color: var(--text-light); font-size: 0.85em;">Rata-rata Poin/Pelanggaran</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="background: <?php echo e($totalPoin >= 50 ? 'var(--danger-color)' : ($totalPoin >= 20 ? '#fdebd0' : '#eafaf1')); ?>;
|
|
||||||
padding: 16px; border-radius: var(--border-radius-sm); text-align: center;">
|
|
||||||
<i class="fas fa-signal" style="font-size: 1.8em; color: <?php echo e($totalPoin >= 50 ? 'white' : ($totalPoin >= 20 ? '#ca6f1e' : 'var(--success-color)')); ?>; margin-bottom: 8px;"></i>
|
|
||||||
<div style="font-size: 1.4em; font-weight: 700; color: <?php echo e($totalPoin >= 50 ? 'white' : ($totalPoin >= 20 ? '#ca6f1e' : 'var(--success-color)')); ?>;">
|
|
||||||
<?php if($totalPoin >= 50): ?> Berat
|
|
||||||
<?php elseif($totalPoin >= 20): ?> Sedang
|
|
||||||
<?php else: ?> Ringan
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<p style="margin: 4px 0 0; color: <?php echo e($totalPoin >= 50 ? 'rgba(255,255,255,0.8)' : 'var(--text-light)'); ?>; font-size: 0.85em;">Tingkat Pelanggaran</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="background: #f8f9fa; padding: 16px; border-radius: var(--border-radius-sm); text-align: center;">
|
|
||||||
<i class="fas fa-calendar-day" style="font-size: 1.8em; color: var(--primary-color); margin-bottom: 8px;"></i>
|
|
||||||
<div style="font-size: 1em; font-weight: 600; color: var(--text-color);">
|
|
||||||
<?php if($riwayat->first()): ?>
|
|
||||||
<?php echo e(\Carbon\Carbon::parse($riwayat->first()->tanggal)->isoFormat('D MMM YYYY')); ?>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
—
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<p style="margin: 4px 0 0; color: var(--text-light); font-size: 0.85em;">Pelanggaran Terakhir</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="background: #fff3cd; padding: 16px; border-radius: var(--border-radius-sm); text-align: center;">
|
|
||||||
<i class="fas fa-calendar-check" style="font-size: 1.8em; color: #856404; margin-bottom: 8px;"></i>
|
|
||||||
<div style="font-size: 1.6em; font-weight: 700; color: #856404;">
|
|
||||||
<?php echo e($pelanggaranBulanIni); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<p style="margin: 4px 0 0; color: #856404; font-size: 0.85em;">Pelanggaran Bulan Ini</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?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/santri/pelanggaran/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,118 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Pembinaan & Sanksi'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-book-open"></i> Pembinaan & Sanksi</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark, #1a4980) 100%);
|
|
||||||
color: white; padding: 22px 26px; border-radius: var(--border-radius); margin-bottom: 20px;
|
|
||||||
box-shadow: 0 4px 15px rgba(0,0,0,0.15); position: relative; overflow: hidden;">
|
|
||||||
|
|
||||||
<div style="position: absolute; right: -30px; top: -30px; width: 130px; height: 130px;
|
|
||||||
background: rgba(255,255,255,0.07); border-radius: 50%;"></div>
|
|
||||||
<div style="position: absolute; right: 50px; bottom: -40px; width: 90px; height: 90px;
|
|
||||||
background: rgba(255,255,255,0.05); border-radius: 50%;"></div>
|
|
||||||
|
|
||||||
<div style="position: relative; z-index: 1;">
|
|
||||||
<div style="display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap;">
|
|
||||||
<div style="background: rgba(255,255,255,0.15); padding: 14px 16px; border-radius: 12px; flex-shrink: 0;">
|
|
||||||
<i class="fas fa-scroll" style="font-size: 2em;"></i>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h3 style="margin: 0 0 6px; font-size: 1.2em;">Panduan Tata Tertib Pondok</h3>
|
|
||||||
<p style="margin: 0; opacity: 0.88; font-size: 0.92em; line-height: 1.6;">
|
|
||||||
Berikut adalah panduan pembinaan dan ketentuan sanksi yang berlaku di pondok.
|
|
||||||
Baca dan pahami setiap poin dengan baik. Ketaatan pada aturan mencerminkan akhlak mulia.
|
|
||||||
</p>
|
|
||||||
<?php if($pembinaanList->count() > 0): ?>
|
|
||||||
<div style="margin-top: 10px; display: flex; gap: 10px; flex-wrap: wrap;">
|
|
||||||
<span style="background: rgba(255,255,255,0.2); padding: 4px 12px; border-radius: 50px; font-size: 0.85em;">
|
|
||||||
<i class="fas fa-file-alt"></i> <?php echo e($pembinaanList->count()); ?> dokumen tersedia
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($pembinaanList->count() > 0): ?>
|
|
||||||
<div style="display: grid; gap: 14px;">
|
|
||||||
<?php $__currentLoopData = $pembinaanList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div style="background: white; border: 1px solid #e8eaed; border-radius: var(--border-radius);
|
|
||||||
transition: box-shadow 0.2s, transform 0.2s; overflow: hidden;"
|
|
||||||
onmouseover="this.style.boxShadow='0 4px 20px rgba(0,0,0,0.1)'; this.style.transform='translateY(-1px)';"
|
|
||||||
onmouseout="this.style.boxShadow='none'; this.style.transform='translateY(0)';">
|
|
||||||
|
|
||||||
<a href="<?php echo e(route('santri.pembinaan.show', $item->id_pembinaan)); ?>"
|
|
||||||
style="display: flex; align-items: stretch; text-decoration: none; color: inherit;">
|
|
||||||
|
|
||||||
|
|
||||||
<div style="background: var(--primary-light); color: var(--primary-color);
|
|
||||||
padding: 0 20px; display: flex; align-items: center; justify-content: center;
|
|
||||||
min-width: 64px; font-size: 1.4em; font-weight: 800; flex-shrink: 0;">
|
|
||||||
<?php echo e(str_pad($index + 1, 2, '0', STR_PAD_LEFT)); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="padding: 16px 20px; flex: 1; min-width: 0;">
|
|
||||||
<div style="display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap;">
|
|
||||||
<div style="flex: 1; min-width: 0;">
|
|
||||||
<h4 style="margin: 0 0 6px; color: var(--primary-color); font-size: 1.05em;
|
|
||||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
|
|
||||||
<?php echo e($item->judul); ?>
|
|
||||||
|
|
||||||
</h4>
|
|
||||||
<p style="margin: 0; color: var(--text-light); font-size: 0.88em; line-height: 1.5;
|
|
||||||
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;">
|
|
||||||
<?php echo e(\Illuminate\Support\Str::limit(strip_tags($item->konten), 140)); ?>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; align-items: center; gap: 10px; flex-shrink: 0;">
|
|
||||||
<div style="text-align: right;">
|
|
||||||
<span class="badge badge-primary" style="font-size: 0.78em; display: block; margin-bottom: 4px;">
|
|
||||||
<?php echo e($item->id_pembinaan); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<span style="color: var(--text-light); font-size: 0.78em;">
|
|
||||||
<i class="fas fa-clock"></i>
|
|
||||||
<?php echo e($item->updated_at->diffForHumans()); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<i class="fas fa-chevron-right" style="color: var(--primary-color); opacity: 0.5; font-size: 1.1em;"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="info-box" style="margin-top: 20px;">
|
|
||||||
<p style="margin: 0;">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
Jika ada pertanyaan tentang isi tata tertib ini, silakan hubungi pengurus atau bagian administrasi pondok.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="content-box">
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-book-open" style="color: var(--primary-color); opacity: 0.4;"></i>
|
|
||||||
<h3>Belum Ada Konten</h3>
|
|
||||||
<p>Panduan pembinaan & sanksi belum tersedia. Silakan hubungi pengurus pondok untuk informasi lebih lanjut.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?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/santri/pembinaan/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,364 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-wallet"></i> Manajemen Uang Saku 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" style="margin-bottom:16px;">
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.uang-saku.index')); ?>" id="filterForm"
|
|
||||||
style="display:flex; flex-wrap:wrap; gap:10px; align-items:flex-end; margin-bottom:18px;">
|
|
||||||
<?php if(request('search')): ?> <input type="hidden" name="search" value="<?php echo e(request('search')); ?>"> <?php endif; ?>
|
|
||||||
<?php if(request('sort')): ?> <input type="hidden" name="sort" value="<?php echo e(request('sort')); ?>"> <?php endif; ?>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label style="font-size:.78rem;color:var(--text-light);display:block;margin-bottom:3px;">Dari Tanggal</label>
|
|
||||||
<input type="date" name="dari" class="form-control" value="<?php echo e($dari); ?>" style="width:155px;">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label style="font-size:.78rem;color:var(--text-light);display:block;margin-bottom:3px;">Sampai Tanggal</label>
|
|
||||||
<input type="date" name="sampai" class="form-control" value="<?php echo e($sampai); ?>" style="width:155px;">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;gap:5px;flex-wrap:wrap;align-self:flex-end;">
|
|
||||||
<?php
|
|
||||||
$bulanIniDari = now()->startOfMonth()->format('Y-m-d');
|
|
||||||
$bulanIniSampai = now()->endOfMonth()->format('Y-m-d');
|
|
||||||
$isBulanIni = $dari === $bulanIniDari && $sampai === $bulanIniSampai;
|
|
||||||
$isHariIni = $dari === now()->format('Y-m-d') && $sampai === now()->format('Y-m-d');
|
|
||||||
?>
|
|
||||||
<button type="button" onclick="setPreset('today')"
|
|
||||||
class="btn btn-sm <?php echo e($isHariIni ? 'btn-primary' : 'btn-secondary'); ?>">
|
|
||||||
Hari Ini
|
|
||||||
</button>
|
|
||||||
<button type="button" onclick="setPreset('month')"
|
|
||||||
class="btn btn-sm <?php echo e($isBulanIni ? 'btn-primary' : 'btn-secondary'); ?>">
|
|
||||||
Bulan Ini
|
|
||||||
</button>
|
|
||||||
<button type="submit" class="btn btn-primary btn-sm">
|
|
||||||
<i class="fas fa-filter"></i> Terapkan
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="row-cards row-cards-4" style="margin-bottom:10px;">
|
|
||||||
<div class="card card-info">
|
|
||||||
<h3>Total Transaksi</h3>
|
|
||||||
<p class="card-value"><?php echo e($kpi['total_transaksi']); ?></p>
|
|
||||||
<span class="card-sub">dari <?php echo e($kpi['total_santri']); ?> santri</span>
|
|
||||||
<i class="fas fa-exchange-alt card-icon"></i>
|
|
||||||
</div>
|
|
||||||
<div class="card card-success">
|
|
||||||
<h3>Total Pemasukan</h3>
|
|
||||||
<p class="card-value" style="font-size:1.05rem;">Rp <?php echo e(number_format($kpi['total_pemasukan'], 0, ',', '.')); ?></p>
|
|
||||||
<span class="card-sub">
|
|
||||||
<?php echo e(\Carbon\Carbon::parse($dari)->format('d M')); ?> – <?php echo e(\Carbon\Carbon::parse($sampai)->format('d M Y')); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<i class="fas fa-arrow-circle-down card-icon"></i>
|
|
||||||
</div>
|
|
||||||
<div class="card card-warning">
|
|
||||||
<h3>Total Pengeluaran</h3>
|
|
||||||
<p class="card-value" style="font-size:1.05rem;">Rp <?php echo e(number_format($kpi['total_pengeluaran'], 0, ',', '.')); ?></p>
|
|
||||||
<span class="card-sub">
|
|
||||||
<?php echo e(\Carbon\Carbon::parse($dari)->format('d M')); ?> – <?php echo e(\Carbon\Carbon::parse($sampai)->format('d M Y')); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<i class="fas fa-arrow-circle-up card-icon"></i>
|
|
||||||
</div>
|
|
||||||
<div class="card <?php echo e($kpi['selisih'] >= 0 ? 'card-success' : 'card-danger'); ?>">
|
|
||||||
<h3>
|
|
||||||
Selisih Periode
|
|
||||||
<span title="Selisih = Total Pemasukan dikurangi Total Pengeluaran pada periode yang dipilih. Surplus berarti lebih banyak uang masuk; Defisit berarti lebih banyak uang keluar."
|
|
||||||
style="cursor:help;font-size:.75rem;color:var(--text-light);">
|
|
||||||
<i class="fas fa-question-circle"></i>
|
|
||||||
</span>
|
|
||||||
</h3>
|
|
||||||
<p class="card-value" style="font-size:1.05rem;">
|
|
||||||
<?php echo e($kpi['selisih'] >= 0 ? '+' : '-'); ?> Rp <?php echo e(number_format(abs($kpi['selisih']), 0, ',', '.')); ?>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
<span class="card-sub"><?php echo e($kpi['selisih'] >= 0 ? '✓ Surplus periode ini' : '✗ Defisit periode ini'); ?></span>
|
|
||||||
<i class="fas fa-balance-scale card-icon"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="row-cards row-cards-1">
|
|
||||||
<div class="card card-primary" style="border-left: 4px solid var(--primary-color); position:relative;">
|
|
||||||
<div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:space-between;">
|
|
||||||
<div>
|
|
||||||
<h3 style="margin:0 0 4px;">
|
|
||||||
Total Saldo Seluruh Santri
|
|
||||||
</h3>
|
|
||||||
<p class="card-value" style="font-size:1.4rem;margin:0;color:var(--primary-color);">
|
|
||||||
Rp <?php echo e(number_format($kpi['total_saldo_realtime'], 0, ',', '.')); ?>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div style="text-align:right;">
|
|
||||||
<span class="badge badge-info" style="font-size:.8rem;padding:5px 10px;">
|
|
||||||
<i class="fas fa-clock"></i> Real-time — tidak terpengaruh filter tanggal
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<i class="fas fa-piggy-bank card-icon"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:14px; flex-wrap:wrap; gap:10px;">
|
|
||||||
<a href="<?php echo e(route('admin.uang-saku.create')); ?>" class="btn btn-primary">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Transaksi
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<div style="display:flex; gap:8px; flex-wrap:wrap; align-items:center;">
|
|
||||||
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.uang-saku.index')); ?>" id="sortForm" style="display:flex;gap:6px;align-items:center;">
|
|
||||||
<input type="hidden" name="dari" value="<?php echo e($dari); ?>">
|
|
||||||
<input type="hidden" name="sampai" value="<?php echo e($sampai); ?>">
|
|
||||||
<?php if(request('search')): ?> <input type="hidden" name="search" value="<?php echo e(request('search')); ?>"> <?php endif; ?>
|
|
||||||
<label style="font-size:.79rem;color:var(--text-light);white-space:nowrap;">
|
|
||||||
<i class="fas fa-sort"></i> Urut:
|
|
||||||
</label>
|
|
||||||
<select name="sort" class="form-control form-control-sm" onchange="this.form.submit()" style="width:auto;">
|
|
||||||
<option value="nama" <?php echo e($sort==='nama' ? 'selected' : ''); ?>>Nama A–Z</option>
|
|
||||||
<option value="saldo_asc" <?php echo e($sort==='saldo_asc' ? 'selected' : ''); ?>>Saldo Terendah</option>
|
|
||||||
<option value="saldo_desc" <?php echo e($sort==='saldo_desc' ? 'selected' : ''); ?>>Saldo Tertinggi</option>
|
|
||||||
<option value="transaksi_desc" <?php echo e($sort==='transaksi_desc'? 'selected' : ''); ?>>Transaksi Terbanyak</option>
|
|
||||||
<option value="terakhir" <?php echo e($sort==='terakhir' ? 'selected' : ''); ?>>Transaksi Terbaru</option>
|
|
||||||
</select>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.uang-saku.index')); ?>" style="display:flex;gap:6px;">
|
|
||||||
<input type="hidden" name="dari" value="<?php echo e($dari); ?>">
|
|
||||||
<input type="hidden" name="sampai" value="<?php echo e($sampai); ?>">
|
|
||||||
<input type="hidden" name="sort" value="<?php echo e($sort); ?>">
|
|
||||||
<input type="text" name="search" class="form-control form-control-sm"
|
|
||||||
placeholder="Cari nama / ID santri..."
|
|
||||||
value="<?php echo e(request('search')); ?>" style="width:210px;">
|
|
||||||
<button type="submit" class="btn btn-primary btn-sm"><i class="fas fa-search"></i></button>
|
|
||||||
<?php if(request('search')): ?>
|
|
||||||
<a href="<?php echo e(route('admin.uang-saku.index', ['dari'=>$dari,'sampai'=>$sampai,'sort'=>$sort])); ?>"
|
|
||||||
class="btn btn-secondary btn-sm"><i class="fas fa-times"></i></a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;gap:14px;margin-bottom:12px;flex-wrap:wrap;font-size:.78rem;color:var(--text-light);">
|
|
||||||
<span><span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:#6FBA9D;margin-right:4px;"></span>Saldo ≥ Rp 100rb</span>
|
|
||||||
<span><span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:#f5a623;margin-right:4px;"></span>Saldo Rp 20rb – 99rb</span>
|
|
||||||
<span><span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:#FF8B94;margin-right:4px;"></span>Saldo < Rp 20rb</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($santriList->count() > 0): ?>
|
|
||||||
<?php $__currentLoopData = $santriList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$saldoColor = $santri->saldo_terakhir >= 100000 ? '#6FBA9D'
|
|
||||||
: ($santri->saldo_terakhir >= 20000 ? '#f5a623' : '#FF8B94');
|
|
||||||
$saldoDot = $saldoColor;
|
|
||||||
?>
|
|
||||||
<div class="content-box us-row" style="margin-bottom:10px;padding:0;overflow:hidden;">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="us-row-header"
|
|
||||||
onclick="toggleDetail('detail-<?php echo e($santri->id_santri); ?>', this)"
|
|
||||||
style="display:flex;align-items:center;gap:0;cursor:pointer;padding:13px 16px;flex-wrap:wrap;gap:10px;">
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;align-items:center;gap:10px;flex:1;min-width:160px;">
|
|
||||||
<i class="fas fa-chevron-right toggle-arrow"
|
|
||||||
style="transition:transform .2s;color:var(--text-light);font-size:.8rem;flex-shrink:0;"></i>
|
|
||||||
<div>
|
|
||||||
<div style="font-weight:700;font-size:.93rem;"><?php echo e($santri->nama_lengkap); ?></div>
|
|
||||||
<div style="font-size:.76rem;color:var(--text-light);"><?php echo e($santri->id_santri); ?></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;flex-direction:column;align-items:center;min-width:120px;">
|
|
||||||
<div style="font-size:.7rem;color:var(--text-light);margin-bottom:2px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;">Saldo</div>
|
|
||||||
<div style="font-size:1.05rem;font-weight:800;color:<?php echo e($saldoColor); ?>;display:flex;align-items:center;gap:5px;">
|
|
||||||
<span style="width:8px;height:8px;border-radius:50%;background:<?php echo e($saldoDot); ?>;flex-shrink:0;display:inline-block;"></span>
|
|
||||||
Rp <?php echo e(number_format($santri->saldo_terakhir, 0, ',', '.')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="width:1px;height:36px;background:var(--primary-light);flex-shrink:0;"></div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;flex-direction:column;align-items:center;min-width:100px;">
|
|
||||||
<div style="font-size:.7rem;color:var(--text-light);margin-bottom:2px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;">Masuk Bln Ini</div>
|
|
||||||
<div style="font-size:.85rem;font-weight:700;color:#6FBA9D;">
|
|
||||||
+ Rp <?php echo e(number_format($santri->pemasukan_bulan, 0, ',', '.')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;flex-direction:column;align-items:center;min-width:100px;">
|
|
||||||
<div style="font-size:.7rem;color:var(--text-light);margin-bottom:2px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;">Keluar Bln Ini</div>
|
|
||||||
<div style="font-size:.85rem;font-weight:700;color:#FF8B94;">
|
|
||||||
- Rp <?php echo e(number_format($santri->pengeluaran_bulan, 0, ',', '.')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="width:1px;height:36px;background:var(--primary-light);flex-shrink:0;"></div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;flex-direction:column;align-items:center;min-width:90px;">
|
|
||||||
<div style="font-size:.7rem;color:var(--text-light);margin-bottom:2px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;">Transaksi</div>
|
|
||||||
<span class="badge badge-info" style="font-size:.74rem;"><?php echo e($santri->transaksi_bulan_ini); ?>x bln ini</span>
|
|
||||||
<?php if($santri->transaksi_terakhir_tgl): ?>
|
|
||||||
<div style="font-size:.7rem;color:var(--text-light);margin-top:3px;">
|
|
||||||
terakhir <?php echo e(\Carbon\Carbon::parse($santri->transaksi_terakhir_tgl)->format('d/m/Y')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;gap:5px;flex-shrink:0;" onclick="event.stopPropagation()">
|
|
||||||
<a href="<?php echo e(route('admin.uang-saku.create')); ?>?id_santri=<?php echo e($santri->id_santri); ?>"
|
|
||||||
class="btn btn-success btn-sm" title="Tambah Transaksi">
|
|
||||||
<i class="fas fa-plus"></i>
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.uang-saku.riwayat', $santri->id_santri)); ?>"
|
|
||||||
class="btn btn-primary btn-sm" title="Riwayat Lengkap">
|
|
||||||
<i class="fas fa-history"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="detail-<?php echo e($santri->id_santri); ?>"
|
|
||||||
style="display:none;border-top:1px solid var(--primary-light);padding:12px 16px;">
|
|
||||||
<?php if($santri->transaksi_terbaru->isNotEmpty()): ?>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Tanggal</th>
|
|
||||||
<th>Jenis</th>
|
|
||||||
<th>Nominal</th>
|
|
||||||
<th>Keterangan</th>
|
|
||||||
<th>Saldo</th>
|
|
||||||
<th class="text-center">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $santri->transaksi_terbaru; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $tx): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($tx->tanggal_transaksi->format('d/m/Y')); ?></td>
|
|
||||||
<td>
|
|
||||||
<?php if($tx->jenis_transaksi === 'pemasukan'): ?>
|
|
||||||
<span class="badge badge-success"><i class="fas fa-arrow-down"></i> Masuk</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="badge badge-danger"><i class="fas fa-arrow-up"></i> Keluar</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td class="nominal-highlight"><?php echo e($tx->nominal_format); ?></td>
|
|
||||||
<td><div class="content-preview"><?php echo e($tx->keterangan ?? '-'); ?></div></td>
|
|
||||||
<td style="font-weight:600;color:<?php echo e($tx->saldo_sesudah >= 0 ? '#6FBA9D' : '#FF8B94'); ?>;">
|
|
||||||
Rp <?php echo e(number_format($tx->saldo_sesudah, 0, ',', '.')); ?>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<div style="display:flex;gap:4px;justify-content:center;">
|
|
||||||
<a href="<?php echo e(route('admin.uang-saku.show', $tx->id)); ?>" class="btn btn-primary btn-sm"><i class="fas fa-eye"></i></a>
|
|
||||||
<a href="<?php echo e(route('admin.uang-saku.edit', $tx->id)); ?>" class="btn btn-warning btn-sm"><i class="fas fa-edit"></i></a>
|
|
||||||
<form action="<?php echo e(route('admin.uang-saku.destroy', $tx->id)); ?>" method="POST"
|
|
||||||
style="display:inline;" onsubmit="return confirm('Yakin hapus transaksi ini?')">
|
|
||||||
<?php echo csrf_field(); ?> <?php echo method_field('DELETE'); ?>
|
|
||||||
<button class="btn btn-danger btn-sm"><i class="fas fa-trash"></i></button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<?php if($santri->transaksi_terbaru->count() >= 5): ?>
|
|
||||||
<div style="text-align:center;margin-top:10px;">
|
|
||||||
<a href="<?php echo e(route('admin.uang-saku.riwayat', $santri->id_santri)); ?>"
|
|
||||||
class="btn btn-secondary btn-sm">
|
|
||||||
<i class="fas fa-arrow-right"></i> Lihat Semua Riwayat
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php else: ?>
|
|
||||||
<p class="text-muted" style="margin:0;">Belum ada transaksi.</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
|
|
||||||
<div style="margin-top:14px;"><?php echo e($santriList->links()); ?></div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-wallet"></i>
|
|
||||||
<h3>Belum Ada Data</h3>
|
|
||||||
<p>Belum ada santri dengan transaksi uang saku.</p>
|
|
||||||
<a href="<?php echo e(route('admin.uang-saku.create')); ?>" class="btn btn-success">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Transaksi
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function toggleDetail(id, el) {
|
|
||||||
var detail = document.getElementById(id);
|
|
||||||
var arrow = el.querySelector('.toggle-arrow');
|
|
||||||
var open = detail.style.display !== 'none';
|
|
||||||
detail.style.display = open ? 'none' : 'block';
|
|
||||||
arrow.style.transform = open ? 'rotate(0deg)' : 'rotate(90deg)';
|
|
||||||
}
|
|
||||||
|
|
||||||
function setPreset(type) {
|
|
||||||
var form = document.getElementById('filterForm');
|
|
||||||
var dari = form.querySelector('[name=dari]');
|
|
||||||
var sampai = form.querySelector('[name=sampai]');
|
|
||||||
var today = new Date();
|
|
||||||
var pad = n => String(n).padStart(2, '0');
|
|
||||||
var ymd = d => d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate());
|
|
||||||
|
|
||||||
if (type === 'today') {
|
|
||||||
dari.value = ymd(today);
|
|
||||||
sampai.value = ymd(today);
|
|
||||||
} else if (type === 'month') {
|
|
||||||
var first = new Date(today.getFullYear(), today.getMonth(), 1);
|
|
||||||
var last = new Date(today.getFullYear(), today.getMonth() + 1, 0);
|
|
||||||
dari.value = ymd(first);
|
|
||||||
sampai.value = ymd(last);
|
|
||||||
}
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
</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/index.blade.php ENDPATH**/ ?>
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,410 +0,0 @@
|
||||||
<?php $__env->startSection('title', 'Pengajuan Kepulangan dari Mobile'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-mobile-alt"></i> Pengajuan Kepulangan dari Mobile</h2>
|
|
||||||
<p style="color: #7F8C8D; margin-top: 5px;">Kelola pengajuan izin kepulangan yang diajukan melalui aplikasi mobile</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 14px; border-radius: 12px; margin-bottom: 14px;">
|
|
||||||
<div style="display: flex; align-items: center; gap: 11px;">
|
|
||||||
<div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 12px;">
|
|
||||||
<i class="fas fa-info-circle" style="font-size: 2rem;"></i>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 style="margin: 0 0 5px 0;">Tentang Pengajuan dari Mobile</h4>
|
|
||||||
<p style="margin: 0; font-size: 0.95rem; opacity: 0.9;">
|
|
||||||
Pengajuan ini dikirim oleh wali santri melalui aplikasi mobile.
|
|
||||||
Setelah Anda approve, data akan otomatis masuk ke tabel kepulangan utama dengan status "Disetujui".
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="row-cards">
|
|
||||||
<div class="card card-info">
|
|
||||||
<h3>Total Pengajuan</h3>
|
|
||||||
<div class="card-value"><?php echo e($stats['total_data']); ?></div>
|
|
||||||
<i class="fas fa-list card-icon"></i>
|
|
||||||
</div>
|
|
||||||
<div class="card card-warning">
|
|
||||||
<h3>Menunggu Review</h3>
|
|
||||||
<div class="card-value"><?php echo e($stats['menunggu']); ?></div>
|
|
||||||
<i class="fas fa-clock card-icon"></i>
|
|
||||||
</div>
|
|
||||||
<div class="card card-success">
|
|
||||||
<h3>Disetujui</h3>
|
|
||||||
<div class="card-value"><?php echo e($stats['disetujui']); ?></div>
|
|
||||||
<i class="fas fa-check-circle card-icon"></i>
|
|
||||||
</div>
|
|
||||||
<div class="card card-danger">
|
|
||||||
<h3>Ditolak</h3>
|
|
||||||
<div class="card-value"><?php echo e($stats['ditolak']); ?></div>
|
|
||||||
<i class="fas fa-times-circle card-icon"></i>
|
|
||||||
</div>
|
|
||||||
</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">
|
|
||||||
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.kepulangan.pengajuan')); ?>" id="filterForm" style="margin-bottom: 14px;">
|
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px; align-items: end;">
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<input type="text"
|
|
||||||
name="search"
|
|
||||||
class="form-control"
|
|
||||||
placeholder="Cari nama santri atau ID..."
|
|
||||||
value="<?php echo e(request('search')); ?>">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<select name="status" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
|
||||||
<option value="">Semua Status</option>
|
|
||||||
<option value="Menunggu" <?php echo e(request('status') == 'Menunggu' ? 'selected' : ''); ?>>Menunggu</option>
|
|
||||||
<option value="Disetujui" <?php echo e(request('status') == 'Disetujui' ? 'selected' : ''); ?>>Disetujui</option>
|
|
||||||
<option value="Ditolak" <?php echo e(request('status') == 'Ditolak' ? 'selected' : ''); ?>>Ditolak</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display: flex; gap: 10px;">
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
<i class="fas fa-search"></i> Filter
|
|
||||||
</button>
|
|
||||||
<a href="<?php echo e(route('admin.kepulangan.pengajuan')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-redo"></i> Reset
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="overflow-x: auto;">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID Pengajuan</th>
|
|
||||||
<th>Santri</th>
|
|
||||||
<th>Tanggal Pengajuan</th>
|
|
||||||
<th>Tanggal Pulang - Kembali</th>
|
|
||||||
<th>Durasi</th>
|
|
||||||
<th>Alasan</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th class="text-center">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__empty_1 = true; $__currentLoopData = $pengajuan; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
|
|
||||||
<tr style="<?php echo e($item->status == 'Menunggu' ? 'background-color: rgba(255, 193, 7, 0.1);' : ''); ?>">
|
|
||||||
<td>
|
|
||||||
<strong><?php echo e($item->id_pengajuan); ?></strong>
|
|
||||||
<?php if($item->status == 'Menunggu'): ?>
|
|
||||||
<span style="display: inline-block; background: #ffc107; color: #000; padding: 2px 6px; border-radius: 4px; font-size: 0.75rem; margin-left: 5px;">
|
|
||||||
<i class="fas fa-clock"></i> BARU
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>
|
|
||||||
<strong><?php echo e($item->santri->nama_lengkap ?? 'N/A'); ?></strong><br>
|
|
||||||
<small style="color: #7F8C8D;">
|
|
||||||
<?php echo e($item->santri->id_santri ?? ''); ?> | <?php echo e($item->santri->kelas ?? ''); ?>
|
|
||||||
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php echo e($item->created_at->format('d M Y')); ?><br>
|
|
||||||
<small style="color: #7F8C8D;"><?php echo e($item->created_at->format('H:i')); ?> WIB</small>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php echo e($item->tanggal_pulang->format('d M Y')); ?><br>
|
|
||||||
<small style="color: #7F8C8D;">s/d <?php echo e($item->tanggal_kembali->format('d M Y')); ?></small>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<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>
|
|
||||||
<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); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span style="display: inline-block; padding: 4px 10px; border-radius: 4px; font-size: 0.85rem; font-weight: 600;
|
|
||||||
<?php if($item->status == 'Menunggu'): ?> background: #ffc107; color: #000;
|
|
||||||
<?php elseif($item->status == 'Disetujui'): ?> background: #28a745; color: white;
|
|
||||||
<?php else: ?> background: #dc3545; color: white;
|
|
||||||
<?php endif; ?>">
|
|
||||||
<?php echo e($item->status); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<?php if($item->reviewed_at): ?>
|
|
||||||
<br><small style="color: #7F8C8D;"><?php echo e($item->reviewed_at->format('d M Y H:i')); ?></small>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<div style="display: flex; gap: 5px; justify-content: center; flex-wrap: wrap;">
|
|
||||||
<?php if($item->status == 'Menunggu'): ?>
|
|
||||||
<button type="button"
|
|
||||||
class="btn btn-sm btn-success"
|
|
||||||
onclick="approvePengajuan(<?php echo e($item->id); ?>)"
|
|
||||||
title="Setujui">
|
|
||||||
<i class="fas fa-check"></i> Setujui
|
|
||||||
</button>
|
|
||||||
<button type="button"
|
|
||||||
class="btn btn-sm btn-danger"
|
|
||||||
onclick="rejectPengajuan(<?php echo e($item->id); ?>)"
|
|
||||||
title="Tolak">
|
|
||||||
<i class="fas fa-times"></i> Tolak
|
|
||||||
</button>
|
|
||||||
<?php else: ?>
|
|
||||||
<small style="color: #7F8C8D;">
|
|
||||||
<?php if($item->catatan_review): ?>
|
|
||||||
<strong>Catatan:</strong><br><?php echo e(Str::limit($item->catatan_review, 50)); ?>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
Sudah direview
|
|
||||||
<?php endif; ?>
|
|
||||||
</small>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
|
||||||
<tr>
|
|
||||||
<td colspan="8" style="text-align: center; padding: 22px;">
|
|
||||||
<i class="fas fa-inbox" style="font-size: 2.2rem; color: #ccc; margin-bottom: 15px;"></i>
|
|
||||||
<p style="color: #7F8C8D;">Tidak ada pengajuan kepulangan dari mobile</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($pengajuan->hasPages()): ?>
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 14px; flex-wrap: wrap; gap: 11px;">
|
|
||||||
<div>
|
|
||||||
Menampilkan <?php echo e($pengajuan->firstItem() ?? 0); ?> - <?php echo e($pengajuan->lastItem() ?? 0); ?>
|
|
||||||
dari <?php echo e($pengajuan->total()); ?> data
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<?php echo e($pengajuan->appends(request()->query())->links()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<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: 14px;">
|
|
||||||
<form id="approveForm">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<div style="margin-bottom: 14px;">
|
|
||||||
<h3 style="margin: 0; color: #2C3E50;">
|
|
||||||
<i class="fas fa-check-circle" style="color: #28a745;"></i>
|
|
||||||
Setujui Pengajuan
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<p>Pengajuan akan otomatis dipindahkan ke tabel kepulangan dengan status <strong>"Disetujui"</strong>.</p>
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Catatan Persetujuan (Opsional):</label>
|
|
||||||
<textarea name="catatan_review" class="form-control" rows="3"
|
|
||||||
placeholder="Tambahkan catatan untuk persetujuan ini..."></textarea>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('approveModal')">Batal</button>
|
|
||||||
<button type="submit" class="btn btn-success">
|
|
||||||
<i class="fas fa-check"></i> Setujui Pengajuan
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</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: 14px;">
|
|
||||||
<form id="rejectForm">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<div style="margin-bottom: 14px;">
|
|
||||||
<h3 style="margin: 0; color: #2C3E50;">
|
|
||||||
<i class="fas fa-times-circle" style="color: #dc3545;"></i>
|
|
||||||
Tolak Pengajuan
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<p style="color: #dc3545;">Pengajuan akan ditolak dan wali santri akan menerima notifikasi penolakan.</p>
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Alasan Penolakan: <span style="color: #dc3545;">*</span></label>
|
|
||||||
<textarea name="catatan_review" class="form-control" rows="3"
|
|
||||||
placeholder="Jelaskan alasan penolakan..." required></textarea>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('rejectModal')">Batal</button>
|
|
||||||
<button type="submit" class="btn btn-danger">
|
|
||||||
<i class="fas fa-times"></i> Tolak Pengajuan
|
|
||||||
</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-content {
|
|
||||||
max-height: 90vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
let currentPengajuanId = null;
|
|
||||||
|
|
||||||
// Approve
|
|
||||||
function approvePengajuan(id) {
|
|
||||||
currentPengajuanId = id;
|
|
||||||
document.getElementById('approveModal').style.display = 'flex';
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('approveForm').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> Memproses...';
|
|
||||||
|
|
||||||
fetch(`/admin/kepulangan/pengajuan/${currentPengajuanId}/approve`, {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData,
|
|
||||||
headers: { 'X-CSRF-TOKEN': '<?php echo e(csrf_token()); ?>' }
|
|
||||||
})
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.success) {
|
|
||||||
closeModal('approveModal');
|
|
||||||
showAlert('success', data.message);
|
|
||||||
setTimeout(() => window.location.reload(), 1000);
|
|
||||||
} else {
|
|
||||||
showAlert('danger', data.message);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => showAlert('danger', 'Error: ' + error.message))
|
|
||||||
.finally(() => {
|
|
||||||
submitBtn.disabled = false;
|
|
||||||
submitBtn.innerHTML = originalText;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Reject
|
|
||||||
function rejectPengajuan(id) {
|
|
||||||
currentPengajuanId = id;
|
|
||||||
document.getElementById('rejectModal').style.display = 'flex';
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('rejectForm').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> Memproses...';
|
|
||||||
|
|
||||||
fetch(`/admin/kepulangan/pengajuan/${currentPengajuanId}/reject`, {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData,
|
|
||||||
headers: { 'X-CSRF-TOKEN': '<?php echo e(csrf_token()); ?>' }
|
|
||||||
})
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.success) {
|
|
||||||
closeModal('rejectModal');
|
|
||||||
showAlert('success', data.message);
|
|
||||||
setTimeout(() => window.location.reload(), 1000);
|
|
||||||
} else {
|
|
||||||
showAlert('danger', data.message);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => showAlert('danger', 'Error: ' + error.message))
|
|
||||||
.finally(() => {
|
|
||||||
submitBtn.disabled = false;
|
|
||||||
submitBtn.innerHTML = originalText;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Helper functions
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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) {
|
|
||||||
this.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</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/kepulangan/pengajuan.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,252 +0,0 @@
|
||||||
<?php $__env->startSection('title', 'Tambah Pembinaan & Sanksi'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-plus-circle"></i> Tambah Peraturan & Tata Tertib</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<form action="<?php echo e(route('admin.pembinaan-sanksi.store')); ?>" method="POST">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label>
|
|
||||||
<i class="fas fa-id-card form-icon"></i>
|
|
||||||
ID Peraturan (Preview)
|
|
||||||
</label>
|
|
||||||
<input type="text" class="form-control" value="<?php echo e($nextId); ?>" disabled>
|
|
||||||
<span class="form-text">ID akan dibuat otomatis</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="judul">
|
|
||||||
<i class="fas fa-heading form-icon"></i>
|
|
||||||
Judul <span style="color: var(--danger-color);">*</span>
|
|
||||||
</label>
|
|
||||||
<input type="text"
|
|
||||||
name="judul"
|
|
||||||
id="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="Contoh: Pembinaan & sanksi, Peraturan Pondok, Tata Tertib, dll"
|
|
||||||
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>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="konten">
|
|
||||||
<i class="fas fa-file-alt form-icon"></i>
|
|
||||||
Konten <span style="color: var(--danger-color);">*</span>
|
|
||||||
</label>
|
|
||||||
<div id="editor-container" style="min-height: 400px; background: white; border: 1px solid #ddd; border-radius: 4px;"></div>
|
|
||||||
<textarea name="konten"
|
|
||||||
id="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); ?>"
|
|
||||||
style="display: none;"
|
|
||||||
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" style="display: block;"><?php echo e($message); ?></span>
|
|
||||||
<?php unset($message);
|
|
||||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
|
||||||
endif;
|
|
||||||
unset($__errorArgs, $__bag); ?>
|
|
||||||
<span class="form-text">
|
|
||||||
<i class="fas fa-magic"></i> Gunakan toolbar di atas untuk formatting: Bold, Italic, Daftar Bernomor, Warna, dsb.
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="urutan">
|
|
||||||
<i class="fas fa-sort-numeric-up form-icon"></i>
|
|
||||||
Urutan Tampilan
|
|
||||||
</label>
|
|
||||||
<input type="number"
|
|
||||||
name="urutan"
|
|
||||||
id="urutan"
|
|
||||||
class="form-control <?php $__errorArgs = ['urutan'];
|
|
||||||
$__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('urutan', 0)); ?>"
|
|
||||||
min="0">
|
|
||||||
<?php $__errorArgs = ['urutan'];
|
|
||||||
$__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>
|
|
||||||
<i class="fas fa-toggle-on form-icon"></i>
|
|
||||||
Status
|
|
||||||
</label>
|
|
||||||
<div style="margin-top: 12px;">
|
|
||||||
<label style="display: flex; align-items: center; cursor: pointer;">
|
|
||||||
<input type="checkbox"
|
|
||||||
name="is_active"
|
|
||||||
value="1"
|
|
||||||
<?php echo e(old('is_active', true) ? 'checked' : ''); ?>
|
|
||||||
|
|
||||||
style="margin-right: 8px;">
|
|
||||||
<span>Aktif</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="btn-group" style="margin-top: 22px;">
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
<i class="fas fa-save"></i> Simpan
|
|
||||||
</button>
|
|
||||||
<a href="<?php echo e(route('admin.pembinaan-sanksi.index')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-times"></i> Batal
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Quill Editor CSS -->
|
|
||||||
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Quill Editor JS -->
|
|
||||||
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// Initialize Quill Editor
|
|
||||||
var quill = new Quill('#editor-container', {
|
|
||||||
theme: 'snow',
|
|
||||||
modules: {
|
|
||||||
toolbar: [
|
|
||||||
[{ 'header': [1, 2, 3, false] }],
|
|
||||||
['bold', 'italic', 'underline', 'strike'],
|
|
||||||
[{ 'color': [] }, { 'background': [] }],
|
|
||||||
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
|
|
||||||
[{ 'indent': '-1'}, { 'indent': '+1' }],
|
|
||||||
[{ 'align': [] }],
|
|
||||||
['link', 'image'],
|
|
||||||
['clean']
|
|
||||||
]
|
|
||||||
},
|
|
||||||
placeholder: 'Tulis konten di sini...\n\n Gunakan toolbar di atas untuk formatting:\n Heading untuk judul\n Bold/Italic untuk penekanan\n List untuk daftar\nColor untuk highlight'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Load existing content if any (for old() values)
|
|
||||||
var existingContent = document.getElementById('konten').value;
|
|
||||||
if (existingContent) {
|
|
||||||
quill.root.innerHTML = existingContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync Quill content to hidden textarea on form submit
|
|
||||||
document.querySelector('form').onsubmit = function() {
|
|
||||||
var kontenInput = document.getElementById('konten');
|
|
||||||
kontenInput.value = quill.root.innerHTML;
|
|
||||||
|
|
||||||
// Validation: check if content is empty
|
|
||||||
if (quill.getText().trim().length === 0) {
|
|
||||||
alert('Konten tidak boleh kosong!');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Optional: Sync on every change (real-time)
|
|
||||||
quill.on('text-change', function() {
|
|
||||||
document.getElementById('konten').value = quill.root.innerHTML;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
/* Custom Quill Editor Styling */
|
|
||||||
.ql-toolbar {
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
border-radius: 4px 4px 0 0;
|
|
||||||
border-bottom: 2px solid #dee2e6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-container {
|
|
||||||
font-size: 11px;
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
min-height: 350px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-editor {
|
|
||||||
min-height: 350px;
|
|
||||||
max-height: 600px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-editor h1 {
|
|
||||||
font-size: 2em;
|
|
||||||
color: #2c3e50;
|
|
||||||
margin-top: 0.5em;
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-editor h2 {
|
|
||||||
font-size: 1.5em;
|
|
||||||
color: #34495e;
|
|
||||||
margin-top: 0.5em;
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-editor h3 {
|
|
||||||
font-size: 1.2em;
|
|
||||||
color: #34495e;
|
|
||||||
margin-top: 0.5em;
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-editor p {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-editor ol, .ql-editor ul {
|
|
||||||
padding-left: 1.5em;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-editor li {
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<?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/pembinaan_sanksi/create.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,136 +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: 14px;">
|
|
||||||
<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: 14px;">
|
|
||||||
<?php if($riwayatUangSaku->count() > 0): ?>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<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>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="margin-top: 14px;">
|
|
||||||
<?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**/ ?>
|
|
||||||
|
|
@ -1,136 +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: 14px;">
|
|
||||||
<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: 6px 11px;">
|
|
||||||
<?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: 22px;">
|
|
||||||
<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: 14px; 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',
|
|
||||||
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: 18px; border-radius: var(--border-radius-sm); border-left: 4px solid var(--primary-color);">
|
|
||||||
<?php echo $berita->konten; ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Info Target Kelas -->
|
|
||||||
<?php if($berita->target_berita === 'kelas_tertentu'): ?>
|
|
||||||
<div class="detail-section">
|
|
||||||
<h4>
|
|
||||||
<i class="fas fa-graduation-cap"></i>
|
|
||||||
Target Kelas
|
|
||||||
</h4>
|
|
||||||
<div style="background: linear-gradient(135deg, #E3F2FD 0%, #D1E9F9 100%); padding: 14px; 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:
|
|
||||||
<strong><?php echo e($berita->target_audience); ?></strong>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</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**/ ?>
|
|
||||||
|
|
@ -1,149 +0,0 @@
|
||||||
<?php $__env->startSection('title', $berita->judul); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-newspaper"></i> Berita & Pengumuman</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content-box" style="padding: 0; overflow: hidden;">
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($berita->gambar): ?>
|
|
||||||
<div style="width: 100%; max-height: 340px; overflow: hidden; position: relative;">
|
|
||||||
<img src="<?php echo e(asset('storage/' . $berita->gambar)); ?>"
|
|
||||||
alt="<?php echo e($berita->judul); ?>"
|
|
||||||
style="width: 100%; height: 340px; object-fit: cover; display: block;">
|
|
||||||
|
|
||||||
<div style="position: absolute; bottom: 0; left: 0; right: 0; height: 120px;
|
|
||||||
background: linear-gradient(to bottom, transparent, rgba(0,0,0,0.55));"></div>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
|
|
||||||
<div style="background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark, #1a4980) 100%);
|
|
||||||
height: 90px; position: relative; overflow: hidden;">
|
|
||||||
<div style="position: absolute; right: -20px; top: -20px; width: 120px; height: 120px;
|
|
||||||
background: rgba(255,255,255,0.07); border-radius: 50%;"></div>
|
|
||||||
<div style="position: absolute; right: 80px; bottom: -30px; width: 80px; height: 80px;
|
|
||||||
background: rgba(255,255,255,0.05); border-radius: 50%;"></div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="padding: 26px 28px;">
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; flex-wrap: wrap; gap: 10px;">
|
|
||||||
<div style="display: flex; align-items: center; gap: 8px;">
|
|
||||||
<a href="<?php echo e(route('santri.berita.index')); ?>"
|
|
||||||
style="color: var(--primary-color); text-decoration: none; font-size: 0.88em;">
|
|
||||||
<i class="fas fa-newspaper"></i> Berita
|
|
||||||
</a>
|
|
||||||
<i class="fas fa-chevron-right" style="color: var(--text-light); font-size: 0.7em;"></i>
|
|
||||||
<span style="color: var(--text-light); font-size: 0.88em;">Detail</span>
|
|
||||||
</div>
|
|
||||||
<a href="<?php echo e(route('santri.berita.index')); ?>" class="btn btn-secondary btn-sm">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="margin-bottom: 12px; display: flex; gap: 8px; flex-wrap: wrap; align-items: center;">
|
|
||||||
<span class="badge badge-primary" style="font-size: 0.82em;"><?php echo e($berita->id_berita); ?></span>
|
|
||||||
<span class="badge badge-success" style="font-size: 0.82em;">
|
|
||||||
<i class="fas fa-check-circle"></i> Published
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<h2 style="margin: 0 0 14px; color: var(--text-color); font-size: 1.5em; line-height: 1.4;">
|
|
||||||
<?php echo e($berita->judul); ?>
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display: flex; gap: 18px; color: var(--text-light); font-size: 0.88em;
|
|
||||||
padding-bottom: 18px; border-bottom: 2px solid var(--primary-light); flex-wrap: wrap;">
|
|
||||||
<span><i class="fas fa-user" style="color: var(--primary-color);"></i> <?php echo e($berita->penulis); ?></span>
|
|
||||||
<span><i class="fas fa-calendar" style="color: var(--primary-color);"></i>
|
|
||||||
<?php echo e($berita->created_at->isoFormat('dddd, D MMMM YYYY')); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<span><i class="fas fa-clock" style="color: var(--primary-color);"></i>
|
|
||||||
<?php echo e($berita->created_at->format('H:i')); ?> WIB
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="berita-body" style="margin-top: 22px; font-size: 1em; line-height: 1.85; color: var(--text-color);">
|
|
||||||
<?php echo $berita->konten; ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="margin-top: 30px; padding-top: 18px; border-top: 1px solid #eee;
|
|
||||||
display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px;">
|
|
||||||
<p style="margin: 0; color: var(--text-light); font-size: 0.85em;">
|
|
||||||
<i class="fas fa-clock"></i>
|
|
||||||
Terakhir diperbarui: <?php echo e($berita->updated_at->isoFormat('D MMMM YYYY, HH:mm')); ?> WIB
|
|
||||||
</p>
|
|
||||||
<div style="display: flex; gap: 8px;">
|
|
||||||
<a href="<?php echo e(route('santri.berita.index')); ?>" class="btn btn-primary btn-sm">
|
|
||||||
<i class="fas fa-list"></i> Berita Lainnya
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('santri.dashboard')); ?>" class="btn btn-secondary btn-sm">
|
|
||||||
<i class="fas fa-home"></i> Dashboard
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.berita-body h1, .berita-body h2, .berita-body h3 {
|
|
||||||
color: var(--primary-color);
|
|
||||||
margin-top: 20px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
.berita-body h1 { font-size: 1.5em; border-bottom: 2px solid var(--primary-light); padding-bottom: 8px; }
|
|
||||||
.berita-body h2 { font-size: 1.25em; }
|
|
||||||
.berita-body h3 { font-size: 1.1em; }
|
|
||||||
.berita-body p { margin-bottom: 14px; }
|
|
||||||
.berita-body ul, .berita-body ol {
|
|
||||||
margin-left: 24px;
|
|
||||||
margin-bottom: 14px;
|
|
||||||
}
|
|
||||||
.berita-body li { margin-bottom: 6px; }
|
|
||||||
.berita-body strong { color: #2c3e50; font-weight: 600; }
|
|
||||||
.berita-body blockquote {
|
|
||||||
border-left: 4px solid var(--primary-color);
|
|
||||||
margin: 0 0 14px;
|
|
||||||
padding: 10px 16px;
|
|
||||||
background: var(--primary-light);
|
|
||||||
border-radius: 0 6px 6px 0;
|
|
||||||
color: var(--primary-dark, #1a4980);
|
|
||||||
}
|
|
||||||
.berita-body img {
|
|
||||||
max-width: 100%;
|
|
||||||
border-radius: var(--border-radius-sm);
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
.berita-body table {
|
|
||||||
width: 100%;
|
|
||||||
border-collapse: collapse;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
font-size: 0.95em;
|
|
||||||
}
|
|
||||||
.berita-body table td, .berita-body table th {
|
|
||||||
border: 1px solid #dee2e6;
|
|
||||||
padding: 9px 12px;
|
|
||||||
}
|
|
||||||
.berita-body table th {
|
|
||||||
background: var(--primary-light);
|
|
||||||
color: var(--primary-color);
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<?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/berita/show.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,207 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Kelola Kelas Santri'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-layer-group"></i> Kelola Kelas Santri</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Flash Messages -->
|
|
||||||
<?php if(session('success')): ?>
|
|
||||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
|
||||||
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
|
|
||||||
|
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if(session('error')): ?>
|
|
||||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
|
||||||
<i class="fas fa-exclamation-circle"></i> <?php echo e(session('error')); ?>
|
|
||||||
|
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<!-- Quick Navigation Menu -->
|
|
||||||
<div class="content-box" style="margin-bottom: 14px; 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; flex-wrap: wrap; gap: 11px;">
|
|
||||||
<div>
|
|
||||||
<h4 style="margin: 0; color: var(--primary-dark); display: flex; align-items: center; gap: 10px;">
|
|
||||||
<i class="fas fa-layer-group"></i>
|
|
||||||
Menu Manajemen Kelas
|
|
||||||
</h4>
|
|
||||||
<p style="margin: 5px 0 0 0; color: var(--text-light); font-size: 0.9rem;">
|
|
||||||
Kelola kelompok kelas, daftar kelas, dan kenaikan kelas tahunan
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
|
|
||||||
<a href="<?php echo e(route('admin.kelas.kelompok.index')); ?>" class="btn btn-info">
|
|
||||||
<i class="fas fa-folder"></i> Kelompok Kelas
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.kelas.kenaikan.index')); ?>" class="btn btn-success">
|
|
||||||
<i class="fas fa-graduation-cap"></i> Kenaikan Kelas
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Header Actions -->
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 11px;">
|
|
||||||
<!-- Search & Filter Form -->
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.kelas.index')); ?>" style="display: flex; gap: 10px; flex-wrap: wrap; flex-grow: 1;">
|
|
||||||
<input type="text"
|
|
||||||
name="search"
|
|
||||||
class="form-control"
|
|
||||||
placeholder="Cari nama atau kode kelas..."
|
|
||||||
value="<?php echo e(request('search')); ?>"
|
|
||||||
style="max-width: 300px;">
|
|
||||||
|
|
||||||
<select name="kelompok" class="form-control" style="max-width: 200px;">
|
|
||||||
<option value="">Semua Kelompok</option>
|
|
||||||
<?php $__currentLoopData = $kelompokKelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelompok): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($kelompok->id_kelompok); ?>"
|
|
||||||
<?php echo e(request('kelompok') == $kelompok->id_kelompok ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($kelompok->nama_kelompok); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select name="status" class="form-control" style="max-width: 150px;">
|
|
||||||
<option value="">Semua Status</option>
|
|
||||||
<option value="active" <?php echo e(request('status') == 'active' ? 'selected' : ''); ?>>Aktif</option>
|
|
||||||
<option value="inactive" <?php echo e(request('status') == 'inactive' ? 'selected' : ''); ?>>Tidak Aktif</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
<i class="fas fa-search"></i> Filter
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<a href="<?php echo e(route('admin.kelas.index')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-redo"></i> Reset
|
|
||||||
</a>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Action Button -->
|
|
||||||
<div>
|
|
||||||
<a href="<?php echo e(route('admin.kelas.create')); ?>" class="btn btn-success">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Kelas Baru
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Kelas List -->
|
|
||||||
<div class="content-box">
|
|
||||||
<?php if($kelas->count() > 0): ?>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 50px;">No</th>
|
|
||||||
<th>Kode Kelas</th>
|
|
||||||
<th>Nama Kelas</th>
|
|
||||||
<th>Kelompok</th>
|
|
||||||
<th style="width: 80px;">Urutan</th>
|
|
||||||
<th style="width: 100px;">Status</th>
|
|
||||||
<th style="width: 150px;">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $kelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($kelas->firstItem() + $index); ?></td>
|
|
||||||
<td><strong><?php echo e($item->kode_kelas); ?></strong></td>
|
|
||||||
<td><?php echo e($item->nama_kelas); ?></td>
|
|
||||||
<td>
|
|
||||||
<span class="badge badge-info">
|
|
||||||
<?php echo e($item->kelompok->nama_kelompok); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="text-center"><?php echo e($item->urutan); ?></td>
|
|
||||||
<td>
|
|
||||||
<?php if($item->is_active): ?>
|
|
||||||
<span class="badge badge-success">
|
|
||||||
<i class="fas fa-check-circle"></i> Aktif
|
|
||||||
</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="badge badge-secondary">
|
|
||||||
<i class="fas fa-times-circle"></i> Tidak Aktif
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div style="display: flex; gap: 5px;">
|
|
||||||
<a href="<?php echo e(route('admin.kelas.show', $item->id)); ?>"
|
|
||||||
class="btn btn-sm btn-info"
|
|
||||||
title="Lihat Detail">
|
|
||||||
<i class="fas fa-eye"></i>
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.kelas.edit', $item->id)); ?>"
|
|
||||||
class="btn btn-sm btn-warning"
|
|
||||||
title="Edit">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
<form action="<?php echo e(route('admin.kelas.destroy', $item->id)); ?>"
|
|
||||||
method="POST"
|
|
||||||
style="display: inline;"
|
|
||||||
onsubmit="return confirm('Apakah Anda yakin ingin menghapus kelas <?php echo e($item->nama_kelas); ?>?')">
|
|
||||||
<?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>
|
|
||||||
|
|
||||||
<!-- Pagination -->
|
|
||||||
<?php if($kelas->hasPages()): ?>
|
|
||||||
<div style="margin-top: 14px;">
|
|
||||||
<?php echo e($kelas->links('vendor.pagination.custom')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php else: ?>
|
|
||||||
<!-- Empty State -->
|
|
||||||
<div class="text-center py-5">
|
|
||||||
<i class="fas fa-layer-group fa-3x text-muted mb-3"></i>
|
|
||||||
<h5 class="text-muted">Tidak ada data kelas</h5>
|
|
||||||
<p class="text-muted">
|
|
||||||
<?php if(request()->has('search') || request()->has('kelompok') || request()->has('status')): ?>
|
|
||||||
Tidak ada kelas yang sesuai dengan filter.
|
|
||||||
<?php else: ?>
|
|
||||||
Belum ada kelas yang ditambahkan.
|
|
||||||
<?php endif; ?>
|
|
||||||
</p>
|
|
||||||
<?php if(!request()->has('search') && !request()->has('kelompok') && !request()->has('status')): ?>
|
|
||||||
<a href="<?php echo e(route('admin.kelas.create')); ?>" class="btn btn-success mt-2">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Kelas Baru
|
|
||||||
</a>
|
|
||||||
<?php else: ?>
|
|
||||||
<a href="<?php echo e(route('admin.kelas.index')); ?>" class="btn btn-secondary mt-2">
|
|
||||||
<i class="fas fa-redo"></i> Reset Filter
|
|
||||||
</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</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/kelas/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,479 +0,0 @@
|
||||||
<?php $__env->startSection('title', 'Tambah Izin Kepulangan'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-plus-circle"></i> Tambah Izin Kepulangan</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="background: #E8F7F2; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #6FBA9D;">
|
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px;">
|
|
||||||
<div>
|
|
||||||
<strong> Periode Kuota:</strong><br>
|
|
||||||
<?php echo e($settings->periode_mulai->format('d M Y')); ?> - <?php echo e($settings->periode_akhir->format('d M Y')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<strong> Kuota Maksimal:</strong><br>
|
|
||||||
<?php echo e($settings->kuota_maksimal); ?> Hari / Tahun
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($errors->any()): ?>
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<ul style="margin: 0; padding-left: 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.kepulangan.store')); ?>" method="POST" id="kepulanganForm">
|
|
||||||
<?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: #dc3545;">*</span>
|
|
||||||
</label>
|
|
||||||
<select name="id_santri" id="id_santri" class="form-control" 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->id_santri); ?> - <?php echo e($santri->kelas); ?>)
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="santriInfo" style="display: none; background: #f8f9fa; padding: 14px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #6FBA9D;">
|
|
||||||
<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>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>
|
|
||||||
|
|
||||||
|
|
||||||
<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>âš ï¸ PERHATIAN:</strong> <span id="warningText"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 14px;">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="tanggal_pulang">
|
|
||||||
<i class="fas fa-calendar-alt form-icon"></i>
|
|
||||||
Tanggal Pulang <span style="color: #dc3545;">*</span>
|
|
||||||
</label>
|
|
||||||
<input type="date"
|
|
||||||
name="tanggal_pulang"
|
|
||||||
id="tanggal_pulang"
|
|
||||||
class="form-control"
|
|
||||||
value="<?php echo e(old('tanggal_pulang', date('Y-m-d'))); ?>"
|
|
||||||
min="<?php echo e(date('Y-m-d')); ?>"
|
|
||||||
required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="tanggal_kembali">
|
|
||||||
<i class="fas fa-calendar-check form-icon"></i>
|
|
||||||
Tanggal Kembali <span style="color: #dc3545;">*</span>
|
|
||||||
</label>
|
|
||||||
<input type="date"
|
|
||||||
name="tanggal_kembali"
|
|
||||||
id="tanggal_kembali"
|
|
||||||
class="form-control"
|
|
||||||
value="<?php echo e(old('tanggal_kembali')); ?>"
|
|
||||||
required>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="durasiInfo" style="display: none; background: #fff3e0; padding: 14px; border-radius: 8px; margin-bottom: 14px; 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: 11px;">
|
|
||||||
<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 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 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;"><?php echo e($settings->kuota_maksimal); ?></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: #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>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="alasan">
|
|
||||||
<i class="fas fa-comment-alt form-icon"></i>
|
|
||||||
Alasan Kepulangan <span style="color: #dc3545;">*</span>
|
|
||||||
</label>
|
|
||||||
<textarea name="alasan"
|
|
||||||
id="alasan"
|
|
||||||
class="form-control"
|
|
||||||
rows="4"
|
|
||||||
placeholder="Jelaskan alasan kepulangan"
|
|
||||||
required><?php echo e(old('alasan')); ?></textarea>
|
|
||||||
<small style="color: #7F8C8D; margin-top: 5px; display: block;">
|
|
||||||
<span id="charCount">0</span>/500 karakter
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
|
|
||||||
<button type="submit" class="btn btn-primary" id="submitBtn">
|
|
||||||
<i class="fas fa-save"></i> Simpan Izin Kepulangan
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-undo"></i> Reset Form
|
|
||||||
</button>
|
|
||||||
<a href="<?php echo e(route('admin.kepulangan.index')); ?>" class="btn btn-danger">
|
|
||||||
<i class="fas fa-times"></i> Batal
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" id="overLimitModal" tabindex="-1" style="display: none;">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
|
||||||
<div style="margin-bottom: 14px;">
|
|
||||||
<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 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: 14px;">
|
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('overLimitModal')">Batal</button>
|
|
||||||
<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>
|
|
||||||
</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-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>
|
|
||||||
let currentSantriData = null;
|
|
||||||
let isOverLimit = false;
|
|
||||||
|
|
||||||
// Load santri data when selected
|
|
||||||
document.getElementById('id_santri').addEventListener('change', function() {
|
|
||||||
const santriId = this.value;
|
|
||||||
|
|
||||||
if (!santriId) {
|
|
||||||
document.getElementById('santriInfo').style.display = 'none';
|
|
||||||
currentSantriData = null;
|
|
||||||
calculateDurasi();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const infoDiv = document.getElementById('santriInfo');
|
|
||||||
infoDiv.style.display = 'block';
|
|
||||||
|
|
||||||
// Show loading state
|
|
||||||
infoDiv.innerHTML = '<div style="text-align: center; padding: 14px;"><i class="fas fa-spinner fa-spin"></i> Memuat data santri...</div>';
|
|
||||||
|
|
||||||
// PERBAIKAN: Proper error handling untuk API
|
|
||||||
fetch(`/admin/kepulangan/api/santri/${santriId}`)
|
|
||||||
.then(response => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Network response was not ok');
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(data => {
|
|
||||||
if (data.success) {
|
|
||||||
currentSantriData = data;
|
|
||||||
updateSantriInfo(data);
|
|
||||||
calculateDurasi();
|
|
||||||
} else {
|
|
||||||
showError(data.message || 'Gagal memuat data santri');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error:', error);
|
|
||||||
showError('Terjadi kesalahan saat memuat data santri: ' + error.message);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// PERBAIKAN: Function untuk show error
|
|
||||||
function showError(message) {
|
|
||||||
const infoDiv = document.getElementById('santriInfo');
|
|
||||||
infoDiv.innerHTML = `
|
|
||||||
<div style="padding: 15px; background: #ffebee; border: 1px solid #ffcdd2; border-radius: 6px; color: #c62828;">
|
|
||||||
<i class="fas fa-exclamation-circle"></i>
|
|
||||||
<strong>Error:</strong> ${message}
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
currentSantriData = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateSantriInfo(data) {
|
|
||||||
const santri = data.santri;
|
|
||||||
const kuota = data.penggunaan_izin;
|
|
||||||
|
|
||||||
// Rebuild HTML structure
|
|
||||||
const infoDiv = document.getElementById('santriInfo');
|
|
||||||
infoDiv.innerHTML = `
|
|
||||||
<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">${santri.nama_lengkap}</span></p>
|
|
||||||
<p style="margin: 5px 0;"><strong>Kelas:</strong> <span id="santriKelas">${santri.kelas}</span></p>
|
|
||||||
<p style="margin: 5px 0;"><strong>Periode:</strong> <span id="santriPeriode">${kuota.periode_mulai} - ${kuota.periode_akhir}</span></p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p style="margin: 5px 0;"><strong>Kuota Maksimal:</strong> <span id="kuotaMaksimal">${kuota.kuota_maksimal} hari</span></p>
|
|
||||||
<p style="margin: 5px 0;"><strong>Total Terpakai:</strong> <span id="totalTerpakai" class="badge" style="background: ${getBadgeColor(kuota.badge_color)}; color: ${kuota.badge_color === 'warning' ? '#000' : 'white'};">${kuota.total_terpakai} hari</span></p>
|
|
||||||
<p style="margin: 5px 0;"><strong>Sisa Kuota:</strong> <span id="sisaKuota" class="badge" style="background: ${getBadgeColor(kuota.badge_color)}; color: ${kuota.badge_color === 'warning' ? '#000' : 'white'};">${kuota.sisa_kuota} hari</span></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<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: ${Math.min(100, kuota.persentase)}%; background: ${getProgressColor(kuota.persentase)}; transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.75rem; font-weight: 600;">${kuota.persentase}%</div>
|
|
||||||
</div>
|
|
||||||
<small id="progressText" style="color: #7F8C8D; margin-top: 5px; display: block;">${kuota.persentase}% dari kuota terpakai</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="warningOverLimit" style="display: ${kuota.status === 'melebihi' ? 'block' : '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>âš ï¸ PERHATIAN:</strong> <span id="warningText">Santri ini sudah melebihi kuota ${kuota.kuota_maksimal} hari per tahun! Total terpakai: ${kuota.total_terpakai} hari.</span>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBadgeColor(badge) {
|
|
||||||
const colors = {
|
|
||||||
'success': '#28a745',
|
|
||||||
'warning': '#ffc107',
|
|
||||||
'danger': '#dc3545'
|
|
||||||
};
|
|
||||||
return colors[badge] || '#6c757d';
|
|
||||||
}
|
|
||||||
|
|
||||||
function getProgressColor(persentase) {
|
|
||||||
if (persentase >= 100) return '#dc3545';
|
|
||||||
if (persentase >= 80) return '#ffc107';
|
|
||||||
return '#28a745';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate durasi when dates change
|
|
||||||
document.getElementById('tanggal_pulang').addEventListener('change', calculateDurasi);
|
|
||||||
document.getElementById('tanggal_kembali').addEventListener('change', calculateDurasi);
|
|
||||||
|
|
||||||
function calculateDurasi() {
|
|
||||||
const tanggalPulang = document.getElementById('tanggal_pulang').value;
|
|
||||||
const tanggalKembali = document.getElementById('tanggal_kembali').value;
|
|
||||||
const durasiInfoDiv = document.getElementById('durasiInfo');
|
|
||||||
|
|
||||||
if (!tanggalPulang || !tanggalKembali) {
|
|
||||||
durasiInfoDiv.style.display = 'none';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const startDate = new Date(tanggalPulang);
|
|
||||||
const endDate = new Date(tanggalKembali);
|
|
||||||
|
|
||||||
if (endDate <= startDate) {
|
|
||||||
durasiInfoDiv.style.display = 'none';
|
|
||||||
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 = <?php echo e($settings->kuota_maksimal); ?> - diffDays;
|
|
||||||
let showWarning = false;
|
|
||||||
let warningMessage = '';
|
|
||||||
|
|
||||||
if (currentSantriData) {
|
|
||||||
const currentUsage = currentSantriData.penggunaan_izin.total_terpakai;
|
|
||||||
const kuotaMaks = currentSantriData.penggunaan_izin.kuota_maksimal;
|
|
||||||
|
|
||||||
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 ${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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 (PERBAIKAN: Tidak ada validasi minimal)
|
|
||||||
document.getElementById('alasan').addEventListener('input', function() {
|
|
||||||
const current = this.value.length;
|
|
||||||
const counter = document.getElementById('charCount');
|
|
||||||
counter.textContent = current;
|
|
||||||
|
|
||||||
if (current > 500) {
|
|
||||||
counter.style.color = 'red';
|
|
||||||
} else {
|
|
||||||
counter.style.color = '#7F8C8D';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Form submission with over limit confirmation
|
|
||||||
document.getElementById('kepulanganForm').addEventListener('submit', function(e) {
|
|
||||||
if (isOverLimit) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
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';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Confirm over limit submission
|
|
||||||
document.getElementById('confirmOverLimit').addEventListener('click', function() {
|
|
||||||
closeModal('overLimitModal');
|
|
||||||
isOverLimit = false;
|
|
||||||
document.getElementById('kepulanganForm').submit();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Auto-set minimum tanggal_kembali
|
|
||||||
document.getElementById('tanggal_pulang').addEventListener('change', function() {
|
|
||||||
const pulangDate = new Date(this.value);
|
|
||||||
pulangDate.setDate(pulangDate.getDate() + 1);
|
|
||||||
|
|
||||||
const minKembaliDate = pulangDate.toISOString().split('T')[0];
|
|
||||||
document.getElementById('tanggal_kembali').min = minKembaliDate;
|
|
||||||
|
|
||||||
const currentKembali = document.getElementById('tanggal_kembali').value;
|
|
||||||
if (currentKembali && currentKembali <= this.value) {
|
|
||||||
document.getElementById('tanggal_kembali').value = minKembaliDate;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initialize
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
const today = new Date().toISOString().split('T')[0];
|
|
||||||
document.getElementById('tanggal_pulang').min = today;
|
|
||||||
|
|
||||||
const alasanField = document.getElementById('alasan');
|
|
||||||
document.getElementById('charCount').textContent = alasanField.value.length;
|
|
||||||
|
|
||||||
calculateDurasi();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Form reset handler
|
|
||||||
document.querySelector('button[type="reset"]').addEventListener('click', function() {
|
|
||||||
setTimeout(() => {
|
|
||||||
document.getElementById('santriInfo').style.display = 'none';
|
|
||||||
document.getElementById('durasiInfo').style.display = 'none';
|
|
||||||
currentSantriData = null;
|
|
||||||
isOverLimit = false;
|
|
||||||
document.getElementById('charCount').textContent = '0';
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Helper functions
|
|
||||||
function closeModal(modalId) {
|
|
||||||
document.getElementById(modalId).style.display = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close modal 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) {
|
|
||||||
this.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</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/kepulangan/create.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
<?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**/ ?>
|
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="id">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Bukti Pembayaran SPP - <?php echo e($pembayaranSpp->id_pembayaran); ?></title>
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body { font-family: Arial, sans-serif; padding: 30px; font-size: 13px; }
|
||||||
|
|
||||||
|
.bukti-container { max-width: 600px; margin: 0 auto; border: 3px solid #6FBA9D; border-radius: 10px; padding: 25px; }
|
||||||
|
|
||||||
|
/* ── KOP SURAT ─────────────────────────────────── */
|
||||||
|
.kop { display: flex; align-items: center; gap: 16px; padding-bottom: 12px; border-bottom: 3px double #6FBA9D; margin-bottom: 8px; }
|
||||||
|
.kop img { width: 72px; height: 72px; object-fit: contain; flex-shrink: 0; }
|
||||||
|
.kop-text { flex: 1; text-align: center; }
|
||||||
|
.kop-text .nama-lembaga { font-size: 17px; font-weight: bold; color: #1a1a1a; letter-spacing: .4px; text-transform: uppercase; }
|
||||||
|
.kop-text .nama-singkat { font-size: 13px; color: #555; margin: 2px 0; }
|
||||||
|
.kop-text .alamat { font-size: 10.5px; color: #555; line-height: 16px; margin-top: 4px; }
|
||||||
|
|
||||||
|
/* ── JUDUL DOKUMEN ─────────────────────────────── */
|
||||||
|
.header { text-align: center; margin: 14px 0 20px; }
|
||||||
|
.header h2 { font-size: 15px; color: #6FBA9D; letter-spacing: 2px; text-transform: uppercase; }
|
||||||
|
.header p { font-size: 12px; color: #666; margin-top: 4px; }
|
||||||
|
|
||||||
|
.bukti-info { background: #f9f9f9; padding: 20px; border-radius: 8px; margin-bottom: 20px; }
|
||||||
|
.bukti-info table { width: 100%; }
|
||||||
|
.bukti-info tr { line-height: 28px; }
|
||||||
|
.bukti-info td:first-child { font-weight: bold; width: 160px; color: #555; }
|
||||||
|
.bukti-info td:nth-child(2) { width: 20px; }
|
||||||
|
.bukti-info td:last-child { color: #333; }
|
||||||
|
|
||||||
|
.nominal-box { background: linear-gradient(135deg, #6FBA9D 0%, #8FCAAE 100%); color: white; padding: 20px; border-radius: 8px; text-align: center; margin: 25px 0; }
|
||||||
|
.nominal-box h3 { font-size: 14px; margin-bottom: 10px; opacity: .9; }
|
||||||
|
.nominal-box .amount { font-size: 32px; font-weight: bold; letter-spacing: 1px; }
|
||||||
|
|
||||||
|
.status-box { text-align: center; padding: 15px; border-radius: 8px; margin-bottom: 20px; }
|
||||||
|
.status-lunas { background: #d4edda; color: #155724; border: 2px solid #c3e6cb; }
|
||||||
|
.status-belum { background: #fff3cd; color: #856404; border: 2px solid #ffeaa7; }
|
||||||
|
|
||||||
|
.footer { text-align: center; margin-top: 30px; padding-top: 20px; border-top: 2px dashed #ddd; }
|
||||||
|
.footer p { font-size: 11px; color: #888; line-height: 18px; }
|
||||||
|
|
||||||
|
.ttd-section { margin-top: 40px; display: flex; justify-content: flex-end; }
|
||||||
|
.ttd-box { text-align: center; width: 45%; }
|
||||||
|
.ttd-box p { margin-bottom: 60px; font-size: 12px; }
|
||||||
|
.ttd-box strong { font-size: 13px; border-top: 1px solid #333; padding-top: 5px; display: inline-block; }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
body { padding: 0; }
|
||||||
|
.no-print { display: none; }
|
||||||
|
@page { margin: 1.5cm; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- Tombol Print -->
|
||||||
|
<div class="no-print" style="text-align:center; margin-bottom:20px;">
|
||||||
|
<button onclick="window.print()" style="padding:12px 30px; background:#6FBA9D; color:white; border:none; border-radius:5px; cursor:pointer; font-size:14px;">
|
||||||
|
Cetak Bukti
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bukti-container">
|
||||||
|
|
||||||
|
<!-- ══ KOP SURAT ══ -->
|
||||||
|
<div class="kop">
|
||||||
|
<img src="<?php echo e(asset('images/logo.png')); ?>" alt="Logo PKPPS Riyadlul Jannah">
|
||||||
|
<div class="kop-text">
|
||||||
|
<div class="nama-lembaga">PKPPS Riyadlul Jannah Mojokerto</div>
|
||||||
|
<div class="alamat">
|
||||||
|
Jl. Raya Brangkal No. 42 RT. 02 RW. 01, Desa Brangkal<br>
|
||||||
|
Kec. Sooko, Kab. Mojokerto, Prov. Jawa Timur
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ══ JUDUL DOKUMEN ══ -->
|
||||||
|
<div class="header">
|
||||||
|
<h2>Bukti Pembayaran SPP</h2>
|
||||||
|
<p>No. Bukti: <strong><?php echo e($pembayaranSpp->id_pembayaran); ?></strong></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Status -->
|
||||||
|
<?php if($pembayaranSpp->status === 'Lunas'): ?>
|
||||||
|
<div class="status-box status-lunas">
|
||||||
|
<strong style="font-size:16px;">✓ LUNAS</strong>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="status-box status-belum">
|
||||||
|
<strong style="font-size:16px;">⚠ BELUM LUNAS</strong>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- Info Santri & Pembayaran -->
|
||||||
|
<div class="bukti-info">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>ID Santri</td>
|
||||||
|
<td>:</td>
|
||||||
|
<td><?php echo e($pembayaranSpp->santri->id_santri); ?></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nama Santri</td>
|
||||||
|
<td>:</td>
|
||||||
|
<td><strong><?php echo e($pembayaranSpp->santri->nama_lengkap); ?></strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Periode Pembayaran</td>
|
||||||
|
<td>:</td>
|
||||||
|
<td><strong><?php echo e($pembayaranSpp->periode_lengkap); ?></strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Tanggal Bayar</td>
|
||||||
|
<td>:</td>
|
||||||
|
<td>
|
||||||
|
<?php if($pembayaranSpp->tanggal_bayar): ?>
|
||||||
|
<?php echo e($pembayaranSpp->tanggal_bayar->format('d F Y')); ?>
|
||||||
|
|
||||||
|
<?php else: ?>
|
||||||
|
<span style="color:#999;">Belum dibayar</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php if($pembayaranSpp->keterangan): ?>
|
||||||
|
<tr>
|
||||||
|
<td>Keterangan</td>
|
||||||
|
<td>:</td>
|
||||||
|
<td><?php echo e($pembayaranSpp->keterangan); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Nominal -->
|
||||||
|
<div class="nominal-box">
|
||||||
|
<h3>JUMLAH PEMBAYARAN</h3>
|
||||||
|
<div class="amount"><?php echo e($pembayaranSpp->nominal_format); ?></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tanda Tangan -->
|
||||||
|
<div class="ttd-section">
|
||||||
|
<div class="ttd-box">
|
||||||
|
<p>Petugas</p>
|
||||||
|
<strong>( )</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<div class="footer">
|
||||||
|
<p>
|
||||||
|
<strong>PERHATIAN:</strong><br>
|
||||||
|
Bukti pembayaran ini sah dan merupakan tanda terima yang diakui secara resmi.<br>
|
||||||
|
Simpan bukti ini sebagai arsip pembayaran SPP.<br>
|
||||||
|
Dicetak pada: <?php echo e(date('d F Y, H:i')); ?> WIB
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/pembayaran-spp/cetak-bukti.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', $admin ? 'Edit Akun Admin' : 'Tambah Akun Admin'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2>
|
|
||||||
<i class="fas fa-user-shield"></i>
|
|
||||||
<?php echo e($admin ? 'Edit Akun Admin: ' . $admin->name : 'Tambah Akun Admin'); ?>
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content-box" style="max-width: 540px;">
|
|
||||||
<?php if($errors->any()): ?>
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<ul style="margin:0;padding-left:18px;">
|
|
||||||
<?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; ?>
|
|
||||||
|
|
||||||
<form action="<?php echo e($action); ?>" method="POST" class="data-form">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<?php if($method === 'PUT'): ?>
|
|
||||||
<?php echo method_field('PUT'); ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="name">Nama Lengkap *</label>
|
|
||||||
<input type="text" id="name" name="name"
|
|
||||||
value="<?php echo e(old('name', $admin->name ?? '')); ?>"
|
|
||||||
class="form-control <?php $__errorArgs = ['name'];
|
|
||||||
$__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 = ['name'];
|
|
||||||
$__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="email">Email (digunakan untuk login) *</label>
|
|
||||||
<input type="email" id="email" name="email"
|
|
||||||
value="<?php echo e(old('email', $admin->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>
|
|
||||||
<?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="role">Role *</label>
|
|
||||||
<select id="role" name="role"
|
|
||||||
class="form-control <?php $__errorArgs = ['role'];
|
|
||||||
$__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 Role --</option>
|
|
||||||
<option value="akademik" <?php echo e(old('role', $admin->role ?? '') === 'akademik' ? 'selected' : ''); ?>>
|
|
||||||
Akademik (Data santri, kegiatan, pelanggaran, absensi, rekap)
|
|
||||||
</option>
|
|
||||||
<option value="pamong" <?php echo e(old('role', $admin->role ?? '') === 'pamong' ? 'selected' : ''); ?>>
|
|
||||||
Pamong (Uang saku, absensi RFID, capaian, kesehatan, kepulangan)
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<?php $__errorArgs = ['role'];
|
|
||||||
$__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">
|
|
||||||
Password <?php echo e($admin ? '(kosongkan jika tidak ingin mengganti)' : '*'); ?>
|
|
||||||
|
|
||||||
</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); ?>"
|
|
||||||
<?php echo e($admin ? '' : '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); ?>
|
|
||||||
<small class="form-text text-muted">Minimal 8 karakter.</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="password_confirmation">Konfirmasi Password <?php echo e($admin ? '' : '*'); ?></label>
|
|
||||||
<input type="password" id="password_confirmation" name="password_confirmation"
|
|
||||||
class="form-control"
|
|
||||||
<?php echo e($admin ? '' : 'required'); ?>>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display:flex;gap:10px;margin-top:16px;">
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
<i class="fas fa-save"></i> <?php echo e($admin ? 'Simpan Perubahan' : 'Buat Akun'); ?>
|
|
||||||
|
|
||||||
</button>
|
|
||||||
<a href="<?php echo e(route('admin.users.admin_accounts')); ?>" 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', ['isAdmin' => true], \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/users/admin_form.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,241 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Mapping ID Fingerprint'); ?>
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
|
|
||||||
<div class="page-header" style="display:flex;align-items:center;justify-content:space-between">
|
|
||||||
<h2><i class="fas fa-link"></i> Mapping ID Fingerprint</h2>
|
|
||||||
<a href="<?php echo e(route('admin.kegiatan.index')); ?>" class="btn btn-sm btn-secondary">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
|
||||||
</a>
|
|
||||||
</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-times-circle"></i> <?php echo e(session('error')); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="margin-bottom:14px">
|
|
||||||
<h4 style="margin:0 0 6px;font-size:15px">
|
|
||||||
<i class="fas fa-magic" style="color:#166534"></i> Auto-Import dari INFO.XLS
|
|
||||||
</h4>
|
|
||||||
<p style="margin:0 0 12px;color:#6B7280;font-size:13px">
|
|
||||||
Upload INFO.XLS dari mesin Eppos sistem otomatis cocokkan nama dan buat mapping.
|
|
||||||
Nama yang tidak cocok otomatis ke dropdown untuk dipilih manual.
|
|
||||||
</p>
|
|
||||||
<form action="<?php echo e(route('admin.mesin.mapping-santri.import-info')); ?>"
|
|
||||||
method="POST" enctype="multipart/form-data"
|
|
||||||
style="display:flex;gap:10px;align-items:center;flex-wrap:wrap">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<input type="file" name="file_info" accept=".xls,.xlsx" required
|
|
||||||
class="form-control" style="max-width:320px">
|
|
||||||
<button type="submit" class="btn btn-success">
|
|
||||||
<i class="fas fa-magic"></i> Auto-Import
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$total = $mappings->count();
|
|
||||||
$terpetakan = $mappings->filter(fn($m) => !empty($m->id_santri))->count();
|
|
||||||
$belum = $total - $terpetakan;
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:14px">
|
|
||||||
<div style="background:#F9FAFB;border:1px solid #E5E7EB;border-radius:10px;padding:14px;text-align:center">
|
|
||||||
<div style="font-size:28px;font-weight:700;color:#1F2937"><?php echo e($total); ?></div>
|
|
||||||
<div style="font-size:12px;color:#6B7280">Total ID Mesin</div>
|
|
||||||
</div>
|
|
||||||
<div style="background:#DCFCE7;border:1px solid #BBF7D0;border-radius:10px;padding:14px;text-align:center">
|
|
||||||
<div style="font-size:28px;font-weight:700;color:#166534"><?php echo e($terpetakan); ?></div>
|
|
||||||
<div style="font-size:12px;color:#166534">Terpetakan</div>
|
|
||||||
</div>
|
|
||||||
<div style="background:<?php echo e($belum > 0 ? '#FEE2E2' : '#DCFCE7'); ?>;border:1px solid <?php echo e($belum > 0 ? '#FECACA' : '#BBF7D0'); ?>;border-radius:10px;padding:14px;text-align:center">
|
|
||||||
<div style="font-size:28px;font-weight:700;color:<?php echo e($belum > 0 ? '#991B1B' : '#166534'); ?>"><?php echo e($belum); ?></div>
|
|
||||||
<div style="font-size:12px;color:<?php echo e($belum > 0 ? '#991B1B' : '#166534'); ?>">
|
|
||||||
<?php echo e($belum > 0 ? 'Belum Dipetakan' : 'Semua Terpetakan'); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($belum > 0): ?>
|
|
||||||
<div style="background:#FEF9C3;border:1px solid #FDE68A;border-left:4px solid #F59E0B;
|
|
||||||
border-radius:8px;padding:12px 16px;margin-bottom:14px;font-size:13px">
|
|
||||||
<strong>âš <?php echo e($belum); ?> ID mesin belum dipetakan ke santri.</strong>
|
|
||||||
Data scan santri tersebut tidak akan tersimpan saat import absensi.
|
|
||||||
Pilih santri yang sesuai dari dropdown di bawah.
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="padding:0;overflow:hidden;margin-bottom:14px">
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width:70px;text-align:center">ID Mesin</th>
|
|
||||||
<th>Nama di Mesin</th>
|
|
||||||
<th style="width:90px">Dept/Kel</th>
|
|
||||||
<th>Santri Web yang Dipetakan</th>
|
|
||||||
<th style="width:110px;text-align:center">Status</th>
|
|
||||||
<th style="width:70px;text-align:center">Hapus</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__empty_1 = true; $__currentLoopData = $mappings; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $m): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
|
|
||||||
<tr style="background:<?php echo e(empty($m->id_santri) ? '#FFFBEB' : 'white'); ?>">
|
|
||||||
|
|
||||||
|
|
||||||
<td style="text-align:center">
|
|
||||||
<strong style="font-family:monospace;font-size:15px;color:#1D4ED8">
|
|
||||||
<?php echo e($m->id_mesin); ?>
|
|
||||||
|
|
||||||
</strong>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
|
||||||
<div style="font-weight:600;color:#1F2937"><?php echo e($m->nama_mesin ?? '-'); ?></div>
|
|
||||||
<?php if($m->catatan): ?>
|
|
||||||
<div style="font-size:11px;color:#9CA3AF"><?php echo e($m->catatan); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
|
|
||||||
<td style="color:#6B7280;font-size:12px"><?php echo e($m->dept_mesin ?? '-'); ?></td>
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
|
||||||
<form action="<?php echo e(route('admin.mesin.mapping-santri.update', $m->id)); ?>"
|
|
||||||
method="POST" style="margin:0">
|
|
||||||
<?php echo csrf_field(); ?> <?php echo method_field('PUT'); ?>
|
|
||||||
<div style="display:flex;align-items:center;gap:8px">
|
|
||||||
<select name="id_santri"
|
|
||||||
class="form-control"
|
|
||||||
style="font-size:13px;
|
|
||||||
border-color:<?php echo e(empty($m->id_santri) ? '#FCA5A5' : '#D1D5DB'); ?>;
|
|
||||||
background:<?php echo e(empty($m->id_santri) ? '#FFF5F5' : 'white'); ?>"
|
|
||||||
onchange="this.form.submit()">
|
|
||||||
<option value="">-- Pilih 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($m->id_santri == $s->id_santri ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($s->nama_lengkap); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
<?php if(!empty($m->id_santri)): ?>
|
|
||||||
<i class="fas fa-check-circle" style="color:#22C55E;font-size:16px" title="Sudah dipetakan"></i>
|
|
||||||
<?php else: ?>
|
|
||||||
<i class="fas fa-exclamation-circle" style="color:#EF4444;font-size:16px" title="Belum dipetakan"></i>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
|
|
||||||
<td style="text-align:center">
|
|
||||||
<?php if(!empty($m->id_santri)): ?>
|
|
||||||
<span style="background:#DCFCE7;color:#166534;border-radius:12px;
|
|
||||||
padding:3px 10px;font-size:11px;font-weight:700">
|
|
||||||
Terpetakan
|
|
||||||
</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="background:#FEE2E2;color:#991B1B;border-radius:12px;
|
|
||||||
padding:3px 10px;font-size:11px;font-weight:700">
|
|
||||||
âš Belum
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
|
|
||||||
<td style="text-align:center">
|
|
||||||
<form action="<?php echo e(route('admin.mesin.mapping-santri.destroy', $m->id)); ?>"
|
|
||||||
method="POST"
|
|
||||||
onsubmit="return confirm('Hapus mapping ID Mesin <?php echo e($m->id_mesin); ?> (<?php echo e($m->nama_mesin); ?>)?')">
|
|
||||||
<?php echo csrf_field(); ?> <?php echo method_field('DELETE'); ?>
|
|
||||||
<button type="submit"
|
|
||||||
class="btn btn-sm btn-danger"
|
|
||||||
style="padding:4px 10px">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
|
||||||
<tr>
|
|
||||||
<td colspan="6" style="text-align:center;padding:40px;color:#9CA3AF">
|
|
||||||
<i class="fas fa-inbox" style="font-size:32px;display:block;margin-bottom:8px"></i>
|
|
||||||
Belum ada mapping. Upload INFO.XLS di atas untuk mulai.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<h4 style="margin:0 0 6px;font-size:15px">
|
|
||||||
<i class="fas fa-plus-circle" style="color:#1D4ED8"></i> Tambah Mapping Manual
|
|
||||||
</h4>
|
|
||||||
<p style="margin:0 0 12px;color:#6B7280;font-size:13px">
|
|
||||||
Untuk santri yang baru daftar ke mesin setelah INFO.XLS diekspor,
|
|
||||||
atau santri yang nama di mesin sangat berbeda dari nama di sistem.
|
|
||||||
</p>
|
|
||||||
<form action="<?php echo e(route('admin.mesin.mapping-santri.store')); ?>" method="POST">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<div style="display:grid;grid-template-columns:120px 160px 1fr auto;gap:10px;align-items:end">
|
|
||||||
<div class="form-group" style="margin:0">
|
|
||||||
<label style="font-size:12px;font-weight:600">ID Mesin <span style="color:red">*</span></label>
|
|
||||||
<input type="text" name="id_mesin" class="form-control"
|
|
||||||
placeholder="cth: 8" required value="<?php echo e(old('id_mesin')); ?>"
|
|
||||||
style="font-family:monospace;font-size:15px;font-weight:700">
|
|
||||||
<?php $__errorArgs = ['id_mesin'];
|
|
||||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
|
||||||
if ($__bag->has($__errorArgs[0])) :
|
|
||||||
if (isset($message)) { $__messageOriginal = $message; }
|
|
||||||
$message = $__bag->first($__errorArgs[0]); ?>
|
|
||||||
<p style="color:#EF4444;font-size:11px;margin:3px 0 0"><?php echo e($message); ?></p>
|
|
||||||
<?php unset($message);
|
|
||||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
|
||||||
endif;
|
|
||||||
unset($__errorArgs, $__bag); ?>
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="margin:0">
|
|
||||||
<label style="font-size:12px;font-weight:600">Nama di Mesin</label>
|
|
||||||
<input type="text" name="nama_mesin" class="form-control"
|
|
||||||
placeholder="cth: ilham" value="<?php echo e(old('nama_mesin')); ?>">
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="margin:0">
|
|
||||||
<label style="font-size:12px;font-weight:600">Santri Web</label>
|
|
||||||
<select name="id_santri" class="form-control">
|
|
||||||
<option value="">-- Pilih Santri (bisa diisi nanti) --</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(old('id_santri') == $s->id_santri ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($s->nama_lengkap); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button type="submit" class="btn btn-primary" style="white-space:nowrap;padding:9px 18px">
|
|
||||||
<i class="fas fa-plus"></i> Tambah
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</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/mesin/mapping-santri/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,830 +0,0 @@
|
||||||
<?php $__env->startSection('title', 'Detail: ' . $kegiatan->nama_kegiatan); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
--g: #1a7a5e;
|
|
||||||
--m: #2bbd8e;
|
|
||||||
--sf: #e8f7f2;
|
|
||||||
--tx: #0f1923;
|
|
||||||
--mu: #64748b;
|
|
||||||
--br: #e8edf2;
|
|
||||||
--bg: #f4f7f9;
|
|
||||||
--wh: #ffffff;
|
|
||||||
--sh: 0 2px 12px rgba(0,0,0,0.06);
|
|
||||||
--sh2: 0 6px 28px rgba(0,0,0,0.10);
|
|
||||||
--ra: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
* { box-sizing: border-box; }
|
|
||||||
|
|
||||||
/* ──────────────────────────────────────────────
|
|
||||||
BREADCRUMB / BACK NAV
|
|
||||||
────────────────────────────────────────────── */
|
|
||||||
.sd-nav {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
margin-bottom: 14px;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
color: var(--mu);
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.sd-nav a {
|
|
||||||
color: var(--g);
|
|
||||||
text-decoration: none;
|
|
||||||
font-weight: 600;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 5px;
|
|
||||||
padding: 5px 12px;
|
|
||||||
background: var(--wh);
|
|
||||||
border: 1.5px solid var(--br);
|
|
||||||
border-radius: 8px;
|
|
||||||
transition: all 0.15s;
|
|
||||||
}
|
|
||||||
.sd-nav a:hover { background: var(--sf); border-color: var(--m); }
|
|
||||||
.sd-nav-sep { color: var(--br); font-size: 1rem; }
|
|
||||||
.sd-nav-cur { font-weight: 700; color: var(--tx); }
|
|
||||||
|
|
||||||
/* ──────────────────────────────────────────────
|
|
||||||
HERO CARD — Info Kegiatan
|
|
||||||
────────────────────────────────────────────── */
|
|
||||||
.sd-hero {
|
|
||||||
background: linear-gradient(135deg, #0b3528 0%, #1a7a5e 60%, #28b585 100%);
|
|
||||||
border-radius: var(--ra);
|
|
||||||
padding: 24px 26px 20px;
|
|
||||||
color: white;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.sd-hero::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute; top: -60px; right: -60px;
|
|
||||||
width: 200px; height: 200px; border-radius: 50%;
|
|
||||||
background: rgba(255,255,255,0.05); pointer-events: none;
|
|
||||||
}
|
|
||||||
.sd-hero-inner { position: relative; z-index: 1; }
|
|
||||||
.sd-hero-name {
|
|
||||||
font-size: 1.35rem; font-weight: 800;
|
|
||||||
margin: 0 0 10px; line-height: 1.2;
|
|
||||||
}
|
|
||||||
.sd-hero-chips { display: flex; gap: 7px; flex-wrap: wrap; margin-bottom: 18px; }
|
|
||||||
.sd-chip {
|
|
||||||
background: rgba(255,255,255,0.14);
|
|
||||||
border: 1px solid rgba(255,255,255,0.22);
|
|
||||||
padding: 4px 11px; border-radius: 20px;
|
|
||||||
font-size: 0.77rem; font-weight: 600;
|
|
||||||
display: inline-flex; align-items: center; gap: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Besar 3 KPI di hero ── */
|
|
||||||
.sd-hero-kpi {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
gap: 1px;
|
|
||||||
background: rgba(255,255,255,0.12);
|
|
||||||
border: 1px solid rgba(255,255,255,0.15);
|
|
||||||
border-radius: 10px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.sd-hkpi {
|
|
||||||
padding: 12px 14px;
|
|
||||||
background: rgba(0,0,0,0.08);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.sd-hkpi-val {
|
|
||||||
font-size: 2rem; font-weight: 900; line-height: 1;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
}
|
|
||||||
.sd-hkpi-val.clr-great { color: #4ade80; }
|
|
||||||
.sd-hkpi-val.clr-ok { color: #fcd34d; }
|
|
||||||
.sd-hkpi-val.clr-bad { color: #fca5a5; }
|
|
||||||
.sd-hkpi-val.clr-white { color: #ffffff; }
|
|
||||||
.sd-hkpi-lbl { font-size: 0.75rem; opacity: 0.75; font-weight: 600; }
|
|
||||||
.sd-hkpi-sub { font-size: 0.66rem; opacity: 0.50; margin-top: 2px; }
|
|
||||||
|
|
||||||
/* ──────────────────────────────────────────────
|
|
||||||
FILTER BAR
|
|
||||||
────────────────────────────────────────────── */
|
|
||||||
.sd-filter {
|
|
||||||
background: var(--wh);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 12px 14px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
box-shadow: var(--sh);
|
|
||||||
display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end;
|
|
||||||
}
|
|
||||||
.sd-fg { display: flex; flex-direction: column; gap: 3px; }
|
|
||||||
.sd-fg label {
|
|
||||||
font-size: 0.70rem; font-weight: 700; color: var(--mu);
|
|
||||||
text-transform: uppercase; letter-spacing: 0.5px;
|
|
||||||
}
|
|
||||||
.sd-presets { display: flex; gap: 4px; flex-wrap: wrap; }
|
|
||||||
.sd-pbtn {
|
|
||||||
padding: 6px 11px; border: 1.5px solid var(--br);
|
|
||||||
border-radius: 8px; background: var(--wh);
|
|
||||||
font-size: 0.78rem; font-weight: 600; color: var(--mu);
|
|
||||||
cursor: pointer; transition: all 0.15s; white-space: nowrap;
|
|
||||||
}
|
|
||||||
.sd-pbtn:hover { border-color: var(--m); color: var(--g); background: var(--sf); }
|
|
||||||
.sd-pbtn.active { border-color: var(--g); background: var(--g); color: white; }
|
|
||||||
.sd-drange { display: flex; align-items: center; gap: 5px; }
|
|
||||||
.sd-drange input[type=date] {
|
|
||||||
padding: 6px 9px; border: 1.5px solid var(--br);
|
|
||||||
border-radius: 8px; font-size: 0.79rem; color: var(--tx);
|
|
||||||
}
|
|
||||||
.sd-drange input[type=date]:focus { outline: none; border-color: var(--m); }
|
|
||||||
.sd-drange span { font-size: 0.78rem; font-weight: 600; color: var(--mu); }
|
|
||||||
.sd-apply {
|
|
||||||
padding: 7px 14px; background: var(--g); color: white;
|
|
||||||
border: none; border-radius: 8px;
|
|
||||||
font-size: 0.8rem; font-weight: 700; cursor: pointer;
|
|
||||||
display: inline-flex; align-items: center; gap: 5px;
|
|
||||||
}
|
|
||||||
.sd-apply:hover { background: #155c47; }
|
|
||||||
.sd-finfo {
|
|
||||||
font-size: 0.75rem; color: var(--mu);
|
|
||||||
padding: 5px 9px; background: var(--bg);
|
|
||||||
border-radius: 8px; border: 1px solid var(--br);
|
|
||||||
display: flex; align-items: center; gap: 4px; align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ──────────────────────────────────────────────
|
|
||||||
6 STAT PILL CARDS
|
|
||||||
────────────────────────────────────────────── */
|
|
||||||
.sd-pills {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(6, 1fr);
|
|
||||||
gap: 8px;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
.sd-pill-card {
|
|
||||||
background: var(--wh);
|
|
||||||
border-radius: 11px;
|
|
||||||
padding: 13px 8px 11px;
|
|
||||||
box-shadow: var(--sh);
|
|
||||||
text-align: center;
|
|
||||||
border-bottom: 3px solid transparent;
|
|
||||||
transition: transform 0.15s, box-shadow 0.15s;
|
|
||||||
}
|
|
||||||
.sd-pill-card:hover { transform: translateY(-2px); box-shadow: var(--sh2); }
|
|
||||||
.sd-pill-card.p-green { border-bottom-color: #2bbd8e; }
|
|
||||||
.sd-pill-card.p-amber { border-bottom-color: #f59e0b; }
|
|
||||||
.sd-pill-card.p-blue { border-bottom-color: #3b82f6; }
|
|
||||||
.sd-pill-card.p-purple { border-bottom-color: #8b5cf6; }
|
|
||||||
.sd-pill-card.p-red { border-bottom-color: #e53e3e; }
|
|
||||||
.sd-pill-card.p-teal { border-bottom-color: #0d9488; }
|
|
||||||
.sd-pill-icon {
|
|
||||||
width: 32px; height: 32px; border-radius: 8px;
|
|
||||||
display: flex; align-items: center; justify-content: center;
|
|
||||||
font-size: 0.85rem; margin: 0 auto 7px;
|
|
||||||
}
|
|
||||||
.p-green .sd-pill-icon { background: #d1fae5; color: #059669; }
|
|
||||||
.p-amber .sd-pill-icon { background: #fef3c7; color: #d97706; }
|
|
||||||
.p-blue .sd-pill-icon { background: #dbeafe; color: #2563eb; }
|
|
||||||
.p-purple .sd-pill-icon { background: #ede9fe; color: #7c3aed; }
|
|
||||||
.p-red .sd-pill-icon { background: #fee2e2; color: #dc2626; }
|
|
||||||
.p-teal .sd-pill-icon { background: #ccfbf1; color: #0f766e; }
|
|
||||||
.sd-pill-val { font-size: 1.6rem; font-weight: 800; color: var(--tx); line-height: 1; }
|
|
||||||
.sd-pill-lbl { font-size: 0.71rem; color: var(--mu); margin-top: 3px; font-weight: 500; }
|
|
||||||
|
|
||||||
/* ──────────────────────────────────────────────
|
|
||||||
INSIGHT BANNER (pesan sederhana untuk santri)
|
|
||||||
────────────────────────────────────────────── */
|
|
||||||
.sd-insight {
|
|
||||||
border-radius: 11px;
|
|
||||||
padding: 13px 16px;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
display: flex; align-items: center; gap: 12px;
|
|
||||||
font-size: 0.84rem; font-weight: 600;
|
|
||||||
}
|
|
||||||
.sd-insight.good { background: #d1fae5; color: #065f46; border: 1px solid #a7f3d0; }
|
|
||||||
.sd-insight.warn { background: #fef3c7; color: #92400e; border: 1px solid #fde68a; }
|
|
||||||
.sd-insight.bad { background: #fee2e2; color: #991b1b; border: 1px solid #fecaca; }
|
|
||||||
.sd-insight-ic { font-size: 1.4rem; flex-shrink: 0; }
|
|
||||||
.sd-insight-text b { display: block; font-size: 0.9rem; margin-bottom: 2px; }
|
|
||||||
|
|
||||||
/* ──────────────────────────────────────────────
|
|
||||||
2 KOLOM — Chart & Distribusi
|
|
||||||
────────────────────────────────────────────── */
|
|
||||||
.sd-row2 {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 3fr 2fr;
|
|
||||||
gap: 14px;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
.sd-card {
|
|
||||||
background: var(--wh);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 18px;
|
|
||||||
box-shadow: var(--sh);
|
|
||||||
}
|
|
||||||
.sd-card-title {
|
|
||||||
font-size: 0.85rem; font-weight: 700; color: var(--tx);
|
|
||||||
margin-bottom: 14px;
|
|
||||||
display: flex; align-items: center; gap: 7px;
|
|
||||||
}
|
|
||||||
.sd-card-title .badge {
|
|
||||||
margin-left: auto;
|
|
||||||
font-size: 0.70rem; color: var(--mu); font-weight: 500;
|
|
||||||
background: var(--bg); padding: 3px 8px; border-radius: 6px;
|
|
||||||
border: 1px solid var(--br);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Progress distribusi */
|
|
||||||
.sd-dist-list { display: flex; flex-direction: column; gap: 10px; }
|
|
||||||
.sd-dist-row { display: flex; align-items: center; gap: 9px; }
|
|
||||||
.sd-dist-lbl { font-size: 0.77rem; font-weight: 600; color: var(--tx); min-width: 72px; }
|
|
||||||
.sd-dist-track{ flex: 1; height: 9px; background: #f1f5f9; border-radius: 5px; overflow: hidden; }
|
|
||||||
.sd-dist-fill { height: 100%; border-radius: 5px; transition: width 0.6s ease; }
|
|
||||||
.sd-dist-val { font-size: 0.73rem; font-weight: 700; color: var(--tx); min-width: 46px; text-align: right; }
|
|
||||||
.sd-dist-pct { font-size: 0.67rem; color: var(--mu); font-weight: 400; }
|
|
||||||
|
|
||||||
/* ──────────────────────────────────────────────
|
|
||||||
TABEL RIWAYAT
|
|
||||||
────────────────────────────────────────────── */
|
|
||||||
.sd-table-wrap {
|
|
||||||
background: var(--wh);
|
|
||||||
border-radius: 12px;
|
|
||||||
box-shadow: var(--sh);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.sd-table-header {
|
|
||||||
padding: 13px 16px;
|
|
||||||
border-bottom: 1px solid var(--br);
|
|
||||||
display: flex; align-items: center; gap: 8px;
|
|
||||||
}
|
|
||||||
.sd-table-header-title {
|
|
||||||
font-size: 0.86rem; font-weight: 700; color: var(--tx);
|
|
||||||
display: flex; align-items: center; gap: 7px;
|
|
||||||
}
|
|
||||||
.sd-count-badge {
|
|
||||||
margin-left: auto;
|
|
||||||
background: var(--sf); color: var(--g);
|
|
||||||
padding: 3px 10px; border-radius: 8px;
|
|
||||||
font-size: 0.72rem; font-weight: 700;
|
|
||||||
}
|
|
||||||
.sd-table { width: 100%; border-collapse: collapse; }
|
|
||||||
.sd-table thead tr { background: var(--bg); }
|
|
||||||
.sd-table th {
|
|
||||||
padding: 9px 14px;
|
|
||||||
text-align: left;
|
|
||||||
font-size: 0.72rem; font-weight: 700; color: var(--mu);
|
|
||||||
text-transform: uppercase; letter-spacing: 0.5px;
|
|
||||||
border-bottom: 1px solid var(--br);
|
|
||||||
}
|
|
||||||
.sd-table td {
|
|
||||||
padding: 10px 14px;
|
|
||||||
font-size: 0.83rem;
|
|
||||||
border-bottom: 1px solid #f5f8fa;
|
|
||||||
color: var(--tx);
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
.sd-table tbody tr:last-child td { border-bottom: none; }
|
|
||||||
.sd-table tbody tr:hover { background: #fafcfd; }
|
|
||||||
|
|
||||||
/* Row highlight berdasarkan status */
|
|
||||||
.sd-table tbody tr.row-alpa { background: #fff5f5; }
|
|
||||||
.sd-table tbody tr.row-alpa:hover { background: #fee2e2; }
|
|
||||||
|
|
||||||
/* Status badge di tabel */
|
|
||||||
.sd-status {
|
|
||||||
padding: 4px 11px; border-radius: 20px;
|
|
||||||
font-size: 0.76rem; font-weight: 700;
|
|
||||||
display: inline-flex; align-items: center; gap: 4px;
|
|
||||||
}
|
|
||||||
.sd-status.hadir { background: #d1fae5; color: #065f46; }
|
|
||||||
.sd-status.terlambat { background: #fef3c7; color: #92400e; }
|
|
||||||
.sd-status.izin { background: #dbeafe; color: #1e40af; }
|
|
||||||
.sd-status.sakit { background: #ede9fe; color: #5b21b6; }
|
|
||||||
.sd-status.alpa { background: #fee2e2; color: #991b1b; }
|
|
||||||
.sd-status.pulang { background: #ccfbf1; color: #0f766e; }
|
|
||||||
|
|
||||||
/* Kolom tanggal + hari */
|
|
||||||
.sd-date-main { font-weight: 700; font-size: 0.84rem; color: var(--tx); }
|
|
||||||
.sd-date-day { font-size: 0.71rem; color: var(--mu); margin-top: 1px; }
|
|
||||||
|
|
||||||
/* Metode chip */
|
|
||||||
.sd-metode {
|
|
||||||
display: inline-flex; align-items: center; gap: 5px;
|
|
||||||
background: var(--bg); border: 1px solid var(--br);
|
|
||||||
padding: 3px 9px; border-radius: 7px;
|
|
||||||
font-size: 0.74rem; font-weight: 600; color: var(--mu);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sd-empty {
|
|
||||||
text-align: center; padding: 44px 20px;
|
|
||||||
color: var(--mu); font-size: 0.84rem;
|
|
||||||
}
|
|
||||||
.sd-empty i { font-size: 2.6rem; opacity: 0.15; display: block; margin-bottom: 10px; }
|
|
||||||
|
|
||||||
/* ──────────────────────────────────────────────
|
|
||||||
PAGINATION
|
|
||||||
────────────────────────────────────────────── */
|
|
||||||
.sd-pagination { padding: 12px 16px; border-top: 1px solid var(--br); }
|
|
||||||
|
|
||||||
@media (max-width: 720px) {
|
|
||||||
.sd-pills { grid-template-columns: repeat(3, 1fr); }
|
|
||||||
.sd-row2 { grid-template-columns: 1fr; }
|
|
||||||
.sd-hero-kpi { grid-template-columns: repeat(3, 1fr); }
|
|
||||||
.sd-table th:nth-child(1),
|
|
||||||
.sd-table td:nth-child(1) { display: none; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="sd-nav">
|
|
||||||
<a href="<?php echo e(route('santri.kegiatan.index')); ?>?tab=<?php echo e($fromTab ?? 'jadwal'); ?>">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali ke Jadwal
|
|
||||||
</a>
|
|
||||||
<span class="sd-nav-sep">›</span>
|
|
||||||
<span class="sd-nav-cur"><?php echo e($kegiatan->nama_kegiatan); ?></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="sd-hero">
|
|
||||||
<div class="sd-hero-inner">
|
|
||||||
<h1 class="sd-hero-name">
|
|
||||||
<i class="fas fa-clipboard-list" style="opacity:0.7;margin-right:4px;"></i>
|
|
||||||
<?php echo e($kegiatan->nama_kegiatan); ?>
|
|
||||||
|
|
||||||
</h1>
|
|
||||||
<div class="sd-hero-chips">
|
|
||||||
<span class="sd-chip"><i class="fas fa-tag"></i> <?php echo e($kegiatan->kategori->nama_kategori); ?></span>
|
|
||||||
<span class="sd-chip"><i class="fas fa-calendar-day"></i> Setiap <?php echo e($kegiatan->hari); ?></span>
|
|
||||||
<span class="sd-chip">
|
|
||||||
<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))); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<?php if($kegiatan->materi): ?>
|
|
||||||
<span class="sd-chip"><i class="fas fa-book-open"></i> <?php echo e(Str::limit($kegiatan->materi, 35)); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="sd-hero-kpi">
|
|
||||||
<div class="sd-hkpi">
|
|
||||||
<?php
|
|
||||||
$clr = $persentaseHadir >= 85 ? 'clr-great' : ($persentaseHadir >= 70 ? 'clr-ok' : 'clr-bad');
|
|
||||||
?>
|
|
||||||
<div class="sd-hkpi-val <?php echo e($clr); ?>"><?php echo e($persentaseHadir); ?>%</div>
|
|
||||||
<div class="sd-hkpi-lbl">Tingkat Kehadiran</div>
|
|
||||||
<div class="sd-hkpi-sub">hadir + terlambat</div>
|
|
||||||
</div>
|
|
||||||
<div class="sd-hkpi">
|
|
||||||
<div class="sd-hkpi-val clr-white"><?php echo e($hadirEfektif); ?></div>
|
|
||||||
<div class="sd-hkpi-lbl">Kali Hadir</div>
|
|
||||||
<div class="sd-hkpi-sub">dari <?php echo e($totalAbsensi); ?> tercatat</div>
|
|
||||||
</div>
|
|
||||||
<div class="sd-hkpi">
|
|
||||||
<div class="sd-hkpi-val <?php echo e(($stats['Alpa'] ?? 0) > 0 ? 'clr-bad' : 'clr-great'); ?>">
|
|
||||||
<?php echo e($stats['Alpa'] ?? 0); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="sd-hkpi-lbl">Kali Alpa</div>
|
|
||||||
<div class="sd-hkpi-sub">tidak masuk tanpa izin</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<form method="GET" action="<?php echo e(route('santri.kegiatan.show', $kegiatan->kegiatan_id)); ?>" id="filterForm">
|
|
||||||
<input type="hidden" name="from_tab" value="<?php echo e($fromTab ?? 'jadwal'); ?>">
|
|
||||||
<input type="hidden" name="preset" id="hPreset" value="<?php echo e($preset); ?>">
|
|
||||||
<input type="hidden" name="date_from" id="hDateFrom" value="<?php echo e(request('date_from')); ?>">
|
|
||||||
<input type="hidden" name="date_to" id="hDateTo" value="<?php echo e(request('date_to')); ?>">
|
|
||||||
|
|
||||||
<div class="sd-filter">
|
|
||||||
<div class="sd-fg">
|
|
||||||
<label><i class="fas fa-bolt"></i> Tampilkan periode</label>
|
|
||||||
<div class="sd-presets" id="presetBtns">
|
|
||||||
<?php $__currentLoopData = [
|
|
||||||
'this_week' => 'Minggu Ini',
|
|
||||||
'this_month' => 'Bulan Ini',
|
|
||||||
'last_month' => 'Bulan Lalu',
|
|
||||||
'last_3m' => '3 Bulan',
|
|
||||||
'all' => 'Semua Data',
|
|
||||||
]; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $v => $l): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<button type="button"
|
|
||||||
class="sd-pbtn <?php echo e($preset === $v ? 'active' : ''); ?>"
|
|
||||||
onclick="setPreset('<?php echo e($v); ?>')"><?php echo e($l); ?></button>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="sd-fg">
|
|
||||||
<label><i class="fas fa-calendar-alt"></i> Rentang kustom</label>
|
|
||||||
<div class="sd-drange">
|
|
||||||
<input type="date" id="inpFrom" value="<?php echo e($dateFrom->format('Y-m-d')); ?>" onchange="setCustom()">
|
|
||||||
<span>—</span>
|
|
||||||
<input type="date" id="inpTo" value="<?php echo e($dateTo->format('Y-m-d')); ?>" onchange="setCustom()">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="sd-apply"><i class="fas fa-sync-alt"></i> Terapkan</button>
|
|
||||||
<div class="sd-finfo">
|
|
||||||
<i class="fas fa-calendar-check" style="color:var(--m);"></i>
|
|
||||||
<?php echo e($dateFrom->locale('id')->isoFormat('D MMM YYYY')); ?> –
|
|
||||||
<?php echo e($dateTo->locale('id')->isoFormat('D MMM YYYY')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="sd-pills">
|
|
||||||
<?php
|
|
||||||
$pillData = [
|
|
||||||
['label' => 'Hadir', 'val' => $stats['Hadir'] ?? 0, 'icon' => 'check-circle', 'cls' => 'p-green'],
|
|
||||||
['label' => 'Terlambat', 'val' => $stats['Terlambat'] ?? 0, 'icon' => 'clock', 'cls' => 'p-amber'],
|
|
||||||
['label' => 'Izin', 'val' => $stats['Izin'] ?? 0, 'icon' => 'info-circle', 'cls' => 'p-blue'],
|
|
||||||
['label' => 'Sakit', 'val' => $stats['Sakit'] ?? 0, 'icon' => 'heartbeat', 'cls' => 'p-purple'],
|
|
||||||
['label' => 'Alpa', 'val' => $stats['Alpa'] ?? 0, 'icon' => 'times-circle', 'cls' => 'p-red'],
|
|
||||||
['label' => 'Pulang', 'val' => $stats['Pulang'] ?? 0, 'icon' => 'home', 'cls' => 'p-teal'],
|
|
||||||
];
|
|
||||||
?>
|
|
||||||
<?php $__currentLoopData = $pillData; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $p): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div class="sd-pill-card <?php echo e($p['cls']); ?>">
|
|
||||||
<div class="sd-pill-icon"><i class="fas fa-<?php echo e($p['icon']); ?>"></i></div>
|
|
||||||
<div class="sd-pill-val"><?php echo e($p['val']); ?></div>
|
|
||||||
<div class="sd-pill-lbl"><?php echo e($p['label']); ?></div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$alpaCount = $stats['Alpa'] ?? 0;
|
|
||||||
$insightCls = $persentaseHadir >= 85 ? 'good' : ($persentaseHadir >= 65 ? 'warn' : 'bad');
|
|
||||||
if ($insightCls === 'good') {
|
|
||||||
$insightIcon = '🎉';
|
|
||||||
$insightJudul = 'Kehadiranmu sangat baik!';
|
|
||||||
$insightMsg = "Kamu hadir $hadirEfektif dari $totalAbsensi sesi yang tercatat. Pertahankan ya!";
|
|
||||||
} elseif ($insightCls === 'warn') {
|
|
||||||
$insightIcon = '⚠️';
|
|
||||||
$insightJudul = 'Kehadiranmu perlu ditingkatkan.';
|
|
||||||
$insightMsg = "Tingkat kehadiranmu $persentaseHadir% dalam periode ini. Yuk lebih rajin lagi!";
|
|
||||||
} else {
|
|
||||||
$insightIcon = '❗';
|
|
||||||
$insightJudul = 'Kehadiranmu sangat rendah.';
|
|
||||||
$insightMsg = "Hanya $persentaseHadir% dari sesi yang dihadiri. Ada $alpaCount kali alpa. Segera konsultasikan ke pembimbing.";
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<?php if($totalAbsensi > 0): ?>
|
|
||||||
<div class="sd-insight <?php echo e($insightCls); ?>">
|
|
||||||
<div class="sd-insight-ic"><?php echo e($insightIcon); ?></div>
|
|
||||||
<div class="sd-insight-text">
|
|
||||||
<b><?php echo e($insightJudul); ?></b>
|
|
||||||
<?php echo e($insightMsg); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
// $absensiByDate sudah dikirim dari controller: ['Y-m-d' => 'Status', ...]
|
|
||||||
// Mencakup SEMUA data dalam range, bukan hanya halaman saat ini
|
|
||||||
|
|
||||||
$statusMeta = [
|
|
||||||
'Hadir' => ['bg'=>'#d1fae5','text'=>'#065f46','border'=>'#6ee7b7','dot'=>'#2bbd8e','icon'=>'✓'],
|
|
||||||
'Terlambat' => ['bg'=>'#fef3c7','text'=>'#92400e','border'=>'#fcd34d','dot'=>'#f59e0b','icon'=>'⏰'],
|
|
||||||
'Izin' => ['bg'=>'#dbeafe','text'=>'#1e40af','border'=>'#93c5fd','dot'=>'#3b82f6','icon'=>'I'],
|
|
||||||
'Sakit' => ['bg'=>'#ede9fe','text'=>'#5b21b6','border'=>'#c4b5fd','dot'=>'#8b5cf6','icon'=>'🏥'],
|
|
||||||
'Alpa' => ['bg'=>'#fee2e2','text'=>'#991b1b','border'=>'#fca5a5','dot'=>'#e53e3e','icon'=>'✗'],
|
|
||||||
'Pulang' => ['bg'=>'#ccfbf1','text'=>'#0f766e','border'=>'#5eead4','dot'=>'#0d9488','icon'=>'🏠'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$distItems = [
|
|
||||||
['label'=>'Hadir', 'val'=>$stats['Hadir'] ?? 0, 'color'=>'#2bbd8e', 'emoji'=>'✅'],
|
|
||||||
['label'=>'Terlambat', 'val'=>$stats['Terlambat'] ?? 0, 'color'=>'#f59e0b', 'emoji'=>'⏰'],
|
|
||||||
['label'=>'Izin', 'val'=>$stats['Izin'] ?? 0, 'color'=>'#3b82f6', 'emoji'=>'ℹ️'],
|
|
||||||
['label'=>'Sakit', 'val'=>$stats['Sakit'] ?? 0, 'color'=>'#8b5cf6', 'emoji'=>'🏥'],
|
|
||||||
['label'=>'Alpa', 'val'=>$stats['Alpa'] ?? 0, 'color'=>'#e53e3e', 'emoji'=>'❌'],
|
|
||||||
['label'=>'Pulang', 'val'=>$stats['Pulang'] ?? 0, 'color'=>'#0d9488', 'emoji'=>'🏠'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$hariSingkat = ['Monday'=>'Sen','Tuesday'=>'Sel','Wednesday'=>'Rab',
|
|
||||||
'Thursday'=>'Kam','Friday'=>'Jum','Saturday'=>'Sab','Sunday'=>'Ahd'];
|
|
||||||
?>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
/* ── Kalender Visual ── */
|
|
||||||
.sd-cal-wrap {
|
|
||||||
background: var(--wh); border-radius: 12px;
|
|
||||||
padding: 18px; box-shadow: var(--sh); margin-bottom: 14px;
|
|
||||||
}
|
|
||||||
.sd-cal-title {
|
|
||||||
font-size: 0.85rem; font-weight: 700; color: var(--tx);
|
|
||||||
margin-bottom: 6px; display: flex; align-items: center; gap: 7px;
|
|
||||||
}
|
|
||||||
.sd-cal-hint {
|
|
||||||
font-size: 0.75rem; color: var(--mu);
|
|
||||||
margin-bottom: 14px; padding: 7px 11px;
|
|
||||||
background: var(--bg); border-radius: 7px;
|
|
||||||
border-left: 3px solid var(--m);
|
|
||||||
display: flex; align-items: center; gap: 6px;
|
|
||||||
}
|
|
||||||
.sd-legend {
|
|
||||||
display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px;
|
|
||||||
}
|
|
||||||
.sd-legend-item {
|
|
||||||
display: inline-flex; align-items: center; gap: 5px;
|
|
||||||
font-size: 0.74rem; font-weight: 600; color: var(--tx);
|
|
||||||
}
|
|
||||||
.sd-legend-dot { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
|
|
||||||
|
|
||||||
.sd-cal-grid { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
||||||
.sd-cal-slot {
|
|
||||||
width: 50px; border-radius: 9px; padding: 7px 4px 6px;
|
|
||||||
text-align: center; border: 1.5px solid #e8edf2;
|
|
||||||
background: #f8fafc; transition: transform 0.12s, box-shadow 0.12s;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
.sd-cal-slot:hover { transform: translateY(-2px); box-shadow: 0 5px 16px rgba(0,0,0,0.13); z-index: 5; }
|
|
||||||
.sd-cal-slot-icon { font-size: 1rem; line-height: 1; margin-bottom: 3px; display: block; }
|
|
||||||
.sd-cal-slot-date { font-size: 0.69rem; font-weight: 800; line-height: 1; display: block; }
|
|
||||||
.sd-cal-slot-day { font-size: 0.60rem; font-weight: 500; opacity: 0.65; display: block; margin-top: 1px; }
|
|
||||||
.sd-cal-slot-lbl { font-size: 0.58rem; font-weight: 700; display: block; margin-top: 3px;
|
|
||||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
||||||
.sd-cal-slot.empty { background: #f1f5f9; border-color: #e2e8f0; opacity: 0.5; }
|
|
||||||
.sd-cal-slot.is-today { outline: 2px solid #f5a623; outline-offset: 2px; }
|
|
||||||
|
|
||||||
/* ── Distribusi ── */
|
|
||||||
.sd-dist2-wrap {
|
|
||||||
background: var(--wh); border-radius: 12px;
|
|
||||||
padding: 18px; box-shadow: var(--sh); margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
.sd-dist2-title {
|
|
||||||
font-size: 0.85rem; font-weight: 700; color: var(--tx);
|
|
||||||
margin-bottom: 14px; display: flex; align-items: center; gap: 7px;
|
|
||||||
}
|
|
||||||
.sd-dist2-list { display: flex; flex-direction: column; gap: 13px; }
|
|
||||||
.sd-dist2-row { display: flex; align-items: center; gap: 10px; }
|
|
||||||
.sd-dist2-emoji { font-size: 1.05rem; width: 22px; text-align: center; flex-shrink: 0; }
|
|
||||||
.sd-dist2-lbl { font-size: 0.82rem; font-weight: 700; color: var(--tx); min-width: 76px; }
|
|
||||||
.sd-dist2-track { flex: 1; height: 12px; background: #f1f5f9; border-radius: 6px; overflow: hidden; }
|
|
||||||
.sd-dist2-fill { height: 100%; border-radius: 6px; }
|
|
||||||
.sd-dist2-val { font-size: 0.82rem; font-weight: 800; color: var(--tx); min-width: 30px; text-align: right; }
|
|
||||||
.sd-dist2-pct { font-size: 0.72rem; color: var(--mu); min-width: 38px; text-align: right; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="sd-cal-wrap">
|
|
||||||
<div class="sd-cal-title">
|
|
||||||
<i class="fas fa-calendar-alt" style="color:var(--m);"></i>
|
|
||||||
Kalender Kehadiran
|
|
||||||
<span style="margin-left:auto;font-size:0.71rem;color:var(--mu);font-weight:500;background:var(--bg);border:1px solid var(--br);padding:3px 9px;border-radius:7px;">
|
|
||||||
<?php echo e($dateFrom->locale('id')->isoFormat('D MMM')); ?> – <?php echo e($dateTo->locale('id')->isoFormat('D MMM YYYY')); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="sd-cal-hint">
|
|
||||||
<i class="fas fa-lightbulb" style="color:var(--m);flex-shrink:0;"></i>
|
|
||||||
Tiap kotak = 1 hari dalam periode filter. Warna = status absensimu. Kotak abu-abu = tidak ada catatan absensi di hari itu.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="sd-legend">
|
|
||||||
<?php $__currentLoopData = $statusMeta; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $sLabel => $sMeta): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div class="sd-legend-item">
|
|
||||||
<div class="sd-legend-dot" style="background:<?php echo e($sMeta['dot']); ?>;"></div> <?php echo e($sLabel); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div class="sd-legend-item">
|
|
||||||
<div class="sd-legend-dot" style="background:#e2e8f0;"></div> Tidak ada catatan
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="sd-cal-grid">
|
|
||||||
<?php $cursor = $dateFrom->copy(); ?>
|
|
||||||
<?php while($cursor->lte($dateTo)): ?>
|
|
||||||
<?php
|
|
||||||
$tgl = $cursor->format('Y-m-d');
|
|
||||||
$status = $absensiByDate[$tgl] ?? null;
|
|
||||||
$meta = $status ? ($statusMeta[$status] ?? null) : null;
|
|
||||||
$hariId = $hariSingkat[$cursor->format('l')] ?? substr($cursor->format('l'), 0, 3);
|
|
||||||
$tglFmt = $cursor->format('d/m');
|
|
||||||
$isToday = $tgl === \Carbon\Carbon::today()->format('Y-m-d');
|
|
||||||
?>
|
|
||||||
<?php if($meta): ?>
|
|
||||||
<div class="sd-cal-slot <?php echo e($isToday ? 'is-today' : ''); ?>"
|
|
||||||
style="background:<?php echo e($meta['bg']); ?>;border-color:<?php echo e($meta['border']); ?>;color:<?php echo e($meta['text']); ?>;"
|
|
||||||
title="<?php echo e($cursor->locale('id')->isoFormat('dddd, D MMMM YYYY')); ?> — <?php echo e($status); ?>">
|
|
||||||
<span class="sd-cal-slot-icon"><?php echo e($meta['icon']); ?></span>
|
|
||||||
<span class="sd-cal-slot-date"><?php echo e($tglFmt); ?></span>
|
|
||||||
<span class="sd-cal-slot-day"><?php echo e($hariId); ?></span>
|
|
||||||
<span class="sd-cal-slot-lbl"><?php echo e($status); ?></span>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="sd-cal-slot empty <?php echo e($isToday ? 'is-today' : ''); ?>"
|
|
||||||
title="<?php echo e($cursor->locale('id')->isoFormat('dddd, D MMMM YYYY')); ?> — Tidak ada catatan">
|
|
||||||
<span class="sd-cal-slot-icon" style="color:#cbd5e1;">–</span>
|
|
||||||
<span class="sd-cal-slot-date" style="color:#94a3b8;"><?php echo e($tglFmt); ?></span>
|
|
||||||
<span class="sd-cal-slot-day" style="color:#94a3b8;"><?php echo e($hariId); ?></span>
|
|
||||||
<span class="sd-cal-slot-lbl" style="color:#d1d5db;">Belum</span>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php $cursor->addDay(); ?>
|
|
||||||
<?php endwhile; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="sd-dist2-wrap">
|
|
||||||
<div class="sd-dist2-title">
|
|
||||||
<i class="fas fa-align-left" style="color:#f5a623;"></i>
|
|
||||||
Perincian Status
|
|
||||||
<span style="margin-left:auto;font-size:0.71rem;color:var(--mu);font-weight:500;background:var(--bg);border:1px solid var(--br);padding:3px 9px;border-radius:7px;"><?php echo e($totalAbsensi); ?> total sesi tercatat</span>
|
|
||||||
</div>
|
|
||||||
<?php if($totalAbsensi > 0): ?>
|
|
||||||
<div class="sd-dist2-list">
|
|
||||||
<?php $__currentLoopData = $distItems; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $d): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php if($d['val'] > 0 || in_array($d['label'], ['Hadir','Alpa'])): ?>
|
|
||||||
<div class="sd-dist2-row">
|
|
||||||
<div class="sd-dist2-emoji"><?php echo e($d['emoji']); ?></div>
|
|
||||||
<div class="sd-dist2-lbl"><?php echo e($d['label']); ?></div>
|
|
||||||
<div class="sd-dist2-track">
|
|
||||||
<div class="sd-dist2-fill" style="width:<?php echo e(round($d['val']/$totalAbsensi*100)); ?>%;background:<?php echo e($d['color']); ?>;"></div>
|
|
||||||
</div>
|
|
||||||
<div class="sd-dist2-val"><?php echo e($d['val']); ?>×</div>
|
|
||||||
<div class="sd-dist2-pct"><?php echo e(round($d['val']/$totalAbsensi*100)); ?>%</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="sd-empty"><i class="fas fa-inbox"></i><p>Belum ada data absensi.</p></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="sd-table-wrap">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="sd-table-header" style="flex-wrap:wrap;gap:8px;">
|
|
||||||
<div class="sd-table-header-title">
|
|
||||||
<i class="fas fa-history" style="color:var(--m);"></i>
|
|
||||||
Rekap Kehadiran
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display:flex;align-items:center;gap:6px;flex-wrap:wrap;flex:1;">
|
|
||||||
<span style="
|
|
||||||
background:#e8f7f2; color:#1a7a5e;
|
|
||||||
border:1px solid #a7f3d0;
|
|
||||||
padding:4px 11px; border-radius:20px;
|
|
||||||
font-size:0.76rem; font-weight:700;
|
|
||||||
display:inline-flex; align-items:center; gap:5px;
|
|
||||||
">
|
|
||||||
<i class="fas fa-calendar-check"></i>
|
|
||||||
<?php echo e($dateFrom->locale('id')->isoFormat('D MMM YYYY')); ?>
|
|
||||||
|
|
||||||
–
|
|
||||||
<?php echo e($dateTo->locale('id')->isoFormat('D MMM YYYY')); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<?php
|
|
||||||
$presetLabels = [
|
|
||||||
'this_week' => 'Minggu Ini',
|
|
||||||
'this_month' => 'Bulan Ini',
|
|
||||||
'last_month' => 'Bulan Lalu',
|
|
||||||
'last_3m' => '3 Bulan Terakhir',
|
|
||||||
'all' => 'Semua Data',
|
|
||||||
'custom' => 'Kustom',
|
|
||||||
];
|
|
||||||
?>
|
|
||||||
<?php if(isset($presetLabels[$preset])): ?>
|
|
||||||
<span style="font-size:0.73rem;color:var(--mu);">
|
|
||||||
(<?php echo e($presetLabels[$preset]); ?>)
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<span class="sd-count-badge"><?php echo e($riwayats->total()); ?> sesi</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="
|
|
||||||
padding:9px 16px;
|
|
||||||
background:#f8fafc;
|
|
||||||
border-bottom:1px solid var(--br);
|
|
||||||
font-size:0.78rem; color:var(--mu);
|
|
||||||
display:flex; align-items:center; gap:6px;
|
|
||||||
">
|
|
||||||
<i class="fas fa-info-circle" style="color:var(--m);"></i>
|
|
||||||
Menampilkan <strong style="color:var(--tx);"><?php echo e($riwayats->total()); ?> catatan absensi</strong>
|
|
||||||
kegiatan <strong style="color:var(--tx);"><?php echo e($kegiatan->nama_kegiatan); ?></strong>
|
|
||||||
dari tanggal <strong style="color:var(--tx);"><?php echo e($dateFrom->locale('id')->isoFormat('D MMM YYYY')); ?></strong>
|
|
||||||
sampai <strong style="color:var(--tx);"><?php echo e($dateTo->locale('id')->isoFormat('D MMM YYYY')); ?></strong>.
|
|
||||||
<?php if($riwayats->hasPages()): ?>
|
|
||||||
Halaman <?php echo e($riwayats->currentPage()); ?> dari <?php echo e($riwayats->lastPage()); ?>.
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($riwayats->count() > 0): ?>
|
|
||||||
<div style="overflow-x:auto;">
|
|
||||||
<table class="sd-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width:42px;">#</th>
|
|
||||||
<th>Tanggal</th>
|
|
||||||
<th>Jam Absen</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th>Cara Absen</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $riwayats; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $idx => $absensi): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$statusLower = strtolower($absensi->status);
|
|
||||||
$rowCls = $statusLower === 'alpa' ? 'row-alpa' : '';
|
|
||||||
$metode = $absensi->metode_absen ?? '';
|
|
||||||
$metodeLabel = $metode === 'Import_Mesin' ? 'Mesin' : ($metode ?: 'Manual');
|
|
||||||
$metodeIcon = $metode === 'RFID' ? 'id-card' : ($metode === 'Import_Mesin' ? 'desktop' : 'hand-pointer');
|
|
||||||
?>
|
|
||||||
<tr class="<?php echo e($rowCls); ?>">
|
|
||||||
<td style="color:#9ca3af;font-size:0.74rem;text-align:center;">
|
|
||||||
<?php echo e($riwayats->firstItem() + $idx); ?>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class="sd-date-main">
|
|
||||||
<?php echo e(\Carbon\Carbon::parse($absensi->tanggal)->format('d M Y')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="sd-date-day">
|
|
||||||
<?php echo e(\Carbon\Carbon::parse($absensi->tanggal)->locale('id')->isoFormat('dddd')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($absensi->waktu_absen): ?>
|
|
||||||
<span style="font-weight:700;color:var(--tx);font-size:0.9rem;">
|
|
||||||
<?php echo e(\Carbon\Carbon::parse($absensi->waktu_absen)->format('H:i')); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<span style="font-size:0.7rem;color:var(--mu);display:block;">WIB</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="color:#d1d5db;font-size:0.8rem;">—</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span class="sd-status <?php echo e($statusLower); ?>">
|
|
||||||
<?php if($absensi->status === 'Hadir'): ?> <i class="fas fa-check"></i>
|
|
||||||
<?php elseif($absensi->status === 'Terlambat'): ?> <i class="fas fa-clock"></i>
|
|
||||||
<?php elseif($absensi->status === 'Izin'): ?> <i class="fas fa-info"></i>
|
|
||||||
<?php elseif($absensi->status === 'Sakit'): ?> <i class="fas fa-heartbeat"></i>
|
|
||||||
<?php elseif($absensi->status === 'Alpa'): ?> <i class="fas fa-times"></i>
|
|
||||||
<?php elseif($absensi->status === 'Pulang'): ?> <i class="fas fa-home"></i>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php echo e($absensi->status); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span class="sd-metode">
|
|
||||||
<i class="fas fa-<?php echo e($metodeIcon); ?>"></i> <?php echo e($metodeLabel); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="sd-pagination">
|
|
||||||
<?php echo e($riwayats->appends(request()->query())->links()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="sd-empty">
|
|
||||||
<i class="fas fa-inbox"></i>
|
|
||||||
<p>Belum ada catatan absensi dalam periode ini.</p>
|
|
||||||
<p style="font-size:0.76rem;margin-top:4px;">
|
|
||||||
Periode aktif: <strong><?php echo e($dateFrom->locale('id')->isoFormat('D MMM YYYY')); ?> – <?php echo e($dateTo->locale('id')->isoFormat('D MMM YYYY')); ?></strong>.
|
|
||||||
Coba pilih periode yang lebih luas di filter atas.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function setPreset(val) {
|
|
||||||
document.querySelectorAll('.sd-pbtn').forEach(b => b.classList.remove('active'));
|
|
||||||
event.target.classList.add('active');
|
|
||||||
document.getElementById('hPreset').value = val;
|
|
||||||
document.getElementById('hDateFrom').value = '';
|
|
||||||
document.getElementById('hDateTo').value = '';
|
|
||||||
document.getElementById('filterForm').submit();
|
|
||||||
}
|
|
||||||
function setCustom() {
|
|
||||||
document.getElementById('hPreset').value = '';
|
|
||||||
document.getElementById('hDateFrom').value = document.getElementById('inpFrom').value;
|
|
||||||
document.getElementById('hDateTo').value = document.getElementById('inpTo').value;
|
|
||||||
document.querySelectorAll('.sd-pbtn').forEach(b => b.classList.remove('active'));
|
|
||||||
}
|
|
||||||
|
|
||||||
</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/show.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Manajemen Akun Admin'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-user-shield"></i> Manajemen Akun Admin</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if(session('success')): ?>
|
|
||||||
<div class="alert alert-success"><?php echo e(session('success')); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if(session('error')): ?>
|
|
||||||
<div class="alert alert-danger"><?php echo e(session('error')); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<div class="content-header-flex">
|
|
||||||
<a href="<?php echo e(route('admin.users.admin_create')); ?>" class="btn btn-primary">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Akun Admin
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="text-muted" style="margin-top: 8px;">
|
|
||||||
Kelola akun untuk role <strong>Akademik</strong> dan <strong>Pamong</strong>.
|
|
||||||
Akun <strong>Super Admin</strong> tidak dapat dihapus dari halaman ini.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="table-wrapper">
|
|
||||||
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>No</th>
|
|
||||||
<th>Nama</th>
|
|
||||||
<th>Email</th>
|
|
||||||
<th>Role</th>
|
|
||||||
<th>Dibuat</th>
|
|
||||||
<th>Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__empty_1 = true; $__currentLoopData = $admins; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $i => $admin): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($i + 1); ?></td>
|
|
||||||
<td><?php echo e($admin->name); ?></td>
|
|
||||||
<td><?php echo e($admin->email); ?></td>
|
|
||||||
<td>
|
|
||||||
<?php if($admin->role === 'super_admin'): ?>
|
|
||||||
<span class="badge" style="background:#6f42c1;color:#fff;padding:3px 8px;border-radius:4px;">Super Admin</span>
|
|
||||||
<?php elseif($admin->role === 'akademik'): ?>
|
|
||||||
<span class="badge" style="background:#0d6efd;color:#fff;padding:3px 8px;border-radius:4px;">Akademik</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="badge" style="background:#198754;color:#fff;padding:3px 8px;border-radius:4px;">Pamong</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td><?php echo e($admin->created_at->format('d/m/Y')); ?></td>
|
|
||||||
<td>
|
|
||||||
<?php if($admin->role !== 'super_admin'): ?>
|
|
||||||
<a href="<?php echo e(route('admin.users.admin_edit', $admin->id)); ?>" class="btn btn-sm btn-warning">
|
|
||||||
<i class="fas fa-edit"></i> Edit
|
|
||||||
</a>
|
|
||||||
<form action="<?php echo e(route('admin.users.admin_destroy', $admin->id)); ?>" method="POST" style="display:inline;"
|
|
||||||
onsubmit="return confirm('Yakin hapus akun <?php echo e($admin->name); ?>?')">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<?php echo method_field('DELETE'); ?>
|
|
||||||
<button type="submit" class="btn btn-sm btn-danger">
|
|
||||||
<i class="fas fa-trash"></i> Hapus
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="text-muted"><i class="fas fa-lock"></i> Protected</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
|
||||||
<tr>
|
|
||||||
<td colspan="6" class="text-center">Belum ada akun admin terdaftar.</td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</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/users/admin_accounts.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,253 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<div class="modal-kegiatan-detail">
|
|
||||||
|
|
||||||
|
|
||||||
<div style="background: linear-gradient(135deg, <?php echo e($kegiatan->kategori->warna ?? '#6FBAA5'); ?>, <?php echo e($kegiatan->kategori->warna ?? '#5AA88D'); ?>);
|
|
||||||
color: white; padding: 14px; border-radius: 8px; margin-bottom: 14px;">
|
|
||||||
<h4 style="margin: 0 0 10px 0; display: flex; align-items: center; gap: 10px;">
|
|
||||||
<i class="fas <?php echo e($kegiatan->kategori->icon ?? 'fa-calendar'); ?>"></i>
|
|
||||||
<?php echo e($kegiatan->nama_kegiatan); ?>
|
|
||||||
|
|
||||||
</h4>
|
|
||||||
<div style="display: flex; gap: 20px; flex-wrap: wrap; font-size: 0.9rem; opacity: 0.95;">
|
|
||||||
<span><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))); ?></span>
|
|
||||||
<span><i class="fas fa-tag"></i> <?php echo e($kegiatan->kategori->nama_kategori); ?></span>
|
|
||||||
<span><i class="fas fa-calendar-day"></i> <?php echo e($kegiatan->hari); ?></span>
|
|
||||||
<span>
|
|
||||||
<i class="fas fa-layer-group"></i>
|
|
||||||
<?php if($kegiatan->kelasKegiatan->isEmpty()): ?>
|
|
||||||
Kegiatan Umum
|
|
||||||
<?php else: ?>
|
|
||||||
<?php echo e($kegiatan->kelasKegiatan->pluck('nama_kelas')->implode(', ')); ?>
|
|
||||||
|
|
||||||
<?php endif; ?>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<?php if($kegiatan->materi): ?>
|
|
||||||
<div style="margin-top: 10px; padding-top: 10px; border-top: 1px solid rgba(255,255,255,0.2);">
|
|
||||||
<i class="fas fa-book"></i> Materi: <?php echo e($kegiatan->materi); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 11px; margin-bottom: 20px;">
|
|
||||||
<div style="background: linear-gradient(135deg, #28a745, #218838); color: white; padding: 15px; border-radius: 8px; text-align: center;">
|
|
||||||
<div style="font-size: 2rem; font-weight: 700;"><?php echo e($stats['hadir']); ?></div>
|
|
||||||
<div style="font-size: 0.85rem; opacity: 0.9; margin-top: 5px;"><i class="fas fa-check-circle"></i> Hadir</div>
|
|
||||||
</div>
|
|
||||||
<div style="background: linear-gradient(135deg, #ffc107, #e0a800); color: white; padding: 15px; border-radius: 8px; text-align: center;">
|
|
||||||
<div style="font-size: 2rem; font-weight: 700;"><?php echo e($stats['izin']); ?></div>
|
|
||||||
<div style="font-size: 0.85rem; opacity: 0.9; margin-top: 5px;"><i class="fas fa-info-circle"></i> Izin</div>
|
|
||||||
</div>
|
|
||||||
<div style="background: linear-gradient(135deg, #17a2b8, #138496); color: white; padding: 15px; border-radius: 8px; text-align: center;">
|
|
||||||
<div style="font-size: 2rem; font-weight: 700;"><?php echo e($stats['sakit']); ?></div>
|
|
||||||
<div style="font-size: 0.85rem; opacity: 0.9; margin-top: 5px;"><i class="fas fa-heartbeat"></i> Sakit</div>
|
|
||||||
</div>
|
|
||||||
<div style="background: linear-gradient(135deg, #dc3545, #c82333); color: white; padding: 15px; border-radius: 8px; text-align: center;">
|
|
||||||
<div style="font-size: 2rem; font-weight: 700;"><?php echo e($stats['alpa']); ?></div>
|
|
||||||
<div style="font-size: 0.85rem; opacity: 0.9; margin-top: 5px;"><i class="fas fa-times-circle"></i> Alpa</div>
|
|
||||||
</div>
|
|
||||||
<div style="background: linear-gradient(135deg, #6c757d, #5a6268); color: white; padding: 15px; border-radius: 8px; text-align: center;">
|
|
||||||
<div style="font-size: 2rem; font-weight: 700;"><?php echo e($stats['belum_absen']); ?></div>
|
|
||||||
<div style="font-size: 0.85rem; opacity: 0.9; margin-top: 5px;"><i class="fas fa-hourglass-half"></i> Belum</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-bottom: 14px;">
|
|
||||||
<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
|
|
||||||
<strong style="color: #2c3e50;">Total Kehadiran</strong>
|
|
||||||
<strong style="color: <?php echo e($stats['persen_hadir'] >= 85 ? '#28a745' : ($stats['persen_hadir'] >= 70 ? '#ffc107' : '#dc3545')); ?>;">
|
|
||||||
<?php echo e($stats['hadir']); ?>/<?php echo e($stats['total']); ?> (<?php echo e($stats['persen_hadir']); ?>%)
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
<div style="height: 30px; background: #e9ecef; border-radius: 15px; overflow: hidden;">
|
|
||||||
<div style="height: 100%; width: <?php echo e($stats['persen_hadir']); ?>%;
|
|
||||||
background: <?php echo e($stats['persen_hadir'] >= 85 ? 'linear-gradient(90deg, #28a745, #20c997)' : ($stats['persen_hadir'] >= 70 ? 'linear-gradient(90deg, #ffc107, #fd7e14)' : 'linear-gradient(90deg, #dc3545, #c82333)')); ?>;
|
|
||||||
display: flex; align-items: center; justify-content: center;
|
|
||||||
color: white; font-weight: 700; font-size: 0.85rem;">
|
|
||||||
<?php echo e($stats['persen_hadir']); ?>%
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
|
|
||||||
<h5 style="color: #2c3e50; margin: 0;">
|
|
||||||
<i class="fas fa-users"></i> Daftar Absensi (<?php echo e($absensis->count()); ?> dari <?php echo e($stats['total']); ?> santri)
|
|
||||||
</h5>
|
|
||||||
<input type="text" id="searchSantri_<?php echo e($kegiatan->kegiatan_id); ?>"
|
|
||||||
placeholder="Cari santri..."
|
|
||||||
style="padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; width: 200px;"
|
|
||||||
onkeyup="filterSantri_<?php echo e($kegiatan->kegiatan_id); ?>()">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($absensis->count() > 0): ?>
|
|
||||||
<?php $__currentLoopData = $absensiPerKelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $namaKelas => $kelasAbsensis): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div style="margin-bottom: 18px;">
|
|
||||||
<div style="background: linear-gradient(135deg, #f0f7f4, #e8f5e9); padding: 10px 14px; border-radius: 8px 8px 0 0; display: flex; justify-content: space-between; align-items: center;">
|
|
||||||
<h6 style="margin: 0; color: #2c6b4f; font-size: 0.9rem;">
|
|
||||||
<i class="fas fa-school"></i> <?php echo e($namaKelas); ?>
|
|
||||||
|
|
||||||
</h6>
|
|
||||||
<span style="background: #6FBAA5; color: white; padding: 2px 10px; border-radius: 10px; font-size: 0.75rem; font-weight: 600;">
|
|
||||||
<?php echo e($kelasAbsensis->count()); ?> santri
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div style="max-height: 250px; overflow-y: auto; border: 1px solid #e9ecef; border-top: 0; border-radius: 0 0 8px 8px;">
|
|
||||||
<table style="width: 100%; border-collapse: collapse;">
|
|
||||||
<thead style="position: sticky; top: 0; background: white; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
|
|
||||||
<tr style="border-bottom: 2px solid #e9ecef;">
|
|
||||||
<th style="padding: 10px; text-align: left; font-size: 0.8rem; color: #6c757d;">No</th>
|
|
||||||
<th style="padding: 10px; text-align: left; font-size: 0.8rem; color: #6c757d;">ID</th>
|
|
||||||
<th style="padding: 10px; text-align: left; font-size: 0.8rem; color: #6c757d;">Nama Santri</th>
|
|
||||||
<th style="padding: 10px; text-align: center; font-size: 0.8rem; color: #6c757d;">Status</th>
|
|
||||||
<th style="padding: 10px; text-align: center; font-size: 0.8rem; color: #6c757d;">Waktu</th>
|
|
||||||
<th style="padding: 10px; text-align: center; font-size: 0.8rem; color: #6c757d;">Metode</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $kelasAbsensis; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $absensi): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr class="santri-row-<?php echo e($kegiatan->kegiatan_id); ?>"
|
|
||||||
style="border-bottom: 1px solid #f1f3f5;"
|
|
||||||
data-nama="<?php echo e(strtolower($absensi->santri->nama_lengkap)); ?>">
|
|
||||||
<td style="padding: 8px 10px;"><?php echo e($index + 1); ?></td>
|
|
||||||
<td style="padding: 8px 10px; font-weight: 600;"><?php echo e($absensi->santri->id_santri); ?></td>
|
|
||||||
<td style="padding: 8px 10px;"><?php echo e($absensi->santri->nama_lengkap); ?></td>
|
|
||||||
<td style="padding: 8px 10px; text-align: center;">
|
|
||||||
<?php if($absensi->status == 'Hadir'): ?>
|
|
||||||
<span style="background: #d4edda; color: #155724; padding: 4px 10px; border-radius: 12px; font-size: 0.8rem; font-weight: 600;">
|
|
||||||
<i class="fas fa-check-circle"></i> Hadir
|
|
||||||
</span>
|
|
||||||
<?php elseif($absensi->status == 'Izin'): ?>
|
|
||||||
<span style="background: #fff3cd; color: #856404; padding: 4px 10px; border-radius: 12px; font-size: 0.8rem; font-weight: 600;">
|
|
||||||
<i class="fas fa-info-circle"></i> Izin
|
|
||||||
</span>
|
|
||||||
<?php elseif($absensi->status == 'Sakit'): ?>
|
|
||||||
<span style="background: #d1ecf1; color: #0c5460; padding: 4px 10px; border-radius: 12px; font-size: 0.8rem; font-weight: 600;">
|
|
||||||
<i class="fas fa-heartbeat"></i> Sakit
|
|
||||||
</span>
|
|
||||||
<?php elseif($absensi->status == 'Pulang'): ?>
|
|
||||||
<span style="background: #FFF3E0; color: #E65100; padding: 4px 10px; border-radius: 12px; font-size: 0.8rem; font-weight: 600;">
|
|
||||||
<i class="fas fa-home"></i> Pulang
|
|
||||||
</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="background: #f8d7da; color: #721c24; padding: 4px 10px; border-radius: 12px; font-size: 0.8rem; font-weight: 600;">
|
|
||||||
<i class="fas fa-times-circle"></i> Alpa
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="padding: 8px 10px; text-align: center; font-size: 0.85rem; color: #6c757d;">
|
|
||||||
<?php echo e($absensi->waktu_absen ? date('H:i', strtotime($absensi->waktu_absen)) : '-'); ?>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td style="padding: 8px 10px; text-align: center;">
|
|
||||||
<?php if($absensi->metode_absen == 'RFID'): ?>
|
|
||||||
<span style="background: #6FBAA5; color: white; padding: 3px 8px; border-radius: 8px; font-size: 0.75rem;">
|
|
||||||
<i class="fas fa-id-card"></i> RFID
|
|
||||||
</span>
|
|
||||||
<?php elseif($absensi->metode_absen == 'Import_Mesin'): ?>
|
|
||||||
<span style="background: #7c3aed; color: white; padding: 3px 8px; border-radius: 8px; font-size: 0.75rem;">
|
|
||||||
<i class="fas fa-desktop"></i> Mesin
|
|
||||||
</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="background: #6c757d; color: white; padding: 3px 8px; border-radius: 8px; font-size: 0.75rem;">
|
|
||||||
<i class="fas fa-hand-pointer"></i> Manual
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php else: ?>
|
|
||||||
<div style="text-align: center; padding: 22px; background: #f8f9fa; border-radius: 8px;">
|
|
||||||
<i class="fas fa-inbox" style="font-size: 2.2rem; color: #cbd5e0; margin-bottom: 15px;"></i>
|
|
||||||
<p style="color: #6c757d; margin: 0;">Belum ada absensi untuk kegiatan ini.</p>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if(isset($santriBelumAbsen) && $santriBelumAbsen->count() > 0): ?>
|
|
||||||
<div style="margin-top: 18px;">
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
|
||||||
<h5 style="color: #d97706; margin: 0;">
|
|
||||||
<i class="fas fa-exclamation-triangle"></i> Santri Belum Absen (<?php echo e($santriBelumAbsen->count()); ?> orang)
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php $__currentLoopData = $santriBelumAbsenPerKelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $namaKelas => $kelasSantris): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div style="margin-bottom: 12px;">
|
|
||||||
<div style="background: linear-gradient(135deg, #fef3c7, #fef9c3); padding: 8px 14px; border-radius: 8px 8px 0 0; display: flex; justify-content: space-between; align-items: center;">
|
|
||||||
<h6 style="margin: 0; color: #92400e; font-size: 0.9rem;">
|
|
||||||
<i class="fas fa-school"></i> <?php echo e($namaKelas); ?>
|
|
||||||
|
|
||||||
</h6>
|
|
||||||
<span style="background: #f59e0b; color: white; padding: 2px 10px; border-radius: 10px; font-size: 0.75rem; font-weight: 600;">
|
|
||||||
<?php echo e($kelasSantris->count()); ?> santri
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div style="max-height: 200px; overflow-y: auto; border: 1px solid #fde68a; border-top: 0; border-radius: 0 0 8px 8px;">
|
|
||||||
<table style="width: 100%; border-collapse: collapse;">
|
|
||||||
<thead style="position: sticky; top: 0; background: white; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
|
|
||||||
<tr style="border-bottom: 2px solid #fde68a;">
|
|
||||||
<th style="padding: 8px; text-align: left; font-size: 0.8rem; color: #6c757d;">No</th>
|
|
||||||
<th style="padding: 8px; text-align: left; font-size: 0.8rem; color: #6c757d;">ID</th>
|
|
||||||
<th style="padding: 8px; text-align: left; font-size: 0.8rem; color: #6c757d;">Nama Santri</th>
|
|
||||||
<th style="padding: 8px; text-align: center; font-size: 0.8rem; color: #6c757d;">Status</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $kelasSantris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $idx => $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr style="border-bottom: 1px solid #fef3c7;">
|
|
||||||
<td style="padding: 6px 8px; font-size: 0.85rem;"><?php echo e($idx + 1); ?></td>
|
|
||||||
<td style="padding: 6px 8px; font-size: 0.85rem; font-weight: 600;"><?php echo e($santri->id_santri); ?></td>
|
|
||||||
<td style="padding: 6px 8px; font-size: 0.85rem;"><?php echo e($santri->nama_lengkap); ?></td>
|
|
||||||
<td style="padding: 6px 8px; text-align: center;">
|
|
||||||
<span style="background: #fef3c7; color: #92400e; padding: 3px 8px; border-radius: 10px; font-size: 0.75rem; font-weight: 600;">
|
|
||||||
<i class="fas fa-hourglass-half"></i> Belum
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="margin-top: 25px; padding-top: 20px; border-top: 2px solid #e9ecef; display: flex; gap: 10px; justify-content: flex-end;">
|
|
||||||
<a href="<?php echo e(route('admin.absensi-kegiatan.input', $kegiatan->kegiatan_id)); ?>?tanggal=<?php echo e($tanggal); ?>"
|
|
||||||
class="btn btn-primary">
|
|
||||||
<i class="fas fa-clipboard-check"></i> Input Absensi
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index')); ?>?kegiatan_id=<?php echo e($kegiatan->kegiatan_id); ?>&tanggal=<?php echo e($tanggal); ?>"
|
|
||||||
class="btn btn-info">
|
|
||||||
<i class="fas fa-chart-bar"></i> Lihat Rekap Lengkap
|
|
||||||
</a>
|
|
||||||
<button class="btn btn-secondary" onclick="closeModal()">
|
|
||||||
<i class="fas fa-times"></i> Tutup
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function filterSantri_<?php echo e($kegiatan->kegiatan_id); ?>() {
|
|
||||||
var val = document.getElementById('searchSantri_<?php echo e($kegiatan->kegiatan_id); ?>').value.toLowerCase();
|
|
||||||
var rows = document.querySelectorAll('.santri-row-<?php echo e($kegiatan->kegiatan_id); ?>');
|
|
||||||
rows.forEach(function(row) {
|
|
||||||
row.style.display = (row.getAttribute('data-nama') || '').includes(val) ? '' : 'none';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/data/partials/detail-modal.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,115 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?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: 14px;">
|
|
||||||
<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): ?>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<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->kelasSantri->first()?->kelas?->nama_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>
|
|
||||||
|
|
||||||
<div style="margin-top: 14px;">
|
|
||||||
<?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**/ ?>
|
|
||||||
|
|
@ -0,0 +1,168 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="id">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Laporan Pembayaran SPP</title>
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body { font-family: Arial, sans-serif; padding: 20px; font-size: 12px; }
|
||||||
|
|
||||||
|
.header { text-align: center; margin-bottom: 30px; border-bottom: 3px solid #333; padding-bottom: 15px; }
|
||||||
|
.header h1 { font-size: 20px; margin-bottom: 5px; }
|
||||||
|
.header h2 { font-size: 16px; color: #666; margin-bottom: 10px; }
|
||||||
|
.header p { font-size: 11px; color: #888; }
|
||||||
|
|
||||||
|
.info-box { background: #f5f5f5; padding: 15px; margin-bottom: 20px; border-radius: 5px; }
|
||||||
|
.info-box table { width: 100%; }
|
||||||
|
.info-box td { padding: 5px; }
|
||||||
|
.info-box td:first-child { font-weight: bold; width: 150px; }
|
||||||
|
|
||||||
|
.stats { display: flex; justify-content: space-around; margin-bottom: 20px; }
|
||||||
|
.stat-card { text-align: center; flex: 1; padding: 15px; background: #f9f9f9; border-radius: 5px; margin: 0 5px; }
|
||||||
|
.stat-card h3 { font-size: 11px; color: #666; margin-bottom: 8px; }
|
||||||
|
.stat-card .value { font-size: 18px; font-weight: bold; color: #333; }
|
||||||
|
|
||||||
|
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
|
||||||
|
th, td { padding: 10px; text-align: left; border: 1px solid #ddd; }
|
||||||
|
th { background: #6FBA9D; color: white; font-weight: bold; }
|
||||||
|
tr:nth-child(even) { background: #f9f9f9; }
|
||||||
|
|
||||||
|
.text-center { text-align: center; }
|
||||||
|
.text-right { text-align: right; }
|
||||||
|
.badge { padding: 4px 8px; border-radius: 3px; font-size: 10px; font-weight: bold; }
|
||||||
|
.badge-success { background: #d4edda; color: #155724; }
|
||||||
|
.badge-warning { background: #fff3cd; color: #856404; }
|
||||||
|
.badge-danger { background: #f8d7da; color: #721c24; }
|
||||||
|
|
||||||
|
.footer { margin-top: 30px; text-align: center; font-size: 10px; color: #888; border-top: 1px solid #ddd; padding-top: 10px; }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
body { padding: 0; }
|
||||||
|
.no-print { display: none; }
|
||||||
|
@page { margin: 1cm; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Tombol Print -->
|
||||||
|
<div class="no-print" style="margin-bottom: 20px; text-align: right;">
|
||||||
|
<button onclick="window.print()" style="padding: 10px 20px; background: #6FBA9D; color: white; border: none; border-radius: 5px; cursor: pointer;">
|
||||||
|
<i class="fas fa-print"></i> Cetak Laporan
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="header">
|
||||||
|
<h1>PKPPS RIYADLUL JANNAH</h1>
|
||||||
|
<h2>LAPORAN PEMBAYARAN SPP</h2>
|
||||||
|
<p>Tanggal Cetak: <?php echo e(date('d F Y')); ?> WIB</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Info Filter -->
|
||||||
|
<?php if(request()->has('bulan') || request()->has('tahun') || request()->has('status')): ?>
|
||||||
|
<div class="info-box">
|
||||||
|
<table>
|
||||||
|
<?php if(request()->filled('bulan')): ?>
|
||||||
|
<tr>
|
||||||
|
<td>Bulan</td>
|
||||||
|
<td>: <?php echo e(DateTime::createFromFormat('!m', request('bulan'))->format('F')); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if(request()->filled('tahun')): ?>
|
||||||
|
<tr>
|
||||||
|
<td>Tahun</td>
|
||||||
|
<td>: <?php echo e(request('tahun')); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if(request()->filled('status')): ?>
|
||||||
|
<tr>
|
||||||
|
<td>Status</td>
|
||||||
|
<td>: <?php echo e(request('status')); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- Statistik -->
|
||||||
|
<div class="stats">
|
||||||
|
<div class="stat-card">
|
||||||
|
<h3>Total Terbayar</h3>
|
||||||
|
<div class="value" style="color: #28a745;">Rp <?php echo e(number_format($totalLunas, 0, ',', '.')); ?></div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<h3>Total Tunggakan</h3>
|
||||||
|
<div class="value" style="color: #dc3545;">Rp <?php echo e(number_format($totalTunggakan, 0, ',', '.')); ?></div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<h3>Pembayaran Telat</h3>
|
||||||
|
<div class="value" style="color: #ffc107;"><?php echo e($jumlahTelat); ?></div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<h3>Total Data</h3>
|
||||||
|
<div class="value" style="color: #17a2b8;"><?php echo e($pembayaranSpp->count()); ?></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tabel Data -->
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th width="5%">No</th>
|
||||||
|
<th width="10%">ID</th>
|
||||||
|
<th width="20%">Santri</th>
|
||||||
|
<th width="15%">Periode</th>
|
||||||
|
<th width="15%">Nominal</th>
|
||||||
|
<th width="12%">Batas Bayar</th>
|
||||||
|
<th width="12%">Tgl Bayar</th>
|
||||||
|
<th width="11%">Status</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 class="text-center"><?php echo e($index + 1); ?></td>
|
||||||
|
<td><?php echo e($spp->id_pembayaran); ?></td>
|
||||||
|
<td>
|
||||||
|
<strong><?php echo e($spp->santri->nama_lengkap); ?></strong><br>
|
||||||
|
<small style="color: #666;"><?php echo e($spp->santri->id_santri); ?></small>
|
||||||
|
</td>
|
||||||
|
<td><?php echo e($spp->periode_lengkap); ?></td>
|
||||||
|
<td class="text-right"><strong><?php echo e($spp->nominal_format); ?></strong></td>
|
||||||
|
<td class="text-center"><?php echo e($spp->batas_bayar->format('d/m/Y')); ?></td>
|
||||||
|
<td class="text-center">
|
||||||
|
<?php if($spp->tanggal_bayar): ?>
|
||||||
|
<?php echo e($spp->tanggal_bayar->format('d/m/Y')); ?>
|
||||||
|
|
||||||
|
<?php else: ?>
|
||||||
|
<span style="color: #999;">-</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<?php if($spp->status === 'Lunas'): ?>
|
||||||
|
<span class="badge badge-success">Lunas</span>
|
||||||
|
<?php elseif($spp->isTelat()): ?>
|
||||||
|
<span class="badge badge-danger">Telat</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="badge badge-warning">Belum Lunas</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
||||||
|
<tr>
|
||||||
|
<td colspan="8" class="text-center" style="padding: 30px; color: #999;">
|
||||||
|
Tidak ada data pembayaran SPP
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Auto print saat load (opsional)
|
||||||
|
// window.onload = function() { window.print(); }
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/pembayaran-spp/cetak-laporan.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -1,272 +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: 4px 0 0 0; color: var(--text-light);">
|
|
||||||
Kunjungan UKP — <strong><?php echo e($santri->nama_lengkap); ?></strong>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($sedangDirawatSekarang): ?>
|
|
||||||
<div style="
|
|
||||||
background: linear-gradient(135deg, #E74C3C, #C0392B);
|
|
||||||
color: white; padding: 16px 20px; border-radius: 12px;
|
|
||||||
margin-bottom: 18px; display: flex; align-items: center; gap: 14px;
|
|
||||||
box-shadow: 0 4px 18px rgba(231,76,60,0.4); animation: alertPulse 2.5s infinite;">
|
|
||||||
<div style="background: rgba(255,255,255,0.2); width: 52px; height: 52px; border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-shrink: 0;">
|
|
||||||
<i class="fas fa-procedures" style="font-size: 1.5rem;"></i>
|
|
||||||
</div>
|
|
||||||
<div style="flex: 1; min-width: 0;">
|
|
||||||
<strong style="font-size: 1.05rem; display: block;">⚠️ Kamu Sedang Dalam Perawatan UKP</strong>
|
|
||||||
<span style="font-size: 0.85rem; opacity: 0.9; display: block; margin-top: 2px;">
|
|
||||||
Masuk sejak <?php echo e($sedangDirawatSekarang->tanggal_masuk->locale('id')->isoFormat('D MMMM Y')); ?>
|
|
||||||
|
|
||||||
• Hari ke-<?php echo e($sedangDirawatSekarang->lama_dirawat); ?>
|
|
||||||
|
|
||||||
• <?php echo e(Str::limit($sedangDirawatSekarang->keluhan, 55)); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<a href="<?php echo e(route('santri.kesehatan.show', $sedangDirawatSekarang->id)); ?>"
|
|
||||||
style="background: rgba(255,255,255,0.2); color: white; padding: 8px 14px; border-radius: 8px;
|
|
||||||
text-decoration: none; font-size: 0.82rem; white-space: nowrap; border: 1px solid rgba(255,255,255,0.35); flex-shrink: 0;"
|
|
||||||
onmouseover="this.style.background='rgba(255,255,255,0.35)';"
|
|
||||||
onmouseout="this.style.background='rgba(255,255,255,0.2)';">
|
|
||||||
<i class="fas fa-eye"></i> Lihat Detail
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if($errors->any()): ?>
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<i class="fas fa-exclamation-triangle"></i> <?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: 8px; font-size: 0.82rem; color: var(--text-light);">Periode 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>
|
|
||||||
<p style="margin-top: 8px; font-size: 0.82rem; color: <?php echo e($statistik['sedang_dirawat'] > 0 ? 'var(--danger-color)' : 'var(--text-light)'); ?>;">
|
|
||||||
<?php echo e($statistik['sedang_dirawat'] > 0 ? '⚠️ Perlu perhatian' : 'Tidak ada'); ?>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</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: 8px; font-size: 0.82rem; 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: 8px; font-size: 0.82rem; color: var(--text-light);">Izin pulang</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 14px;">
|
|
||||||
<div style="background: linear-gradient(135deg, #E8F7F2, #D4F1E3); padding: 16px; border-radius: 12px; border-left: 4px solid #6FBA9D; display: flex; align-items: center; gap: 14px;">
|
|
||||||
<i class="fas fa-history" style="font-size: 2rem; color: #6FBA9D; flex-shrink: 0;"></i>
|
|
||||||
<div>
|
|
||||||
<p style="margin: 0; font-size: 0.82rem; color: var(--text-light);">Total Kunjungan Semua Waktu</p>
|
|
||||||
<p style="margin: 0; font-size: 1.7rem; font-weight: 700; color: #2C5F4F; line-height: 1.1;"><?php echo e($totalAllTime); ?> <span style="font-size: 1rem;">kali</span></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="background: linear-gradient(135deg, #FFF8E1, #FFF3CD); padding: 16px; border-radius: 12px; border-left: 4px solid #FFD56B; display: flex; align-items: center; gap: 14px;">
|
|
||||||
<i class="fas fa-bed" style="font-size: 2rem; color: #F39C12; flex-shrink: 0;"></i>
|
|
||||||
<div>
|
|
||||||
<p style="margin: 0; font-size: 0.82rem; color: var(--text-light);">Total Hari Dirawat Semua Waktu</p>
|
|
||||||
<p style="margin: 0; font-size: 1.7rem; font-weight: 700; color: #7D5A00; line-height: 1.1;"><?php echo e($totalHariDirawat); ?> <span style="font-size: 1rem;">hari</span></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<form method="GET" action="<?php echo e(route('santri.kesehatan.index')); ?>" id="filterForm">
|
|
||||||
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr auto; gap: 11px; align-items: end;">
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<label style="display: block; font-size: 0.82rem; font-weight: 600; margin-bottom: 6px;">
|
|
||||||
<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="display: block; font-size: 0.82rem; font-weight: 600; margin-bottom: 6px;">
|
|
||||||
<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="display: block; font-size: 0.82rem; font-weight: 600; margin-bottom: 6px;">
|
|
||||||
<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: 8px;">
|
|
||||||
<button type="submit" class="btn btn-primary hover-lift">
|
|
||||||
<i class="fas fa-search"></i> Filter
|
|
||||||
</button>
|
|
||||||
<a href="<?php echo e(route('santri.kesehatan.index')); ?>" class="btn btn-secondary hover-lift">
|
|
||||||
<i class="fas fa-sync"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<p style="margin: 11px 0 0 0; color: var(--text-light); font-size: 0.82rem;">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
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>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($riwayatKesehatan->isEmpty()): ?>
|
|
||||||
<div class="empty-state" style="margin-top: 14px;">
|
|
||||||
<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: 14px;">
|
|
||||||
<i class="fas fa-sync"></i> Lihat Semua Data
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="content-box" style="margin-top: 14px;">
|
|
||||||
<h3 style="margin: 0 0 14px 0; color: var(--primary-color);">
|
|
||||||
<i class="fas fa-list"></i> Daftar Riwayat
|
|
||||||
<span style="color: var(--text-light); font-weight: 400; font-size: 0.9rem;">(<?php echo e($riwayatKesehatan->total()); ?> data)</span>
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<div style="display: flex; flex-direction: column; gap: 10px;">
|
|
||||||
<?php $__currentLoopData = $riwayatKesehatan; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$bColor = match($item->status) { 'dirawat' => '#E74C3C', 'sembuh' => '#6FBA9D', default => '#F39C12' };
|
|
||||||
$iBg = match($item->status) { 'dirawat' => 'linear-gradient(135deg,#FFE8EA,#FFD5D8)', 'sembuh' => 'linear-gradient(135deg,#E8F7F2,#D4F1E3)', default => 'linear-gradient(135deg,#FFF8E1,#FFF3CD)' };
|
|
||||||
$ico = match($item->status) { 'dirawat' => 'fa-procedures', 'sembuh' => 'fa-check-circle', default => 'fa-home' };
|
|
||||||
?>
|
|
||||||
<a href="<?php echo e(route('santri.kesehatan.show', $item->id)); ?>"
|
|
||||||
style="display:flex; gap:14px; padding:14px 16px; background:white; border-radius:10px; border-left:4px solid <?php echo e($bColor); ?>; text-decoration:none; box-shadow:0 2px 8px rgba(0,0,0,0.06); transition:all 0.2s;"
|
|
||||||
onmouseover="this.style.transform='translateX(5px)'; this.style.boxShadow='0 4px 16px rgba(0,0,0,0.12)';"
|
|
||||||
onmouseout="this.style.transform=''; this.style.boxShadow='0 2px 8px rgba(0,0,0,0.06)';">
|
|
||||||
|
|
||||||
<div style="flex-shrink:0; width:54px; height:54px; border-radius:50%; background:<?php echo e($iBg); ?>; display:flex; align-items:center; justify-content:center;">
|
|
||||||
<i class="fas <?php echo e($ico); ?>" style="font-size:1.5rem; color:<?php echo e($bColor); ?>;"></i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="flex:1; min-width:0;">
|
|
||||||
<div style="display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:5px;">
|
|
||||||
<strong style="color:var(--text-color); font-size:0.95rem;"><?php echo e(Str::limit($item->keluhan, 65)); ?></strong>
|
|
||||||
<span class="badge badge-<?php echo e($item->status_badge_color); ?>" style="margin-left:8px; flex-shrink:0;"><?php echo e(ucfirst($item->status)); ?></span>
|
|
||||||
</div>
|
|
||||||
<div style="display:flex; flex-wrap:wrap; gap:10px; font-size:0.8rem; color:var(--text-light);">
|
|
||||||
<span><i class="fas fa-calendar-plus"></i> <?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>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($item->status === 'dirawat'): ?>
|
|
||||||
<span class="badge badge-danger badge-sm"><i class="fas fa-clock"></i> Hari ke-<?php echo e($item->lama_dirawat); ?></span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="badge badge-info badge-sm"><i class="fas fa-clock"></i> <?php echo e($item->lama_dirawat); ?> hari</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<span style="color:#ccc; font-size:0.75rem;"><?php echo e($item->id_kesehatan); ?></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="flex-shrink:0; align-self:center;">
|
|
||||||
<i class="fas fa-chevron-right" style="color:var(--text-light); font-size:0.8rem;"></i>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="margin-top: 18px;">
|
|
||||||
<?php echo e($riwayatKesehatan->links()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<div class="info-box" style="margin-top: 14px;">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
<strong>Info:</strong> Default menampilkan data bulan berjalan. Gunakan filter untuk melihat periode lain.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($dataGrafik->count() > 0): ?>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
|
||||||
<script>
|
|
||||||
const dataGrafik = <?php echo json_encode($dataGrafik, 15, 512) ?>;
|
|
||||||
new Chart(document.getElementById('chartKesehatan').getContext('2d'), {
|
|
||||||
type: 'bar',
|
|
||||||
data: {
|
|
||||||
labels: dataGrafik.map(d => d.label),
|
|
||||||
datasets: [
|
|
||||||
{ label: 'Sembuh', data: dataGrafik.map(d => d.sembuh), backgroundColor: 'rgba(111,186,157,0.85)', borderRadius: 5, borderSkipped: false },
|
|
||||||
{ label: 'Izin', data: dataGrafik.map(d => d.izin), backgroundColor: 'rgba(255,213,107,0.85)', borderRadius: 5, borderSkipped: false },
|
|
||||||
{ label: 'Dirawat', data: dataGrafik.map(d => d.dirawat), backgroundColor: 'rgba(231,76,60,0.85)', borderRadius: 5, borderSkipped: false },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: true,
|
|
||||||
plugins: {
|
|
||||||
legend: { position: 'top' },
|
|
||||||
tooltip: {
|
|
||||||
callbacks: { afterBody: items => `Total: ${dataGrafik[items[0].dataIndex].total} kunjungan` }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
x: { stacked: true, grid: { display: false } },
|
|
||||||
y: { stacked: true, beginAtZero: true, ticks: { stepSize: 1 } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
const dari = document.querySelector('input[name="tanggal_dari"]');
|
|
||||||
const sampai = document.querySelector('input[name="tanggal_sampai"]');
|
|
||||||
dari.addEventListener('change', () => { if (sampai.value && sampai.value < dari.value) sampai.value = dari.value; });
|
|
||||||
sampai.addEventListener('change', function() {
|
|
||||||
if (dari.value && this.value < dari.value) {
|
|
||||||
alert('Tanggal sampai tidak boleh lebih kecil dari tanggal dari!');
|
|
||||||
this.value = dari.value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
@keyframes alertPulse {
|
|
||||||
0%, 100% { box-shadow: 0 4px 18px rgba(231,76,60,0.4); }
|
|
||||||
50% { box-shadow: 0 4px 28px rgba(231,76,60,0.75); }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<?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**/ ?>
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-chart-line"></i> Data Capaian 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" style="margin-bottom: 14px;">
|
|
||||||
<div style="display: flex; gap: 10px; flex-wrap: wrap; align-items: center;">
|
|
||||||
<a href="<?php echo e(route('admin.capaian.create')); ?>" class="btn btn-success" style="padding: 9px 18px;">
|
|
||||||
<i class="fas fa-plus"></i> Input Capaian
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.capaian.akses-santri')); ?>" class="btn btn-primary" style="padding: 9px 18px;">
|
|
||||||
<i class="fas fa-unlock-alt"></i> Kelola Akses Input Santri
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.capaian.index')); ?>" class="filter-form-inline">
|
|
||||||
<div style="display: flex; gap: 10px; flex-wrap: wrap; align-items: center;">
|
|
||||||
|
|
||||||
<select name="id_kelas" class="form-control" style="width: 220px;" onchange="this.form.submit()">
|
|
||||||
<option value="">Semua Kelas</option>
|
|
||||||
<?php
|
|
||||||
$kelompokGrouped = $kelasList->groupBy(fn($k) => $k->kelompok->nama_kelompok ?? 'Lainnya');
|
|
||||||
?>
|
|
||||||
<?php $__currentLoopData = $kelompokGrouped; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $namaKelompok => $kelasGroup): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<optgroup label="<?php echo e($namaKelompok); ?>">
|
|
||||||
<?php $__currentLoopData = $kelasGroup; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kls): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($kls->id); ?>" <?php echo e($selectedKelas == $kls->id ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($kls->nama_kelas); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</optgroup>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
|
|
||||||
<select name="id_semester" class="form-control" style="width: 250px;">
|
|
||||||
<?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); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
|
|
||||||
<input type="text" name="search" class="form-control" placeholder="Cari nama santri / NIS..."
|
|
||||||
value="<?php echo e($search ?? ''); ?>" style="width: 300px;">
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
<i class="fas fa-search"></i> Filter
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<?php if($selectedKelas || $search): ?>
|
|
||||||
<a href="<?php echo e(route('admin.capaian.index', ['id_semester' => $selectedSemester])); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-redo"></i> Reset
|
|
||||||
</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<?php if($selectedKelas): ?>
|
|
||||||
<?php $selectedKelasObj = $kelasList->firstWhere('id', $selectedKelas); ?>
|
|
||||||
<div style="margin-bottom: 15px; padding: 12px 15px; background: #e3f2fd; border-left: 4px solid #2196F3; border-radius: 4px;">
|
|
||||||
<span style="color: #1976D2; font-weight: 600;">
|
|
||||||
<i class="fas fa-filter"></i> Menampilkan data kelas: <strong><?php echo e($selectedKelasObj->nama_kelas ?? 'Unknown'); ?></strong>
|
|
||||||
<?php if($selectedKelasObj && $selectedKelasObj->kelompok): ?>
|
|
||||||
(<?php echo e($selectedKelasObj->kelompok->nama_kelompok); ?>)
|
|
||||||
<?php endif; ?>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if($santriData->count() > 0): ?>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 5%;">No</th>
|
|
||||||
<th style="width: 15%;">NIS</th>
|
|
||||||
<th style="width: 30%;">Nama Santri</th>
|
|
||||||
<th style="width: 10%;">Kelas</th>
|
|
||||||
<th style="width: 15%;">Total Materi</th>
|
|
||||||
<th style="width: 15%;">Total Progress</th>
|
|
||||||
<th class="text-center" style="width: 10%;">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $santriData; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $data): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($index + 1); ?></td>
|
|
||||||
<td><strong><?php echo e($data['santri']->nis); ?></strong></td>
|
|
||||||
<td><?php echo e($data['santri']->nama_lengkap); ?></td>
|
|
||||||
<td>
|
|
||||||
<span class="badge badge-secondary"><?php echo e($data['santri']->kelas); ?></span>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<span class="badge badge-info"><?php echo e($data['total_materi']); ?> materi</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php
|
|
||||||
$progress = $data['total_progress'];
|
|
||||||
if ($progress >= 100) {
|
|
||||||
$badgeClass = 'badge-success';
|
|
||||||
$icon = 'fa-check-circle';
|
|
||||||
} elseif ($progress >= 75) {
|
|
||||||
$badgeClass = 'badge-primary';
|
|
||||||
$icon = 'fa-battery-three-quarters';
|
|
||||||
} elseif ($progress >= 50) {
|
|
||||||
$badgeClass = 'badge-warning';
|
|
||||||
$icon = 'fa-battery-half';
|
|
||||||
} elseif ($progress >= 25) {
|
|
||||||
$badgeClass = 'badge-danger';
|
|
||||||
$icon = 'fa-battery-quarter';
|
|
||||||
} else {
|
|
||||||
$badgeClass = 'badge-secondary';
|
|
||||||
$icon = 'fa-battery-empty';
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<span class="badge <?php echo e($badgeClass); ?>">
|
|
||||||
<i class="fas <?php echo e($icon); ?>"></i> <?php echo e(number_format($progress, 2)); ?>%
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<a href="<?php echo e(route('admin.capaian.riwayat-santri', ['id_santri' => $data['santri']->id_santri, 'id_semester' => $selectedSemester])); ?>"
|
|
||||||
class="btn btn-sm btn-primary" title="Lihat Detail Capaian">
|
|
||||||
<i class="fas fa-eye"></i> Show
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-inbox"></i>
|
|
||||||
<h3>Tidak Ada Data</h3>
|
|
||||||
<p>
|
|
||||||
<?php if($search): ?>
|
|
||||||
Tidak ditemukan santri dengan kata kunci "<strong><?php echo e($search); ?></strong>".
|
|
||||||
<?php else: ?>
|
|
||||||
Belum ada santri dengan data capaian.
|
|
||||||
<?php endif; ?>
|
|
||||||
</p>
|
|
||||||
<?php if($search || $selectedKelas): ?>
|
|
||||||
<a href="<?php echo e(route('admin.capaian.index')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-redo"></i> Reset Filter
|
|
||||||
</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</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/capaian/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,290 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Kenaikan Kelas Massal'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header" style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;">
|
|
||||||
<div>
|
|
||||||
<h2><i class="fas fa-graduation-cap"></i> Kenaikan Kelas Massal</h2>
|
|
||||||
<p class="text-muted" style="margin: 0;">Kelola kenaikan kelas santri per tahun ajaran</p>
|
|
||||||
</div>
|
|
||||||
<a href="<?php echo e(route('admin.kelas.index')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali ke Kelola Kelas
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if(session('success')): ?>
|
|
||||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
|
||||||
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
|
|
||||||
|
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if(session('error')): ?>
|
|
||||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
|
||||||
<i class="fas fa-exclamation-circle"></i> <?php echo e(session('error')); ?>
|
|
||||||
|
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<!-- Info Card -->
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<div class="row-cards">
|
|
||||||
<div class="card card-info">
|
|
||||||
<h3>Tahun Ajaran Aktif</h3>
|
|
||||||
<div class="card-value"><?php echo e($tahunAjaranAktif); ?></div>
|
|
||||||
<p class="text-muted" style="margin: 0;">Tahun ajaran saat ini</p>
|
|
||||||
</div>
|
|
||||||
<div class="card card-success">
|
|
||||||
<h3>Total Santri Aktif</h3>
|
|
||||||
<div class="card-value"><?php echo e($totalSantriAktif); ?></div>
|
|
||||||
<p class="text-muted" style="margin: 0;">Santri dengan status aktif</p>
|
|
||||||
</div>
|
|
||||||
<div class="card card-warning">
|
|
||||||
<h3>Tahun Ajaran Baru</h3>
|
|
||||||
<div class="card-value" style="font-size: 1.8rem;"><?php echo e($tahunAjaranBaru); ?></div>
|
|
||||||
<p class="text-muted" style="margin: 0;">Target kenaikan kelas</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Filter by Kelompok -->
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.kelas.kenaikan.index')); ?>" style="display: flex; gap: 10px; flex-wrap: wrap; align-items: center;">
|
|
||||||
<label style="margin: 0; font-weight: 600; color: var(--primary-dark);">
|
|
||||||
<i class="fas fa-filter"></i> Pilih Kelompok Kelas:
|
|
||||||
</label>
|
|
||||||
<select name="kelompok" class="form-control" style="max-width: 300px;" onchange="this.form.submit()">
|
|
||||||
<?php $__currentLoopData = $kelompokKelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelompok): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($kelompok->id_kelompok); ?>"
|
|
||||||
<?php echo e($selectedKelompok == $kelompok->id_kelompok ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($kelompok->nama_kelompok); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($kelasList->isNotEmpty()): ?>
|
|
||||||
<?php
|
|
||||||
$currentKelompok = $kelompokKelas->where('id_kelompok', $selectedKelompok)->first();
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="content-box" style="margin-bottom: 25px;">
|
|
||||||
<div style="background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); padding: 14px; border-radius: 8px; margin-bottom: 14px;">
|
|
||||||
<h3 style="margin: 0 0 8px 0; color: var(--primary-dark);">
|
|
||||||
<i class="fas fa-layer-group"></i>
|
|
||||||
<?php echo e($currentKelompok->nama_kelompok ?? 'Kelas'); ?>
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
<p style="margin: 0; color: var(--text-light); font-size: 0.95rem;">
|
|
||||||
<?php echo e($currentKelompok->deskripsi ?? 'Kelola kenaikan kelas untuk kelompok ini'); ?>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="table-wrapper">
|
|
||||||
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 50px;">No</th>
|
|
||||||
<th>Kelas Asal</th>
|
|
||||||
<th style="width: 140px; text-align: center;">Santri Aktif</th>
|
|
||||||
<th style="width: 280px;">Naik ke Kelas</th>
|
|
||||||
<th style="width: 200px; text-align: center;">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $kelasList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($loop->iteration); ?></td>
|
|
||||||
<td>
|
|
||||||
<strong style="color: var(--primary-dark);"><?php echo e($kelas->nama_kelas); ?></strong>
|
|
||||||
<br>
|
|
||||||
<span class="text-muted" style="font-size: 0.85rem;">
|
|
||||||
<i class="fas fa-tag"></i> <?php echo e($kelas->kode_kelas); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<?php if($kelas->santri_aktif_count > 0): ?>
|
|
||||||
<span class="badge badge-info" style="font-size: 0.95rem; padding: 8px 14px;">
|
|
||||||
<i class="fas fa-users"></i> <?php echo e($kelas->santri_aktif_count); ?> santri
|
|
||||||
</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="badge badge-secondary" style="font-size: 0.9rem; padding: 7px 12px;">
|
|
||||||
<i class="fas fa-user-slash"></i> 0 santri
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($kelas->santri_aktif_count > 0): ?>
|
|
||||||
<select class="form-control form-control-sm target-kelas-select"
|
|
||||||
data-kelas-id="<?php echo e($kelas->id); ?>"
|
|
||||||
style="font-size: 0.9rem;">
|
|
||||||
<option value="">-- Pilih Kelas Tujuan --</option>
|
|
||||||
<?php $__currentLoopData = $allKelasList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $targetKelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php if($targetKelas->id != $kelas->id): ?>
|
|
||||||
<option value="<?php echo e($targetKelas->id); ?>">
|
|
||||||
<?php echo e($targetKelas->kelompok->nama_kelompok); ?> - <?php echo e($targetKelas->nama_kelas); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="text-muted" style="font-size:0.85rem;"></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<?php if($kelas->santri_aktif_count > 0): ?>
|
|
||||||
<div style="display: flex; gap: 5px; justify-content: center;">
|
|
||||||
<button type="button"
|
|
||||||
class="btn btn-sm btn-success btn-naikkan"
|
|
||||||
data-kelas-id="<?php echo e($kelas->id); ?>"
|
|
||||||
data-kelas-nama="<?php echo e($kelas->nama_kelas); ?>"
|
|
||||||
data-santri-count="<?php echo e($kelas->santri_aktif_count); ?>"
|
|
||||||
disabled
|
|
||||||
title="Pilih kelas tujuan terlebih dahulu">
|
|
||||||
<i class="fas fa-arrow-up"></i> Naikkan
|
|
||||||
</button>
|
|
||||||
<a href="<?php echo e(route('admin.kelas.kenaikan.preview', $kelas->id)); ?>"
|
|
||||||
class="btn btn-sm btn-info"
|
|
||||||
title="Lihat & Pilih Santri">
|
|
||||||
<i class="fas fa-eye"></i> Lihat
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="badge badge-secondary">
|
|
||||||
<i class="fas fa-user-slash"></i> Tidak ada santri
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="content-box">
|
|
||||||
<div class="text-center py-5">
|
|
||||||
<i class="fas fa-graduation-cap fa-3x text-muted mb-3"></i>
|
|
||||||
<h5 class="text-muted">Tidak ada kelas ditemukan</h5>
|
|
||||||
<p class="text-muted">Belum ada kelas aktif di kelompok yang dipilih.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<div class="alert alert-info" style="border-left: 4px solid var(--info-color); background: #E3F7FC;">
|
|
||||||
<div style="display: flex; gap: 11px;">
|
|
||||||
<div style="font-size: 2rem; color: var(--info-color);"><i class="fas fa-info-circle"></i></div>
|
|
||||||
<div>
|
|
||||||
<strong style="color: var(--primary-dark); font-size: 1.1rem;">Cara Menggunakan Kenaikan Kelas:</strong>
|
|
||||||
<ol style="margin: 10px 0 0 0; padding-left: 20px; color: var(--text-color);">
|
|
||||||
<li style="margin-bottom: 8px;"><strong>Pilih Kelompok Kelas</strong> dari dropdown untuk menampilkan daftar kelas</li>
|
|
||||||
<li style="margin-bottom: 8px;"><strong>Pilih Kelas Tujuan</strong> di kolom dropdown tiap baris</li>
|
|
||||||
<li style="margin-bottom: 8px;">Klik <span class="badge badge-success"><i class="fas fa-arrow-up"></i> Naikkan</span> untuk memproses semua santri di kelas tersebut</li>
|
|
||||||
<li style="margin-bottom: 8px;">Atau klik <span class="badge badge-info"><i class="fas fa-eye"></i> Lihat</span> untuk memilih santri secara individual</li>
|
|
||||||
<li style="margin-bottom: 8px;">Santri akan dipindahkan ke <strong>Tahun Ajaran <?php echo e($tahunAjaranBaru); ?></strong></li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php $__env->stopSection(); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('scripts'); ?>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
|
|
||||||
// ── Enable/disable tombol Naikkan berdasarkan pilihan dropdown ──
|
|
||||||
document.querySelectorAll('.target-kelas-select').forEach(function (select) {
|
|
||||||
var kelasId = select.dataset.kelasId;
|
|
||||||
var button = document.querySelector('.btn-naikkan[data-kelas-id="' + kelasId + '"]');
|
|
||||||
if (!button) return;
|
|
||||||
|
|
||||||
select.addEventListener('change', function () {
|
|
||||||
if (this.value) {
|
|
||||||
button.disabled = false;
|
|
||||||
button.title = 'Klik untuk menaikkan kelas semua santri';
|
|
||||||
} else {
|
|
||||||
button.disabled = true;
|
|
||||||
button.title = 'Pilih kelas tujuan terlebih dahulu';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ── Handle klik tombol Naikkan ──
|
|
||||||
document.querySelectorAll('.btn-naikkan').forEach(function (button) {
|
|
||||||
button.addEventListener('click', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
var kelasId = this.dataset.kelasId;
|
|
||||||
var kelasNama = this.dataset.kelasNama;
|
|
||||||
var santriCount = this.dataset.santriCount;
|
|
||||||
var select = document.querySelector('.target-kelas-select[data-kelas-id="' + kelasId + '"]');
|
|
||||||
|
|
||||||
if (!select || !select.value) {
|
|
||||||
if (select) {
|
|
||||||
select.focus();
|
|
||||||
select.style.border = '2px solid #FF8B94';
|
|
||||||
setTimeout(function () { select.style.border = ''; }, 2000);
|
|
||||||
}
|
|
||||||
alert('Silakan pilih kelas tujuan terlebih dahulu!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var targetKelasText = select.options[select.selectedIndex].text;
|
|
||||||
var tahunAjaranBaru = '<?php echo e($tahunAjaranBaru); ?>';
|
|
||||||
|
|
||||||
var confirmMessage =
|
|
||||||
'KONFIRMASI KENAIKAN KELAS\n\n' +
|
|
||||||
'Kelas Asal : ' + kelasNama + '\n' +
|
|
||||||
'Kelas Tujuan : ' + targetKelasText + '\n' +
|
|
||||||
'Jumlah Santri: ' + santriCount + ' orang\n' +
|
|
||||||
'Tahun Ajaran : ' + tahunAjaranBaru + '\n\n' +
|
|
||||||
'Proses ini akan memindahkan SEMUA santri aktif ke kelas dan tahun ajaran baru.\n' +
|
|
||||||
'Lanjutkan?';
|
|
||||||
|
|
||||||
if (!confirm(confirmMessage)) return;
|
|
||||||
|
|
||||||
// Disable tombol agar tidak double-submit
|
|
||||||
this.disabled = true;
|
|
||||||
this.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
|
||||||
|
|
||||||
// Buat form dan submit
|
|
||||||
var form = document.createElement('form');
|
|
||||||
form.method = 'POST';
|
|
||||||
form.action = '<?php echo e(route("admin.kelas.kenaikan.process")); ?>';
|
|
||||||
|
|
||||||
[
|
|
||||||
{ name: '_token', value: '<?php echo e(csrf_token()); ?>' },
|
|
||||||
{ name: 'id_kelas_asal', value: kelasId },
|
|
||||||
{ name: 'id_kelas_tujuan', value: select.value },
|
|
||||||
].forEach(function (item) {
|
|
||||||
var input = document.createElement('input');
|
|
||||||
input.type = 'hidden';
|
|
||||||
input.name = item.name;
|
|
||||||
input.value = item.value;
|
|
||||||
form.appendChild(input);
|
|
||||||
});
|
|
||||||
|
|
||||||
document.body.appendChild(form);
|
|
||||||
form.submit();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
</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/kelas/kenaikan/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
|
||||||
|
|
||||||
|
<?php $__env->startSection('content'); ?>
|
||||||
|
<style>
|
||||||
|
.text-center { text-align:center; }
|
||||||
|
.progress-inline { display:flex; align-items:center; gap:8px; }
|
||||||
|
.progress-bar-mini { flex:1; background:#e9ecef; border-radius:8px; height:8px; overflow:hidden; max-width:120px; }
|
||||||
|
.progress-bar-mini .fill { height:100%; border-radius:8px; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><i class="fas fa-user-clock"></i> Santri Perlu Perhatian</h2>
|
||||||
|
<a href="<?php echo e(route('admin.laporan-kegiatan.index', request()->only('periode','tanggal_dari','tanggal_sampai'))); ?>"
|
||||||
|
class="btn btn-secondary">
|
||||||
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="content-box" style="margin-bottom:14px;">
|
||||||
|
<p style="margin:0;font-size:.88rem;color:var(--text-light);">
|
||||||
|
<i class="fas fa-info-circle"></i>
|
||||||
|
Menampilkan <strong><?php echo e($santris->total()); ?> santri</strong>
|
||||||
|
dari <strong><?php echo e($totalSantriAktif); ?> santri aktif</strong>
|
||||||
|
yang kehadiran efektifnya <70%
|
||||||
|
dalam periode <strong><?php echo e($periodeLabel); ?></strong>.
|
||||||
|
<br>
|
||||||
|
<span style="font-size:.8rem;opacity:.8;">
|
||||||
|
<i class="fas fa-clock"></i> Terlambat dihitung sebagai Hadir efektif.
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="content-box" style="margin-bottom:14px;">
|
||||||
|
<form method="GET" style="display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;">
|
||||||
|
<input type="hidden" name="periode" value="<?php echo e(request('periode','bulan_ini')); ?>">
|
||||||
|
<input type="hidden" name="tanggal_dari" value="<?php echo e(request('tanggal_dari')); ?>">
|
||||||
|
<input type="hidden" name="tanggal_sampai" value="<?php echo e(request('tanggal_sampai')); ?>">
|
||||||
|
<div class="form-group" style="margin:0;">
|
||||||
|
<label style="font-size:.82rem;">Filter Kelas</label>
|
||||||
|
<select name="id_kelas" class="form-control" style="min-width:180px;">
|
||||||
|
<option value="">-- Semua Kelas --</option>
|
||||||
|
<?php $__currentLoopData = $kelasList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $k): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<option value="<?php echo e($k->id); ?>" <?php echo e(request('id_kelas')==$k->id?'selected':''); ?>>
|
||||||
|
<?php echo e($k->kelompok->nama_kelompok ?? ''); ?> – <?php echo e($k->nama_kelas); ?>
|
||||||
|
|
||||||
|
</option>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary btn-sm"><i class="fas fa-filter"></i> Filter</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content-box">
|
||||||
|
<?php if($santris->count() > 0): ?>
|
||||||
|
<div class="table-wrapper">
|
||||||
|
<table class="data-table" style="font-size:.84rem;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>No</th>
|
||||||
|
<th>Nama</th>
|
||||||
|
<th class="text-center">Total Sesi</th>
|
||||||
|
<th class="text-center">
|
||||||
|
Hadir Efektif
|
||||||
|
<span style="display:block;font-weight:400;font-size:.73rem;color:#9CA3AF;">(Hadir+Terlambat)</span>
|
||||||
|
</th>
|
||||||
|
<th class="text-center">Terlambat</th>
|
||||||
|
<th class="text-center">Alpa</th>
|
||||||
|
<th class="text-center">Izin</th>
|
||||||
|
<th class="text-center">Sakit</th>
|
||||||
|
<th class="text-center" style="min-width:180px;">
|
||||||
|
% Kehadiran
|
||||||
|
<span style="display:block;font-weight:400;font-size:.73rem;color:#9CA3AF;">(hadir / total sesi)</span>
|
||||||
|
</th>
|
||||||
|
<th>Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php $__currentLoopData = $santris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $i => $s): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo e($santris->firstItem() + $i); ?></td>
|
||||||
|
<td>
|
||||||
|
<strong><?php echo e($s->nama_lengkap); ?></strong>
|
||||||
|
<div style="font-size:.75rem;color:#9CA3AF;"><code><?php echo e($s->id_santri); ?></code></div>
|
||||||
|
</td>
|
||||||
|
<td class="text-center"><?php echo e($s->total); ?></td>
|
||||||
|
<td class="text-center">
|
||||||
|
<span class="badge badge-success"><?php echo e($s->hadir); ?></span>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<?php if(($s->terlambat ?? 0) > 0): ?>
|
||||||
|
<span class="badge badge-warning"><?php echo e($s->terlambat); ?></span>
|
||||||
|
<?php else: ?>
|
||||||
|
<span style="color:#9CA3AF;">0</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<span class="badge badge-danger"><?php echo e($s->alpa); ?></span>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<span class="badge badge-warning"><?php echo e($s->izin); ?></span>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<span class="badge badge-info"><?php echo e($s->sakit); ?></span>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<div class="progress-inline" style="justify-content:center;">
|
||||||
|
<div class="progress-bar-mini">
|
||||||
|
<div class="fill" style="width:<?php echo e($s->persen); ?>%;background:#EF4444;"></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong style="color:#EF4444;"><?php echo e($s->persen); ?>%</strong>
|
||||||
|
|
||||||
|
<div style="font-size:.72rem;color:#9CA3AF;">
|
||||||
|
<?php echo e($s->hadir); ?> dari <?php echo e($s->total); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.detail-santri', $s->id_santri)); ?>"
|
||||||
|
class="btn btn-sm btn-info" title="Lihat Riwayat Lengkap">
|
||||||
|
<i class="fas fa-history"></i> Riwayat
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top:16px;"><?php echo e($santris->links()); ?></div>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="empty-state">
|
||||||
|
<i class="fas fa-check-circle" style="color:#10B981;font-size:2rem;"></i>
|
||||||
|
<h3>Alhamdulillah!</h3>
|
||||||
|
<p>Tidak ada santri dengan kehadiran di bawah 70%.</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/laporan/santri-perlu-perhatian.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -1,270 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Import Absensi Mesin'); ?>
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-file-import"></i> Import Absensi Fingerprint</h2>
|
|
||||||
<a href="<?php echo e(route('admin.kegiatan.index')); ?>" class="btn btn-sm btn-secondary">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
|
||||||
</a>
|
|
||||||
</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-times-circle"></i> <?php echo e(session('error')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if($belumMapping > 0): ?>
|
|
||||||
<div class="alert alert-warning">
|
|
||||||
<i class="fas fa-exclamation-triangle"></i>
|
|
||||||
<strong><?php echo e($belumMapping); ?></strong> ID mesin belum dipetakan ke santri.
|
|
||||||
Data santri tersebut tidak akan tersimpan saat import.
|
|
||||||
<a href="<?php echo e(route('admin.mesin.mapping-santri.index')); ?>"
|
|
||||||
class="btn btn-sm btn-warning" style="margin-left:8px;">
|
|
||||||
Lengkapi Mapping
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="margin-bottom:14px">
|
|
||||||
<h4 style="margin:0 0 12px;color:var(--primary-color)">
|
|
||||||
<i class="fas fa-info-circle"></i> Cara Kerja Matching
|
|
||||||
</h4>
|
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px">
|
|
||||||
<div style="background:#FFF3E8;border:1px solid #FDBA74;border-radius:8px;padding:12px">
|
|
||||||
<div style="font-size:18px;margin-bottom:4px"></div>
|
|
||||||
<div style="font-weight:700;color:#C05621;margin-bottom:4px">Mesin Sholat</div>
|
|
||||||
<div style="font-size:12px;color:#374151;line-height:1.6">
|
|
||||||
JK1 Masuk Shubuh<br>
|
|
||||||
JK1 Pulang Dhuhur<br>
|
|
||||||
JK2 Masuk Ashar<br>
|
|
||||||
JK2 Pulang Maghrib<br>
|
|
||||||
Lb Masuk Isya
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="background:#EFF6FF;border:1px solid #BFDBFE;border-radius:8px;padding:12px">
|
|
||||||
<div style="font-size:18px;margin-bottom:4px"></div>
|
|
||||||
<div style="font-weight:700;color:#1D4ED8;margin-bottom:4px">Mesin Ngaji</div>
|
|
||||||
<div style="font-size:12px;color:#374151;line-height:1.6">
|
|
||||||
JK1 Masuk Ngaji Shubuh<br>
|
|
||||||
JK1 Pulang sekolah<br>
|
|
||||||
JK2 Masuk Ngaji Siang<br>
|
|
||||||
JK2 Pulang Ngaji Maghrib<br>
|
|
||||||
Lb Masuk Ngaji Malam
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="background:#FEF9C3;border:1px solid #FDE68A;border-radius:8px;padding:12px">
|
|
||||||
<div style="font-size:18px;margin-bottom:4px"></div>
|
|
||||||
<div style="font-weight:700;color:#92400E;margin-bottom:4px">Konflik</div>
|
|
||||||
<div style="font-size:12px;color:#374151;line-height:1.6">
|
|
||||||
Jika santri sudah punya absen<br>
|
|
||||||
Manual/RFID, sistem akan<br>
|
|
||||||
minta pilihan Anda di halaman<br>
|
|
||||||
preview sebelum disimpan.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<h4 style="margin:0 0 16px">
|
|
||||||
<i class="fas fa-upload" style="color:var(--primary-color)"></i>
|
|
||||||
Upload File GLog.txt
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<form action="<?php echo e(route('admin.mesin.import.preview')); ?>"
|
|
||||||
method="POST"
|
|
||||||
enctype="multipart/form-data">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom:16px">
|
|
||||||
<label style="font-weight:600;font-size:14px">
|
|
||||||
<i class="fas fa-database" style="color:#1A56DB"></i>
|
|
||||||
File GLog.txt <span style="color:red">*</span>
|
|
||||||
</label>
|
|
||||||
<input type="file" name="file_glog" class="form-control"
|
|
||||||
accept=".txt,.csv,.xls,.xlsx" required>
|
|
||||||
<small class="text-muted">
|
|
||||||
Export dari software Eppos: menu
|
|
||||||
<strong>Report Download Log</strong>.
|
|
||||||
Pilih periode tanggal yang diinginkan lalu export.
|
|
||||||
</small>
|
|
||||||
<?php $__errorArgs = ['file_glog'];
|
|
||||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
|
||||||
if ($__bag->has($__errorArgs[0])) :
|
|
||||||
if (isset($message)) { $__messageOriginal = $message; }
|
|
||||||
$message = $__bag->first($__errorArgs[0]); ?>
|
|
||||||
<div style="color:#EF4444;font-size:12px;margin-top:4px">
|
|
||||||
<?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:16px;margin-bottom:16px">
|
|
||||||
<div class="form-group" style="margin:0">
|
|
||||||
<label style="font-weight:600;font-size:14px">
|
|
||||||
<i class="fas fa-clock"></i>
|
|
||||||
Toleransi Sebelum Kegiatan (menit)
|
|
||||||
</label>
|
|
||||||
<input type="number" name="tol_sebelum" class="form-control"
|
|
||||||
value="15" min="0" max="60">
|
|
||||||
<small class="text-muted">
|
|
||||||
Scan diterima berapa menit <strong>sebelum</strong> kegiatan mulai
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="margin:0">
|
|
||||||
<label style="font-weight:600;font-size:14px">
|
|
||||||
<i class="fas fa-clock"></i>
|
|
||||||
Toleransi Sesudah Kegiatan (menit)
|
|
||||||
</label>
|
|
||||||
<input type="number" name="tol_sesudah" class="form-control"
|
|
||||||
value="10" min="0" max="60">
|
|
||||||
<small class="text-muted">
|
|
||||||
Scan diterima berapa menit <strong>setelah</strong> kegiatan selesai
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom:20px">
|
|
||||||
<div style="display:flex;align-items:center;gap:10px;
|
|
||||||
background:#F8FAFC;border:1px solid #E2E8F0;
|
|
||||||
border-radius:8px;padding:12px">
|
|
||||||
<input type="checkbox" name="isi_alpa" value="1"
|
|
||||||
id="isiAlpa" checked
|
|
||||||
style="width:18px;height:18px;cursor:pointer">
|
|
||||||
<label for="isiAlpa" style="margin:0;cursor:pointer;font-weight:500">
|
|
||||||
Isi <strong>Alpa</strong> otomatis untuk santri yang tidak scan
|
|
||||||
<span style="color:#6B7280;font-size:12px;display:block;font-weight:400">
|
|
||||||
Jika tidak dicentang, santri yang tidak scan tidak akan diisi apapun
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom:20px">
|
|
||||||
<label style="font-weight:600;font-size:14px;margin-bottom:8px;display:block">
|
|
||||||
<i class="fas fa-exchange-alt" style="color:#DC2626"></i>
|
|
||||||
Jika ada konflik dengan data absen yang sudah ada:
|
|
||||||
</label>
|
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px">
|
|
||||||
<label style="background:#DCFCE7;border:2px solid #86EFAC;border-radius:8px;padding:12px;cursor:pointer;display:flex;align-items:flex-start;gap:8px;margin:0"
|
|
||||||
id="lbl_mesin">
|
|
||||||
<input type="radio" name="conflict_strategy" value="mesin" checked
|
|
||||||
style="margin-top:3px;width:16px;height:16px">
|
|
||||||
<div>
|
|
||||||
<div style="font-weight:700;color:#166534">Utamakan Data Mesin</div>
|
|
||||||
<div style="font-size:11px;color:#374151;margin-top:2px">
|
|
||||||
Timpa semua data lama dengan hasil mesin. Paling umum dipakai.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label style="background:#DBEAFE;border:2px solid #93C5FD;border-radius:8px;padding:12px;cursor:pointer;display:flex;align-items:flex-start;gap:8px;margin:0"
|
|
||||||
id="lbl_exist">
|
|
||||||
<input type="radio" name="conflict_strategy" value="exist"
|
|
||||||
style="margin-top:3px;width:16px;height:16px">
|
|
||||||
<div>
|
|
||||||
<div style="font-weight:700;color:#1D4ED8">Pertahankan Data Lama</div>
|
|
||||||
<div style="font-size:11px;color:#374151;margin-top:2px">
|
|
||||||
Data Manual/RFID yang sudah ada tidak diubah.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label style="background:#FEF9C3;border:2px solid #FDE68A;border-radius:8px;padding:12px;cursor:pointer;display:flex;align-items:flex-start;gap:8px;margin:0"
|
|
||||||
id="lbl_manual">
|
|
||||||
<input type="radio" name="conflict_strategy" value="manual"
|
|
||||||
style="margin-top:3px;width:16px;height:16px">
|
|
||||||
<div>
|
|
||||||
<div style="font-weight:700;color:#92400E">Pilih Manual per Sel</div>
|
|
||||||
<div style="font-size:11px;color:#374151;margin-top:2px">
|
|
||||||
Review tiap konflik satu per satu di halaman preview.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display:flex;gap:10px;align-items:center">
|
|
||||||
<button type="submit" class="btn btn-primary"
|
|
||||||
style="padding:10px 28px;font-size:15px">
|
|
||||||
<i class="fas fa-search"></i> Preview Data Import
|
|
||||||
</button>
|
|
||||||
<a href="<?php echo e(route('admin.mesin.mapping-santri.index')); ?>"
|
|
||||||
class="btn btn-secondary" style="padding:10px 20px">
|
|
||||||
<i class="fas fa-link"></i> Kelola Mapping Santri
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($riwayat->count() > 0): ?>
|
|
||||||
<div class="content-box" style="margin-top:14px">
|
|
||||||
<h4 style="margin:0 0 12px">
|
|
||||||
<i class="fas fa-history"></i> Riwayat Import Terakhir
|
|
||||||
</h4>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Waktu</th>
|
|
||||||
<th>Jumlah Scan</th>
|
|
||||||
<th>Berhasil</th>
|
|
||||||
<th>Konflik Selesai</th>
|
|
||||||
<th>Duplikat</th>
|
|
||||||
<th>Tanpa Mapping</th>
|
|
||||||
<th>Oleh</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $riwayat; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $r): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($r->created_at->format('d/m/Y H:i')); ?></td>
|
|
||||||
<td><?php echo e(number_format($r->jumlah_scan)); ?></td>
|
|
||||||
<td>
|
|
||||||
<span class="badge badge-success"><?php echo e($r->berhasil); ?></span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($r->konflik_selesai > 0): ?>
|
|
||||||
<span class="badge badge-warning"><?php echo e($r->konflik_selesai); ?></span>
|
|
||||||
<?php else: ?> <span style="color:#9CA3AF">-</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($r->dilewati > 0): ?>
|
|
||||||
<span class="badge badge-secondary"><?php echo e($r->dilewati); ?></span>
|
|
||||||
<?php else: ?> <span style="color:#9CA3AF">-</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($r->no_santri > 0): ?>
|
|
||||||
<span class="badge badge-danger"><?php echo e($r->no_santri); ?></span>
|
|
||||||
<?php else: ?> <span style="color:#9CA3AF">-</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="color:#6B7280"><?php echo e($r->user->name ?? '-'); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?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/mesin/import/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,298 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Preview Kenaikan Kelas'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-users"></i> Preview Kenaikan Kelas - <?php echo e($kelas->nama_kelas); ?></h2>
|
|
||||||
<p class="text-muted">Pilih santri yang akan dinaikkan kelasnya</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Flash Messages -->
|
|
||||||
<?php if(session('success')): ?>
|
|
||||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
|
||||||
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
|
|
||||||
|
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<!-- Info Cards -->
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<div class="row-cards">
|
|
||||||
<div class="card card-info">
|
|
||||||
<h3>Kelas Asal</h3>
|
|
||||||
<div class="card-value-small"><?php echo e($kelas->nama_kelas); ?></div>
|
|
||||||
<p class="text-muted" style="margin: 0;"><?php echo e($kelas->kelompok->nama_kelompok); ?></p>
|
|
||||||
</div>
|
|
||||||
<div class="card card-success">
|
|
||||||
<h3>Total Santri</h3>
|
|
||||||
<div class="card-value"><?php echo e($santriList->count()); ?></div>
|
|
||||||
<p class="text-muted" style="margin: 0;">Santri aktif di kelas ini</p>
|
|
||||||
</div>
|
|
||||||
<div class="card card-warning">
|
|
||||||
<h3>Tahun Ajaran</h3>
|
|
||||||
<div class="card-value-small"><?php echo e($tahunAjaranAktif); ?></div>
|
|
||||||
<div style="margin-top: 8px; font-size: 0.9rem; color: var(--text-light);">
|
|
||||||
<i class="fas fa-arrow-down"></i>
|
|
||||||
</div>
|
|
||||||
<div class="card-value-small" style="color: var(--success-color);"><?php echo e($tahunAjaranBaru); ?></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Form Kenaikan Kelas -->
|
|
||||||
<div class="content-box">
|
|
||||||
<form action="<?php echo e(route('admin.kelas.kenaikan.process-selected')); ?>" method="POST" id="formKenaikanKelas">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
|
|
||||||
<input type="hidden" name="id_kelas_asal" value="<?php echo e($kelas->id); ?>">
|
|
||||||
|
|
||||||
<!-- Pilih Kelas Tujuan -->
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="id_kelas_tujuan">
|
|
||||||
<i class="fas fa-graduation-cap"></i> Kelas Tujuan <span class="text-danger">*</span>
|
|
||||||
</label>
|
|
||||||
<select class="form-control <?php $__errorArgs = ['id_kelas_tujuan'];
|
|
||||||
$__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); ?>"
|
|
||||||
id="id_kelas_tujuan"
|
|
||||||
name="id_kelas_tujuan"
|
|
||||||
required>
|
|
||||||
<option value="">-- Pilih Kelas Tujuan --</option>
|
|
||||||
<?php $__currentLoopData = $kelasOptions; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelompok): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<optgroup label="<?php echo e($kelompok->nama_kelompok); ?>">
|
|
||||||
<?php $__currentLoopData = $kelompok->kelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelasOption): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php if($kelasOption->id != $kelas->id): ?>
|
|
||||||
<option value="<?php echo e($kelasOption->id); ?>">
|
|
||||||
<?php echo e($kelasOption->nama_kelas); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</optgroup>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
<?php $__errorArgs = ['id_kelas_tujuan'];
|
|
||||||
$__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 text-muted">
|
|
||||||
Pilih kelas yang akan menjadi tujuan kenaikan untuk santri yang dipilih
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<!-- Daftar Santri -->
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
|
|
||||||
<h4 style="margin: 0;">
|
|
||||||
<i class="fas fa-users"></i> Daftar Santri
|
|
||||||
<span class="badge badge-info" id="selectedCount">0 dipilih</span>
|
|
||||||
</h4>
|
|
||||||
<div>
|
|
||||||
<button type="button" class="btn btn-sm btn-info" id="btnSelectAll">
|
|
||||||
<i class="fas fa-check-square"></i> Pilih Semua
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-secondary" id="btnDeselectAll">
|
|
||||||
<i class="fas fa-square"></i> Batal Pilih
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($santriList->count() > 0): ?>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 50px;">
|
|
||||||
<input type="checkbox" id="checkAll" style="width: 18px; height: 18px; cursor: pointer;">
|
|
||||||
</th>
|
|
||||||
<th style="width: 50px;">No</th>
|
|
||||||
<th>Foto</th>
|
|
||||||
<th>NIS</th>
|
|
||||||
<th>Nama Santri</th>
|
|
||||||
<th>Jenis Kelamin</th>
|
|
||||||
<th>Status</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $santriList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<input type="checkbox"
|
|
||||||
name="santri_ids[]"
|
|
||||||
value="<?php echo e($santri->id_santri); ?>"
|
|
||||||
class="santri-checkbox"
|
|
||||||
style="width: 18px; height: 18px; cursor: pointer;">
|
|
||||||
</td>
|
|
||||||
<td><?php echo e($index + 1); ?></td>
|
|
||||||
<td>
|
|
||||||
<?php if($santri->foto): ?>
|
|
||||||
<img src="<?php echo e($santri->foto_url); ?>"
|
|
||||||
alt="<?php echo e($santri->nama_lengkap); ?>"
|
|
||||||
class="santri-avatar">
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="santri-avatar-initial">
|
|
||||||
<?php echo e(strtoupper(substr($santri->nama_lengkap, 0, 1))); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td><?php echo e($santri->nis ?? '-'); ?></td>
|
|
||||||
<td><strong><?php echo e($santri->nama_lengkap); ?></strong></td>
|
|
||||||
<td>
|
|
||||||
<?php if($santri->jenis_kelamin === 'Laki-laki'): ?>
|
|
||||||
<i class="fas fa-mars text-primary"></i> Laki-laki
|
|
||||||
<?php else: ?>
|
|
||||||
<i class="fas fa-venus" style="color: #FF8B94;"></i> Perempuan
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span class="badge badge-success">
|
|
||||||
<i class="fas fa-check-circle"></i> <?php echo e($santri->status); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
|
||||||
<div class="alert alert-warning">
|
|
||||||
<i class="fas fa-exclamation-triangle"></i> <strong>Perhatian:</strong>
|
|
||||||
<ul class="mb-0 mt-2">
|
|
||||||
<li>Pastikan kelas tujuan sudah dipilih</li>
|
|
||||||
<li>Pilih santri yang akan dinaikkan kelasnya (minimal 1 santri)</li>
|
|
||||||
<li>Proses kenaikan kelas akan memindahkan santri ke tahun ajaran <strong><?php echo e($tahunAjaranBaru); ?></strong></li>
|
|
||||||
<li>Santri yang dipilih akan otomatis terdaftar di kelas tujuan</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
|
|
||||||
<button type="submit" class="btn btn-success" id="btnSubmit" disabled>
|
|
||||||
<i class="fas fa-arrow-up"></i> Naikkan Kelas yang Dipilih
|
|
||||||
</button>
|
|
||||||
<a href="<?php echo e(route('admin.kelas.kenaikan.index')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="text-center py-5">
|
|
||||||
<i class="fas fa-users fa-3x text-muted mb-3"></i>
|
|
||||||
<h5 class="text-muted">Tidak ada santri aktif di kelas ini</h5>
|
|
||||||
<p class="text-muted">Kelas <?php echo e($kelas->nama_kelas); ?> tidak memiliki santri aktif.</p>
|
|
||||||
<a href="<?php echo e(route('admin.kelas.kenaikan.index')); ?>" class="btn btn-secondary mt-2">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php $__env->stopSection(); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('scripts'); ?>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
const checkAll = document.getElementById('checkAll');
|
|
||||||
const checkboxes = document.querySelectorAll('.santri-checkbox');
|
|
||||||
const selectedCount = document.getElementById('selectedCount');
|
|
||||||
const btnSubmit = document.getElementById('btnSubmit');
|
|
||||||
const btnSelectAll = document.getElementById('btnSelectAll');
|
|
||||||
const btnDeselectAll = document.getElementById('btnDeselectAll');
|
|
||||||
const kelasSelect = document.getElementById('id_kelas_tujuan');
|
|
||||||
|
|
||||||
function updateSelectedCount() {
|
|
||||||
const checked = document.querySelectorAll('.santri-checkbox:checked').length;
|
|
||||||
selectedCount.textContent = `${checked} dipilih`;
|
|
||||||
|
|
||||||
// Enable submit button if kelas tujuan selected and at least 1 santri checked
|
|
||||||
if (kelasSelect.value && checked > 0) {
|
|
||||||
btnSubmit.disabled = false;
|
|
||||||
} else {
|
|
||||||
btnSubmit.disabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check all functionality
|
|
||||||
if (checkAll) {
|
|
||||||
checkAll.addEventListener('change', function() {
|
|
||||||
checkboxes.forEach(checkbox => {
|
|
||||||
checkbox.checked = this.checked;
|
|
||||||
});
|
|
||||||
updateSelectedCount();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Individual checkbox
|
|
||||||
checkboxes.forEach(checkbox => {
|
|
||||||
checkbox.addEventListener('change', function() {
|
|
||||||
// Update check all status
|
|
||||||
const allChecked = Array.from(checkboxes).every(cb => cb.checked);
|
|
||||||
if (checkAll) {
|
|
||||||
checkAll.checked = allChecked;
|
|
||||||
}
|
|
||||||
updateSelectedCount();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Select all button
|
|
||||||
if (btnSelectAll) {
|
|
||||||
btnSelectAll.addEventListener('click', function() {
|
|
||||||
checkboxes.forEach(checkbox => checkbox.checked = true);
|
|
||||||
if (checkAll) checkAll.checked = true;
|
|
||||||
updateSelectedCount();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deselect all button
|
|
||||||
if (btnDeselectAll) {
|
|
||||||
btnDeselectAll.addEventListener('click', function() {
|
|
||||||
checkboxes.forEach(checkbox => checkbox.checked = false);
|
|
||||||
if (checkAll) checkAll.checked = false;
|
|
||||||
updateSelectedCount();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kelas tujuan change
|
|
||||||
if (kelasSelect) {
|
|
||||||
kelasSelect.addEventListener('change', updateSelectedCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Form submit confirmation
|
|
||||||
const form = document.getElementById('formKenaikanKelas');
|
|
||||||
if (form) {
|
|
||||||
form.addEventListener('submit', function(e) {
|
|
||||||
const checked = document.querySelectorAll('.santri-checkbox:checked').length;
|
|
||||||
const kelasText = kelasSelect.options[kelasSelect.selectedIndex].text;
|
|
||||||
|
|
||||||
if (!confirm(`Apakah Anda yakin ingin menaikkan ${checked} santri ke kelas "${kelasText}"?\n\nProses ini tidak dapat dibatalkan.`)) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initial count
|
|
||||||
updateSelectedCount();
|
|
||||||
});
|
|
||||||
</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/kelas/kenaikan/preview.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -108,8 +108,6 @@
|
||||||
<a href="<?php echo e(route('admin.kepulangan.create')); ?>" class="btn btn-primary">
|
<a href="<?php echo e(route('admin.kepulangan.create')); ?>" class="btn btn-primary">
|
||||||
<i class="fas fa-plus"></i> Tambah Izin Kepulangan
|
<i class="fas fa-plus"></i> Tambah Izin Kepulangan
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<a href="<?php echo e(route('admin.kepulangan.pengajuan')); ?>" class="btn btn-warning">
|
<a href="<?php echo e(route('admin.kepulangan.pengajuan')); ?>" class="btn btn-warning">
|
||||||
<i class="fas fa-mobile-alt"></i> Pengajuan izin
|
<i class="fas fa-mobile-alt"></i> Pengajuan izin
|
||||||
<?php if($pendingPengajuan > 0): ?>
|
<?php if($pendingPengajuan > 0): ?>
|
||||||
|
|
@ -126,14 +124,8 @@
|
||||||
<form method="GET" action="<?php echo e(route('admin.kepulangan.index')); ?>" id="filterForm" style="margin-bottom: 14px;">
|
<form method="GET" action="<?php echo e(route('admin.kepulangan.index')); ?>" id="filterForm" style="margin-bottom: 14px;">
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px; align-items: end;">
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px; align-items: end;">
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
<div class="form-group" style="margin-bottom: 0;">
|
||||||
<input type="text"
|
<input type="text" name="search" class="form-control" placeholder="Cari nama, ID, atau alasan..." value="<?php echo e(request('search')); ?>" id="searchInput">
|
||||||
name="search"
|
|
||||||
class="form-control"
|
|
||||||
placeholder="Cari nama, ID, atau alasan..."
|
|
||||||
value="<?php echo e(request('search')); ?>"
|
|
||||||
id="searchInput">
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
<div class="form-group" style="margin-bottom: 0;">
|
||||||
<select name="status" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
<select name="status" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
||||||
<option value="">Semua Status</option>
|
<option value="">Semua Status</option>
|
||||||
|
|
@ -143,19 +135,14 @@ class="form-control"
|
||||||
<option value="Selesai" <?php echo e(request('status') == 'Selesai' ? 'selected' : ''); ?>>Selesai</option>
|
<option value="Selesai" <?php echo e(request('status') == 'Selesai' ? 'selected' : ''); ?>>Selesai</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
<div class="form-group" style="margin-bottom: 0;">
|
||||||
<select name="tahun" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
<select name="tahun" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
||||||
<option value="">Semua Tahun</option>
|
<option value="">Semua Tahun</option>
|
||||||
<?php $__currentLoopData = $tahunList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $tahun): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
<?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' : ''); ?>>
|
<option value="<?php echo e($tahun); ?>" <?php echo e(request('tahun') == $tahun ? 'selected' : ''); ?>><?php echo e($tahun); ?></option>
|
||||||
<?php echo e($tahun); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
<div class="form-group" style="margin-bottom: 0;">
|
||||||
<select name="bulan" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
<select name="bulan" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
||||||
<option value="">Semua Bulan</option>
|
<option value="">Semua Bulan</option>
|
||||||
|
|
@ -167,14 +154,9 @@ class="form-control"
|
||||||
<?php endfor; ?>
|
<?php endfor; ?>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: flex; gap: 10px;">
|
<div style="display: flex; gap: 10px;">
|
||||||
<button type="submit" class="btn btn-primary">
|
<button type="submit" class="btn btn-primary"><i class="fas fa-search"></i> Filter</button>
|
||||||
<i class="fas fa-search"></i> Filter
|
<a href="<?php echo e(route('admin.kepulangan.index')); ?>" class="btn btn-secondary"><i class="fas fa-redo"></i> Reset</a>
|
||||||
</button>
|
|
||||||
<a href="<?php echo e(route('admin.kepulangan.index')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-redo"></i> Reset
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -206,8 +188,7 @@ class="form-control"
|
||||||
<td>
|
<td>
|
||||||
<strong><?php echo e($item->id_kepulangan); ?></strong>
|
<strong><?php echo e($item->id_kepulangan); ?></strong>
|
||||||
<?php if($isOverLimit): ?>
|
<?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;"
|
<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">
|
||||||
title="Over Limit: <?php echo e($totalHariTerpakai); ?> hari">
|
|
||||||
<i class="fas fa-exclamation-triangle"></i>
|
<i class="fas fa-exclamation-triangle"></i>
|
||||||
</span>
|
</span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
@ -215,10 +196,7 @@ class="form-control"
|
||||||
<td>
|
<td>
|
||||||
<div>
|
<div>
|
||||||
<strong><?php echo e($item->santri->nama_lengkap ?? 'N/A'); ?></strong><br>
|
<strong><?php echo e($item->santri->nama_lengkap ?? 'N/A'); ?></strong><br>
|
||||||
<small style="color: #7F8C8D;">
|
<small style="color: #7F8C8D;"><?php echo e($item->santri->id_santri ?? ''); ?> | <?php echo e($item->santri->kelas ?? ''); ?></small>
|
||||||
<?php echo e($item->santri->id_santri ?? ''); ?> | <?php echo e($item->santri->kelas ?? ''); ?>
|
|
||||||
|
|
||||||
</small>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td><?php echo e($item->tanggal_pulang_formatted); ?></td>
|
<td><?php echo e($item->tanggal_pulang_formatted); ?></td>
|
||||||
|
|
@ -232,11 +210,7 @@ class="form-control"
|
||||||
<?php
|
<?php
|
||||||
$kuotaSantri = \App\Models\Kepulangan::getSisaKuotaSantri($item->id_santri);
|
$kuotaSantri = \App\Models\Kepulangan::getSisaKuotaSantri($item->id_santri);
|
||||||
$badgeColor = $kuotaSantri['badge_color'];
|
$badgeColor = $kuotaSantri['badge_color'];
|
||||||
$badgeColors = [
|
$badgeColors = ['success' => '#28a745', 'warning' => '#ffc107', 'danger' => '#dc3545'];
|
||||||
'success' => '#28a745',
|
|
||||||
'warning' => '#ffc107',
|
|
||||||
'danger' => '#dc3545'
|
|
||||||
];
|
|
||||||
$bgColor = $badgeColors[$badgeColor] ?? '#6c757d';
|
$bgColor = $badgeColors[$badgeColor] ?? '#6c757d';
|
||||||
$textColor = $badgeColor == 'warning' ? '#000' : '#fff';
|
$textColor = $badgeColor == 'warning' ? '#000' : '#fff';
|
||||||
?>
|
?>
|
||||||
|
|
@ -277,49 +251,32 @@ class="form-control"
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<div style="display: flex; gap: 5px; justify-content: center; flex-wrap: wrap;">
|
<div style="display: flex; gap: 5px; justify-content: center; flex-wrap: wrap;">
|
||||||
<a href="<?php echo e(route('admin.kepulangan.show', $item->id_kepulangan)); ?>"
|
<a href="<?php echo e(route('admin.kepulangan.show', $item->id_kepulangan)); ?>" class="btn btn-sm btn-primary" title="Detail">
|
||||||
class="btn btn-sm btn-primary" title="Detail">
|
|
||||||
<i class="fas fa-eye"></i>
|
<i class="fas fa-eye"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<?php if($item->status == 'Menunggu'): ?>
|
<?php if($item->status == 'Menunggu'): ?>
|
||||||
<a href="<?php echo e(route('admin.kepulangan.edit', $item->id_kepulangan)); ?>"
|
<a href="<?php echo e(route('admin.kepulangan.edit', $item->id_kepulangan)); ?>" class="btn btn-sm btn-warning" title="Edit">
|
||||||
class="btn btn-sm btn-warning" title="Edit">
|
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
<button type="button"
|
<button type="button" class="btn btn-sm btn-success" onclick="approveKepulangan('<?php echo e($item->id_kepulangan); ?>')" title="Setujui">
|
||||||
class="btn btn-sm btn-success"
|
|
||||||
onclick="approveKepulangan('<?php echo e($item->id_kepulangan); ?>')"
|
|
||||||
title="Setujui">
|
|
||||||
<i class="fas fa-check"></i>
|
<i class="fas fa-check"></i>
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button type="button" class="btn btn-sm btn-danger" onclick="rejectKepulangan('<?php echo e($item->id_kepulangan); ?>')" title="Tolak">
|
||||||
class="btn btn-sm btn-danger"
|
|
||||||
onclick="rejectKepulangan('<?php echo e($item->id_kepulangan); ?>')"
|
|
||||||
title="Tolak">
|
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-times"></i>
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if($item->status == 'Disetujui'): ?>
|
<?php if($item->status == 'Disetujui'): ?>
|
||||||
<a href="<?php echo e(route('admin.kepulangan.print', $item->id_kepulangan)); ?>"
|
<a href="<?php echo e(route('admin.kepulangan.print', $item->id_kepulangan)); ?>" class="btn btn-sm btn-secondary" target="_blank" title="Cetak Surat">
|
||||||
class="btn btn-sm btn-secondary"
|
|
||||||
target="_blank" title="Cetak Surat">
|
|
||||||
<i class="fas fa-print"></i>
|
<i class="fas fa-print"></i>
|
||||||
</a>
|
</a>
|
||||||
<button type="button"
|
<button type="button" class="btn btn-sm btn-success"
|
||||||
class="btn btn-sm btn-success"
|
|
||||||
onclick="completeKepulangan('<?php echo e($item->id_kepulangan); ?>', '<?php echo e($item->santri->nama_lengkap); ?>', '<?php echo e($item->tanggal_pulang->format('Y-m-d')); ?>', '<?php echo e($item->tanggal_kembali->format('Y-m-d')); ?>', <?php echo e($item->durasi_izin); ?>)"
|
onclick="completeKepulangan('<?php echo e($item->id_kepulangan); ?>', '<?php echo e($item->santri->nama_lengkap); ?>', '<?php echo e($item->tanggal_pulang->format('Y-m-d')); ?>', '<?php echo e($item->tanggal_kembali->format('Y-m-d')); ?>', <?php echo e($item->durasi_izin); ?>)"
|
||||||
title="Selesaikan">
|
title="Selesaikan">
|
||||||
<i class="fas fa-check-double"></i>
|
<i class="fas fa-check-double"></i>
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if(in_array($item->status, ['Menunggu', 'Ditolak', 'Selesai'])): ?>
|
<?php if(in_array($item->status, ['Menunggu', 'Ditolak', 'Selesai'])): ?>
|
||||||
<button type="button"
|
<button type="button" class="btn btn-sm btn-danger" onclick="deleteKepulangan('<?php echo e($item->id_kepulangan); ?>')" title="Hapus">
|
||||||
class="btn btn-sm btn-danger"
|
|
||||||
onclick="deleteKepulangan('<?php echo e($item->id_kepulangan); ?>')"
|
|
||||||
title="Hapus">
|
|
||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
@ -342,14 +299,8 @@ class="btn btn-sm btn-danger"
|
||||||
|
|
||||||
<?php if($kepulangan->hasPages()): ?>
|
<?php if($kepulangan->hasPages()): ?>
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 14px; flex-wrap: wrap; gap: 11px;">
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 14px; flex-wrap: wrap; gap: 11px;">
|
||||||
<div>
|
<div>Menampilkan <?php echo e($kepulangan->firstItem() ?? 0); ?> - <?php echo e($kepulangan->lastItem() ?? 0); ?> dari <?php echo e($kepulangan->total()); ?> data</div>
|
||||||
Menampilkan <?php echo e($kepulangan->firstItem() ?? 0); ?> - <?php echo e($kepulangan->lastItem() ?? 0); ?>
|
<div><?php echo e($kepulangan->appends(request()->query())->links()); ?></div>
|
||||||
dari <?php echo e($kepulangan->total()); ?> data
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<?php echo e($kepulangan->appends(request()->query())->links()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -360,19 +311,14 @@ class="btn btn-sm btn-danger"
|
||||||
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
||||||
<form id="approveForm">
|
<form id="approveForm">
|
||||||
<?php echo csrf_field(); ?>
|
<?php echo csrf_field(); ?>
|
||||||
<div style="margin-bottom: 14px;">
|
<div style="margin-bottom: 14px;"><h3 style="margin: 0; color: #2C3E50;">Setujui Izin Kepulangan</h3></div>
|
||||||
<h3 style="margin: 0; color: #2C3E50;">Setujui Izin Kepulangan</h3>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Catatan (Opsional):</label>
|
<label>Catatan (Opsional):</label>
|
||||||
<textarea name="catatan" class="form-control" rows="3"
|
<textarea name="catatan" class="form-control" rows="3" placeholder="Tambahkan catatan untuk persetujuan ini..."></textarea>
|
||||||
placeholder="Tambahkan catatan untuk persetujuan ini..."></textarea>
|
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('approveModal')">Batal</button>
|
<button type="button" class="btn btn-secondary" onclick="closeModal('approveModal')">Batal</button>
|
||||||
<button type="submit" class="btn btn-success">
|
<button type="submit" class="btn btn-success"><i class="fas fa-check"></i> Setujui</button>
|
||||||
<i class="fas fa-check"></i> Setujui
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -385,19 +331,14 @@ class="btn btn-sm btn-danger"
|
||||||
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
||||||
<form id="rejectForm">
|
<form id="rejectForm">
|
||||||
<?php echo csrf_field(); ?>
|
<?php echo csrf_field(); ?>
|
||||||
<div style="margin-bottom: 14px;">
|
<div style="margin-bottom: 14px;"><h3 style="margin: 0; color: #2C3E50;">Tolak Izin Kepulangan</h3></div>
|
||||||
<h3 style="margin: 0; color: #2C3E50;">Tolak Izin Kepulangan</h3>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Alasan Penolakan: <span style="color: #dc3545;">*</span></label>
|
<label>Alasan Penolakan: <span style="color: #dc3545;">*</span></label>
|
||||||
<textarea name="alasan_penolakan" class="form-control" rows="3"
|
<textarea name="alasan_penolakan" class="form-control" rows="3" placeholder="Jelaskan alasan penolakan..." required></textarea>
|
||||||
placeholder="Jelaskan alasan penolakan..." required></textarea>
|
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('rejectModal')">Batal</button>
|
<button type="button" class="btn btn-secondary" onclick="closeModal('rejectModal')">Batal</button>
|
||||||
<button type="submit" class="btn btn-danger">
|
<button type="submit" class="btn btn-danger"><i class="fas fa-times"></i> Tolak</button>
|
||||||
<i class="fas fa-times"></i> Tolak
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -408,16 +349,12 @@ class="btn btn-sm btn-danger"
|
||||||
<div class="modal fade" id="deleteModal" tabindex="-1" style="display: none;">
|
<div class="modal fade" id="deleteModal" tabindex="-1" style="display: none;">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
||||||
<div style="margin-bottom: 14px;">
|
<div style="margin-bottom: 14px;"><h3 style="margin: 0; color: #2C3E50;">Konfirmasi Hapus</h3></div>
|
||||||
<h3 style="margin: 0; color: #2C3E50;">Konfirmasi Hapus</h3>
|
|
||||||
</div>
|
|
||||||
<p>Apakah Anda yakin ingin menghapus data kepulangan ini?</p>
|
<p>Apakah Anda yakin ingin menghapus data kepulangan ini?</p>
|
||||||
<p style="color: #dc3545; font-size: 0.9rem;">Data yang sudah dihapus tidak dapat dikembalikan.</p>
|
<p style="color: #dc3545; font-size: 0.9rem;">Data yang sudah dihapus tidak dapat dikembalikan.</p>
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('deleteModal')">Batal</button>
|
<button type="button" class="btn btn-secondary" onclick="closeModal('deleteModal')">Batal</button>
|
||||||
<button type="button" class="btn btn-danger" id="confirmDeleteBtn">
|
<button type="button" class="btn btn-danger" id="confirmDeleteBtn"><i class="fas fa-trash"></i> Hapus</button>
|
||||||
<i class="fas fa-trash"></i> Hapus
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -430,12 +367,8 @@ class="btn btn-sm btn-danger"
|
||||||
<form id="completeForm">
|
<form id="completeForm">
|
||||||
<?php echo csrf_field(); ?>
|
<?php echo csrf_field(); ?>
|
||||||
<div style="margin-bottom: 14px;">
|
<div style="margin-bottom: 14px;">
|
||||||
<h3 style="margin: 0; color: #2C3E50;">
|
<h3 style="margin: 0; color: #2C3E50;"><i class="fas fa-check-circle" style="color: #28a745;"></i> Selesaikan Kepulangan</h3>
|
||||||
<i class="fas fa-check-circle" style="color: #28a745;"></i>
|
|
||||||
Selesaikan Kepulangan
|
|
||||||
</h3>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="background: #E8F7F2; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #6FBA9D;">
|
<div style="background: #E8F7F2; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #6FBA9D;">
|
||||||
<p style="margin: 5px 0;"><strong>ID Kepulangan:</strong> <span id="completeIdKepulangan"></span></p>
|
<p style="margin: 5px 0;"><strong>ID Kepulangan:</strong> <span id="completeIdKepulangan"></span></p>
|
||||||
<p style="margin: 5px 0;"><strong>Santri:</strong> <span id="completeNamaSantri"></span></p>
|
<p style="margin: 5px 0;"><strong>Santri:</strong> <span id="completeNamaSantri"></span></p>
|
||||||
|
|
@ -443,32 +376,20 @@ class="btn btn-sm btn-danger"
|
||||||
<p style="margin: 5px 0;"><strong>Rencana Kembali:</strong> <span id="completeTanggalKembaliRencana"></span></p>
|
<p style="margin: 5px 0;"><strong>Rencana Kembali:</strong> <span id="completeTanggalKembaliRencana"></span></p>
|
||||||
<p style="margin: 5px 0;"><strong>Durasi Rencana:</strong> <span id="completeDurasiRencana"></span> hari</p>
|
<p style="margin: 5px 0;"><strong>Durasi Rencana:</strong> <span id="completeDurasiRencana"></span> hari</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="tanggal_kembali_aktual">
|
<label for="tanggal_kembali_aktual">
|
||||||
<i class="fas fa-calendar-check"></i>
|
<i class="fas fa-calendar-check"></i> Tanggal Kembali Aktual <span style="color: #dc3545;">*</span>
|
||||||
Tanggal Kembali Aktual <span style="color: #dc3545;">*</span>
|
|
||||||
</label>
|
</label>
|
||||||
<input type="date"
|
<input type="date" name="tanggal_kembali_aktual" id="tanggal_kembali_aktual" class="form-control" required>
|
||||||
name="tanggal_kembali_aktual"
|
<small style="color: #7F8C8D; margin-top: 5px; display: block;">Masukkan tanggal santri kembali ke pesantren.</small>
|
||||||
id="tanggal_kembali_aktual"
|
|
||||||
class="form-control"
|
|
||||||
required>
|
|
||||||
<small style="color: #7F8C8D; margin-top: 5px; display: block;">
|
|
||||||
Masukkan tanggal santri kembali ke pesantren. Jika pulang lebih cepat, kuota akan disesuaikan otomatis.
|
|
||||||
</small>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="durasiAktualInfo" style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #007bff; display: none;">
|
<div id="durasiAktualInfo" style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #007bff; display: none;">
|
||||||
<p style="margin: 0;"><strong>Durasi Aktual:</strong> <span id="durasiAktual" style="font-weight: 600; color: #007bff;">-</span> hari</p>
|
<p style="margin: 0;"><strong>Durasi Aktual:</strong> <span id="durasiAktual" style="font-weight: 600; color: #007bff;">-</span> hari</p>
|
||||||
<p style="margin: 5px 0 0 0; font-size: 0.9rem; color: #7F8C8D;" id="selisihInfo"></p>
|
<p style="margin: 5px 0 0 0; font-size: 0.9rem; color: #7F8C8D;" id="selisihInfo"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('completeModal')">Batal</button>
|
<button type="button" class="btn btn-secondary" onclick="closeModal('completeModal')">Batal</button>
|
||||||
<button type="submit" class="btn btn-success">
|
<button type="submit" class="btn btn-success"><i class="fas fa-check"></i> Selesaikan</button>
|
||||||
<i class="fas fa-check"></i> Selesaikan
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -479,26 +400,26 @@ 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.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 { max-width: 500px; width: 90%; margin: auto; }
|
||||||
.modal-content { max-height: 90vh; overflow-y: auto; }
|
.modal-content { max-height: 90vh; overflow-y: auto; }
|
||||||
|
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
|
||||||
@keyframes pulse {
|
|
||||||
0%, 100% { opacity: 1; }
|
|
||||||
50% { opacity: 0.5; }
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const KEPULANGAN_BASE_URL = "<?php echo e(url('admin/kepulangan')); ?>";
|
||||||
|
const CSRF_TOKEN = "<?php echo e(csrf_token()); ?>";
|
||||||
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let currentActionId = null;
|
let currentActionId = null;
|
||||||
|
|
||||||
// Auto submit search dengan debounce
|
// Auto submit search
|
||||||
let searchTimeout;
|
let searchTimeout;
|
||||||
document.getElementById('searchInput')?.addEventListener('input', function() {
|
document.getElementById('searchInput')?.addEventListener('input', function() {
|
||||||
clearTimeout(searchTimeout);
|
clearTimeout(searchTimeout);
|
||||||
searchTimeout = setTimeout(() => {
|
searchTimeout = setTimeout(() => document.getElementById('filterForm').submit(), 500);
|
||||||
document.getElementById('filterForm').submit();
|
|
||||||
}, 500);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Approve
|
// ===== APPROVE =====
|
||||||
function approveKepulangan(id) {
|
function approveKepulangan(id) {
|
||||||
currentActionId = id;
|
currentActionId = id;
|
||||||
document.getElementById('approveModal').style.display = 'flex';
|
document.getElementById('approveModal').style.display = 'flex';
|
||||||
|
|
@ -509,33 +430,25 @@ function approveKepulangan(id) {
|
||||||
const formData = new FormData(this);
|
const formData = new FormData(this);
|
||||||
const submitBtn = this.querySelector('button[type="submit"]');
|
const submitBtn = this.querySelector('button[type="submit"]');
|
||||||
const originalText = submitBtn.innerHTML;
|
const originalText = submitBtn.innerHTML;
|
||||||
|
|
||||||
submitBtn.disabled = true;
|
submitBtn.disabled = true;
|
||||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
||||||
|
|
||||||
fetch(`/admin/kepulangan/${currentActionId}/approve`, {
|
// ✅ FIX: pakai KEPULANGAN_BASE_URL
|
||||||
|
fetch(`${KEPULANGAN_BASE_URL}/${currentActionId}/approve`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
headers: { 'X-CSRF-TOKEN': '<?php echo e(csrf_token()); ?>' }
|
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) { closeModal('approveModal'); showAlert('success', data.message); setTimeout(() => location.reload(), 1000); }
|
||||||
closeModal('approveModal');
|
else showAlert('danger', data.message);
|
||||||
showAlert('success', data.message);
|
|
||||||
setTimeout(() => window.location.reload(), 1000);
|
|
||||||
} else {
|
|
||||||
showAlert('danger', data.message);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(error => showAlert('danger', 'Error: ' + error.message))
|
.catch(e => showAlert('danger', 'Error: ' + e.message))
|
||||||
.finally(() => {
|
.finally(() => { submitBtn.disabled = false; submitBtn.innerHTML = originalText; });
|
||||||
submitBtn.disabled = false;
|
|
||||||
submitBtn.innerHTML = originalText;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reject
|
// ===== REJECT =====
|
||||||
function rejectKepulangan(id) {
|
function rejectKepulangan(id) {
|
||||||
currentActionId = id;
|
currentActionId = id;
|
||||||
document.getElementById('rejectModal').style.display = 'flex';
|
document.getElementById('rejectModal').style.display = 'flex';
|
||||||
|
|
@ -546,150 +459,92 @@ function rejectKepulangan(id) {
|
||||||
const formData = new FormData(this);
|
const formData = new FormData(this);
|
||||||
const submitBtn = this.querySelector('button[type="submit"]');
|
const submitBtn = this.querySelector('button[type="submit"]');
|
||||||
const originalText = submitBtn.innerHTML;
|
const originalText = submitBtn.innerHTML;
|
||||||
|
|
||||||
submitBtn.disabled = true;
|
submitBtn.disabled = true;
|
||||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
||||||
|
|
||||||
fetch(`/admin/kepulangan/${currentActionId}/reject`, {
|
// ✅ FIX: pakai KEPULANGAN_BASE_URL
|
||||||
|
fetch(`${KEPULANGAN_BASE_URL}/${currentActionId}/reject`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
headers: { 'X-CSRF-TOKEN': '<?php echo e(csrf_token()); ?>' }
|
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) { closeModal('rejectModal'); showAlert('success', data.message); setTimeout(() => location.reload(), 1000); }
|
||||||
closeModal('rejectModal');
|
else showAlert('danger', data.message);
|
||||||
showAlert('success', data.message);
|
|
||||||
setTimeout(() => window.location.reload(), 1000);
|
|
||||||
} else {
|
|
||||||
showAlert('danger', data.message);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(error => showAlert('danger', 'Error: ' + error.message))
|
.catch(e => showAlert('danger', 'Error: ' + e.message))
|
||||||
.finally(() => {
|
.finally(() => { submitBtn.disabled = false; submitBtn.innerHTML = originalText; });
|
||||||
submitBtn.disabled = false;
|
|
||||||
submitBtn.innerHTML = originalText;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Complete (Selesaikan Kepulangan)
|
// ===== COMPLETE =====
|
||||||
let currentCompleteData = {};
|
let currentCompleteData = {};
|
||||||
|
|
||||||
function completeKepulangan(id, namaSantri, tanggalPulang, tanggalKembaliRencana, durasiRencana) {
|
function completeKepulangan(id, namaSantri, tanggalPulang, tanggalKembaliRencana, durasiRencana) {
|
||||||
currentCompleteData = {
|
currentCompleteData = { id, namaSantri, tanggalPulang, tanggalKembaliRencana, durasiRencana };
|
||||||
id: id,
|
|
||||||
namaSantri: namaSantri,
|
|
||||||
tanggalPulang: tanggalPulang,
|
|
||||||
tanggalKembaliRencana: tanggalKembaliRencana,
|
|
||||||
durasiRencana: durasiRencana
|
|
||||||
};
|
|
||||||
|
|
||||||
// Populate modal
|
|
||||||
document.getElementById('completeIdKepulangan').textContent = id;
|
document.getElementById('completeIdKepulangan').textContent = id;
|
||||||
document.getElementById('completeNamaSantri').textContent = namaSantri;
|
document.getElementById('completeNamaSantri').textContent = namaSantri;
|
||||||
document.getElementById('completeTanggalPulang').textContent = formatTanggal(tanggalPulang);
|
document.getElementById('completeTanggalPulang').textContent = formatTanggal(tanggalPulang);
|
||||||
document.getElementById('completeTanggalKembaliRencana').textContent = formatTanggal(tanggalKembaliRencana);
|
document.getElementById('completeTanggalKembaliRencana').textContent = formatTanggal(tanggalKembaliRencana);
|
||||||
document.getElementById('completeDurasiRencana').textContent = durasiRencana;
|
document.getElementById('completeDurasiRencana').textContent = durasiRencana;
|
||||||
|
|
||||||
// Set default tanggal kembali aktual = hari ini
|
|
||||||
const today = new Date().toISOString().split('T')[0];
|
const today = new Date().toISOString().split('T')[0];
|
||||||
document.getElementById('tanggal_kembali_aktual').value = today;
|
document.getElementById('tanggal_kembali_aktual').value = today;
|
||||||
document.getElementById('tanggal_kembali_aktual').min = tanggalPulang;
|
document.getElementById('tanggal_kembali_aktual').min = tanggalPulang;
|
||||||
|
|
||||||
// Hitung durasi aktual
|
|
||||||
calculateDurasiAktual();
|
calculateDurasiAktual();
|
||||||
|
|
||||||
// Show modal
|
|
||||||
document.getElementById('completeModal').style.display = 'flex';
|
document.getElementById('completeModal').style.display = 'flex';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate durasi aktual
|
|
||||||
function calculateDurasiAktual() {
|
function calculateDurasiAktual() {
|
||||||
const tanggalPulang = currentCompleteData.tanggalPulang;
|
|
||||||
const tanggalKembaliAktual = document.getElementById('tanggal_kembali_aktual').value;
|
const tanggalKembaliAktual = document.getElementById('tanggal_kembali_aktual').value;
|
||||||
|
if (!tanggalKembaliAktual || !currentCompleteData.tanggalPulang) return;
|
||||||
if (!tanggalKembaliAktual) return;
|
const startDate = new Date(currentCompleteData.tanggalPulang);
|
||||||
|
|
||||||
const startDate = new Date(tanggalPulang);
|
|
||||||
const endDate = new Date(tanggalKembaliAktual);
|
const endDate = new Date(tanggalKembaliAktual);
|
||||||
|
if (endDate < startDate) { document.getElementById('durasiAktualInfo').style.display = 'none'; return; }
|
||||||
if (endDate < startDate) {
|
const durasiAktual = Math.ceil(Math.abs(endDate - startDate) / (1000 * 60 * 60 * 24)) + 1;
|
||||||
document.getElementById('durasiAktualInfo').style.display = 'none';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const diffTime = Math.abs(endDate - startDate);
|
|
||||||
const durasiAktual = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1;
|
|
||||||
const durasiRencana = currentCompleteData.durasiRencana;
|
const durasiRencana = currentCompleteData.durasiRencana;
|
||||||
|
|
||||||
document.getElementById('durasiAktual').textContent = durasiAktual;
|
document.getElementById('durasiAktual').textContent = durasiAktual;
|
||||||
document.getElementById('durasiAktualInfo').style.display = 'block';
|
document.getElementById('durasiAktualInfo').style.display = 'block';
|
||||||
|
let selisihText = '', selisihColor = '#007bff';
|
||||||
// Show selisih
|
|
||||||
let selisihText = '';
|
|
||||||
let selisihColor = '#007bff';
|
|
||||||
|
|
||||||
if (durasiAktual < durasiRencana) {
|
if (durasiAktual < durasiRencana) {
|
||||||
const selisih = durasiRencana - durasiAktual;
|
selisihText = `Santri pulang ${durasiRencana - durasiAktual} hari lebih cepat. Kuota akan berkurang ${durasiAktual} hari.`;
|
||||||
selisihText = `✅ Santri pulang ${selisih} hari lebih cepat dari rencana. Kuota akan berkurang ${durasiAktual} hari.`;
|
|
||||||
selisihColor = '#28a745';
|
selisihColor = '#28a745';
|
||||||
} else if (durasiAktual > durasiRencana) {
|
} else if (durasiAktual > durasiRencana) {
|
||||||
const selisih = durasiAktual - durasiRencana;
|
selisihText = `Santri pulang ${durasiAktual - durasiRencana} hari lebih lambat. Kuota akan bertambah.`;
|
||||||
selisihText = `⚠︠Santri pulang ${selisih} hari lebih lambat dari rencana. Kuota akan bertambah ${selisih} hari.`;
|
|
||||||
selisihColor = '#ffc107';
|
selisihColor = '#ffc107';
|
||||||
} else {
|
} else {
|
||||||
selisihText = `✓ Sesuai rencana (${durasiAktual} hari).`;
|
selisihText = `Sesuai rencana (${durasiAktual} hari).`;
|
||||||
selisihColor = '#007bff';
|
|
||||||
}
|
}
|
||||||
|
document.getElementById('selisihInfo').textContent = selisihText;
|
||||||
const selisihInfo = document.getElementById('selisihInfo');
|
document.getElementById('selisihInfo').style.color = selisihColor;
|
||||||
selisihInfo.textContent = selisihText;
|
|
||||||
selisihInfo.style.color = selisihColor;
|
|
||||||
document.getElementById('durasiAktual').style.color = selisihColor;
|
document.getElementById('durasiAktual').style.color = selisihColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event listener untuk tanggal kembali aktual
|
|
||||||
document.getElementById('tanggal_kembali_aktual')?.addEventListener('change', calculateDurasiAktual);
|
document.getElementById('tanggal_kembali_aktual')?.addEventListener('change', calculateDurasiAktual);
|
||||||
|
|
||||||
// Submit form complete
|
|
||||||
document.getElementById('completeForm')?.addEventListener('submit', function(e) {
|
document.getElementById('completeForm')?.addEventListener('submit', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const formData = new FormData(this);
|
const formData = new FormData(this);
|
||||||
const submitBtn = this.querySelector('button[type="submit"]');
|
const submitBtn = this.querySelector('button[type="submit"]');
|
||||||
const originalText = submitBtn.innerHTML;
|
const originalText = submitBtn.innerHTML;
|
||||||
|
|
||||||
submitBtn.disabled = true;
|
submitBtn.disabled = true;
|
||||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
||||||
|
|
||||||
fetch(`/admin/kepulangan/${currentCompleteData.id}/complete`, {
|
// ✅ FIX: pakai KEPULANGAN_BASE_URL
|
||||||
|
fetch(`${KEPULANGAN_BASE_URL}/${currentCompleteData.id}/complete`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
headers: { 'X-CSRF-TOKEN': '<?php echo e(csrf_token()); ?>' }
|
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) { closeModal('completeModal'); showAlert('success', data.message); setTimeout(() => location.reload(), 1500); }
|
||||||
closeModal('completeModal');
|
else showAlert('danger', data.message);
|
||||||
showAlert('success', data.message);
|
|
||||||
setTimeout(() => window.location.reload(), 1500);
|
|
||||||
} else {
|
|
||||||
showAlert('danger', data.message);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(error => showAlert('danger', 'Error: ' + error.message))
|
.catch(e => showAlert('danger', 'Error: ' + e.message))
|
||||||
.finally(() => {
|
.finally(() => { submitBtn.disabled = false; submitBtn.innerHTML = originalText; });
|
||||||
submitBtn.disabled = false;
|
|
||||||
submitBtn.innerHTML = originalText;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Helper: Format tanggal
|
// ===== DELETE =====
|
||||||
function formatTanggal(dateString) {
|
|
||||||
const options = { year: 'numeric', month: 'long', day: 'numeric' };
|
|
||||||
return new Date(dateString).toLocaleDateString('id-ID', options);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete
|
|
||||||
function deleteKepulangan(id) {
|
function deleteKepulangan(id) {
|
||||||
currentActionId = id;
|
currentActionId = id;
|
||||||
document.getElementById('deleteModal').style.display = 'flex';
|
document.getElementById('deleteModal').style.display = 'flex';
|
||||||
|
|
@ -698,61 +553,39 @@ function deleteKepulangan(id) {
|
||||||
document.getElementById('confirmDeleteBtn').addEventListener('click', function() {
|
document.getElementById('confirmDeleteBtn').addEventListener('click', function() {
|
||||||
const btn = this;
|
const btn = this;
|
||||||
const originalText = btn.innerHTML;
|
const originalText = btn.innerHTML;
|
||||||
|
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Menghapus...';
|
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Menghapus...';
|
||||||
|
|
||||||
fetch(`/admin/kepulangan/${currentActionId}`, {
|
// ✅ FIX: pakai KEPULANGAN_BASE_URL
|
||||||
|
fetch(`${KEPULANGAN_BASE_URL}/${currentActionId}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: { 'X-CSRF-TOKEN': '<?php echo e(csrf_token()); ?>' }
|
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) { closeModal('deleteModal'); showAlert('success', data.message); setTimeout(() => location.reload(), 1000); }
|
||||||
closeModal('deleteModal');
|
else showAlert('danger', data.message);
|
||||||
showAlert('success', data.message);
|
|
||||||
setTimeout(() => window.location.reload(), 1000);
|
|
||||||
} else {
|
|
||||||
showAlert('danger', data.message);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(error => showAlert('danger', 'Error: ' + error.message))
|
.catch(e => showAlert('danger', 'Error: ' + e.message))
|
||||||
.finally(() => {
|
.finally(() => { btn.disabled = false; btn.innerHTML = originalText; });
|
||||||
btn.disabled = false;
|
|
||||||
btn.innerHTML = originalText;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Helper functions
|
// ===== HELPERS =====
|
||||||
function closeModal(modalId) {
|
function formatTanggal(dateString) {
|
||||||
document.getElementById(modalId).style.display = 'none';
|
return new Date(dateString).toLocaleDateString('id-ID', { year: 'numeric', month: 'long', day: 'numeric' });
|
||||||
}
|
}
|
||||||
|
function closeModal(modalId) { document.getElementById(modalId).style.display = 'none'; }
|
||||||
function showAlert(type, message) {
|
function showAlert(type, message) {
|
||||||
const alertDiv = document.createElement('div');
|
const alertDiv = document.createElement('div');
|
||||||
alertDiv.className = `alert alert-${type}`;
|
alertDiv.className = `alert alert-${type}`;
|
||||||
alertDiv.innerHTML = `<i class="fas fa-${type === 'success' ? 'check' : 'exclamation'}-circle"></i> ${message}`;
|
alertDiv.innerHTML = `<i class="fas fa-${type === 'success' ? 'check' : 'exclamation'}-circle"></i> ${message}`;
|
||||||
|
document.querySelector('.page-header').insertAdjacentElement('afterend', alertDiv);
|
||||||
const pageHeader = document.querySelector('.page-header');
|
|
||||||
pageHeader.insertAdjacentElement('afterend', alertDiv);
|
|
||||||
|
|
||||||
setTimeout(() => alertDiv.remove(), 5000);
|
setTimeout(() => alertDiv.remove(), 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close modals on ESC
|
document.addEventListener('keydown', e => { if (e.key === 'Escape') document.querySelectorAll('.modal.fade').forEach(m => m.style.display = 'none'); });
|
||||||
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 => {
|
document.querySelectorAll('.modal.fade').forEach(modal => {
|
||||||
modal.addEventListener('click', function(e) {
|
modal.addEventListener('click', function(e) { if (e.target === this) this.style.display = 'none'; });
|
||||||
if (e.target === this) {
|
|
||||||
this.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<?php $__env->stopSection(); ?>
|
<?php $__env->stopSection(); ?>
|
||||||
|
|
|
||||||
|
|
@ -1,180 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Manajemen Akun Wali Santri'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-mobile-alt"></i> Manajemen Akun Wali Santri (Mobile App)</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if(session('success')): ?>
|
|
||||||
<div class="alert alert-success"><?php echo session('success'); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if(session('error')): ?>
|
|
||||||
<div class="alert alert-danger"><?php echo e(session('error')); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if(session('info')): ?>
|
|
||||||
<div class="alert alert-info"><?php echo e(session('info')); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<div class="alert alert-info">
|
|
||||||
<i class="fas fa-info-circle"></i> <strong>Info Login Wali (Mobile):</strong><br>
|
|
||||||
<strong>Username:</strong> Nama Orang Tua
|
|
||||||
<small class="text-muted">(jika ada nama orang tua yang sama, otomatis menjadi "Nama Orang Tua - Nama Santri")</small><br>
|
|
||||||
<strong>Password:</strong> NIS Santri
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Daftar Akun Wali (<?php echo e($users->count()); ?>)</h3>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID Santri</th>
|
|
||||||
<th>Nama Santri</th>
|
|
||||||
<th>Nama Orang Tua</th>
|
|
||||||
<th>NIS</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->id_santri); ?></td>
|
|
||||||
<td><?php echo e($user->santri->nama_lengkap ?? '-'); ?></td>
|
|
||||||
<td><?php echo e($user->santri->nama_orang_tua ?? '-'); ?></td>
|
|
||||||
<td><?php echo e($user->santri->nis ?? '-'); ?></td>
|
|
||||||
<td><code><?php echo e($user->username); ?></code></td>
|
|
||||||
<td>
|
|
||||||
<form action="<?php echo e(route('admin.users.wali_destroy', $user->id)); ?>"
|
|
||||||
method="POST" style="display:inline;"
|
|
||||||
onsubmit="return confirm('Yakin hapus akun wali <?php echo e($user->santri->nama_lengkap ?? ''); ?>?')">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<button type="submit" class="btn btn-sm btn-danger">
|
|
||||||
<i class="fas fa-trash"></i> Hapus
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
|
||||||
<tr>
|
|
||||||
<td colspan="6" class="text-center">Belum ada akun wali.</td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<h3 style="margin-top:22px;">
|
|
||||||
Santri Belum Punya Akun Wali (<?php echo e($santris_tanpa_wali->count()); ?>)
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<?php if($santris_tanpa_wali->count() > 0): ?>
|
|
||||||
<div style="margin-bottom:12px;">
|
|
||||||
<form action="<?php echo e(route('admin.users.wali_buat_semua')); ?>" method="POST" style="display:inline;"
|
|
||||||
onsubmit="return confirm('Buat akun wali untuk SEMUA <?php echo e($santris_tanpa_wali->count()); ?> santri sekaligus?')">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<button type="submit" class="btn btn-success">
|
|
||||||
<i class="fas fa-users"></i> Buat Semua Sekaligus (<?php echo e($santris_tanpa_wali->count()); ?>)
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
// Kumpulkan nama ortu yang sudah dipakai di akun existing
|
|
||||||
// untuk preview username yang akan dibuat
|
|
||||||
$namaOrtuSudahAda = \App\Models\SantriAccount::where('role', 'wali')
|
|
||||||
->pluck('username')
|
|
||||||
->toArray();
|
|
||||||
$namaOrtuPreviewDipakai = [];
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="table-wrapper">
|
|
||||||
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID Santri</th>
|
|
||||||
<th>NIS</th>
|
|
||||||
<th>Nama Santri</th>
|
|
||||||
<th>Nama Orang Tua</th>
|
|
||||||
<th>Kelas</th>
|
|
||||||
<th>Username (Preview)</th>
|
|
||||||
<th>Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__empty_1 = true; $__currentLoopData = $santris_tanpa_wali; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
|
|
||||||
<?php
|
|
||||||
// Preview username: sama persis dgn logika resolveUsernameWali() di controller
|
|
||||||
$previewUsername = null;
|
|
||||||
if ($santri->nama_orang_tua) {
|
|
||||||
$usernameDefault = $santri->nama_orang_tua;
|
|
||||||
$sudahDiDb = in_array($usernameDefault, $namaOrtuSudahAda);
|
|
||||||
$sudahDiMemori = in_array($usernameDefault, $namaOrtuPreviewDipakai);
|
|
||||||
|
|
||||||
if ($sudahDiDb || $sudahDiMemori) {
|
|
||||||
$previewUsername = $usernameDefault . ' - ' . $santri->nama_lengkap;
|
|
||||||
} else {
|
|
||||||
$previewUsername = $usernameDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
$namaOrtuPreviewDipakai[] = $previewUsername;
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($santri->id_santri); ?></td>
|
|
||||||
<td>
|
|
||||||
<?php if($santri->nis): ?>
|
|
||||||
<?php echo e($santri->nis); ?>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="text-danger">Belum ada NIS</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td><?php echo e($santri->nama_lengkap); ?></td>
|
|
||||||
<td><?php echo e($santri->nama_orang_tua ?? '-'); ?></td>
|
|
||||||
<td><?php echo e($santri->kelas ?? '-'); ?></td>
|
|
||||||
<td>
|
|
||||||
<?php if($previewUsername): ?>
|
|
||||||
<code style="font-size:.78rem;"><?php echo e($previewUsername); ?></code>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="text-muted">-</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($santri->nis && $santri->nama_orang_tua): ?>
|
|
||||||
<form action="<?php echo e(route('admin.users.wali_buat_akun', $santri->id_santri)); ?>"
|
|
||||||
method="POST" style="display:inline;"
|
|
||||||
onsubmit="return confirm('Buat akun wali untuk <?php echo e($santri->nama_lengkap); ?>?')">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<button type="submit" class="btn btn-sm btn-primary">
|
|
||||||
<i class="fas fa-user-plus"></i> Buat Akun
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
<?php elseif(!$santri->nis): ?>
|
|
||||||
<span class="text-muted">Isi NIS dulu</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="text-muted">Isi nama orang tua dulu</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
|
||||||
<tr>
|
|
||||||
<td colspan="7" class="text-center text-success">
|
|
||||||
<i class="fas fa-check"></i> Semua santri sudah punya akun wali.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</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/users/wali_accounts.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,506 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Preview Import Absensi'); ?>
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<?php
|
|
||||||
use Carbon\Carbon;
|
|
||||||
|
|
||||||
$statusStyle = [
|
|
||||||
'Hadir' => ['bg'=>'#DCFCE7','c'=>'#166534','ic'=>'✅'],
|
|
||||||
'Terlambat' => ['bg'=>'#FEF9C3','c'=>'#92400E','ic'=>'⏰'],
|
|
||||||
'Alpa' => ['bg'=>'#FEE2E2','c'=>'#991B1B','ic'=>'❌'],
|
|
||||||
'Pulang' => ['bg'=>'#FFF7ED','c'=>'#9A3412','ic'=>'🏠'],
|
|
||||||
'Izin' => ['bg'=>'#F3E8FF','c'=>'#6B21A8','ic'=>'📋'],
|
|
||||||
'Sakit' => ['bg'=>'#E0F2FE','c'=>'#0C4A6E','ic'=>'🏥'],
|
|
||||||
];
|
|
||||||
|
|
||||||
// ── 1. Kolom kegiatan: UNIK, diurutkan waktu_mulai ───────────────────────────
|
|
||||||
$kegiatanCols = collect($hasilEnriched)
|
|
||||||
->flatMap(fn($h) => $h['rows'])
|
|
||||||
->unique('kegiatan_id')
|
|
||||||
->sortBy('waktu_mulai')
|
|
||||||
->values()
|
|
||||||
->map(fn($r) => [
|
|
||||||
'kegiatan_id' => $r['kegiatan_id'],
|
|
||||||
'nama' => $r['nama_kegiatan'],
|
|
||||||
'waktu_mulai' => $r['waktu_mulai'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// ── 2. Susun data: [tanggal][id_santri_or_mesin] = data ──────────────────────
|
|
||||||
$byTanggalSantri = [];
|
|
||||||
$santriList = []; // untuk urutan santri konsisten
|
|
||||||
|
|
||||||
foreach ($hasilEnriched as $h) {
|
|
||||||
$tgl = $h['tanggal'];
|
|
||||||
$key = $h['id_santri'] ?? ('__'.$h['id_mesin']);
|
|
||||||
$byTanggalSantri[$tgl][$key] = $h;
|
|
||||||
|
|
||||||
if (!isset($santriList[$key])) {
|
|
||||||
$santriList[$key] = [
|
|
||||||
'nama' => $h['nama_web'] ?? $h['nama_mesin'],
|
|
||||||
'kelas' => $h['kelas'] ?? '-',
|
|
||||||
'status' => $h['match_status'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ksort($byTanggalSantri);
|
|
||||||
|
|
||||||
// ── 3. Statistik ─────────────────────────────────────────────────────────────
|
|
||||||
$allRows = collect($hasilEnriched)->flatMap(fn($h) => $h['rows']);
|
|
||||||
$totalKonflik = $allRows->where('is_conflict', true)->count();
|
|
||||||
$hadir = $allRows->where('status_final','Hadir')->count();
|
|
||||||
$terlambat = $allRows->where('status_final','Terlambat')->count();
|
|
||||||
$alpa = $allRows->where('status_final','Alpa')->count();
|
|
||||||
$notMapped = collect($hasilEnriched)->where('match_status','NOT_MAPPED')->count();
|
|
||||||
?>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
/* Sticky top bar */
|
|
||||||
.top-bar {
|
|
||||||
position: sticky; top: 0; z-index: 50;
|
|
||||||
background: #0F172A; color: #F1F5F9;
|
|
||||||
padding: 8px 16px; display: flex; align-items: center;
|
|
||||||
gap: 10px; flex-wrap: wrap; box-shadow: 0 2px 8px rgba(0,0,0,.3);
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
.chip {
|
|
||||||
border-radius: 8px; padding: 4px 10px;
|
|
||||||
text-align: center; min-width: 56px;
|
|
||||||
font-size: 11px; line-height: 1.3;
|
|
||||||
}
|
|
||||||
.chip .n { font-size: 17px; font-weight: 700; display: block }
|
|
||||||
.btn-act {
|
|
||||||
border: none; border-radius: 6px; padding: 6px 12px;
|
|
||||||
cursor: pointer; font-weight: 600; font-size: 12px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.btn-save {
|
|
||||||
border: none; border-radius: 8px; padding: 8px 20px;
|
|
||||||
cursor: pointer; font-weight: 700; font-size: 13px;
|
|
||||||
color: #fff; white-space: nowrap; transition: background .2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Matrix table */
|
|
||||||
.wrap { overflow-x: auto }
|
|
||||||
.mx { border-collapse: collapse; font-size: 12px; width: 100% }
|
|
||||||
.mx th, .mx td {
|
|
||||||
border: 1px solid #E5E7EB; padding: 0;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
/* Sticky kolom tanggal + nama */
|
|
||||||
.col-tgl {
|
|
||||||
position: sticky; left: 0; z-index: 4;
|
|
||||||
background: #F8FAFC; min-width: 90px;
|
|
||||||
border-right: 2px solid #CBD5E1;
|
|
||||||
padding: 6px 10px; font-size: 11px;
|
|
||||||
}
|
|
||||||
.col-nama {
|
|
||||||
position: sticky; left: 90px; z-index: 4;
|
|
||||||
background: #F8FAFC; min-width: 130px;
|
|
||||||
border-right: 2px solid #CBD5E1;
|
|
||||||
padding: 6px 10px;
|
|
||||||
}
|
|
||||||
/* Header kegiatan (rotate) */
|
|
||||||
.th-wrap {
|
|
||||||
writing-mode: vertical-rl;
|
|
||||||
transform: rotate(180deg);
|
|
||||||
display: flex; align-items: center; justify-content: flex-end;
|
|
||||||
gap: 2px; height: 80px; padding: 5px 6px;
|
|
||||||
}
|
|
||||||
/* Status pill */
|
|
||||||
.pill {
|
|
||||||
display: inline-block; border-radius: 8px;
|
|
||||||
padding: 2px 6px; font-size: 10px; font-weight: 700;
|
|
||||||
}
|
|
||||||
/* Konflik cell */
|
|
||||||
.conf-cell { background: #FFF5F5 !important; border: 2px solid #FCA5A5 !important }
|
|
||||||
.conf-wrap { display: flex; flex-direction: column }
|
|
||||||
.conf-opt {
|
|
||||||
padding: 4px 8px; cursor: pointer;
|
|
||||||
font-size: 11px; display: flex; align-items: center; gap: 4px;
|
|
||||||
border-bottom: 1px solid #F1F5F9; transition: background .12s;
|
|
||||||
}
|
|
||||||
.conf-opt:last-child { border-bottom: none }
|
|
||||||
.conf-opt:hover { background: #F8FAFC }
|
|
||||||
.sel-m { background: #DCFCE7 !important }
|
|
||||||
.sel-e { background: #DBEAFE !important }
|
|
||||||
/* Date separator row */
|
|
||||||
.date-sep td {
|
|
||||||
background: #1E293B; color: #94A3B8; font-weight: 700;
|
|
||||||
font-size: 11px; padding: 5px 12px; border-bottom: 2px solid #334155;
|
|
||||||
}
|
|
||||||
/* Alternating santri rows */
|
|
||||||
.row-alt { background: #FAFAFA }
|
|
||||||
/* Sticky header */
|
|
||||||
.th-sticky {
|
|
||||||
position: sticky; top: 52px; z-index: 6;
|
|
||||||
background: #1E293B;
|
|
||||||
}
|
|
||||||
.th-tgl { position: sticky; left: 0; z-index: 8 }
|
|
||||||
.th-nama { position: sticky; left: 90px; z-index: 8 }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<form action="<?php echo e(route('admin.mesin.import.store')); ?>" method="POST" id="frm">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<input type="hidden" name="conflict_strategy" value="manual" id="stratInput">
|
|
||||||
|
|
||||||
|
|
||||||
<?php if(session('error')): ?>
|
|
||||||
<div style="background:#FEE2E2;border:1px solid #FCA5A5;border-left:4px solid #DC2626;
|
|
||||||
padding:12px 16px;font-size:13px;color:#991B1B">
|
|
||||||
<strong>❌ Error:</strong> <?php echo e(session('error')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="top-bar">
|
|
||||||
<div style="flex:1;min-width:160px">
|
|
||||||
<div style="color:#64748B;font-size:10px;text-transform:uppercase;letter-spacing:1px">
|
|
||||||
Preview Import
|
|
||||||
</div>
|
|
||||||
<div style="font-weight:700;font-size:14px;margin-top:1px">
|
|
||||||
<?php echo e(count($santriList)); ?> santri
|
|
||||||
<?php if($totalKonflik > 0): ?>
|
|
||||||
· <span style="color:#FCA5A5" id="lbl">
|
|
||||||
⚡ <span id="cnt"><?php echo e($totalKonflik); ?></span> konflik perlu diselesaikan
|
|
||||||
</span>
|
|
||||||
<?php else: ?>
|
|
||||||
· <span style="color:#86EFAC">✅ Siap disimpan</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="chip" style="background:#DCFCE7;color:#166534">
|
|
||||||
<span class="n"><?php echo e($hadir); ?></span>Hadir
|
|
||||||
</div>
|
|
||||||
<div class="chip" style="background:#FEF9C3;color:#92400E">
|
|
||||||
<span class="n"><?php echo e($terlambat); ?></span>Telat
|
|
||||||
</div>
|
|
||||||
<div class="chip" style="background:#FEE2E2;color:#991B1B">
|
|
||||||
<span class="n"><?php echo e($alpa); ?></span>Alpa
|
|
||||||
</div>
|
|
||||||
<?php if($totalKonflik > 0): ?>
|
|
||||||
<div class="chip" style="background:#FEE2E2;color:#DC2626">
|
|
||||||
<span class="n" id="chip"><?php echo e($totalKonflik); ?></span>Konflik
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($notMapped > 0): ?>
|
|
||||||
<div class="chip" style="background:#FFF3E8;color:#C05621">
|
|
||||||
<span class="n"><?php echo e($notMapped); ?></span>Blm Map
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($totalKonflik > 0): ?>
|
|
||||||
<div style="display:flex;flex-direction:column;gap:3px;font-size:11px;color:#94A3B8">
|
|
||||||
Konflik:
|
|
||||||
</div>
|
|
||||||
<button type="button" class="btn-act" style="background:#DCFCE7;color:#166534"
|
|
||||||
onclick="resolveAll('m');document.getElementById('stratInput').value='mesin'">👆 Mesin</button>
|
|
||||||
<button type="button" class="btn-act" style="background:#DBEAFE;color:#1D4ED8"
|
|
||||||
onclick="resolveAll('e');document.getElementById('stratInput').value='exist'">🔒 Lama</button>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<button type="button" class="btn-save" id="saveBtn"
|
|
||||||
style="background:<?php echo e($totalKonflik > 0 ? '#64748B' : 'linear-gradient(135deg,#166534,#22C55E)'); ?>"
|
|
||||||
<?php echo e($totalKonflik > 0 ? 'disabled' : ''); ?>
|
|
||||||
|
|
||||||
onclick="submitForm()">
|
|
||||||
<?php if($totalKonflik > 0): ?> ⏳ Selesaikan konflik dulu
|
|
||||||
<?php else: ?> 💾 Simpan ke Database <?php endif; ?>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<a href="<?php echo e(route('admin.mesin.import.index')); ?>"
|
|
||||||
class="btn-act" style="background:#374151;color:#F1F5F9;text-decoration:none">
|
|
||||||
← Kembali
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;gap:8px;flex-wrap:wrap;padding:8px 16px;
|
|
||||||
background:#F8FAFC;border-bottom:1px solid #E5E7EB;font-size:11px">
|
|
||||||
<span style="color:#6B7280;font-weight:600">Status:</span>
|
|
||||||
<?php $__currentLoopData = $statusStyle; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $st => $s): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<span class="pill" style="background:<?php echo e($s['bg']); ?>;color:<?php echo e($s['c']); ?>">
|
|
||||||
<?php echo e($s['ic']); ?> <?php echo e($st); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<span style="color:#9CA3AF;margin-left:4px">| — = tidak ada data</span>
|
|
||||||
<span style="border:2px solid #FCA5A5;border-radius:4px;padding:1px 6px;color:#991B1B">
|
|
||||||
⚡ Konflik
|
|
||||||
</span>
|
|
||||||
<span style="color:#9CA3AF">= ada data berbeda, pilih salah satu</span>
|
|
||||||
<?php if($notMapped > 0): ?>
|
|
||||||
<span style="margin-left:auto">
|
|
||||||
⚠️ <?php echo e($notMapped); ?> belum dipetakan →
|
|
||||||
<a href="<?php echo e(route('admin.mesin.mapping-santri.index')); ?>" target="_blank">
|
|
||||||
Lengkapi Mapping
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="wrap">
|
|
||||||
<table class="mx">
|
|
||||||
|
|
||||||
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
|
|
||||||
<th class="th-sticky th-tgl"
|
|
||||||
style="min-width:90px;padding:8px 10px;text-align:left;
|
|
||||||
color:#94A3B8;font-size:10px;border-right:2px solid #334155">
|
|
||||||
Tanggal
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<th class="th-sticky th-nama"
|
|
||||||
style="min-width:130px;padding:8px 10px;text-align:left;
|
|
||||||
color:#94A3B8;font-size:10px;border-right:2px solid #334155">
|
|
||||||
Santri
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<?php $__currentLoopData = $kegiatanCols; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kg): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<th class="th-sticky" style="min-width:70px;vertical-align:bottom">
|
|
||||||
<div class="th-wrap">
|
|
||||||
<span style="color:#F1F5F9;font-size:10px;font-weight:600">
|
|
||||||
<?php echo e($kg['nama']); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<span style="color:#64748B;font-size:9px">
|
|
||||||
<?php echo e($kg['waktu_mulai']); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $byTanggalSantri; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $tgl => $santriRows): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$tglCarbon = Carbon::parse($tgl);
|
|
||||||
$tglLabel = $tglCarbon->locale('id')->isoFormat('ddd, D MMM');
|
|
||||||
$isOdd = ($loop->index % 2 === 1);
|
|
||||||
?>
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__currentLoopData = $santriList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $key => $info): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$data = $santriRows[$key] ?? null;
|
|
||||||
$rowBg = ($loop->index % 2 === 0) ? 'white' : '#FAFAFA';
|
|
||||||
if ($data && $data['match_status'] === 'NOT_MAPPED') $rowBg = '#FFF5F5';
|
|
||||||
?>
|
|
||||||
<tr style="background:<?php echo e($rowBg); ?>">
|
|
||||||
|
|
||||||
|
|
||||||
<td class="col-tgl" style="background:<?php echo e($rowBg); ?>">
|
|
||||||
<?php if($loop->first): ?>
|
|
||||||
<strong style="color:#1E293B"><?php echo e($tglLabel); ?></strong>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
|
|
||||||
<td class="col-nama" style="background:<?php echo e($rowBg); ?>">
|
|
||||||
<?php if($info['status'] === 'NOT_MAPPED'): ?>
|
|
||||||
<div style="font-size:10px;font-weight:700;color:#DC2626">⚠ BELUM MAP</div>
|
|
||||||
<div style="font-size:10px;color:#9CA3AF"><?php echo e($info['nama']); ?></div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div style="font-weight:600;color:#1F2937;font-size:12px">
|
|
||||||
<?php echo e($info['nama']); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div style="font-size:10px;color:#9CA3AF"><?php echo e($info['kelas']); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__currentLoopData = $kegiatanCols; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kg): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$row = $data
|
|
||||||
? collect($data['rows'])->firstWhere('kegiatan_id', $kg['kegiatan_id'])
|
|
||||||
: null;
|
|
||||||
$sf = $row['status_final'] ?? null;
|
|
||||||
$st = $sf ? ($statusStyle[$sf] ?? null) : null;
|
|
||||||
$isConf = $row['is_conflict'] ?? false;
|
|
||||||
$key2 = "{$kg['kegiatan_id']}_{$data['id_santri']}_{$tgl}";
|
|
||||||
?>
|
|
||||||
|
|
||||||
<td style="padding:0;text-align:center;vertical-align:middle;min-width:70px"
|
|
||||||
class="<?php echo e($isConf ? 'conf-cell' : ''); ?>">
|
|
||||||
|
|
||||||
<?php if(!$data || !$row || $sf === null): ?>
|
|
||||||
|
|
||||||
<span style="color:#D1D5DB">—</span>
|
|
||||||
|
|
||||||
<?php elseif($isConf): ?>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$ex = $row['existing'];
|
|
||||||
$exSt = $statusStyle[$ex['status']] ?? ['bg'=>'#F9FAFB','c'=>'#6B7280','ic'=>'?'];
|
|
||||||
?>
|
|
||||||
<div class="conf-wrap" data-key="<?php echo e($key2); ?>">
|
|
||||||
|
|
||||||
<div class="conf-opt" data-ch="m" onclick="pick('<?php echo e($key2); ?>','m',this)">
|
|
||||||
<input type="radio" name="conflict_choices[<?php echo e($key2); ?>]"
|
|
||||||
value="mesin" id="cm_<?php echo e($key2); ?>" style="display:none">
|
|
||||||
<span>👆</span>
|
|
||||||
<div>
|
|
||||||
<span class="pill" style="background:<?php echo e($st['bg']); ?>;color:<?php echo e($st['c']); ?>">
|
|
||||||
<?php echo e($st['ic']); ?> <?php echo e($sf); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<div style="font-size:9px;color:#6B7280">
|
|
||||||
Mesin·<?php echo e($row['jam_scan'] ?? '-'); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="conf-opt" data-ch="e" onclick="pick('<?php echo e($key2); ?>','e',this)">
|
|
||||||
<input type="radio" name="conflict_choices[<?php echo e($key2); ?>]"
|
|
||||||
value="exist" id="ce_<?php echo e($key2); ?>" style="display:none">
|
|
||||||
<span>🔒</span>
|
|
||||||
<div>
|
|
||||||
<span class="pill" style="background:<?php echo e($exSt['bg']); ?>;color:<?php echo e($exSt['c']); ?>">
|
|
||||||
<?php echo e($exSt['ic']); ?> <?php echo e($ex['status']); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<div style="font-size:9px;color:#6B7280">
|
|
||||||
<?php echo e($ex['metode'] ?? 'Manual'); ?>
|
|
||||||
|
|
||||||
<?php if($ex['waktu']): ?> ·<?php echo e(substr($ex['waktu'],0,5)); ?><?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="background:#FEE2E2;padding:1px 4px;font-size:9px;
|
|
||||||
color:#DC2626;font-weight:700;text-align:center">
|
|
||||||
⚡ pilih
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
|
|
||||||
<div style="padding:5px 3px">
|
|
||||||
<span class="pill" style="background:<?php echo e($st['bg']); ?>;color:<?php echo e($st['c']); ?>">
|
|
||||||
<?php echo e($st['ic']); ?> <?php echo e($sf); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<?php if($row['jam_scan']): ?>
|
|
||||||
<div style="font-size:9px;color:#9CA3AF;margin-top:1px">
|
|
||||||
<?php echo e($row['jam_scan']); ?>
|
|
||||||
|
|
||||||
<?php if(($row['selisih_menit'] ?? 0) > 0): ?>
|
|
||||||
<span style="color:#F59E0B">+<?php echo e($row['selisih_menit']); ?>m</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
|
|
||||||
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<th style="background:#1E293B;color:#94A3B8;font-size:10px;
|
|
||||||
padding:6px 10px;border-right:2px solid #334155;
|
|
||||||
position:sticky;left:0">Tanggal</th>
|
|
||||||
<th style="background:#1E293B;color:#94A3B8;font-size:10px;
|
|
||||||
padding:6px 10px;border-right:2px solid #334155;
|
|
||||||
position:sticky;left:90px">Santri</th>
|
|
||||||
<?php $__currentLoopData = $kegiatanCols; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kg): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<th style="background:#1E293B;color:#94A3B8;font-size:9px;padding:4px 6px">
|
|
||||||
<?php echo e($kg['nama']); ?>
|
|
||||||
|
|
||||||
</th>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="padding:8px 16px;background:#F8FAFC;border-top:1px solid #E5E7EB;
|
|
||||||
font-size:11px;color:#6B7280;display:flex;gap:12px;flex-wrap:wrap">
|
|
||||||
<span>📊 <?php echo e(count($santriList)); ?> santri · <?php echo e(count($byTanggalSantri)); ?> hari</span>
|
|
||||||
<span>✅ <?php echo e($hadir); ?> Hadir</span>
|
|
||||||
<span>⏰ <?php echo e($terlambat); ?> Terlambat</span>
|
|
||||||
<span>❌ <?php echo e($alpa); ?> Alpa</span>
|
|
||||||
<?php if($totalKonflik > 0): ?>
|
|
||||||
<span style="color:#DC2626">⚡ <?php echo e($totalKonflik); ?> Konflik</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<span style="margin-left:auto">
|
|
||||||
Toleransi: <?php echo e($tolSebelum); ?>m sebelum / <?php echo e($tolSesudah); ?>m sesudah
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const totalK = <?php echo e($totalKonflik); ?>;
|
|
||||||
const done = new Set();
|
|
||||||
|
|
||||||
function pick(key, ch, el) {
|
|
||||||
const wrap = el.closest('.conf-wrap');
|
|
||||||
wrap.querySelectorAll('.conf-opt').forEach(o => {
|
|
||||||
o.classList.remove('sel-m','sel-e');
|
|
||||||
});
|
|
||||||
el.classList.add(ch === 'm' ? 'sel-m' : 'sel-e');
|
|
||||||
const radio = document.getElementById((ch==='m'?'cm_':'ce_') + key);
|
|
||||||
if (radio) radio.checked = true;
|
|
||||||
done.add(key);
|
|
||||||
updateUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveAll(ch) {
|
|
||||||
document.querySelectorAll('.conf-wrap').forEach(wrap => {
|
|
||||||
const key = wrap.dataset.key;
|
|
||||||
const opt = wrap.querySelector('[data-ch="'+ch+'"]');
|
|
||||||
if (opt) pick(key, ch, opt);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function submitForm() {
|
|
||||||
const btn = document.getElementById('saveBtn');
|
|
||||||
btn.disabled = true;
|
|
||||||
btn.style.background = '#64748B';
|
|
||||||
btn.textContent = '⏳ Menyimpan...';
|
|
||||||
document.getElementById('frm').submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateUI() {
|
|
||||||
const rem = totalK - done.size;
|
|
||||||
const btn = document.getElementById('saveBtn');
|
|
||||||
const lbl = document.getElementById('lbl');
|
|
||||||
const chip = document.getElementById('chip');
|
|
||||||
if (rem <= 0) {
|
|
||||||
btn.disabled = false;
|
|
||||||
btn.style.background = 'linear-gradient(135deg,#166534,#22C55E)';
|
|
||||||
btn.textContent = '💾 Simpan ke Database';
|
|
||||||
if (lbl) lbl.innerHTML = '<span style="color:#86EFAC">✅ Semua konflik selesai</span>';
|
|
||||||
if (chip) chip.textContent = '0';
|
|
||||||
} else {
|
|
||||||
btn.disabled = true;
|
|
||||||
btn.style.background = '#64748B';
|
|
||||||
btn.textContent = '⏳ Selesaikan ' + rem + ' konflik';
|
|
||||||
if (lbl) lbl.innerHTML = '<span style="color:#FCA5A5">⚡ <span id="cnt">'+rem+'</span> konflik</span>';
|
|
||||||
if (chip) chip.textContent = rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</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/mesin/import/preview.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,183 +0,0 @@
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-history"></i> Riwayat Capaian Santri</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<div style="display: flex; align-items: center; gap: 20px;">
|
|
||||||
<div class="icon-wrapper icon-wrapper-lg">
|
|
||||||
<i class="fas fa-user-graduate"></i>
|
|
||||||
</div>
|
|
||||||
<div style="flex: 1;">
|
|
||||||
<h3 style="margin: 0 0 5px 0;"><?php echo e($santri->nama_lengkap); ?></h3>
|
|
||||||
<p style="margin: 0; color: var(--text-light);">
|
|
||||||
<strong>NIS:</strong> <?php echo e($santri->nis); ?> |
|
|
||||||
<strong>Kelas:</strong> <span class="badge badge-secondary"><?php echo e($santri->kelas); ?></span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div style="text-align: right; display: flex; gap: 10px; justify-content: flex-end;">
|
|
||||||
<a href="<?php echo e(route('admin.capaian.index')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali ke Data Capaian
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.santri.show', $santri)); ?>" class="btn btn-info">
|
|
||||||
<i class="fas fa-user"></i> Profil Santri
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</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>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-primary">
|
|
||||||
<h3>Al-Qur'an</h3>
|
|
||||||
<div class="card-value-small"><?php echo e(number_format($statistikKategori['Al-Qur\'an'] ?? 0, 1)); ?>%</div>
|
|
||||||
<p class="text-muted">Progress kategori</p>
|
|
||||||
<i class="fas fa-book-quran card-icon"></i>
|
|
||||||
</div>
|
|
||||||
<div class="card card-warning">
|
|
||||||
<h3>Hadist</h3>
|
|
||||||
<div class="card-value-small"><?php echo e(number_format($statistikKategori['Hadist'] ?? 0, 1)); ?>%</div>
|
|
||||||
<p class="text-muted">Progress kategori</p>
|
|
||||||
<i class="fas fa-scroll card-icon"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.capaian.riwayat-santri', $santri->id_santri)); ?>" class="filter-form-inline">
|
|
||||||
<select name="id_semester" class="form-control" style="width: 250px;">
|
|
||||||
<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(request('id_semester') == $semester->id_semester ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($semester->nama_semester); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<input type="text" name="search" class="form-control" placeholder="Cari nama materi..."
|
|
||||||
value="<?php echo e(request('search')); ?>" style="width: 300px;">
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
<i class="fas fa-search"></i> Filter
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<?php if(request()->filled('id_semester') || request()->filled('search')): ?>
|
|
||||||
<a href="<?php echo e(route('admin.capaian.riwayat-santri', $santri->id_santri)); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-redo"></i> Reset
|
|
||||||
</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<a href="<?php echo e(route('admin.capaian.create', ['id_santri' => $santri->id_santri])); ?>" class="btn btn-success" style="margin-left: auto;">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Capaian
|
|
||||||
</a>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<?php if($capaians->count() > 0): ?>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$groupedCapaians = $capaians->groupBy(function($item) {
|
|
||||||
return $item->materi->kategori;
|
|
||||||
});
|
|
||||||
?>
|
|
||||||
|
|
||||||
<?php $__currentLoopData = ['Al-Qur\'an', 'Hadist', 'Materi Tambahan']; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kategori): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php if(isset($groupedCapaians[$kategori]) && $groupedCapaians[$kategori]->count() > 0): ?>
|
|
||||||
<div style="margin-bottom: 22px;">
|
|
||||||
<h4 style="color: var(--primary-dark); margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid var(--primary-light);">
|
|
||||||
<i class="fas fa-<?php echo e($kategori == 'Al-Qur\'an' ? 'book-quran' : ($kategori == 'Hadist' ? 'scroll' : 'book')); ?>"></i>
|
|
||||||
Kategori: <?php echo e($kategori); ?>
|
|
||||||
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 5%;">No</th>
|
|
||||||
<th style="width: 25%;">Materi</th>
|
|
||||||
<th style="width: 15%;">Semester</th>
|
|
||||||
<th style="width: 15%;">Halaman</th>
|
|
||||||
<th style="width: 15%;">Progress</th>
|
|
||||||
<th style="width: 15%;">Tanggal Input</th>
|
|
||||||
<th class="text-center" style="width: 10%;">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $groupedCapaians[$kategori]; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $capaian): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($index + 1); ?></td>
|
|
||||||
<td>
|
|
||||||
<strong><?php echo e($capaian->materi->nama_kitab); ?></strong><br>
|
|
||||||
<small class="text-muted">Total: <?php echo e($capaian->materi->total_halaman); ?> hal</small>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<small><?php echo e($capaian->semester->nama_semester); ?></small>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<span class="badge badge-info">
|
|
||||||
<?php echo e($capaian->jumlah_halaman_selesai); ?> / <?php echo e($capaian->materi->total_halaman); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php echo $capaian->persentase_badge; ?>
|
|
||||||
|
|
||||||
<div class="progress-bar" style="margin-top: 5px; height: 8px;">
|
|
||||||
<div class="progress-fill" style="width: <?php echo e($capaian->persentase); ?>%; background: linear-gradient(90deg, var(--primary-color), var(--success-color));"></div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td><?php echo e($capaian->tanggal_input->format('d/m/Y')); ?></td>
|
|
||||||
<td class="text-center">
|
|
||||||
<div class="btn-group">
|
|
||||||
<a href="<?php echo e(route('admin.capaian.show', $capaian)); ?>"
|
|
||||||
class="btn btn-sm btn-info" title="Detail">
|
|
||||||
<i class="fas fa-eye"></i>
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.capaian.edit', $capaian)); ?>"
|
|
||||||
class="btn btn-sm btn-warning" title="Edit">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="margin-top: 14px;">
|
|
||||||
<?php echo e($capaians->links()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-clipboard-list"></i>
|
|
||||||
<h3>Belum Ada Capaian</h3>
|
|
||||||
<p>Santri ini belum memiliki data capaian.</p>
|
|
||||||
<a href="<?php echo e(route('admin.capaian.create', ['id_santri' => $santri->id_santri])); ?>" class="btn btn-primary">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Capaian 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/capaian/riwayat-santri.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,264 +0,0 @@
|
||||||
<?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 style="background: #fff; border-radius: 12px; padding: 18px 22px; margin-bottom: 16px; box-shadow: 0 2px 12px rgba(0,0,0,0.06); border-left: 4px solid #2563eb;">
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 12px;">
|
|
||||||
<div>
|
|
||||||
<h3 style="margin: 0; font-size: 1rem; color: #1a2332;">
|
|
||||||
<i class="fas fa-users" style="color: #2563eb;"></i> Total Semua Santri: <strong><?php echo e($totalSantriEligible); ?></strong>
|
|
||||||
</h3>
|
|
||||||
<p style="margin: 4px 0 0; font-size: 0.84rem; color: #6b7280;">
|
|
||||||
Sudah absen: <strong style="color: #059669;"><?php echo e($santriSudahAbsen); ?></strong>
|
|
||||||
·
|
|
||||||
Belum absen: <strong style="color: <?php echo e($belumAbsen > 0 ? '#dc2626' : '#059669'); ?>;"><?php echo e($belumAbsen); ?></strong>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div style="text-align: right;">
|
|
||||||
<div style="font-size: 1.6rem; font-weight: 800; color: <?php echo e($persenHadir >= 85 ? '#059669' : ($persenHadir >= 70 ? '#d97706' : '#dc2626')); ?>;">
|
|
||||||
<?php echo e($persenHadir); ?>%
|
|
||||||
</div>
|
|
||||||
<div style="font-size: 0.78rem; color: #6b7280;">Kehadiran</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="height: 28px; background: #f3f4f6; border-radius: 14px; overflow: hidden; display: flex;">
|
|
||||||
<?php
|
|
||||||
$pctHadir = $totalSantriEligible > 0 ? round(($stats['Hadir'] ?? 0) / $totalSantriEligible * 100, 1) : 0;
|
|
||||||
$pctTerlambat = $totalSantriEligible > 0 ? round(($stats['Terlambat'] ?? 0) / $totalSantriEligible * 100, 1) : 0;
|
|
||||||
$pctIzin = $totalSantriEligible > 0 ? round(($stats['Izin'] ?? 0) / $totalSantriEligible * 100, 1) : 0;
|
|
||||||
$pctSakit = $totalSantriEligible > 0 ? round(($stats['Sakit'] ?? 0) / $totalSantriEligible * 100, 1) : 0;
|
|
||||||
$pctAlpa = $totalSantriEligible > 0 ? round(($stats['Alpa'] ?? 0) / $totalSantriEligible * 100, 1) : 0;
|
|
||||||
$pctBelum = $totalSantriEligible > 0 ? round($belumAbsen / $totalSantriEligible * 100, 1) : 0;
|
|
||||||
?>
|
|
||||||
<?php if($pctHadir > 0): ?>
|
|
||||||
<div style="width: <?php echo e($pctHadir); ?>%; background: #22c55e; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.73rem; font-weight: 700;" title="Hadir: <?php echo e($stats['Hadir'] ?? 0); ?>">
|
|
||||||
<?php echo e(($stats['Hadir'] ?? 0) > 0 ? ($stats['Hadir'] ?? 0) : ''); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($pctTerlambat > 0): ?>
|
|
||||||
<div style="width: <?php echo e($pctTerlambat); ?>%; background: #FF9800; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.73rem; font-weight: 700;" title="Terlambat: <?php echo e($stats['Terlambat'] ?? 0); ?>">
|
|
||||||
<?php echo e(($stats['Terlambat'] ?? 0) > 0 ? ($stats['Terlambat'] ?? 0) : ''); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($pctIzin > 0): ?>
|
|
||||||
<div style="width: <?php echo e($pctIzin); ?>%; background: #f59e0b; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.73rem; font-weight: 700;" title="Izin: <?php echo e($stats['Izin'] ?? 0); ?>">
|
|
||||||
<?php echo e(($stats['Izin'] ?? 0) > 0 ? ($stats['Izin'] ?? 0) : ''); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($pctSakit > 0): ?>
|
|
||||||
<div style="width: <?php echo e($pctSakit); ?>%; background: #3b82f6; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.73rem; font-weight: 700;" title="Sakit: <?php echo e($stats['Sakit'] ?? 0); ?>">
|
|
||||||
<?php echo e(($stats['Sakit'] ?? 0) > 0 ? ($stats['Sakit'] ?? 0) : ''); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($pctAlpa > 0): ?>
|
|
||||||
<div style="width: <?php echo e($pctAlpa); ?>%; background: #ef4444; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.73rem; font-weight: 700;" title="Alpa: <?php echo e($stats['Alpa'] ?? 0); ?>">
|
|
||||||
<?php echo e(($stats['Alpa'] ?? 0) > 0 ? ($stats['Alpa'] ?? 0) : ''); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($pctBelum > 0): ?>
|
|
||||||
<div style="width: <?php echo e($pctBelum); ?>%; background: #d1d5db; display: flex; align-items: center; justify-content: center; color: #6b7280; font-size: 0.73rem; font-weight: 700;" title="Belum Absen: <?php echo e($belumAbsen); ?>">
|
|
||||||
<?php echo e($belumAbsen > 0 ? $belumAbsen : ''); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; gap: 14px; flex-wrap: wrap; margin-top: 8px; font-size: 0.75rem; color: #6b7280;">
|
|
||||||
<span><span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#22c55e;margin-right:3px;"></span> Hadir</span>
|
|
||||||
<span><span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#FF9800;margin-right:3px;"></span> Terlambat</span>
|
|
||||||
<span><span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#f59e0b;margin-right:3px;"></span> Izin</span>
|
|
||||||
<span><span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#3b82f6;margin-right:3px;"></span> Sakit</span>
|
|
||||||
<span><span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#ef4444;margin-right:3px;"></span> Alpa</span>
|
|
||||||
<span><span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#d1d5db;margin-right:3px;"></span> Belum Absen</span>
|
|
||||||
</div>
|
|
||||||
</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" style="border-top: 3px solid #FF9800;">
|
|
||||||
<h3>Terlambat</h3>
|
|
||||||
<div class="card-value"><?php echo e($stats['Terlambat'] ?? 0); ?></div>
|
|
||||||
<i class="fas fa-clock card-icon" style="color: #FF9800;"></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 class="card" style="border-top: 3px solid #9ca3af;">
|
|
||||||
<h3>Belum Absen</h3>
|
|
||||||
<div class="card-value" style="color: <?php echo e($belumAbsen > 0 ? '#dc2626' : '#6b7280'); ?>;"><?php echo e($belumAbsen); ?></div>
|
|
||||||
<i class="fas fa-hourglass-half card-icon" style="color: #9ca3af;"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<div style="margin-bottom: 14px;">
|
|
||||||
<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">
|
|
||||||
|
|
||||||
<select name="kelas_id" class="form-control" style="max-width: 200px;">
|
|
||||||
<option value="">Semua Kelas</option>
|
|
||||||
<?php $__currentLoopData = $kelasFilterList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($kelas->id); ?>" <?php echo e(request('kelas_id') == $kelas->id ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($kelas->nama_kelas); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
<i class="fas fa-filter"></i> Filter
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<?php if(request()->hasAny(['tanggal', 'bulan', 'kelas_id'])): ?>
|
|
||||||
<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.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): ?>
|
|
||||||
<?php $__currentLoopData = $absensiPerKelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $namaKelas => $kelasAbsensis): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div class="content-box" style="margin-bottom: 18px;">
|
|
||||||
<h4 style="margin: 0 0 12px; color: var(--primary-color);">
|
|
||||||
<i class="fas fa-school"></i> Kelas: <?php echo e($namaKelas); ?>
|
|
||||||
|
|
||||||
<span class="badge badge-secondary" style="font-size: 0.8rem; margin-left: 6px;">
|
|
||||||
<?php echo e($kelasAbsensis->count()); ?> data
|
|
||||||
</span>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<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: 120px; text-align: center;">Status</th>
|
|
||||||
<th style="width: 100px;">Metode</th>
|
|
||||||
<th style="width: 100px;">Waktu</th>
|
|
||||||
<th style="width: 120px; text-align: center;">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $kelasAbsensis; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $absensi): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($index + 1); ?></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 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 elseif($absensi->metode_absen == 'Import_Mesin'): ?>
|
|
||||||
<span class="badge" style="background: #7c3aed; color: white;"><i class="fas fa-desktop"></i> Mesin</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>
|
|
||||||
<td class="text-center">
|
|
||||||
<div style="display: flex; gap: 4px; justify-content: center;">
|
|
||||||
<a href="<?php echo e(route('admin.absensi-kegiatan.edit', $absensi->id)); ?>" class="btn btn-sm btn-warning" title="Edit">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
<form action="<?php echo e(route('admin.absensi-kegiatan.hapus', $absensi->id)); ?>" method="POST" style="display: inline;" onsubmit="return confirm('Yakin hapus absensi <?php echo e($absensi->santri->nama_lengkap); ?>?');">
|
|
||||||
<?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>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?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; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($santriBelumAbsen->count() > 0): ?>
|
|
||||||
<div class="content-box" style="margin-top: 18px; border-left: 4px solid #f59e0b;">
|
|
||||||
<h4 style="margin: 0 0 12px; color: #d97706;">
|
|
||||||
<i class="fas fa-exclamation-triangle"></i> Santri Belum Absen (<?php echo e($santriBelumAbsen->count()); ?> orang)
|
|
||||||
<?php if(request('tanggal')): ?>
|
|
||||||
<span style="font-size: 0.8rem; font-weight: 400; color: #6b7280; margin-left: 6px;">
|
|
||||||
Tanggal: <?php echo e(\Carbon\Carbon::parse(request('tanggal'))->format('d/m/Y')); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<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: 150px;">Kelas</th>
|
|
||||||
<th style="width: 120px; text-align: center;">Status</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $santriBelumAbsen; $__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><?php echo e(optional(optional($santri->kelasPrimary)->kelas)->nama_kelas ?? '-'); ?></td>
|
|
||||||
<td class="text-center">
|
|
||||||
<span class="badge" style="background: #fef3c7; color: #92400e; padding: 4px 10px; border-radius: 12px; font-size: 0.8rem;">
|
|
||||||
<i class="fas fa-hourglass-half"></i> Belum Absen
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</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**/ ?>
|
|
||||||
|
|
@ -1,194 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Master Pelanggaran'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-list-ul"></i> Kategori Pelanggaran</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; ?>
|
|
||||||
|
|
||||||
<!-- Filter -->
|
|
||||||
<div class="content-box" style="margin-bottom: 14px;">
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.kategori-pelanggaran.index')); ?>">
|
|
||||||
<div style="display: grid; grid-template-columns: 2fr 1fr auto; gap: 11px; align-items: end;">
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<label for="id_klasifikasi">
|
|
||||||
<i class="fas fa-filter form-icon"></i>
|
|
||||||
Filter Klasifikasi
|
|
||||||
</label>
|
|
||||||
<select name="id_klasifikasi" id="id_klasifikasi" class="form-control">
|
|
||||||
<option value="">-- Semua Klasifikasi --</option>
|
|
||||||
<?php $__currentLoopData = $klasifikasiList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kl): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($kl->id_klasifikasi); ?>"
|
|
||||||
<?php echo e(request('id_klasifikasi') == $kl->id_klasifikasi ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($kl->nama_klasifikasi); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<label for="is_active">
|
|
||||||
<i class="fas fa-toggle-on form-icon"></i>
|
|
||||||
Status
|
|
||||||
</label>
|
|
||||||
<select name="is_active" id="is_active" class="form-control">
|
|
||||||
<option value="">-- Semua Status --</option>
|
|
||||||
<option value="1" <?php echo e(request('is_active') == '1' ? 'selected' : ''); ?>>Aktif</option>
|
|
||||||
<option value="0" <?php echo e(request('is_active') == '0' ? 'selected' : ''); ?>>Nonaktif</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="btn-group" style="margin-bottom: 0;">
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
<i class="fas fa-search"></i> Filter
|
|
||||||
</button>
|
|
||||||
<a href="<?php echo e(route('admin.kategori-pelanggaran.index')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-redo"></i> Reset
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Tabel Data -->
|
|
||||||
<div class="content-box">
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px;">
|
|
||||||
<h3 style="margin: 0; color: var(--primary-color);">
|
|
||||||
<i class="fas fa-table"></i> Daftar Pelanggaran
|
|
||||||
</h3>
|
|
||||||
<div style="display: flex; gap: 10px;">
|
|
||||||
<a href="<?php echo e(route('admin.klasifikasi-pelanggaran.index')); ?>" class="btn btn-warning">
|
|
||||||
<i class="fas fa-tags"></i> Klasifikasi Pelanggaran
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.kategori-pelanggaran.create')); ?>" class="btn btn-primary">
|
|
||||||
<i class="fas fa-plus-circle"></i> Tambah Pelanggaran
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($data->isNotEmpty()): ?>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 50px;">No</th>
|
|
||||||
<th style="width: 100px;">ID</th>
|
|
||||||
<th style="width: 150px;">Klasifikasi</th>
|
|
||||||
<th>Nama Pelanggaran</th>
|
|
||||||
<th style="width: 80px; text-align: center;">Poin</th>
|
|
||||||
<th style="width: 100px; text-align: center;">Digunakan</th>
|
|
||||||
<th style="width: 100px; text-align: center;">Status</th>
|
|
||||||
<th style="width: 200px; text-align: center;">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $data; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($index + 1); ?></td>
|
|
||||||
<td><span class="badge badge-primary"><?php echo e($item->id_kategori); ?></span></td>
|
|
||||||
<td>
|
|
||||||
<?php if($item->klasifikasi): ?>
|
|
||||||
<span class="badge badge-info"><?php echo e($item->klasifikasi->nama_klasifikasi); ?></span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="badge badge-secondary">-</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<strong><?php echo e($item->nama_pelanggaran); ?></strong>
|
|
||||||
<?php if($item->kafaroh): ?>
|
|
||||||
<br><small style="color: var(--text-light);">
|
|
||||||
<i class="fas fa-hands"></i> Kafaroh: <?php echo e(Str::limit($item->kafaroh, 50)); ?>
|
|
||||||
|
|
||||||
</small>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<span class="badge badge-danger" style="font-size: 0.9em;">
|
|
||||||
<i class="fas fa-star"></i> <?php echo e($item->poin); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<span class="badge badge-secondary">
|
|
||||||
<?php echo e($item->riwayatPelanggaran->count()); ?>x
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<?php if($item->is_active): ?>
|
|
||||||
<span class="badge badge-success">Aktif</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="badge badge-secondary">Nonaktif</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<div style="display: flex; justify-content: center; gap: 8px;">
|
|
||||||
<a href="<?php echo e(route('admin.kategori-pelanggaran.show', $item)); ?>"
|
|
||||||
class="btn btn-sm btn-success"
|
|
||||||
title="Detail">
|
|
||||||
<i class="fas fa-eye"></i>
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.kategori-pelanggaran.edit', $item)); ?>"
|
|
||||||
class="btn btn-sm btn-warning"
|
|
||||||
title="Edit">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
<form action="<?php echo e(route('admin.kategori-pelanggaran.destroy', $item)); ?>"
|
|
||||||
method="POST"
|
|
||||||
style="display: inline;"
|
|
||||||
onsubmit="return confirm('Yakin ingin menghapus pelanggaran <?php echo e($item->nama_pelanggaran); ?>?');">
|
|
||||||
<?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>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-folder-open"></i>
|
|
||||||
<h3>Belum ada data pelanggaran</h3>
|
|
||||||
<p>Silakan tambah pelanggaran baru menggunakan tombol di atas.</p>
|
|
||||||
<a href="<?php echo e(route('admin.kategori-pelanggaran.create')); ?>" class="btn btn-primary">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Pelanggaran
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// Auto hide alerts after 5 seconds
|
|
||||||
setTimeout(function() {
|
|
||||||
const alerts = document.querySelectorAll('.alert');
|
|
||||||
alerts.forEach(alert => {
|
|
||||||
alert.style.transition = 'opacity 0.5s';
|
|
||||||
alert.style.opacity = '0';
|
|
||||||
setTimeout(() => alert.remove(), 500);
|
|
||||||
});
|
|
||||||
}, 5000);
|
|
||||||
</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/kategori_pelanggaran/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,465 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<style>
|
|
||||||
.page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; }
|
|
||||||
.page-header h2 { margin: 0; color: var(--primary-dark); font-size: 1.5rem; display: flex; align-items: center; gap: 10px; }
|
|
||||||
.btn-back { padding: 8px 16px; background: #6B7280; color: #fff; border: none; border-radius: 8px; font-size: 0.85rem; text-decoration: none; display: inline-flex; align-items: center; gap: 6px; transition: background 0.2s; }
|
|
||||||
.btn-back:hover { background: #4B5563; color: #fff; }
|
|
||||||
|
|
||||||
.info-box-header { background: linear-gradient(135deg, var(--primary-color), #059669); color: #fff; padding: 20px 24px; border-radius: 12px; margin-bottom: 14px; box-shadow: 0 4px 12px rgba(16,185,129,0.2); }
|
|
||||||
.info-box-header h3 { margin: 0 0 6px; font-size: 1.3rem; display: flex; align-items: center; gap: 10px; }
|
|
||||||
.info-box-header .meta { opacity: 0.9; font-size: 0.88rem; display: flex; flex-wrap: wrap; gap: 12px; margin-top: 6px; }
|
|
||||||
.info-box-header .periode-tag { background: rgba(255,255,255,0.2); padding: 3px 10px; border-radius: 20px; font-size: 0.8rem; display: inline-flex; align-items: center; gap: 5px; }
|
|
||||||
|
|
||||||
/* 6 KPI cards */
|
|
||||||
.stats-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(6, 1fr);
|
|
||||||
gap: 12px;
|
|
||||||
margin-bottom: 14px;
|
|
||||||
}
|
|
||||||
@media (max-width: 1100px) { .stats-row { grid-template-columns: repeat(3, 1fr); } }
|
|
||||||
@media (max-width: 600px) { .stats-row { grid-template-columns: repeat(2, 1fr); } }
|
|
||||||
|
|
||||||
.stat-card { background: #fff; padding: 14px 12px; border-radius: 10px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); display: flex; align-items: center; gap: 12px; }
|
|
||||||
.stat-card .icon { font-size: 1.4rem; width: 40px; height: 40px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; border-radius: 10px; }
|
|
||||||
.stat-card.hadir .icon { background: #D1FAE5; color: #065F46; }
|
|
||||||
.stat-card.terlambat .icon { background: #FFF3E0; color: #E65100; }
|
|
||||||
.stat-card.izin .icon { background: #FEF3C7; color: #92400E; }
|
|
||||||
.stat-card.sakit .icon { background: #DBEAFE; color: #1E40AF; }
|
|
||||||
.stat-card.alpa .icon { background: #FEE2E2; color: #991B1B; }
|
|
||||||
.stat-card.pulang .icon { background: #F3E8FF; color: #6B21A8; }
|
|
||||||
.stat-card .content { flex: 1; min-width: 0; }
|
|
||||||
.stat-card .label { font-size: 0.78rem; color: var(--text-light); margin-bottom: 2px; }
|
|
||||||
.stat-card .value { font-size: 1.5rem; font-weight: 700; color: var(--primary-dark); line-height: 1.2; }
|
|
||||||
|
|
||||||
.filter-box { background: #fff; padding: 14px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); margin-bottom: 14px; }
|
|
||||||
.filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px; }
|
|
||||||
.form-group { margin: 0; }
|
|
||||||
.form-group label { display: block; font-size: 0.85rem; margin-bottom: 5px; color: var(--text-light); font-weight: 500; }
|
|
||||||
.form-control { width: 100%; padding: 8px 12px; border: 1px solid #e2e8f0; border-radius: 8px; font-size: 0.85rem; }
|
|
||||||
.btn-filter { background: var(--primary-color); color: #fff; border: none; padding: 9px 16px; border-radius: 8px; cursor: pointer; font-size: 0.85rem; display: inline-flex; align-items: center; gap: 6px; transition: all 0.2s; }
|
|
||||||
.btn-filter:hover { background: #059669; }
|
|
||||||
.btn-reset { background: #6B7280; color: #fff; border: none; padding: 9px 12px; border-radius: 8px; font-size: 0.85rem; display: inline-flex; align-items: center; gap: 6px; text-decoration: none; }
|
|
||||||
.btn-reset:hover { background: #4B5563; color: #fff; }
|
|
||||||
|
|
||||||
.day-group { margin-bottom: 18px; background: #fff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); overflow: hidden; }
|
|
||||||
.day-header { background: linear-gradient(135deg, #f0fdf4 0%, #E8F7F2 100%); padding: 14px 18px; display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #E8F7F2; cursor: pointer; transition: background 0.2s; user-select: none; }
|
|
||||||
.day-header:hover { background: linear-gradient(135deg, #E8F7F2 0%, #d1f2e8 100%); }
|
|
||||||
.day-title { font-weight: 700; font-size: 1rem; color: var(--primary-dark); display: flex; align-items: center; gap: 8px; }
|
|
||||||
.day-title i { color: var(--primary-color); }
|
|
||||||
.day-stats { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
|
|
||||||
.mini-badge { padding: 4px 10px; border-radius: 20px; font-size: 0.75rem; font-weight: 600; display: inline-flex; align-items: center; gap: 4px; }
|
|
||||||
.mini-badge.hadir { background: #D1FAE5; color: #065F46; }
|
|
||||||
.mini-badge.terlambat { background: #FFF3E0; color: #E65100; }
|
|
||||||
.mini-badge.izin { background: #FEF3C7; color: #92400E; }
|
|
||||||
.mini-badge.sakit { background: #DBEAFE; color: #1E40AF; }
|
|
||||||
.mini-badge.alpa { background: #FEE2E2; color: #991B1B; }
|
|
||||||
.mini-badge.pulang { background: #F3E8FF; color: #6B21A8; }
|
|
||||||
.day-body table { width: 100%; border-collapse: collapse; }
|
|
||||||
.day-body table thead { background: #f8fafc; }
|
|
||||||
.day-body table th { padding: 10px 14px; text-align: left; font-weight: 600; font-size: 0.82rem; color: #64748b; border-bottom: 1px solid #e2e8f0; }
|
|
||||||
.day-body table td { padding: 9px 14px; font-size: 0.85rem; border-bottom: 1px solid #f1f5f9; }
|
|
||||||
.day-body table tbody tr:last-child td { border-bottom: none; }
|
|
||||||
.day-body table tbody tr:hover { background: #f8fafc; }
|
|
||||||
.toggle-icon { transition: transform 0.3s; font-size: 0.85rem; color: #94a3b8; }
|
|
||||||
.toggle-icon.collapsed { transform: rotate(-90deg); }
|
|
||||||
|
|
||||||
.empty-state { text-align: center; padding: 36px 20px; color: var(--text-light); background: #fff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
|
|
||||||
.empty-state i { font-size: 3.5rem; margin-bottom: 14px; opacity: 0.3; display: block; }
|
|
||||||
|
|
||||||
.pagination { display: flex; justify-content: center; align-items: center; gap: 6px; margin-top: 14px; }
|
|
||||||
.pagination a, .pagination span { padding: 6px 12px; border: 1px solid #e2e8f0; border-radius: 6px; font-size: 0.82rem; text-decoration: none; color: var(--text-dark); transition: all 0.2s; }
|
|
||||||
.pagination a:hover { background: var(--primary-color); color: #fff; border-color: var(--primary-color); }
|
|
||||||
.pagination .active { background: var(--primary-color); color: #fff; border-color: var(--primary-color); font-weight: 600; }
|
|
||||||
.pagination .disabled { color: #cbd5e1; cursor: not-allowed; }
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.day-header { flex-direction: column; align-items: flex-start; gap: 8px; }
|
|
||||||
.day-body table th:nth-child(2), .day-body table td:nth-child(2) { display: none; }
|
|
||||||
.day-body table th:nth-child(7), .day-body table td:nth-child(7) { display: none; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
// Ambil range dari query string (diteruskan dari index)
|
|
||||||
$defaultDari = now()->startOfWeek(\Carbon\Carbon::MONDAY)->format('Y-m-d');
|
|
||||||
$defaultSampai = now()->endOfWeek(\Carbon\Carbon::SUNDAY)->format('Y-m-d');
|
|
||||||
$filterDari = request('tanggal_dari', $defaultDari);
|
|
||||||
$filterSampai = request('tanggal_sampai', $defaultSampai);
|
|
||||||
$filterBulan = request('bulan', '');
|
|
||||||
|
|
||||||
if ($filterBulan) {
|
|
||||||
$periodeLabel = 'Bulan ' . \Carbon\Carbon::parse($filterBulan . '-01')->locale('id')->isoFormat('MMMM Y');
|
|
||||||
} else {
|
|
||||||
$periodeLabel = \Carbon\Carbon::parse($filterDari)->locale('id')->isoFormat('D MMM Y')
|
|
||||||
. ' – '
|
|
||||||
. \Carbon\Carbon::parse($filterSampai)->locale('id')->isoFormat('D MMM Y');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hitung KPI dari data yang sudah difilter (semua halaman, bukan hanya halaman ini)
|
|
||||||
// $stats sudah dihitung di controller berdasarkan filter — gunakan langsung
|
|
||||||
// Tapi jika controller belum menghitung per filter, hitung dari koleksi paginator saat ini
|
|
||||||
// Gunakan $stats dari controller jika ada, fallback ke hitung manual
|
|
||||||
$statsHadir = $stats['Hadir'] ?? 0;
|
|
||||||
$statsTerlambat = $stats['Terlambat'] ?? 0;
|
|
||||||
$statsIzin = $stats['Izin'] ?? 0;
|
|
||||||
$statsSakit = $stats['Sakit'] ?? 0;
|
|
||||||
$statsAlpa = $stats['Alpa'] ?? 0;
|
|
||||||
$statsPulang = $stats['Pulang'] ?? 0;
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-file-alt"></i> Detail Riwayat: <?php echo e($kegiatan->nama_kegiatan); ?></h2>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['tanggal_dari' => $filterDari, 'tanggal_sampai' => $filterSampai])); ?>"
|
|
||||||
class="btn-back">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="info-box-header">
|
|
||||||
<h3><i class="fas fa-clipboard-check"></i> <?php echo e($kegiatan->nama_kegiatan); ?></h3>
|
|
||||||
<div class="meta">
|
|
||||||
<span><i class="fas fa-tag"></i> <?php echo e($kegiatan->kategori->nama_kategori); ?></span>
|
|
||||||
<span><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))); ?></span>
|
|
||||||
<span><i class="fas fa-calendar-day"></i> <?php echo e($kegiatan->hari); ?></span>
|
|
||||||
<?php if($kegiatan->kelasKegiatan->count() > 0): ?>
|
|
||||||
<span><i class="fas fa-users"></i> <?php echo e($kegiatan->kelasKegiatan->pluck('nama_kelas')->implode(', ')); ?></span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span><i class="fas fa-globe"></i> Umum</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<span class="periode-tag"><i class="fas fa-calendar-check"></i> <?php echo e($periodeLabel); ?></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if(isset($totalSantriEligible)): ?>
|
|
||||||
<div style="background: #fff; border-radius: 12px; padding: 16px 20px; margin-bottom: 14px; box-shadow: 0 2px 12px rgba(0,0,0,0.06); border-left: 4px solid #2563eb;">
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 10px;">
|
|
||||||
<div>
|
|
||||||
<h4 style="margin: 0; font-size: 1rem; color: #1a2332;">
|
|
||||||
<i class="fas fa-users" style="color: #2563eb;"></i> Total Semua Santri: <strong><?php echo e($totalSantriEligible); ?></strong>
|
|
||||||
</h4>
|
|
||||||
<p style="margin: 4px 0 0; font-size: 0.84rem; color: #6b7280;">
|
|
||||||
Sudah absen: <strong style="color: #059669;"><?php echo e($totalRecorded); ?></strong>
|
|
||||||
·
|
|
||||||
Belum absen: <strong style="color: <?php echo e(($totalSantriEligible - $totalRecorded) > 0 ? '#dc2626' : '#059669'); ?>;"><?php echo e(max(0, $totalSantriEligible - $totalRecorded)); ?></strong>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div style="text-align: right;">
|
|
||||||
<div style="font-size: 1.5rem; font-weight: 800; color: <?php echo e($persenHadir >= 85 ? '#059669' : ($persenHadir >= 70 ? '#d97706' : '#dc2626')); ?>;">
|
|
||||||
<?php echo e($persenHadir); ?>%
|
|
||||||
</div>
|
|
||||||
<div style="font-size: 0.78rem; color: #6b7280;">Kehadiran</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$pctSudah = $totalSantriEligible > 0 ? round($totalRecorded / $totalSantriEligible * 100, 1) : 0;
|
|
||||||
$pctBelumRiwayat = 100 - $pctSudah;
|
|
||||||
?>
|
|
||||||
<div style="height: 24px; background: #f3f4f6; border-radius: 12px; overflow: hidden; display: flex;">
|
|
||||||
<?php if($pctSudah > 0): ?>
|
|
||||||
<div style="width: <?php echo e($pctSudah); ?>%; background: linear-gradient(90deg, #22c55e, #16a34a); display: flex; align-items: center; justify-content: center; color: white; font-size: 0.73rem; font-weight: 700;" title="Sudah Absen: <?php echo e($totalRecorded); ?>">
|
|
||||||
<?php echo e($totalRecorded); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($pctBelumRiwayat > 0 && ($totalSantriEligible - $totalRecorded) > 0): ?>
|
|
||||||
<div style="width: <?php echo e($pctBelumRiwayat); ?>%; background: #d1d5db; display: flex; align-items: center; justify-content: center; color: #6b7280; font-size: 0.73rem; font-weight: 700;" title="Belum Absen: <?php echo e($totalSantriEligible - $totalRecorded); ?>">
|
|
||||||
<?php echo e($totalSantriEligible - $totalRecorded); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="stats-row">
|
|
||||||
<div class="stat-card hadir">
|
|
||||||
<div class="icon"><i class="fas fa-check-circle"></i></div>
|
|
||||||
<div class="content">
|
|
||||||
<div class="label">Hadir</div>
|
|
||||||
<div class="value"><?php echo e($statsHadir); ?></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card terlambat">
|
|
||||||
<div class="icon"><i class="fas fa-clock"></i></div>
|
|
||||||
<div class="content">
|
|
||||||
<div class="label">Terlambat</div>
|
|
||||||
<div class="value"><?php echo e($statsTerlambat); ?></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card izin">
|
|
||||||
<div class="icon"><i class="fas fa-envelope"></i></div>
|
|
||||||
<div class="content">
|
|
||||||
<div class="label">Izin</div>
|
|
||||||
<div class="value"><?php echo e($statsIzin); ?></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card sakit">
|
|
||||||
<div class="icon"><i class="fas fa-heartbeat"></i></div>
|
|
||||||
<div class="content">
|
|
||||||
<div class="label">Sakit</div>
|
|
||||||
<div class="value"><?php echo e($statsSakit); ?></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card alpa">
|
|
||||||
<div class="icon"><i class="fas fa-times-circle"></i></div>
|
|
||||||
<div class="content">
|
|
||||||
<div class="label">Alpa</div>
|
|
||||||
<div class="value"><?php echo e($statsAlpa); ?></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card pulang">
|
|
||||||
<div class="icon"><i class="fas fa-home"></i></div>
|
|
||||||
<div class="content">
|
|
||||||
<div class="label">Pulang</div>
|
|
||||||
<div class="value"><?php echo e($statsPulang); ?></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="filter-box">
|
|
||||||
<form method="GET">
|
|
||||||
|
|
||||||
<input type="hidden" name="tanggal_dari" value="<?php echo e($filterDari); ?>">
|
|
||||||
<input type="hidden" name="tanggal_sampai" value="<?php echo e($filterSampai); ?>">
|
|
||||||
|
|
||||||
<div class="filter-grid">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="id_santri">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">
|
|
||||||
<label for="id_kelas">Kelas</label>
|
|
||||||
<select name="id_kelas" id="id_kelas" class="form-control">
|
|
||||||
<option value="">-- Semua Kelas --</option>
|
|
||||||
<?php $__currentLoopData = $kelasList->groupBy('kelompok.nama_kelompok'); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelompokNama => $kelasList_group): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<optgroup label="<?php echo e($kelompokNama); ?>">
|
|
||||||
<?php $__currentLoopData = $kelasList_group; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($kelas->id); ?>" <?php echo e(request('id_kelas') == $kelas->id ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($kelas->nama_kelas); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</optgroup>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="status">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="Terlambat" <?php echo e(request('status') == 'Terlambat' ? 'selected' : ''); ?>>Terlambat</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>
|
|
||||||
<option value="Pulang" <?php echo e(request('status') == 'Pulang' ? 'selected' : ''); ?>>Pulang</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="tanggal_spesifik">Filter Tanggal Spesifik</label>
|
|
||||||
<input type="date" name="tanggal_spesifik" id="tanggal_spesifik" class="form-control"
|
|
||||||
value="<?php echo e(request('tanggal_spesifik')); ?>"
|
|
||||||
min="<?php echo e($filterDari); ?>" max="<?php echo e($filterSampai); ?>">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display: flex; align-items: flex-end; gap: 10px;">
|
|
||||||
<button type="submit" class="btn-filter" style="flex: 1;">
|
|
||||||
<i class="fas fa-filter"></i> Filter
|
|
||||||
</button>
|
|
||||||
<?php if(request()->hasAny(['id_santri', 'id_kelas', 'status', 'tanggal_spesifik'])): ?>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.show', $kegiatan->id)); ?>?tanggal_dari=<?php echo e($filterDari); ?>&tanggal_sampai=<?php echo e($filterSampai); ?>"
|
|
||||||
class="btn-reset">
|
|
||||||
<i class="fas fa-times"></i>
|
|
||||||
</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($riwayats->count() > 0): ?>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$grouped = $riwayats->getCollection()->groupBy(function($item) {
|
|
||||||
return $item->tanggal->format('Y-m-d');
|
|
||||||
})->sortKeysDesc();
|
|
||||||
?>
|
|
||||||
|
|
||||||
<?php $__currentLoopData = $grouped; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $tanggal => $records): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$tglCarbon = \Carbon\Carbon::parse($tanggal);
|
|
||||||
$hariIndo = $tglCarbon->locale('id')->isoFormat('dddd');
|
|
||||||
$tglFormatted = $tglCarbon->locale('id')->isoFormat('D MMMM Y');
|
|
||||||
|
|
||||||
$dayHadir = $records->where('status', 'Hadir')->count();
|
|
||||||
$dayTerlambat = $records->where('status', 'Terlambat')->count();
|
|
||||||
$dayIzin = $records->where('status', 'Izin')->count();
|
|
||||||
$daySakit = $records->where('status', 'Sakit')->count();
|
|
||||||
$dayAlpa = $records->where('status', 'Alpa')->count();
|
|
||||||
$dayPulang = $records->where('status', 'Pulang')->count();
|
|
||||||
$dayTotal = $records->count();
|
|
||||||
|
|
||||||
// Group per kelas kegiatan (khusus) atau kelas_name santri (umum)
|
|
||||||
$isUmum = $kegiatan->kelasKegiatan->isEmpty();
|
|
||||||
if ($isUmum) {
|
|
||||||
$recordsPerKelas = $records->groupBy(fn($r) =>
|
|
||||||
optional(optional($r->santri->kelasSantri->first())->kelas)->nama_kelas ?? 'Tanpa Kelas'
|
|
||||||
)->sortKeys();
|
|
||||||
} else {
|
|
||||||
$recordsPerKelas = collect();
|
|
||||||
$placedIds = [];
|
|
||||||
foreach ($kegiatan->kelasKegiatan as $kls) {
|
|
||||||
$inKelas = $records->filter(function($r) use ($kls, &$placedIds) {
|
|
||||||
if (in_array($r->id, $placedIds)) return false;
|
|
||||||
return $r->santri->kelasSantri->contains('id_kelas', $kls->id);
|
|
||||||
});
|
|
||||||
foreach ($inKelas as $r) $placedIds[] = $r->id;
|
|
||||||
if ($inKelas->count() > 0) $recordsPerKelas[$kls->nama_kelas] = $inKelas;
|
|
||||||
}
|
|
||||||
$lainnya = $records->filter(fn($r) => !in_array($r->id, $placedIds));
|
|
||||||
if ($lainnya->count() > 0) $recordsPerKelas['Kelas Lain'] = $lainnya;
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="day-group">
|
|
||||||
<div class="day-header" onclick="toggleDay(this)">
|
|
||||||
<div class="day-title">
|
|
||||||
<i class="fas fa-calendar-day"></i>
|
|
||||||
<?php echo e($hariIndo); ?>, <?php echo e($tglFormatted); ?>
|
|
||||||
|
|
||||||
<span style="font-weight: 400; font-size: 0.85rem; color: #94a3b8; margin-left: 4px;">(<?php echo e($dayTotal); ?> santri)</span>
|
|
||||||
</div>
|
|
||||||
<div class="day-stats">
|
|
||||||
<?php if($dayHadir > 0): ?>
|
|
||||||
<span class="mini-badge hadir"><i class="fas fa-check"></i> <?php echo e($dayHadir); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($dayTerlambat > 0): ?>
|
|
||||||
<span class="mini-badge terlambat"><i class="fas fa-clock"></i> <?php echo e($dayTerlambat); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($dayIzin > 0): ?>
|
|
||||||
<span class="mini-badge izin"><i class="fas fa-envelope"></i> <?php echo e($dayIzin); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($daySakit > 0): ?>
|
|
||||||
<span class="mini-badge sakit"><i class="fas fa-heartbeat"></i> <?php echo e($daySakit); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($dayAlpa > 0): ?>
|
|
||||||
<span class="mini-badge alpa"><i class="fas fa-times"></i> <?php echo e($dayAlpa); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($dayPulang > 0): ?>
|
|
||||||
<span class="mini-badge pulang"><i class="fas fa-home"></i> <?php echo e($dayPulang); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<i class="fas fa-chevron-down toggle-icon"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="day-body">
|
|
||||||
<?php $__currentLoopData = $recordsPerKelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $namaKelas => $kelasRecords): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div style="background: linear-gradient(135deg, #f0fdf4, #e8f5e9); padding: 8px 18px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #e2e8f0;">
|
|
||||||
<span style="font-size: 0.85rem; font-weight: 600; color: #065f46;">
|
|
||||||
<i class="fas fa-school"></i> <?php echo e($namaKelas); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<span style="background: #6FBAA5; color: white; padding: 2px 10px; border-radius: 10px; font-size: 0.75rem; font-weight: 600;">
|
|
||||||
<?php echo e($kelasRecords->count()); ?> santri
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 45px;">No</th>
|
|
||||||
<th style="width: 90px;">ID Santri</th>
|
|
||||||
<th>Nama Santri</th>
|
|
||||||
<th style="width: 90px; text-align: center;">Status</th>
|
|
||||||
<th style="width: 80px; text-align: center;">Waktu</th>
|
|
||||||
<th style="width: 80px;">Metode</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $kelasRecords->values(); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $riwayat): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($index + 1); ?></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 style="text-align: center;"><?php echo $riwayat->status_badge; ?></td>
|
|
||||||
<td style="text-align: center;">
|
|
||||||
<?php echo e($riwayat->waktu_absen ? \Carbon\Carbon::parse($riwayat->waktu_absen)->format('H:i') : '-'); ?>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($riwayat->metode_absen == 'RFID'): ?>
|
|
||||||
<span style="background: #DBEAFE; color: #1E40AF; padding: 3px 8px; border-radius: 10px; font-size: 0.75rem; font-weight: 600;">
|
|
||||||
<i class="fas fa-id-card"></i> RFID
|
|
||||||
</span>
|
|
||||||
<?php elseif($riwayat->metode_absen == 'Import_Mesin'): ?>
|
|
||||||
<span style="background: #EDE9FE; color: #6B21A8; padding: 3px 8px; border-radius: 10px; font-size: 0.75rem; font-weight: 600;">
|
|
||||||
<i class="fas fa-desktop"></i> Mesin
|
|
||||||
</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="background: #E5E7EB; color: #374151; padding: 3px 8px; border-radius: 10px; font-size: 0.75rem; font-weight: 600;">
|
|
||||||
<i class="fas fa-hand-pointer"></i> Manual
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
|
|
||||||
<div class="pagination">
|
|
||||||
<?php echo $riwayats->appends(request()->query())->links('pagination::simple-bootstrap-4'); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-inbox"></i>
|
|
||||||
<h3>Tidak Ada Riwayat</h3>
|
|
||||||
<p>Tidak ada data absensi untuk periode <strong><?php echo e($periodeLabel); ?></strong>.</p>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function toggleDay(header) {
|
|
||||||
var body = header.nextElementSibling;
|
|
||||||
var icon = header.querySelector('.toggle-icon');
|
|
||||||
if (body.style.display === 'none') {
|
|
||||||
body.style.display = 'block';
|
|
||||||
icon.classList.remove('collapsed');
|
|
||||||
} else {
|
|
||||||
body.style.display = 'none';
|
|
||||||
icon.classList.add('collapsed');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</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/riwayat/show.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,138 +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 (Web)</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if(session('success')): ?>
|
|
||||||
<div class="alert alert-success"><?php echo session('success'); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if(session('error')): ?>
|
|
||||||
<div class="alert alert-danger"><?php echo e(session('error')); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if(session('info')): ?>
|
|
||||||
<div class="alert alert-info"><?php echo e(session('info')); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<div class="alert alert-info">
|
|
||||||
<i class="fas fa-info-circle"></i> <strong>Info Login Santri (Web) : </strong>
|
|
||||||
Username = Nama Lengkap Santri | Password = NIS Santri
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Daftar Akun Santri (<?php echo e($users->count()); ?>)</h3>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID Santri</th>
|
|
||||||
<th>Nama Santri</th>
|
|
||||||
<th>NIS</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->id_santri); ?></td>
|
|
||||||
<td><?php echo e($user->santri->nama_lengkap ?? '-'); ?></td>
|
|
||||||
<td><?php echo e($user->santri->nis ?? '-'); ?></td>
|
|
||||||
<td><code><?php echo e($user->username); ?></code></td>
|
|
||||||
<td>
|
|
||||||
<form action="<?php echo e(route('admin.users.santri_destroy', $user->id)); ?>"
|
|
||||||
method="POST" style="display:inline;"
|
|
||||||
onsubmit="return confirm('Yakin hapus akun santri <?php echo e($user->santri->nama_lengkap ?? ''); ?>?')">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<button type="submit" class="btn btn-sm btn-danger">
|
|
||||||
<i class="fas fa-trash"></i> Hapus
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
|
||||||
<tr>
|
|
||||||
<td colspan="5" class="text-center">Belum ada akun santri.</td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<h3 style="margin-top:22px;">
|
|
||||||
Santri Belum Punya Akun (<?php echo e($santris_tanpa_akun->count()); ?>)
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<?php if($santris_tanpa_akun->count() > 0): ?>
|
|
||||||
<div style="margin-bottom:12px;">
|
|
||||||
<form action="<?php echo e(route('admin.users.santri_buat_semua')); ?>" method="POST" style="display:inline;"
|
|
||||||
onsubmit="return confirm('Buat akun untuk SEMUA <?php echo e($santris_tanpa_akun->count()); ?> santri sekaligus?')">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<button type="submit" class="btn btn-success">
|
|
||||||
<i class="fas fa-users"></i> Buat Semua Sekaligus (<?php echo e($santris_tanpa_akun->count()); ?>)
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<div class="table-wrapper">
|
|
||||||
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID Santri</th>
|
|
||||||
<th>NIS</th>
|
|
||||||
<th>Nama Santri</th>
|
|
||||||
<th>Kelas</th>
|
|
||||||
<th>Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__empty_1 = true; $__currentLoopData = $santris_tanpa_akun; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($santri->id_santri); ?></td>
|
|
||||||
<td>
|
|
||||||
<?php if($santri->nis): ?>
|
|
||||||
<?php echo e($santri->nis); ?>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="text-danger">Belum ada NIS</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td><?php echo e($santri->nama_lengkap); ?></td>
|
|
||||||
<td><?php echo e($santri->kelas ?? '-'); ?></td>
|
|
||||||
<td>
|
|
||||||
<?php if($santri->nis): ?>
|
|
||||||
<form action="<?php echo e(route('admin.users.santri_buat_akun', $santri->id_santri)); ?>"
|
|
||||||
method="POST" style="display:inline;"
|
|
||||||
onsubmit="return confirm('Buat akun untuk <?php echo e($santri->nama_lengkap); ?>?')">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<button type="submit" class="btn btn-sm btn-primary">
|
|
||||||
<i class="fas fa-user-plus"></i> Buat Akun
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="text-muted">Isi NIS dulu</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
|
||||||
<tr>
|
|
||||||
<td colspan="5" class="text-center text-success">
|
|
||||||
<i class="fas fa-check"></i> Semua santri sudah punya akun.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</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/users/santri_accounts.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,298 +1,456 @@
|
||||||
<?php $__env->startSection('content'); ?>
|
<?php $__env->startSection('content'); ?>
|
||||||
<style>
|
<style>
|
||||||
.day-group { margin-bottom: 18px; background: #fff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); overflow: hidden; }
|
/* ============================================================
|
||||||
.day-header { background: linear-gradient(135deg, #f0fdf4 0%, #E8F7F2 100%); padding: 13px 18px; display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #E8F7F2; cursor: pointer; transition: background 0.2s; user-select: none; }
|
RIWAYAT KEGIATAN — INDEX (v3)
|
||||||
.day-header:hover{ background: linear-gradient(135deg, #E8F7F2 0%, #d1f2e8 100%); }
|
============================================================ */
|
||||||
.day-title { font-weight: 700; font-size: 1rem; color: var(--primary-dark); display: flex; align-items: center; gap: 8px; }
|
|
||||||
.day-title i { color: var(--primary-color); }
|
|
||||||
.day-meta { display: flex; gap: 10px; align-items: center; }
|
|
||||||
.day-count { background: var(--primary-color); color: #fff; padding: 3px 10px; border-radius: 20px; font-size: 0.78rem; font-weight: 600; }
|
|
||||||
.toggle-icon { transition: transform 0.3s; font-size: 0.85rem; color: #94a3b8; }
|
|
||||||
.toggle-icon.collapsed { transform: rotate(-90deg); }
|
|
||||||
.day-body { overflow: hidden; }
|
|
||||||
.day-body table { width: 100%; border-collapse: collapse; }
|
|
||||||
.day-body thead { background: #f8fafc; }
|
|
||||||
.day-body th { padding: 9px 14px; text-align: left; font-weight: 600; font-size: 0.8rem; color: #64748b; border-bottom: 1px solid #e2e8f0; }
|
|
||||||
.day-body td { padding: 10px 14px; font-size: 0.85rem; border-bottom: 1px solid #f1f5f9; vertical-align: middle; }
|
|
||||||
.day-body tbody tr:last-child td { border-bottom: none; }
|
|
||||||
.day-body tbody tr:hover { background: #f8fafc; }
|
|
||||||
|
|
||||||
.stat-chips { display: flex; gap: 5px; flex-wrap: wrap; }
|
.rw-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:16px; flex-wrap:wrap; gap:10px; }
|
||||||
.chip { padding: 2px 8px; border-radius: 10px; font-size: 0.74rem; font-weight: 600; display: inline-flex; align-items: center; gap: 3px; }
|
.rw-header h2 { margin:0; font-size:1.35rem; color:var(--primary-dark); display:flex; align-items:center; gap:9px; }
|
||||||
.chip-hadir { background: #D1FAE5; color: #065F46; }
|
.rw-header h2 i { color:var(--primary-color); }
|
||||||
.chip-terlambat { background: #FFF3E0; color: #E65100; }
|
|
||||||
.chip-izin { background: #FEF3C7; color: #92400E; }
|
|
||||||
.chip-sakit { background: #DBEAFE; color: #1E40AF; }
|
|
||||||
.chip-alpa { background: #FEE2E2; color: #991B1B; }
|
|
||||||
.chip-pulang { background: #F3E8FF; color: #6B21A8; }
|
|
||||||
.chip-none { background: #F1F5F9; color: #94a3b8; }
|
|
||||||
.kelas-tag { display: inline-block; background: #E8F7F2; color: var(--primary-dark); padding: 2px 7px; border-radius: 8px; font-size: 0.74rem; margin: 2px 2px 0 0; }
|
|
||||||
.umum-tag { display: inline-block; background: #F1F5F9; color: #64748b; padding: 2px 7px; border-radius: 8px; font-size: 0.74rem; }
|
|
||||||
.btn-detail { padding: 5px 12px; background: var(--primary-color); color: #fff; border: none; border-radius: 6px; font-size: 0.8rem; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; transition: all 0.2s; }
|
|
||||||
.btn-detail:hover { background: #059669; color: #fff; transform: translateY(-1px); }
|
|
||||||
|
|
||||||
.filter-box { background: #fff; padding: 14px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); margin-bottom: 14px; }
|
/* Filter */
|
||||||
.filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px; }
|
.rw-filter { background:#fff; border-radius:12px; box-shadow:0 2px 10px rgba(0,0,0,.06); padding:14px 18px; margin-bottom:14px; }
|
||||||
.form-group { margin: 0; }
|
.rw-mode-tabs { display:flex; gap:6px; margin-bottom:14px; flex-wrap:wrap; }
|
||||||
.form-group label { display: block; font-size: 0.85rem; margin-bottom: 5px; color: var(--text-light); font-weight: 500; }
|
.rw-tab { padding:7px 18px; border-radius:22px; border:1.5px solid #e2e8f0; background:#fff;
|
||||||
.form-control { width: 100%; padding: 8px 12px; border: 1px solid #e2e8f0; border-radius: 8px; font-size: 0.85rem; }
|
font-size:0.82rem; font-weight:600; cursor:pointer; text-decoration:none;
|
||||||
.btn-filter { background: var(--primary-color); color: #fff; border: none; padding: 9px 16px; border-radius: 8px; cursor: pointer; font-size: 0.85rem; display: inline-flex; align-items: center; gap: 6px; transition: all 0.2s; }
|
color:#64748b; transition:all .18s; display:inline-flex; align-items:center; gap:6px; }
|
||||||
.btn-filter:hover { background: #059669; transform: translateY(-1px); }
|
.rw-tab:hover { border-color:var(--primary-color); color:var(--primary-color); background:#f0fdf4; }
|
||||||
.btn-reset { background: #6B7280; color: #fff; border: none; padding: 9px 12px; border-radius: 8px; cursor: pointer; font-size: 0.85rem; display: inline-flex; align-items: center; gap: 6px; text-decoration: none; }
|
.rw-tab.active { background:var(--primary-color); color:#fff; border-color:var(--primary-color); box-shadow:0 2px 8px rgba(16,185,129,.25); }
|
||||||
.btn-reset:hover { background: #4B5563; }
|
.rw-filter-row { display:flex; gap:10px; align-items:flex-end; flex-wrap:wrap; }
|
||||||
|
.rw-fg { display:flex; flex-direction:column; gap:4px; }
|
||||||
|
.rw-fg label { font-size:0.78rem; font-weight:600; color:#64748b; }
|
||||||
|
.rw-fg .form-control { padding:7px 11px; font-size:0.84rem; border:1.5px solid #e2e8f0; border-radius:8px; }
|
||||||
|
.rw-fg .form-control:focus { border-color:var(--primary-color); outline:none; }
|
||||||
|
.btn-rw-apply { background:var(--primary-color); color:#fff; border:none; padding:8px 18px; border-radius:8px;
|
||||||
|
font-size:0.84rem; font-weight:600; cursor:pointer; display:inline-flex; align-items:center; gap:6px;
|
||||||
|
align-self:flex-end; white-space:nowrap; }
|
||||||
|
.btn-rw-apply:hover { background:#059669; }
|
||||||
|
.btn-rw-reset { background:#f1f5f9; color:#64748b; border:1.5px solid #e2e8f0; padding:8px 12px; border-radius:8px;
|
||||||
|
font-size:0.84rem; font-weight:600; text-decoration:none;
|
||||||
|
display:inline-flex; align-items:center; gap:6px; align-self:flex-end; }
|
||||||
|
.btn-rw-reset:hover { background:#e2e8f0; }
|
||||||
|
|
||||||
.period-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
|
/* Periode label */
|
||||||
.period-tab { padding: 5px 14px; border-radius: 20px; border: 1px solid #e2e8f0; background: #fff; font-size: 0.82rem; cursor: pointer; text-decoration: none; color: var(--text-dark); transition: all 0.2s; display: inline-flex; align-items: center; gap: 5px; }
|
.rw-periode { background:linear-gradient(90deg,#f0fdf4,#e8f7f2); border-left:3px solid var(--primary-color);
|
||||||
.period-tab:hover, .period-tab.active { background: var(--primary-color); color: #fff; border-color: var(--primary-color); }
|
border-radius:8px; padding:9px 14px; margin-bottom:14px; font-size:0.84rem; color:#374151;
|
||||||
|
display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
|
||||||
|
.rw-periode i { color:var(--primary-color); }
|
||||||
|
|
||||||
.periode-info { font-size: 0.82rem; color: var(--text-light); margin-bottom: 12px; padding: 8px 12px; background: #f0fdf4; border-radius: 8px; border-left: 3px solid var(--primary-color); }
|
/* KPI strip */
|
||||||
.periode-info strong { color: var(--primary-color); }
|
.rw-kpi-strip { display:grid; grid-template-columns:repeat(auto-fit,minmax(105px,1fr)); gap:8px; margin-bottom:14px; }
|
||||||
|
.rw-kpi { background:#fff; border-radius:10px; padding:11px 14px; box-shadow:0 2px 8px rgba(0,0,0,.05); text-align:center; }
|
||||||
|
.rw-kpi-val { font-size:1.45rem; font-weight:800; line-height:1; }
|
||||||
|
.rw-kpi-lbl { font-size:0.73rem; color:#94a3b8; margin-top:4px; font-weight:500; }
|
||||||
|
.rw-kpi-sub { font-size:0.68rem; color:#cbd5e1; margin-top:2px; }
|
||||||
|
|
||||||
.empty-state { text-align: center; padding: 44px 14px; color: var(--text-light); background: #fff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
|
/* Per-date block */
|
||||||
.empty-state i { font-size: 3.5rem; margin-bottom: 14px; opacity: 0.3; display: block; }
|
.rw-date-block { margin-bottom:20px; }
|
||||||
.empty-state h3 { margin: 0 0 6px; }
|
.rw-date-header { display:flex; align-items:center; gap:10px; padding:10px 16px; flex-wrap:wrap;
|
||||||
|
background:linear-gradient(90deg,var(--primary-color),#0ea574);
|
||||||
|
border-radius:10px 10px 0 0; color:#fff; }
|
||||||
|
.rw-date-today { background:linear-gradient(90deg,#0ea574,#059669); }
|
||||||
|
.dh-date { font-size:1rem; font-weight:700; }
|
||||||
|
.dh-hari { background:rgba(255,255,255,.22); padding:2px 10px; border-radius:12px; font-size:0.78rem; font-weight:600; }
|
||||||
|
.dh-count { margin-left:auto; font-size:0.78rem; background:rgba(255,255,255,.2); padding:3px 10px; border-radius:12px; }
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
/* Table */
|
||||||
.day-header { flex-direction: column; align-items: flex-start; gap: 6px; }
|
.rw-tbl-wrap { background:#fff; border-radius:0 0 10px 10px; box-shadow:0 3px 12px rgba(0,0,0,.07); overflow-x:auto; }
|
||||||
.day-body th:nth-child(3), .day-body td:nth-child(3),
|
.rw-table { width:100%; border-collapse:collapse; min-width:680px; }
|
||||||
.day-body th:nth-child(4), .day-body td:nth-child(4) { display: none; }
|
.rw-table thead th { padding:9px 13px; text-align:left; font-size:0.78rem; font-weight:700;
|
||||||
|
color:#475569; background:#f8fafc; border-bottom:1.5px solid #e2e8f0; white-space:nowrap; }
|
||||||
|
.rw-table tbody td { padding:9px 13px; font-size:0.83rem; border-bottom:1px solid #f8fafc; vertical-align:middle; }
|
||||||
|
.rw-table tbody tr:last-child td { border-bottom:none; }
|
||||||
|
.rw-table tbody tr:hover { background:#f8fafc; }
|
||||||
|
.rw-table tfoot td { padding:8px 13px; }
|
||||||
|
|
||||||
|
/* Tags */
|
||||||
|
.rw-kelas-tag { background:#e8f7f2; color:var(--primary-dark); padding:2px 7px; border-radius:6px; font-size:.72rem; font-weight:600; margin-right:2px; display:inline-block; }
|
||||||
|
.rw-umum-tag { background:#f1f5f9; color:#64748b; padding:2px 7px; border-radius:6px; font-size:.72rem; font-weight:600; display:inline-block; }
|
||||||
|
.rw-kat-tag { background:#dbeafe; color:#1e40af; padding:2px 7px; border-radius:6px; font-size:.72rem; font-weight:600; display:inline-block; }
|
||||||
|
|
||||||
|
/* Mini progress */
|
||||||
|
.rw-mini-prog { height:6px; background:#f1f5f9; border-radius:3px; overflow:hidden; display:flex; min-width:70px; }
|
||||||
|
|
||||||
|
/* Button table */
|
||||||
|
.btn-tbl-detail { padding:5px 11px; background:var(--primary-color); color:#fff; border:none; border-radius:6px;
|
||||||
|
font-size:0.76rem; font-weight:600; text-decoration:none; display:inline-flex; align-items:center; gap:4px; white-space:nowrap; }
|
||||||
|
.btn-tbl-detail:hover { background:#059669; color:#fff; }
|
||||||
|
|
||||||
|
/* Cards (hari_ini) */
|
||||||
|
.rw-card { background:#fff; border-radius:12px; box-shadow:0 2px 10px rgba(0,0,0,.06); border:1px solid #f0f0f0; overflow:hidden; margin-bottom:10px; }
|
||||||
|
.rw-card:hover { box-shadow:0 4px 18px rgba(0,0,0,.1); }
|
||||||
|
.rw-card-head { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; padding:14px 18px 10px; border-bottom:1px solid #f1f5f9; flex-wrap:wrap; }
|
||||||
|
.rw-card-title { font-size:1rem; font-weight:700; color:var(--primary-dark); margin:0 0 5px; display:flex; align-items:center; gap:8px; }
|
||||||
|
.rw-card-meta { display:flex; gap:10px; flex-wrap:wrap; font-size:.8rem; color:#64748b; align-items:center; }
|
||||||
|
.rw-card-meta span{ display:inline-flex; align-items:center; gap:4px; }
|
||||||
|
.rw-status { padding:4px 12px; border-radius:20px; font-size:.76rem; font-weight:700; white-space:nowrap; flex-shrink:0; display:inline-flex; align-items:center; gap:5px; }
|
||||||
|
.rw-status.belum { background:#f1f5f9; color:#64748b; }
|
||||||
|
.rw-status.selesai{ background:#d1fae5; color:#065f46; }
|
||||||
|
.rw-status.brlgs { background:#fef9c3; color:#854d0e; }
|
||||||
|
.rw-card-body { padding:10px 18px 14px; }
|
||||||
|
.rw-stats-row { display:flex; gap:6px; flex-wrap:wrap; align-items:center; margin-bottom:10px; }
|
||||||
|
.rw-chip { padding:4px 10px; border-radius:10px; font-size:.76rem; font-weight:700; display:inline-flex; align-items:center; gap:4px; }
|
||||||
|
.rw-chip.hadir { background:#d1fae5; color:#065f46; }
|
||||||
|
.rw-chip.terlambat{ background:#fff3e0; color:#e65100; }
|
||||||
|
.rw-chip.izin { background:#fef3c7; color:#92400e; }
|
||||||
|
.rw-chip.sakit { background:#dbeafe; color:#1e40af; }
|
||||||
|
.rw-chip.alpa { background:#fee2e2; color:#991b1b; }
|
||||||
|
.rw-chip.pulang { background:#f3e8ff; color:#6b21a8; }
|
||||||
|
.rw-chip.none { background:#f1f5f9; color:#94a3b8; }
|
||||||
|
.rw-progress-wrap { height:8px; background:#f1f5f9; border-radius:4px; overflow:hidden; display:flex; margin-bottom:6px; }
|
||||||
|
.rw-prog-hadir { background:#22c55e; }
|
||||||
|
.rw-prog-terlambat{ background:#FF9800; }
|
||||||
|
.rw-prog-izin { background:#f59e0b; }
|
||||||
|
.rw-prog-sakit { background:#3b82f6; }
|
||||||
|
.rw-prog-alpa { background:#ef4444; }
|
||||||
|
.rw-prog-pulang { background:#a855f7; }
|
||||||
|
.rw-prog-belum { background:#e2e8f0; }
|
||||||
|
.rw-card-foot { display:flex; align-items:center; justify-content:space-between; padding:8px 18px; background:#fafafa; border-top:1px solid #f1f5f9; flex-wrap:wrap; gap:8px; }
|
||||||
|
.rw-total-txt { font-size:.78rem; color:#94a3b8; }
|
||||||
|
.rw-total-txt strong { color:#374151; }
|
||||||
|
.btn-rw-detail { padding:6px 16px; background:var(--primary-color); color:#fff; border:none; border-radius:7px; font-size:.82rem; font-weight:600; text-decoration:none; display:inline-flex; align-items:center; gap:5px; }
|
||||||
|
.btn-rw-detail:hover { background:#059669; color:#fff; }
|
||||||
|
|
||||||
|
/* Empty */
|
||||||
|
.rw-empty { text-align:center; padding:48px 20px; background:#fff; border-radius:12px; box-shadow:0 2px 10px rgba(0,0,0,.06); }
|
||||||
|
.rw-empty i { font-size:3rem; color:#cbd5e1; display:block; margin-bottom:12px; }
|
||||||
|
.rw-empty h3 { margin:0 0 6px; color:var(--primary-dark); }
|
||||||
|
.rw-empty p { margin:0; color:var(--text-light); font-size:.88rem; }
|
||||||
|
|
||||||
|
@media(max-width:640px) {
|
||||||
|
.rw-filter-row { flex-direction:column; }
|
||||||
|
.rw-fg { width:100%; }
|
||||||
|
.rw-fg .form-control { width:100%; }
|
||||||
|
.btn-rw-apply,.btn-rw-reset { width:100%; justify-content:center; }
|
||||||
|
.rw-kpi-strip { grid-template-columns:repeat(3,1fr); }
|
||||||
|
.dh-count { display:none; }
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
// Default: minggu ini
|
$mode = $mode ?? 'hari_ini';
|
||||||
$defaultDari = now()->startOfWeek(\Carbon\Carbon::MONDAY)->format('Y-m-d');
|
$dari = $dari ?? now()->format('Y-m-d');
|
||||||
$defaultSampai = now()->endOfWeek(\Carbon\Carbon::SUNDAY)->format('Y-m-d');
|
$sampai = $sampai ?? now()->format('Y-m-d');
|
||||||
|
$tanggal = $tanggal ?? now()->format('Y-m-d');
|
||||||
|
$kategoriId = $kategoriId ?? '';
|
||||||
|
$passParams = ['mode' => $mode, 'dari' => $dari, 'sampai' => $sampai, 'tanggal' => $tanggal];
|
||||||
|
|
||||||
$activeDari = request('tanggal_dari', $defaultDari);
|
$totalAbsensi = $summary['total_absensi'] ?? 0;
|
||||||
$activeSampai = request('tanggal_sampai', $defaultSampai);
|
$totalHadir = $summary['hadir'] ?? 0;
|
||||||
$activeKategori = request('kategori_id', '');
|
$pctHadirGlbl = $totalAbsensi > 0 ? round($totalHadir / $totalAbsensi * 100, 1) : 0;
|
||||||
$activeBulan = request('bulan', '');
|
|
||||||
|
|
||||||
// Label periode
|
|
||||||
if ($activeBulan) {
|
|
||||||
$periodeLabel = 'Bulan ' . \Carbon\Carbon::parse($activeBulan . '-01')->locale('id')->isoFormat('MMMM Y');
|
|
||||||
} else {
|
|
||||||
$periodeLabel = \Carbon\Carbon::parse($activeDari)->locale('id')->isoFormat('D MMM Y')
|
|
||||||
. ' – '
|
|
||||||
. \Carbon\Carbon::parse($activeSampai)->locale('id')->isoFormat('D MMM Y');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cek shortcut aktif
|
|
||||||
$isMingguIni = !$activeBulan
|
|
||||||
&& $activeDari == $defaultDari
|
|
||||||
&& $activeSampai == $defaultSampai;
|
|
||||||
|
|
||||||
$isBulanIni = !$activeBulan
|
|
||||||
&& $activeDari == now()->startOfMonth()->format('Y-m-d')
|
|
||||||
&& $activeSampai == now()->endOfMonth()->format('Y-m-d');
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-history"></i> Riwayat Kegiatan & Absensi</h2>
|
<div class="rw-header">
|
||||||
|
<h2><i class="fas fa-history"></i> Riwayat Kegiatan & Absensi</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if(session('success')): ?>
|
|
||||||
<div class="alert alert-success">
|
|
||||||
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
|
|
||||||
|
|
||||||
</div>
|
<div class="rw-filter">
|
||||||
<?php endif; ?>
|
<div class="rw-mode-tabs">
|
||||||
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['mode'=>'hari_ini','tanggal'=>$tanggal])); ?>"
|
||||||
|
class="rw-tab <?php echo e($mode==='hari_ini'?'active':''); ?>">
|
||||||
<div class="filter-box">
|
<i class="fas fa-calendar-day"></i> Hari Ini
|
||||||
|
</a>
|
||||||
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['mode'=>'minggu_ini'])); ?>"
|
||||||
<div class="period-tabs">
|
class="rw-tab <?php echo e($mode==='minggu_ini'?'active':''); ?>">
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['tanggal_dari' => $defaultDari, 'tanggal_sampai' => $defaultSampai, 'kategori_id' => $activeKategori])); ?>"
|
|
||||||
class="period-tab <?php echo e($isMingguIni ? 'active' : ''); ?>">
|
|
||||||
<i class="fas fa-calendar-week"></i> Minggu Ini
|
<i class="fas fa-calendar-week"></i> Minggu Ini
|
||||||
</a>
|
</a>
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['tanggal_dari' => now()->startOfMonth()->format('Y-m-d'), 'tanggal_sampai' => now()->endOfMonth()->format('Y-m-d'), 'kategori_id' => $activeKategori])); ?>"
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['mode'=>'custom','dari'=>$dari,'sampai'=>$sampai])); ?>"
|
||||||
class="period-tab <?php echo e($isBulanIni ? 'active' : ''); ?>">
|
class="rw-tab <?php echo e($mode==='custom'?'active':''); ?>">
|
||||||
<i class="fas fa-calendar-alt"></i> Bulan Ini
|
<i class="fas fa-sliders-h"></i> Rentang Tanggal
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index')); ?>"
|
|
||||||
class="period-tab <?php echo e(!$isMingguIni && !$isBulanIni ? 'active' : ''); ?>"
|
|
||||||
style="<?php echo e(!$isMingguIni && !$isBulanIni ? '' : 'display:none'); ?>">
|
|
||||||
<i class="fas fa-filter"></i> Custom
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form method="GET">
|
<form method="GET" action="<?php echo e(route('admin.riwayat-kegiatan.index')); ?>">
|
||||||
<div class="filter-grid">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="kategori_id">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($activeKategori == $k->kategori_id ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($k->nama_kategori); ?>
|
|
||||||
|
|
||||||
</option>
|
<?php if($mode === 'hari_ini'): ?>
|
||||||
|
<input type="hidden" name="mode" value="hari_ini">
|
||||||
|
<div class="rw-filter-row">
|
||||||
|
<div class="rw-fg">
|
||||||
|
<label><i class="fas fa-calendar-alt"></i> Tanggal</label>
|
||||||
|
<input type="date" name="tanggal" class="form-control" value="<?php echo e($tanggal); ?>" style="max-width:180px;">
|
||||||
|
</div>
|
||||||
|
<div class="rw-fg">
|
||||||
|
<label><i class="fas fa-tag"></i> Kategori</label>
|
||||||
|
<select name="kategori_id" class="form-control" style="max-width:200px;">
|
||||||
|
<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($kategoriId==$k->kategori_id?'selected':''); ?>><?php echo e($k->nama_kategori); ?></option>
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<button type="submit" class="btn-rw-apply"><i class="fas fa-search"></i> Tampilkan</button>
|
||||||
<label for="tanggal_dari">Tanggal Dari</label>
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.index')); ?>" class="btn-rw-reset"><i class="fas fa-undo"></i> Reset</a>
|
||||||
<input type="date" name="tanggal_dari" id="tanggal_dari" class="form-control" value="<?php echo e($activeDari); ?>">
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<label for="tanggal_sampai">Tanggal Sampai</label>
|
<?php elseif($mode === 'minggu_ini'): ?>
|
||||||
<input type="date" name="tanggal_sampai" id="tanggal_sampai" class="form-control" value="<?php echo e($activeSampai); ?>">
|
<input type="hidden" name="mode" value="minggu_ini">
|
||||||
|
<div class="rw-filter-row">
|
||||||
|
<div class="rw-fg">
|
||||||
|
<label><i class="fas fa-tag"></i> Kategori</label>
|
||||||
|
<select name="kategori_id" class="form-control" style="max-width:200px;">
|
||||||
|
<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($kategoriId==$k->kategori_id?'selected':''); ?>><?php echo e($k->nama_kategori); ?></option>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<button type="submit" class="btn-rw-apply"><i class="fas fa-search"></i> Tampilkan</button>
|
||||||
<label for="bulan">Atau Pilih Bulan</label>
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['mode'=>'minggu_ini'])); ?>" class="btn-rw-reset"><i class="fas fa-undo"></i> Reset</a>
|
||||||
<input type="month" name="bulan" id="bulan" class="form-control" value="<?php echo e($activeBulan); ?>">
|
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; align-items: flex-end; gap: 10px;">
|
|
||||||
<button type="submit" class="btn-filter" style="flex: 1;">
|
<?php else: ?>
|
||||||
<i class="fas fa-filter"></i> Filter
|
<input type="hidden" name="mode" value="custom">
|
||||||
</button>
|
<div class="rw-filter-row">
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index')); ?>" class="btn-reset" title="Reset ke minggu ini">
|
<div class="rw-fg">
|
||||||
<i class="fas fa-undo"></i>
|
<label><i class="fas fa-calendar-alt"></i> Dari Tanggal</label>
|
||||||
</a>
|
<input type="date" name="dari" class="form-control" value="<?php echo e($dari); ?>" style="max-width:180px;" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="rw-fg">
|
||||||
|
<label><i class="fas fa-calendar-alt"></i> Sampai Tanggal</label>
|
||||||
|
<input type="date" name="sampai" class="form-control" value="<?php echo e($sampai); ?>" style="max-width:180px;" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="rw-fg">
|
||||||
|
<label><i class="fas fa-tag"></i> Kategori</label>
|
||||||
|
<select name="kategori_id" class="form-control" style="max-width:200px;">
|
||||||
|
<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($kategoriId==$k->kategori_id?'selected':''); ?>><?php echo e($k->nama_kategori); ?></option>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn-rw-apply"><i class="fas fa-search"></i> Tampilkan</button>
|
||||||
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['mode'=>'custom'])); ?>" class="btn-rw-reset"><i class="fas fa-undo"></i> Reset</a>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<p class="periode-info">
|
<div class="rw-periode">
|
||||||
<i class="fas fa-calendar-check"></i> Menampilkan kegiatan periode: <strong><?php echo e($periodeLabel); ?></strong>
|
<i class="fas fa-calendar-check"></i>
|
||||||
|
Menampilkan: <strong><?php echo e($periodeLabel); ?></strong>
|
||||||
|
<?php if($mode !== 'hari_ini' && ($summary['jumlah_hari'] ?? 0) > 0): ?>
|
||||||
|
<span style="color:#94a3b8;">·</span>
|
||||||
|
<strong style="color:var(--primary-color);"><?php echo e($summary['jumlah_hari']); ?></strong> hari aktif
|
||||||
|
<span style="color:#94a3b8;">·</span>
|
||||||
|
<strong style="color:var(--primary-color);"><?php echo e($summary['jumlah_kegiatan']); ?></strong> sesi
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<?php if($totalAbsensi > 0): ?>
|
||||||
|
<div class="rw-kpi-strip">
|
||||||
|
<div class="rw-kpi">
|
||||||
|
<div class="rw-kpi-val" style="color:#065f46;"><?php echo e($summary['hadir']); ?></div>
|
||||||
|
<div class="rw-kpi-lbl"><i class="fas fa-check" style="color:#22c55e;"></i> Hadir Efektif</div>
|
||||||
|
<?php if($summary['terlambat'] > 0): ?>
|
||||||
|
<div class="rw-kpi-sub">+<?php echo e($summary['terlambat']); ?> terlambat</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<div class="rw-kpi">
|
||||||
|
<div class="rw-kpi-val" style="color:#e65100;"><?php echo e($summary['terlambat']); ?></div>
|
||||||
|
<div class="rw-kpi-lbl"><i class="fas fa-clock" style="color:#FF9800;"></i> Terlambat</div>
|
||||||
|
</div>
|
||||||
|
<div class="rw-kpi">
|
||||||
|
<div class="rw-kpi-val" style="color:#92400e;"><?php echo e($summary['izin']); ?></div>
|
||||||
|
<div class="rw-kpi-lbl"><i class="fas fa-envelope" style="color:#f59e0b;"></i> Izin</div>
|
||||||
|
</div>
|
||||||
|
<div class="rw-kpi">
|
||||||
|
<div class="rw-kpi-val" style="color:#1e40af;"><?php echo e($summary['sakit']); ?></div>
|
||||||
|
<div class="rw-kpi-lbl"><i class="fas fa-heartbeat" style="color:#3b82f6;"></i> Sakit</div>
|
||||||
|
</div>
|
||||||
|
<div class="rw-kpi">
|
||||||
|
<div class="rw-kpi-val" style="color:#991b1b;"><?php echo e($summary['alpa']); ?></div>
|
||||||
|
<div class="rw-kpi-lbl"><i class="fas fa-times-circle" style="color:#ef4444;"></i> Alpa</div>
|
||||||
|
</div>
|
||||||
|
<div class="rw-kpi" style="border-top:2px solid var(--primary-color);">
|
||||||
|
<div class="rw-kpi-val" style="color:<?php echo e($pctHadirGlbl>=85?'#059669':($pctHadirGlbl>=70?'#d97706':'#dc2626')); ?>;"><?php echo e($pctHadirGlbl); ?>%</div>
|
||||||
|
<div class="rw-kpi-lbl"><i class="fas fa-chart-pie" style="color:var(--primary-color);"></i> Rata-rata</div>
|
||||||
|
<div class="rw-kpi-sub">dari <?php echo e($totalAbsensi); ?> tercatat
|
||||||
|
<?php if($mode !== 'hari_ini' && ($summary['jumlah_kegiatan']??0) > 0): ?>
|
||||||
|
· <?php echo e($summary['jumlah_kegiatan']); ?> sesi
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
||||||
|
<?php if($mode === 'hari_ini'): ?>
|
||||||
|
|
||||||
|
<?php if($kegiatans && $kegiatans->count() > 0): ?>
|
||||||
|
<?php $__currentLoopData = $kegiatans; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kegiatan): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<?php echo $__env->make('admin.kegiatan.riwayat._card', ['kegiatan' => $kegiatan, 'passParams' => $passParams], \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<div style="margin-top:16px;"><?php echo $kegiatans->appends(request()->query())->links('pagination::simple-bootstrap-4'); ?></div>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="rw-empty">
|
||||||
|
<i class="fas fa-calendar-times"></i>
|
||||||
|
<h3>Tidak Ada Kegiatan</h3>
|
||||||
|
<p>Tidak ada kegiatan pada <strong><?php echo e($periodeLabel); ?></strong>.</p>
|
||||||
|
<p style="margin-top:8px; font-size:.82rem;">
|
||||||
|
Coba tanggal lain atau lihat <a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['mode'=>'minggu_ini'])); ?>" style="color:var(--primary-color);">riwayat minggu ini</a>.
|
||||||
</p>
|
</p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if($kegiatans->count() > 0): ?>
|
|
||||||
|
|
||||||
|
<?php else: ?>
|
||||||
|
|
||||||
|
<?php if($kegiatanPerTanggal && $kegiatanPerTanggal->count() > 0): ?>
|
||||||
|
|
||||||
|
<?php $__currentLoopData = $kegiatanPerTanggal; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $tgl => $items): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
<?php
|
<?php
|
||||||
$hariOrder = ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu', 'Ahad'];
|
$tglCarbon = \Carbon\Carbon::parse($tgl);
|
||||||
$grouped = $kegiatans->getCollection()->groupBy('hari');
|
$isHariIni = ($tgl === now()->format('Y-m-d'));
|
||||||
|
$hariLabel = $tglCarbon->locale('id')->isoFormat('dddd');
|
||||||
|
$tglLabel = $tglCarbon->locale('id')->isoFormat('D MMMM Y');
|
||||||
|
$tglHadir = $items->sum('hadir') + $items->sum('terlambat');
|
||||||
|
$tglTotal = $items->sum('total_absensi');
|
||||||
|
$tglPct = $tglTotal > 0 ? round($tglHadir / $tglTotal * 100) : 0;
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<?php $__currentLoopData = $hariOrder; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $hari): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
<div class="rw-date-block">
|
||||||
<?php if($grouped->has($hari)): ?>
|
<div class="rw-date-header <?php echo e($isHariIni ? 'rw-date-today' : ''); ?>">
|
||||||
<?php $items = $grouped[$hari]; ?>
|
<span class="dh-date"><?php echo e($tglLabel); ?></span>
|
||||||
<div class="day-group">
|
<span class="dh-hari"><?php echo e($hariLabel); ?><?php echo e($isHariIni ? ' · Hari Ini' : ''); ?></span>
|
||||||
<div class="day-header" onclick="toggleDay(this)">
|
<span class="dh-count">
|
||||||
<div class="day-title">
|
<?php echo e($items->count()); ?> kegiatan
|
||||||
<i class="fas fa-calendar-day"></i> <?php echo e($hari); ?>
|
·
|
||||||
|
<strong><?php echo e($tglHadir); ?></strong>/<?php echo e($tglTotal); ?> hadir
|
||||||
</div>
|
<?php if($tglTotal > 0): ?>
|
||||||
<div class="day-meta">
|
<span style="background:rgba(255,255,255,.15); padding:1px 7px; border-radius:8px; margin-left:4px;"><?php echo e($tglPct); ?>%</span>
|
||||||
<span class="day-count"><?php echo e($items->count()); ?> kegiatan</span>
|
<?php endif; ?>
|
||||||
<i class="fas fa-chevron-down toggle-icon"></i>
|
</span>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="day-body">
|
<div class="rw-tbl-wrap">
|
||||||
<table>
|
<table class="rw-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 40px;">No</th>
|
<th style="width:36px; text-align:center;">No</th>
|
||||||
<th>Nama Kegiatan</th>
|
<th>Nama Kegiatan</th>
|
||||||
<th style="width: 110px;">Waktu</th>
|
<th style="width:95px;">Waktu</th>
|
||||||
<th>Kelas</th>
|
<th style="width:110px;">Kategori</th>
|
||||||
<th style="width: 130px;">Kategori</th>
|
<th style="width:140px;">Kelas</th>
|
||||||
<th style="width: 250px; text-align: center;">Statistik Absensi</th>
|
<th style="width:58px; text-align:center; color:#22c55e;" title="Hadir efektif (termasuk terlambat)">Hadir</th>
|
||||||
<th style="width: 90px; text-align: center;">Aksi</th>
|
<th style="width:52px; text-align:center; color:#FF9800;" title="Terlambat">Tlbt</th>
|
||||||
|
<th style="width:48px; text-align:center; color:#f59e0b;" title="Izin">Izin</th>
|
||||||
|
<th style="width:48px; text-align:center; color:#3b82f6;" title="Sakit">Skt</th>
|
||||||
|
<th style="width:48px; text-align:center; color:#ef4444;" title="Alpa">Alpa</th>
|
||||||
|
<th style="width:90px;">Progress</th>
|
||||||
|
<th style="width:88px; text-align:center;">Aksi</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php $__currentLoopData = $items; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $i => $kegiatan): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
<?php $__currentLoopData = $items; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $idx => $kegiatan): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<?php
|
||||||
|
$hadirEfektif = $kegiatan->hadir + $kegiatan->terlambat;
|
||||||
|
$totalKeg = $kegiatan->total_absensi;
|
||||||
|
$kelasNames = $kegiatan->kelasKegiatan->pluck('nama_kelas');
|
||||||
|
$isUmum = $kelasNames->isEmpty();
|
||||||
|
?>
|
||||||
<tr>
|
<tr>
|
||||||
<td><?php echo e($i + 1); ?></td>
|
<td style="color:#94a3b8; font-size:.76rem; text-align:center;"><?php echo e($idx + 1); ?></td>
|
||||||
<td><strong><?php echo e($kegiatan->nama_kegiatan); ?></strong></td>
|
<td>
|
||||||
<td style="white-space: nowrap; color: #64748b; font-size: 0.82rem;">
|
<div style="font-weight:700; font-size:.87rem; color:var(--primary-dark);"><?php echo e($kegiatan->nama_kegiatan); ?></div>
|
||||||
<i class="fas fa-clock" style="color: var(--primary-color);"></i>
|
</td>
|
||||||
<?php echo e(date('H:i', strtotime($kegiatan->waktu_mulai))); ?>–<?php echo e(date('H:i', strtotime($kegiatan->waktu_selesai))); ?>
|
<td style="font-size:.79rem; color:#64748b; white-space:nowrap;">
|
||||||
|
<?php echo e(date('H:i', strtotime($kegiatan->waktu_mulai))); ?><br>
|
||||||
|
<span style="color:#94a3b8; font-size:.7rem;">s/d <?php echo e(date('H:i', strtotime($kegiatan->waktu_selesai))); ?></span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<?php if($kegiatan->kelasKegiatan->isEmpty()): ?>
|
<?php if($kegiatan->kategori): ?>
|
||||||
<span class="umum-tag"><i class="fas fa-globe"></i> Umum</span>
|
<span class="rw-kat-tag"><?php echo e($kegiatan->kategori->nama_kategori); ?></span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<?php if($isUmum): ?>
|
||||||
|
<span class="rw-umum-tag"><i class="fas fa-globe-asia"></i> Umum</span>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<?php $__currentLoopData = $kegiatan->kelasKegiatan->take(3); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kls): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
<?php $__currentLoopData = $kelasNames->take(2); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kn): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
<span class="kelas-tag"><?php echo e($kls->nama_kelas); ?></span>
|
<span class="rw-kelas-tag"><?php echo e($kn); ?></span>
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
<?php if($kegiatan->kelasKegiatan->count() > 3): ?>
|
<?php if($kelasNames->count() > 2): ?>
|
||||||
<span class="umum-tag">+<?php echo e($kegiatan->kelasKegiatan->count() - 3); ?></span>
|
<span class="rw-umum-tag">+<?php echo e($kelasNames->count()-2); ?></span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
|
<td style="text-align:center; font-weight:700; color:#065f46;"><?php echo e($hadirEfektif ?: '–'); ?></td>
|
||||||
|
<td style="text-align:center; color:#e65100;"><?php echo e($kegiatan->terlambat ?: '–'); ?></td>
|
||||||
|
<td style="text-align:center; color:#92400e;"><?php echo e($kegiatan->izin ?: '–'); ?></td>
|
||||||
|
<td style="text-align:center; color:#1e40af;"><?php echo e($kegiatan->sakit ?: '–'); ?></td>
|
||||||
|
<td style="text-align:center; color:#991b1b; font-weight:700;"><?php echo e($kegiatan->alpa ?: '–'); ?></td>
|
||||||
<td>
|
<td>
|
||||||
<span class="badge badge-success"><?php echo e($kegiatan->kategori->nama_kategori); ?></span>
|
<?php if($totalKeg > 0): ?>
|
||||||
</td>
|
<?php
|
||||||
<td style="text-align: center;">
|
$segs = [
|
||||||
<?php if($kegiatan->total_absensi > 0): ?>
|
['w'=>round($kegiatan->hadir/$totalKeg*100), 'c'=>'#22c55e'],
|
||||||
<div class="stat-chips" style="justify-content: center;">
|
['w'=>round($kegiatan->terlambat/$totalKeg*100), 'c'=>'#FF9800'],
|
||||||
<?php if($kegiatan->hadir > 0): ?>
|
['w'=>round($kegiatan->izin/$totalKeg*100), 'c'=>'#f59e0b'],
|
||||||
<span class="chip chip-hadir"><i class="fas fa-check"></i> <?php echo e($kegiatan->hadir); ?></span>
|
['w'=>round($kegiatan->sakit/$totalKeg*100), 'c'=>'#3b82f6'],
|
||||||
<?php endif; ?>
|
['w'=>round($kegiatan->alpa/$totalKeg*100), 'c'=>'#ef4444'],
|
||||||
<?php if(($kegiatan->terlambat ?? 0) > 0): ?>
|
];
|
||||||
<span class="chip chip-terlambat"><i class="fas fa-clock"></i> <?php echo e($kegiatan->terlambat); ?></span>
|
?>
|
||||||
<?php endif; ?>
|
<div class="rw-mini-prog">
|
||||||
<?php if($kegiatan->izin > 0): ?>
|
<?php $__currentLoopData = $segs; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $s): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
<span class="chip chip-izin"><i class="fas fa-envelope"></i> <?php echo e($kegiatan->izin); ?></span>
|
<?php if($s['w'] > 0): ?><div style="width:<?php echo e($s['w']); ?>%;background:<?php echo e($s['c']); ?>;"></div><?php endif; ?>
|
||||||
<?php endif; ?>
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
<?php if($kegiatan->sakit > 0): ?>
|
|
||||||
<span class="chip chip-sakit"><i class="fas fa-heartbeat"></i> <?php echo e($kegiatan->sakit); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($kegiatan->alpa > 0): ?>
|
|
||||||
<span class="chip chip-alpa"><i class="fas fa-times"></i> <?php echo e($kegiatan->alpa); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if(($kegiatan->pulang ?? 0) > 0): ?>
|
|
||||||
<span class="chip chip-pulang"><i class="fas fa-home"></i> <?php echo e($kegiatan->pulang); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<div style="font-size: 0.74rem; color: #94a3b8; margin-top: 3px;">
|
|
||||||
Total: <?php echo e($kegiatan->total_absensi); ?>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<div style="font-size:.67rem; color:#94a3b8; margin-top:2px;"><?php echo e($hadirEfektif); ?>/<?php echo e($totalKeg); ?></div>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<span class="chip chip-none">Belum ada data</span>
|
<span style="color:#cbd5e1; font-size:.76rem;">–</span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:center;">
|
<td style="text-align:center;">
|
||||||
|
<a href="<?php echo e(route('admin.riwayat-kegiatan.show', $kegiatan->id)); ?>?mode=hari_ini&tanggal=<?php echo e($tgl); ?>&dari=<?php echo e($tgl); ?>&sampai=<?php echo e($tgl); ?>"
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.show', $kegiatan->id)); ?>?tanggal_dari=<?php echo e($activeDari); ?>&tanggal_sampai=<?php echo e($activeSampai); ?>"
|
class="btn-tbl-detail">
|
||||||
class="btn-detail">
|
<i class="fas fa-users"></i> Santri
|
||||||
<i class="fas fa-eye"></i> Detail
|
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
<?php if($items->count() > 1): ?>
|
||||||
|
<tfoot>
|
||||||
|
<tr style="background:#f0fdf4; border-top:1.5px solid #bbf7d0;">
|
||||||
|
<td colspan="5" style="font-size:.78rem; font-weight:700; color:#065f46; padding:8px 13px;">
|
||||||
|
<i class="fas fa-layer-group"></i> Total <?php echo e($tglLabel); ?>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td style="text-align:center; font-weight:800; color:#065f46;"><?php echo e($tglHadir); ?></td>
|
||||||
|
<td style="text-align:center; font-weight:700; color:#e65100;"><?php echo e($items->sum('terlambat')); ?></td>
|
||||||
|
<td style="text-align:center; font-weight:700; color:#92400e;"><?php echo e($items->sum('izin')); ?></td>
|
||||||
|
<td style="text-align:center; font-weight:700; color:#1e40af;"><?php echo e($items->sum('sakit')); ?></td>
|
||||||
|
<td style="text-align:center; font-weight:700; color:#991b1b;"><?php echo e($items->sum('alpa')); ?></td>
|
||||||
|
<td colspan="2" style="font-size:.75rem; color:#94a3b8; padding:8px 13px;">
|
||||||
|
<?php echo e($tglTotal); ?> tercatat · <?php echo e($tglPct); ?>% hadir
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
<?php endif; ?>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
|
||||||
<div class="pagination" style="margin-top: 16px;">
|
|
||||||
<?php echo $kegiatans->appends(request()->query())->links('pagination::simple-bootstrap-4'); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div class="empty-state">
|
<div class="rw-empty">
|
||||||
<i class="fas fa-inbox"></i>
|
<i class="fas fa-calendar-times"></i>
|
||||||
<h3>Tidak Ada Data</h3>
|
<h3>Tidak Ada Data Absensi</h3>
|
||||||
<p>Tidak ada kegiatan pada periode <strong><?php echo e($periodeLabel); ?></strong>.</p>
|
<p>Tidak ada absensi yang tercatat pada periode <strong><?php echo e($periodeLabel); ?></strong>.</p>
|
||||||
|
<?php if($mode === 'custom'): ?>
|
||||||
|
<p style="margin-top:8px; font-size:.82rem; color:#6b7280;">
|
||||||
|
Pastikan rentang tanggal sudah benar dan ada data absensi di periode tersebut.
|
||||||
|
</p>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<script>
|
<?php endif; ?>
|
||||||
function toggleDay(header) {
|
|
||||||
var body = header.nextElementSibling;
|
|
||||||
var icon = header.querySelector('.toggle-icon');
|
|
||||||
if (body.style.display === 'none') {
|
|
||||||
body.style.display = 'block';
|
|
||||||
icon.classList.remove('collapsed');
|
|
||||||
} else {
|
|
||||||
body.style.display = 'none';
|
|
||||||
icon.classList.add('collapsed');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<?php $__env->stopSection(); ?>
|
<?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**/ ?>
|
<?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**/ ?>
|
||||||
|
|
@ -1,632 +0,0 @@
|
||||||
<?php $__env->startSection('title', 'Kegiatan & Absensi'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
--g: #1a7a5e;
|
|
||||||
--m: #2bbd8e;
|
|
||||||
--sf: #e8f7f2;
|
|
||||||
--gd: #f5a623;
|
|
||||||
--rd: #e53e3e;
|
|
||||||
--bl: #3b82f6;
|
|
||||||
--tx: #1a2332;
|
|
||||||
--mu: #6b7280;
|
|
||||||
--br: #e2e8f0;
|
|
||||||
--wh: #ffffff;
|
|
||||||
--bg: #f8fafb;
|
|
||||||
--ra: 14px;
|
|
||||||
--sh: 0 4px 20px rgba(0,0,0,0.07);
|
|
||||||
--shl: 0 8px 40px rgba(0,0,0,0.12);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── HERO ── */
|
|
||||||
.kg-hero {
|
|
||||||
background: linear-gradient(135deg, #0d3b2e 0%, #1a7a5e 55%, #2bbd8e 100%);
|
|
||||||
border-radius: var(--ra);
|
|
||||||
padding: 26px 28px 22px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
.kg-hero::before { content:''; position:absolute; top:-50px; right:-50px; width:180px; height:180px; border-radius:50%; background:rgba(255,255,255,0.05); pointer-events:none; }
|
|
||||||
.kg-hero::after { content:''; position:absolute; bottom:-40px; left:38%; width:140px; height:140px; border-radius:50%; background:rgba(255,255,255,0.04); pointer-events:none; }
|
|
||||||
.kg-hero-row { display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:10px; position:relative; z-index:1; }
|
|
||||||
.kg-hero-title { font-size:1.25rem; font-weight:800; margin:0 0 3px; }
|
|
||||||
.kg-hero-sub { font-size:0.85rem; opacity:0.8; margin:0; }
|
|
||||||
.kg-hero-right { text-align:right; }
|
|
||||||
.kg-hero-day { font-size:1rem; font-weight:700; opacity:0.9; }
|
|
||||||
.kg-hero-date { font-size:0.8rem; opacity:0.7; }
|
|
||||||
.kg-hero-badges { display:flex; gap:7px; flex-wrap:wrap; margin-top:14px; position:relative; z-index:1; }
|
|
||||||
.kg-badge {
|
|
||||||
background:rgba(255,255,255,0.14); border:1px solid rgba(255,255,255,0.2);
|
|
||||||
padding:4px 11px; border-radius:20px; font-size:0.79rem; font-weight:600;
|
|
||||||
display:inline-flex; align-items:center; gap:5px;
|
|
||||||
}
|
|
||||||
.kg-badge.fire { background:linear-gradient(135deg,#f59e0b,#f97316); border:none; }
|
|
||||||
|
|
||||||
/* ── KPI CARDS ── */
|
|
||||||
.kg-kpi-row { display:grid; grid-template-columns:repeat(5,1fr); gap:10px; margin-bottom:16px; }
|
|
||||||
.kg-kpi { background:white; border-radius:12px; padding:14px 12px; box-shadow:var(--sh); text-align:center; border-top:3px solid transparent; transition:transform 0.18s,box-shadow 0.18s; }
|
|
||||||
.kg-kpi:hover { transform:translateY(-3px); box-shadow:var(--shl); }
|
|
||||||
.kg-kpi.c-green { border-top-color:#2bbd8e; }
|
|
||||||
.kg-kpi.c-blue { border-top-color:#3b82f6; }
|
|
||||||
.kg-kpi.c-gold { border-top-color:#f5a623; }
|
|
||||||
.kg-kpi.c-orange { border-top-color:#f97316; }
|
|
||||||
.kg-kpi.c-red { border-top-color:#e53e3e; }
|
|
||||||
.kg-kpi-ic { width:36px; height:36px; border-radius:9px; display:flex; align-items:center; justify-content:center; font-size:0.9rem; margin:0 auto 7px; }
|
|
||||||
.c-green .kg-kpi-ic { background:#d1fae5; color:#059669; }
|
|
||||||
.c-blue .kg-kpi-ic { background:#dbeafe; color:#2563eb; }
|
|
||||||
.c-gold .kg-kpi-ic { background:#fef3c7; color:#d97706; }
|
|
||||||
.c-orange .kg-kpi-ic { background:#ffedd5; color:#ea580c; }
|
|
||||||
.c-red .kg-kpi-ic { background:#fee2e2; color:#dc2626; }
|
|
||||||
.kg-kpi-v { font-size:1.7rem; font-weight:800; color:var(--tx); line-height:1; margin-bottom:3px; }
|
|
||||||
.kg-kpi-l { font-size:0.73rem; color:var(--mu); font-weight:500; }
|
|
||||||
.kg-kpi-bar { margin-top:7px; height:4px; background:#f0f0f0; border-radius:2px; overflow:hidden; }
|
|
||||||
.kg-kpi-fill { height:100%; border-radius:2px; }
|
|
||||||
|
|
||||||
/* ── TABS ── */
|
|
||||||
.kg-tabs { display:flex; gap:4px; background:var(--bg); border-radius:12px; padding:5px; margin-bottom:18px; border:1px solid var(--br); overflow-x:auto; }
|
|
||||||
.kg-tab { flex:1; min-width:90px; padding:9px 14px; border:none; background:transparent; border-radius:8px; font-size:0.82rem; font-weight:600; color:var(--mu); cursor:pointer; transition:all 0.18s; display:flex; align-items:center; justify-content:center; gap:6px; white-space:nowrap; }
|
|
||||||
.kg-tab:hover { background:white; color:var(--g); }
|
|
||||||
.kg-tab.active { background:white; color:var(--g); box-shadow:0 2px 8px rgba(0,0,0,0.09); }
|
|
||||||
.kg-panel { display:none; }
|
|
||||||
.kg-panel.active { display:block; }
|
|
||||||
|
|
||||||
/* ── FILTER BAR ── */
|
|
||||||
.kg-tab-filter {
|
|
||||||
background:white; border-radius:12px; padding:12px 14px;
|
|
||||||
margin-bottom:14px; box-shadow:var(--sh);
|
|
||||||
display:flex; flex-wrap:wrap; gap:8px; align-items:flex-end;
|
|
||||||
}
|
|
||||||
.kg-fg { display:flex; flex-direction:column; gap:3px; }
|
|
||||||
.kg-fg label { font-size:0.72rem; font-weight:700; color:var(--mu); text-transform:uppercase; letter-spacing:0.4px; }
|
|
||||||
.kg-presets { display:flex; gap:4px; flex-wrap:wrap; }
|
|
||||||
.kg-preset-btn { padding:6px 12px; border:1.5px solid var(--br); border-radius:8px; background:white; font-size:0.79rem; font-weight:600; color:var(--mu); cursor:pointer; transition:all 0.15s; white-space:nowrap; }
|
|
||||||
.kg-preset-btn:hover { border-color:var(--m); color:var(--g); background:var(--sf); }
|
|
||||||
.kg-preset-btn.active { border-color:var(--g); background:var(--g); color:white; }
|
|
||||||
.kg-date-range { display:flex; align-items:center; gap:5px; }
|
|
||||||
.kg-date-range input[type=date] { padding:6px 9px; border:1.5px solid var(--br); border-radius:8px; font-size:0.8rem; color:var(--tx); background:white; }
|
|
||||||
.kg-date-range input[type=date]:focus { outline:none; border-color:var(--m); }
|
|
||||||
.kg-date-range span { color:var(--mu); font-size:0.79rem; font-weight:600; }
|
|
||||||
.kg-apply-btn { padding:7px 15px; background:var(--g); color:white; border:none; border-radius:8px; font-size:0.81rem; font-weight:700; cursor:pointer; display:inline-flex; align-items:center; gap:5px; }
|
|
||||||
.kg-apply-btn:hover { background:#155c47; }
|
|
||||||
.kg-filter-label { font-size:0.77rem; color:var(--mu); padding:5px 9px; background:var(--bg); border-radius:8px; border:1px solid var(--br); display:flex; align-items:center; gap:4px; align-self:center; }
|
|
||||||
.kg-filter-label i { color:var(--g); }
|
|
||||||
|
|
||||||
/* ── JADWAL CARDS ── */
|
|
||||||
.kg-jadwal-group { margin-bottom:14px; }
|
|
||||||
.kg-hari-label { font-size:0.77rem; font-weight:700; text-transform:uppercase; letter-spacing:0.8px; color:var(--g); padding:5px 11px; background:var(--sf); border-radius:8px; margin-bottom:8px; display:inline-flex; align-items:center; gap:5px; }
|
|
||||||
.kg-hari-label.today-label { background:var(--g); color:white; }
|
|
||||||
.kg-jadwal-card { background:white; border-radius:11px; padding:13px 15px; box-shadow:var(--sh); display:flex; align-items:center; gap:12px; border-left:4px solid var(--br); margin-bottom:7px; transition:transform 0.16s; }
|
|
||||||
.kg-jadwal-card:hover { transform:translateX(3px); }
|
|
||||||
.kg-jadwal-card.s-hadir { border-left-color:#2bbd8e; }
|
|
||||||
.kg-jadwal-card.s-terlambat { border-left-color:#f59e0b; }
|
|
||||||
.kg-jadwal-card.s-izin { border-left-color:#3b82f6; }
|
|
||||||
.kg-jadwal-card.s-sakit { border-left-color:#8b5cf6; }
|
|
||||||
.kg-jadwal-card.s-alpa { border-left-color:#e53e3e; }
|
|
||||||
.kg-jadwal-card.s-pulang { border-left-color:#0d9488; }
|
|
||||||
.kg-jadwal-card.s-belum { border-left-color:#f5a623; }
|
|
||||||
.kg-time { min-width:58px; text-align:center; }
|
|
||||||
.kg-time-main { font-size:0.93rem; font-weight:700; color:var(--g); }
|
|
||||||
.kg-time-end { font-size:0.71rem; color:var(--mu); font-weight:500; }
|
|
||||||
.kg-divider { width:1px; height:34px; background:var(--br); flex-shrink:0; }
|
|
||||||
.kg-jinfo { flex:1; min-width:0; }
|
|
||||||
.kg-jname { font-weight:700; font-size:0.89rem; color:var(--tx); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin:0 0 3px; }
|
|
||||||
.kg-jmeta { font-size:0.76rem; color:var(--mu); display:flex; gap:8px; flex-wrap:wrap; }
|
|
||||||
.kg-detail-btn {
|
|
||||||
padding:5px 11px; background:var(--g); color:white !important;
|
|
||||||
border-radius:7px; font-size:0.75rem; font-weight:600;
|
|
||||||
text-decoration:none !important; display:inline-flex;
|
|
||||||
align-items:center; gap:4px; white-space:nowrap; flex-shrink:0;
|
|
||||||
transition:background 0.15s;
|
|
||||||
}
|
|
||||||
.kg-detail-btn:hover { background:#155c47; }
|
|
||||||
|
|
||||||
/* Pill status */
|
|
||||||
.kpill { padding:3px 11px; border-radius:20px; font-size:0.75rem; font-weight:700; flex-shrink:0; }
|
|
||||||
.kpill.hadir { background:#d1fae5; color:#065f46; }
|
|
||||||
.kpill.terlambat { background:#fef3c7; color:#92400e; }
|
|
||||||
.kpill.belum { background:#fef3c7; color:#92400e; }
|
|
||||||
.kpill.izin { background:#dbeafe; color:#1e40af; }
|
|
||||||
.kpill.sakit { background:#ede9fe; color:#5b21b6; }
|
|
||||||
.kpill.alpa { background:#fee2e2; color:#991b1b; }
|
|
||||||
.kpill.pulang { background:#ccfbf1; color:#0f766e; }
|
|
||||||
|
|
||||||
/* ── STATISTIK LAYOUT ── */
|
|
||||||
.kg-stat-grid { display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-bottom:14px; }
|
|
||||||
.kg-chart-box { background:white; border-radius:12px; padding:18px; box-shadow:var(--sh); }
|
|
||||||
.kg-chart-title { font-size:0.86rem; font-weight:700; color:var(--tx); margin-bottom:14px; display:flex; align-items:center; gap:6px; }
|
|
||||||
|
|
||||||
/* ── RECENT ABSENSI ── */
|
|
||||||
.kg-recent-list { display:flex; flex-direction:column; gap:6px; }
|
|
||||||
.kg-recent-item {
|
|
||||||
display:flex; align-items:center; gap:11px;
|
|
||||||
background:white; border-radius:10px; padding:10px 13px;
|
|
||||||
box-shadow:var(--sh); border-left:3px solid transparent;
|
|
||||||
transition:transform 0.15s;
|
|
||||||
}
|
|
||||||
.kg-recent-item:hover { transform:translateX(3px); }
|
|
||||||
.kg-recent-item.s-hadir { border-left-color:#2bbd8e; }
|
|
||||||
.kg-recent-item.s-terlambat { border-left-color:#f59e0b; }
|
|
||||||
.kg-recent-item.s-izin { border-left-color:#3b82f6; }
|
|
||||||
.kg-recent-item.s-sakit { border-left-color:#8b5cf6; }
|
|
||||||
.kg-recent-item.s-alpa { border-left-color:#e53e3e; }
|
|
||||||
.kg-recent-item.s-pulang { border-left-color:#0d9488; }
|
|
||||||
.kg-recent-ic {
|
|
||||||
width:32px; height:32px; border-radius:8px; flex-shrink:0;
|
|
||||||
display:flex; align-items:center; justify-content:center; font-size:0.82rem;
|
|
||||||
}
|
|
||||||
.s-hadir .kg-recent-ic { background:#d1fae5; color:#059669; }
|
|
||||||
.s-terlambat .kg-recent-ic { background:#fef3c7; color:#d97706; }
|
|
||||||
.s-izin .kg-recent-ic { background:#dbeafe; color:#2563eb; }
|
|
||||||
.s-sakit .kg-recent-ic { background:#ede9fe; color:#7c3aed; }
|
|
||||||
.s-alpa .kg-recent-ic { background:#fee2e2; color:#dc2626; }
|
|
||||||
.s-pulang .kg-recent-ic { background:#ccfbf1; color:#0f766e; }
|
|
||||||
.kg-recent-info { flex:1; min-width:0; }
|
|
||||||
.kg-recent-name { font-weight:700; font-size:0.84rem; color:var(--tx); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
|
||||||
.kg-recent-meta { font-size:0.72rem; color:var(--mu); margin-top:2px; display:flex; gap:8px; flex-wrap:wrap; }
|
|
||||||
.kg-recent-right { text-align:right; flex-shrink:0; }
|
|
||||||
.kg-recent-date { font-size:0.69rem; color:var(--mu); opacity:0.7; margin-top:3px; }
|
|
||||||
|
|
||||||
/* ── MINI CALENDAR ── */
|
|
||||||
.kg-cal-mini { width:220px; flex-shrink:0; }
|
|
||||||
.kg-cal-mini-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:2px; }
|
|
||||||
.kg-cal-mini-dname { text-align:center; font-size:0.6rem; font-weight:700; color:var(--mu); padding-bottom:3px; text-transform:uppercase; }
|
|
||||||
.kg-cal-mini-cell { aspect-ratio:1; border-radius:4px; display:flex; align-items:center; justify-content:center; font-size:0.63rem; font-weight:600; cursor:default; transition:transform 0.1s; }
|
|
||||||
.kg-cal-mini-cell:hover { transform:scale(1.2); z-index:5; }
|
|
||||||
.kg-cal-mini-cell.l0 { background:#f3f4f6; color:#9ca3af; }
|
|
||||||
.kg-cal-mini-cell.l1 { background:#bbf7d0; color:#065f46; }
|
|
||||||
.kg-cal-mini-cell.l2 { background:#4ade80; color:#14532d; }
|
|
||||||
.kg-cal-mini-cell.l3 { background:#16a34a; color:white; }
|
|
||||||
.kg-cal-mini-cell.l4 { background:#064e2d; color:white; }
|
|
||||||
.kg-cal-mini-cell.is-today { outline:2px solid var(--gd); outline-offset:1px; }
|
|
||||||
.kg-cal-mini-cell.out-range { opacity:0.3; }
|
|
||||||
|
|
||||||
/* ── EMPTY ── */
|
|
||||||
.kg-empty { text-align:center; padding:36px 20px; color:var(--mu); background:white; border-radius:12px; box-shadow:var(--sh); }
|
|
||||||
.kg-empty i { font-size:2.8rem; opacity:0.2; display:block; margin-bottom:10px; }
|
|
||||||
|
|
||||||
@media (max-width:768px) {
|
|
||||||
.kg-kpi-row { grid-template-columns:repeat(3,1fr); }
|
|
||||||
.kg-stat-grid { grid-template-columns:1fr; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kg-hero">
|
|
||||||
<div class="kg-hero-row">
|
|
||||||
<div>
|
|
||||||
<h1 class="kg-hero-title"><i class="fas fa-calendar-check"></i> Kegiatan & Absensi</h1>
|
|
||||||
<p class="kg-hero-sub"><?php echo e($santri->nama_lengkap); ?> · Kelas <?php echo e($namaKelas); ?></p>
|
|
||||||
</div>
|
|
||||||
<div class="kg-hero-right">
|
|
||||||
<div class="kg-hero-day"><?php echo e(\Carbon\Carbon::now()->locale('id')->isoFormat('dddd')); ?></div>
|
|
||||||
<div class="kg-hero-date"><?php echo e(\Carbon\Carbon::now()->locale('id')->isoFormat('D MMMM YYYY')); ?></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="kg-hero-badges">
|
|
||||||
<span class="kg-badge"><i class="fas fa-id-card"></i> <?php echo e($santri->nis ?? $santri->id_santri); ?></span>
|
|
||||||
<span class="kg-badge"><i class="fas fa-chart-line"></i> <?php echo e($persentaseKehadiran); ?>% kehadiran</span>
|
|
||||||
<?php if($streak > 0): ?>
|
|
||||||
<span class="kg-badge fire"><i class="fas fa-fire"></i> Streak <?php echo e($streak); ?>x hadir</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kg-kpi-row">
|
|
||||||
<div class="kg-kpi c-green">
|
|
||||||
<div class="kg-kpi-ic"><i class="fas fa-list-alt"></i></div>
|
|
||||||
<div class="kg-kpi-v"><?php echo e($expectedTotal); ?></div>
|
|
||||||
<div class="kg-kpi-l">Wajib Hadir</div>
|
|
||||||
<div class="kg-kpi-bar"><div class="kg-kpi-fill" style="width:100%;background:#2bbd8e;"></div></div>
|
|
||||||
</div>
|
|
||||||
<div class="kg-kpi c-blue">
|
|
||||||
<div class="kg-kpi-ic"><i class="fas fa-check-circle"></i></div>
|
|
||||||
<div class="kg-kpi-v"><?php echo e($hadirEfektif); ?></div>
|
|
||||||
<div class="kg-kpi-l">Hadir
|
|
||||||
<?php if($terlambatRange > 0): ?>
|
|
||||||
<span style="display:block;font-size:0.67rem;color:#f59e0b;">(+<?php echo e($terlambatRange); ?> terlambat)</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<div class="kg-kpi-bar"><div class="kg-kpi-fill" style="width:<?php echo e($expectedTotal > 0 ? round($hadirEfektif/$expectedTotal*100) : 0); ?>%;background:#3b82f6;"></div></div>
|
|
||||||
</div>
|
|
||||||
<div class="kg-kpi c-gold">
|
|
||||||
<div class="kg-kpi-ic"><i class="fas fa-percentage"></i></div>
|
|
||||||
<div class="kg-kpi-v"><?php echo e($persentaseKehadiran); ?>%</div>
|
|
||||||
<div class="kg-kpi-l">Kehadiran</div>
|
|
||||||
<div class="kg-kpi-bar"><div class="kg-kpi-fill" style="width:<?php echo e($persentaseKehadiran); ?>%;background:#f5a623;"></div></div>
|
|
||||||
</div>
|
|
||||||
<div class="kg-kpi c-orange">
|
|
||||||
<div class="kg-kpi-ic"><i class="fas fa-hourglass-half"></i></div>
|
|
||||||
<div class="kg-kpi-v"><?php echo e($belumAbsenRange); ?></div>
|
|
||||||
<div class="kg-kpi-l">Belum Absen</div>
|
|
||||||
<div class="kg-kpi-bar"><div class="kg-kpi-fill" style="width:<?php echo e($expectedTotal > 0 ? round($belumAbsenRange/$expectedTotal*100) : 0); ?>%;background:#f97316;"></div></div>
|
|
||||||
</div>
|
|
||||||
<div class="kg-kpi c-red">
|
|
||||||
<div class="kg-kpi-ic"><i class="fas fa-times-circle"></i></div>
|
|
||||||
<div class="kg-kpi-v"><?php echo e($alpaRange); ?></div>
|
|
||||||
<div class="kg-kpi-l">Alpa</div>
|
|
||||||
<div class="kg-kpi-bar"><div class="kg-kpi-fill" style="width:<?php echo e($expectedTotal > 0 ? round($alpaRange/$expectedTotal*100) : 0); ?>%;background:#e53e3e;"></div></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kg-tabs">
|
|
||||||
<button class="kg-tab <?php echo e($activeTab === 'statistik' ? 'active' : ''); ?>" onclick="switchTab('statistik',this)">
|
|
||||||
<i class="fas fa-chart-bar"></i> Statistik
|
|
||||||
</button>
|
|
||||||
<button class="kg-tab <?php echo e($activeTab === 'jadwal' ? 'active' : ''); ?>" onclick="switchTab('jadwal',this)">
|
|
||||||
<i class="fas fa-clock"></i> Jadwal
|
|
||||||
<?php if($jadwalDalamRange->count() > 0): ?>
|
|
||||||
<span style="background:var(--g);color:white;border-radius:10px;padding:1px 6px;font-size:0.67rem;"><?php echo e($jadwalDalamRange->count()); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kg-panel <?php echo e($activeTab === 'statistik' ? 'active' : ''); ?>" id="panel-statistik">
|
|
||||||
|
|
||||||
<form method="GET" action="<?php echo e(route('santri.kegiatan.index')); ?>" id="formStat">
|
|
||||||
<input type="hidden" name="tab" value="statistik">
|
|
||||||
<input type="hidden" name="preset_jad" value="<?php echo e($jadPreset); ?>">
|
|
||||||
<input type="hidden" name="preset_stat" id="hStat" value="<?php echo e($statPreset); ?>">
|
|
||||||
<input type="hidden" name="stat_date_from" id="hStatFrom" value="<?php echo e(request('stat_date_from')); ?>">
|
|
||||||
<input type="hidden" name="stat_date_to" id="hStatTo" value="<?php echo e(request('stat_date_to')); ?>">
|
|
||||||
|
|
||||||
<div class="kg-tab-filter">
|
|
||||||
<div class="kg-fg">
|
|
||||||
<label><i class="fas fa-bolt"></i> Periode</label>
|
|
||||||
<div class="kg-presets" id="statPresets">
|
|
||||||
<?php $__currentLoopData = ['today'=>'Hari Ini','this_week'=>'Minggu Ini','last_30'=>'30 Hari','this_month'=>'Bulan Ini','last_month'=>'Bulan Lalu']; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $v=>$l): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<button type="button" class="kg-preset-btn <?php echo e($statPreset===$v ? 'active' : ''); ?>"
|
|
||||||
onclick="setPreset('stat','<?php echo e($v); ?>')"><?php echo e($l); ?></button>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="kg-fg">
|
|
||||||
<label><i class="fas fa-calendar-alt"></i> Kustom</label>
|
|
||||||
<div class="kg-date-range">
|
|
||||||
<input type="date" id="inpStatFrom" value="<?php echo e(request('stat_date_from', $statFrom->format('Y-m-d'))); ?>" onchange="setCustom('stat')">
|
|
||||||
<span>—</span>
|
|
||||||
<input type="date" id="inpStatTo" value="<?php echo e(request('stat_date_to', $statTo->format('Y-m-d'))); ?>" onchange="setCustom('stat')">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="kg-apply-btn"><i class="fas fa-sync-alt"></i> Terapkan</button>
|
|
||||||
<div class="kg-filter-label">
|
|
||||||
<i class="fas fa-calendar-check"></i>
|
|
||||||
<?php echo e($statFrom->locale('id')->isoFormat('D MMM YYYY')); ?> – <?php echo e($statTo->locale('id')->isoFormat('D MMM YYYY')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="kg-stat-grid">
|
|
||||||
<div class="kg-chart-box">
|
|
||||||
<div class="kg-chart-title">
|
|
||||||
<i class="fas fa-chart-line" style="color:var(--m);"></i> Tren Kehadiran
|
|
||||||
<span style="margin-left:auto;font-size:0.73rem;color:var(--mu);font-weight:500;"><?php echo e($diffDays<=31?'Harian':'Mingguan'); ?></span>
|
|
||||||
</div>
|
|
||||||
<canvas id="chartTren" style="max-height:220px;"></canvas>
|
|
||||||
</div>
|
|
||||||
<div class="kg-chart-box">
|
|
||||||
<div class="kg-chart-title"><i class="fas fa-chart-pie" style="color:var(--gd);"></i> Distribusi Status</div>
|
|
||||||
<canvas id="chartDonut" style="max-height:200px;"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:grid; grid-template-columns:1fr auto; gap:14px; margin-bottom:14px; align-items:start;">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kg-chart-box" style="min-width:0;">
|
|
||||||
<div class="kg-chart-title">
|
|
||||||
<i class="fas fa-history" style="color:var(--m);"></i>
|
|
||||||
Absensi Terbaru
|
|
||||||
<span style="margin-left:auto;font-size:0.71rem;color:var(--mu);font-weight:500;">
|
|
||||||
<?php echo e($statFrom->locale('id')->isoFormat('D MMM')); ?> – <?php echo e($statTo->locale('id')->isoFormat('D MMM YY')); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($recentAbsensi->count() > 0): ?>
|
|
||||||
<div class="kg-recent-list">
|
|
||||||
<?php $__currentLoopData = $recentAbsensi; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $ab): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php $sl = strtolower($ab->status); ?>
|
|
||||||
<div class="kg-recent-item s-<?php echo e($sl); ?>">
|
|
||||||
<div class="kg-recent-ic">
|
|
||||||
<?php if($ab->status === 'Hadir'): ?> <i class="fas fa-check"></i>
|
|
||||||
<?php elseif($ab->status === 'Terlambat'): ?> <i class="fas fa-clock"></i>
|
|
||||||
<?php elseif($ab->status === 'Izin'): ?> <i class="fas fa-info"></i>
|
|
||||||
<?php elseif($ab->status === 'Sakit'): ?> <i class="fas fa-heartbeat"></i>
|
|
||||||
<?php elseif($ab->status === 'Alpa'): ?> <i class="fas fa-times"></i>
|
|
||||||
<?php elseif($ab->status === 'Pulang'): ?> <i class="fas fa-home"></i>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<div class="kg-recent-info">
|
|
||||||
<div class="kg-recent-name"><?php echo e($ab->kegiatan->nama_kegiatan); ?></div>
|
|
||||||
<div class="kg-recent-meta">
|
|
||||||
<span><i class="fas fa-tag"></i> <?php echo e($ab->kegiatan->kategori->nama_kategori); ?></span>
|
|
||||||
<?php if($ab->waktu_absen): ?>
|
|
||||||
<span><i class="fas fa-clock"></i> <?php echo e(\Carbon\Carbon::parse($ab->waktu_absen)->format('H:i')); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php $metode = $ab->metode_absen ?? ''; ?>
|
|
||||||
<span>
|
|
||||||
<i class="fas fa-<?php echo e($metode === 'RFID' ? 'id-card' : ($metode === 'Import_Mesin' ? 'desktop' : 'hand-pointer')); ?>"></i>
|
|
||||||
<?php echo e($metode === 'Import_Mesin' ? 'Mesin' : ($metode ?: 'Manual')); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="kg-recent-right">
|
|
||||||
<span class="kpill <?php echo e($sl); ?>" style="font-size:0.72rem;padding:2px 9px;"><?php echo e($ab->status); ?></span>
|
|
||||||
<div class="kg-recent-date">
|
|
||||||
<?php echo e(\Carbon\Carbon::parse($ab->tanggal)->locale('id')->isoFormat('D MMM')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<p style="text-align:center;color:var(--mu);font-size:0.84rem;padding:20px 0;">
|
|
||||||
Belum ada absensi dalam periode ini.
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php $calMonth = collect($heatmapMonths)->last(); ?>
|
|
||||||
<?php if($calMonth): ?>
|
|
||||||
<div class="kg-chart-box kg-cal-mini">
|
|
||||||
<div class="kg-chart-title" style="margin-bottom:8px;font-size:0.82rem;">
|
|
||||||
<i class="fas fa-calendar-alt" style="color:var(--g);"></i> <?php echo e($calMonth['label']); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div style="display:flex;gap:3px;align-items:center;margin-bottom:7px;font-size:0.67rem;color:var(--mu);">
|
|
||||||
<?php $__currentLoopData = ['#f3f4f6','#bbf7d0','#4ade80','#16a34a','#064e2d']; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $hc): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div style="width:7px;height:7px;border-radius:2px;background:<?php echo e($hc); ?>;flex-shrink:0;"></div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<span style="margin-left:2px;">Hadir</span>
|
|
||||||
</div>
|
|
||||||
<div class="kg-cal-mini-grid">
|
|
||||||
<?php $__currentLoopData = ['S','S','R','K','J','S','M']; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $hn): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div class="kg-cal-mini-dname"><?php echo e($hn); ?></div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php for($e = 1; $e < $calMonth['firstDayOfWeek']; $e++): ?>
|
|
||||||
<div></div>
|
|
||||||
<?php endfor; ?>
|
|
||||||
<?php $__currentLoopData = $calMonth['days']; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $day): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div class="kg-cal-mini-cell l<?php echo e($day['level']); ?> <?php echo e($day['is_today'] ? 'is-today' : ''); ?> <?php echo e(!$day['in_range'] ? 'out-range' : ''); ?>"
|
|
||||||
title="<?php echo e(\Carbon\Carbon::parse($day['date'])->locale('id')->isoFormat('D MMM')); ?><?php echo e($day['total'] > 0 ? ': '.$day['count'].'/'.$day['total'].' hadir' : ''); ?>">
|
|
||||||
<?php echo e($day['day']); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kg-panel <?php echo e($activeTab === 'jadwal' ? 'active' : ''); ?>" id="panel-jadwal">
|
|
||||||
|
|
||||||
<form method="GET" action="<?php echo e(route('santri.kegiatan.index')); ?>" id="formJad">
|
|
||||||
<input type="hidden" name="tab" value="jadwal">
|
|
||||||
<input type="hidden" name="preset_stat" value="<?php echo e($statPreset); ?>">
|
|
||||||
<input type="hidden" name="preset_jad" id="hJad" value="<?php echo e($jadPreset); ?>">
|
|
||||||
<input type="hidden" name="jad_date_from" id="hJadFrom" value="<?php echo e(request('jad_date_from')); ?>">
|
|
||||||
<input type="hidden" name="jad_date_to" id="hJadTo" value="<?php echo e(request('jad_date_to')); ?>">
|
|
||||||
|
|
||||||
<div class="kg-tab-filter">
|
|
||||||
<div class="kg-fg">
|
|
||||||
<label><i class="fas fa-bolt"></i> Periode</label>
|
|
||||||
<div class="kg-presets" id="jadPresets">
|
|
||||||
<?php $__currentLoopData = ['today'=>'Hari Ini','this_week'=>'Minggu Ini','this_month'=>'Bulan Ini','last_month'=>'Bulan Lalu']; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $v=>$l): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<button type="button" class="kg-preset-btn <?php echo e($jadPreset===$v ? 'active' : ''); ?>"
|
|
||||||
onclick="setPreset('jad','<?php echo e($v); ?>')"><?php echo e($l); ?></button>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="kg-fg">
|
|
||||||
<label><i class="fas fa-calendar-alt"></i> Kustom</label>
|
|
||||||
<div class="kg-date-range">
|
|
||||||
<input type="date" id="inpJadFrom" value="<?php echo e(request('jad_date_from', $jadFrom->format('Y-m-d'))); ?>" onchange="setCustom('jad')">
|
|
||||||
<span>—</span>
|
|
||||||
<input type="date" id="inpJadTo" value="<?php echo e(request('jad_date_to', $jadTo->format('Y-m-d'))); ?>" onchange="setCustom('jad')">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="kg-apply-btn"><i class="fas fa-sync-alt"></i> Terapkan</button>
|
|
||||||
<div class="kg-filter-label">
|
|
||||||
<i class="fas fa-calendar-check"></i>
|
|
||||||
<?php echo e($jadFrom->locale('id')->isoFormat('D MMM')); ?> – <?php echo e($jadTo->locale('id')->isoFormat('D MMM YYYY')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<?php if($jadwalDalamRange->count() > 0): ?>
|
|
||||||
<?php
|
|
||||||
$hariOrder = ['Senin','Selasa','Rabu','Kamis','Jumat','Sabtu','Ahad'];
|
|
||||||
$jadGrouped = $jadwalDalamRange->groupBy('hari')
|
|
||||||
->sortBy(fn($v,$k) => array_search($k, $hariOrder));
|
|
||||||
?>
|
|
||||||
<?php $__currentLoopData = $jadGrouped; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $hari => $jadwals): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div class="kg-jadwal-group">
|
|
||||||
<div class="kg-hari-label <?php echo e($hari === $hariIni ? 'today-label' : ''); ?>">
|
|
||||||
<i class="fas fa-calendar-day"></i> <?php echo e($hari); ?>
|
|
||||||
|
|
||||||
<?php if($hari === $hariIni): ?> <span style="font-size:0.66rem;opacity:0.85;">(Hari Ini)</span> <?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<?php $__currentLoopData = $jadwals; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $jadwal): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$statusAbsen = $hari === $hariIni
|
|
||||||
? ($absensiHariIni[$jadwal->kegiatan_id] ?? null)
|
|
||||||
: ($absensiDalamRange[$jadwal->kegiatan_id] ?? null);
|
|
||||||
$sc = $statusAbsen ? 's-' . strtolower($statusAbsen) : 's-belum';
|
|
||||||
?>
|
|
||||||
<div class="kg-jadwal-card <?php echo e($sc); ?>">
|
|
||||||
<div class="kg-time">
|
|
||||||
<div class="kg-time-main"><?php echo e(date('H:i', strtotime($jadwal->waktu_mulai))); ?></div>
|
|
||||||
<div class="kg-time-end"><?php echo e(date('H:i', strtotime($jadwal->waktu_selesai))); ?></div>
|
|
||||||
</div>
|
|
||||||
<div class="kg-divider"></div>
|
|
||||||
<div class="kg-jinfo">
|
|
||||||
<div class="kg-jname"><?php echo e($jadwal->nama_kegiatan); ?></div>
|
|
||||||
<div class="kg-jmeta">
|
|
||||||
<span><i class="fas fa-tag"></i> <?php echo e($jadwal->kategori->nama_kategori); ?></span>
|
|
||||||
<?php if($jadwal->materi): ?>
|
|
||||||
<span><i class="fas fa-book"></i> <?php echo e(Str::limit($jadwal->materi, 28)); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($statusAbsen): ?>
|
|
||||||
<span class="kpill <?php echo e(strtolower($statusAbsen)); ?>">
|
|
||||||
<?php if($statusAbsen === 'Terlambat'): ?> <i class="fas fa-clock"></i>
|
|
||||||
<?php elseif($statusAbsen === 'Pulang'): ?> <i class="fas fa-home"></i>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php echo e($statusAbsen); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<?php elseif($hari === $hariIni): ?>
|
|
||||||
<span class="kpill belum"><i class="fas fa-hourglass-half"></i> Belum</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<a href="<?php echo e(route('santri.kegiatan.show', $jadwal->kegiatan_id)); ?>?from_tab=jadwal"
|
|
||||||
class="kg-detail-btn">
|
|
||||||
<i class="fas fa-chart-bar"></i> Detail
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="kg-empty">
|
|
||||||
<i class="fas fa-calendar-times"></i>
|
|
||||||
<p>Tidak ada kegiatan terjadwal dalam periode ini.</p>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
|
||||||
<script>
|
|
||||||
// ── TAB SWITCHER ─────────────────────────────────
|
|
||||||
function switchTab(name, el) {
|
|
||||||
document.querySelectorAll('.kg-tab').forEach(t => t.classList.remove('active'));
|
|
||||||
document.querySelectorAll('.kg-panel').forEach(p => p.classList.remove('active'));
|
|
||||||
el.classList.add('active');
|
|
||||||
document.getElementById('panel-' + name).classList.add('active');
|
|
||||||
if (name === 'statistik' && !window._chartsInit) { initCharts(); window._chartsInit = true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── PRESET SETTER ────────────────────────────────
|
|
||||||
function setPreset(scope, val) {
|
|
||||||
document.querySelectorAll('#' + scope + 'Presets .kg-preset-btn').forEach(b => b.classList.remove('active'));
|
|
||||||
event.target.classList.add('active');
|
|
||||||
var cap = scope.charAt(0).toUpperCase() + scope.slice(1);
|
|
||||||
document.getElementById('h' + cap).value = val;
|
|
||||||
document.getElementById('h' + cap + 'From').value = '';
|
|
||||||
document.getElementById('h' + cap + 'To').value = '';
|
|
||||||
document.getElementById('form' + cap).submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setCustom(scope) {
|
|
||||||
var cap = scope.charAt(0).toUpperCase() + scope.slice(1);
|
|
||||||
document.getElementById('h' + cap).value = '';
|
|
||||||
document.getElementById('h' + cap + 'From').value = document.getElementById('inp' + cap + 'From').value;
|
|
||||||
document.getElementById('h' + cap + 'To').value = document.getElementById('inp' + cap + 'To').value;
|
|
||||||
document.querySelectorAll('#' + scope + 'Presets .kg-preset-btn').forEach(b => b.classList.remove('active'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── CHARTS ───────────────────────────────────────
|
|
||||||
function initCharts() {
|
|
||||||
const trenLabels = <?php echo json_encode(collect($dataGrafik)->pluck('label'), 15, 512) ?>;
|
|
||||||
const trenHadir = <?php echo json_encode(collect($dataGrafik)->pluck('hadir'), 15, 512) ?>;
|
|
||||||
const trenTotal = <?php echo json_encode(collect($dataGrafik)->pluck('total'), 15, 512) ?>;
|
|
||||||
|
|
||||||
new Chart(document.getElementById('chartTren'), {
|
|
||||||
type: 'line',
|
|
||||||
data: {
|
|
||||||
labels: trenLabels,
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
label: 'Hadir (incl. Terlambat)',
|
|
||||||
data: trenHadir,
|
|
||||||
borderColor: '#2bbd8e', backgroundColor: 'rgba(43,189,142,0.1)',
|
|
||||||
borderWidth: 3, pointRadius: trenLabels.length > 20 ? 2 : 5,
|
|
||||||
pointBackgroundColor: '#2bbd8e', tension: 0.4, fill: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Total Tercatat',
|
|
||||||
data: trenTotal,
|
|
||||||
borderColor: '#cbd5e1', backgroundColor: 'transparent',
|
|
||||||
borderWidth: 2, borderDash: [4,4],
|
|
||||||
pointRadius: trenLabels.length > 20 ? 2 : 4,
|
|
||||||
pointBackgroundColor: '#cbd5e1', tension: 0.4
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true, maintainAspectRatio: true,
|
|
||||||
plugins: { legend: { position:'top', labels:{ font:{ size:11, weight:'600' } } } },
|
|
||||||
scales: {
|
|
||||||
y: { beginAtZero:true, ticks:{ stepSize:1 }, grid:{ color:'rgba(0,0,0,0.04)' } },
|
|
||||||
x: { grid:{ display:false }, ticks:{ maxRotation:45, font:{ size:10 }, maxTicksLimit:12 } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
new Chart(document.getElementById('chartDonut'), {
|
|
||||||
type: 'doughnut',
|
|
||||||
data: {
|
|
||||||
labels: ['Hadir', 'Terlambat', 'Izin', 'Sakit', 'Alpa', 'Pulang', 'Belum Absen'],
|
|
||||||
datasets: [{
|
|
||||||
data: [
|
|
||||||
<?php echo e($hadirRange); ?>,
|
|
||||||
<?php echo e($terlambatRange); ?>,
|
|
||||||
<?php echo e($izinRange); ?>,
|
|
||||||
<?php echo e($sakitRange); ?>,
|
|
||||||
<?php echo e($alpaRange); ?>,
|
|
||||||
<?php echo e($pulangRange); ?>,
|
|
||||||
<?php echo e($belumAbsenRange); ?>
|
|
||||||
|
|
||||||
],
|
|
||||||
backgroundColor: ['#2bbd8e','#f59e0b','#3b82f6','#8b5cf6','#e53e3e','#0d9488','#d1d5db'],
|
|
||||||
borderWidth: 3, borderColor: '#fff'
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true, maintainAspectRatio: true, cutout: '65%',
|
|
||||||
plugins: {
|
|
||||||
legend: { position:'bottom', labels:{ padding:10, font:{ size:10 } } },
|
|
||||||
tooltip: { callbacks: {
|
|
||||||
label: function(ctx) {
|
|
||||||
var total = <?php echo e($expectedTotal); ?>;
|
|
||||||
var pct = total > 0 ? ((ctx.parsed / total) * 100).toFixed(1) : 0;
|
|
||||||
return ctx.label + ': ' + ctx.parsed + ' (' + pct + '%)';
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── INIT ─────────────────────────────────────────
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
var tab = new URLSearchParams(window.location.search).get('tab') || 'statistik';
|
|
||||||
var map = { statistik: 0, jadwal: 1 };
|
|
||||||
var idx = map[tab] ?? 0;
|
|
||||||
var tabs = document.querySelectorAll('.kg-tab');
|
|
||||||
if (tabs[idx]) tabs[idx].click();
|
|
||||||
});
|
|
||||||
</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**/ ?>
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
<!-- views/layouts/santri-wali-sidebar.blade.php -->
|
|
||||||
<ul class="sidebar-menu">
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<a href="<?php echo e(route('santri.dashboard')); ?>" class="<?php echo e(Request::routeIs('santri.dashboard') ? 'active' : ''); ?>">
|
|
||||||
<i class="fas fa-tachometer-alt"></i>
|
|
||||||
<span>Dashboard</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<a href="<?php echo e(route('santri.profil.index')); ?>" class="<?php echo e(Request::routeIs('santri.profil.*') ? 'active' : ''); ?>">
|
|
||||||
<i class="fas fa-user"></i>
|
|
||||||
<span>Profil Santri</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<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>Kegiatan & Absensi</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<a href="<?php echo e(route('santri.capaian.index')); ?>" class="<?php echo e(request()->routeIs('santri.capaian.*') ? 'active' : ''); ?>">
|
|
||||||
<i class="fas fa-book-reader"></i>
|
|
||||||
<span>Capaian Materi</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<a href="<?php echo e(route('santri.pelanggaran.index')); ?>" class="<?php echo e(Request::routeIs('santri.pelanggaran.*') ? 'active' : ''); ?>">
|
|
||||||
<i class="fas fa-exclamation-circle"></i>
|
|
||||||
<span>Riwayat Pelanggaran</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<a href="<?php echo e(route('santri.uang-saku.index')); ?>" class="<?php echo e(Request::routeIs('santri.uang-saku.*') ? 'active' : ''); ?>">
|
|
||||||
<i class="fas fa-wallet"></i>
|
|
||||||
<span>Riwayat Uang Saku</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<a href="<?php echo e(route('santri.kesehatan.index')); ?>" class="<?php echo e(request()->routeIs('santri.kesehatan.*') ? 'active' : ''); ?>">
|
|
||||||
<i class="fas fa-heartbeat"></i>
|
|
||||||
<span>Riwayat Kesehatan</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<a href="<?php echo e(route('santri.kepulangan.index')); ?>" class="<?php echo e(request()->routeIs('santri.kepulangan.*') ? 'active' : ''); ?>">
|
|
||||||
<i class="fas fa-home"></i>
|
|
||||||
<span>Riwayat Kepulangan</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<a href="<?php echo e(route('santri.berita.index')); ?>" class="<?php echo e(request()->routeIs('santri.berita.*') ? 'active' : ''); ?>">
|
|
||||||
<i class="fas fa-newspaper"></i>
|
|
||||||
<span>Berita</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/layouts/santri-wali-sidebar.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?php $__env->startSection('title', 'Laporan Pembayaran SPP'); ?>
|
||||||
|
|
||||||
|
<?php $__env->startSection('content'); ?>
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><i class="fas fa-file-pdf"></i> Laporan Pembayaran SPP</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row-cards">
|
||||||
|
<!-- Laporan Semua Data -->
|
||||||
|
<div class="card card-primary hover-lift">
|
||||||
|
<h3>Laporan Semua Data</h3>
|
||||||
|
<p style="margin: 10px 0; color: var(--text-light);">
|
||||||
|
Cetak laporan semua pembayaran SPP atau dengan filter tertentu
|
||||||
|
</p>
|
||||||
|
<form action="<?php echo e(route('admin.pembayaran-spp.cetak-laporan')); ?>" method="GET" target="_blank">
|
||||||
|
<div class="form-group">
|
||||||
|
<label><i class="fas fa-calendar form-icon"></i> Bulan (Opsional)</label>
|
||||||
|
<select name="bulan" class="form-control">
|
||||||
|
<option value="">Semua Bulan</option>
|
||||||
|
<?php for($i = 1; $i <= 12; $i++): ?>
|
||||||
|
<option value="<?php echo e($i); ?>"><?php echo e(DateTime::createFromFormat('!m', $i)->format('F')); ?></option>
|
||||||
|
<?php endfor; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label><i class="fas fa-calendar-alt form-icon"></i> Tahun (Opsional)</label>
|
||||||
|
<select name="tahun" class="form-control">
|
||||||
|
<option value="">Semua Tahun</option>
|
||||||
|
<?php for($year = date('Y'); $year >= 2020; $year--): ?>
|
||||||
|
<option value="<?php echo e($year); ?>"><?php echo e($year); ?></option>
|
||||||
|
<?php endfor; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label><i class="fas fa-info-circle form-icon"></i> Status (Opsional)</label>
|
||||||
|
<select name="status" class="form-control">
|
||||||
|
<option value="">Semua Status</option>
|
||||||
|
<option value="Lunas">Lunas</option>
|
||||||
|
<option value="Belum Lunas">Belum Lunas</option>
|
||||||
|
<option value="Telat">Telat</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary hover-shadow" style="width: 100%;">
|
||||||
|
<i class="fas fa-print"></i> Cetak Laporan
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<div class="content-box" style="margin-top: 25px;">
|
||||||
|
<a href="<?php echo e(route('admin.pembayaran-spp.index')); ?>" class="btn btn-secondary">
|
||||||
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<?php $__env->startPush('scripts'); ?>
|
||||||
|
<script>
|
||||||
|
// Update form action saat santri dipilih
|
||||||
|
document.getElementById('select-santri').addEventListener('change', function() {
|
||||||
|
const form = document.getElementById('form-santri');
|
||||||
|
const selectedId = this.value;
|
||||||
|
if (selectedId) {
|
||||||
|
form.action = "<?php echo e(route('admin.pembayaran-spp.cetak-laporan-santri', ':id')); ?>".replace(':id', selectedId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<?php $__env->stopPush(); ?>
|
||||||
|
<?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/laporan.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
<?php $__env->startSection('title', 'Berita & Pengumuman'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-newspaper"></i> Berita & Pengumuman</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($berita->isEmpty()): ?>
|
|
||||||
<div class="content-box">
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-newspaper" style="color: var(--primary-color); opacity: 0.3;"></i>
|
|
||||||
<h3>Belum Ada Berita</h3>
|
|
||||||
<p>Belum ada berita atau pengumuman yang dipublikasikan untuk Anda saat ini.</p>
|
|
||||||
<a href="<?php echo e(route('santri.dashboard')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-home"></i> Kembali ke Dashboard
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="content-box">
|
|
||||||
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 18px; padding-bottom: 14px; border-bottom: 1px solid #eee; flex-wrap: wrap; gap: 10px;">
|
|
||||||
<span style="color: var(--text-light); font-size: 0.9em;">
|
|
||||||
<i class="fas fa-list"></i>
|
|
||||||
Menampilkan <?php echo e($berita->firstItem()); ?>–<?php echo e($berita->lastItem()); ?> dari <strong><?php echo e($berita->total()); ?></strong> berita
|
|
||||||
</span>
|
|
||||||
<span style="color: var(--text-light); font-size: 0.85em;">
|
|
||||||
<i class="fas fa-sort-amount-down"></i> Terbaru dahulu
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display: flex; flex-direction: column; gap: 14px;">
|
|
||||||
<?php $__currentLoopData = $berita; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<a href="<?php echo e(route('santri.berita.show', $item->id_berita)); ?>"
|
|
||||||
style="display: flex; gap: 0; background: white; border: 1px solid #e8eaed;
|
|
||||||
border-radius: var(--border-radius); text-decoration: none; color: inherit;
|
|
||||||
overflow: hidden; transition: box-shadow 0.2s, transform 0.2s;"
|
|
||||||
onmouseover="this.style.boxShadow='0 4px 20px rgba(0,0,0,0.1)'; this.style.transform='translateY(-1px)';"
|
|
||||||
onmouseout="this.style.boxShadow='none'; this.style.transform='translateY(0)';">
|
|
||||||
|
|
||||||
|
|
||||||
<div style="flex-shrink: 0; width: 130px; min-height: 110px;
|
|
||||||
background: linear-gradient(135deg, var(--primary-light) 0%, var(--primary-color) 100%);
|
|
||||||
display: flex; align-items: center; justify-content: center; overflow: hidden;">
|
|
||||||
<?php if($item->gambar): ?>
|
|
||||||
<img src="<?php echo e(asset('storage/' . $item->gambar)); ?>"
|
|
||||||
alt="<?php echo e($item->judul); ?>"
|
|
||||||
style="width: 100%; height: 100%; object-fit: cover; min-height: 110px;">
|
|
||||||
<?php else: ?>
|
|
||||||
<i class="fas fa-newspaper" style="font-size: 2.5em; color: white; opacity: 0.4;"></i>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="flex: 1; padding: 14px 18px; display: flex; flex-direction: column; justify-content: space-between; min-width: 0;">
|
|
||||||
<div>
|
|
||||||
<h4 style="margin: 0 0 7px; color: var(--primary-color); font-size: 1.05em; line-height: 1.4;
|
|
||||||
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;">
|
|
||||||
<?php echo e($item->judul); ?>
|
|
||||||
|
|
||||||
</h4>
|
|
||||||
<p style="margin: 0; color: var(--text-light); font-size: 0.88em; line-height: 1.5;
|
|
||||||
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;">
|
|
||||||
<?php echo e(\Illuminate\Support\Str::limit(strip_tags($item->konten), 150)); ?>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-top: 10px; flex-wrap: wrap; gap: 8px;">
|
|
||||||
<div style="display: flex; gap: 14px; font-size: 0.82em; color: var(--text-light);">
|
|
||||||
<span><i class="fas fa-user"></i> <?php echo e($item->penulis); ?></span>
|
|
||||||
<span><i class="fas fa-calendar"></i> <?php echo e($item->created_at->isoFormat('D MMM YYYY')); ?></span>
|
|
||||||
</div>
|
|
||||||
<span class="badge badge-primary" style="font-size: 0.78em;">
|
|
||||||
<i class="fas fa-arrow-right"></i> Baca
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="margin-top: 20px; padding-top: 14px; border-top: 1px solid #eee;
|
|
||||||
display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;">
|
|
||||||
<p style="margin: 0; color: var(--text-light); font-size: 0.85em;">
|
|
||||||
Halaman <?php echo e($berita->currentPage()); ?> dari <?php echo e($berita->lastPage()); ?>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
<?php echo e($berita->links()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
a[style*="flex-shrink: 0; width: 130px"] {
|
|
||||||
flex-direction: column !important;
|
|
||||||
}
|
|
||||||
a[style*="flex-shrink: 0; width: 130px"] > div:first-child {
|
|
||||||
width: 100% !important;
|
|
||||||
min-height: 160px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<?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/berita/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,173 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Data Santri'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-users"></i> Data 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; ?>
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<!-- Header Actions -->
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: flex-start; gap: 11px; margin-bottom: 14px; flex-wrap: wrap;">
|
|
||||||
<!-- Tombol Tambah -->
|
|
||||||
<a href="<?php echo e(route('admin.santri.create')); ?>" class="btn btn-primary btn-sm">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Santri
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Form Search & Filter -->
|
|
||||||
<form action="<?php echo e(route('admin.santri.index')); ?>" method="GET" style="display: flex; gap: 8px; flex-wrap: wrap; align-items: center;">
|
|
||||||
<input type="text" name="search" class="form-control" placeholder="Cari nama, NIS, atau ID..." value="<?php echo e(request('search')); ?>" style="width: 220px; height: 38px;">
|
|
||||||
|
|
||||||
<select name="status" class="form-control" style="width: 150px; height: 38px;">
|
|
||||||
<option value=""> Semua Status</option>
|
|
||||||
<option value="Aktif" <?php echo e(request('status') == 'Aktif' ? 'selected' : ''); ?>>Aktif</option>
|
|
||||||
<option value="Lulus" <?php echo e(request('status') == 'Lulus' ? 'selected' : ''); ?>>Lulus</option>
|
|
||||||
<option value="Tidak Aktif" <?php echo e(request('status') == 'Tidak Aktif' ? 'selected' : ''); ?>>Tidak Aktif</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select name="id_kelas" class="form-control" style="width: 180px; height: 38px;">
|
|
||||||
<option value=""> Semua Kelas</option>
|
|
||||||
<?php $__currentLoopData = $kelompokKelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelompok): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php if($kelompok->kelas && $kelompok->kelas->count() > 0): ?>
|
|
||||||
<optgroup label="<?php echo e($kelompok->nama_kelompok); ?>">
|
|
||||||
<?php $__currentLoopData = $kelompok->kelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($kelas->id); ?>" <?php echo e(request('id_kelas') == $kelas->id ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($kelas->nama_kelas); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</optgroup>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary btn-sm" style="height: 38px; padding: 0 16px;">
|
|
||||||
<i class="fas fa-search"></i> Cari
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<?php if(request('search') || request('status') || request('id_kelas')): ?>
|
|
||||||
<a href="<?php echo e(route('admin.santri.index')); ?>" class="btn btn-secondary btn-sm" style="height: 38px; padding: 0 16px; display: inline-flex; align-items: center;">
|
|
||||||
<i class="fas fa-redo"></i> Reset
|
|
||||||
</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="table-wrapper">
|
|
||||||
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>No</th>
|
|
||||||
<th>Foto</th>
|
|
||||||
<th>ID Santri</th>
|
|
||||||
<th>NIS</th>
|
|
||||||
<th>Nama Lengkap</th>
|
|
||||||
<th>Jenis Kelamin</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th>Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<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($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>
|
|
||||||
<td><?php echo e($santri->jenis_kelamin); ?></td>
|
|
||||||
<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>
|
|
||||||
<td>
|
|
||||||
<a href="<?php echo e(route('admin.santri.show', $santri)); ?>" class="btn btn-sm btn-primary">
|
|
||||||
<i class="fas fa-eye"></i></a>
|
|
||||||
<a href="<?php echo e(route('admin.santri.edit', $santri)); ?>" class="btn btn-sm btn-warning">
|
|
||||||
<i class="fas fa-edit"></i></a>
|
|
||||||
<form action="<?php echo e(route('admin.santri.destroy', $santri)); ?>" method="POST" style="display:inline;">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<?php echo method_field('DELETE'); ?>
|
|
||||||
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Yakin ingin menghapus data santri <?php echo e($santri->nama_lengkap); ?>?')">
|
|
||||||
<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: 22px;">
|
|
||||||
<i class="fas fa-inbox" style="font-size: 2.2rem; color: #ccc; margin-bottom: 15px; display: block;"></i>
|
|
||||||
<?php if(request('search') || request('status') || request('id_kelas')): ?>
|
|
||||||
<strong>Data tidak ditemukan.</strong><br>
|
|
||||||
<small>Coba ubah kata kunci pencarian atau filter yang digunakan.</small>
|
|
||||||
<?php else: ?>
|
|
||||||
<strong>Belum ada data santri.</strong><br>
|
|
||||||
<small>Klik tombol "Tambah Santri" untuk menambahkan data baru.</small>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($santris->count() > 0): ?>
|
|
||||||
<div style="margin-top: 14px; 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> dari <strong><?php echo e($santris->total()); ?></strong> data santri
|
|
||||||
<?php if(request('search') || request('status') || request('id_kelas')): ?>
|
|
||||||
(hasil pencarian/filter)
|
|
||||||
<?php endif; ?>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<!-- Pagination -->
|
|
||||||
<?php if(method_exists($santris, 'links')): ?>
|
|
||||||
<div style="margin-top: 14px;">
|
|
||||||
<?php echo e($santris->links()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</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/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,285 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Data Kesehatan Santri'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-heartbeat"></i> Data Kesehatan Santri</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Flash Messages -->
|
|
||||||
<?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; ?>
|
|
||||||
|
|
||||||
<!-- Content Box -->
|
|
||||||
<div class="content-box">
|
|
||||||
<!-- Header Actions -->
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; flex-wrap: wrap; gap: 11px;">
|
|
||||||
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
|
|
||||||
<a href="<?php echo e(route('admin.kesehatan-santri.create')); ?>" class="btn btn-primary">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Data Kesehatan
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Filter Section -->
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.kesehatan-santri.index')); ?>" id="filterForm" style="margin-bottom: 14px;">
|
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px; align-items: end;">
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<input type="text"
|
|
||||||
name="search"
|
|
||||||
class="form-control"
|
|
||||||
placeholder="Nama santri, keluhan..."
|
|
||||||
value="<?php echo e(request('search')); ?>"
|
|
||||||
id="searchInput">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<select name="status" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
|
||||||
<option value="">Semua Status</option>
|
|
||||||
<?php $__currentLoopData = $statusOptions; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $status): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($status); ?>" <?php echo e(request('status') == $status ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e(ucfirst($status)); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<select name="month" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
|
||||||
<option value="">Semua Bulan</option>
|
|
||||||
<?php $__currentLoopData = $monthOptions; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $num => $name): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($num); ?>" <?php echo e(request('month') == $num ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($name); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<select name="year" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
|
||||||
<option value="">Semua Tahun</option>
|
|
||||||
<?php $__currentLoopData = $yearOptions; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $year): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($year); ?>" <?php echo e((request('year') ?: date('Y')) == $year ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e($year); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display: flex; gap: 10px;">
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
<i class="fas fa-search"></i> Filter
|
|
||||||
</button>
|
|
||||||
<a href="<?php echo e(route('admin.kesehatan-santri.index')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-redo"></i> Reset
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Data Table -->
|
|
||||||
<?php if($kesehatanSantri->count() > 0): ?>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 5%;">No</th>
|
|
||||||
<th style="width: 9%;">ID Santri</th>
|
|
||||||
<th style="width: 15%;">Nama Santri</th>
|
|
||||||
<th style="width: 10%;">Tgl Masuk</th>
|
|
||||||
<th style="width: 18%;">Keluhan</th>
|
|
||||||
<th style="width: 10%;">Tgl Keluar</th>
|
|
||||||
<th style="width: 8%;">Status</th>
|
|
||||||
<th style="width: 5%;">Lama</th>
|
|
||||||
<th style="width: 20%;">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $kesehatanSantri; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $data): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td class="text-center"><?php echo e($kesehatanSantri->firstItem() + $index); ?></td>
|
|
||||||
<td><strong><?php echo e($data->id_santri); ?></strong></td>
|
|
||||||
<td>
|
|
||||||
<strong><?php echo e($data->santri->nama_lengkap); ?></strong><br>
|
|
||||||
<small style="color: #7F8C8D;"><?php echo e($data->santri->kelas); ?></small>
|
|
||||||
</td>
|
|
||||||
<td><?php echo e($data->tanggal_masuk_formatted); ?></td>
|
|
||||||
<td>
|
|
||||||
<span title="<?php echo e($data->keluhan); ?>">
|
|
||||||
<?php echo e(Str::limit($data->keluhan, 50)); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($data->tanggal_keluar): ?>
|
|
||||||
<?php echo e($data->tanggal_keluar_formatted); ?>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="color: #E74C3C; font-weight: bold;">Belum keluar</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<span class="btn btn-<?php echo e($data->status_badge_color); ?> btn-sm"
|
|
||||||
style="cursor: default; padding: 5px 10px;">
|
|
||||||
<?php echo e(ucfirst($data->status)); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="text-center"><strong><?php echo e($data->lama_dirawat); ?></strong> hari</td>
|
|
||||||
<td>
|
|
||||||
<div style="display: flex; gap: 5px; flex-wrap: wrap;">
|
|
||||||
<a href="<?php echo e(route('admin.kesehatan-santri.show', $data)); ?>"
|
|
||||||
class="btn btn-primary btn-sm"
|
|
||||||
title="Detail">
|
|
||||||
<i class="fas fa-eye"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="<?php echo e(route('admin.kesehatan-santri.edit', $data)); ?>"
|
|
||||||
class="btn btn-warning btn-sm"
|
|
||||||
title="Edit">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<?php if($data->status == 'dirawat'): ?>
|
|
||||||
<button type="button"
|
|
||||||
class="btn btn-success btn-sm"
|
|
||||||
title="Keluar UKP"
|
|
||||||
onclick="keluarUkp(<?php echo e($data->id); ?>, '<?php echo e($data->santri->nama_lengkap); ?>', '<?php echo e($data->tanggal_masuk->format('Y-m-d')); ?>')">
|
|
||||||
<i class="fas fa-sign-out-alt"></i>
|
|
||||||
</button>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<a href="<?php echo e(route('admin.kesehatan-santri.cetak-surat', $data)); ?>"
|
|
||||||
class="btn btn-secondary btn-sm"
|
|
||||||
title="Cetak Surat"
|
|
||||||
target="_blank">
|
|
||||||
<i class="fas fa-print"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<form action="<?php echo e(route('admin.kesehatan-santri.destroy', $data)); ?>"
|
|
||||||
method="POST"
|
|
||||||
style="display: inline;"
|
|
||||||
onsubmit="return confirm('Yakin ingin menghapus data ini?')">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<?php echo method_field('DELETE'); ?>
|
|
||||||
<button type="submit"
|
|
||||||
class="btn btn-danger btn-sm"
|
|
||||||
title="Hapus">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Pagination -->
|
|
||||||
<div style="margin-top: 14px; display: flex; justify-content: center;">
|
|
||||||
<?php echo e($kesehatanSantri->appends(request()->query())->links()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div style="text-align: center; padding: 36px; color: #7F8C8D;">
|
|
||||||
<i class="fas fa-search" style="font-size: 3em; margin-bottom: 15px; color: #BDC3C7;"></i>
|
|
||||||
<h3>Tidak ada data kesehatan santri</h3>
|
|
||||||
<p>Belum ada data kesehatan santri yang tercatat atau sesuai dengan filter yang dipilih.</p>
|
|
||||||
<a href="<?php echo e(route('admin.kesehatan-santri.create')); ?>" class="btn btn-primary" style="margin-top: 15px;">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Data Kesehatan
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Modal Keluar UKP -->
|
|
||||||
<div id="keluarUkpModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); z-index: 1000;">
|
|
||||||
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 22px; border-radius: 12px; min-width: 300px; max-width: 90%; box-shadow: 0 10px 25px rgba(0,0,0,0.2);">
|
|
||||||
<h3 style="margin-bottom: 14px; color: var(--primary-color);">
|
|
||||||
<i class="fas fa-sign-out-alt"></i> Keluar dari UKP
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<form id="keluarUkpForm" method="POST">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<?php echo method_field('PATCH'); ?>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label><i class="fas fa-user form-icon"></i>Nama Santri</label>
|
|
||||||
<input type="text" id="modalNamaSantri" readonly class="form-control" style="background-color: #F8F9FA;">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="tanggal_keluar"><i class="fas fa-calendar form-icon"></i>Tanggal Keluar *</label>
|
|
||||||
<input type="date" name="tanggal_keluar" id="tanggal_keluar" class="form-control" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="status_keluar"><i class="fas fa-check-circle form-icon"></i>Status *</label>
|
|
||||||
<select name="status" id="status_keluar" class="form-control" required>
|
|
||||||
<option value="">Pilih Status</option>
|
|
||||||
<option value="sembuh">Sembuh</option>
|
|
||||||
<option value="izin">Izin Pulang</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeKeluarUkpModal()">
|
|
||||||
<i class="fas fa-times"></i> Batal
|
|
||||||
</button>
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
<i class="fas fa-save"></i> Simpan
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function keluarUkp(id, namaSantri, tanggalMasuk) {
|
|
||||||
document.getElementById('modalNamaSantri').value = namaSantri;
|
|
||||||
document.getElementById('keluarUkpForm').action = `/admin/kesehatan-santri/${id}/keluar-ukp`;
|
|
||||||
document.getElementById('tanggal_keluar').value = new Date().toISOString().split('T')[0];
|
|
||||||
document.getElementById('tanggal_keluar').min = tanggalMasuk;
|
|
||||||
document.getElementById('tanggal_keluar').max = new Date().toISOString().split('T')[0];
|
|
||||||
document.getElementById('keluarUkpModal').style.display = 'block';
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeKeluarUkpModal() {
|
|
||||||
document.getElementById('keluarUkpModal').style.display = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close modal when clicking outside
|
|
||||||
document.getElementById('keluarUkpModal').addEventListener('click', function(e) {
|
|
||||||
if (e.target === this) {
|
|
||||||
closeKeluarUkpModal();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Close modal with Escape key
|
|
||||||
document.addEventListener('keydown', function(e) {
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
closeKeluarUkpModal();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</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/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
<?php $__env->startSection('title', 'Edit Santri: ' . $santri->nama_lengkap); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-user-edit"></i> Edit Data Santri</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<?php if($errors->any()): ?>
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<strong><i class="fas fa-exclamation-triangle"></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 style="background: linear-gradient(135deg, #E3F2FD 0%, #D1E9F9 100%); padding: 14px; border-radius: 8px; border-left: 4px solid #81C6E8; margin-bottom: 25px;">
|
|
||||||
<div style="display: flex; align-items: center; gap: 11px;">
|
|
||||||
<?php if($santri->foto): ?>
|
|
||||||
<img src="<?php echo e(asset('storage/' . $santri->foto)); ?>"
|
|
||||||
alt="Foto <?php echo e($santri->nama_lengkap); ?>"
|
|
||||||
style="width: 60px; height: 60px; border-radius: 50%; object-fit: cover; border: 3px solid #81C6E8;"
|
|
||||||
loading="lazy">
|
|
||||||
<?php 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;">
|
|
||||||
<?php echo e(strtoupper(substr($santri->nama_lengkap, 0, 1))); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php 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;">
|
|
||||||
<?php echo e($santri->nama_lengkap); ?> (<?php echo e($santri->id_santri); ?>)
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php echo $__env->make('admin.santri.form', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?>
|
|
||||||
</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/edit.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,465 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?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: 14px;">
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 11px;">
|
|
||||||
<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-secondary" onclick="setMode('rfid')">
|
|
||||||
<i class="fas fa-id-card"></i> Mode RFID
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="info-box" style="margin-bottom: 14px; border-left: 4px solid var(--primary-color);">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
<?php if($kegiatanInfo['is_umum']): ?>
|
|
||||||
<strong>Kegiatan Umum</strong> - Diikuti oleh semua santri aktif (<?php echo e($santris->count()); ?> santri)
|
|
||||||
<?php else: ?>
|
|
||||||
<strong>Kegiatan Khusus</strong> - Untuk kelas:
|
|
||||||
<strong style="color: var(--primary-color);"><?php echo e($kegiatanInfo['kelas_list']); ?></strong>
|
|
||||||
(<?php echo e($kegiatanInfo['jumlah_kelas']); ?> kelas)
|
|
||||||
| Total semua santri aktif: <strong><?php echo e($santris->count()); ?> santri</strong>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$sudahAdaData = count($absensiData) > 0;
|
|
||||||
?>
|
|
||||||
<?php if($sudahAdaData): ?>
|
|
||||||
<div class="alert alert-info" style="margin-bottom: 14px;">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
<strong>Mode Edit</strong> - Data absensi untuk tanggal ini sudah ada
|
|
||||||
(<strong><?php echo e(count($absensiData)); ?></strong> dari <strong><?php echo e($santris->count()); ?></strong> santri sudah diinput,
|
|
||||||
<strong style="color: <?php echo e(($santris->count() - count($absensiData)) > 0 ? '#dc2626' : '#059669'); ?>;"><?php echo e($santris->count() - count($absensiData)); ?> belum absen</strong>).
|
|
||||||
Anda dapat mengubah status absensi lalu klik Simpan.
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<!-- 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="filter-form-inline" style="margin-bottom: 14px; gap: 12px;">
|
|
||||||
<div class="filter-form-inline" style="gap: 8px;">
|
|
||||||
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
|
||||||
<i class="fas fa-calendar"></i> Tanggal:
|
|
||||||
</label>
|
|
||||||
<input type="date" name="tanggal" id="tanggal" class="form-control"
|
|
||||||
value="<?php echo e($tanggal); ?>" required style="max-width: 170px;">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="filter-form-inline" style="gap: 8px;">
|
|
||||||
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
|
||||||
<i class="fas fa-school"></i> Pilih Kelas:
|
|
||||||
</label>
|
|
||||||
<select id="kelasFilter" class="form-control" onchange="filterKelas(this.value)" style="max-width: 220px;">
|
|
||||||
<option value="semua">-- Tampilkan Semua Kelas --</option>
|
|
||||||
<?php $__currentLoopData = $santriGrouped; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelasNama => $santriKelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($kelasNama); ?>"><?php echo e($kelasNama); ?> (<?php echo e($santriKelas->count()); ?> santri)</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap;">
|
|
||||||
<button type="button" class="btn btn-sm btn-info" onclick="setAllStatus('Hadir')">
|
|
||||||
<i class="fas fa-check-double"></i> Semua Hadir
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-sm" style="background: #FF9800; color: white;" onclick="setAllStatus('Terlambat')">
|
|
||||||
<i class="fas fa-clock"></i> Semua Terlambat
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-danger" onclick="setAllStatus('Alpa')">
|
|
||||||
<i class="fas fa-times"></i> Semua Alpa
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-secondary" onclick="clearAllStatus()">
|
|
||||||
<i class="fas fa-eraser"></i> Kosongkan
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="info-box" style="margin-bottom: 14px;">
|
|
||||||
<p style="margin: 0;"><i class="fas fa-info-circle"></i> Pilih kelas terlebih dahulu untuk menampilkan daftar santri. Santri tanpa pilihan status akan <strong>dilewati</strong>. Santri yang <strong>sedang pulang</strong> otomatis ditandai.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__currentLoopData = $santriGrouped; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelasNama => $santriKelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$hadirCount = 0;
|
|
||||||
$totalKelas = $santriKelas->count();
|
|
||||||
foreach ($santriKelas as $s) {
|
|
||||||
$st = $absensiData[$s->id_santri] ?? null;
|
|
||||||
if ($st === 'Hadir') $hadirCount++;
|
|
||||||
}
|
|
||||||
$sudahInputKelas = false;
|
|
||||||
foreach ($santriKelas as $s) {
|
|
||||||
if (isset($absensiData[$s->id_santri])) { $sudahInputKelas = true; break; }
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<div class="kelas-group" data-kelas="<?php echo e($kelasNama); ?>" style="margin-bottom: 20px; display: none;">
|
|
||||||
<div style="background: var(--primary-light); padding: 10px 14px; border-radius: 8px 8px 0 0; display: flex; justify-content: space-between; align-items: center;">
|
|
||||||
<h4 style="margin: 0; color: var(--primary-color); font-size: 0.95rem;">
|
|
||||||
<i class="fas fa-users"></i> <?php echo e($kelasNama); ?>
|
|
||||||
|
|
||||||
</h4>
|
|
||||||
<div style="display: flex; gap: 8px; align-items: center;">
|
|
||||||
<?php if($sudahInputKelas): ?>
|
|
||||||
<span class="badge badge-info"><i class="fas fa-edit"></i> <?php echo e($hadirCount); ?>/<?php echo e($totalKelas); ?> hadir</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<span class="badge badge-primary"><?php echo e($totalKelas); ?> santri</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table" style="margin-top: 0; border-top-left-radius: 0; border-top-right-radius: 0;">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 50px;">No</th>
|
|
||||||
<th style="width: 100px;">ID Santri</th>
|
|
||||||
<th>Nama Santri</th>
|
|
||||||
<th style="width: 420px; text-align: center;">Status</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $santriKelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$isPulang = in_array($santri->id_santri, $santriSedangPulang ?? []);
|
|
||||||
$currentStatus = $absensiData[$santri->id_santri] ?? ($isPulang ? 'Pulang' : '');
|
|
||||||
?>
|
|
||||||
<tr <?php if($isPulang): ?> style="background: #FFF8E1; opacity: 0.85;" <?php endif; ?>>
|
|
||||||
<td><?php echo e($loop->iteration); ?></td>
|
|
||||||
<td><strong><?php echo e($santri->id_santri); ?></strong></td>
|
|
||||||
<td>
|
|
||||||
<?php echo e($santri->nama_lengkap); ?>
|
|
||||||
|
|
||||||
<?php if($isPulang): ?>
|
|
||||||
<span class="badge" style="background: #FFF3E0; color: #E65100; font-size: 0.75rem; margin-left: 6px;">
|
|
||||||
<i class="fas fa-home"></i> Sedang Pulang
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if(isset($absensiData[$santri->id_santri])): ?>
|
|
||||||
<span class="badge badge-secondary" style="font-size: 0.7rem; margin-left: 4px;">
|
|
||||||
<i class="fas fa-edit"></i> Sudah input
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<?php if($isPulang): ?>
|
|
||||||
<input type="hidden" name="absensi[<?php echo e($santri->id_santri); ?>]" value="Pulang" class="absensi-input">
|
|
||||||
<span class="badge" style="background: #FFF3E0; color: #E65100; padding: 6px 14px; font-size: 0.85rem;">
|
|
||||||
<i class="fas fa-home"></i> Pulang
|
|
||||||
</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<div style="display: flex; gap: 5px; justify-content: center; flex-wrap: wrap;">
|
|
||||||
<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' : ''); ?> class="absensi-radio absensi-input">
|
|
||||||
<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="Terlambat"
|
|
||||||
<?php echo e($currentStatus == 'Terlambat' ? 'checked' : ''); ?> class="absensi-radio absensi-input">
|
|
||||||
<span class="badge" style="background: #FF9800; color: white;">Terlambat</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' : ''); ?> class="absensi-radio absensi-input">
|
|
||||||
<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' : ''); ?> class="absensi-radio absensi-input">
|
|
||||||
<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' : ''); ?> class="absensi-radio absensi-input">
|
|
||||||
<span class="badge badge-danger">Alpa</span>
|
|
||||||
</label>
|
|
||||||
<?php if($currentStatus): ?>
|
|
||||||
<label style="margin: 0; cursor: pointer;" title="Hapus pilihan">
|
|
||||||
<button type="button" class="btn btn-sm" style="padding: 2px 8px; font-size: 0.75rem; background: #f1f1f1;" onclick="clearRadio('<?php echo e($santri->id_santri); ?>')">
|
|
||||||
<i class="fas fa-undo"></i>
|
|
||||||
</button>
|
|
||||||
</label>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
|
|
||||||
<div id="noKelasSelected" class="empty-state" style="padding: 40px 20px;">
|
|
||||||
<i class="fas fa-hand-pointer"></i>
|
|
||||||
<h3>Pilih Kelas Terlebih Dahulu</h3>
|
|
||||||
<p>Silakan pilih kelas pada dropdown di atas untuk menampilkan daftar santri yang akan diabsen.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="btn-group" style="margin-top: 14px;">
|
|
||||||
<button type="submit" class="btn btn-success">
|
|
||||||
<i class="fas fa-save"></i> <?php echo e($sudahAdaData ? 'Update Absensi' : 'Simpan Absensi'); ?>
|
|
||||||
|
|
||||||
</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>
|
|
||||||
|
|
||||||
<!-- 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: 22px; border-radius: var(--border-radius); text-align: center; margin-bottom: 14px;">
|
|
||||||
<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: 14px;">
|
|
||||||
<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.kegiatan.index')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// -- Kelas Filter --
|
|
||||||
function filterKelas(value) {
|
|
||||||
var groups = document.querySelectorAll('.kelas-group');
|
|
||||||
var emptyMsg = document.getElementById('noKelasSelected');
|
|
||||||
|
|
||||||
if (value === 'semua') {
|
|
||||||
for (var i = 0; i < groups.length; i++) {
|
|
||||||
groups[i].style.display = 'block';
|
|
||||||
toggleGroupInputs(groups[i], true);
|
|
||||||
}
|
|
||||||
emptyMsg.style.display = 'none';
|
|
||||||
} else {
|
|
||||||
var found = false;
|
|
||||||
for (var i = 0; i < groups.length; i++) {
|
|
||||||
if (groups[i].getAttribute('data-kelas') === value) {
|
|
||||||
groups[i].style.display = 'block';
|
|
||||||
toggleGroupInputs(groups[i], true);
|
|
||||||
found = true;
|
|
||||||
} else {
|
|
||||||
groups[i].style.display = 'none';
|
|
||||||
toggleGroupInputs(groups[i], false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
emptyMsg.style.display = found ? 'none' : 'block';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable/disable all inputs in a kelas group so hidden groups don't submit
|
|
||||||
function toggleGroupInputs(group, enabled) {
|
|
||||||
var inputs = group.querySelectorAll('.absensi-input');
|
|
||||||
for (var i = 0; i < inputs.length; i++) {
|
|
||||||
inputs[i].disabled = !enabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Set All Status (for visible groups only) --
|
|
||||||
function setAllStatus(status) {
|
|
||||||
var groups = document.querySelectorAll('.kelas-group');
|
|
||||||
for (var i = 0; i < groups.length; i++) {
|
|
||||||
if (groups[i].style.display !== 'none') {
|
|
||||||
var radios = groups[i].querySelectorAll('input.absensi-radio[value="' + status + '"]');
|
|
||||||
for (var j = 0; j < radios.length; j++) {
|
|
||||||
radios[j].checked = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Clear radio selection for a specific santri --
|
|
||||||
function clearRadio(santriId) {
|
|
||||||
var radios = document.querySelectorAll('input[name="absensi[' + santriId + ']"]');
|
|
||||||
for (var i = 0; i < radios.length; i++) {
|
|
||||||
radios[i].checked = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Clear all selections in visible groups --
|
|
||||||
function clearAllStatus() {
|
|
||||||
var groups = document.querySelectorAll('.kelas-group');
|
|
||||||
for (var i = 0; i < groups.length; i++) {
|
|
||||||
if (groups[i].style.display !== 'none') {
|
|
||||||
var radios = groups[i].querySelectorAll('input.absensi-radio');
|
|
||||||
for (var j = 0; j < radios.length; j++) {
|
|
||||||
radios[j].checked = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Mode Switch --
|
|
||||||
var currentMode = 'manual';
|
|
||||||
var kegiatanId = '<?php echo e($kegiatan->kegiatan_id); ?>';
|
|
||||||
|
|
||||||
function setMode(mode) {
|
|
||||||
currentMode = mode;
|
|
||||||
var modeManualEl = document.getElementById('modeManual');
|
|
||||||
var modeRfidEl = document.getElementById('modeRfid');
|
|
||||||
var btnManual = document.getElementById('btnModeManual');
|
|
||||||
var btnRfid = document.getElementById('btnModeRfid');
|
|
||||||
|
|
||||||
if (mode === 'manual') {
|
|
||||||
modeManualEl.style.display = 'block';
|
|
||||||
modeRfidEl.style.display = 'none';
|
|
||||||
btnManual.className = 'btn btn-primary';
|
|
||||||
btnRfid.className = 'btn btn-secondary';
|
|
||||||
} else {
|
|
||||||
modeManualEl.style.display = 'none';
|
|
||||||
modeRfidEl.style.display = 'block';
|
|
||||||
btnManual.className = 'btn btn-secondary';
|
|
||||||
btnRfid.className = 'btn btn-success';
|
|
||||||
document.getElementById('rfidInput').focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- RFID Scanner --
|
|
||||||
document.getElementById('rfidInput').addEventListener('keypress', function(e) {
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
e.preventDefault();
|
|
||||||
var rfidUid = this.value.trim();
|
|
||||||
if (rfidUid) {
|
|
||||||
scanRfid(rfidUid);
|
|
||||||
this.value = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function scanRfid(rfidUid) {
|
|
||||||
var tanggal = document.getElementById('tanggalRfid').value;
|
|
||||||
var 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(function(response) { return response.json(); })
|
|
||||||
.then(function(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');
|
|
||||||
} else {
|
|
||||||
statusEl.innerHTML = '<i class="fas fa-exclamation-circle"></i> ' + data.message;
|
|
||||||
statusEl.style.color = 'var(--danger-color)';
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
statusEl.innerHTML = '<i class="fas fa-wifi"></i> Siap Scan RFID';
|
|
||||||
statusEl.style.color = 'var(--primary-color)';
|
|
||||||
}, 2000);
|
|
||||||
})
|
|
||||||
.catch(function(error) {
|
|
||||||
statusEl.innerHTML = '<i class="fas fa-times-circle"></i> Koneksi error';
|
|
||||||
statusEl.style.color = 'var(--danger-color)';
|
|
||||||
console.error('Error:', error);
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
statusEl.innerHTML = '<i class="fas fa-wifi"></i> Siap Scan RFID';
|
|
||||||
statusEl.style.color = 'var(--primary-color)';
|
|
||||||
}, 2000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function addLogEntry(data, type) {
|
|
||||||
var logContent = document.getElementById('rfidLogContent');
|
|
||||||
|
|
||||||
if (logContent.querySelector('p')) {
|
|
||||||
logContent.innerHTML = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
var 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>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Auto-focus RFID input --
|
|
||||||
setInterval(function() {
|
|
||||||
if (currentMode === 'rfid') {
|
|
||||||
var rfidInput = document.getElementById('rfidInput');
|
|
||||||
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/absensi/input.blade.php ENDPATH**/ ?>
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue