197 lines
7.9 KiB
PHP
197 lines
7.9 KiB
PHP
<?php
|
|
require_once 'includes/auth.php';
|
|
require_login();
|
|
|
|
require_once 'db/config.php';
|
|
require_once __DIR__ . '/includes/header.php';
|
|
|
|
try {
|
|
$stmt = db()->query("SELECT id, name, price, stock FROM products ORDER BY name ASC");
|
|
$products = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} catch (PDOException $e) {
|
|
die("Error fetching products: " . $e->getMessage());
|
|
}
|
|
?>
|
|
|
|
<div class="container-fluid mt-4">
|
|
<div class="row">
|
|
<!-- Product Selection -->
|
|
<div class="col-md-7">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">Products</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row" id="product-grid">
|
|
<?php if (empty($products)): ?>
|
|
<div class="col-12">
|
|
<div class="alert alert-info">No products found. Please <a href="product_add.php">add a product</a> first.</div>
|
|
</div>
|
|
<?php else: ?>
|
|
<?php foreach ($products as $product): ?>
|
|
<div class="col-md-4 col-lg-3 mb-3">
|
|
<div class="card product-card h-100" onclick='addToCart(<?php echo htmlspecialchars(json_encode($product)); ?>)'>
|
|
<div class="card-body text-center">
|
|
<h6 class="card-title small"><?php echo htmlspecialchars($product['name']); ?></h6>
|
|
<p class="card-text small fw-bold">IDR <?php echo number_format($product['price'], 2); ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Cart -->
|
|
<div class="col-md-5">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">Cart</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="cart-items" class="mb-3">
|
|
<p class="text-muted text-center">Cart is empty</p>
|
|
</div>
|
|
<hr>
|
|
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
<h6 class="mb-0">Subtotal</h6>
|
|
<h6 class="mb-0" id="cart-subtotal">IDR 0.00</h6>
|
|
</div>
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<h5 class="mb-0">Total</h5>
|
|
<h5 class="mb-0" id="cart-total">IDR 0.00</h5>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="payment-method" class="form-label">Payment Method</label>
|
|
<select id="payment-method" class="form-select">
|
|
<option>Cash</option>
|
|
<option>Card</option>
|
|
<option>QRIS</option>
|
|
</select>
|
|
</div>
|
|
<div class="d-grid">
|
|
<button class="btn btn-success btn-lg" id="checkout-btn" disabled>Checkout</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
const cart = [];
|
|
|
|
function formatCurrency(amount) {
|
|
return new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR', minimumFractionDigits: 2 }).format(amount);
|
|
}
|
|
|
|
function findCartItem(productId) {
|
|
return cart.find(item => item.id === productId);
|
|
}
|
|
|
|
function addToCart(product) {
|
|
let itemInCart = findCartItem(product.id);
|
|
|
|
if (itemInCart) {
|
|
itemInCart.quantity++;
|
|
} else {
|
|
cart.push({ id: product.id, name: product.name, price: product.price, quantity: 1 });
|
|
}
|
|
renderCart();
|
|
}
|
|
|
|
function updateQuantity(productId, change) {
|
|
let itemInCart = findCartItem(productId);
|
|
if (itemInCart) {
|
|
itemInCart.quantity += change;
|
|
if (itemInCart.quantity <= 0) {
|
|
const itemIndex = cart.findIndex(item => item.id === productId);
|
|
cart.splice(itemIndex, 1);
|
|
}
|
|
}
|
|
renderCart();
|
|
}
|
|
|
|
function renderCart() {
|
|
const cartItemsContainer = document.getElementById('cart-items');
|
|
const subtotalEl = document.getElementById('cart-subtotal');
|
|
const totalEl = document.getElementById('cart-total');
|
|
const checkoutBtn = document.getElementById('checkout-btn');
|
|
|
|
if (cart.length === 0) {
|
|
cartItemsContainer.innerHTML = '<p class="text-muted text-center">Cart is empty</p>';
|
|
subtotalEl.textContent = formatCurrency(0);
|
|
totalEl.textContent = formatCurrency(0);
|
|
checkoutBtn.disabled = true;
|
|
return;
|
|
}
|
|
|
|
cartItemsContainer.innerHTML = cart.map(item => `
|
|
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
<div>
|
|
<h6 class="mb-0 small">${item.name}</h6>
|
|
<p class="mb-0 text-muted small">${formatCurrency(item.price)}</p>
|
|
</div>
|
|
<div class="d-flex align-items-center">
|
|
<button class="btn btn-sm btn-outline-secondary" onclick="updateQuantity(${item.id}, -1)">-</button>
|
|
<span class="mx-2">${item.quantity}</span>
|
|
<button class="btn btn-sm btn-outline-secondary" onclick="updateQuantity(${item.id}, 1)">+</button>
|
|
</div>
|
|
<h6 class="mb-0 small">${formatCurrency(item.price * item.quantity)}</h6>
|
|
</div>
|
|
`).join('');
|
|
|
|
const subtotal = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);
|
|
|
|
subtotalEl.textContent = formatCurrency(subtotal);
|
|
totalEl.textContent = formatCurrency(subtotal); // Assuming no tax for now
|
|
checkoutBtn.disabled = false;
|
|
}
|
|
|
|
async function handleCheckout() {
|
|
const paymentMethod = document.getElementById('payment-method').value;
|
|
const checkoutBtn = document.getElementById('checkout-btn');
|
|
checkoutBtn.disabled = true;
|
|
checkoutBtn.textContent = 'Processing...';
|
|
|
|
try {
|
|
const response = await fetch('_handle_checkout.php', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ cart: cart, payment_method: paymentMethod })
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.success) {
|
|
const cartContainer = document.querySelector('.col-md-5 .card-body');
|
|
cartContainer.innerHTML = `
|
|
<div class="text-center">
|
|
<h5 class="text-success">Checkout Successful!</h5>
|
|
<p>Transaction ID: ${result.transaction_id}</p>
|
|
<a href="receipt.php?sale_id=${result.transaction_id}" target="_blank" class="btn btn-primary">Print Receipt</a>
|
|
<button onclick="window.location.reload()" class="btn btn-secondary">New Sale</button>
|
|
</div>
|
|
`;
|
|
} else {
|
|
alert(`Error: ${result.message}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Checkout error:', error);
|
|
alert('An unexpected error occurred during checkout.');
|
|
} finally {
|
|
checkoutBtn.disabled = false;
|
|
checkoutBtn.textContent = 'Checkout';
|
|
}
|
|
}
|
|
|
|
document.getElementById('checkout-btn').addEventListener('click', handleCheckout);
|
|
|
|
</script>
|
|
|
|
<?php require_once 'includes/footer.php'; ?>
|