Membuat Aplikasi Cart dengan Fitur Checkout
Seperti sebelumnya yang saya ceritakan tentang proses saya membuat aplikasi kasir dan manajemen toko dengan next js. saya ingin lebih detail cerita tentang bagaimana membuat bagian cart cekout produk atau bagian kasirnya lah. Jadi di page ini user bisa menambahkan barang ke keranjang, mengubah jumlah barang, mengedit harga untuk diskon, dan melakukan checkout. Saat checkout, data akan disimpan dalam tiga tabel utama: penjualanbrg
, detail_penjualan
, dan barang
. Untuk update stok, trigger yang sebelumnya dibuat secara otomatis akan menyesuaikan stok barang di database.
Berikut adalah penjelasan logika dan proses pembuatan aplikasi ini:
1. Membuat Tabel Database
Tabel utama dalam aplikasi ini meliputi:
- Tabel
barang
: Menyimpan data barang dan stok. - Tabel
penjualanbrg
: Menyimpan informasi transaksi. - Tabel
detail_penjualan
: Menyimpan rincian barang yang dibeli dalam setiap transaksi.
Untuk mempermudah pemeliharaan stok, trigger di database akan mengurangi stok secara otomatis berdasarkan jumlah barang yang ditambahkan ke detail_penjualan
.
2. Menampilkan Peta Barang Berdasarkan Kategori
Aplikasi ini menggunakan state barangList
yang diambil dari tabel barang
di Supabase. Untuk memudahkan pengguna, barang ditampilkan berdasarkan kategori yang dipilih oleh pengguna, dan fitur pencarian memudahkan pencarian barang tertentu.
Contoh Logika Pencarian Barang Berdasarkan Kategori dan Nama:
const filteredBarangList = barangList.filter(
(barang) =>
(barang.barang && barang.barang.toLowerCase().includes(searchTerm.toLowerCase())) ||
(barang.kode_barang && barang.kode_barang.toLowerCase().includes(searchTerm.toLowerCase()))
);
3. Menambahkan Barang ke Keranjang (Cart)
Pengguna dapat menambah barang ke keranjang jika stok masih tersedia. Jika barang yang sama sudah ada di keranjang, maka jumlahnya akan bertambah. Jika stok tidak cukup, aplikasi akan menampilkan peringatan.
Logika Menambahkan Barang ke Keranjang:
const addToCart = (barang) => {
if (barang.stok <= 0) {
alert('Stok barang ini kosong. Tidak dapat menambah ke keranjang.');
return;
}
setCartItems((prevItems) => {
const itemExists = prevItems.find((item) => item.kode_barang === barang.kode_barang);
if (itemExists) {
return prevItems.map((item) =>
item.kode_barang === barang.kode_barang && item.jumlah < barang.stok
? { ...item, jumlah: item.jumlah + 1 }
: item
);
} else {
return [...prevItems, { ...barang, jumlah: 1, totalHarga: barang.harga_jual }];
}
});
};
4. Mengedit Harga untuk Diskon
Aplikasi menyediakan input untuk pengguna mengedit harga barang di keranjang, yang bisa digunakan saat memberi diskon. Saat harga diubah, total harga keseluruhan akan diperbarui secara otomatis.
const handleTotalPriceChange = (kode_barang, newPrice) => {
setCartItems((prevItems) =>
prevItems.map((item) =>
item.kode_barang === kode_barang ? { ...item, totalHarga: newPrice } : item
)
);
};
5. Menghitung Total Harga
Setiap perubahan dalam keranjang, termasuk penambahan, pengurangan, atau perubahan harga, akan memicu perhitungan ulang total harga menggunakan fungsi reduce
.
useEffect(() => {
const total = cartItems.reduce((acc, item) => acc + item.totalHarga * item.jumlah, 0);
setTotalHarga(total);
}, [cartItems]);
6. Proses Checkout dan Penyimpanan Transaksi
Saat pengguna mengklik tombol Checkout, aplikasi akan menyimpan transaksi ke database. Proses ini mencakup langkah-langkah berikut:
- Membuat entri baru di tabel
penjualanbrg
dengantotal_harga
,nama_pelanggan
, dan waktu transaksi. - Menyimpan setiap barang dalam keranjang ke tabel
detail_penjualan
. - Karena tabel
barang
memiliki trigger, stok barang akan berkurang secara otomatis setiap kali barang ditambahkan kedetail_penjualan
.
const handleCheckout = async () => {
if (cartItems.length === 0) {
alert("Keranjang kosong. Tambahkan barang terlebih dahulu.");
return;
}
setLoading(true);
const { data: penjualanData, error: penjualanError } = await supabase
.from('penjualanbrg')
.insert([{ total_harga: totalHarga, nama_pelanggan: namaPelanggan, tanggal: timestamp }])
.select()
.single();
if (penjualanError) {
alert('Gagal membuat transaksi penjualan. Silakan coba lagi.');
setLoading(false);
return;
}
const detailPenjualanData = cartItems.map((item) => ({
id_penjualanbrg: penjualanData.id_penjualanbrg,
kode_barang: item.kode_barang,
jumlah: item.jumlah,
harga_jual: item.totalHarga,
}));
const { error: detailError } = await supabase
.from('detail_penjualan')
.insert(detailPenjualanData);
if (detailError) {
alert('Gagal menyimpan detail transaksi penjualan.');
} else {
alert("Transaksi berhasil disimpan.");
setCartItems([]);
setTotalHarga(0);
setNamaPelanggan('');
router.push('/cart/laporan');
}
setLoading(false);
};
Selesai sudah bagian logic nya, Sekarang untuk tampilannya
- Komponen Pencarian Barang
Buat input teks untuk memfilter barang berdasarkan nama atau kode barang. Pencarian ini memudahkan pengguna untuk menemukan barang tertentu.
<input
type="text"
placeholder="Cari barang atau kode..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
2. Daftar Barang Berdasarkan Kategori
Tampilkan barang berdasarkan hasil pencarian atau kategori tertentu. Setiap barang akan memiliki tombol tambah untuk menambahkannya ke keranjang.
<div className="grid grid-cols-2 gap-4">
{filteredBarangList.map((barang) => (
<div key={barang.kode_barang}>
<h3>{barang.barang}</h3>
<p>Rp {barang.harga_jual}</p>
<p>Stok: {barang.stok}</p>
<button onClick={() => addToCart(barang)}>+</button>
</div>
))}
</div>
3. Tampilan Keranjang
Di keranjang, pengguna dapat melihat barang yang sudah ditambahkan, mengubah jumlah atau mengedit harga jika ada diskon.
<div className="cart">
{cartItems.map((item) => (
<div key={item.kode_barang}>
<h3>{item.barang}</h3>
<p>Jumlah: {item.jumlah}</p>
<input
type="number"
value={item.totalHarga}
onChange={(e) => handleTotalPriceChange(item.kode_barang, Number(e.target.value))}
/>
<button onClick={() => removeFromCart(item.kode_barang)}>−</button>
</div>
))}
<p>Total: Rp {totalHarga}</p>
</div>
4. Tombol Checkout
Tombol checkout akan menyimpan data transaksi ke database dan mengarahkan pengguna ke halaman laporan jika berhasil.
<button onClick={handleCheckout}>Checkout</button>
Dengan gini tampilan dinamis dan reaktif proses perpindahan dari mobile app ke web app harusnya mulus, karena usernya yaitu kasir , gamau yang lemot lemot macam php