init backend presensi
This commit is contained in:
114
app/Views/dashboard/devices.php
Normal file
114
app/Views/dashboard/devices.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<div class="space-y-6">
|
||||
<h1 class="text-xl font-semibold">Device Absen</h1>
|
||||
<p class="text-gray-600 dark:text-gray-400 text-sm">Daftar perangkat absensi dan status online. Koordinat presensi diatur terpusat di <a href="<?= base_url('dashboard/presence-settings') ?>" class="text-primary hover:underline">Pengaturan Presensi</a>.</p>
|
||||
|
||||
<div id="devices-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">
|
||||
Loading…
|
||||
</div>
|
||||
<div id="devices-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="devices-content" class="hidden rounded-2xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 shadow-sm overflow-hidden">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left">
|
||||
<thead class="bg-gray-50 dark:bg-gray-700/50 text-sm text-gray-600 dark:text-gray-400">
|
||||
<tr>
|
||||
<th class="px-6 py-3 font-medium">Device Code</th>
|
||||
<th class="px-6 py-3 font-medium">Device Name</th>
|
||||
<th class="px-6 py-3 font-medium">Active</th>
|
||||
<th class="px-6 py-3 font-medium">Last Seen</th>
|
||||
<th class="px-6 py-3 font-medium">Status</th>
|
||||
<th class="px-6 py-3 font-medium">Zona</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="devices-tbody" class="divide-y divide-gray-200 dark:divide-gray-700"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var baseUrl = '<?= base_url() ?>'.replace(/\/$/, '');
|
||||
var apiUrl = baseUrl + '/api/dashboard/devices';
|
||||
|
||||
var loading = document.getElementById('devices-loading');
|
||||
var errorEl = document.getElementById('devices-error');
|
||||
var content = document.getElementById('devices-content');
|
||||
var tbody = document.getElementById('devices-tbody');
|
||||
|
||||
var currentDevices = [];
|
||||
|
||||
function showLoading() {
|
||||
loading.classList.remove('hidden');
|
||||
errorEl.classList.add('hidden');
|
||||
content.classList.add('hidden');
|
||||
}
|
||||
function showError(msg) {
|
||||
loading.classList.add('hidden');
|
||||
content.classList.add('hidden');
|
||||
errorEl.classList.remove('hidden');
|
||||
errorEl.textContent = msg;
|
||||
}
|
||||
function showContent() {
|
||||
loading.classList.add('hidden');
|
||||
errorEl.classList.add('hidden');
|
||||
content.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
if (str == null) return '';
|
||||
var div = document.createElement('div');
|
||||
div.textContent = str;
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function loadDevices() {
|
||||
showLoading();
|
||||
fetch(apiUrl, { method: 'GET', credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest' } })
|
||||
.then(function(res) { return res.json().then(function(j) { return { ok: res.ok, data: j }; }); })
|
||||
.then(function(r) {
|
||||
if (!r.ok) {
|
||||
showError(r.data && r.data.message ? r.data.message : 'Failed to load devices');
|
||||
return;
|
||||
}
|
||||
var list = r.data && r.data.data ? r.data.data : r.data;
|
||||
if (!Array.isArray(list)) {
|
||||
showError('Invalid response');
|
||||
return;
|
||||
}
|
||||
currentDevices = list;
|
||||
tbody.innerHTML = '';
|
||||
list.forEach(function(row) {
|
||||
var tr = document.createElement('tr');
|
||||
tr.className = 'hover:bg-gray-50 dark:hover:bg-gray-700/30';
|
||||
var activeText = row.is_active ? 'Yes' : 'No';
|
||||
var activeClass = row.is_active ? 'text-green-600 dark:text-green-400' : 'text-gray-500 dark:text-gray-400';
|
||||
var lastSeen = row.last_seen_at ? escapeHtml(row.last_seen_at) : '–';
|
||||
var status = (row.online_status || 'offline').toLowerCase();
|
||||
var statusClass = status === 'online'
|
||||
? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400'
|
||||
: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-400';
|
||||
var statusLabel = status === 'online' ? 'Online' : 'Offline';
|
||||
|
||||
var zoneText = 'Terpusat (zona sekolah)';
|
||||
|
||||
tr.innerHTML =
|
||||
'<td class="px-6 py-3 font-medium">' + escapeHtml(row.device_code) + '</td>' +
|
||||
'<td class="px-6 py-3 text-gray-600 dark:text-gray-400">' + escapeHtml(row.device_name) + '</td>' +
|
||||
'<td class="px-6 py-3 ' + activeClass + '">' + escapeHtml(activeText) + '</td>' +
|
||||
'<td class="px-6 py-3 text-gray-600 dark:text-gray-400">' + lastSeen + '</td>' +
|
||||
'<td class="px-6 py-3"><span class="inline-flex px-2.5 py-0.5 rounded-full text-xs font-medium ' + statusClass + '">' + escapeHtml(statusLabel) + '</span></td>' +
|
||||
'<td class="px-6 py-3 text-gray-600 dark:text-gray-400 text-xs">' + escapeHtml(zoneText) + '</td>';
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
showContent();
|
||||
})
|
||||
.catch(function() {
|
||||
showError('Network error');
|
||||
});
|
||||
}
|
||||
|
||||
// Init
|
||||
loadDevices();
|
||||
})();
|
||||
</script>
|
||||
Reference in New Issue
Block a user