Spaces:
Runtime error
Runtime error
| let currentUser = null; | |
| let currentPrescriptions = []; | |
| document.addEventListener('DOMContentLoaded', () => { | |
| console.log('DOM fully loaded, initializing event listeners'); | |
| document.getElementById('showSignupLink').addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| console.log('Show signup link clicked'); | |
| showSignup(); | |
| }); | |
| document.getElementById('showLoginLink').addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| console.log('Show login link clicked'); | |
| showLogin(); | |
| }); | |
| document.getElementById('signupRole').addEventListener('change', function() { | |
| console.log('Signup role changed to:', this.value); | |
| const isPatient = this.value === 'Patient'; | |
| document.getElementById('signupAllergies').disabled = !isPatient; | |
| document.getElementById('signupSymptoms').disabled = !isPatient; | |
| }); | |
| document.getElementById('loginButton').addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| console.log('Login button clicked'); | |
| login(); | |
| }); | |
| document.getElementById('doctorLogout').addEventListener('click', logout); | |
| document.getElementById('patientLogout').addEventListener('click', logout); | |
| document.getElementById('pharmacyLogout').addEventListener('click', logout); | |
| document.getElementById('mostPrescribedButton').addEventListener('click', fetchMostPrescribed); | |
| document.getElementById('viewPrescriptionsButton').addEventListener('click', fetchPrescriptions); | |
| document.getElementById('findPharmaciesButton').addEventListener('click', findPharmacies); | |
| document.getElementById('checkRemindersButton').addEventListener('click', fetchRefillReminders); | |
| document.getElementById('viewOrdersButton').addEventListener('click', fetchOrders); | |
| document.getElementById('checkLowStockButton').addEventListener('click', fetchLowStock); | |
| document.getElementById('medicineIdStock').addEventListener('change', toggleNewTabletFields); | |
| document.getElementById('prescriptionId').addEventListener('change', displayPrescriptionPrice); | |
| document.getElementById('paymentMethod').addEventListener('change', updateButtonStates); | |
| document.getElementById('upiApp').addEventListener('change', updateButtonStates); | |
| document.getElementById('prescriptionId').addEventListener('change', updateButtonStates); | |
| document.getElementById('pharmacyId').addEventListener('change', updateButtonStates); | |
| document.getElementById('orderForm').addEventListener('submit', (e) => { | |
| e.preventDefault(); | |
| placeOrder(); | |
| }); | |
| // Delegated event listener for confirmPayment | |
| document.addEventListener('click', (e) => { | |
| if (e.target.id === 'confirmPayment') { | |
| console.log('Confirm Payment button clicked (delegated)'); | |
| confirmPayment(); | |
| } | |
| }); | |
| }); | |
| function showSignup() { | |
| document.getElementById('loginSection').classList.add('d-none'); | |
| document.getElementById('signupSection').classList.remove('d-none'); | |
| } | |
| function showLogin() { | |
| document.getElementById('signupSection').classList.add('d-none'); | |
| document.getElementById('loginSection').classList.remove('d-none'); | |
| hideDashboards(); | |
| document.getElementById('loginSection').querySelector('form')?.reset(); | |
| console.log('Login form reset and displayed'); | |
| } | |
| function hideDashboards() { | |
| document.getElementById('doctorDashboard').classList.add('d-none'); | |
| document.getElementById('patientDashboard').classList.add('d-none'); | |
| document.getElementById('pharmacyDashboard').classList.add('d-none'); | |
| } | |
| function logout() { | |
| console.log('Logout triggered'); | |
| currentUser = null; | |
| currentPrescriptions = []; | |
| document.getElementById('loginSection').querySelector('form')?.reset(); | |
| document.getElementById('signupForm').reset(); | |
| document.getElementById('prescribeForm').reset(); | |
| document.getElementById('symptomsForm').reset(); | |
| document.getElementById('orderForm').reset(); | |
| document.getElementById('stockForm').reset(); | |
| document.getElementById('prescriptions').innerHTML = ''; | |
| document.getElementById('prescriptionPrice').innerHTML = ''; | |
| document.getElementById('qrCode').innerHTML = ''; | |
| document.getElementById('patientMedicalRecords').innerHTML = ''; | |
| document.getElementById('analytics').innerHTML = ''; | |
| document.getElementById('pendingOrders').innerHTML = ''; | |
| document.getElementById('lowStock').innerHTML = ''; | |
| document.getElementById('nearbyPharmacies').innerHTML = ''; | |
| document.getElementById('refillReminders').innerHTML = ''; | |
| document.getElementById('patientId').innerHTML = '<option value="" disabled selected>Select a Patient</option>'; | |
| document.getElementById('medicineId').innerHTML = '<option value="" disabled selected>Select a Medicine</option>'; | |
| document.getElementById('prescriptionId').innerHTML = '<option value="" disabled selected>Select a Prescription</option>'; | |
| document.getElementById('pharmacyId').innerHTML = '<option value="" disabled selected>Select a Pharmacy</option>'; | |
| document.getElementById('zipCode').innerHTML = '<option value="" disabled selected>Select Zip Code</option>'; | |
| document.getElementById('medicineIdPharmacy').innerHTML = '<option value="" disabled selected>Select Medicine</option>'; | |
| document.getElementById('medicineIdStock').innerHTML = '<option value="" disabled selected>Select a Medicine</option>'; | |
| showLogin(); | |
| showToast('Logged out successfully!', 'success'); | |
| console.log('Login section displayed after logout'); | |
| } | |
| function signup() { | |
| const signupButton = document.querySelector('#signupForm button[type="submit"]'); | |
| setLoading(signupButton, true); | |
| const data = { | |
| role: document.getElementById('signupRole').value, | |
| username: document.getElementById('signupUsername').value, | |
| password: document.getElementById('signupPassword').value, | |
| name: document.getElementById('signupName').value, | |
| email: document.getElementById('signupEmail').value, | |
| zip_code: document.getElementById('signupZipCode').value, | |
| allergies: document.getElementById('signupAllergies').value, | |
| symptoms: document.getElementById('signupSymptoms').value | |
| }; | |
| if (!data.role || !data.username || !data.password || !data.name) { | |
| showToast('Please fill in all required fields.', 'warning'); | |
| setLoading(signupButton, false); | |
| return; | |
| } | |
| console.log('Signup request data:', JSON.stringify(data, null, 2)); | |
| fetch('/signup', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(data) | |
| }) | |
| .then(response => { | |
| console.log('Signup response status:', response.status); | |
| if (!response.ok) { | |
| return response.json().then(err => { throw new Error(err.message || `HTTP error! status: ${response.status}`); }); | |
| } | |
| return response.json(); | |
| }) | |
| .then(data => { | |
| console.log('Signup response data:', JSON.stringify(data, null, 2)); | |
| if (data.status === 'success') { | |
| showToast('Registration successful! Please login.', 'success'); | |
| showLogin(); | |
| document.getElementById('signupForm').reset(); | |
| } else { | |
| showToast(data.message || 'Signup failed.', 'danger'); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Signup error:', error); | |
| showToast(error.message || 'Error connecting to the server.', 'danger'); | |
| }) | |
| .finally(() => { | |
| setLoading(signupButton, false); | |
| }); | |
| } | |
| function login() { | |
| const loginButton = document.getElementById('loginButton'); | |
| setLoading(loginButton, true); | |
| const role = document.getElementById('loginRole').value; | |
| const username = document.getElementById('loginUsername').value; | |
| const password = document.getElementById('loginPassword').value; | |
| if (!role || !username || !password) { | |
| showToast('Please fill in all required fields.', 'warning'); | |
| setLoading(loginButton, false); | |
| return; | |
| } | |
| const data = { username, password, role }; | |
| console.log('Login request data:', JSON.stringify(data, null, 2)); | |
| fetch('/login', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(data) | |
| }) | |
| .then(response => { | |
| console.log('Login response status:', response.status, 'OK:', response.ok); | |
| if (!response.ok) { | |
| return response.json().then(err => { | |
| console.error('Login error response:', err); | |
| throw new Error(err.message || `HTTP error! status: ${response.status}`); | |
| }); | |
| } | |
| return response.json(); | |
| }) | |
| .then(data => { | |
| console.log('Login response data:', JSON.stringify(data, null, 2)); | |
| if (data.status === 'success') { | |
| currentUser = { id: data.user_id, role: data.role, name: data.name }; | |
| hideDashboards(); | |
| if (role === 'Doctor') { | |
| document.getElementById('doctorDashboard').classList.remove('d-none'); | |
| document.getElementById('doctorName').textContent = data.name; | |
| fetchPatients(); | |
| fetchMedicines(); | |
| } else if (role === 'Patient') { | |
| document.getElementById('patientDashboard').classList.remove('d-none'); | |
| document.getElementById('patientName').textContent = data.name; | |
| fetchPrescriptions(); | |
| fetchPharmacies(); | |
| fetchZipCodes(); | |
| fetchMedicinesForPharmacy(); | |
| fetchCurrentSymptoms(); | |
| document.getElementById('orderForm').reset(); | |
| updateButtonStates(); | |
| } else if (role === 'Pharmacy') { | |
| document.getElementById('pharmacyDashboard').classList.remove('d-none'); | |
| document.getElementById('pharmacyName').textContent = data.name; | |
| fetchMedicinesForStock(); | |
| } | |
| showToast('Login successful!', 'success'); | |
| } else { | |
| showToast(data.message || 'Invalid credentials.', 'danger'); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Login fetch error:', error); | |
| showToast(error.message || 'Error connecting to the server.', 'danger'); | |
| }) | |
| .finally(() => { | |
| setLoading(loginButton, false); | |
| console.log('Login request completed'); | |
| }); | |
| } | |
| function updateSymptoms() { | |
| const symptomsButton = document.querySelector('#symptomsForm button[type="submit"]'); | |
| setLoading(symptomsButton, true); | |
| const symptoms = document.getElementById('patientSymptoms').value; | |
| if (!symptoms) { | |
| showToast('Please enter symptoms.', 'warning'); | |
| setLoading(symptomsButton, false); | |
| return; | |
| } | |
| const data = { | |
| patient_id: currentUser.id, | |
| symptoms: symptoms | |
| }; | |
| fetch('/update_symptoms', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(data) | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.status === 'success') { | |
| showToast('Symptoms updated successfully!', 'success'); | |
| document.getElementById('symptomsForm').reset(); | |
| fetchCurrentSymptoms(); | |
| } else { | |
| showToast(data.message || 'Error updating symptoms.', 'danger'); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Error updating symptoms:', error); | |
| showToast('Error connecting to server.', 'danger'); | |
| }) | |
| .finally(() => { | |
| setLoading(symptomsButton, false); | |
| }); | |
| } | |
| function fetchCurrentSymptoms() { | |
| fetch(`/medical_records/${currentUser.id}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.status === 'success') { | |
| document.getElementById('patientSymptoms').value = data.symptoms !== 'None' ? data.symptoms : ''; | |
| } | |
| }) | |
| .catch(error => console.error('Error fetching symptoms:', error)); | |
| } | |
| function fetchPatientMedicalRecords() { | |
| const patientId = document.getElementById('patientId').value; | |
| if (!patientId) return; | |
| fetch(`/medical_records/${patientId}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| const recordsDiv = document.getElementById('patientMedicalRecords'); | |
| if (data.status === 'success') { | |
| recordsDiv.innerHTML = ` | |
| <p><strong>Allergies:</strong> ${data.allergies}</p> | |
| <p><strong>Symptoms:</strong> ${data.symptoms}</p> | |
| `; | |
| } else { | |
| recordsDiv.innerHTML = '<p>No medical records found.</p>'; | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Error fetching medical records:', error); | |
| document.getElementById('patientMedicalRecords').innerHTML = '<p>Error loading records.</p>'; | |
| }); | |
| } | |
| function fetchPatients() { | |
| fetch('/patients') | |
| .then(response => response.json()) | |
| .then(data => { | |
| const patientSelect = document.getElementById('patientId'); | |
| patientSelect.innerHTML = '<option value="" disabled selected>Select a Patient</option>'; | |
| if (data.length === 0) { | |
| patientSelect.innerHTML += '<option value="" disabled>No patients available</option>'; | |
| return; | |
| } | |
| data.forEach(patient => { | |
| patientSelect.innerHTML += `<option value="${patient.id}">${patient.name} (ID: ${patient.id})</option>`; | |
| }); | |
| }) | |
| .catch(error => console.error('Error fetching patients:', error)); | |
| } | |
| function fetchMedicines() { | |
| fetch('/medicines') | |
| .then(response => response.json()) | |
| .then(data => { | |
| const medicineSelect = document.getElementById('medicineId'); | |
| medicineSelect.innerHTML = '<option value="" disabled selected>Select a Medicine</option>'; | |
| if (data.length === 0) { | |
| medicineSelect.innerHTML += '<option value="" disabled>No medicines available</option>'; | |
| return; | |
| } | |
| data.forEach(medicine => { | |
| medicineSelect.innerHTML += `<option value="${medicine.id}">${medicine.name} ($${medicine.price.toFixed(2)})</option>`; | |
| }); | |
| }) | |
| .catch(error => console.error('Error fetching medicines:', error)); | |
| } | |
| function fetchMedicinesForPharmacy() { | |
| fetch('/medicines') | |
| .then(response => response.json()) | |
| .then(data => { | |
| const medicineSelect = document.getElementById('medicineIdPharmacy'); | |
| medicineSelect.innerHTML = '<option value="" disabled selected>Select Medicine</option>'; | |
| if (data.length === 0) { | |
| medicineSelect.innerHTML += '<option value="" disabled>No medicines available</option>'; | |
| return; | |
| } | |
| data.forEach(medicine => { | |
| medicineSelect.innerHTML += `<option value="${medicine.id}">${medicine.name} ($${medicine.price.toFixed(2)})</option>`; | |
| }); | |
| }) | |
| .catch(error => console.error('Error fetching medicines for pharmacy:', error)); | |
| } | |
| function fetchMedicinesForStock() { | |
| fetch('/medicines') | |
| .then(response => response.json()) | |
| .then(data => { | |
| const medicineSelect = document.getElementById('medicineIdStock'); | |
| medicineSelect.innerHTML = '<option value="" disabled selected>Select a Medicine</option>'; | |
| medicineSelect.innerHTML += '<option value="new">Add New Tablet</option>'; | |
| if (data.length === 0) { | |
| return; | |
| } | |
| data.forEach(medicine => { | |
| medicineSelect.innerHTML += `<option value="${medicine.id}">${medicine.name} ($${medicine.price.toFixed(2)})</option>`; | |
| }); | |
| }) | |
| .catch(error => console.error('Error fetching medicines for stock:', error)); | |
| } | |
| function fetchPharmacies() { | |
| fetch('/pharmacies') | |
| .then(response => response.json()) | |
| .then(data => { | |
| const pharmacySelect = document.getElementById('pharmacyId'); | |
| pharmacySelect.innerHTML = '<option value="" disabled selected>Select a Pharmacy</option>'; | |
| if (data.length === 0) { | |
| pharmacySelect.innerHTML += '<option value="" disabled>No pharmacies available</option>'; | |
| return; | |
| } | |
| data.forEach(pharmacy => { | |
| pharmacySelect.innerHTML += `<option value="${pharmacy.id}">${pharmacy.name} (ID: ${pharmacy.id})</option>`; | |
| }); | |
| }) | |
| .catch(error => console.error('Error fetching pharmacies:', error)); | |
| } | |
| function fetchZipCodes() { | |
| fetch('/zip_codes') | |
| .then(response => response.json()) | |
| .then(data => { | |
| const zipSelect = document.getElementById('zipCode'); | |
| zipSelect.innerHTML = '<option value="" disabled selected>Select Zip Code</option>'; | |
| if (data.length === 0) { | |
| zipSelect.innerHTML += '<option value="" disabled>No zip codes available</option>'; | |
| return; | |
| } | |
| data.forEach(zip => { | |
| zipSelect.innerHTML += `<option value="${zip}">${zip}</option>`; | |
| }); | |
| }) | |
| .catch(error => console.error('Error fetching zip codes:', error)); | |
| } | |
| function prescribe() { | |
| const prescribeButton = document.querySelector('#prescribeForm button[type="submit"]'); | |
| setLoading(prescribeButton, true); | |
| const data = { | |
| doctor_id: currentUser.id, | |
| patient_id: document.getElementById('patientId').value, | |
| medicine_id: document.getElementById('medicineId').value, | |
| symptoms: document.getElementById('symptoms').value, | |
| dosage: document.getElementById('dosage').value, | |
| duration: document.getElementById('duration').value | |
| }; | |
| fetch('/prescribe', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(data) | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.status === 'success') { | |
| showToast('Prescription created successfully', 'success'); | |
| document.getElementById('prescribeForm').reset(); | |
| document.getElementById('patientMedicalRecords').innerHTML = ''; | |
| fetchPatients(); | |
| } else { | |
| showToast(data.message || 'Error creating prescription', 'danger'); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| showToast('Error connecting to server', 'danger'); | |
| }) | |
| .finally(() => { | |
| setLoading(prescribeButton, false); | |
| }); | |
| } | |
| function displayPrescriptionPrice() { | |
| const prescriptionId = document.getElementById('prescriptionId').value; | |
| const priceDiv = document.getElementById('prescriptionPrice'); | |
| if (!prescriptionId) { | |
| priceDiv.innerHTML = ''; | |
| return; | |
| } | |
| const prescription = currentPrescriptions.find(p => p.id === parseInt(prescriptionId)); | |
| if (prescription) { | |
| priceDiv.innerHTML = `<p><strong>Price:</strong> $${prescription.price.toFixed(2)}</p>`; | |
| } else { | |
| priceDiv.innerHTML = '<p>Price not available.</p>'; | |
| } | |
| updateButtonStates(); | |
| } | |
| function updateButtonStates() { | |
| const prescriptionId = document.getElementById('prescriptionId').value; | |
| const pharmacyId = document.getElementById('pharmacyId').value; | |
| const paymentMethod = document.getElementById('paymentMethod').value; | |
| const upiApp = document.getElementById('upiApp').value; | |
| const orderId = document.getElementById('orderId').value; | |
| const placeOrderBtn = document.getElementById('placeOrderButton'); | |
| const confirmButton = document.getElementById('confirmPayment'); | |
| const upiForm = document.getElementById('upiForm'); | |
| const upiSelect = document.getElementById('upiApp'); | |
| console.log('Updating button states:', JSON.stringify({ prescriptionId, pharmacyId, paymentMethod, upiApp, orderId }, null, 2)); | |
| placeOrderBtn.disabled = !(prescriptionId && pharmacyId && paymentMethod); | |
| if (paymentMethod === 'upi') { | |
| upiForm.classList.remove('d-none'); | |
| upiSelect.disabled = false; | |
| confirmButton.disabled = !(orderId && upiApp); | |
| console.log('Confirm button state:', JSON.stringify({ orderId, upiApp, disabled: confirmButton.disabled }, null, 2)); | |
| } else { | |
| upiForm.classList.add('d-none'); | |
| upiSelect.disabled = true; | |
| upiSelect.value = ''; | |
| confirmButton.disabled = true; | |
| document.getElementById('qrCode').innerHTML = ''; | |
| console.log('UPI form hidden, confirm button disabled'); | |
| } | |
| } | |
| function generateQRCode(orderId, amount) { | |
| const upiApp = document.getElementById('upiApp').value; | |
| if (!upiApp) { | |
| showToast('Please select a UPI app before generating QR code.', 'warning'); | |
| return; | |
| } | |
| const pharmacyUpiId = 'pharmacy@upi'; | |
| const pharmacyName = 'City Pharmacy'; | |
| const upiUri = `upi://pay?pa=${encodeURIComponent(pharmacyUpiId)}&pn=${encodeURIComponent(pharmacyName)}&am=${encodeURIComponent(amount)}&cu=INR&tn=Order${orderId}`; | |
| console.log('Generated UPI URI:', upiUri); | |
| const qrCodeDiv = document.getElementById('qrCode'); | |
| qrCodeDiv.innerHTML = ''; | |
| if (typeof QRCode === 'undefined') { | |
| console.error('QRCode library not loaded'); | |
| showToast('QR code generation failed: Library not loaded.', 'danger'); | |
| return; | |
| } | |
| try { | |
| new QRCode(qrCodeDiv, { | |
| text: upiUri, | |
| width: 200, | |
| height: 200 | |
| }); | |
| console.log('QR code generated successfully for order:', orderId); | |
| } catch (error) { | |
| console.error('Error generating QR code:', error); | |
| showToast('Failed to generate QR code.', 'danger'); | |
| } | |
| } | |
| function confirmPayment() { | |
| console.log('Confirm Payment button clicked'); | |
| const orderId = document.getElementById('orderId').value; | |
| const paymentMethod = document.getElementById('paymentMethod').value; | |
| const upiApp = document.getElementById('upiApp').value; | |
| console.log('Confirm payment attempt:', JSON.stringify({ orderId, paymentMethod, upiApp }, null, 2)); | |
| if (!orderId || !paymentMethod) { | |
| showToast('Order ID or payment method missing.', 'warning'); | |
| console.log('Confirm payment validation failed:', { orderId, paymentMethod, upiApp }); | |
| return; | |
| } | |
| if (paymentMethod === 'upi' && !upiApp) { | |
| showToast('Please select a UPI app.', 'warning'); | |
| console.log('UPI app not selected:', { upiApp }); | |
| return; | |
| } | |
| const data = { order_id: orderId, payment_method: paymentMethod }; | |
| console.log('Confirm payment request data:', JSON.stringify(data, null, 2)); | |
| fetch('/generate_payment', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(data) | |
| }) | |
| .then(response => { | |
| console.log('Generate payment response status:', response.status, 'OK:', response.ok); | |
| if (!response.ok) { | |
| return response.json().then(err => { | |
| console.error('Generate payment error response:', err); | |
| throw new Error(err.message || `HTTP error! status: ${response.status}`); | |
| }); | |
| } | |
| return response.json(); | |
| }) | |
| .then(data => { | |
| console.log('Generate payment response data:', JSON.stringify(data, null, 2)); | |
| if (data.status === 'success') { | |
| showToast('Payment confirmed successfully!', 'success'); | |
| document.getElementById('prescriptionId').value = ''; | |
| document.getElementById('pharmacyId').value = ''; | |
| document.getElementById('paymentMethod').value = ''; | |
| document.getElementById('upiApp').value = ''; | |
| document.getElementById('orderId').value = ''; | |
| document.getElementById('qrCode').innerHTML = ''; | |
| document.getElementById('placeOrderButton').disabled = true; | |
| document.getElementById('upiForm').classList.add('d-none'); | |
| document.getElementById('confirmPayment').disabled = true; | |
| fetchPrescriptions(); | |
| } else { | |
| showToast(data.message || 'Error confirming payment.', 'danger'); | |
| console.log('Payment confirmation failed:', data); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Confirm payment fetch error:', error); | |
| showToast(error.message || 'Error connecting to server.', 'danger'); | |
| }); | |
| } | |
| function fetchPrescriptions() { | |
| fetch(`/prescriptions/${currentUser.id}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| currentPrescriptions = data; | |
| const prescriptionsDiv = document.getElementById('prescriptions'); | |
| prescriptionsDiv.innerHTML = '<h4 class="h4 fw-semibold">Prescriptions</h4>'; | |
| if (data.length === 0) { | |
| prescriptionsDiv.innerHTML += '<p>No prescriptions found.</p>'; | |
| } else { | |
| data.forEach(p => { | |
| prescriptionsDiv.innerHTML += ` | |
| <div class="border p-3 mb-2 rounded bg-light"> | |
| <p><strong>Prescription ID:</strong> ${p.id}</p> | |
| <p><strong>Medicine:</strong> ${p.medicine}</p> | |
| <p><strong>Price:</strong> $${p.price.toFixed(2)}</p> | |
| <p><strong>Symptoms:</strong> ${p.symptoms || 'N/A'}</p> | |
| <p><strong>Dosage:</strong> ${p.dosage}</p> | |
| <p><strong>Duration:</strong> ${p.duration} days</p> | |
| <p><strong>Date:</strong> ${p.date}</p> | |
| <p><strong>Side Effects:</strong> ${p.side_effects || 'None'}</p> | |
| </div> | |
| `; | |
| }); | |
| } | |
| const prescriptionSelect = document.getElementById('prescriptionId'); | |
| prescriptionSelect.innerHTML = '<option value="" disabled selected>Select a Prescription</option>'; | |
| if (data.length === 0) { | |
| prescriptionSelect.innerHTML += '<option value="" disabled>No prescriptions available</option>'; | |
| } else { | |
| data.forEach(p => { | |
| prescriptionSelect.innerHTML += `<option value="${p.id}">${p.medicine} ($${p.price.toFixed(2)}, Date: ${p.date})</option>`; | |
| }); | |
| } | |
| displayPrescriptionPrice(); | |
| updateButtonStates(); | |
| }) | |
| .catch(error => console.error('Error fetching prescriptions:', error)); | |
| } | |
| function placeOrder() { | |
| const orderButton = document.querySelector('#placeOrderButton'); | |
| setLoading(orderButton, true); | |
| const prescriptionId = document.getElementById('prescriptionId').value; | |
| const pharmacyId = document.getElementById('pharmacyId').value; | |
| const paymentMethod = document.getElementById('paymentMethod').value; | |
| const upiApp = document.getElementById('upiApp').value; | |
| if (!prescriptionId || !pharmacyId || !paymentMethod) { | |
| showToast('Please fill in all required fields.', 'warning'); | |
| setLoading(orderButton, false); | |
| return; | |
| } | |
| const data = { | |
| prescription_id: prescriptionId, | |
| pharmacy_id: pharmacyId, | |
| patient_id: currentUser.id | |
| }; | |
| console.log('Place order request data:', JSON.stringify(data, null, 2)); | |
| fetch('/order', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(data) | |
| }) | |
| .then(response => { | |
| console.log('Place order response status:', response.status, 'OK:', response.ok); | |
| if (!response.ok) { | |
| return response.json().then(err => { | |
| console.error('Place order error response:', err); | |
| throw new Error(err.message || `HTTP error! status: ${response.status}`); | |
| }); | |
| } | |
| return response.json(); | |
| }) | |
| .then(data => { | |
| console.log('Place order response data:', JSON.stringify(data, null, 2)); | |
| if (data.status === 'success') { | |
| showToast('Order placed successfully', 'success'); | |
| if (!data.order_id) { | |
| console.error('Order ID not returned from server'); | |
| showToast('Error: Order ID not received.', 'danger'); | |
| setLoading(orderButton, false); | |
| return; | |
| } | |
| document.getElementById('orderId').value = data.order_id; | |
| console.log('Order ID set to:', data.order_id); | |
| if (paymentMethod === 'upi') { | |
| if (upiApp) { | |
| generateQRCode(data.order_id, data.price); | |
| } else { | |
| showToast('Please select a UPI app to proceed with payment.', 'warning'); | |
| } | |
| updateButtonStates(); | |
| } else { | |
| confirmPayment(); | |
| } | |
| } else { | |
| if (data.alternatives) { | |
| showToast(`Out of stock. Try these pharmacies: ${data.alternatives.map(a => a.name).join(', ')}`, 'warning'); | |
| } else { | |
| showToast(data.message || 'Error placing order', 'danger'); | |
| } | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Place order fetch error:', error); | |
| showToast(error.message || 'Error connecting to server', 'danger'); | |
| }) | |
| .finally(() => { | |
| setLoading(orderButton, false); | |
| }); | |
| } | |
| function fetchOrders() { | |
| fetch(`/orders/${currentUser.id}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| const ordersDiv = document.getElementById('pendingOrders'); | |
| ordersDiv.innerHTML = '<h4 class="h4 fw-semibold">Orders</h4>'; | |
| if (data.length === 0) { | |
| ordersDiv.innerHTML += '<p>No orders found.</p>'; | |
| return; | |
| } | |
| data.forEach(o => { | |
| ordersDiv.innerHTML += ` | |
| <div class="border p-3 mb-2 rounded bg-light"> | |
| <p><strong>Order ID:</strong> ${o.order_id}</p> | |
| <p><strong>Prescription ID:</strong> ${o.prescription_id}</p> | |
| <p><strong>Medicine:</strong> ${o.medicine}</p> | |
| <p><strong>Price:</strong> $${o.price.toFixed(2)}</p> | |
| <p><strong>Status:</strong> ${o.status}</p> | |
| <button class="btn btn-success btn-sm me-2" data-order-id="${o.order_id}" data-status="Fulfilled">Mark Fulfilled</button> | |
| <button class="btn btn-danger btn-sm" data-order-id="${o.order_id}" data-status="Cancelled">Cancel</button> | |
| </div> | |
| `; | |
| }); | |
| document.querySelectorAll('#pendingOrders button').forEach(button => { | |
| button.addEventListener('click', (e) => { | |
| const orderId = e.target.getAttribute('data-order-id'); | |
| const status = e.target.getAttribute('data-status'); | |
| updateOrderStatus(orderId, status); | |
| }); | |
| }); | |
| }) | |
| .catch(error => console.error('Error:', error)); | |
| } | |
| function updateOrderStatus(orderId, status) { | |
| fetch('/update_order', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ order_id: orderId, status }) | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.status === 'success') { | |
| showToast(`Order ${status} successfully`, 'success'); | |
| fetchOrders(); | |
| } else { | |
| showToast('Error updating order', 'danger'); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| showToast('Error connecting to server', 'danger'); | |
| }); | |
| } | |
| function fetchMostPrescribed() { | |
| fetch('/most_prescribed') | |
| .then(response => response.json()) | |
| .then(data => { | |
| const analyticsDiv = document.getElementById('analytics'); | |
| analyticsDiv.innerHTML = '<h4 class="h4 fw-semibold">Most Prescribed Medicines</h4>'; | |
| if (data.length === 0) { | |
| analyticsDiv.innerHTML += '<p>No data available.</p>'; | |
| return; | |
| } | |
| data.forEach(d => { | |
| analyticsDiv.innerHTML += `<p>${d.medicine}: ${d.count} prescriptions</p>`; | |
| }); | |
| }) | |
| .catch(error => console.error('Error:', error)); | |
| } | |
| function fetchLowStock() { | |
| fetch(`/low_stock/${currentUser.id}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| const lowStockDiv = document.getElementById('lowStock'); | |
| lowStockDiv.innerHTML = '<h4 class="h4 fw-semibold">Low Stock Alerts</h4>'; | |
| if (data.length === 0) { | |
| lowStockDiv.innerHTML += '<p>No low stock items.</p>'; | |
| return; | |
| } | |
| data.forEach(d => { | |
| lowStockDiv.innerHTML += `<p>${d.medicine}: ${d.quantity} units</p>`; | |
| }); | |
| }) | |
| .catch(error => console.error('Error:', error)); | |
| } | |
| function findPharmacies() { | |
| const findButton = document.getElementById('findPharmaciesButton'); | |
| setLoading(findButton, true); | |
| const zipCode = document.getElementById('zipCode').value; | |
| const medicineId = document.getElementById('medicineIdPharmacy').value; | |
| if (!zipCode || !medicineId) { | |
| showToast('Please select both a zip code and a medicine.', 'warning'); | |
| setLoading(findButton, false); | |
| return; | |
| } | |
| fetch(`/nearby_pharmacies/${zipCode}/${medicineId}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| const pharmaciesDiv = document.getElementById('nearbyPharmacies'); | |
| pharmaciesDiv.innerHTML = '<h4 class="h4 fw-semibold">Nearby Pharmacies</h4>'; | |
| if (data.length === 0) { | |
| pharmaciesDiv.innerHTML += '<p>No pharmacies found with stock.</p>'; | |
| return; | |
| } | |
| data.forEach(p => { | |
| pharmaciesDiv.innerHTML += `<p>ID: ${p.id}, Name: ${p.name}</p>`; | |
| }); | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| showToast('Error connecting to server', 'danger'); | |
| }) | |
| .finally(() => { | |
| setLoading(findButton, false); | |
| }); | |
| } | |
| function fetchRefillReminders() { | |
| fetch(`/refill_reminders/${currentUser.id}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| const remindersDiv = document.getElementById('refillReminders'); | |
| remindersDiv.innerHTML = '<h4 class="h4 fw-semibold">Refill Reminders</h4>'; | |
| if (data.length === 0) { | |
| remindersDiv.innerHTML += '<p>No refills due.</p>'; | |
| return; | |
| } | |
| data.forEach(r => { | |
| remindersDiv.innerHTML += `<p>Prescription ID: ${r.prescription_id}, Medicine: ${r.medicine}</p>`; | |
| }); | |
| }) | |
| .catch(error => console.error('Error:', error)); | |
| } | |
| function toggleNewTabletFields() { | |
| const medicineSelect = document.getElementById('medicineIdStock'); | |
| const newTabletFields = document.getElementById('newTabletFields'); | |
| const inputs = [ | |
| document.getElementById('newTabletName'), | |
| document.getElementById('newTabletStrength'), | |
| document.getElementById('newTabletManufacturer'), | |
| document.getElementById('newTabletPrice') | |
| ]; | |
| if (medicineSelect.value === 'new') { | |
| newTabletFields.classList.remove('d-none'); | |
| inputs.forEach(input => input.disabled = false); | |
| } else { | |
| newTabletFields.classList.add('d-none'); | |
| inputs.forEach(input => { | |
| input.disabled = true; | |
| input.value = ''; | |
| }); | |
| } | |
| } | |
| function updateStock() { | |
| const stockButton = document.querySelector('#stockForm button[type="submit"]'); | |
| setLoading(stockButton, true); | |
| const medicineId = document.getElementById('medicineIdStock').value; | |
| const quantity = document.getElementById('quantity').value; | |
| const data = { | |
| pharmacy_id: currentUser.id, | |
| medicine_id: medicineId, | |
| quantity: parseInt(quantity) | |
| }; | |
| if (medicineId === 'new') { | |
| data.new_tablet = { | |
| name: document.getElementById('newTabletName').value, | |
| strength: document.getElementById('newTabletStrength').value, | |
| manufacturer: document.getElementById('newTabletManufacturer').value, | |
| price: parseFloat(document.getElementById('newTabletPrice').value) || 0.0 | |
| }; | |
| } | |
| if (!quantity || (medicineId === 'new' && (!data.new_tablet.name || !data.new_tablet.strength || !data.new_tablet.manufacturer))) { | |
| showToast('Please fill in all required fields.', 'warning'); | |
| setLoading(stockButton, false); | |
| return; | |
| } | |
| fetch('/update_stock', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(data) | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.status === 'success') { | |
| showToast('Stock updated successfully', 'success'); | |
| document.getElementById('stockForm').reset(); | |
| toggleNewTabletFields(); | |
| fetchMedicinesForStock(); | |
| } else { | |
| showToast(data.message || 'Error updating stock', 'danger'); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| showToast('Error connecting to server', 'danger'); | |
| }) | |
| .finally(() => { | |
| setLoading(stockButton, false); | |
| }); | |
| } | |
| function setLoading(button, isLoading) { | |
| if (isLoading) { | |
| button.disabled = true; | |
| button.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...'; | |
| } else { | |
| button.disabled = false; | |
| button.innerHTML = button.id === 'loginButton' ? 'Login' : | |
| button.id === 'placeOrderButton' ? 'Place Order' : | |
| button.id === 'findPharmaciesButton' ? 'Find Pharmacies' : | |
| button.id === 'checkLowStockButton' ? 'Check Low Stock' : | |
| 'Submit'; | |
| } | |
| } | |
| function showToast(message, type) { | |
| const toastContainer = document.createElement('div'); | |
| toastContainer.className = `toast align-items-center text-white bg-${type} border-0 position-fixed bottom-0 end-0 m-3`; | |
| toastContainer.setAttribute('role', 'alert'); | |
| toastContainer.setAttribute('aria-live', 'assertive'); | |
| toastContainer.setAttribute('aria-atomic', 'true'); | |
| toastContainer.innerHTML = ` | |
| <div class="d-flex"> | |
| <div class="toast-body">${message}</div> | |
| <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button> | |
| </div> | |
| `; | |
| document.body.appendChild(toastContainer); | |
| const toast = new bootstrap.Toast(toastContainer); | |
| toast.show(); | |
| setTimeout(() => toastContainer.remove(), 3000); | |
| } |