`;
const redeemList = customerActions.querySelector('#redeem-rewards-list');
state.config.rewards.forEach(reward => {
const canAfford = customer.points >= reward.cost;
const button = document.createElement('button');
button.type = 'button';
button.dataset.cost = reward.cost;
button.dataset.id = reward.id;
button.className = `w-full text-left p-2 rounded-lg border text-sm flex justify-between items-center ${canAfford ? 'bg-green-100 text-green-800 hover:bg-green-200' : 'bg-gray-100 text-gray-500 btn-disabled'}`;
button.innerHTML = `
${reward.name} ${reward.cost} pts`;
if (!canAfford) button.disabled = true;
redeemList.appendChild(button);
});
} else {
customerActions.innerHTML = `
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();
});