master-brain-api / static /js /generate.js
Dilip8756's picture
Upload 100 files
58c1398 verified
/**
* 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() !== "" ? `<br>Mobile: ${mobile}` : "";
let listHtml = `To<br>${nameHi}<br>${nameEn}<br>S/O: ${fatherEn},<br>${houseEn ? houseEn + ', ' : ''}${villageEn},<br>VTC: ${villageEn},<br>PO: ${postEn},<br>Sub District: ${subdistEn},<br>District: ${distEn},<br>State: ${stateEn},<br>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 = `<?xml version="1.0" encoding="UTF-8"?> <PrintLetterBarcodeData uid="${adhar}" name="${name}" gender="${gender.charAt(0)}" yob="${dob.split('/')[2] || ''}" co="${document.getElementById('in-father-en')?.value || ''}" vtc="${document.getElementById('in-village-en')?.value || ''}" po="${document.getElementById('in-post-en')?.value || ''}" dist="${document.getElementById('in-district-en')?.value || ''}" state="${document.getElementById('in-state-en')?.value || ''}" pc="${document.getElementById('in-pin')?.value || ''}"/>`;
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 = `
<div class="history-card-top">
<div>
<div class="history-card-name">${item['in-name-en'] || 'Unknown'}</div>
<div class="history-card-aadhaar">${item['in-aadhaar'] || 'XXXX XXXX XXXX'}</div>
</div>
<div class="history-card-time">${date}</div>
</div>
<div class="history-card-actions">
<button class="history-card-btn reprint">
<i class="fa-solid fa-redo"></i> Reprint
</button>
<button class="history-card-btn delete">
<i class="fa-solid fa-trash-can"></i> Delete
</button>
</div>
`;
// 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");
}