504 lines
25 KiB
HTML
504 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<base target="_top">
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
<meta name="theme-color" content="#111111">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
<title>POS - Riwayat Belanja</title>
|
|
<script src="/local-preview-bridge.js"></script>
|
|
<style>
|
|
body { margin:0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background:#f4f7f6; color: #333; padding-bottom: 40px; -webkit-font-smoothing: antialiased; }
|
|
.header { background:#111; color:white; padding:15px; text-align:center; position:sticky; top:0; z-index:100; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
|
|
.container { padding:12px; max-width: 600px; margin: 0 auto; }
|
|
.card { background:white; border-radius:12px; padding:15px; margin-bottom:15px; border: 1px solid #eee; transform: translateZ(0); }
|
|
.title { font-size: 16px; font-weight: 800; margin-bottom: 12px; color: #111; text-align: center; }
|
|
|
|
.date-header { background:#fff; padding:10px 12px; font-weight:800; font-size:13px; margin:15px 0 8px 0; border-radius:10px; display:flex; justify-content:space-between; align-items:center; border-left: 4px solid #e11d48; border-top: 1px solid #eee; border-right: 1px solid #eee; border-bottom: 1px solid #eee; }
|
|
.total-day { font-size: 12px; color: #e11d48; font-weight: 800; }
|
|
|
|
.item-row { display:flex; justify-content:space-between; align-items:center; padding:12px; border:1px solid #eee; border-radius:12px; margin-bottom:8px; background: white; transition: background 0.1s; }
|
|
.item-row:active { background: #f9fafb; }
|
|
.item-info { display:flex; flex-direction:column; }
|
|
.item-name { font-weight:800; font-size:14px; color: #111; }
|
|
.item-kat { font-size: 9px; color: #e11d48; text-transform: uppercase; font-weight: 800; margin-bottom: 2px; }
|
|
.item-detail { font-size:11px; color:#777; margin-top:2px; }
|
|
.item-price { font-weight:800; color: #111; font-size:14px; }
|
|
|
|
#loading { position:fixed; inset:0; background:#fff; display:flex; flex-direction:column; justify-content:center; align-items:center; z-index:1000; }
|
|
.spinner { border:3px solid #f3f3f3; border-top:3px solid #e11d48; border-radius:50%; width:35px; height:35px; animation:spin 0.8s linear infinite; margin-bottom: 10px; }
|
|
@keyframes spin { 0% { transform:rotate(0deg); } 100% { transform:rotate(360deg); } }
|
|
|
|
input, select, textarea {
|
|
width:100%;
|
|
box-sizing:border-box;
|
|
padding:12px;
|
|
border-radius:10px;
|
|
border:1px solid #ccc;
|
|
outline:none;
|
|
font-size: 14px;
|
|
background: #fff;
|
|
-webkit-appearance: none;
|
|
}
|
|
.btn {
|
|
width:100%;
|
|
padding:14px;
|
|
border:none;
|
|
border-radius:12px;
|
|
font-weight:800;
|
|
cursor:pointer;
|
|
font-size: 14px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 8px;
|
|
}
|
|
.btn-primary { background:#e11d48; color:white; }
|
|
.btn:active { opacity: 0.7; }
|
|
|
|
.muted { color: #999; font-size: 12px; text-align: center; margin-top: 30px; }
|
|
::-webkit-scrollbar { width: 4px; }
|
|
::-webkit-scrollbar-thumb { background: #ddd; border-radius: 10px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="loading"><div class="spinner"></div><p>Memuat Riwayat Belanja...</p></div>
|
|
|
|
<div class="header">
|
|
<div id="store-name" style="font-weight:900; font-size:20px;">POS</div>
|
|
<div style="font-size:12px; opacity:0.8;">Manajemen Pengeluaran Belanja</div>
|
|
</div>
|
|
|
|
<div class="container">
|
|
<!-- Input Belanja Section -->
|
|
<div class="card">
|
|
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:12px;">
|
|
<div class="title" style="margin:0;">Input Belanja Baru</div>
|
|
<div style="display:flex; gap:6px;">
|
|
<button class="btn" style="padding: 6px 12px; font-size: 10px; width: auto; background: #22c55e; color: white;" onclick="exportBelanjaCSV()">EXPORT</button>
|
|
<button class="btn" style="padding: 6px 12px; font-size: 10px; width: auto; background: #3b82f6; color: white;" onclick="importBelanjaCSV()">IMPORT</button>
|
|
<button class="btn" style="padding: 6px 12px; font-size: 10px; width: auto; background: #111; color: white;" onclick="syncBelanjaOneWay()">SYNC</button>
|
|
</div>
|
|
</div>
|
|
<input type="hidden" id="bl-id">
|
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 10px;">
|
|
<input id="bl-nama" placeholder="Nama Barang / Biaya">
|
|
<select id="bl-kat" style="width:100%; padding:12px; border:1px solid #ddd; border-radius:10px; font-size:14px;">
|
|
<option value="Modal">Modal</option>
|
|
<option value="Bawah">Bawah</option>
|
|
<option value="Dapur" selected>Dapur</option>
|
|
<option value="Makan">Makan</option>
|
|
<option value="Operasional">Operasional</option>
|
|
<option value="Pegawai">Pegawai</option>
|
|
</select>
|
|
</div>
|
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 10px;">
|
|
<div><small style="font-size: 10px; color: #666;">Qty</small><input id="bl-qty" type="number" value="1" oninput="recalcBelanja('qty')"></div>
|
|
<div><small style="font-size: 10px; color: #666;">Harga Satuan</small><input id="bl-harga" type="number" oninput="recalcBelanja('harga')"></div>
|
|
</div>
|
|
<div style="margin-bottom: 10px;">
|
|
<small style="font-size: 10px; color: #666;">Total (Otomatis)</small>
|
|
<input id="bl-total" type="number" oninput="recalcBelanja('total')">
|
|
</div>
|
|
<button class="btn btn-primary" onclick="simpanBelanja()" style="margin-bottom:10px;">SIMPAN DATA BELANJA</button>
|
|
|
|
<div style="border-top: 1px dashed #ccc; padding-top: 10px; margin-top: 5px;">
|
|
<div style="font-size: 12px; font-weight: bold; margin-bottom: 5px;">Input Bulk (Cepat)</div>
|
|
<textarea id="bl-bulk" placeholder="Format: Nama Qty Harga Contoh: Es Batu 5 5000" style="width:100%; height:80px; padding:10px; border:1px solid #ddd; border-radius:10px; font-size:13px; font-family:monospace; margin-bottom:10px;"></textarea>
|
|
<div style="display:flex; gap:10px; flex-wrap:wrap; margin-bottom:10px;">
|
|
<div style="flex:1; min-width:160px;">
|
|
<small style="font-size: 10px; color: #666;">Kategori Bulk</small>
|
|
<select id="bl-bulk-kat" style="width:100%; padding:12px; border:1px solid #ddd; border-radius:10px; font-size:14px;">
|
|
<option value="Modal">Modal</option>
|
|
<option value="Bawah">Bawah</option>
|
|
<option value="Dapur" selected>Dapur</option>
|
|
<option value="Makan">Makan</option>
|
|
<option value="Operasional">Operasional</option>
|
|
<option value="Pegawai">Pegawai</option>
|
|
</select>
|
|
</div>
|
|
<div style="flex:1; min-width:160px; display:flex; align-items:flex-end;">
|
|
<small style="font-size: 10px; color: #64748b; font-weight:800;">Tips: tambah "Q" di depan/akhir nama untuk catat QRIS/Transfer.</small>
|
|
</div>
|
|
</div>
|
|
<button class="btn" style="background:#111; color:white;" onclick="simpanBelanjaBulk()">SIMPAN BULK</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Kalkulator Section -->
|
|
<div class="card">
|
|
<div class="title" style="font-size: 14px; margin-bottom: 10px;">Kalkulator Bantu</div>
|
|
<input id="calc-input" placeholder="Misal: 5000 + 3000 * 2" style="font-family:monospace; font-size:16px; text-align: right; margin-bottom: 5px;">
|
|
<div id="calc-result" style="font-weight:900; font-size:20px; text-align:right; color: #e11d48; margin-bottom: 15px;">= 0</div>
|
|
<div style="display:grid; grid-template-columns: repeat(4, 1fr); gap:8px;">
|
|
<button class="btn" style="background:#f3f4f6;" onclick="calcAdd('7')">7</button>
|
|
<button class="btn" style="background:#f3f4f6;" onclick="calcAdd('8')">8</button>
|
|
<button class="btn" style="background:#f3f4f6;" onclick="calcAdd('9')">9</button>
|
|
<button class="btn" style="background:#111; color: white;" onclick="calcAdd('/')">/</button>
|
|
|
|
<button class="btn" style="background:#f3f4f6;" onclick="calcAdd('4')">4</button>
|
|
<button class="btn" style="background:#f3f4f6;" onclick="calcAdd('5')">5</button>
|
|
<button class="btn" style="background:#f3f4f6;" onclick="calcAdd('6')">6</button>
|
|
<button class="btn" style="background:#111; color: white;" onclick="calcAdd('*')">*</button>
|
|
|
|
<button class="btn" style="background:#f3f4f6;" onclick="calcAdd('1')">1</button>
|
|
<button class="btn" style="background:#f3f4f6;" onclick="calcAdd('2')">2</button>
|
|
<button class="btn" style="background:#f3f4f6;" onclick="calcAdd('3')">3</button>
|
|
<button class="btn" style="background:#111; color: white;" onclick="calcAdd('-')">-</button>
|
|
|
|
<button class="btn" style="background:#f3f4f6;" onclick="calcAdd('0')">0</button>
|
|
<button class="btn" style="background:#f3f4f6;" onclick="calcAdd('.')">.</button>
|
|
<button class="btn" style="background:#e11d48; color: white;" onclick="calcEval()">=</button>
|
|
<button class="btn" style="background:#111; color: white;" onclick="calcAdd('+')">+</button>
|
|
|
|
<button class="btn" style="background:#111; color: white; grid-column: span 4;" onclick="calcClear()">CLEAR</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="belanja-list"></div>
|
|
</div>
|
|
|
|
<script>
|
|
function showLoading(s, text) {
|
|
document.getElementById('loading').style.display = s ? 'flex' : 'none';
|
|
if (text) document.querySelector('#loading p').innerText = text;
|
|
else document.querySelector('#loading p').innerText = 'Memuat Riwayat Belanja...';
|
|
}
|
|
|
|
var currentBelanja = [];
|
|
var storeName = 'POS';
|
|
window.onload = function() {
|
|
google.script.run.withSuccessHandler(function(res) {
|
|
showLoading(false);
|
|
if (res && res.belanja) {
|
|
currentBelanja = res.belanja;
|
|
renderBelanja(res.belanja);
|
|
}
|
|
if (res && res.settings) {
|
|
storeName = String(res.settings.store_name || storeName);
|
|
var el = document.getElementById('store-name');
|
|
if (el) el.innerText = storeName;
|
|
try { document.title = storeName + ' - Riwayat Belanja'; } catch(e) {}
|
|
}
|
|
}).withFailureHandler(function(err) {
|
|
showLoading(false);
|
|
alert('Gagal memuat data belanja.\n' + (err && err.message ? err.message : err));
|
|
}).getInitialData();
|
|
};
|
|
|
|
function cleanCSVNumber(val) {
|
|
if (!val) return 0;
|
|
var s = String(val).replace(/,/g, '').trim();
|
|
return Number(s) || 0;
|
|
}
|
|
|
|
function exportBelanjaCSV() {
|
|
if (!currentBelanja || !currentBelanja.length) { alert('Tidak ada data belanja.'); return; }
|
|
var csv = 'ID,Nama,Harga,Qty,Total,Tanggal,Kategori,Catatan,Timestamp\n';
|
|
currentBelanja.forEach(function(b) {
|
|
var row = [
|
|
'"' + (b.id || '') + '"',
|
|
'"' + (b.nama || '') + '"',
|
|
(b.harga || 0),
|
|
(b.qty || 0),
|
|
(b.total || 0),
|
|
'"' + (b.tgl || '') + '"',
|
|
'"' + (b.kategori || '') + '"',
|
|
'"' + (b.catatan || '') + '"',
|
|
'"' + (b.timestamp || '') + '"'
|
|
];
|
|
csv += row.join(',') + '\n';
|
|
});
|
|
var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
|
|
var link = document.createElement('a');
|
|
link.setAttribute('href', URL.createObjectURL(blob));
|
|
link.setAttribute('download', 'Belanja_' + String(storeName || 'POS').replace(/[^a-zA-Z0-9]+/g, '_') + '_' + new Date().toISOString().split('T')[0] + '.csv');
|
|
link.click();
|
|
}
|
|
|
|
function importBelanjaCSV() {
|
|
var input = document.createElement('input');
|
|
input.type = 'file';
|
|
input.accept = '.csv';
|
|
input.onchange = function(e) {
|
|
var file = e.target.files[0];
|
|
if (!file) return;
|
|
var reader = new FileReader();
|
|
reader.onload = function(re) {
|
|
var lines = re.target.result.split('\n');
|
|
var imported = [];
|
|
for (var i = 1; i < lines.length; i++) {
|
|
var line = lines[i].trim();
|
|
if (!line) continue;
|
|
var p = line.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/).map(function(s){ return s.replace(/^"|"$/g, ''); });
|
|
if (p.length >= 8) {
|
|
imported.push({
|
|
id: p[0] || null,
|
|
nama: p[1],
|
|
harga: cleanCSVNumber(p[2]),
|
|
qty: cleanCSVNumber(p[3]),
|
|
total: cleanCSVNumber(p[4]),
|
|
tgl: p[5],
|
|
kategori: p[6],
|
|
catatan: p[7]
|
|
});
|
|
}
|
|
}
|
|
if (imported.length > 0 && confirm('Akan memproses ' + imported.length + ' data belanja. Lanjutkan?')) {
|
|
showLoading(true, 'IMPORT DATA BELANJA...');
|
|
google.script.run.withSuccessHandler(function(res) {
|
|
showLoading(false);
|
|
if (res && res.belanja) {
|
|
currentBelanja = res.belanja;
|
|
renderBelanja(res.belanja);
|
|
}
|
|
alert('Berhasil memproses data belanja.');
|
|
}).withFailureHandler(function(err) {
|
|
showLoading(false);
|
|
alert('Gagal import belanja.\n' + (err && err.message ? err.message : err));
|
|
}).saveBelanjaBulk(imported);
|
|
}
|
|
};
|
|
reader.readAsText(file);
|
|
};
|
|
input.click();
|
|
}
|
|
|
|
function recalcBelanja(mode) {
|
|
var h = Number(document.getElementById('bl-harga').value) || 0;
|
|
var q = Number(document.getElementById('bl-qty').value) || 0;
|
|
var t = Number(document.getElementById('bl-total').value) || 0;
|
|
if (mode === 'qty' || mode === 'harga') {
|
|
document.getElementById('bl-total').value = h * q;
|
|
} else if (mode === 'total' && q > 0) {
|
|
document.getElementById('bl-harga').value = Math.floor(t / q);
|
|
}
|
|
}
|
|
|
|
function simpanBelanja() {
|
|
var p = {
|
|
id: document.getElementById('bl-id').value || null,
|
|
nama: document.getElementById('bl-nama').value.trim(),
|
|
kategori: document.getElementById('bl-kat').value,
|
|
harga: Number(document.getElementById('bl-harga').value) || 0,
|
|
qty: Number(document.getElementById('bl-qty').value) || 0,
|
|
total: Number(document.getElementById('bl-total').value) || 0,
|
|
tgl: new Date().toISOString().split('T')[0]
|
|
};
|
|
|
|
if (!p.nama) { alert('Nama barang wajib diisi!'); return; }
|
|
if (p.total <= 0) { alert('Total belanja tidak boleh nol!'); return; }
|
|
|
|
showLoading(true, 'Menyimpan Data...');
|
|
google.script.run.withSuccessHandler(function(res) {
|
|
showLoading(false);
|
|
alert('Berhasil menyimpan belanja!');
|
|
document.getElementById('bl-id').value = '';
|
|
document.getElementById('bl-nama').value = '';
|
|
document.getElementById('bl-harga').value = '';
|
|
document.getElementById('bl-qty').value = '1';
|
|
document.getElementById('bl-total').value = '';
|
|
if (res && res.belanja) renderBelanja(res.belanja);
|
|
}).withFailureHandler(function(err) {
|
|
showLoading(false);
|
|
alert('Gagal menyimpan belanja.\n' + (err && err.message ? err.message : err));
|
|
}).saveBelanjaBulk([p]);
|
|
}
|
|
|
|
function simpanBelanjaBulk() {
|
|
var bulkText = document.getElementById('bl-bulk').value.trim();
|
|
if (!bulkText) return;
|
|
var lines = bulkText.split('\n');
|
|
var payloads = [];
|
|
var today = new Date().toISOString().split('T')[0];
|
|
var bulkKat = (document.getElementById('bl-bulk-kat') ? document.getElementById('bl-bulk-kat').value : '') || 'Dapur';
|
|
|
|
lines.forEach(function(line) {
|
|
var parts = line.trim().split(/\s+/);
|
|
if (parts.length < 3) return;
|
|
|
|
var last = parts.pop();
|
|
var mid = parts.pop();
|
|
var first = parts.pop();
|
|
var nama = parts.join(' ');
|
|
|
|
var qty, harga, total;
|
|
|
|
if (mid.toLowerCase() === 'x') {
|
|
// Format: Nama Qty x Total (Es Batu 5 x 25000)
|
|
qty = Number(first) || 0;
|
|
total = Number(last) || 0;
|
|
harga = qty > 0 ? Math.floor(total / qty) : total;
|
|
} else if (!isNaN(Number(first)) && !isNaN(Number(mid)) && !isNaN(Number(last))) {
|
|
// Format: Nama Qty Harga Total (Es Batu 5 5000 25000)
|
|
qty = Number(first) || 0;
|
|
harga = Number(mid) || 0;
|
|
total = Number(last) || 0;
|
|
} else {
|
|
// Format: Nama Qty Harga (Es Batu 5 5000)
|
|
nama = (nama ? nama + ' ' : '') + first;
|
|
qty = Number(mid) || 0;
|
|
harga = Number(last) || 0;
|
|
total = qty * harga;
|
|
}
|
|
|
|
nama = autoTitleCase(nama);
|
|
|
|
payloads.push({
|
|
nama: nama,
|
|
qty: qty,
|
|
harga: harga,
|
|
total: total,
|
|
kategori: bulkKat,
|
|
tgl: today
|
|
});
|
|
});
|
|
|
|
if (!payloads.length) { alert('Format salah. Contoh: Es Batu 5 5000'); return; }
|
|
|
|
showLoading(true, 'Menyimpan Belanja...');
|
|
google.script.run.withSuccessHandler(function(res) {
|
|
showLoading(false);
|
|
document.getElementById('bl-bulk').value = '';
|
|
alert('Berhasil menyimpan ' + payloads.length + ' item.');
|
|
if (res && res.belanja) renderBelanja(res.belanja);
|
|
}).withFailureHandler(function(err) {
|
|
showLoading(false);
|
|
alert('Gagal menyimpan belanja.\n' + (err && err.message ? err.message : err));
|
|
}).saveBelanjaBulk(payloads);
|
|
}
|
|
|
|
function syncBelanjaOneWay() {
|
|
var today = new Date().toISOString().split('T')[0];
|
|
if (!confirm('Sinkron 1 arah belanja tanggal ' + today + ' ke Dashboard (RekapTransaksi) dan Stok&Belanja?')) return;
|
|
showLoading(true, 'SYNC BELANJA...');
|
|
google.script.run.withSuccessHandler(function(res) {
|
|
showLoading(false);
|
|
var msg = 'SYNC selesai.\n\nTanggal: ' + (res && res.date ? res.date : today) +
|
|
'\nItem lokal: ' + (res && res.localCount != null ? res.localCount : '-') +
|
|
'\nRekapTransaksi: ' + (res && res.rekap && res.rekap.ok ? ('OK (insert ' + res.rekap.inserted + ', update ' + res.rekap.updated + ', skip ' + res.rekap.skipped + ')') : ('GAGAL: ' + ((res && res.rekap && res.rekap.error) ? res.rekap.error : '-'))) +
|
|
'\nStok&Belanja: ' + (res && res.stokBelanja && res.stokBelanja.ok ? ('OK (belanja ' + res.stokBelanja.belanja + ', operasional ' + res.stokBelanja.operasional + ', pegawai ' + res.stokBelanja.pegawai + ', skip ' + res.stokBelanja.skipped + ')') : ('GAGAL: ' + ((res && res.stokBelanja && res.stokBelanja.error) ? res.stokBelanja.error : '-')));
|
|
alert(msg);
|
|
}).withFailureHandler(function(err) {
|
|
showLoading(false);
|
|
alert('Gagal sync.\n' + (err && err.message ? err.message : err));
|
|
}).syncBelanjaOut(today);
|
|
}
|
|
|
|
function editBelanja(id, dataStr) {
|
|
var data = JSON.parse(decodeURIComponent(dataStr));
|
|
document.getElementById('bl-id').value = data.id;
|
|
document.getElementById('bl-nama').value = data.nama;
|
|
document.getElementById('bl-kat').value = mapBelanjaKategori(data.kategori || 'Dapur');
|
|
document.getElementById('bl-qty').value = data.qty;
|
|
document.getElementById('bl-harga').value = data.harga;
|
|
document.getElementById('bl-total').value = data.total;
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
document.getElementById('bl-nama').focus();
|
|
}
|
|
|
|
function mapBelanjaKategori(k) {
|
|
var s = String(k || '').trim();
|
|
var allowed = { Modal: true, Bawah: true, Dapur: true, Makan: true, Operasional: true, Pegawai: true, QRIS: true };
|
|
if (allowed[s]) return s;
|
|
var upper = s.toLowerCase();
|
|
if (upper === 'bahan baku') return 'Dapur';
|
|
if (upper === 'gaji') return 'Pegawai';
|
|
if (upper === 'listrik/air' || upper === 'listrik & air') return 'Operasional';
|
|
if (upper === 'sewa') return 'Operasional';
|
|
if (upper === 'lainnya' || upper === 'lain-lain') return 'Operasional';
|
|
return 'Dapur';
|
|
}
|
|
|
|
function autoTitleCase(s) {
|
|
var str = String(s || '').trim().replace(/\s+/g, ' ');
|
|
if (!str) return '';
|
|
return str.split(' ').map(function(w) {
|
|
if (!w) return w;
|
|
if (/[0-9]/.test(w)) return w;
|
|
if (/^[A-Z0-9\-\._]+$/.test(w) && w.length <= 4) return w;
|
|
var lower = w.toLowerCase();
|
|
return lower.charAt(0).toUpperCase() + lower.slice(1);
|
|
}).join(' ');
|
|
}
|
|
|
|
function hapusBelanja(id) {
|
|
if (!confirm('Anda yakin ingin menghapus item belanja ini?')) return;
|
|
showLoading(true, 'Menghapus...');
|
|
google.script.run.withSuccessHandler(function(res) {
|
|
showLoading(false);
|
|
alert('Item berhasil dihapus.');
|
|
if (res && res.belanja) renderBelanja(res.belanja);
|
|
}).withFailureHandler(function(err) {
|
|
showLoading(false);
|
|
alert('Gagal menghapus belanja.\n' + (err && err.message ? err.message : err));
|
|
}).deleteBelanja(id);
|
|
}
|
|
|
|
// Kalkulator Logic
|
|
function calcAdd(v) { document.getElementById('calc-input').value += v; }
|
|
function calcClear() { document.getElementById('calc-input').value = ''; document.getElementById('calc-result').innerText = '= 0'; }
|
|
function calcEval() {
|
|
try {
|
|
var res = eval(document.getElementById('calc-input').value);
|
|
document.getElementById('calc-result').innerText = '= ' + (Number(res)||0).toLocaleString();
|
|
} catch(e) { alert('Format kalkulator salah'); }
|
|
}
|
|
|
|
function renderBelanja(data) {
|
|
currentBelanja = data; // Update currentBelanja whenever data is rendered
|
|
var box = document.getElementById('belanja-list');
|
|
box.innerHTML = '';
|
|
|
|
if (!data || data.length === 0) {
|
|
box.innerHTML = '<div class="muted">Belum ada data belanja.</div>';
|
|
return;
|
|
}
|
|
|
|
// Group by date
|
|
var grouped = {};
|
|
data.forEach(function(b) {
|
|
var tgl = b.tgl ? b.tgl.split(' ')[0] : 'Tanpa Tanggal';
|
|
if (!grouped[tgl]) grouped[tgl] = [];
|
|
grouped[tgl].push(b);
|
|
});
|
|
|
|
var sortedDates = Object.keys(grouped).sort().reverse();
|
|
|
|
sortedDates.forEach(function(tgl) {
|
|
var items = grouped[tgl].slice().reverse();
|
|
var totalDay = items.reduce(function(acc, b) { return acc + (Number(b.total) || 0); }, 0);
|
|
|
|
var header = document.createElement('div');
|
|
header.className = 'date-header';
|
|
header.innerHTML = '<span>' + tgl + '</span>' +
|
|
'<span class="total-day">Rp ' + totalDay.toLocaleString() + '</span>';
|
|
box.appendChild(header);
|
|
|
|
items.forEach(function(b) {
|
|
var div = document.createElement('div');
|
|
div.className = 'item-row';
|
|
var katLabel = b.kategori ? '<span class="item-kat">[' + b.kategori + ']</span>' : '';
|
|
var dataStr = encodeURIComponent(JSON.stringify(b));
|
|
div.innerHTML = '<div class="item-info">' +
|
|
katLabel +
|
|
'<span class="item-name">' + b.nama + '</span>' +
|
|
'<span class="item-detail">' + b.qty + ' x Rp ' + (Number(b.harga)||0).toLocaleString() + '</span>' +
|
|
'</div>' +
|
|
'<div style="text-align: right;">' +
|
|
'<div class="item-price">Rp ' + (Number(b.total)||0).toLocaleString() + '</div>' +
|
|
'<div style="margin-top: 5px;">' +
|
|
'<button class="btn" style="padding: 4px 10px; font-size: 10px; width: auto; background: #111; color: white; margin-right: 5px;" onclick="editBelanja(\'' + b.id + '\', \'' + dataStr + '\')">EDIT</button>' +
|
|
'<button class="btn" style="padding: 4px 10px; font-size: 10px; width: auto; background: #e11d48; color: white;" onclick="hapusBelanja(\'' + b.id + '\')">HAPUS</button>' +
|
|
'</div>' +
|
|
'</div>';
|
|
box.appendChild(div);
|
|
});
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|