// Initialize Lucide icons lucide.createIcons(); // State management let isSidebarCollapsed = false; let isBillingExpanded = true; let lineItemCount = 0; let currentPatient = null; // Mock patient data for search const mockPatients = [ { id: 'PT-1001', name: 'John Smith', phone: '+1 (555) 123-4567', image: 'https://static.photos/people/100x100/10' }, { id: 'PT-1002', name: 'Emma Wilson', phone: '+1 (555) 234-5678', image: 'https://static.photos/people/100x100/20' }, { id: 'PT-1003', name: 'Michael Brown', phone: '+1 (555) 345-6789', image: 'https://static.photos/people/100x100/30' }, { id: 'PT-1004', name: 'Sarah Johnson', phone: '+1 (555) 456-7890', image: 'https://static.photos/people/100x100/40' }, { id: 'PT-1005', name: 'David Lee', phone: '+1 (555) 567-8901', image: 'https://static.photos/people/100x100/50' } ]; // Initialize on load document.addEventListener('DOMContentLoaded', () => { // Set default dates const today = new Date().toISOString().split('T')[0]; document.getElementById('invoiceDate').value = today; const dueDate = new Date(); dueDate.setDate(dueDate.getDate() + 30); document.getElementById('dueDate').value = dueDate.toISOString().split('T')[0]; // Add initial line item addLineItem(); }); // Sidebar toggle for mobile function toggleSidebar() { const sidebar = document.getElementById('sidebar'); const overlay = document.getElementById('mobileOverlay'); const isOpen = !sidebar.classList.contains('-translate-x-full'); if (isOpen) { sidebar.classList.add('-translate-x-full'); overlay.classList.add('hidden'); document.body.style.overflow = ''; } else { sidebar.classList.remove('-translate-x-full'); overlay.classList.remove('hidden'); document.body.style.overflow = 'hidden'; } } // Sidebar toggle for desktop function toggleSidebarDesktop() { const sidebar = document.getElementById('sidebar'); const mainWrapper = document.getElementById('mainWrapper'); const desktopToggle = document.getElementById('desktopToggle'); isSidebarCollapsed = !isSidebarCollapsed; if (isSidebarCollapsed) { sidebar.classList.add('sidebar-collapsed'); sidebar.style.width = '5rem'; mainWrapper.style.marginLeft = '5rem'; desktopToggle.innerHTML = ''; } else { sidebar.classList.remove('sidebar-collapsed'); sidebar.style.width = '16rem'; mainWrapper.style.marginLeft = '16rem'; desktopToggle.innerHTML = ''; } lucide.createIcons(); // Handle billing submenu visibility const submenu = document.getElementById('billingSubmenu'); if (isSidebarCollapsed) { submenu.style.display = 'none'; } else if (isBillingExpanded) { submenu.style.display = 'block'; } } // Billing submenu toggle function toggleBillingSubmenu() { if (isSidebarCollapsed) return; const submenu = document.getElementById('billingSubmenu'); const chevron = document.getElementById('billingChevron'); isBillingExpanded = !isBillingExpanded; if (isBillingExpanded) { submenu.style.display = 'block'; chevron.style.transform = 'rotate(0deg)'; } else { submenu.style.display = 'none'; chevron.style.transform = 'rotate(-90deg)'; } } // Patient type toggle function setPatientType(type) { const btnExisting = document.getElementById('btnExisting'); const btnNew = document.getElementById('btnNew'); const existingForm = document.getElementById('existingPatientForm'); const newForm = document.getElementById('newPatientForm'); if (type === 'existing') { btnExisting.classList.add('bg-white', 'text-gray-900', 'shadow-sm'); btnExisting.classList.remove('text-gray-600'); btnNew.classList.remove('bg-white', 'text-gray-900', 'shadow-sm'); btnNew.classList.add('text-gray-600'); existingForm.classList.remove('hidden'); newForm.classList.add('hidden'); } else { btnNew.classList.add('bg-white', 'text-gray-900', 'shadow-sm'); btnNew.classList.remove('text-gray-600'); btnExisting.classList.remove('bg-white', 'text-gray-900', 'shadow-sm'); btnExisting.classList.add('text-gray-600'); newForm.classList.remove('hidden'); existingForm.classList.add('hidden'); } } // Patient search functionality function searchPatients(query) { const resultsDiv = document.getElementById('searchResults'); if (query.length < 2) { resultsDiv.classList.add('hidden'); return; } const filtered = mockPatients.filter(p => p.name.toLowerCase().includes(query.toLowerCase()) || p.id.toLowerCase().includes(query.toLowerCase()) || p.phone.includes(query) ); if (filtered.length === 0) { resultsDiv.innerHTML = '
No patients found
'; } else { resultsDiv.innerHTML = filtered.map(patient => `

${patient.name}

${patient.id} • ${patient.phone}

`).join(''); } resultsDiv.classList.remove('hidden'); } // Select patient from search function selectPatient(patientId) { const patient = mockPatients.find(p => p.id === patientId); if (!patient) return; currentPatient = patient; document.getElementById('searchResults').classList.add('hidden'); document.getElementById('patientSearch').value = ''; // Show selected patient card document.getElementById('spImage').src = patient.image; document.getElementById('spName').textContent = patient.name; document.getElementById('spId').textContent = patient.id; document.getElementById('spPhone').textContent = patient.phone; document.getElementById('selectedPatientCard').classList.remove('hidden'); } // Clear selected patient function clearPatient() { currentPatient = null; document.getElementById('selectedPatientCard').classList.add('hidden'); } // Add line item to invoice function addLineItem() { const tbody = document.getElementById('lineItemsBody'); const row = document.createElement('tr'); row.className = 'line-item border-b border-gray-100 hover:bg-gray-50 transition-colors'; row.id = `lineItem-${lineItemCount}`; row.innerHTML = ` `; tbody.appendChild(row); lineItemCount++; // Refresh icons lucide.createIcons(); } // Remove line item function removeLineItem(id) { const row = document.getElementById(`lineItem-${id}`); if (row) { row.style.opacity = '0'; row.style.transform = 'translateX(-20px)'; setTimeout(() => { row.remove(); calculateTotals(); }, 200); } } // Update line item calculation function updateCalculation(id) { const qty = parseFloat(document.getElementById(`qty-${id}`).value) || 0; const rate = parseFloat(document.getElementById(`rate-${id}`).value) || 0; const amount = qty * rate; document.getElementById(`amount-${id}`).value = '$' + amount.toFixed(2); calculateTotals(); } // Calculate invoice totals function calculateTotals() { let subtotal = 0; // Sum all line items for (let i = 0; i < lineItemCount; i++) { const amountField = document.getElementById(`amount-${i}`); if (amountField && amountField.parentElement.parentElement.style.display !== 'none') { const value = parseFloat(amountField.value.replace('$', '')) || 0; subtotal += value; } } const tax = subtotal * 0.08; // 8% tax const total = subtotal + tax; // Update summary displays document.getElementById('summarySubtotal').textContent = '$' + subtotal.toFixed(2); document.getElementById('summaryTax').textContent = '$' + tax.toFixed(2); document.getElementById('summaryTotal').textContent = '$' + total.toFixed(2); document.getElementById('mobileTotal').textContent = '$' + total.toFixed(2); } // Save invoice function saveInvoice() { showToast('Invoice saved successfully!'); // In real app, would send to backend } // Print invoice function printInvoice() { window.print(); } // Send invoice function sendInvoice() { showToast('Invoice sent to patient email!'); // In real app, would trigger email/SMS } // Toast notification function showToast(message) { const toast = document.getElementById('toast'); const toastMessage = document.getElementById('toastMessage'); toastMessage.textContent = message; toast.classList.remove('translate-y-20', 'opacity-0'); setTimeout(() => { toast.classList.add('translate-y-20', 'opacity-0'); }, 3000); } // Close search results when clicking outside document.addEventListener('click', (e) => { const searchContainer = document.getElementById('patientSearch'); const resultsDiv = document.getElementById('searchResults'); if (!searchContainer.contains(e.target) && !resultsDiv.contains(e.target)) { resultsDiv.classList.add('hidden'); } }); // Handle window resize window.addEventListener('resize', () => { if (window.innerWidth >= 1024) { document.getElementById('mobileOverlay').classList.add('hidden'); document.body.style.overflow = ''; } else { const sidebar = document.getElementById('sidebar'); sidebar.classList.add('-translate-x-full'); } });