561 lines
22 KiB
PHP
561 lines
22 KiB
PHP
{{-- resources/views/santri/capaian/input.blade.php --}}
|
||
@extends('layouts.app')
|
||
|
||
@section('title', 'Input Capaian')
|
||
|
||
@section('content')
|
||
<style>
|
||
.input-hero {
|
||
background: linear-gradient(135deg, #1b5e20, #2e7d32, #43a047);
|
||
border-radius: 14px;
|
||
padding: 22px 24px;
|
||
color: #fff;
|
||
margin-bottom: 18px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16px;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
.input-hero::after {
|
||
content: '✏️';
|
||
position: absolute;
|
||
right: 20px;
|
||
font-size: 4rem;
|
||
opacity: 0.15;
|
||
}
|
||
.input-hero h2 { margin: 0 0 4px; font-size: 1.2rem; }
|
||
.input-hero p { margin: 0; opacity: 0.8; font-size: .84rem; }
|
||
|
||
.deadline-banner {
|
||
background: linear-gradient(135deg, #fff3e0, #ffe0b2);
|
||
border: 2px solid #ffa726;
|
||
border-radius: 10px;
|
||
padding: 12px 16px;
|
||
margin-bottom: 14px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
font-size: .84rem;
|
||
color: #555;
|
||
}
|
||
.deadline-banner i { font-size: 1.4rem; color: #e65100; flex-shrink: 0; }
|
||
|
||
.materi-card {
|
||
background: #fff;
|
||
border-radius: 12px;
|
||
padding: 16px 18px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,.06);
|
||
margin-bottom: 10px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 14px;
|
||
cursor: pointer;
|
||
border: 2px solid transparent;
|
||
transition: all .2s;
|
||
}
|
||
.materi-card:hover { border-color: var(--primary-color); transform: translateX(3px); }
|
||
.materi-card.selected { border-color: var(--primary-color); background: #f0faf4; }
|
||
.materi-card.done { border-color: #66bb6a; background: #f1f8e9; }
|
||
.materi-badge { width: 44px; height: 44px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 1.2rem; flex-shrink: 0; }
|
||
.materi-info { flex: 1; }
|
||
.materi-info h4 { margin: 0 0 3px; font-size: .9rem; }
|
||
.materi-info small { color: #999; font-size: .75rem; }
|
||
|
||
.form-section {
|
||
background: #fff;
|
||
border-radius: 14px;
|
||
padding: 22px;
|
||
box-shadow: 0 2px 12px rgba(0,0,0,.06);
|
||
margin-bottom: 14px;
|
||
border: 1px solid #e8f0ec;
|
||
}
|
||
.form-section h4 { margin: 0 0 16px; color: var(--primary-dark); font-size: .95rem; }
|
||
|
||
.prog-preview {
|
||
background: linear-gradient(135deg, #e8f5e9, #f1f8e9);
|
||
border-radius: 10px;
|
||
padding: 14px;
|
||
margin-top: 12px;
|
||
display: none;
|
||
}
|
||
.prog-preview.show { display: block; }
|
||
.prog-row { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; margin-bottom: 10px; }
|
||
.prog-stat { background: #fff; border-radius: 8px; padding: 10px; text-align: center; }
|
||
.prog-stat .pv { font-size: 1.2rem; font-weight: 800; color: var(--primary-color); }
|
||
.prog-stat .pl { font-size: .7rem; color: #999; margin-top: 2px; }
|
||
.prog-bar { height: 10px; background: #e0e0e0; border-radius: 10px; overflow: hidden; }
|
||
.prog-fill { height: 100%; border-radius: 10px; background: linear-gradient(90deg, var(--primary-color), var(--success-color)); transition: width .5s; }
|
||
|
||
.method-tabs { display: flex; gap: 6px; margin-bottom: 14px; flex-wrap: wrap; }
|
||
.mt-btn { padding: 7px 14px; border: 2px solid #e0e0e0; background: #fff; border-radius: 8px; font-size: .78rem; font-weight: 600; cursor: pointer; transition: .2s; color: #666; }
|
||
.mt-btn.active { border-color: var(--primary-color); background: var(--primary-light); color: var(--primary-dark); }
|
||
.method-panel { display: none; }
|
||
.method-panel.active { display: block; }
|
||
</style>
|
||
|
||
{{-- Hero --}}
|
||
<div class="input-hero">
|
||
<div>
|
||
<h2><i class="fas fa-pencil-alt"></i> Input Capaian Mandiri</h2>
|
||
<p>
|
||
{{ $santri->nama_lengkap }} •
|
||
{{ $santri->kelasPrimary?->kelas?->nama_kelas ?? '-' }}
|
||
@if($semesterAktif)
|
||
• Semester: <strong>{{ $semesterAktif->nama_semester }}</strong>
|
||
@endif
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
@if(session('success'))
|
||
<div class="alert alert-success" style="border-radius:10px;"><i class="fas fa-check-circle"></i> {{ session('success') }}</div>
|
||
@endif
|
||
@if(session('error'))
|
||
<div class="alert alert-danger" style="border-radius:10px;"><i class="fas fa-exclamation-circle"></i> {{ session('error') }}</div>
|
||
@endif
|
||
|
||
{{-- Deadline / catatan admin --}}
|
||
@if(!empty($accessConfig['catatan']))
|
||
<div class="deadline-banner">
|
||
<i class="fas fa-bell"></i>
|
||
<div>
|
||
<strong>Informasi dari Admin:</strong> {{ $accessConfig['catatan'] }}
|
||
@if($sisaWaktu)
|
||
• <strong>Sisa waktu: {{ $sisaWaktu }}</strong>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
@elseif($sisaWaktu)
|
||
<div class="deadline-banner">
|
||
<i class="fas fa-hourglass-half"></i>
|
||
<div>Waktu input masih tersedia: <strong>{{ $sisaWaktu }}</strong></div>
|
||
</div>
|
||
@endif
|
||
|
||
<div style="display:grid;grid-template-columns:1fr 1.5fr;gap:18px;">
|
||
|
||
{{-- ===== KIRI: PILIH MATERI ===== --}}
|
||
<div>
|
||
<div class="form-section">
|
||
<h4><i class="fas fa-book"></i> Pilih Materi</h4>
|
||
|
||
@php
|
||
$materiByKat = $materiOptions->groupBy('kategori');
|
||
@endphp
|
||
|
||
@foreach([
|
||
["Al-Qur'an", 'fas fa-book-quran', 'var(--success-color)', '#e8f5e9'],
|
||
['Hadist', 'fas fa-scroll', 'var(--info-color)', '#e3f2fd'],
|
||
['Materi Tambahan', 'fas fa-book', 'var(--warning-color)', '#fffde7'],
|
||
] as [$kat, $icon, $color, $bg])
|
||
@if(isset($materiByKat[$kat]) && $materiByKat[$kat]->count() > 0)
|
||
<div style="margin-bottom:14px;">
|
||
<div style="font-size:.77rem;font-weight:700;color:{{ $color }};margin-bottom:6px;display:flex;align-items:center;gap:5px;">
|
||
<i class="{{ $icon }}"></i> {{ $kat }}
|
||
</div>
|
||
@foreach($materiByKat[$kat] as $materi)
|
||
@php
|
||
$existPct = $existingCapaians[$materi->id_materi] ?? null;
|
||
@endphp
|
||
<div class="materi-card {{ $existPct >= 100 ? 'done' : '' }}"
|
||
onclick="selectMateri('{{ $materi->id_materi }}', this)"
|
||
data-materi-id="{{ $materi->id_materi }}"
|
||
id="materi-card-{{ $materi->id_materi }}">
|
||
<div class="materi-badge" style="background:{{ $bg }};color:{{ $color }};">
|
||
<i class="{{ $icon }}"></i>
|
||
</div>
|
||
<div class="materi-info">
|
||
<h4>{{ $materi->nama_kitab }}</h4>
|
||
<small>Hal. {{ $materi->halaman_mulai }}–{{ $materi->halaman_akhir }} • {{ $materi->total_halaman }} hal</small>
|
||
@if($existPct !== null)
|
||
<div style="margin-top:4px;">
|
||
<span style="font-size:.72rem;font-weight:700;color:{{ $existPct >= 100 ? '#2e7d32' : '#f57f17' }};">
|
||
<i class="fas fa-{{ $existPct >= 100 ? 'check-circle' : 'edit' }}"></i>
|
||
{{ number_format($existPct, 0) }}% — {{ $existPct >= 100 ? 'Khatam' : 'Sudah diisi' }}
|
||
</span>
|
||
</div>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
@endforeach
|
||
</div>
|
||
@endif
|
||
@endforeach
|
||
|
||
@if($materiOptions->isEmpty())
|
||
<div style="text-align:center;color:#aaa;padding:20px;">
|
||
<i class="fas fa-book" style="font-size:2rem;display:block;margin-bottom:8px;opacity:.4;"></i>
|
||
Tidak ada materi untuk kelas Anda
|
||
</div>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
|
||
{{-- ===== KANAN: FORM INPUT ===== --}}
|
||
<div>
|
||
{{-- Placeholder --}}
|
||
<div id="formPlaceholder" class="form-section" style="text-align:center;color:#aaa;min-height:200px;display:flex;flex-direction:column;align-items:center;justify-content:center;">
|
||
<i class="fas fa-hand-point-left" style="font-size:2rem;opacity:.4;margin-bottom:10px;"></i>
|
||
<p style="margin:0;font-size:.85rem;">Pilih materi di sebelah kiri untuk mulai input capaian</p>
|
||
</div>
|
||
|
||
{{-- Form Input --}}
|
||
<div id="formInput" style="display:none;">
|
||
<div class="form-section">
|
||
<h4 id="formTitle"><i class="fas fa-edit"></i> Input Capaian</h4>
|
||
|
||
<form method="POST" action="{{ route('santri.capaian.input.store') }}" id="santriCapaianForm">
|
||
@csrf
|
||
<input type="hidden" name="id_materi" id="id_materi">
|
||
<input type="hidden" name="id_semester" value="{{ $semesterAktif?->id_semester }}">
|
||
|
||
{{-- Materi Info (read) --}}
|
||
<div style="background:#f8fdf9;border-radius:9px;padding:12px;margin-bottom:14px;font-size:.83rem;">
|
||
<div id="info-nama" style="font-weight:700;color:var(--primary-dark);margin-bottom:3px;"></div>
|
||
<div id="info-meta" style="color:#888;"></div>
|
||
</div>
|
||
|
||
{{-- Metode Input --}}
|
||
<div style="margin-bottom:10px;">
|
||
<div style="font-size:.78rem;font-weight:700;color:#555;margin-bottom:6px;">Metode Input:</div>
|
||
<div class="method-tabs">
|
||
<button type="button" class="mt-btn active" onclick="switchMethod(1, this)"><i class="fas fa-keyboard"></i> Range Text</button>
|
||
<button type="button" class="mt-btn" onclick="switchMethod(2, this)"><i class="fas fa-th"></i> Visual Grid</button>
|
||
<button type="button" class="mt-btn" onclick="switchMethod(3, this)"><i class="fas fa-bolt"></i> Quick Input</button>
|
||
</div>
|
||
</div>
|
||
|
||
{{-- Method 1: Range Text --}}
|
||
<div class="method-panel active" id="method1">
|
||
<div class="form-group" style="margin-bottom:8px;">
|
||
<input type="text" id="halaman_selesai" name="halaman_selesai"
|
||
class="form-control" placeholder="Contoh: 1-10, 16-21, 40"
|
||
style="font-size:.85rem;" oninput="onRangeInput(this.value)">
|
||
<small style="color:#999;font-size:.73rem;">Range dengan tanda (-) dan pisahkan koma (,)</small>
|
||
</div>
|
||
<button type="button" class="btn btn-info btn-sm" onclick="previewRange()">
|
||
<i class="fas fa-eye"></i> Preview
|
||
</button>
|
||
</div>
|
||
|
||
{{-- Method 2: Visual Grid --}}
|
||
<div class="method-panel" id="method2">
|
||
<div style="margin-bottom:8px;display:flex;gap:6px;">
|
||
<button type="button" class="btn btn-sm btn-success" onclick="selectAllGrid()"><i class="fas fa-check-square"></i> Semua</button>
|
||
<button type="button" class="btn btn-sm btn-danger" onclick="clearGrid()"><i class="fas fa-times"></i> Reset</button>
|
||
</div>
|
||
<div id="pageGrid" style="display:grid;grid-template-columns:repeat(8,1fr);gap:5px;max-height:280px;overflow-y:auto;"></div>
|
||
</div>
|
||
|
||
{{-- Method 3: Quick Input --}}
|
||
<div class="method-panel" id="method3">
|
||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:8px;">
|
||
<span style="font-size:.83rem;">Halaman 1 sampai</span>
|
||
<input type="number" id="quickVal" class="form-control" style="width:90px;font-size:.83rem;" min="1" placeholder="...">
|
||
<button type="button" class="btn btn-primary btn-sm" onclick="applyQuick()">Terapkan</button>
|
||
</div>
|
||
<button type="button" class="btn btn-sm btn-success" onclick="selectAllQuick()"><i class="fas fa-check-double"></i> Semua Halaman</button>
|
||
</div>
|
||
|
||
{{-- Preview Progress --}}
|
||
<div class="prog-preview" id="progPreview">
|
||
<div class="prog-row">
|
||
<div class="prog-stat"><div class="pv" id="prevHal">0</div><div class="pl">Hal Selesai</div></div>
|
||
<div class="prog-stat"><div class="pv" id="prevTot">0</div><div class="pl">Total Hal</div></div>
|
||
<div class="prog-stat"><div class="pv" id="prevPct" style="color:var(--success-color);">0%</div><div class="pl">Progress</div></div>
|
||
</div>
|
||
<div class="prog-bar"><div class="prog-fill" id="prevBar" style="width:0%;"></div></div>
|
||
</div>
|
||
|
||
{{-- Catatan --}}
|
||
<div class="form-group" style="margin:12px 0 10px;">
|
||
<label style="font-size:.78rem;font-weight:600;color:#555;display:block;margin-bottom:3px;">
|
||
<i class="fas fa-sticky-note"></i> Catatan (opsional)
|
||
</label>
|
||
<textarea name="catatan" class="form-control" rows="2"
|
||
style="font-size:.83rem;" placeholder="Catatan tambahan..."></textarea>
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-bottom:14px;">
|
||
<label style="font-size:.78rem;font-weight:600;color:#555;display:block;margin-bottom:3px;">
|
||
<i class="fas fa-calendar-day"></i> Tanggal Input <span style="color:red;">*</span>
|
||
</label>
|
||
<input type="date" name="tanggal_input" class="form-control"
|
||
value="{{ date('Y-m-d') }}" style="font-size:.83rem;" required>
|
||
</div>
|
||
|
||
<div style="display:flex;gap:8px;">
|
||
<button type="submit" class="btn btn-success" style="flex:1;">
|
||
<i class="fas fa-save"></i> Simpan Capaian
|
||
</button>
|
||
<button type="button" class="btn btn-secondary" onclick="resetForm()">
|
||
<i class="fas fa-undo"></i>
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>{{-- /grid --}}
|
||
|
||
<div style="margin-top:10px;">
|
||
<a href="{{ route('santri.capaian.index') }}" class="btn btn-secondary btn-sm">
|
||
<i class="fas fa-arrow-left"></i> Kembali ke Capaian
|
||
</a>
|
||
</div>
|
||
|
||
<script>
|
||
// ===== STATE =====
|
||
let totalHal = 0, halamanMulai = 1, halamanAkhir = 1;
|
||
let selectedPages = new Set();
|
||
let currentMethod = 1;
|
||
|
||
// Data materi dari PHP
|
||
const materiData = {
|
||
@foreach($materiOptions as $m)
|
||
'{{ $m->id_materi }}': {
|
||
nama: '{{ addslashes($m->nama_kitab) }}',
|
||
kategori: '{{ addslashes($m->kategori) }}',
|
||
total: {{ $m->total_halaman }},
|
||
mulai: {{ $m->halaman_mulai }},
|
||
akhir: {{ $m->halaman_akhir }},
|
||
},
|
||
@endforeach
|
||
};
|
||
|
||
const existingCapaians = {
|
||
@foreach($existingCapaians as $idMateri => $pct)
|
||
// (only id_materi:halaman_selesai is needed but pct is enough for display)
|
||
@endforeach
|
||
};
|
||
|
||
// ===== SELECT MATERI =====
|
||
function selectMateri(idMateri, el) {
|
||
// Remove selection from all cards
|
||
document.querySelectorAll('.materi-card').forEach(c => c.classList.remove('selected'));
|
||
el.classList.add('selected');
|
||
|
||
const m = materiData[idMateri];
|
||
if (!m) return;
|
||
|
||
// Set form
|
||
document.getElementById('id_materi').value = idMateri;
|
||
document.getElementById('formTitle').innerHTML = `<i class="fas fa-edit"></i> Input: ${m.nama}`;
|
||
document.getElementById('info-nama').textContent = m.nama;
|
||
document.getElementById('info-meta').textContent = `${m.kategori} — Hal. ${m.mulai}–${m.akhir} (${m.total} halaman)`;
|
||
|
||
totalHal = m.total;
|
||
halamanMulai = m.mulai;
|
||
halamanAkhir = m.akhir;
|
||
|
||
// Reset pages
|
||
selectedPages = new Set();
|
||
generateGrid();
|
||
document.getElementById('halaman_selesai').value = '';
|
||
hidePreview();
|
||
|
||
// Load existing
|
||
loadExisting(idMateri);
|
||
|
||
document.getElementById('formPlaceholder').style.display = 'none';
|
||
document.getElementById('formInput').style.display = 'block';
|
||
}
|
||
|
||
// ===== LOAD EXISTING CAPAIAN =====
|
||
function loadExisting(idMateri) {
|
||
const idSemester = document.querySelector('[name="id_semester"]').value;
|
||
if (!idSemester) return;
|
||
|
||
fetch('{{ route("santri.capaian.input.ajax.detail") }}', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||
},
|
||
body: JSON.stringify({ id_materi: idMateri, id_semester: idSemester })
|
||
})
|
||
.then(r => r.json())
|
||
.then(data => {
|
||
if (data.existing_capaian && data.existing_capaian.halaman_selesai) {
|
||
const hs = data.existing_capaian.halaman_selesai;
|
||
document.getElementById('halaman_selesai').value = hs;
|
||
selectedPages = parseRange(hs);
|
||
updateGridDisplay();
|
||
updatePreview();
|
||
if (data.existing_capaian.catatan) {
|
||
document.querySelector('[name="catatan"]').value = data.existing_capaian.catatan;
|
||
}
|
||
}
|
||
})
|
||
.catch(() => {});
|
||
}
|
||
|
||
// ===== METHOD SWITCH =====
|
||
function switchMethod(n, btn) {
|
||
currentMethod = n;
|
||
document.querySelectorAll('.method-panel').forEach(p => p.classList.remove('active'));
|
||
document.querySelectorAll('.mt-btn').forEach(b => b.classList.remove('active'));
|
||
document.getElementById('method' + n).classList.add('active');
|
||
btn.classList.add('active');
|
||
if (n === 2) updateGridDisplay();
|
||
syncRange();
|
||
}
|
||
|
||
// ===== RANGE TEXT =====
|
||
function onRangeInput(val) {
|
||
if (!val.trim()) { selectedPages.clear(); hidePreview(); return; }
|
||
selectedPages = parseRange(val);
|
||
updatePreview();
|
||
}
|
||
|
||
function previewRange() {
|
||
const val = document.getElementById('halaman_selesai').value.trim();
|
||
if (!val) { alert('Masukkan range halaman dulu!'); return; }
|
||
selectedPages = parseRange(val);
|
||
updateGridDisplay();
|
||
updatePreview();
|
||
}
|
||
|
||
// ===== GRID =====
|
||
function generateGrid() {
|
||
const grid = document.getElementById('pageGrid');
|
||
grid.innerHTML = '';
|
||
for (let i = halamanMulai; i <= halamanAkhir; i++) {
|
||
const box = document.createElement('div');
|
||
box.id = 'pg-' + i;
|
||
box.textContent = i;
|
||
box.style.cssText = 'padding:6px;border:1.5px solid #ddd;border-radius:6px;text-align:center;cursor:pointer;font-size:.7rem;font-weight:600;background:#fff;transition:all .15s;';
|
||
box.onclick = () => togglePage(i);
|
||
grid.appendChild(box);
|
||
}
|
||
}
|
||
|
||
function togglePage(i) {
|
||
if (selectedPages.has(i)) selectedPages.delete(i);
|
||
else selectedPages.add(i);
|
||
updateGridDisplay();
|
||
updatePreview();
|
||
syncRange();
|
||
}
|
||
|
||
function updateGridDisplay() {
|
||
for (let i = halamanMulai; i <= halamanAkhir; i++) {
|
||
const box = document.getElementById('pg-' + i);
|
||
if (!box) continue;
|
||
if (selectedPages.has(i)) {
|
||
box.style.background = 'linear-gradient(135deg,var(--primary-color),var(--success-color))';
|
||
box.style.borderColor = 'var(--primary-color)';
|
||
box.style.color = '#fff';
|
||
} else {
|
||
box.style.background = '#fff';
|
||
box.style.borderColor = '#ddd';
|
||
box.style.color = '#333';
|
||
}
|
||
}
|
||
}
|
||
|
||
function selectAllGrid() {
|
||
selectedPages.clear();
|
||
for (let i = halamanMulai; i <= halamanAkhir; i++) selectedPages.add(i);
|
||
updateGridDisplay();
|
||
updatePreview();
|
||
syncRange();
|
||
}
|
||
|
||
function clearGrid() {
|
||
selectedPages.clear();
|
||
updateGridDisplay();
|
||
hidePreview();
|
||
syncRange();
|
||
}
|
||
|
||
// ===== QUICK =====
|
||
function applyQuick() {
|
||
const v = parseInt(document.getElementById('quickVal').value);
|
||
if (!v || v < 1) { alert('Masukkan nilai!'); return; }
|
||
selectedPages.clear();
|
||
for (let i = halamanMulai; i <= Math.min(halamanMulai + v - 1, halamanAkhir); i++) selectedPages.add(i);
|
||
updatePreview();
|
||
syncRange();
|
||
}
|
||
|
||
function selectAllQuick() {
|
||
selectedPages.clear();
|
||
for (let i = halamanMulai; i <= halamanAkhir; i++) selectedPages.add(i);
|
||
updatePreview();
|
||
syncRange();
|
||
}
|
||
|
||
// ===== SYNC RANGE INPUT =====
|
||
function syncRange() {
|
||
if (selectedPages.size === 0) {
|
||
document.getElementById('halaman_selesai').value = '';
|
||
return;
|
||
}
|
||
const sorted = [...selectedPages].sort((a,b) => a-b);
|
||
document.getElementById('halaman_selesai').value = toRangeString(sorted);
|
||
}
|
||
|
||
// ===== HELPERS =====
|
||
function parseRange(str) {
|
||
const pages = new Set();
|
||
str.split(',').forEach(part => {
|
||
part = part.trim();
|
||
if (part.includes('-')) {
|
||
const [s, e] = part.split('-').map(n => parseInt(n.trim()));
|
||
for (let i = s; i <= e; i++) { if (i >= halamanMulai && i <= halamanAkhir) pages.add(i); }
|
||
} else {
|
||
const n = parseInt(part);
|
||
if (n >= halamanMulai && n <= halamanAkhir) pages.add(n);
|
||
}
|
||
});
|
||
return pages;
|
||
}
|
||
|
||
function toRangeString(arr) {
|
||
if (!arr.length) return '';
|
||
const ranges = [];
|
||
let s = arr[0], e = arr[0];
|
||
for (let i = 1; i < arr.length; i++) {
|
||
if (arr[i] === e + 1) { e = arr[i]; }
|
||
else { ranges.push(s === e ? `${s}` : `${s}-${e}`); s = e = arr[i]; }
|
||
}
|
||
ranges.push(s === e ? `${s}` : `${s}-${e}`);
|
||
return ranges.join(',');
|
||
}
|
||
|
||
function updatePreview() {
|
||
const jml = selectedPages.size;
|
||
const pct = totalHal > 0 ? ((jml / totalHal) * 100).toFixed(1) : 0;
|
||
document.getElementById('prevHal').textContent = jml;
|
||
document.getElementById('prevTot').textContent = totalHal;
|
||
document.getElementById('prevPct').textContent = pct + '%';
|
||
document.getElementById('prevBar').style.width = pct + '%';
|
||
document.getElementById('progPreview').classList.add('show');
|
||
}
|
||
|
||
function hidePreview() {
|
||
document.getElementById('progPreview').classList.remove('show');
|
||
}
|
||
|
||
function resetForm() {
|
||
selectedPages.clear();
|
||
document.getElementById('halaman_selesai').value = '';
|
||
document.querySelectorAll('.materi-card').forEach(c => c.classList.remove('selected'));
|
||
document.getElementById('formPlaceholder').style.display = 'flex';
|
||
document.getElementById('formInput').style.display = 'none';
|
||
hidePreview();
|
||
}
|
||
|
||
// Form validation
|
||
document.getElementById('santriCapaianForm')?.addEventListener('submit', function(e) {
|
||
const hs = document.getElementById('halaman_selesai').value.trim();
|
||
if (!hs) {
|
||
e.preventDefault();
|
||
alert('Silakan input halaman yang sudah selesai!');
|
||
}
|
||
});
|
||
</script>
|
||
@endsection |