Documentation Index
Fetch the complete documentation index at: https://mintlify.com/CodecraftBySyed/Mini-POS-System/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The POS component (pos.js) is the core transaction processing interface. It handles product selection, cart management, discount calculations, checkout operations, and thermal receipt generation.
Responsibilities
- Display available products for sale
- Manage shopping cart (add, update, remove items)
- Calculate subtotals, discounts, and grand totals
- Process sales and save to database
- Generate and print thermal receipts
- Handle both quick checkout and print-with-checkout flows
State Management
Cart State
The cart is an array of cart items with structure:
{
id: number,
name: string,
price: number,
qty: number
}
DOM Elements
#productGrid - Container for product buttons
#cartItems - Container for cart item list
#itemCount - Display total item quantity
#subtotal - Display subtotal amount
#discountAmount - Display calculated discount
#grandTotal - Display final total
#discountValue - Input for discount value
#discountType - Select for discount type (percent/fixed)
#clearCart - Button to clear entire cart
#checkoutBtn - Quick checkout button
#printBillBtn - Checkout with print button
Functions
renderProducts()
Fetches and displays all available products as clickable buttons.
async function renderProducts()
Behavior:
- Fetches products from database
- Shows empty state if no products
- Renders product grid with name and price
- Attaches click handlers to add products to cart
Example Output:
productGrid.innerHTML = products.map(p => `
<button data-id="${p.id}" data-name="${p.name}" data-price="${p.price}"
class="add-product border-2 border-gray-200 rounded-lg p-4 hover:border-indigo-500">
<div class="font-semibold text-gray-900 mb-1">${p.name}</div>
<div class="text-lg font-bold text-indigo-600">₹${money(p.price)}</div>
</button>
`).join('');
addToCart(prod)
Adds a product to the cart or increments quantity if already present.
Product object with id, name, and price
function addToCart(prod) {
const found = cart.find(c => c.id === prod.id);
if (found) found.qty += 1;
else cart.push({ ...prod, qty: 1 });
renderCart();
showToast(`${prod.name} added to cart`, 'success');
}
calculateDiscount(subtotal)
Calculates discount amount based on type and value.
The cart subtotal before discount
Returns: number - Discount amount
function calculateDiscount(subtotal) {
const value = parseFloat(discountValueEl.value) || 0;
const type = discountTypeEl.value;
if (type === 'percent') {
return (subtotal * (value / 100));
}
return value;
}
Discount Types:
percent - Percentage-based discount (e.g., 10% off)
fixed - Fixed amount discount (e.g., ₹50 off)
renderCart()
Renders the shopping cart UI and updates all totals.
Behavior:
- Shows empty state if cart has no items
- Renders each cart item with quantity controls
- Calculates subtotal, discount, and grand total
- Attaches event handlers for increment, decrement, and remove buttons
Cart Item Controls:
- Decrement (−): Reduces quantity (minimum 1)
- Increment (+): Increases quantity
- Remove (×): Removes item from cart
Example Cart Item Rendering:
cartItems.innerHTML = cart.map((c, idx) => {
itemCount += c.qty;
subtotal += c.qty * c.price;
return `
<div class="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
<div class="flex-1">
<div class="font-medium text-gray-900">${c.name}</div>
<div class="text-sm text-gray-600">₹${money(c.price)} × ${c.qty}</div>
</div>
<div class="flex items-center gap-2">
<button data-idx="${idx}" class="dec-btn">−</button>
<button data-idx="${idx}" class="inc-btn">+</button>
<button data-idx="${idx}" class="rem-btn">×</button>
</div>
</div>
`;
}).join('');
generateThermalReceipt()
Generates a formatted thermal receipt string (32 characters wide).
Returns: string - Formatted receipt text
function generateThermalReceipt() {
const date = new Date().toLocaleString();
const subtotal = Number(subtotalEl.textContent.slice(1));
const discount = Number(discountAmountEl.textContent.slice(2));
const total = Number(grandTotalEl.textContent.slice(1));
let receipt = [
'Mini POS - Codecraft by Syed',
'--------------------------------',
`Date: ${date}`,
'--------------------------------',
'Items:',
...cart.map(item => [
item.name,
`${item.qty} x ₹${money(item.price)} ₹${money(item.qty * item.price)}`
]).flat(),
'--------------------------------',
`Subtotal: ₹${money(subtotal)}`,
`Discount: -₹${money(discount)}`,
'--------------------------------',
`Total: ₹${money(total)}`,
'--------------------------------',
'',
' Thank You!',
' Please Visit Again',
''
].join('\\n');
return receipt;
}
printReceipt(receipt)
Opens a print dialog with formatted thermal receipt.
The formatted receipt text from generateThermalReceipt()
Behavior:
- Opens a 300x600px popup window
- Injects receipt HTML with thermal printer styling (80mm width)
- Automatically triggers print dialog
- Closes window after printing
function printReceipt(receipt) {
const printWindow = window.open('', '', 'width=300,height=600');
printWindow.document.write(`
<html>
<head>
<style>
body {
font-family: 'Courier New', monospace;
font-size: 12px;
width: 80mm;
margin: 0;
padding: 10px;
}
</style>
</head>
<body>
<pre>${receipt}</pre>
<script>
window.onload = function() {
window.print();
window.onafterprint = function() {
window.close();
};
};
</script>
</body>
</html>
`);
}
processSale(withPrint)
Processes the current cart as a sale and optionally prints receipt.
Whether to print a thermal receipt after checkout
Returns: Promise<void>
Behavior:
- Validates cart is not empty
- Collects subtotal, discount, and total from DOM
- Creates sale object with timestamp and items
- Saves sale to database via
addSale()
- Optionally generates and prints receipt
- Clears cart and shows success toast
async function processSale(withPrint = false) {
if (cart.length === 0) {
showToast('Cart is empty', 'error');
return;
}
const sale = {
date: new Date().toISOString(),
items: cart.map(({ id, name, price, qty }) => ({ id, name, price, qty })),
subtotal,
discount,
total
};
await addSale(sale);
if (withPrint) {
const receipt = generateThermalReceipt();
printReceipt(receipt);
}
cart = [];
renderCart();
showToast('Sale completed successfully!', 'success');
}
Event Handlers
Clear Cart
clearCartBtn.addEventListener('click', () => {
if (cart.length > 0 && confirm('Clear cart?')) {
cart = [];
renderCart();
showToast('Cart cleared');
}
});
Auto-recalculates totals when discount value or type changes:
[discountValueEl, discountTypeEl].forEach(el => {
el.addEventListener('input', renderCart);
});
// Quick checkout without printing
checkoutBtn.addEventListener('click', () => processSale(false));
// Checkout with bill printing
document.getElementById('printBillBtn').addEventListener('click', () => processSale(true));
Dependencies
Provides getProducts() and addSale() functions
Provides money() formatting and showToast() notification functions
Auto-Execution
On module load:
renderProducts();
renderCart();