Spaces:
Sleeping
Sleeping
| /** | |
| * Wallet Page Logic - Aadhaar Pro | |
| */ | |
| let currentUserInfo = null; | |
| document.addEventListener('DOMContentLoaded', () => { | |
| initWalletPage(); | |
| }); | |
| function initWalletPage() { | |
| loadBalance(); | |
| setupAmountPresets(); | |
| setupModalFlow(); | |
| setupPaymentForm(); | |
| loadTopupRequests(); | |
| } | |
| /** | |
| * Fetch and update user balance | |
| */ | |
| async function loadBalance() { | |
| try { | |
| const res = await fetch('/api/user/info'); | |
| const data = await res.json(); | |
| currentUserInfo = data; | |
| // Update hero amount | |
| const heroBalance = document.getElementById('user-balance-hero'); | |
| if (heroBalance) heroBalance.innerText = data.balance.toFixed(2); | |
| // Update sidebar pill if it exists | |
| const sidebarPill = document.getElementById('wallet-balance'); | |
| if (sidebarPill) sidebarPill.innerText = data.balance.toFixed(2); | |
| } catch (err) { | |
| console.error('Error loading wallet balance:', err); | |
| } | |
| } | |
| /** | |
| * Amount Preset Buttons functionality | |
| */ | |
| function setupAmountPresets() { | |
| const buttons = document.querySelectorAll('.btn-preset'); | |
| const amountInput = document.getElementById('init-amount'); | |
| buttons.forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| const amount = btn.getAttribute('data-amount'); | |
| if (amountInput) amountInput.value = amount; | |
| }); | |
| }); | |
| } | |
| /** | |
| * Setup Modal Open/Close Logic | |
| */ | |
| function setupModalFlow() { | |
| const proceedBtn = document.getElementById('btn-proceed-topup'); | |
| const modal = document.getElementById('topup-payment-modal'); | |
| const closeBtn = document.getElementById('close-topup-modal'); | |
| if (!proceedBtn || !modal) return; | |
| proceedBtn.addEventListener('click', () => { | |
| const initAmount = document.getElementById('init-amount').value; | |
| const amount = parseFloat(initAmount); | |
| if (isNaN(amount) || amount < 10) { | |
| alert('Please enter a valid amount (Minimum ₹10).'); | |
| return; | |
| } | |
| // Set amount in the modal | |
| document.getElementById('pay-amount').value = amount; | |
| document.getElementById('modal-display-amount').innerText = `₹${amount}`; | |
| // Update QR Code dynamically | |
| const upiId = '9219361344@ybl'; | |
| const qrImg = document.getElementById('payment-qr-img'); | |
| qrImg.src = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=upi://pay?pa=${upiId}&am=${amount}&tn=WalletTopup`; | |
| // Show Modal | |
| modal.style.display = 'flex'; | |
| }); | |
| if (closeBtn) { | |
| closeBtn.addEventListener('click', () => { | |
| modal.style.display = 'none'; | |
| }); | |
| } | |
| } | |
| /** | |
| * Custom Toast Notification | |
| */ | |
| function showToast(type, title, message) { | |
| const container = document.getElementById('toast-container'); | |
| if (!container) return; | |
| const toast = document.createElement('div'); | |
| toast.className = `toast-message ${type}`; | |
| let iconClass = 'fa-solid fa-circle-info'; | |
| if (type === 'success') iconClass = 'fa-solid fa-circle-check'; | |
| if (type === 'error') iconClass = 'fa-solid fa-circle-exclamation'; | |
| toast.innerHTML = ` | |
| <div class="toast-icon"><i class="${iconClass}"></i></div> | |
| <div class="toast-content"> | |
| <h4>${title}</h4> | |
| <p>${message}</p> | |
| </div> | |
| `; | |
| container.appendChild(toast); | |
| // Remove toast after 5 seconds | |
| setTimeout(() => { | |
| toast.classList.add('fade-out'); | |
| setTimeout(() => toast.remove(), 400); // Wait for animation | |
| }, 5000); | |
| } | |
| /** | |
| * Setup Payment Form Submission | |
| */ | |
| function setupPaymentForm() { | |
| const form = document.getElementById('payment-form'); | |
| if (!form) return; | |
| form.addEventListener('submit', async (e) => { | |
| e.preventDefault(); | |
| const amount = document.getElementById('pay-amount').value; | |
| const utr = document.getElementById('pay-utr').value; | |
| const fileInput = document.getElementById('pay-screenshot'); | |
| const file = fileInput ? fileInput.files[0] : null; | |
| const submitBtn = document.getElementById('btn-submit-topup'); | |
| if (!utr || utr.length < 12) { | |
| alert('Please enter a valid 12-digit UTR number.'); | |
| return; | |
| } | |
| submitBtn.disabled = true; | |
| submitBtn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Submitting...'; | |
| // Prepare FormData for multipart upload | |
| const formData = new FormData(); | |
| formData.append('amount', amount); | |
| formData.append('utr', utr); | |
| formData.append('screenshot', file); | |
| try { | |
| const res = await fetch('/api/wallet/topup', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const data = await res.json(); | |
| if (data.success) { | |
| // Close modal | |
| document.getElementById('topup-payment-modal').style.display = 'none'; | |
| // Show rich toast message | |
| const userName = currentUserInfo ? currentUserInfo.name : 'User'; | |
| const toastMsg = ` | |
| <strong>Retailer:</strong> ${userName}<br> | |
| <strong>Added:</strong> ₹${amount}<br> | |
| <strong>UTR:</strong> ${utr}<br> | |
| <em>Pending verification.</em> | |
| `; | |
| showToast('success', 'Top-up Request Submitted', toastMsg); | |
| // Reset form and initial input | |
| form.reset(); | |
| document.getElementById('init-amount').value = ''; | |
| // Refresh the top-up requests list | |
| loadTopupRequests(); | |
| } else { | |
| showToast('error', 'Submission Failed', data.error); | |
| } | |
| } catch (err) { | |
| console.error('Error submitting top-up:', err); | |
| showToast('error', 'Network Error', 'Failed to connect to the server.'); | |
| } finally { | |
| submitBtn.disabled = false; | |
| submitBtn.innerHTML = '<i class="fa-solid fa-paper-plane" style="margin-right: 8px;"></i> Submit Request'; | |
| } | |
| }); | |
| } | |
| /** | |
| * Load and display user's top-up requests | |
| */ | |
| async function loadTopupRequests() { | |
| try { | |
| const res = await fetch('/api/wallet/history'); | |
| const requests = await res.json(); | |
| const requestsList = document.getElementById('topup-requests-list'); | |
| const emptyState = document.getElementById('empty-requests'); | |
| if (!requestsList) return; | |
| // Clear existing content except empty state | |
| requestsList.innerHTML = ''; | |
| if (requests.length === 0) { | |
| if (emptyState) { | |
| requestsList.appendChild(emptyState); | |
| } | |
| return; | |
| } | |
| // Hide empty state if it exists | |
| if (emptyState) { | |
| emptyState.style.display = 'none'; | |
| } | |
| // Add requests to the list | |
| requests.forEach(request => { | |
| const requestItem = createRequestElement(request); | |
| requestsList.appendChild(requestItem); | |
| }); | |
| } catch (err) { | |
| console.error('Error loading top-up requests:', err); | |
| } | |
| } | |
| /** | |
| * Create HTML element for a top-up request | |
| */ | |
| function createRequestElement(request) { | |
| const item = document.createElement('div'); | |
| item.className = 'request-item'; | |
| const statusClass = `status-${request.status}`; | |
| const statusIcon = getStatusIcon(request.status); | |
| const formattedDate = new Date(request.date).toLocaleString('en-IN', { | |
| day: '2-digit', | |
| month: 'short', | |
| year: 'numeric', | |
| hour: '2-digit', | |
| minute: '2-digit' | |
| }); | |
| item.innerHTML = ` | |
| <div class="request-info"> | |
| <div class="request-amount">₹${request.amount.toFixed(2)}</div> | |
| <div class="request-details"> | |
| <span>UTR: ${request.utr}</span> | |
| <span>${formattedDate}</span> | |
| </div> | |
| </div> | |
| <div class="request-status ${statusClass}"> | |
| <i class="${statusIcon}"></i> | |
| ${request.status.charAt(0).toUpperCase() + request.status.slice(1)} | |
| </div> | |
| `; | |
| return item; | |
| } | |
| /** | |
| * Get appropriate icon for request status | |
| */ | |
| function getStatusIcon(status) { | |
| switch (status) { | |
| case 'pending': return 'fa-solid fa-clock'; | |
| case 'approved': return 'fa-solid fa-check-circle'; | |
| case 'rejected': return 'fa-solid fa-times-circle'; | |
| default: return 'fa-solid fa-question-circle'; | |
| } | |
| } | |