/* @jsx React.createElement */
const { useState, useEffect, useRef, useMemo } = React;
/* ============================================================
   Yappari — PENGATURAN (Settings) + per-machine layout editor
   ============================================================ */
function Stepper({ value, min, max, onSet }) {
  return React.createElement('div', { className: 'row gap-2', style: { alignItems: 'center' } },
    React.createElement('button', { className: 'icon-btn', style: { width: 28, height: 28, fontSize: 17, fontWeight: 800, lineHeight: 1 }, disabled: value <= min, onClick: () => onSet(value - 1) }, '\u2212'),
    React.createElement('span', { style: { minWidth: 24, textAlign: 'center', fontWeight: 800, fontFamily: 'var(--font-mono)', fontSize: 15 } }, value),
    React.createElement('button', { className: 'icon-btn', style: { width: 28, height: 28, fontSize: 16, fontWeight: 800, lineHeight: 1 }, disabled: value >= max, onClick: () => onSet(value + 1) }, '+'));
}

function LayoutEditor({ mid, onChange }) {
  const Y = window.YAPPARI;
  const [, force] = useState(0);
  const apply = (patch) => { Y.setLayout(mid, patch); force(x => x + 1); onChange && onChange(); };
  const L = Y.LAYOUTS[mid];
  const slots = Y.SLOTS[mid];
  const visible = slots.filter(s => !s.hidden);
  const [selNo, setSelNo] = useState(visible[0] ? visible[0].no : 1);
  const sel = visible.find(s => s.no === selNo) || visible[0];

  const setSlotCap = (no, cap) => { const sc = { ...(L.slotCap || {}) }; sc[no] = cap; apply({ slotCap: sc }); };
  const toggleMerge = (s) => { const merges = { ...L.merges }; if (s.span > 1) delete merges[s.no]; else if (s.col + 1 < L.cols) merges[s.no] = 2; apply({ merges }); };
  const applyRow = (r, cap) => {
    const rc = L.rowCap.slice(); rc[r] = cap;
    const sc = { ...(L.slotCap || {}) };
    Object.keys(sc).forEach(no => { if (Math.floor((+no - 1) / L.cols) === r) delete sc[no]; });
    apply({ rowCap: rc, slotCap: sc });
  };
  const dim = (label, value, min, max, on) => React.createElement('div', null, React.createElement('div', { className: 'field-label' }, label), React.createElement(Stepper, { value, min, max, onSet: on }));

  return React.createElement('div', { className: 'col gap-5', style: { marginTop: 16, paddingTop: 16, borderTop: '1px solid var(--border-subtle)' } },
    React.createElement('div', { className: 'row', style: { justifyContent: 'space-between', flexWrap: 'wrap', gap: 16 } },
      dim('Baris (shelf)', L.rows, 3, 8, (v) => apply({ rows: v })),
      dim('Kolom', L.cols, 5, 12, (v) => apply({ cols: v })),
      React.createElement('div', null, React.createElement('div', { className: 'field-label' }, 'Slot aktif'), React.createElement('div', { style: { fontWeight: 800, fontFamily: 'var(--font-mono)', fontSize: 18, paddingTop: 2, color: 'var(--st-maint)' } }, visible.length))),
    React.createElement('div', null,
      React.createElement('div', { className: 'field-label', style: { marginBottom: 6 } }, 'Slot, kapasitas & penggabungan'),
      React.createElement('p', { style: { fontSize: 12.5, color: 'var(--fg-3)', margin: '0 0 12px', lineHeight: 1.5 } }, 'Angka besar di tiap kotak = kapasitas spiral slot itu. Klik slot untuk memilih, lalu atur kapasitas / gabungkan di bawah.'),
      React.createElement('div', { style: { overflowX: 'auto', paddingBottom: 4 } },
        React.createElement('div', { style: { minWidth: L.cols * 46, display: 'grid', gridTemplateColumns: 'repeat(' + L.cols + ',1fr)', gridAutoRows: 48, gap: 4 } },
          visible.map(s => {
            const isSel = sel && s.no === sel.no;
            return React.createElement('button', {
              key: s.no, onClick: () => setSelNo(s.no),
              title: 'Slot ' + s.no + ' \u00b7 kapasitas ' + s.cap + (s.span > 1 ? ' \u00b7 gabungan \u00d7' + s.span : ''),
              style: {
                gridColumn: (s.col + 1) + ' / span ' + s.span, gridRow: s.row + 1, borderRadius: 6, position: 'relative',
                border: isSel ? '2px solid var(--accent)' : '1px solid ' + (s.span > 1 ? 'var(--st-maint)' : 'var(--border)'),
                background: s.span > 1 ? 'var(--st-maint-bg)' : 'var(--bg-elev)', cursor: 'pointer',
                display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
                boxShadow: isSel ? '0 0 0 3px rgba(240,64,0,.18)' : 'none',
              },
            },
              React.createElement('span', { style: { position: 'absolute', top: 3, left: 5, fontSize: 9, fontWeight: 800, color: 'var(--fg-4)', fontFamily: 'var(--font-mono)' } }, s.no),
              s.span > 1 && React.createElement('span', { style: { position: 'absolute', top: 3, right: 5, fontSize: 9, fontWeight: 800, color: 'var(--st-maint)' } }, '\u21c6'),
              React.createElement('span', { style: { fontSize: 17, fontWeight: 800, fontFamily: 'var(--font-mono)', color: 'var(--fg-1)', marginTop: 4 } }, s.cap));
          }))),
    ),
    sel && React.createElement('div', { className: 'card', style: { padding: 14, boxShadow: 'none', background: 'var(--bg-sunken)' } },
      React.createElement('div', { className: 'row', style: { justifyContent: 'space-between', flexWrap: 'wrap', gap: 16, alignItems: 'flex-end' } },
        React.createElement('div', null,
          React.createElement('div', { className: 'field-label', style: { marginBottom: 2 } }, 'Slot terpilih'),
          React.createElement('div', { style: { fontWeight: 800, fontSize: 16, fontFamily: 'var(--font-mono)' } }, 'Slot ' + sel.no + (sel.span > 1 ? ' (gabung \u00d7' + sel.span + ')' : ''))),
        React.createElement('div', null,
          React.createElement('div', { className: 'field-label', style: { marginBottom: 4 } }, 'Kapasitas spiral'),
          React.createElement(Stepper, { value: sel.cap, min: 1, max: 20, onSet: (v) => setSlotCap(sel.no, v) }))),
      React.createElement('div', { className: 'row gap-2', style: { marginTop: 12, flexWrap: 'wrap' } },
        React.createElement('button', { className: 'btn btn-ghost btn-sm', disabled: sel.span === 1 && sel.col + 1 >= L.cols, onClick: () => toggleMerge(sel) }, React.createElement(Icon, { name: 'layers', size: 14 }), sel.span > 1 ? 'Pisah slot' : 'Gabung dengan kanan'),
        React.createElement('button', { className: 'btn btn-ghost btn-sm', onClick: () => applyRow(sel.row, sel.cap) }, React.createElement(Icon, { name: 'check', size: 14 }), 'Samakan ke shelf ' + String.fromCharCode(65 + sel.row))),
    ),
  );
}

function MachineSettingCard({ m, onChange }) {
  const Y = window.YAPPARI;
  const [edit, setEdit] = useState(false);
  const [showLayout, setShowLayout] = useState(false);
  const [name, setName] = useState(m.name);
  const [loc, setLoc] = useState(m.loc);
  const L = Y.LAYOUTS[m.id];
  const active = Y.SLOTS[m.id].filter(s => !s.hidden).length;
  const field = (label, value, mono) => React.createElement('div', null,
    React.createElement('div', { className: 'field-label', style: { marginBottom: 2 } }, label),
    React.createElement('div', { style: { fontSize: 14, fontWeight: 600, color: 'var(--fg-1)', fontFamily: mono ? 'var(--font-mono)' : 'inherit' } }, value));
  return React.createElement('div', { className: 'card', style: { overflow: 'hidden' } },
    React.createElement('div', { className: 'card-head' },
      React.createElement('div', { className: 'row gap-3' },
        React.createElement('div', { style: { width: 40, height: 40, borderRadius: '50%', background: '#fff', display: 'grid', placeItems: 'center', border: '1px solid var(--border-subtle)' } }, React.createElement(PlumBlossom, { size: 24, color: '#004080' })),
        edit
          ? React.createElement('input', { className: 'input', value: name, onChange: e => setName(e.target.value), style: { fontWeight: 700, maxWidth: 180 } })
          : React.createElement('h3', null, name)),
      React.createElement('div', { className: 'row gap-2' },
        React.createElement(StatusBadge, { status: m.status }),
        React.createElement('button', { className: 'icon-btn', style: { width: 34, height: 34 }, onClick: () => setEdit(e => !e) }, React.createElement(Icon, { name: edit ? 'check' : 'pencil', size: 16 }))),
    ),
    React.createElement('div', { className: 'card-pad' },
      React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 'var(--sp-4)' } },
        React.createElement('div', { style: { gridColumn: '1 / -1' } },
          React.createElement('div', { className: 'field-label', style: { marginBottom: 2 } }, 'Lokasi'),
          edit ? React.createElement('input', { className: 'input', value: loc, onChange: e => setLoc(e.target.value) })
            : React.createElement('div', { className: 'row gap-1', style: { fontSize: 14, fontWeight: 600, color: 'var(--fg-1)' } }, React.createElement(Icon, { name: 'mapPin', size: 14, style: { color: 'var(--st-maint)' } }), loc)),
        field('ID / Serial', m.serial, true),
        field('Model', m.model),
        field('Koordinat', m.coord, true),
        field('Layout planogram', L.rows + ' \u00d7 ' + L.cols + ' \u00b7 ' + active + ' slot'),
      ),
      React.createElement('button', { className: 'btn btn-ghost btn-sm', style: { marginTop: 16 }, onClick: () => setShowLayout(s => !s) },
        React.createElement(Icon, { name: 'planogram', size: 15 }), showLayout ? 'Tutup pengaturan layout' : 'Atur layout & kapasitas',
        React.createElement(Icon, { name: showLayout ? 'chevronUp' : 'chevronDown', size: 14 })),
      showLayout && React.createElement(LayoutEditor, { mid: m.id, onChange }),
    ),
  );
}

function UserModal({ user, machines, onClose, onSaved }) {
  const Y = window.YAPPARI;
  const isNew = !user;
  const [name, setName] = useState(user ? user.name : '');
  const [email, setEmail] = useState(user ? user.email : '');
  const [role, setRole] = useState(user ? user.role : 'operator');
  const [phone, setPhone] = useState(user ? user.phone || '' : '');
  const [active, setActive] = useState(user ? user.active !== false : true);
  const [password, setPassword] = useState('');
  const [assigned, setAssigned] = useState(() => {
    const map = {}; (user && user.machines || []).forEach(m => { map[m.machine_id] = m.relation || 'staff'; }); return map;
  });
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState('');

  const toggleM = (id) => setAssigned(a => { const n = { ...a }; if (n[id]) delete n[id]; else n[id] = 'staff'; return n; });
  const setRel = (id, rel) => setAssigned(a => ({ ...a, [id]: rel }));

  const save = async () => {
    setErr(''); if (!name || !email) { setErr('Nama & email wajib'); return; }
    if (isNew && (!password || password.length < 6)) { setErr('Password minimal 6 karakter untuk user baru'); return; }
    setBusy(true);
    try {
      const machinesArr = Object.entries(assigned).map(([machine_id, relation]) => ({ machine_id, relation }));
      const body = { email, name, role, phone, active, machines: machinesArr };
      if (password) body.password = password;
      await Y.saveUser(body);
      onSaved();
    } catch (e) { setErr(e.message || 'Gagal menyimpan'); setBusy(false); }
  };

  return React.createElement('div', { style: { position: 'fixed', inset: 0, zIndex: 200, background: 'rgba(0,20,38,.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16, animation: 'fadeIn .15s' }, onClick: onClose },
    React.createElement('div', { onClick: e => e.stopPropagation(), style: { width: 560, maxWidth: '96vw', maxHeight: '92vh', overflowY: 'auto', background: 'var(--bg)', borderRadius: 'var(--r-4)', boxShadow: 'var(--shadow-3)' } },
      React.createElement('div', { style: { padding: '18px 22px', borderBottom: '1px solid var(--border-subtle)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
        React.createElement('h3', { style: { margin: 0 } }, isNew ? 'Tambah pengguna' : 'Edit pengguna'),
        React.createElement('button', { className: 'icon-btn', onClick: onClose }, React.createElement(Icon, { name: 'x', size: 18 }))),
      React.createElement('div', { style: { padding: 22 } },
        React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 } },
          React.createElement('div', null, React.createElement('div', { className: 'field-label' }, 'Nama'), React.createElement('input', { className: 'input', value: name, onChange: e => setName(e.target.value) })),
          React.createElement('div', null, React.createElement('div', { className: 'field-label' }, 'Email'), React.createElement('input', { className: 'input', type: 'email', value: email, disabled: !isNew, onChange: e => setEmail(e.target.value) })),
          React.createElement('div', null, React.createElement('div', { className: 'field-label' }, 'Role'),
            React.createElement('select', { className: 'select-native', value: role, onChange: e => setRole(e.target.value) },
              ['admin', 'operator', 'teknisi', 'finance'].map(r => React.createElement('option', { key: r, value: r }, r)))),
          React.createElement('div', null, React.createElement('div', { className: 'field-label' }, 'Telepon'), React.createElement('input', { className: 'input', value: phone, onChange: e => setPhone(e.target.value) })),
          React.createElement('div', { style: { gridColumn: '1 / -1' } }, React.createElement('div', { className: 'field-label' }, isNew ? 'Password' : 'Password baru (kosongkan jika tidak diubah)'), React.createElement('input', { className: 'input', type: 'password', value: password, placeholder: '••••••', onChange: e => setPassword(e.target.value) }))),
        React.createElement('div', { className: 'row', style: { justifyContent: 'space-between', marginTop: 14, paddingTop: 14, borderTop: '1px solid var(--border-subtle)' } },
          React.createElement('div', null, React.createElement('div', { style: { fontWeight: 700, fontSize: 14 } }, 'Akun aktif'), React.createElement('div', { style: { fontSize: 12, color: 'var(--fg-3)' } }, 'Nonaktif = tidak bisa login')),
          React.createElement('button', { className: 'toggle ' + (active ? 'on' : ''), onClick: () => setActive(a => !a) })),
        role !== 'admin' && React.createElement('div', { style: { marginTop: 16 } },
          React.createElement('div', { className: 'field-label', style: { marginBottom: 6 } }, 'Mesin yang ditugaskan'),
          React.createElement('p', { style: { fontSize: 12.5, color: 'var(--fg-3)', margin: '0 0 10px' } }, 'Pilih mesin yang boleh dikelola user ini. Admin otomatis bisa akses semua mesin.'),
          React.createElement('div', { className: 'col gap-2' },
            machines.map(m => React.createElement('div', { key: m.id, className: 'row', style: { justifyContent: 'space-between', alignItems: 'center', padding: '8px 10px', borderRadius: 8, border: '1px solid var(--border-subtle)', background: assigned[m.id] ? 'var(--st-maint-bg)' : 'transparent' } },
              React.createElement('label', { className: 'row gap-2', style: { cursor: 'pointer', flex: 1 } },
                React.createElement('input', { type: 'checkbox', checked: !!assigned[m.id], onChange: () => toggleM(m.id) }),
                React.createElement('div', null, React.createElement('div', { style: { fontWeight: 700, fontSize: 13.5 } }, m.name), React.createElement('div', { style: { fontSize: 12, color: 'var(--fg-3)' } }, m.loc))),
              assigned[m.id] && React.createElement('select', { className: 'select-native', style: { width: 'auto', minWidth: 110 }, value: assigned[m.id], onChange: e => setRel(m.id, e.target.value) },
                [['owner', 'Pemilik'], ['client', 'Mesin klien'], ['staff', 'Staf']].map(([v, l]) => React.createElement('option', { key: v, value: v }, l))))))),
        err && React.createElement('div', { style: { marginTop: 14, color: 'var(--st-error)', fontSize: 13 } }, err),
        React.createElement('div', { className: 'row gap-2', style: { marginTop: 18, justifyContent: 'flex-end' } },
          React.createElement('button', { className: 'btn btn-ghost', onClick: onClose }, 'Batal'),
          React.createElement('button', { className: 'btn btn-primary', disabled: busy, onClick: save }, busy ? 'Menyimpan…' : 'Simpan'))),
    ));
}

function UsersSection({ machines }) {
  const Y = window.YAPPARI;
  const isAdmin = Y.CURRENT_USER && Y.CURRENT_USER.role === 'admin';
  const [users, setUsers] = useState(Y.USERS);
  const [modal, setModal] = useState(null);
  const roleColor = { admin: 'var(--accent)', operator: 'var(--st-maint)', teknisi: 'var(--st-warn)', finance: 'var(--st-online)' };

  const reload = async () => {
    try { const fresh = await window.yappariApi('/api/users'); setUsers(fresh.map(u => ({ ...u, machines: u.machines || [] }))); } catch (e) {}
    setModal(null);
  };
  const del = async (email) => { if (!confirm('Hapus pengguna ' + email + '?')) return; try { await Y.deleteUser(email); reload(); } catch (e) { alert(e.message); } };

  if (!isAdmin) {
    return React.createElement(SectionCard, { title: 'Akses pengguna', sub: 'Hanya admin' },
      React.createElement('div', { style: { padding: 24, color: 'var(--fg-3)', fontSize: 13 } }, 'Hanya admin yang dapat mengelola pengguna.'));
  }

  const avatar = (u) => React.createElement('div', { style: { width: 36, height: 36, borderRadius: '50%', background: roleColor[u.role] || 'var(--fg-3)', color: '#fff', display: 'grid', placeItems: 'center', fontWeight: 800, fontSize: 14 } }, (u.name || '?').split(' ').map(n => n[0]).slice(0, 2).join(''));

  const row = (u, i) => React.createElement('tr', { key: u.email || i },
    React.createElement('td', null, React.createElement('div', { className: 'row gap-3' }, avatar(u),
      React.createElement('div', null,
        React.createElement('div', { className: 'strong' }, u.name),
        React.createElement('div', { style: { fontSize: 12, color: 'var(--fg-3)' } }, u.email)))),
    React.createElement('td', null, React.createElement('span', { className: 'badge', style: { color: roleColor[u.role], background: 'var(--bg-sunken)' } }, u.role)),
    React.createElement('td', null, u.role === 'admin'
      ? React.createElement('span', { style: { fontSize: 12.5, color: 'var(--fg-3)' } }, 'Semua mesin')
      : React.createElement('span', { style: { fontSize: 12.5 } }, (u.machines || []).length + ' mesin')),
    React.createElement('td', { style: { textAlign: 'center' } }, React.createElement('span', { className: 'badge ' + (u.active ? 'badge-online' : 'badge-offline') }, u.active ? 'Aktif' : 'Nonaktif')),
    React.createElement('td', null, React.createElement('div', { className: 'row gap-1' },
      React.createElement('button', { className: 'icon-btn', style: { width: 30, height: 30 }, onClick: () => setModal({ user: u }) }, React.createElement(Icon, { name: 'pencil', size: 14 })),
      React.createElement('button', { className: 'icon-btn', style: { width: 30, height: 30, color: 'var(--st-error)' }, onClick: () => del(u.email) }, React.createElement(Icon, { name: 'trash', size: 14 })))));

  const card = React.createElement(SectionCard, {
      title: 'Pengguna & akses', sub: users.length + ' pengguna', motif: true,
      right: React.createElement('button', { className: 'btn btn-primary btn-sm', onClick: () => setModal({ new: true }) }, React.createElement(Icon, { name: 'plus', size: 14 }), 'Tambah'),
    },
    React.createElement('table', { className: 'tbl' },
      React.createElement('thead', null, React.createElement('tr', null,
        React.createElement('th', null, 'Pengguna'),
        React.createElement('th', null, 'Role'),
        React.createElement('th', null, 'Mesin'),
        React.createElement('th', { style: { textAlign: 'center' } }, 'Status'),
        React.createElement('th', null, ''))),
      React.createElement('tbody', null, users.map(row))));

  const modalEl = modal ? React.createElement(UserModal, { user: modal.user, machines, onClose: () => setModal(null), onSaved: reload }) : null;

  return React.createElement(React.Fragment, null, card, modalEl);
}

function XenditSection() {
  const Y = window.YAPPARI;
  const isAdmin = Y.CURRENT_USER && Y.CURRENT_USER.role === 'admin';
  const x = (Y.SETTINGS && Y.SETTINGS.xendit) || {};
  const [enabled, setEnabled] = useState(!!x.enabled);
  const [secret, setSecret] = useState('');
  const [webhook, setWebhook] = useState('');
  const [busy, setBusy] = useState(false);
  const [msg, setMsg] = useState('');

  const save = async () => {
    setBusy(true); setMsg('');
    try {
      const body = { enabled };
      if (secret) body.secret_key = secret;
      if (webhook) body.webhook_token = webhook;
      await Y.saveSettings('xendit', body);
      setMsg('Tersimpan'); setSecret(''); setWebhook('');
    } catch (e) { setMsg(e.message || 'Gagal'); }
    setBusy(false);
  };

  return React.createElement(SectionCard, { title: 'Pembayaran — Xendit (QRIS)', sub: x.enabled ? 'Aktif' : 'Belum aktif',
    right: React.createElement('span', { className: 'badge ' + (x.enabled ? 'badge-online' : 'badge-warn') }, x.enabled ? 'Aktif' : 'Menunggu key'), bodyStyle: { padding: 'var(--sp-5)' } },
    React.createElement('div', { className: 'col gap-4' },
      React.createElement('div', { style: { fontSize: 13, color: 'var(--fg-2)', lineHeight: 1.6, padding: '10px 12px', background: 'var(--st-warn-bg)', borderRadius: 8, border: '1px solid var(--st-warn)' } },
        React.createElement('div', { className: 'row gap-2', style: { fontWeight: 700, color: 'var(--st-warn)', marginBottom: 4 } }, React.createElement(Icon, { name: 'alert', size: 15 }), 'Integrasi belum aktif'),
        'Masukkan Secret Key & Webhook Token dari dashboard Xendit untuk mengaktifkan pembayaran QRIS di mesin. Key disimpan aman di server (tidak ditampilkan kembali).'),
      React.createElement('div', null, React.createElement('div', { className: 'field-label' }, 'Secret Key' + (x.has_secret_key ? ' (sudah tersimpan)' : '')),
        React.createElement('input', { className: 'input', type: 'password', placeholder: x.has_secret_key ? '•••••• (kosongkan jika tidak diubah)' : 'xnd_production_…', value: secret, disabled: !isAdmin, onChange: e => setSecret(e.target.value) })),
      React.createElement('div', null, React.createElement('div', { className: 'field-label' }, 'Webhook Verification Token' + (x.has_webhook_token ? ' (sudah tersimpan)' : '')),
        React.createElement('input', { className: 'input', type: 'password', placeholder: x.has_webhook_token ? '••••••' : 'token…', value: webhook, disabled: !isAdmin, onChange: e => setWebhook(e.target.value) })),
      React.createElement('div', null, React.createElement('div', { className: 'field-label' }, 'Callback URL (set di dashboard Xendit)'),
        React.createElement('input', { className: 'input', readOnly: true, value: x.callback_url || 'https://api.yappari.id/api/report/xendit', style: { fontFamily: 'var(--font-mono)', fontSize: 12.5 } })),
      React.createElement('div', { className: 'row', style: { justifyContent: 'space-between', paddingTop: 8, borderTop: '1px solid var(--border-subtle)' } },
        React.createElement('div', { style: { paddingTop: 8 } }, React.createElement('div', { style: { fontWeight: 700, fontSize: 14 } }, 'Aktifkan QRIS'), React.createElement('div', { style: { fontSize: 12, color: 'var(--fg-3)' } }, 'Mesin akan menampilkan QR pembayaran')),
        React.createElement('button', { className: 'toggle ' + (enabled ? 'on' : ''), style: { marginTop: 10 }, disabled: !isAdmin, onClick: () => setEnabled(v => !v) })),
      isAdmin && React.createElement('div', { className: 'row gap-2', style: { justifyContent: 'flex-end', alignItems: 'center' } },
        msg && React.createElement('span', { style: { fontSize: 13, color: msg === 'Tersimpan' ? 'var(--st-online)' : 'var(--st-error)' } }, msg),
        React.createElement('button', { className: 'btn btn-primary', disabled: busy, onClick: save }, busy ? 'Menyimpan…' : 'Simpan konfigurasi'))));
}

function SettingsView({ machines, onChange }) {
  const Y = window.YAPPARI;
  return React.createElement('div', { className: 'view' },
    React.createElement('div', { style: { marginBottom: 'var(--sp-4)' } },
      React.createElement('h2', { style: { fontSize: 'var(--fs-lg)', fontWeight: 800, margin: 0 } }, 'Mesin terdaftar'),
      React.createElement('p', { className: 'muted', style: { margin: '2px 0 0', fontSize: 13 } }, machines.length + ' unit \u00b7 atur nama, lokasi, layout grid, kapasitas spiral & penggabungan slot per mesin')),
    React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(440px,1fr))', gap: 'var(--sp-4)', marginBottom: 'var(--sp-6)' } },
      machines.map(m => React.createElement(MachineSettingCard, { key: m.id, m, onChange }))),
    React.createElement('div', { className: 'grid-2' },
      React.createElement(UsersSection, { machines }),
      React.createElement(XenditSection, null)),
  );
}

Object.assign(window, { SettingsView, MachineSettingCard, LayoutEditor, Stepper });
