Spaces:
Running
Running
| document.addEventListener('DOMContentLoaded', function() { | |
| // Initialize variables | |
| let products = []; | |
| let rtrAmount = 0; | |
| let taxRate = 8.25; | |
| // DOM elements | |
| const productList = document.getElementById('productList'); | |
| const addProductBtn = document.getElementById('addProductBtn'); | |
| const rtrCheckbox = document.getElementById('rtrCheckbox'); | |
| const rtrContainer = document.getElementById('rtrContainer'); | |
| const rtrAmountInput = document.getElementById('rtrAmount'); | |
| const taxRateInput = document.getElementById('taxRate'); | |
| const generateBtn = document.getElementById('generateBtn'); | |
| const downloadBtn = document.getElementById('downloadBtn'); | |
| const resetBtn = document.getElementById('resetBtn'); | |
| const receiptPreview = document.getElementById('receiptPreview'); | |
| const storeNameInput = document.getElementById('storeName'); | |
| const storeAddressInput = document.getElementById('storeAddress'); | |
| const storeCityInput = document.getElementById('storeCity'); | |
| const logoUpload = document.getElementById('logoUpload'); | |
| const logoPreview = document.getElementById('logoPreview'); | |
| // Event listeners | |
| addProductBtn.addEventListener('click', addProduct); | |
| rtrCheckbox.addEventListener('change', toggleRtr); | |
| rtrAmountInput.addEventListener('input', updateRtrAmount); | |
| taxRateInput.addEventListener('input', updateTaxRate); | |
| generateBtn.addEventListener('click', generateReceipt); | |
| downloadBtn.addEventListener('click', downloadPDF); | |
| resetBtn.addEventListener('click', resetForm); | |
| logoUpload.addEventListener('change', handleLogoUpload); | |
| // Handle logo upload | |
| function handleLogoUpload(event) { | |
| const file = event.target.files[0]; | |
| if (file) { | |
| const reader = new FileReader(); | |
| reader.onload = function(e) { | |
| logoPreview.src = e.target.result; | |
| logoPreview.classList.remove('hidden'); | |
| updateReceipt(); | |
| }; | |
| reader.readAsDataURL(file); | |
| } | |
| } | |
| // Add product function | |
| function addProduct() { | |
| const productId = Date.now(); | |
| const productItem = document.createElement('div'); | |
| productItem.className = 'product-item'; | |
| productItem.dataset.id = productId; | |
| productItem.innerHTML = ` | |
| <input type="text" placeholder="Product Name" class="product-name px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <input type="number" placeholder="Price" step="0.01" min="0" class="product-price px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <button class="remove-product px-2 py-1 text-red-500 hover:text-red-700"> | |
| <i data-feather="trash-2"></i> | |
| </button> | |
| `; | |
| productList.appendChild(productItem); | |
| feather.replace(); | |
| // Add event listener to remove button | |
| const removeBtn = productItem.querySelector('.remove-product'); | |
| removeBtn.addEventListener('click', () => { | |
| productList.removeChild(productItem); | |
| updateReceipt(); | |
| }); | |
| // Add event listeners to inputs | |
| const nameInput = productItem.querySelector('.product-name'); | |
| const priceInput = productItem.querySelector('.product-price'); | |
| nameInput.addEventListener('input', updateReceipt); | |
| priceInput.addEventListener('input', updateReceipt); | |
| } | |
| // Toggle RTR payment | |
| function toggleRtr() { | |
| rtrContainer.classList.toggle('hidden', !rtrCheckbox.checked); | |
| if (!rtrCheckbox.checked) { | |
| rtrAmount = 0; | |
| rtrAmountInput.value = ''; | |
| } | |
| updateReceipt(); | |
| } | |
| // Update RTR amount | |
| function updateRtrAmount() { | |
| rtrAmount = parseFloat(rtrAmountInput.value) || 0; | |
| updateReceipt(); | |
| } | |
| // Update tax rate | |
| function updateTaxRate() { | |
| taxRate = parseFloat(taxRateInput.value) || 0; | |
| updateReceipt(); | |
| } | |
| // Generate receipt preview | |
| function updateReceipt() { | |
| // Get all products | |
| products = []; | |
| const productItems = document.querySelectorAll('.product-item'); | |
| productItems.forEach(item => { | |
| const name = item.querySelector('.product-name').value; | |
| const price = parseFloat(item.querySelector('.product-price').value) || 0; | |
| if (name && price > 0) { | |
| products.push({ name, price }); | |
| } | |
| }); | |
| // Calculate totals | |
| const subtotal = products.reduce((sum, product) => sum + product.price, 0); | |
| const taxableAmount = rtrCheckbox.checked ? subtotal : subtotal + rtrAmount; | |
| const tax = taxableAmount * (taxRate / 100); | |
| const total = subtotal + tax + (rtrCheckbox.checked ? rtrAmount : 0); | |
| // Format current date and time | |
| const now = new Date(); | |
| const date = now.toLocaleDateString('en-US', { month: '2-digit', day: '2-digit', year: 'numeric' }); | |
| const time = now.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', second: '2-digit' }); | |
| // Generate receipt HTML | |
| let receiptHTML = ''; | |
| // Add logo if uploaded | |
| if (logoPreview.src && !logoPreview.classList.contains('hidden')) { | |
| receiptHTML += `<div class="logo-container"><img src="${logoPreview.src}" alt="Logo" class="logo"></div>\n`; | |
| } | |
| receiptHTML += ` | |
| <div class="header"> | |
| ${storeNameInput.value || 'BOOST MOBILE'}\n | |
| ${storeAddressInput.value || '22424 IMPERIAL VALLEY DR'}\n | |
| ${storeCityInput.value || 'HOUSTON, TX 77073'}\n | |
| \n | |
| DATE: ${date} TIME: ${time}\n | |
| \n | |
| ITEM DESCRIPTION AMOUNT\n | |
| ----------------------------------------\n | |
| `; | |
| // Add products | |
| products.forEach(product => { | |
| const name = product.name.length > 20 ? product.name.substring(0, 17) + '...' : product.name; | |
| const price = product.price.toFixed(2).padStart(8); | |
| receiptHTML += `${name.padEnd(25)} ${price}\n`; | |
| }); | |
| // Add RTR payment if checked | |
| if (rtrCheckbox.checked && rtrAmount > 0) { | |
| receiptHTML += `\nBoost RTR $5-500${' '.repeat(12)} ${rtrAmount.toFixed(2).padStart(8)}\n`; | |
| receiptHTML += `(No Tax)${' '.repeat(25)}\n`; | |
| } | |
| // Add totals | |
| receiptHTML += ` | |
| \n | |
| ----------------------------------------\n | |
| SUBTOTAL${' '.repeat(19)} ${subtotal.toFixed(2).padStart(8)}\n | |
| TAX${' '.repeat(24)} ${tax.toFixed(2).padStart(8)}\n | |
| TOTAL${' '.repeat(22)} ${total.toFixed(2).padStart(8)}\n | |
| \n | |
| \n | |
| THANK YOU FOR YOUR BUSINESS\n | |
| PAYMENT PROCESSED SUCCESSFULLY\n | |
| \n | |
| \n | |
| NO RETURNS - ALL SALES ARE FINAL.\n | |
| EXCHANGES MAY BE MADE WITHIN 7 DAYS\n | |
| OF PURCHASE.\n | |
| APPROVED RETURNS WILL RECEIVE A\n | |
| REFUND EXCLUDING CHARGES INCURRED\n | |
| FOR WIRELESS SERVICE, ACCESSORIES,\n | |
| AND ADD-ONS.\n | |
| RETURNS MAY BE SUBJECT TO UP TO 20%\n | |
| RESTOCKING FEE.\n | |
| `; | |
| receiptPreview.innerHTML = receiptHTML; | |
| downloadBtn.disabled = false; | |
| } | |
| // Generate PDF receipt | |
| function generateReceipt() { | |
| updateReceipt(); | |
| downloadBtn.disabled = false; | |
| } | |
| // Download PDF | |
| function downloadPDF() { | |
| const { jsPDF } = window.jspdf; | |
| const doc = new jsPDF({ | |
| orientation: 'portrait', | |
| unit: 'mm', | |
| format: [80, 297] | |
| }); | |
| // Get receipt content | |
| const receiptContent = receiptPreview.textContent; | |
| // Set font and add text | |
| doc.setFont('courier'); | |
| doc.setFontSize(8); // Smaller font for thermal receipt | |
| // Split content into lines and add to PDF | |
| const lines = receiptContent.split('\n'); | |
| let y = 10; | |
| const lineHeight = 5; | |
| const marginLeft = 5; | |
| lines.forEach(line => { | |
| // Handle long lines by splitting them | |
| if (doc.getStringUnitWidth(line) * doc.internal.scaleFactor > 70) { | |
| const chunks = []; | |
| let tempLine = line; | |
| while (doc.getStringUnitWidth(tempLine) * doc.internal.scaleFactor > 70) { | |
| let chunk = tempLine.substring(0, 40); | |
| tempLine = tempLine.substring(40); | |
| chunks.push(chunk); | |
| } | |
| chunks.push(tempLine); | |
| chunks.forEach(chunk => { | |
| doc.text(chunk, marginLeft, y); | |
| y += lineHeight; | |
| }); | |
| } else { | |
| doc.text(line, marginLeft, y); | |
| y += lineHeight; | |
| } | |
| }); | |
| // Save the PDF | |
| doc.save('boost_receipt.pdf'); | |
| } | |
| // Reset form | |
| function resetForm() { | |
| productList.innerHTML = ''; | |
| products = []; | |
| rtrCheckbox.checked = false; | |
| rtrContainer.classList.add('hidden'); | |
| rtrAmount = 0; | |
| rtrAmountInput.value = ''; | |
| taxRateInput.value = '8.25'; | |
| taxRate = 8.25; | |
| storeNameInput.value = 'BOOST MOBILE'; | |
| storeAddressInput.value = '22424 IMPERIAL VALLEY DR'; | |
| storeCityInput.value = 'HOUSTON, TX 77073'; | |
| logoUpload.value = ''; | |
| logoPreview.classList.add('hidden'); | |
| receiptPreview.innerHTML = ''; | |
| downloadBtn.disabled = true; | |
| } | |
| // Initialize with one product | |
| addProduct(); | |
| }); | |