Berikut adalah modul pembelajaran lengkap untuk membangun aplikasi Kasir (Point of Sale) sederhana berbasis JavaScript/Web, lengkap dengan persiapan, struktur kode, dan alur logika di balik layarnya.
Modul 1: Persiapan & Struktur Project
1. Tools yang Dibutuhkan
Editor Kode: Visual Studio Code.
Browser: Google Chrome / Firefox.
2. Struktur Folder & File
Buat folder baru bernama aplikasi-kasir dan siapkan 3 file utama:
index.html(Tampilan antarmuka)style.css(Desain/tata letak)app.js(Logika & pemrosesan data)
Modul 2: Desain Antarmuka (index.html & style.css)
Buat struktur HTML dengan dua area utama: Daftar Produk (kiri) dan Keranjang/Struk (kanan).
index.html
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<title>Aplikasi Kasir Sederhana</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<!-- Bagian Produk -->
<div class="produk-section">
<h2>Daftar Produk</h2>
<div id="daftar-produk" class="grid-produk"></div>
</div>
<!-- Bagian Keranjang & Pembayaran -->
<div class="kasir-section">
<h2>Keranjang Belanja</h2>
<ul id="daftar-keranjang"></ul>
<hr>
<p><strong>Total: Rp <span id="total-harga">0</span></strong></p>
<div class="pembayaran">
<label>Bayar: Rp</label>
<input type="number" id="input-bayar" placeholder="Masukkan nominal">
<button onclick="prosesBayar()">Proses Transaksi</button>
</div>
<p id="pesan-kembalian"></p>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
style.css
body { font-family: Arial, sans-serif; margin: 20px; background: #f4f4f9; }
.container { display: flex; gap: 20px; }
.produk-section, .kasir-section { background: white; padding: 20px; border-radius: 8px; flex: 1; }
.grid-produk { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.item-produk { border: 1px solid #ddd; padding: 10px; text-align: center; border-radius: 5px; }
.item-produk button { background: #28a745; color: white; border: none; padding: 5px 10px; cursor: pointer; }
button { cursor: pointer; }
Modul 3: Logika Sistem & Pemrograman (app.js)
app.js
// Data Master Produk
const produkList = [
{ id: 1, nama: "Kopi Hitam", harga: 10000 },
{ id: 2, nama: "Roti Bakar", harga: 15000 },
{ id: 3, nama: "Es Teh Manis", harga: 5000 },
{ id: 4, nama: "Nasi Goreng", harga: 20000 }
];
// State Keranjang
let keranjang = [];
// 1. Tampilkan Daftar Produk ke HTML
function tampilkanProduk() {
const container = document.getElementById('daftar-produk');
container.innerHTML = '';
produkList.forEach(item => {
container.innerHTML += `
<div class="item-produk">
<h4>${item.nama}</h4>
<p>Rp ${item.harga.toLocaleString('id-ID')}</p>
<button onclick="tambahKeKeranjang(${item.id})">+ Tambah</button>
</div>
`;
});
}
// 2. Tambah Produk ke Keranjang
function tambahKeKeranjang(idProduk) {
const itemInKeranjang = keranjang.find(item => item.id === idProduk);
if (itemInKeranjang) {
itemInKeranjang.jumlah += 1;
} else {
const produkAwal = produkList.find(p => p.id === idProduk);
keranjang.push({ ...produkAwal, jumlah: 1 });
}
updateTampilanKeranjang();
}
// 3. Update Tampilan Keranjang & Total
function updateTampilanKeranjang() {
const listKeranjang = document.getElementById('daftar-keranjang');
const totalHargaEl = document.getElementById('total-harga');
listKeranjang.innerHTML = '';
let total = 0;
keranjang.forEach(item => {
const subtotal = item.harga * item.jumlah;
total += subtotal;
listKeranjang.innerHTML += `
<li>${item.nama} x ${item.jumlah} = Rp ${subtotal.toLocaleString('id-ID')}</li>
`;
});
totalHargaEl.innerText = total.toLocaleString('id-ID');
}
// 4. Hitung Pembayaran & Kembalian
function prosesBayar() {
const total = keranjang.reduce((acc, item) => acc + (item.harga * item.jumlah), 0);
const nominalBayar = Number(document.getElementById('input-bayar').value);
const pesanEl = document.getElementById('pesan-kembalian');
if (total === 0) {
pesanEl.innerText = "Keranjang masih kosong!";
return;
}
if (nominalBayar < total) {
pesanEl.innerText = "Uang tidak cukup!";
} else {
const kembalian = nominalBayar - total;
pesanEl.innerText = `Transaksi Berhasil! Kembalian: Rp ${kembalian.toLocaleString('id-ID')}`;
// Reset Kasir
keranjang = [];
document.getElementById('input-bayar').value = '';
updateTampilanKeranjang();
}
}
// Jalankan saat pertama kali dibuka
tampilkanProduk();
Modul 4: Penjelasan Alur Logika Sistem
1. Konsep State (Penyimpanan Sementara Data)
Array
produkList: Berfungsi sebagai database lokal yang menyimpan master barang (ID, nama, harga).Array
keranjang: Berfungsi menampung transaksi aktif. Ketika tombol "+ Tambah" diklik, sistem mengecek apakah barang sudah ada di keranjang. Jika sudah ada, tambahkan nilaijumlah(+1). Jika belum ada, masukkan objek barang baru denganjumlah = 1.
2. Alur Pengolahan Data (Data Flow)
Aksi Tambah:
User klik tombol$\rightarrow$Fungsi tambahKeKeranjang(id)$\rightarrow$Update Array keranjang$\rightarrow$Panggil updateTampilanKeranjang().Kalkulasi Total: Fungsi
updateTampilanKeranjang()melakukan kalkulasisubtotalper item ($\text{harga} \times \text{jumlah}$) lalu menjumlahkan seluruh item untuk menghasilkanTotal.
3. Logika Validasi Pembayaran
Ambil input dari
input-bayar.Lakukan percabangan logika (Condition Check):
Jika $\text{Bayar} < \text{Total}$: Tampilkan peringatan uang kurang.
Jika $\text{Bayar} \ge \text{Total}$: Hitung $\text{Kembalian} = \text{Bayar} - \text{Total}$, tampilkan pesan sukses, lalu kosongkan array
keranjanguntuk transaksi berikutnya.
Berikut adalah pembaruan kode app.js yang menyertakan fitur hapus/kurangi item dari keranjang serta penyimpanan riwayat transaksi otomatis menggunakan localStorage agar data tidak hilang saat halaman di-refresh.
1. Pembaruan Antarmuka (index.html)
Tambahkan area untuk menampilkan riwayat transaksi di bawah bagian keranjang pada index.html:
<!-- Tambahkan div ini di dalam .container atau di bagian bawah html -->
<div class="riwayat-section" style="margin-top: 20px; background: white; padding: 20px; border-radius: 8px;">
<h2>Riwayat Transaksi</h2>
<button onclick="hapusRiwayat()" style="background: #dc3545; color: white; border: none; padding: 5px 10px; margin-bottom: 10px;">Hapus Riwayat</button>
<ul id="daftar-riwayat"></ul>
</div>
2. Kode Logika Baru (app.js)
Gantikan seluruh isi file app.js Anda dengan kode berikut:
// Data Master Produk
const produkList = [
{ id: 1, nama: "Kopi Hitam", harga: 10000 },
{ id: 2, nama: "Roti Bakar", harga: 15000 },
{ id: 3, nama: "Es Teh Manis", harga: 5000 },
{ id: 4, nama: "Nasi Goreng", harga: 20000 }
];
// State Keranjang & Riwayat Transaksi
let keranjang = [];
// Ambil riwayat dari LocalStorage jika ada, jika tidak set array kosong
let riwayatTransaksi = JSON.parse(localStorage.getItem('riwayat_kasir')) || [];
// 1. Tampilkan Daftar Produk
function tampilkanProduk() {
const container = document.getElementById('daftar-produk');
container.innerHTML = '';
produkList.forEach(item => {
container.innerHTML += `
<div class="item-produk">
<h4>${item.nama}</h4>
<p>Rp ${item.harga.toLocaleString('id-ID')}</p>
<button onclick="tambahKeKeranjang(${item.id})">+ Tambah</button>
</div>
`;
});
}
// 2. Tambah Produk ke Keranjang
function tambahKeKeranjang(idProduk) {
const itemInKeranjang = keranjang.find(item => item.id === idProduk);
if (itemInKeranjang) {
itemInKeranjang.jumlah += 1;
} else {
const produkAwal = produkList.find(p => p.id === idProduk);
keranjang.push({ ...produkAwal, jumlah: 1 });
}
updateTampilanKeranjang();
}
// 3. Fitur Baru: Hapus / Kurangi Item dari Keranjang
function kurangiDariKeranjang(idProduk) {
const index = keranjang.findIndex(item => item.id === idProduk);
if (index !== -1) {
if (keranjang[index].jumlah > 1) {
keranjang[index].jumlah -= 1; // Kurangi jumlah jika > 1
} else {
keranjang.splice(index, 1); // Hapus dari keranjang jika jumlah tinggal 1
}
}
updateTampilanKeranjang();
}
// 4. Update Tampilan Keranjang
function updateTampilanKeranjang() {
const listKeranjang = document.getElementById('daftar-keranjang');
const totalHargaEl = document.getElementById('total-harga');
listKeranjang.innerHTML = '';
let total = 0;
keranjang.forEach(item => {
const subtotal = item.harga * item.jumlah;
total += subtotal;
listKeranjang.innerHTML += `
<li style="margin-bottom: 5px;">
${item.nama} x ${item.jumlah} = Rp ${subtotal.toLocaleString('id-ID')}
<button onclick="kurangiDariKeranjang(${item.id})" style="background:#dc3545; color:white; border:none; padding:2px 6px; border-radius:3px; margin-left:8px;">- Hapus</button>
</li>
`;
});
totalHargaEl.innerText = total.toLocaleString('id-ID');
}
// 5. Fitur Baru: Simpan & Tampilkan Riwayat
function simpanDanTampilkanRiwayat(transaksiBaru) {
// Tambahkan ke array riwayat
riwayatTransaksi.push(transaksiBaru);
// Simpan array riwayat ke LocalStorage (diubah ke format string JSON)
localStorage.setItem('riwayat_kasir', JSON.stringify(riwayatTransaksi));
tampilkanRiwayat();
}
function tampilkanRiwayat() {
const listRiwayat = document.getElementById('daftar-riwayat');
if (!listRiwayat) return;
listRiwayat.innerHTML = '';
if (riwayatTransaksi.length === 0) {
listRiwayat.innerHTML = '<li>Belum ada transaksi.</li>';
return;
}
riwayatTransaksi.forEach((tx, index) => {
listRiwayat.innerHTML += `
<li style="margin-bottom: 8px; border-bottom: 1px #eee solid; padding-bottom: 5px;">
<strong>[${tx.waktu}]</strong> Total: Rp ${tx.total.toLocaleString('id-ID')} | Bayar: Rp ${tx.bayar.toLocaleString('id-ID')} (Kembali: Rp ${tx.kembalian.toLocaleString('id-ID')})
</li>
`;
});
}
function hapusRiwayat() {
localStorage.removeItem('riwayat_kasir');
riwayatTransaksi = [];
tampilkanRiwayat();
}
// 6. Hitung Pembayaran
function prosesBayar() {
const total = keranjang.reduce((acc, item) => acc + (item.harga * item.jumlah), 0);
const nominalBayar = Number(document.getElementById('input-bayar').value);
const pesanEl = document.getElementById('pesan-kembalian');
if (total === 0) {
pesanEl.innerText = "Keranjang masih kosong!";
return;
}
if (nominalBayar < total) {
pesanEl.innerText = "Uang tidak cukup!";
} else {
const kembalian = nominalBayar - total;
pesanEl.innerText = `Transaksi Berhasil! Kembalian: Rp ${kembalian.toLocaleString('id-ID')}`;
// Buat Objek Transaksi
const transaksi = {
waktu: new Date().toLocaleString('id-ID'),
total: total,
bayar: nominalBayar,
kembalian: kembalian
};
// Simpan ke LocalStorage
simpanDanTampilkanRiwayat(transaksi);
// Reset Kasir
keranjang = [];
document.getElementById('input-bayar').value = '';
updateTampilanKeranjang();
}
}
// Inisialisasi awal saat halaman dimuat
tampilkanProduk();
tampilkanRiwayat();
3. Penjelasan Logika Fitur Baru
localStorage(Penyimpanan Browser):localStoragehanya menerima tipe data string. Oleh karena itu, kita gunakanJSON.stringify()saat menyimpannya danJSON.parse()saat membaca kembali data objek ke bentuk Javascript Array.Logika Pengurangan/Penghapusan Array (
splice): PadakurangiDariKeranjang(), sistem mengecek nilaijumlah. Jika item lebih dari 1, nilainya cukup dikurangi 1. Jika tersisa 1, kita gunakansplice(index, 1)untuk menghapus elemen tersebut secara penuh dari arraykeranjang.
No comments:
Post a Comment
Terima kasih telah mampir ke Blog yang amburadul ini