Smart Customizable Loyalty Reward Points System

Smart Customizable Loyalty Reward Points System

Manage customers, points, and rewards all in one place.

Customer Loyalty Overview

Customer Name Points Balance

Earning Rules

Rewards Management

Customer Management

No customer selected or no customers exist.

`; } // Populate customer list table customerListTable.innerHTML = ''; state.customers.forEach(c => { const tr = document.createElement('tr'); tr.className = 'bg-white border-b hover:bg-gray-50'; tr.innerHTML = ` ${c.name} ${c.points} `; customerListTable.appendChild(tr); }); }; const renderAll = () => { renderConfig(); renderPOS(); updateNavButtons(); }; // --- Row Creation for Config --- const createRewardRow = (reward = {}) => { const id = reward.id || nextId++; const div = document.createElement('div'); div.className = 'reward-row flex items-center gap-2'; div.dataset.id = id; div.innerHTML = ` `; div.querySelector('.remove-btn').addEventListener('click', () => div.remove()); rewardsList.appendChild(div); }; const createCustomerRow = (customer = {}) => { const id = customer.id || nextId++; const div = document.createElement('div'); div.className = 'customer-row flex items-center gap-2'; div.dataset.id = id; div.innerHTML = ` `; div.querySelector('.remove-btn').addEventListener('click', () => { if (state.selectedCustomerId === id) { const firstCustomer = state.customers.find(c => c.id !== id); state.selectedCustomerId = firstCustomer ? firstCustomer.id : null; } div.remove(); saveConfig(); // update state immediately after removal renderPOS(); }); customersList.appendChild(div); }; // --- Event Handlers --- addRewardBtn.addEventListener('click', () => createRewardRow()); addCustomerBtn.addEventListener('click', () => createCustomerRow()); customerSelect.addEventListener('change', (e) => { state.selectedCustomerId = parseInt(e.target.value); renderPOS(); }); // Delegated event listener for dynamic buttons document.body.addEventListener('click', (e) => { if (e.target.id === 'add-points-btn') { const amountInput = document.getElementById('purchase-amount'); const amount = parseFloat(amountInput.value) || 0; if (amount > 0) { const customer = state.customers.find(c => c.id === state.selectedCustomerId); const pointsToAdd = Math.floor(amount * state.config.pointsPerDollar); if (customer && pointsToAdd > 0) { customer.points += pointsToAdd; renderPOS(); } amountInput.value = ''; } } if (e.target.closest('#redeem-rewards-list button')) { const button = e.target.closest('button'); const cost = parseInt(button.dataset.cost); const customer = state.customers.find(c => c.id === state.selectedCustomerId); if (customer && customer.points >= cost) { customer.points -= cost; renderPOS(); } } }); // --- Tab & Navigation Logic --- function switchTab(targetTabId) { if (currentTab === 'config') { saveConfig(); } currentTab = targetTabId; tabs.forEach(tab => tab.classList.toggle('active', tab.dataset.tab === currentTab)); tabContents.forEach(content => content.classList.toggle('active', content.id === currentTab)); renderAll(); // Re-render everything to ensure UI is in sync with state } tabs.forEach(tab => tab.addEventListener('click', () => switchTab(tab.dataset.tab))); nextBtn.addEventListener('click', () => currentTab === 'pos' ? switchTab('config') : switchTab('pos')); prevBtn.addEventListener('click', () => currentTab === 'config' ? switchTab('pos') : switchTab('config')); function updateNavButtons() { if (currentTab === 'pos') { nextBtn.textContent = 'Configure System'; prevBtn.style.display = 'none'; pdfButtonContainer.style.display = 'block'; } else { nextBtn.textContent = 'Go to POS'; prevBtn.style.display = 'inline-flex'; pdfButtonContainer.style.display = 'none'; } } // --- PDF Download --- downloadPdfBtn.addEventListener('click', async () => { const { jsPDF } = window.jspdf; const doc = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' }); const content = document.getElementById('pdf-content'); await new Promise(r => setTimeout(r, 100)); doc.setFont('helvetica', 'bold'); doc.setFontSize(18); doc.text('Customer Loyalty Report', 105, 22, { align: 'center' }); doc.setFontSize(10); doc.setFont('helvetica', 'normal'); doc.text(`Report generated on: ${new Date().toLocaleDateString()}`, 105, 28, { align: 'center' }); const canvas = await html2canvas(content, { scale: 2 }); const imgData = canvas.toDataURL('image/jpeg', 1.0); const imgProps = doc.getImageProperties(imgData); const pdfWidth = doc.internal.pageSize.getWidth() - 28; const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width; doc.addImage(imgData, 'JPEG', 14, 40, pdfWidth, pdfHeight); doc.save(`Loyalty-Report-${new Date().toISOString().slice(0,10)}.pdf`); }); // --- Initial Load --- renderAll(); });
Scroll to Top