 <?php
// ============================================
// ⚙️ KONFIGURASI DATABASE - GANTI DI SINI!
// ============================================
$DB_HOST = "db-thesa-1-instance-1.c2dxumubfces.us-east-1.rds.amazonaws.com";
$DB_PORT = "3306";
$DB_USER = "admin";
$DB_PASS = "12345678";
$DB_NAME = "db_thesa";
// ============================================

if (isset($_GET['api'])) {
    header('Content-Type: application/json');

    try {
        $pdo = new PDO("mysql:host=$DB_HOST;port=$DB_PORT;dbname=$DB_NAME", $DB_USER, $DB_PASS,
            [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]);
    } catch (PDOException $e) {
        die(json_encode(['error' => 'Koneksi gagal: ' . $e->getMessage()]));
    }

    $api = $_GET['api'];

    // LIST
    if ($api === 'list') {
        $search = $_GET['search'] ?? '';
        $page = max(1, intval($_GET['page'] ?? 1));
        $limit = max(1, min(100, intval($_GET['limit'] ?? 10)));
        $offset = ($page - 1) * $limit;
        $sort = $_GET['sort'] ?? 'id';
        $order = strtoupper($_GET['order'] ?? 'DESC') === 'ASC' ? 'ASC' : 'DESC';
        $allowed = ['id','nama_barang','harga','stok'];
        if (!in_array($sort, $allowed)) $sort = 'id';

        $where = '';
        $params = [];
        if ($search) {
            $where = "WHERE nama_barang LIKE :s";
            $params[':s'] = "%$search%";
        }

        $cnt = $pdo->prepare("SELECT COUNT(*) as t FROM tbl_barang $where");
        $cnt->execute($params);
        $total = $cnt->fetch()['t'];

        $q = $pdo->prepare("SELECT * FROM tbl_barang $where ORDER BY $sort $order LIMIT :l OFFSET :o");
        foreach ($params as $k => $v) $q->bindValue($k, $v);
        $q->bindValue(':l', $limit, PDO::PARAM_INT);
        $q->bindValue(':o', $offset, PDO::PARAM_INT);
        $q->execute();

        die(json_encode(['data' => $q->fetchAll(), 'total' => (int)$total, 'page' => $page, 'pages' => ceil($total / $limit)]));
    }

    // CREATE
    if ($api === 'create' && $_SERVER['REQUEST_METHOD'] === 'POST') {
        $d = json_decode(file_get_contents('php://input'), true);
        if (!$d || !$d['nama_barang']) die(json_encode(['error' => 'Nama wajib diisi']));
        $q = $pdo->prepare("INSERT INTO tbl_barang (nama_barang, harga, stok) VALUES (:n, :h, :s)");
        $q->execute([':n' => $d['nama_barang'], ':h' => floatval($d['harga']), ':s' => intval($d['stok'])]);
        die(json_encode(['ok' => true, 'msg' => 'Barang ditambahkan']));
    }

    // UPDATE
    if ($api === 'update' && $_SERVER['REQUEST_METHOD'] === 'PUT') {
        $id = intval($_GET['id'] ?? 0);
        $d = json_decode(file_get_contents('php://input'), true);
        if (!$id || !$d) die(json_encode(['error' => 'Data tidak valid']));
        $q = $pdo->prepare("UPDATE tbl_barang SET nama_barang=:n, harga=:h, stok=:s WHERE id=:id");
        $q->execute([':n' => $d['nama_barang'], ':h' => floatval($d['harga']), ':s' => intval($d['stok']), ':id' => $id]);
        die(json_encode(['ok' => true, 'msg' => 'Barang diupdate']));
    }

    // DELETE
    if ($api === 'delete' && $_SERVER['REQUEST_METHOD'] === 'DELETE') {
        $id = intval($_GET['id'] ?? 0);
        if (!$id) die(json_encode(['error' => 'ID tidak valid']));
        $pdo->prepare("DELETE FROM tbl_barang WHERE id=:id")->execute([':id' => $id]);
        die(json_encode(['ok' => true, 'msg' => 'Barang dihapus']));
    }

    die(json_encode(['error' => 'Endpoint tidak ditemukan']));
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Manajemen Barang</title>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
    <style>
        *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

        :root {
            --bg: #0a0e1a;
            --bg-card: rgba(17, 24, 39, 0.75);
            --bg-input: rgba(15, 23, 42, 0.8);
            --border: rgba(99, 102, 241, 0.15);
            --border-hover: rgba(99, 102, 241, 0.4);
            --text: #f1f5f9;
            --text-sub: #94a3b8;
            --text-muted: #64748b;
            --accent: #6366f1;
            --accent-light: #818cf8;
            --accent-glow: rgba(99, 102, 241, 0.3);
            --green: #22c55e;
            --red: #ef4444;
            --radius: 12px;
        }

        body {
            font-family: 'Inter', sans-serif;
            background: var(--bg);
            color: var(--text);
            min-height: 100vh;
        }

        .bg-orbs { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
        .bg-orbs div { position: absolute; border-radius: 50%; filter: blur(100px); opacity: 0.1; animation: orb-float 20s ease-in-out infinite; }
        .bg-orbs div:nth-child(1) { width: 500px; height: 500px; background: #6366f1; top: -10%; left: -5%; }
        .bg-orbs div:nth-child(2) { width: 400px; height: 400px; background: #8b5cf6; bottom: -5%; right: -5%; animation-delay: -10s; }
        @keyframes orb-float { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(30px, -30px); } }

        .app { position: relative; z-index: 1; max-width: 1100px; margin: 0 auto; padding: 24px; }

        .header {
            display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 14px;
            padding: 20px 24px; background: var(--bg-card); backdrop-filter: blur(20px);
            border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: 24px;
            animation: slideDown 0.5s ease-out;
        }
        @keyframes slideDown { from { opacity: 0; transform: translateY(-16px); } to { opacity: 1; transform: translateY(0); } }
        .header .title { display: flex; align-items: center; gap: 12px; }
        .header .title .icon {
            width: 42px; height: 42px; background: linear-gradient(135deg, #6366f1, #8b5cf6);
            border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 20px;
            box-shadow: 0 0 20px var(--accent-glow);
        }
        .header .title h1 {
            font-size: 1.3rem; font-weight: 700;
            background: linear-gradient(135deg, #6366f1, #a78bfa);
            -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
        }
        .header .status {
            display: flex; align-items: center; gap: 8px; padding: 8px 14px;
            border-radius: 8px; font-size: 0.8rem; font-weight: 500;
            border: 1px solid var(--border); background: var(--bg-input);
        }
        .header .status .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-muted); }
        .header .status.ok .dot { background: var(--green); box-shadow: 0 0 8px rgba(34,197,94,0.5); animation: pulse 2s ease-in-out infinite; }
        .header .status.err .dot { background: var(--red); box-shadow: 0 0 8px rgba(239,68,68,0.5); }
        @keyframes pulse { 0%,100% { opacity:1; } 50% { opacity:0.5; } }

        .toolbar {
            display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 20px;
            animation: fadeUp 0.5s ease-out 0.15s both;
        }
        @keyframes fadeUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
        .search-box { flex: 1; min-width: 200px; position: relative; }
        .search-box input {
            width: 100%; padding: 11px 14px 11px 40px; background: var(--bg-card); backdrop-filter: blur(20px);
            border: 1px solid var(--border); border-radius: var(--radius); color: var(--text);
            font-size: 0.9rem; font-family: inherit; outline: none; transition: all 0.3s;
        }
        .search-box input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }
        .search-box input::placeholder { color: var(--text-muted); }
        .search-box .ico { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: var(--text-muted); pointer-events: none; }

        .btn {
            display: inline-flex; align-items: center; gap: 7px; padding: 11px 18px; border: none;
            border-radius: var(--radius); font-size: 0.88rem; font-weight: 600; font-family: inherit;
            cursor: pointer; transition: all 0.3s; white-space: nowrap;
        }
        .btn-primary { background: linear-gradient(135deg, #6366f1, #8b5cf6); color: #fff; }
        .btn-primary:hover { transform: translateY(-1px); box-shadow: 0 0 24px var(--accent-glow); }
        .btn-ghost { background: transparent; color: var(--text-sub); border: 1px solid var(--border); }
        .btn-ghost:hover { background: rgba(99,102,241,0.08); border-color: var(--border-hover); color: var(--text); }
        .btn-danger { background: rgba(239,68,68,0.1); color: var(--red); border: 1px solid rgba(239,68,68,0.2); }
        .btn-danger:hover { background: rgba(239,68,68,0.2); }
        .btn-sm { padding: 7px 11px; font-size: 0.8rem; border-radius: 8px; }

        .table-wrap {
            background: var(--bg-card); backdrop-filter: blur(20px); border: 1px solid var(--border);
            border-radius: var(--radius); overflow: hidden; animation: fadeUp 0.5s ease-out 0.3s both;
        }
        table { width: 100%; border-collapse: collapse; }
        thead th {
            padding: 14px 18px; text-align: left; font-size: 0.76rem; font-weight: 600;
            text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted);
            border-bottom: 1px solid var(--border); cursor: pointer; user-select: none;
            transition: color 0.3s; white-space: nowrap;
        }
        thead th:hover { color: var(--accent-light); }
        thead th.sorted { color: var(--accent-light); }
        thead th .arr { margin-left: 4px; opacity: 0.4; font-size: 10px; }
        thead th.sorted .arr { opacity: 1; }
        tbody tr { border-bottom: 1px solid rgba(99,102,241,0.06); transition: background 0.2s; }
        tbody tr:hover { background: rgba(99,102,241,0.04); }
        tbody tr:last-child { border-bottom: none; }
        tbody td { padding: 14px 18px; font-size: 0.9rem; color: var(--text-sub); }
        .col-id { color: var(--text-muted); font-size: 0.82rem; }
        .col-nama { color: var(--text); font-weight: 500; }
        .col-harga { color: var(--green); font-weight: 600; font-variant-numeric: tabular-nums; }
        .col-stok { font-weight: 600; font-variant-numeric: tabular-nums; }
        .stok-low { color: var(--red); }
        .stok-med { color: #f59e0b; }
        .stok-high { color: var(--green); }
        .col-aksi { display: flex; gap: 6px; }

        .table-footer {
            display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px;
            padding: 14px 18px; border-top: 1px solid var(--border);
        }
        .table-footer .info { font-size: 0.82rem; color: var(--text-muted); }
        .paging { display: flex; gap: 4px; }
        .paging button {
            width: 34px; height: 34px; display: flex; align-items: center; justify-content: center;
            border: 1px solid var(--border); border-radius: 8px; background: transparent;
            color: var(--text-sub); font-size: 0.82rem; font-family: inherit; cursor: pointer; transition: all 0.3s;
        }
        .paging button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent-light); background: rgba(99,102,241,0.1); }
        .paging button.active { background: var(--accent); border-color: var(--accent); color: #fff; box-shadow: 0 0 12px var(--accent-glow); }
        .paging button:disabled { opacity: 0.3; cursor: not-allowed; }

        .empty { padding: 50px 20px; text-align: center; }
        .empty .ico { font-size: 42px; margin-bottom: 12px; opacity: 0.6; }
        .empty h3 { font-size: 1rem; color: var(--text-sub); margin-bottom: 4px; }
        .empty p { font-size: 0.85rem; color: var(--text-muted); }

        .overlay {
            position: fixed; inset: 0; background: rgba(0,0,0,0.6); backdrop-filter: blur(6px);
            z-index: 1000; display: flex; align-items: center; justify-content: center; padding: 20px;
            opacity: 0; visibility: hidden; transition: all 0.3s;
        }
        .overlay.show { opacity: 1; visibility: visible; }
        .modal {
            background: #111827; border: 1px solid var(--border); border-radius: var(--radius);
            width: 100%; max-width: 460px; transform: scale(0.9) translateY(16px);
            transition: transform 0.3s cubic-bezier(0.4,0,0.2,1);
            box-shadow: 0 10px 40px rgba(0,0,0,0.5), 0 0 50px rgba(99,102,241,0.08);
        }
        .overlay.show .modal { transform: scale(1) translateY(0); }
        .modal-head {
            display: flex; align-items: center; justify-content: space-between;
            padding: 20px 22px; border-bottom: 1px solid var(--border);
        }
        .modal-head h2 { font-size: 1.1rem; font-weight: 700; display: flex; align-items: center; gap: 8px; }
        .modal-close {
            width: 34px; height: 34px; border-radius: 8px; border: 1px solid var(--border);
            background: transparent; color: var(--text-muted); font-size: 16px; cursor: pointer;
            display: flex; align-items: center; justify-content: center; transition: all 0.3s;
        }
        .modal-close:hover { background: rgba(239,68,68,0.1); border-color: rgba(239,68,68,0.3); color: var(--red); }
        .modal-body { padding: 22px; }
        .modal-foot {
            display: flex; justify-content: flex-end; gap: 10px;
            padding: 16px 22px; border-top: 1px solid var(--border);
        }

        .fg { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
        .fg:last-child { margin-bottom: 0; }
        .fg label { font-size: 0.82rem; font-weight: 600; color: var(--text-sub); }
        .fg label .req { color: var(--red); }
        .fg input {
            padding: 10px 14px; background: var(--bg-input); border: 1px solid var(--border);
            border-radius: 8px; color: var(--text); font-size: 0.9rem; font-family: inherit;
            outline: none; transition: all 0.3s;
        }
        .fg input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }
        .fg input::placeholder { color: var(--text-muted); }

        .toast-box { position: fixed; top: 20px; right: 20px; z-index: 2000; display: flex; flex-direction: column; gap: 8px; }
        .toast {
            padding: 12px 18px; border-radius: var(--radius); font-size: 0.88rem; font-weight: 500;
            display: flex; align-items: center; gap: 8px; backdrop-filter: blur(20px); border: 1px solid;
            animation: toastIn 0.3s ease-out; min-width: 260px; box-shadow: 0 8px 30px rgba(0,0,0,0.4);
        }
        .toast.ok { background: rgba(34,197,94,0.15); border-color: rgba(34,197,94,0.3); color: #4ade80; }
        .toast.err { background: rgba(239,68,68,0.15); border-color: rgba(239,68,68,0.3); color: #f87171; }
        @keyframes toastIn { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } }
        .toast.out { animation: toastOut 0.3s forwards; }
        @keyframes toastOut { to { opacity: 0; transform: translateX(20px); } }

        .topbar { position: fixed; top: 0; left: 0; width: 100%; height: 3px; z-index: 9999; overflow: hidden; opacity: 0; transition: opacity 0.2s; }
        .topbar.on { opacity: 1; }
        .topbar::after {
            content: ''; position: absolute; inset: 0;
            background: linear-gradient(135deg, #6366f1, #8b5cf6);
            animation: slide 1.2s ease-in-out infinite;
        }
        @keyframes slide { 0% { transform: translateX(-100%); } 50% { transform: translateX(0); } 100% { transform: translateX(100%); } }

        @media (max-width: 600px) {
            .app { padding: 12px; }
            .header { flex-direction: column; align-items: flex-start; padding: 16px; }
            .toolbar { flex-direction: column; }
        }

        ::-webkit-scrollbar { width: 6px; }
        ::-webkit-scrollbar-track { background: transparent; }
        ::-webkit-scrollbar-thumb { background: rgba(99,102,241,0.2); border-radius: 3px; }
    </style>
</head>
<body>
    <div class="bg-orbs"><div></div><div></div></div>
    <div class="topbar" id="topbar"></div>
    <div class="toast-box" id="toasts"></div>

    <div class="app">
        <header class="header">
            <div class="title">
                <div class="icon">📦</div>
                <h1>Manajemen Barang</h1>
            </div>
            <div class="status" id="dbStatus">
                <span class="dot"></span>
                <span id="dbStatusText">Menghubungkan...</span>
            </div>
        </header>

        <div class="toolbar">
            <div class="search-box">
                <span class="ico">🔍</span>
                <input type="text" id="searchInput" placeholder="Cari barang..." oninput="debounceSearch()">
            </div>
            <button class="btn btn-primary" onclick="openAdd()">＋ Tambah Barang</button>
            <button class="btn btn-ghost" onclick="loadData()">🔄</button>
        </div>

        <div class="table-wrap">
            <div style="overflow-x:auto;">
                <table>
                    <thead>
                        <tr>
                            <th onclick="setSort('id')" id="th-id">ID <span class="arr">▲</span></th>
                            <th onclick="setSort('nama_barang')" id="th-nama_barang">Nama Barang <span class="arr">▲</span></th>
                            <th onclick="setSort('harga')" id="th-harga">Harga <span class="arr">▲</span></th>
                            <th onclick="setSort('stok')" id="th-stok">Stok <span class="arr">▲</span></th>
                            <th>Aksi</th>
                        </tr>
                    </thead>
                    <tbody id="tbody">
                        <tr><td colspan="5"><div class="empty"><div class="ico">📦</div><h3>Memuat...</h3></div></td></tr>
                    </tbody>
                </table>
            </div>
            <div class="table-footer">
                <div class="info" id="tInfo">-</div>
                <div class="paging" id="paging"></div>
            </div>
        </div>
    </div>

    <!-- Modal Tambah/Edit -->
    <div class="overlay" id="formOverlay">
        <div class="modal">
            <div class="modal-head">
                <h2 id="formTitle">📦 Tambah Barang</h2>
                <button class="modal-close" onclick="closeModal('formOverlay')">✕</button>
            </div>
            <div class="modal-body">
                <input type="hidden" id="fId">
                <div class="fg">
                    <label>Nama Barang <span class="req">*</span></label>
                    <input type="text" id="fNama" placeholder="cth: Laptop ASUS">
                </div>
                <div class="fg">
                    <label>Harga (Rp) <span class="req">*</span></label>
                    <input type="number" id="fHarga" placeholder="0" min="0">
                </div>
                <div class="fg">
                    <label>Stok <span class="req">*</span></label>
                    <input type="number" id="fStok" placeholder="0" min="0">
                </div>
            </div>
            <div class="modal-foot">
                <button class="btn btn-ghost" onclick="closeModal('formOverlay')">Batal</button>
                <button class="btn btn-primary" id="btnSave" onclick="save()">💾 Simpan</button>
            </div>
        </div>
    </div>

    <!-- Modal Hapus -->
    <div class="overlay" id="delOverlay">
        <div class="modal" style="max-width:400px;">
            <div class="modal-head">
                <h2>⚠️ Hapus Barang</h2>
                <button class="modal-close" onclick="closeModal('delOverlay')">✕</button>
            </div>
            <div class="modal-body" style="text-align:center;">
                <div style="font-size:42px;margin-bottom:12px;">🗑️</div>
                <h3 style="margin-bottom:6px;">Yakin hapus?</h3>
                <p style="color:var(--text-muted);font-size:0.88rem;">Barang <strong style="color:var(--accent-light);" id="delName"></strong> akan dihapus permanen.</p>
            </div>
            <div class="modal-foot">
                <button class="btn btn-ghost" onclick="closeModal('delOverlay')">Batal</button>
                <button class="btn btn-danger" onclick="confirmDel()">🗑️ Hapus</button>
            </div>
        </div>
    </div>

    <script>
    const S = { page: 1, limit: 10, search: '', sort: 'id', order: 'DESC', delId: null };
    let timer = null;

    const $ = id => document.getElementById(id);
    const fmt = n => new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR', minimumFractionDigits: 0 }).format(n);

    function loading(on) { $('topbar').classList.toggle('on', on); }

    function toast(msg, ok = true) {
        const t = document.createElement('div');
        t.className = `toast ${ok ? 'ok' : 'err'}`;
        t.innerHTML = `<span>${ok ? '✅' : '❌'}</span><span>${msg}</span>`;
        $('toasts').appendChild(t);
        setTimeout(() => { t.classList.add('out'); setTimeout(() => t.remove(), 300); }, 3000);
    }

    function openModal(id) { $(id).classList.add('show'); document.body.style.overflow = 'hidden'; }
    function closeModal(id) { $(id).classList.remove('show'); document.body.style.overflow = ''; }

    async function api(endpoint, opts = {}) {
        loading(true);
        try {
            const r = await fetch(`index.php?${endpoint}`, { headers: { 'Content-Type': 'application/json' }, ...opts });
            const d = await r.json();
            if (d.error) throw new Error(d.error);
            return d;
        } finally { loading(false); }
    }

    async function loadData() {
        const p = new URLSearchParams({ api: 'list', page: S.page, limit: S.limit, sort: S.sort, order: S.order });
        if (S.search) p.set('search', S.search);
        try {
            const r = await api(p.toString());
            $('dbStatus').className = 'status ok';
            $('dbStatusText').textContent = 'MySQL Connected';
            render(r.data);
            renderPaging(r.total, r.pages);
        } catch (e) {
            $('dbStatus').className = 'status err';
            $('dbStatusText').textContent = 'Disconnected';
            toast(e.message, false);
            $('tbody').innerHTML = `<tr><td colspan="5"><div class="empty"><div class="ico">⚠️</div><h3>Gagal memuat</h3><p>${e.message}</p></div></td></tr>`;
        }
    }

    function render(data) {
        if (!data.length) {
            $('tbody').innerHTML = `<tr><td colspan="5"><div class="empty"><div class="ico">📭</div><h3>Kosong</h3><p>Belum ada barang.</p></div></td></tr>`;
            return;
        }
        $('tbody').innerHTML = data.map(i => {
            const sc = i.stok <= 10 ? 'stok-low' : i.stok <= 30 ? 'stok-med' : 'stok-high';
            return `<tr>
                <td class="col-id">${i.id}</td>
                <td class="col-nama">${esc(i.nama_barang)}</td>
                <td class="col-harga">${fmt(i.harga)}</td>
                <td class="col-stok ${sc}">${i.stok}</td>
                <td><div class="col-aksi">
                    <button class="btn btn-ghost btn-sm" onclick="openEdit(${i.id},'${esc(i.nama_barang)}',${i.harga},${i.stok})">✏️</button>
                    <button class="btn btn-danger btn-sm" onclick="openDel(${i.id},'${esc(i.nama_barang)}')">🗑️</button>
                </div></td>
            </tr>`;
        }).join('');
    }

    function esc(s) { if (!s) return ''; const d = document.createElement('div'); d.textContent = s; return d.innerHTML.replace(/'/g, "\\'"); }

    function renderPaging(total, pages) {
        const start = (S.page - 1) * S.limit + 1;
        const end = Math.min(S.page * S.limit, total);
        $('tInfo').textContent = total ? `${start}–${end} dari ${total}` : 'Tidak ada data';
        if (pages <= 1) { $('paging').innerHTML = ''; return; }
        let h = `<button ${S.page<=1?'disabled':''} onclick="go(${S.page-1})">‹</button>`;
        for (let i = 1; i <= pages; i++) h += `<button class="${i===S.page?'active':''}" onclick="go(${i})">${i}</button>`;
        h += `<button ${S.page>=pages?'disabled':''} onclick="go(${S.page+1})">›</button>`;
        $('paging').innerHTML = h;
    }

    function go(p) { S.page = p; loadData(); }

    function setSort(col) {
        if (S.sort === col) S.order = S.order === 'ASC' ? 'DESC' : 'ASC';
        else { S.sort = col; S.order = 'ASC'; }
        document.querySelectorAll('thead th').forEach(t => t.classList.remove('sorted'));
        const th = $('th-' + col);
        if (th) { th.classList.add('sorted'); th.querySelector('.arr').textContent = S.order === 'ASC' ? '▲' : '▼'; }
        S.page = 1; loadData();
    }

    function debounceSearch() {
        clearTimeout(timer);
        timer = setTimeout(() => { S.search = $('searchInput').value.trim(); S.page = 1; loadData(); }, 400);
    }

    function openAdd() {
        $('fId').value = ''; $('fNama').value = ''; $('fHarga').value = ''; $('fStok').value = '';
        $('formTitle').innerHTML = '📦 Tambah Barang';
        $('btnSave').innerHTML = '💾 Simpan';
        openModal('formOverlay');
        $('fNama').focus();
    }

    function openEdit(id, nama, harga, stok) {
        $('fId').value = id; $('fNama').value = nama.replace(/\\'/g, "'"); $('fHarga').value = harga; $('fStok').value = stok;
        $('formTitle').innerHTML = '✏️ Edit Barang';
        $('btnSave').innerHTML = '💾 Update';
        openModal('formOverlay');
    }

    async function save() {
        const id = $('fId').value;
        const payload = { nama_barang: $('fNama').value.trim(), harga: $('fHarga').value, stok: $('fStok').value };
        if (!payload.nama_barang) { toast('Nama wajib diisi', false); return; }
        try {
            if (id) await api(`api=update&id=${id}`, { method: 'PUT', body: JSON.stringify(payload) });
            else await api('api=create', { method: 'POST', body: JSON.stringify(payload) });
            toast(id ? 'Barang diupdate!' : 'Barang ditambahkan!');
            closeModal('formOverlay'); loadData();
        } catch (e) { toast(e.message, false); }
    }

    function openDel(id, nama) { S.delId = id; $('delName').textContent = nama.replace(/\\'/g, "'"); openModal('delOverlay'); }

    async function confirmDel() {
        try {
            await api(`api=delete&id=${S.delId}`, { method: 'DELETE' });
            toast('Barang dihapus!');
            closeModal('delOverlay'); loadData();
        } catch (e) { toast(e.message, false); }
    }

    document.addEventListener('keydown', e => {
        if (e.key === 'Escape') document.querySelectorAll('.overlay.show').forEach(o => closeModal(o.id));
    });
    document.querySelectorAll('.overlay').forEach(o => o.addEventListener('click', e => { if (e.target === o) closeModal(o.id); }));

    loadData();
    </script>
</body>
</html>
