111 lines
5.8 KiB
PHP
111 lines
5.8 KiB
PHP
<!DOCTYPE html>
|
|
<html lang="id" data-theme="light">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
|
<title>Konfigurasi Sistem - WebGIS</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/daisyui@4/dist/full.min.css" rel="stylesheet">
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
|
|
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap" rel="stylesheet">
|
|
<style>
|
|
* { font-family: 'Plus Jakarta Sans', sans-serif; }
|
|
body { font-weight: 500; background-color: #f8fafc; }
|
|
h1, h2, h3, .btn { font-weight: 700 !important; letter-spacing: -0.01em; }
|
|
</style>
|
|
<link rel="stylesheet" href="{{ asset('css/genesis.css') }}">
|
|
</head>
|
|
<body class="min-h-screen app-body">
|
|
@include('partials.sidebar')
|
|
|
|
<main class="app-main">
|
|
<div class="max-w-screen-xl mx-auto px-4 py-8">
|
|
<div class="mb-8">
|
|
<h1 class="text-3xl font-bold flex items-center gap-3"><i class="fa-solid fa-sliders text-primary"></i> Konfigurasi Sistem</h1>
|
|
<p class="text-base-content/50 mt-1">Atur parameter peta dan analisis. Perubahan berlaku setelah halaman peta di-refresh.</p>
|
|
</div>
|
|
|
|
<div id="settingsForm" class="bg-white rounded-2xl shadow-sm border border-base-200 p-6 max-w-2xl">
|
|
<p class="text-center py-8 opacity-30 italic" id="settingsLoading">Memuat pengaturan...</p>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<div class="toast toast-end toast-bottom z-[9999]" id="toastBox"></div>
|
|
|
|
<script>
|
|
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
|
function esc(s) { return String(s).replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); }
|
|
|
|
const settingMeta = {
|
|
map_center_lat: { type: 'number', step: '0.0001', label: 'Pusat Peta — Latitude', hint: 'Contoh: -0.0553 (Pontianak)' },
|
|
map_center_lng: { type: 'number', step: '0.0001', label: 'Pusat Peta — Longitude', hint: 'Contoh: 109.3463 (Pontianak)' },
|
|
map_default_zoom: { type: 'number', step: '1', min: '5', max: '19', label: 'Zoom Default Peta', hint: '1 (jauh) — 19 (dekat)' },
|
|
radius_min: { type: 'number', step: '50', min: '50', max: '500', label: 'Radius Minimum (meter)', hint: 'Minimal 50 m' },
|
|
radius_max: { type: 'number', step: '50', min: '500', max: '5000', label: 'Radius Maksimum (meter)', hint: 'Maksimal 5000 m' },
|
|
};
|
|
|
|
document.addEventListener('DOMContentLoaded', loadSettings);
|
|
|
|
async function loadSettings() {
|
|
const res = await fetch('{{ url('/api/admin/settings') }}', { headers: { 'X-CSRF-TOKEN': csrfToken } });
|
|
const settings = await res.json();
|
|
|
|
const form = document.getElementById('settingsForm');
|
|
form.innerHTML = settings.map(s => {
|
|
const m = settingMeta[s.key] || { type: 'text', label: s.label };
|
|
const extra = ['min', 'max', 'step'].map(a => m[a] ? `${a}="${esc(m[a])}"` : '').join(' ');
|
|
return `
|
|
<div class="form-control mb-5" id="row_${esc(s.key)}">
|
|
<label class="label pb-1">
|
|
<span class="label-text font-bold">${esc(s.label)}</span>
|
|
${m.hint ? `<span class="label-text-alt opacity-50">${esc(m.hint)}</span>` : ''}
|
|
</label>
|
|
<div class="flex gap-2">
|
|
<input id="input_${esc(s.key)}" type="${m.type || 'text'}" ${extra}
|
|
value="${esc(s.value)}"
|
|
class="input input-bordered flex-1 font-mono"
|
|
data-key="${esc(s.key)}">
|
|
<button onclick="saveSetting('${esc(s.key)}')" class="btn btn-primary btn-sm">
|
|
<i class="fa-solid fa-floppy-disk mr-1"></i>Simpan
|
|
</button>
|
|
</div>
|
|
</div>`;
|
|
}).join('<div class="divider my-2"></div>') + `
|
|
<div class="mt-6 alert alert-info text-sm">
|
|
<i class="fa-solid fa-circle-info"></i>
|
|
<span>Setelah menyimpan, buka ulang halaman <a href="{{ url('/map') }}" class="link font-bold">Peta Interaktif</a> untuk melihat perubahan.</span>
|
|
</div>`;
|
|
}
|
|
|
|
async function saveSetting(key) {
|
|
const input = document.getElementById(`input_${key}`);
|
|
const value = input.value.trim();
|
|
if (!value) { showToast('Nilai tidak boleh kosong', 'error'); return; }
|
|
|
|
const res = await fetch(`{{ url('/api/admin/settings') }}/${key}`, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken },
|
|
body: JSON.stringify({ value }),
|
|
});
|
|
const json = await res.json();
|
|
if (json.success) {
|
|
showToast('Pengaturan disimpan', 'success');
|
|
} else {
|
|
showToast(json.message || 'Gagal menyimpan', 'error');
|
|
}
|
|
}
|
|
|
|
function showToast(msg, type = 'info') {
|
|
const t = document.createElement('div');
|
|
const cls = type === 'success' ? 'alert-success' : type === 'error' ? 'alert-error' : 'alert-info';
|
|
t.className = `alert ${cls} shadow-lg py-3 text-xs font-bold`;
|
|
t.innerHTML = `<span><i class="fa-solid fa-circle-info mr-2"></i>${esc(msg)}</span>`;
|
|
document.getElementById('toastBox').appendChild(t);
|
|
setTimeout(() => t.remove(), 3000);
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|