init backend presensi
This commit is contained in:
178
app/Views/dashboard/presence_settings.php
Normal file
178
app/Views/dashboard/presence_settings.php
Normal file
@@ -0,0 +1,178 @@
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
<h1 class="text-xl font-semibold">Pengaturan Presensi</h1>
|
||||
<p class="text-gray-600 dark:text-gray-400 mt-1">Satu pengaturan terpusat: <strong>koordinat sekolah</strong> (untuk semua absen) dan <strong>jadwal jam masuk & jam pulang</strong>.</p>
|
||||
</div>
|
||||
|
||||
<div id="presence-loading" class="rounded-2xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-12 text-center text-gray-500 dark:text-gray-400">
|
||||
Memuat…
|
||||
</div>
|
||||
<div id="presence-error" class="hidden rounded-2xl border border-red-200 dark:border-red-800 bg-red-50 dark:bg-red-900/20 p-6 text-red-700 dark:text-red-300"></div>
|
||||
<div id="presence-form-wrap" class="hidden space-y-6">
|
||||
<!-- Zona sekolah -->
|
||||
<div class="rounded-2xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 shadow-sm p-6">
|
||||
<h2 class="text-base font-semibold text-gray-900 dark:text-gray-100 mb-1">Koordinat Sekolah (Zona Presensi)</h2>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400 mb-4">Semua absen (mobile & device) hanya valid jika siswa berada di dalam radius ini.</p>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||
<div>
|
||||
<label class="block mb-1 text-sm text-gray-600 dark:text-gray-300">Latitude</label>
|
||||
<input type="number" step="0.00000001" id="zone-lat" class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block mb-1 text-sm text-gray-600 dark:text-gray-300">Longitude</label>
|
||||
<input type="number" step="0.00000001" id="zone-lng" class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block mb-1 text-sm text-gray-600 dark:text-gray-300">Radius (meter)</label>
|
||||
<input type="number" min="1" id="zone-radius" class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Jam masuk & pulang -->
|
||||
<div class="rounded-2xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 shadow-sm p-6">
|
||||
<h2 class="text-base font-semibold text-gray-900 dark:text-gray-100 mb-1">Jadwal Masuk & Pulang</h2>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400 mb-4">Window waktu untuk absen masuk dan absen pulang (format 24 jam).</p>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div>
|
||||
<label class="block mb-1 text-sm text-gray-600 dark:text-gray-300">Jam masuk (mulai)</label>
|
||||
<input type="time" id="time-masuk-start" class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block mb-1 text-sm text-gray-600 dark:text-gray-300">Jam masuk (akhir)</label>
|
||||
<input type="time" id="time-masuk-end" class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block mb-1 text-sm text-gray-600 dark:text-gray-300">Jam pulang (mulai)</label>
|
||||
<input type="time" id="time-pulang-start" class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block mb-1 text-sm text-gray-600 dark:text-gray-300">Jam pulang (akhir)</label>
|
||||
<input type="time" id="time-pulang-end" class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end">
|
||||
<button type="button" id="btn-save" class="inline-flex items-center justify-center px-5 py-2.5 rounded-lg bg-primary text-white text-sm font-medium hover:bg-primary-hover">
|
||||
Simpan Pengaturan
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var baseUrl = '<?= base_url() ?>'.replace(/\/$/, '');
|
||||
var apiUrl = baseUrl + '/api/dashboard/presence-settings';
|
||||
|
||||
var loading = document.getElementById('presence-loading');
|
||||
var errorEl = document.getElementById('presence-error');
|
||||
var formWrap = document.getElementById('presence-form-wrap');
|
||||
var zoneLat = document.getElementById('zone-lat');
|
||||
var zoneLng = document.getElementById('zone-lng');
|
||||
var zoneRadius = document.getElementById('zone-radius');
|
||||
var timeMasukStart = document.getElementById('time-masuk-start');
|
||||
var timeMasukEnd = document.getElementById('time-masuk-end');
|
||||
var timePulangStart = document.getElementById('time-pulang-start');
|
||||
var timePulangEnd = document.getElementById('time-pulang-end');
|
||||
var btnSave = document.getElementById('btn-save');
|
||||
|
||||
function showError(msg) {
|
||||
errorEl.textContent = msg || 'Terjadi kesalahan';
|
||||
errorEl.classList.remove('hidden');
|
||||
formWrap.classList.add('hidden');
|
||||
}
|
||||
|
||||
function timeToHhMm(val) {
|
||||
if (!val) return '';
|
||||
if (val.length === 5 && val.indexOf(':') !== -1) return val;
|
||||
var parts = (val + '').trim().split(/[:\s]/);
|
||||
if (parts.length >= 2) return parts[0].padStart(2, '0') + ':' + parts[1].padStart(2, '0');
|
||||
return val.substring(0, 5);
|
||||
}
|
||||
|
||||
function hhMmToTimeInput(hhmmss) {
|
||||
if (!hhmmss) return '';
|
||||
var s = (hhmmss + '').trim();
|
||||
if (s.length >= 5) return s.substring(0, 5);
|
||||
return s;
|
||||
}
|
||||
|
||||
function load() {
|
||||
loading.classList.remove('hidden');
|
||||
errorEl.classList.add('hidden');
|
||||
formWrap.classList.add('hidden');
|
||||
fetch(apiUrl, { method: 'GET', headers: { 'X-Requested-With': 'XMLHttpRequest' }, credentials: 'same-origin' })
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(res) {
|
||||
loading.classList.add('hidden');
|
||||
if (res && res.success && res.data) {
|
||||
var zone = res.data.zone || {};
|
||||
var times = res.data.times || {};
|
||||
zoneLat.value = zone.latitude != null ? zone.latitude : '';
|
||||
zoneLng.value = zone.longitude != null ? zone.longitude : '';
|
||||
zoneRadius.value = zone.radius_meters != null ? zone.radius_meters : '150';
|
||||
timeMasukStart.value = hhMmToTimeInput(times.time_masuk_start);
|
||||
timeMasukEnd.value = hhMmToTimeInput(times.time_masuk_end);
|
||||
timePulangStart.value = hhMmToTimeInput(times.time_pulang_start);
|
||||
timePulangEnd.value = hhMmToTimeInput(times.time_pulang_end);
|
||||
formWrap.classList.remove('hidden');
|
||||
} else {
|
||||
showError(res && res.message ? res.message : 'Gagal memuat pengaturan');
|
||||
}
|
||||
})
|
||||
.catch(function() {
|
||||
loading.classList.add('hidden');
|
||||
showError('Gagal memuat pengaturan (jaringan).');
|
||||
});
|
||||
}
|
||||
|
||||
btnSave.addEventListener('click', function() {
|
||||
var lat = parseFloat(zoneLat.value);
|
||||
var lng = parseFloat(zoneLng.value);
|
||||
var radius = parseInt(zoneRadius.value, 10);
|
||||
if (isNaN(lat) || isNaN(lng) || isNaN(radius) || radius < 1) {
|
||||
alert('Isi koordinat sekolah (Latitude, Longitude, Radius) dengan benar.');
|
||||
return;
|
||||
}
|
||||
var payload = {
|
||||
zone: {
|
||||
latitude: lat,
|
||||
longitude: lng,
|
||||
radius_meters: radius,
|
||||
zone_name: 'Zona Sekolah'
|
||||
},
|
||||
times: {
|
||||
time_masuk_start: timeToHhMm(timeMasukStart.value) + ':00',
|
||||
time_masuk_end: timeToHhMm(timeMasukEnd.value) + ':00',
|
||||
time_pulang_start: timeToHhMm(timePulangStart.value) + ':00',
|
||||
time_pulang_end: timeToHhMm(timePulangEnd.value) + ':00'
|
||||
}
|
||||
};
|
||||
btnSave.disabled = true;
|
||||
fetch(apiUrl, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify(payload)
|
||||
})
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(res) {
|
||||
btnSave.disabled = false;
|
||||
if (res && res.success) {
|
||||
if (typeof showToast === 'function') showToast('Pengaturan presensi berhasil disimpan', 'success');
|
||||
else alert('Pengaturan berhasil disimpan.');
|
||||
} else {
|
||||
alert(res && res.message ? res.message : 'Gagal menyimpan');
|
||||
}
|
||||
})
|
||||
.catch(function() {
|
||||
btnSave.disabled = false;
|
||||
alert('Gagal menyimpan (jaringan).');
|
||||
});
|
||||
});
|
||||
|
||||
load();
|
||||
})();
|
||||
</script>
|
||||
Reference in New Issue
Block a user