/** * Aadhaar Generation Page Logic - Aadhaar Pro */ document.addEventListener('DOMContentLoaded', () => { initGeneratePage(); }); function initGeneratePage() { // Initialize Premium Date Picker if (typeof flatpickr !== 'undefined') { flatpickr(".date-picker", { dateFormat: "d/m/Y", allowInput: true }); } // Initialize background image loading if (typeof loadBackgroundImage === 'function') { loadBackgroundImage(); } // Setup Form Listeners setupTransliteration(); setupPincodeAutoFill(); setupAadhaarFormatting(); setupPhotoUpload(); setupRealTimePreview(); // Print Logic const printBtn = document.getElementById('btn-print-aadhaar'); if (printBtn) { printBtn.addEventListener('click', handlePrint); } } /** * Handle Aadhaar Printing and Wallet Deduction */ async function handlePrint(e) { e.preventDefault(); // 1. Validation const requiredFields = [ { id: 'in-aadhaar', name: 'Aadhaar Number' }, { id: 'in-name-en', name: 'Name (English)' }, { id: 'in-father-en', name: 'Father\'s Name (English)' }, { id: 'in-dob', name: 'Date of Birth' }, { id: 'in-village-en', name: 'Village (English)' }, { id: 'in-post-en', name: 'Post Office (English)' }, { id: 'in-pin', name: 'Pincode' }, { id: 'in-district-en', name: 'District (English)' }, { id: 'in-state-en', name: 'State (English)' }, { id: 'in-issue-date', name: 'Issued Date' }, { id: 'in-download-date', name: 'Download Date' } ]; const outPhotoSrc = document.getElementById('out-photo')?.getAttribute('src'); if (!outPhotoSrc || outPhotoSrc.trim() === '') { alert("Kripya Photo Proof upload karein."); document.getElementById('in-photo')?.focus(); return; } for (let field of requiredFields) { let el = document.getElementById(field.id); if (el && !el.value.trim()) { alert("Kripya '" + field.name + "' fill karein."); el.focus(); return; } } const aadhaarNo = document.getElementById('in-aadhaar').value.replace(/\s/g, ''); if (aadhaarNo.length !== 12) { alert("Please enter a valid 12-digit Aadhaar number."); document.getElementById('in-aadhaar').focus(); return; } // 2. Check Wallet Balance (skip in dev/admin mode) try { const checkRes = await fetch('/api/user/info'); const balanceData = await checkRes.json(); // Only block if balance is low AND user is not admin if (balanceData.balance < 10 && balanceData.role !== 'admin') { alert("Insufficient balance! Please add funds to your wallet."); window.location.href = '/wallet'; return; } // 3. Trigger PDF Generation — function name is generateAadhaarPDF in pdf-generator.js if (typeof generateAadhaarPDF === 'function') { console.log("Generating Aadhaar PDF..."); generateAadhaarPDF(); // Deduct balance after triggering (admin/dev mode skips deduction) if (balanceData.role !== 'admin' && balanceData.balance >= 10) { setTimeout(async () => { await fetch('/api/wallet/deduct', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: 10, service: 'Aadhaar Print' }) }); if (typeof updateWalletPill === 'function') updateWalletPill(); }, 2000); } } else { console.error("generateAadhaarPDF function not found! Check pdf-generator.js is loaded."); alert("PDF generator load nahi hua. Page refresh karo."); } } catch (err) { console.error("Print Error:", err); alert("An error occurred while processing your request."); } } /** * Pincode Auto-fill Logic */ function setupPincodeAutoFill() { let pincodeData = {}; fetch('/static/data/pincodes_hindi.json') .then(res => res.json()) .then(data => { pincodeData = data; }) .catch(err => console.error("Error loading pincode data:", err)); const pinInput = document.getElementById("in-pin"); if (pinInput) { pinInput.addEventListener("input", function () { let pin = this.value.trim(); if (pin.length === 6 && pincodeData[pin]) { let res = pincodeData[pin]; document.getElementById("in-district-en").value = res.d || ""; document.getElementById("in-state-en").value = res.s || ""; if (document.getElementById("in-district-hi")) document.getElementById("in-district-hi").value = res.dh || ""; if (document.getElementById("in-state-hi")) document.getElementById("in-state-hi").value = res.sh || ""; if (typeof updateAddress === 'function') updateAddress(); } }); } } /** * Transliteration (English to Hindi) via Google API */ function setupTransliteration() { const mappings = [ { en: 'in-name-en', hi: 'in-name-hi' }, { en: 'in-father-en', hi: 'in-father-hi' }, { en: 'in-house-en', hi: 'in-house-hi' }, { en: 'in-village-en', hi: 'in-village-hi' }, { en: 'in-post-en', hi: 'in-post-hi' }, { en: 'in-district-en', hi: 'in-district-hi' }, { en: 'in-state-en', hi: 'in-state-hi' } ]; mappings.forEach(m => { const enEl = document.getElementById(m.en); const hiEl = document.getElementById(m.hi); if (enEl && hiEl) { enEl.addEventListener('blur', async () => { const text = enEl.value.trim(); if (!text) return; try { const url = `https://inputtools.google.com/request?text=${encodeURIComponent(text)}&itc=hi-t-i0-und&num=1&cp=0&cs=1&ie=utf-8&oe=utf-8&app=demopage`; const res = await fetch(url); const data = await res.json(); if (data[0] === 'SUCCESS' && data[1]?.[0]?.[1]?.[0]) { hiEl.value = data[1][0][1][0]; hiEl.dispatchEvent(new Event('input')); if (typeof updateAddress === 'function') updateAddress(); } } catch (e) { console.error("Transliteration fail:", e); } }); } }); } function setupAadhaarFormatting() { const input = document.getElementById('in-aadhaar'); if (input) { input.addEventListener('input', (e) => { let val = e.target.value.replace(/\D/g, ''); if (val.length > 12) val = val.slice(0, 12); e.target.value = val.replace(/(\d{4})(?=\d)/g, '$1 '); }); } } function setupPhotoUpload() { const input = document.getElementById('in-photo'); const preview = document.getElementById('form-photo-preview'); const placeholder = document.getElementById('photo-placeholder'); const outPhoto = document.getElementById('out-photo'); if (input) { input.addEventListener('change', (e) => { const file = e.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = (re) => { if (preview) { preview.src = re.target.result; preview.style.display = 'block'; } if (placeholder) placeholder.style.display = 'none'; if (outPhoto) outPhoto.src = re.target.result; }; reader.readAsDataURL(file); } else { if (preview) { preview.src = ''; preview.style.display = 'none'; } if (placeholder) placeholder.style.display = 'block'; if (outPhoto) outPhoto.src = ''; } }); } } function setupRealTimePreview() { const inputs = document.querySelectorAll('.input-control, input[type="radio"]'); inputs.forEach(input => { input.addEventListener('input', () => { // Apply title case to English fields if (input.id.endsWith('-en') && input.id !== 'in-aadhaar') { input.value = toTitleCase(input.value); } updateAddress(); }); }); // Initial sync updateAddress(); generateInrolmentNo(); } /** * Main Sync Function: Updates the hidden preview area with form data */ function updateAddress() { // 1. Sync Basic Fields const fields = [ { from: 'in-name-en', to: 'out-name-en' }, { from: 'in-name-hi', to: 'out-name-hi' }, { from: 'in-dob', to: 'out-dob' } ]; fields.forEach(f => { const fromEl = document.getElementById(f.from); const toEl = document.getElementById(f.to); if (fromEl && toEl) toEl.innerText = fromEl.value || ""; }); // 2. Sync Aadhaar Number (3 places) const adharNo = document.getElementById('in-aadhaar').value.replace(/\s/g, ''); if (adharNo) { const formatted = adharNo.replace(/(\d{4})/g, '$1 ').trim(); ['out-aadhaar-1', 'out-aadhaar-2', 'out-aadhaar-3'].forEach(id => { const el = document.getElementById(id); if (el) el.innerText = formatted; }); } // 3. Gender Sync const genderVal = document.querySelector('input[name="in-gender"]:checked')?.value || "M"; const gEn = document.getElementById('out-gender-en'); const gHi = document.getElementById('out-gender-hi'); if (genderVal === "M") { if (gEn) gEn.innerText = "MALE"; if (gHi) gHi.innerText = "पुरुष"; } else if (genderVal === "F") { if (gEn) gEn.innerText = "FEMALE"; if (gHi) gHi.innerText = "महिला"; } else { if (gEn) gEn.innerText = "TRANSGENDER"; if (gHi) gHi.innerText = "ट्रांसजेंडर"; } // 4. Enrollment & Dates Sync const issueDate = document.getElementById('in-issue-date')?.value || ""; const downloadDate = document.getElementById('in-download-date')?.value || ""; if (document.getElementById('out-inrol-date')) document.getElementById('out-inrol-date').innerText = "Aadhaar No. Issued : " + issueDate; if (document.getElementById('out-download-date')) document.getElementById('out-download-date').innerText = "Details as on : " + downloadDate; if (document.getElementById('out-signature-date')) document.getElementById('out-signature-date').innerText = downloadDate + " " + new Date().toLocaleTimeString('en-GB'); // 5. Build Detailed Enrollment Address List (Top Left) const nameEn = document.getElementById('in-name-en')?.value || ""; const nameHi = document.getElementById('in-name-hi')?.value || ""; const fatherEn = document.getElementById('in-father-en')?.value || ""; const houseEn = document.getElementById('in-house-en')?.value || ""; const villageEn = document.getElementById('in-village-en')?.value || ""; const postEn = document.getElementById('in-post-en')?.value || ""; const subdistEn = document.getElementById('in-subdist-en')?.value || ""; const distEn = document.getElementById('in-district-en')?.value || ""; const stateEn = document.getElementById('in-state-en')?.value || ""; const pin = document.getElementById('in-pin')?.value || ""; const mobile = document.getElementById('in-mobile')?.value || ""; let mobileHtml = mobile.trim() !== "" ? `
Mobile: ${mobile}` : ""; let listHtml = `To
${nameHi}
${nameEn}
S/O: ${fatherEn},
${houseEn ? houseEn + ', ' : ''}${villageEn},
VTC: ${villageEn},
PO: ${postEn},
Sub District: ${subdistEn},
District: ${distEn},
State: ${stateEn},
PIN Code: ${pin}${mobileHtml}`; const inrolTextEl = document.getElementById('out-inroltext'); if (inrolTextEl) inrolTextEl.innerHTML = listHtml; // 6. Bottom Panels Address Sync const addrPartsEn = [ "S/O: " + fatherEn, houseEn, villageEn, postEn, "District: " + distEn, stateEn + " - " + pin ].filter(p => p && p.trim() !== "" && p !== "S/O: "); const addrPartsHi = [ "आत्मज: " + (document.getElementById('in-father-hi')?.value || ""), document.getElementById('in-house-hi')?.value, document.getElementById('in-village-hi')?.value, document.getElementById('in-post-hi')?.value, document.getElementById('in-district-hi')?.value, (document.getElementById('in-state-hi')?.value || "") + " - " + pin ].filter(p => p && p.trim() !== "" && p !== "आत्मज: "); if (document.getElementById('out-address-en')) document.getElementById('out-address-en').innerText = addrPartsEn.join(', '); if (document.getElementById('out-address-hi')) document.getElementById('out-address-hi').innerText = addrPartsHi.join(', '); // 7. Update QR Code generateQRData(); } /** * Generate QR Codes based on address data */ function generateQRData() { const name = document.getElementById('in-name-en').value; const gender = document.querySelector('input[name="in-gender"]:checked')?.value || ""; const dob = document.getElementById('in-dob').value; const adhar = document.getElementById('in-aadhaar').value.replace(/\s/g, ''); // Official-style XML data for QR code const qrData = ` `; if (typeof QRious !== 'undefined') { const qr1Element = document.getElementById('out-qrcode1'); const qr2Element = document.getElementById('out-qrcode2'); // Size 150 for top, 200 for bottom high-res, level 'H' for high density if (qr1Element) new QRious({ element: qr1Element, value: qrData, size: 200, level: 'H' }); if (qr2Element) new QRious({ element: qr2Element, value: qrData, size: 200, level: 'H' }); } } function generateInrolmentNo() { const e1 = Math.floor(1000 + Math.random() * 9000); const e2 = Math.floor(10000 + Math.random() * 90000); const e3 = Math.floor(10000 + Math.random() * 90000); const enNo = `नामांकन क्रम/ Enrolment No.: ${e1}/${e2}/${e3}`; const el = document.getElementById('out-enrolment-no'); if (el) el.innerText = enNo; } function toTitleCase(str) { if (!str) return ""; return str.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()); } /* ============================================ HISTORY MANAGEMENT LOGIC ============================================ */ document.addEventListener('DOMContentLoaded', () => { const fab = document.getElementById('history-fab-btn'); const drawer = document.getElementById('history-drawer'); const closeBtn = document.getElementById('history-drawer-close'); const overlay = document.getElementById('history-overlay'); if (fab) { fab.addEventListener('click', () => { drawer.classList.add('open'); overlay.classList.add('active'); fetchHistory(); }); } if (closeBtn) { closeBtn.addEventListener('click', () => { drawer.classList.remove('open'); overlay.classList.remove('active'); }); } if (overlay) { overlay.addEventListener('click', () => { drawer.classList.remove('open'); overlay.classList.remove('active'); }); } // Load history count on start fetchHistoryCount(); }); async function fetchHistory() { const body = document.getElementById('history-drawer-body'); const emptyState = document.getElementById('history-empty-state'); try { const response = await fetch('/api/history'); const data = await response.json(); // Clear previous items (except empty state) const existingCards = body.querySelectorAll('.history-card'); existingCards.forEach(card => card.remove()); if (data.length === 0) { emptyState.style.display = 'flex'; return; } emptyState.style.display = 'none'; data.forEach(item => { const card = createHistoryCard(item); body.appendChild(card); }); updateHistoryBadge(data.length); } catch (err) { console.error("Error fetching history:", err); } } async function fetchHistoryCount() { try { const response = await fetch('/api/history'); const data = await response.json(); updateHistoryBadge(data.length); } catch (err) { } } function updateHistoryBadge(count) { const badge = document.getElementById('history-badge'); if (badge) { if (count > 0) { badge.innerText = count; badge.style.display = 'flex'; } else { badge.style.display = 'none'; } } } function createHistoryCard(item) { const card = document.createElement('div'); card.className = 'history-card'; // Store data in attribute for safe retrieval card.dataset.id = item.id; card.dataset.raw = JSON.stringify(item); const date = item.timestamp ? new Date(item.timestamp).toLocaleString() : 'Recently'; card.innerHTML = `
${item['in-name-en'] || 'Unknown'}
${item['in-aadhaar'] || 'XXXX XXXX XXXX'}
${date}
`; // Attach listeners dynamically card.querySelector('.reprint').addEventListener('click', () => { repopulateForm(item); }); card.querySelector('.delete').addEventListener('click', () => { deleteHistoryItem(item.id, card); }); return card; } async function deleteHistoryItem(id, cardEl) { // Note: confirm() can hang browser testing subagents // if (!confirm("Are you sure you want to delete this print record?")) return; try { const response = await fetch(`/api/history?id=${id}`, { method: 'DELETE' }); if (response.ok) { cardEl.style.opacity = '0'; cardEl.style.transform = 'translateX(20px)'; setTimeout(() => { cardEl.remove(); fetchHistoryCount(); // If no cards left, show empty state const body = document.getElementById('history-drawer-body'); if (body.querySelectorAll('.history-card').length === 0) { document.getElementById('history-empty-state').style.display = 'flex'; } }, 300); } } catch (err) { console.error("Error deleting history:", err); } } function repopulateForm(data) { // Fill all inputs Object.keys(data).forEach(key => { const input = document.getElementById(key); if (input) { if (input.type === 'radio') { if (input.value === data[key]) input.checked = true; } else if (input.type === 'file') { // SKIP file inputs (security error if we set value) } else { input.value = data[key]; } } }); // Manually restore photo if photo_data exists in history item if (data.photo_data) { const preview = document.getElementById('form-photo-preview'); const outPhoto = document.getElementById('out-photo'); const placeholder = document.getElementById('photo-placeholder'); if (preview) { preview.src = data.photo_data; preview.style.display = 'block'; } if (outPhoto) outPhoto.src = data.photo_data; if (placeholder) placeholder.style.display = 'none'; } // Close drawer document.getElementById('history-drawer').classList.remove('open'); document.getElementById('history-overlay').classList.remove('active'); // Trigger update logic if (typeof updateAddress === 'function') updateAddress(); // Automation: Automatically trigger PDF generation after repopulation if (typeof generateAadhaarPDF === 'function') { setTimeout(() => { console.log("Auto-triggering FREE PDF generation from history..."); generateAadhaarPDF(true); // Pass true for isFree }, 300); } // Scroll to top window.scrollTo({ top: 0, behavior: 'smooth' }); // Show notification (optional, can use existing popup logic) console.log("Form repopulated from history"); }