Competitor Price Tracker

Competitor Price Tracker

Analyze your pricing strategy against key competitors.

Pricing Analysis

No products added yet.

`; return; } elements.config.productListContainer.innerHTML = products.map(p => `
${p.name}
`).join(''); }; const handleFormSubmit = (e) => { e.preventDefault(); const productData = { name: elements.config.productName.value, ourPrice: parseFloat(elements.config.ourPrice.value), compA_name: elements.config.compAName.value || 'Competitor A', compA_price: elements.config.compAPrice.value ? parseFloat(elements.config.compAPrice.value) : null, compB_name: elements.config.compBName.value || 'Competitor B', compB_price: elements.config.compBPrice.value ? parseFloat(elements.config.compBPrice.value) : null, }; if (editingProductId) { // Update const index = products.findIndex(p => p.id === editingProductId); products[index] = { ...products[index], ...productData }; } else { // Add new productData.id = Date.now(); products.push(productData); } clearForm(); renderAll(); }; const clearForm = () => { editingProductId = null; elements.config.form.reset(); elements.config.productId.value = ''; elements.config.formTitle.textContent = 'Add New Product'; }; const handleEdit = (id) => { const product = products.find(p => p.id === id); if (!product) return; editingProductId = id; elements.config.productId.value = product.id; elements.config.productName.value = product.name; elements.config.ourPrice.value = product.ourPrice; elements.config.compAName.value = product.compA_name; elements.config.compAPrice.value = product.compA_price; elements.config.compBName.value = product.compB_name; elements.config.compBPrice.value = product.compB_price; elements.config.formTitle.textContent = 'Edit Product'; switchTab('config'); }; const handleDelete = (id) => { if (confirm('Are you sure you want to delete this product?')) { products = products.filter(p => p.id !== id); if (editingProductId === id) { clearForm(); } renderAll(); } }; const downloadPDF = async () => { const { jsPDF } = window.jspdf; const pdfContent = elements.pdf.contentArea; // Clone the content to modify for PDF without affecting the screen const pdfClone = pdfContent.cloneNode(true); pdfClone.style.padding = '20px'; pdfClone.style.backgroundColor = '#ffffff'; // Remove action buttons from the clone pdfClone.querySelectorAll('.print-hide').forEach(el => el.remove()); document.body.appendChild(pdfClone); const canvas = await html2canvas(pdfClone, { scale: 2, backgroundColor: '#ffffff' }); document.body.removeChild(pdfClone); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'landscape', unit: 'px', format: [canvas.width, canvas.height] }); pdf.addImage(imgData, 'PNG', 0, 0, canvas.width, canvas.height); // Add footer to PDF const pageCount = pdf.internal.getNumberOfPages(); for (let i = 1; i <= pageCount; i++) { pdf.setPage(i); pdf.setFontSize(10); pdf.setTextColor(150); pdf.text( `Report generated on: ${new Date().toLocaleDateString()}`, pdf.internal.pageSize.getWidth() / 2, pdf.internal.pageSize.getHeight() - 10, { align: 'center' } ); } pdf.save('competitor-price-report.pdf'); }; const renderAll = () => { renderDashboard(); renderProductList(); }; // --- INITIALIZATION --- const initialize = () => { products = [...sampleData]; // Event Listeners elements.tabs.dashboard.addEventListener('click', () => switchTab('dashboard')); elements.tabs.config.addEventListener('click', () => switchTab('config')); elements.navButtons.next.addEventListener('click', () => { const currentIndex = tabs.indexOf(currentTab); if (currentIndex < tabs.length - 1) switchTab(tabs[currentIndex + 1]); }); elements.navButtons.prev.addEventListener('click', () => { const currentIndex = tabs.indexOf(currentTab); if (currentIndex > 0) switchTab(tabs[currentIndex - 1]); }); elements.config.form.addEventListener('submit', handleFormSubmit); elements.config.clearFormBtn.addEventListener('click', clearForm); elements.pdf.downloadBtn.addEventListener('click', downloadPDF); // Make functions globally accessible for inline onclick handlers window.app = { handleEdit, handleDelete }; renderAll(); updateNavButtons(); }; initialize(); });
Scroll to Top