/**
* CRUD Stasiun Kerja - Vanilla JS (fetch API)
*
* Catatan penting soal CSRF & session (biar tidak kejadian lagi
* seperti "CSRF token mismatch" / auto-logout):
* 1. Selalu kirim header X-CSRF-TOKEN dari meta tag .
* Pastikan tag ini ADA di
layout utama:
*
* 2. Selalu set credentials: 'same-origin' supaya cookie session ikut terkirim.
* 3. Endpoint diambil dari window.STASIUNKERJA_ENDPOINT (di-inject dari Blade
* pakai url()), BUKAN di-hardcode, supaya otomatis ikut host/port yang aktif.
*/
(function () {
"use strict";
const ENDPOINT = window.STASIUNKERJA_ENDPOINT; // contoh: http://localhost:8888/stasiunkerja
const CSRF_TOKEN = document.querySelector('meta[name="csrf-token"]')?.content;
if (!CSRF_TOKEN) {
console.error(
'Meta tag csrf-token tidak ditemukan. Tambahkan di head layout.',
);
}
const tbody = document.getElementById("tbodyStasiunKerja");
const modalEl = document.getElementById("modalStasiunKerja");
const modal = new bootstrap.Modal(modalEl);
const form = document.getElementById("formStasiunKerja");
const btnTambah = document.getElementById("btnTambah");
const modalTitle = document.getElementById("modalStasiunKerjaTitle");
const inputMode = document.getElementById("inputMode");
const inputKodeOriginal = document.getElementById("inputKodeOriginal");
const inputKode = document.getElementById("inputKode");
const inputNama = document.getElementById("inputNama");
const inputMargin = document.getElementById("inputMargin");
const inputTarget = document.getElementById("inputTarget");
const inputStatus = document.getElementById("inputStatus");
const inputKodeAkses = document.getElementById("inputKodeAkses");
const inputSpv = document.getElementById("inputSpv");
const inputIdLokasi = document.getElementById("inputIdLokasi");
const inputLantai = document.getElementById("inputLantai");
const inputBank = document.getElementById("inputBank");
const inputTelp = document.getElementById("inputTelp");
const inputAlamat = document.getElementById("inputAlamat");
/**
* Notifikasi interaktif pengganti alert()/confirm() bawaan browser.
* SweetAlert2 wajib di-load di view (vendor/sweetalert2).
*/
function info(icon, title, text) {
return Swal.fire({ icon, title, text });
}
function loadingRow(colspan, text) {
return `
${text}
`;
}
/**
* Helper fetch generik dengan header CSRF + credentials.
*/
async function apiFetch(url, options = {}) {
const headers = Object.assign(
{
Accept: "application/json",
"X-Requested-With": "XMLHttpRequest",
"X-CSRF-TOKEN": CSRF_TOKEN,
},
options.headers || {},
);
// Kalau body berupa object biasa (bukan FormData), kirim sebagai JSON.
if (options.body && !(options.body instanceof FormData)) {
headers["Content-Type"] = "application/json";
options.body = JSON.stringify(options.body);
}
const response = await fetch(url, {
credentials: "same-origin", // WAJIB supaya cookie session ikut terkirim
...options,
headers,
});
// Kalau sesi habis / tidak ter-autentikasi, kasih info lalu redirect ke login
// daripada diam-diam gagal.
if (response.status === 401 || response.status === 419) {
info("warning", "Sesi habis", "Sesi kamu sudah habis, silakan login ulang.").then(() => {
window.location.href = "/login";
});
throw new Error("Unauthenticated / session expired");
}
const json = await response.json().catch(() => null);
if (!response.ok) {
const error = new Error(json?.message || "Terjadi kesalahan pada server.");
error.status = response.status;
error.payload = json;
throw error;
}
return json;
}
/**
* Escape teks sederhana biar aman ditaruh ke innerHTML (mencegah XSS dasar).
*/
function escapeHtml(text) {
if (text === null || text === undefined) return "";
return String(text)
.replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
/**
* Render baris tabel dari array data.
*/
function renderTable(rows) {
tbody.innerHTML = "";
if (!rows.length) {
tbody.innerHTML = `