Automated Business License Renewal Reminder

Automated Business License Renewal Reminder

Track and manage all your business license renewals in one place.

Total Licenses

0

Expiring Soon

0

Expired

0

License Overview

${license.name}

${license.authority} • Expires: ${formatDate(license.expiryDate)}

`).join(''); }; /** * Updates the summary statistics on the dashboard. */ const updateSummaries = () => { let expiringCount = 0; let expiredCount = 0; licenses.forEach(license => { const status = getLicenseStatus(license.expiryDate).text; if (status === 'Expiring Soon') expiringCount++; if (status === 'Expired') expiredCount++; }); summaryTotal.textContent = licenses.length; summaryExpiring.textContent = expiringCount; summaryExpired.textContent = expiredCount; }; // --- FORM HANDLING --- /** * Handles the form submission for adding or updating a license. * @param {Event} e - The form submission event. */ const handleFormSubmit = (e) => { e.preventDefault(); const id = licenseIdInput.value; const licenseData = { name: licenseNameInput.value.trim(), authority: issuingAuthorityInput.value.trim(), expiryDate: expiryDateInput.value, cost: parseFloat(renewalCostInput.value) || 0 }; if (id) { // Update existing license const index = licenses.findIndex(l => l.id === id); if (index > -1) { licenses[index] = { ...licenses[index], ...licenseData }; } } else { // Add new license licenses.push({ id: generateId(), ...licenseData }); } // Sort licenses by expiry date, ascending licenses.sort((a, b) => new Date(a.expiryDate) - new Date(b.expiryDate)); saveLicenses(); renderAll(); resetForm(); switchTab('dashboard'); // Switch to dashboard to see the result }; /** * Prepares the form for editing a license. * @param {string} id - The ID of the license to edit. */ const editLicense = (id) => { const license = licenses.find(l => l.id === id); if (!license) return; licenseIdInput.value = license.id; licenseNameInput.value = license.name; issuingAuthorityInput.value = license.authority; expiryDateInput.value = license.expiryDate; renewalCostInput.value = license.cost; formTitle.textContent = 'Edit License'; formSubmitBtn.textContent = 'Update License'; cancelEditBtn.classList.remove('hidden'); }; /** * Deletes a license after confirmation. * @param {string} id - The ID of the license to delete. */ const deleteLicense = (id) => { licenses = licenses.filter(l => l.id !== id); saveLicenses(); renderAll(); resetForm(); // Reset form in case the deleted item was being edited }; /** * Resets the form to its initial state for adding a new license. */ const resetForm = () => { licenseForm.reset(); licenseIdInput.value = ''; formTitle.textContent = 'Add a New License'; formSubmitBtn.textContent = 'Add License'; cancelEditBtn.classList.add('hidden'); }; // --- TAB & NAVIGATION LOGIC --- /** * Switches the view to the specified tab. * @param {string} tabId - The ID of the tab to switch to ('dashboard' or 'data-config'). */ const switchTab = (tabId) => { currentTab = tabId; Object.values(contentElements).forEach(el => el.classList.add('hidden')); Object.values(tabElements).forEach(el => el.classList.remove('active')); if (contentElements[tabId]) { contentElements[tabId].classList.remove('hidden'); } if (tabElements[tabId]) { tabElements[tabId].classList.add('active'); } updateNavButtons(); }; /** * Handles clicks on the 'Previous' and 'Next' navigation buttons. * @param {string} direction - 'prev' or 'next'. */ const navigateTabs = (direction) => { const tabs = ['dashboard', 'data-config']; const currentIndex = tabs.indexOf(currentTab); let newIndex = currentIndex; if (direction === 'next' && currentIndex < tabs.length - 1) { newIndex++; } else if (direction === 'prev' && currentIndex > 0) { newIndex--; } switchTab(tabs[newIndex]); }; /** * Updates the visibility and disabled state of the 'Previous' and 'Next' buttons. */ const updateNavButtons = () => { prevBtn.disabled = (currentTab === 'dashboard'); prevBtn.classList.toggle('opacity-50', prevBtn.disabled); nextBtn.disabled = (currentTab === 'data-config'); nextBtn.classList.toggle('opacity-50', nextBtn.disabled); }; /** * A helper function to switch to the data config tab and reset the form for adding a new license. */ const switchToAddMode = () => { switchTab('data-config'); resetForm(); licenseNameInput.focus(); }; // --- PDF GENERATION --- /** * Generates and downloads a PDF of the license dashboard. */ const generatePDF = () => { const { jsPDF } = window.jspdf; const doc = new jsPDF(); doc.setFont('helvetica', 'bold'); doc.setFontSize(18); doc.text('Business License Renewal Dashboard', 14, 22); doc.setFont('helvetica', 'normal'); doc.setFontSize(11); doc.setTextColor(100); doc.text(`Report generated on: ${new Date().toLocaleDateString()}`, 14, 30); const tableData = licenses.map(license => { const status = getLicenseStatus(license.expiryDate); return [ license.name, license.authority, formatDate(license.expiryDate), `$${license.cost.toFixed(2)}`, status.text ]; }); doc.autoTable({ startY: 40, head: [['License Name', 'Issuing Authority', 'Expiry Date', 'Est. Cost', 'Status']], body: tableData, theme: 'striped', headStyles: { fillColor: [37, 99, 235] }, // Blue header didParseCell: function(data) { // Color code the status cell based on its text content if (data.column.dataKey === 4) { // 4 is the index of the 'Status' column if (data.cell.raw === 'Expired') { data.cell.styles.textColor = [153, 27, 27]; // Dark red data.cell.styles.fontStyle = 'bold'; } else if (data.cell.raw === 'Expiring Soon') { data.cell.styles.textColor = [133, 77, 14]; // Dark yellow/orange data.cell.styles.fontStyle = 'bold'; } } } }); doc.save('Business_License_Dashboard.pdf'); }; // --- EVENT LISTENERS & INITIALIZATION --- licenseForm.addEventListener('submit', handleFormSubmit); downloadPdfBtn.addEventListener('click', generatePDF); // Make key functions globally accessible for inline onclick handlers, scoped to an app object. // This is a clean way to meet specification IV.C. window.app = { editLicense, deleteLicense }; // Initialize the application loadLicenses(); renderAll(); // Expose switchTab and other global functions needed by onclick attributes window.switchTab = switchTab; window.navigateTabs = navigateTabs; window.resetForm = resetForm; window.switchToAddMode = switchToAddMode; });
Scroll to Top