Online Daily Deals & Time-Limited Offer Scheduler

Online Daily Deals & Time-Limited Offer Scheduler

Plan and visualize your promotional calendar with precision.

Add New Deal

$
$

Deal Schedule

No deals scheduled yet. Add one using the form.

Ends: ${end.toLocaleString()}

${currencyFormatter.format(deal.discounted)} ${currencyFormatter.format(deal.original)} (${discountPercent.toFixed(0)}% off)

${countdownText}

`; scheduleContainer.appendChild(card); }); }; const updateCountdowns = () => { document.querySelectorAll('.countdown').forEach(el => { const targetTime = new Date(el.dataset.time).getTime(); const now = new Date().getTime(); const distance = targetTime - now; if (distance < 0) { el.parentElement.textContent = "Offer status changed."; // A full re-render might be needed here to update status tag return; } const days = Math.floor(distance / (1000 * 60 * 60 * 24)); const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((distance % (1000 * 60)) / 1000); el.textContent = `${days}d ${hours}h ${minutes}m ${seconds}s`; }); }; const handleAddOrUpdate = () => { const name = dealNameEl.value.trim(); const original = parseFloat(originalPriceEl.value); const discounted = parseFloat(discountedPriceEl.value); const start = startTimeEl.value; const end = endTimeEl.value; if (!name || isNaN(original) || isNaN(discounted) || !start || !end) { alert('Please fill out all fields with valid data.'); return; } if (new Date(start) >= new Date(end)) { alert('End time must be after the start time.'); return; } if (editingId) { // Update existing deals = deals.map(d => d.id === editingId ? { ...d, name, original, discounted, start, end } : d); } else { // Add new const newDeal = { id: Date.now(), name, original, discounted, start, end }; deals.push(newDeal); } resetForm(); renderDeals(); }; const handleScheduleClick = (e) => { if (e.target.classList.contains('edit-btn')) { const id = Number(e.target.dataset.id); const dealToEdit = deals.find(d => d.id === id); if (dealToEdit) { formTitleEl.textContent = 'Edit Deal'; addUpdateBtn.textContent = 'Update Deal'; addUpdateBtn.classList.remove('bg-blue-600', 'hover:bg-blue-700'); addUpdateBtn.classList.add('bg-amber-500', 'hover:bg-amber-600'); cancelEditBtn.classList.remove('hidden'); dealIdEl.value = dealToEdit.id; dealNameEl.value = dealToEdit.name; originalPriceEl.value = dealToEdit.original; discountedPriceEl.value = dealToEdit.discounted; startTimeEl.value = dealToEdit.start; endTimeEl.value = dealToEdit.end; editingId = id; window.scrollTo({ top: 0, behavior: 'smooth' }); } } else if (e.target.classList.contains('delete-btn')) { const id = Number(e.target.dataset.id); deals = deals.filter(d => d.id !== id); renderDeals(); } }; const downloadPDF = () => { const { jsPDF } = window.jspdf; const pdfContent = document.getElementById('pdf-content'); // Temporarily remove buttons for PDF pdfContent.querySelectorAll('button').forEach(btn => btn.style.display = 'none'); html2canvas(pdfContent, { scale: 2, backgroundColor: '#f9fafb' }).then(canvas => { // Restore buttons after capture pdfContent.querySelectorAll('button').forEach(btn => btn.style.display = 'block'); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = (canvas.height * pdfWidth) / canvas.width; pdf.setFontSize(16); pdf.text("Deal Schedule", pdfWidth / 2, 15, { align: 'center' }); pdf.addImage(imgData, 'PNG', 0, 25, pdfWidth, pdfHeight); pdf.save('deal-schedule.pdf'); }); }; // --- EVENT LISTENERS --- addUpdateBtn.addEventListener('click', handleAddOrUpdate); cancelEditBtn.addEventListener('click', resetForm); scheduleContainer.addEventListener('click', handleScheduleClick); downloadPdfBtn.addEventListener('click', downloadPDF); // --- INITIALIZATION --- renderDeals(); setInterval(() => { updateCountdowns(); // Periodically check if a deal's status has changed renderDeals(); }, 1000); });
Scroll to Top