Rev 36807 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"><title>Store Verification - SmartDukaan</title><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"><style>body {background: #f5f6f8;font-family: 'Segoe UI', Roboto, sans-serif;color: #2b2b2b;}/* ---------- Top navbar ---------- */.top-nav {background: #fff;border-bottom: 1px solid #ececec;box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);padding: 14px 22px;display: flex;align-items: center;justify-content: space-between;position: sticky;top: 0;z-index: 10;}.nav-home {display: inline-flex;align-items: center;gap: 8px;color: #2b2b2b;font-weight: 600;font-size: 15px;text-decoration: none;}.nav-home:hover {color: #e1212a;text-decoration: none;}.nav-brand {display: inline-flex;align-items: center;text-decoration: none;}.nav-brand .brand-logo {height: 30px;width: auto;display: block;}.nav-help {display: inline-flex;align-items: center;gap: 8px;font-size: 14px;color: #555;white-space: nowrap;}.nav-call {display: inline-flex;align-items: center;gap: 7px;text-decoration: none;color: #555;}.nav-call:hover {text-decoration: none;}.nav-call .call-word {color: #555;font-weight: 600;}.nav-help .phone {color: #e1212a;font-weight: 700;}@media (max-width: 575px) {.top-nav {padding: 10px 12px;}.nav-brand .brand-logo {height: 22px;}.nav-help .q-label,.nav-call .call-word {display: none;}.nav-call {gap: 5px;}.nav-help .phone {font-size: 13px;}.subhead {padding: 12px 14px 0;}}/* ---------- Sub-header home button ---------- */.subhead {padding: 16px 22px 0;}.btn-home {display: inline-flex;align-items: center;gap: 7px;background: #fff;color: #374151;border: 1px solid #e3e6ea;border-radius: 9px;padding: 8px 14px;font-size: 14px;font-weight: 600;text-decoration: none;box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);}.btn-home:hover {background: #f1f3f5;color: #374151;text-decoration: none;}/* ---------- Greeting ---------- */.greeting {text-align: center;font-size: 19px;color: #2b2b2b;margin: 26px 16px 18px;}/* ---------- Card ---------- */.geo-card {max-width: 720px;margin: 0 auto 36px;background: #fff;border-radius: 14px;box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);overflow: hidden;}.card-head {padding: 22px 28px 18px;border-bottom: 1px solid #eee;}.card-head h4 {margin: 0 0 6px;font-weight: 700;font-size: 22px;}.card-head p {margin: 0;color: #6b7280;font-size: 14px;}.card-body-geo {padding: 26px 28px 28px;}@media (max-width: 575px) {.card-head, .card-body-geo {padding-left: 18px;padding-right: 18px;}}/* ---------- Step indicator + labels ---------- */.step-indicator {display: flex;justify-content: center;gap: 8px;margin-bottom: 10px;}.step-caption {text-align: center;font-size: 13px;font-weight: 600;color: #8b93a1;margin-bottom: 24px;}.step-dot {width: 28px;height: 5px;border-radius: 3px;background: #e3e6ea;transition: background 0.3s;}.step-dot.done {background: #22c55e;}.step-dot.current {background: #e1212a;}.section-label {font-size: 12px;font-weight: 700;letter-spacing: 0.6px;text-transform: uppercase;color: #8b93a1;margin-bottom: 12px;}.section-label .step-no {color: #e1212a;}/* Hindi line shown right under its English counterpart */.hindi {display: block;margin-top: 6px;}/* divider between the two steps on the same page */.step-divider {border: none;border-top: 1px solid #eef0f3;margin: 26px 0;}.step-section.locked {opacity: 0.6;pointer-events: none;}/* ---------- Form fields ---------- */.field-label {font-weight: 600;font-size: 15px;margin-bottom: 8px;display: block;}.field-label .req {color: #e1212a;margin-left: 2px;}.input-geo {width: 100%;background: #f1f3f5;border: 1px solid #f1f3f5;border-radius: 10px;padding: 13px 16px;font-size: 15px;transition: border-color 0.2s, background 0.2s;}.input-geo:focus {outline: none;background: #fff;border-color: #e1212a;box-shadow: 0 0 0 0.18rem rgba(225, 33, 42, 0.15);}.input-geo:disabled {color: #6b7280;}.mobile-row {position: relative;}.mobile-row .input-geo {width: 100%;}/* reserve room on the right for the in-field badge once verified */.input-geo.field-verified {padding-right: 104px;}.verified-pill {position: absolute;right: 8px;top: 50%;transform: translateY(-50%);display: none;align-items: center;gap: 6px;background: #e8f7ee;color: #16a34a;border-radius: 8px;padding: 6px 12px;font-size: 13px;font-weight: 600;white-space: nowrap;}.verified-pill.show {display: inline-flex;animation: badgeIn 0.4s ease both;}@keyframes badgeIn {from {opacity: 0;transform: translateY(-50%) translateX(8px);}to {opacity: 1;transform: translateY(-50%) translateX(0);}}/* soft reveal used for Step 2 appearing */@keyframes softReveal {from {opacity: 0;transform: translateY(10px);}to {opacity: 1;transform: translateY(0);}}.reveal-soft {animation: softReveal 0.45s ease both;}/* the tick draws itself once the badge appears */.verified-pill svg path {stroke-dasharray: 24;stroke-dashoffset: 24;}.verified-pill.show svg path {animation: drawTick 0.45s ease-out 0.15s forwards;}@keyframes drawTick {to {stroke-dashoffset: 0;}}/* ---------- Success / thank-you ---------- */.success-wrap {min-height: 380px;display: flex;flex-direction: column;align-items: center;justify-content: center;gap: 30px;padding: 44px 24px;text-align: center;}/* circle draws a full 360, then the tick ticks left -> right; repeats 3x every 4s */.success-circle {stroke-dasharray: 151;stroke-dashoffset: 151;animation: drawCircle 4s ease-in-out 3 forwards;}.success-check {stroke-dasharray: 32;stroke-dashoffset: 32;animation: drawCheck 4s ease-in-out 3 forwards;}@keyframes drawCircle {0% {stroke-dashoffset: 151;}25% {stroke-dashoffset: 0;}100% {stroke-dashoffset: 0;}}@keyframes drawCheck {0%, 25% {stroke-dashoffset: 32;}45% {stroke-dashoffset: 0;}100% {stroke-dashoffset: 0;}}.success-msg {margin: 0;font-size: 22px;font-weight: 700;color: #16a34a;}.success-msg-hi {margin: 6px 0 0;font-size: 16px;color: #4b5563;}/* ---------- Capture (combined location + photo) ---------- */.capture-help {color: #6b7280;font-size: 14px;margin: 0 0 16px;}/* "Take Store Photo" + "Close" controls row */.camera-controls {display: flex;gap: 10px;align-items: stretch;margin-bottom: 18px;}.btn-camera-open {flex: 1;display: flex;flex-direction: row;align-items: center;justify-content: center;gap: 9px;background: #ef5a68;color: #fff;border: none;border-radius: 12px;padding: 15px 18px;cursor: pointer;box-shadow: 0 2px 10px rgba(239, 90, 104, 0.3);}.btn-camera-open .sep {opacity: 0.5;font-weight: 400;}.btn-camera-close {display: inline-flex;align-items: center;justify-content: center;gap: 6px;background: #fff;color: #455a64;border: 1px solid #cfd6dd;border-radius: 12px;padding: 0 22px;font-size: 15px;font-weight: 600;cursor: pointer;white-space: nowrap;}.btn-camera-close .close-x {display: none;}/* mobile: collapse Close to a compact icon-only ✕ — placed AFTER thebase rules above so it wins the cascade on small screens */@media (max-width: 575px) {.btn-camera-close {padding: 0 14px;}.btn-camera-close .close-label {display: none;}.btn-camera-close .close-x {display: block;}}.btn-camera-close:hover {background: #f1f3f5;}.btn-camera-open:hover {filter: brightness(0.96);color: #fff;}.btn-camera-open .label-en {font-size: 15px;font-weight: 700;line-height: 1.2;}.btn-camera-open .label-hi {font-size: 14px;font-weight: 500;opacity: 0.95;}.camera-wrap {position: relative;background: #000;border-radius: 12px;overflow: hidden;aspect-ratio: 4 / 3;margin-bottom: 14px;}.camera-wrap video,.camera-wrap img {width: 100%;height: 100%;object-fit: cover;display: block;}.camera-wrap .cam-overlay {position: absolute;inset: 0;display: flex;align-items: center;justify-content: center;color: #fff;font-size: 13px;background: rgba(0, 0, 0, 0.55);text-align: center;padding: 16px;}.capture-row {display: flex;align-items: center;justify-content: center;gap: 16px;margin-bottom: 16px;}.btn-capture {background: #fff;color: #e1212a;border: 3px solid #e1212a;border-radius: 50%;width: 64px;height: 64px;display: inline-flex;align-items: center;justify-content: center;cursor: pointer;box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);}.btn-capture:disabled {opacity: 0.5;cursor: not-allowed;}.btn-capture .inner {width: 48px;height: 48px;border-radius: 50%;background: linear-gradient(135deg, #f7931e 0%, #e1212a 100%);}.btn-retake {background: transparent;border: 1px solid #b0bec5;color: #455a64;border-radius: 8px;padding: 9px 16px;cursor: pointer;font-size: 14px;}.capture-status {border-radius: 10px;padding: 12px 16px;font-size: 14px;margin-bottom: 18px;display: none;}.capture-status.ok {display: block;background: #e8f7ee;color: #16a34a;}.capture-status.err {display: block;background: #fce4ec;color: #c62828;}/* ---------- Buttons ---------- */.btn-primary-geo {background: #475569;color: #fff;border: none;border-radius: 10px;padding: 14px 24px;font-size: 16px;width: 100%;cursor: pointer;font-weight: 600;box-shadow: 0 2px 6px rgba(71, 85, 105, 0.20);}.btn-primary-geo:hover {background: #334155;color: #fff;}.btn-primary-geo:disabled {background: #b0bec5;box-shadow: none;cursor: not-allowed;}.btn-submit {background: #ef5a68;color: #fff;border: none;border-radius: 10px;padding: 15px 24px;font-size: 16px;width: 100%;cursor: pointer;font-weight: 700;box-shadow: 0 2px 10px rgba(239, 90, 104, 0.3);}.btn-submit:hover {filter: brightness(0.96);color: #fff;}.btn-submit:disabled {background: #f1a8b0;box-shadow: none;cursor: not-allowed;}.inline-err {background: #fce4ec;color: #c62828;border-radius: 8px;padding: 11px 14px;font-size: 14px;margin-bottom: 14px;display: none;}/* ---------- Consent ---------- */.consent-box {border: 1px solid #e3e6ea;background: #fafbfc;border-radius: 10px;padding: 16px 18px;margin-bottom: 22px;display: flex;gap: 12px;align-items: flex-start;}.consent-box input[type="checkbox"] {width: 18px;height: 18px;margin-top: 2px;flex-shrink: 0;cursor: pointer;accent-color: #e1212a;}.consent-box label {margin: 0;font-size: 13.5px;color: #4b5563;line-height: 1.5;cursor: pointer;}/* ---------- Spinner ---------- */.spinner {display: inline-block;width: 18px;height: 18px;border: 3px solid #fff;border-top-color: transparent;border-radius: 50%;animation: spin 0.8s linear infinite;vertical-align: middle;}@keyframes spin {to {transform: rotate(360deg);}}/* ---------- Footer ---------- */.footer-help {text-align: center;font-size: 14px;color: #4b5563;padding: 20px 16px 2px;}.footer-call {display: inline-flex;align-items: center;gap: 6px;color: #e1212a;font-weight: 700;text-decoration: none;margin-left: 6px;}.footer-call:hover {text-decoration: none;}.geo-footer {text-align: center;color: #9aa1ab;font-size: 13px;padding: 8px 16px 30px;line-height: 1.6;}</style></head><body><!-- ===== Top navbar ===== --><div class="top-nav"><a href="https://smartdukaan.com/" class="nav-brand"><img src="https://images.smartdukaan.com/uploads/campaigns/image2026-06-10/smartdukaanlogo_singleline_june20261781071724758.png" alt="SmartDukaan" class="brand-logo"></a><span class="nav-help"><span class="q-label">Any questions?</span><a href="tel:1800270273" class="nav-call"><span class="call-word">Call</span><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#e1212a" stroke-width="2"stroke-linecap="round" stroke-linejoin="round"><pathd="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92z"/></svg><span class="phone">1800 270 273</span></a></span></div><div class="subhead"><a href="https://smartdukaan.com/" class="btn-home"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"stroke-linecap="round" stroke-linejoin="round"><path d="M3 9.5L12 3l9 6.5"/><pathd="M5 10v10h14V10"/><path d="M9 20v-6h6v6"/></svg>Home</a></div>#if($leadName && $leadName.trim() != "")<p class="greeting">Greetings, <strong>$leadName</strong>!</p>#else<p class="greeting">Greetings!</p>#end<div class="geo-card"><div class="card-head"><h4>Store Verification Form</h4><p>Please provide your details for our Area Sales Manager to schedule a visit</p></div><div class="card-body-geo"><div class="step-indicator"><div class="step-dot current" id="dot1"></div><div class="step-dot" id="dot2"></div></div><div class="step-caption" id="stepCaption">Step 1 of 2</div><!-- ===== STEP 1: Mobile verification (stays on the page) ===== --><div class="step-section" id="step1Section"><div class="section-label"><span class="step-no">Step 1.</span> Verify Mobile Number</div><label class="field-label" for="mobileNumber">Mobile Number <span class="req">*</span></label><div class="mobile-row"><input type="tel" class="input-geo" id="mobileNumber" maxlength="10"placeholder="Enter 10-digit registered mobile number" autocomplete="off"><div class="verified-pill" id="mobileVerified"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"stroke-linecap="round" stroke-linejoin="round"><path d="M4 12L9 17L20 6"/></svg>Verified</div></div><div id="mobileError" class="inline-err mt-3"></div><button class="btn-primary-geo mt-3" id="btnVerifyMobile">Verify & Continue</button></div><!-- ===== STEP 2: Single combined capture — photo + auto location ===== --><div class="step-section" id="step2Section" style="display:none;"><hr class="step-divider"><div class="section-label"><span class="step-no">Step 2.</span> Capture Your Store Photo</div><p class="capture-help">Tap the button below to open your camera and take a live photo of your store front.Your location is recorded automatically with the photo.<span class="hindi">नीचे दिए गए बटन पर टैप करके कैमरा खोलें और अपनी दुकान के सामने की लाइव फोटो लें। आपकी लोकेशन फोटो के साथ अपने-आप रिकॉर्ड हो जाती है।</span></p><div class="camera-controls"><button type="button" class="btn-camera-open" id="btnOpenCamera"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"stroke-linecap="round" stroke-linejoin="round"><pathd="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circlecx="12" cy="13" r="4"/></svg><span class="label-en">Take a Photo</span><span class="sep">|</span><span class="label-hi">दुकान की फोटो लें</span></button><button type="button" class="btn-camera-close" id="btnCloseCamera" style="display:none;"aria-label="Close camera"><svg class="close-x" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6"y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg><span class="close-label">Close</span></button></div><div id="cameraStage" style="display:none;"><div class="camera-wrap" id="cameraWrap"><video id="cameraVideo" autoplay playsinline muted></video><img id="photoPreview" alt="Captured photo" style="display:none;"><div class="cam-overlay" id="cameraOverlay">Starting camera...</div></div><div class="capture-row"><button type="button" class="btn-capture" id="btnCapture" disabled><span class="inner"></span></button><button type="button" class="btn-retake" id="btnRetake" style="display:none;">Retake</button></div></div><div id="captureStatus" class="capture-status"></div><!-- Consent --><div class="consent-box"><input type="checkbox" id="consentCheck"><label for="consentCheck">I acknowledge that the information provided above is accurate and I consent to SmartDukaan'sArea Sales Manager visiting my store at the location specified. I understand that thisinformation will be used for onboarding purposes only.<span class="hindi">मैं स्वीकार करता/करती हूँ कि ऊपर दी गई जानकारी सही है, और मैं SmartDukaan के एरिया सेल्स मैनेजर को बताए गए स्थान पर मेरी दुकान पर आने की सहमति देता/देती हूँ। मुझे पता है कि इस जानकारी का उपयोग केवल ऑनबोर्डिंग के लिए किया जाएगा।</span></label></div><div id="submitError" class="inline-err"></div><input type="hidden" id="latitude" value=""><input type="hidden" id="longitude" value=""><input type="hidden" id="imageDocumentId" value="0"><button class="btn-submit" id="btnSubmit" disabled>Submit Details</button></div></div></div><div class="footer-help">Need help? Call<a href="tel:1800270273" class="footer-call"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"stroke-linecap="round" stroke-linejoin="round"><pathd="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92z"/></svg>1800 270 273</a></div><div class="geo-footer">© 2026 SmartDukaan. All rights reserved.<br>Transforming mobile retail across India</div><!-- Hidden canvas used to grab a still frame from the live video stream --><canvas id="captureCanvas" style="display:none;"></canvas><input type="hidden" id="leadId" value="$leadId"><script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script><script>var contextPath = "$rc.contextPath";var mediaStream = null; // live camera streamfunction markStepsAfterVerify() {$('#dot1').removeClass('current').addClass('done');$('#dot2').addClass('current');$('#stepCaption').text('Step 2 of 2');}// ===== STEP 1: Verify mobile against the lead record =====$('#btnVerifyMobile').click(function () {var mobile = $('#mobileNumber').val().trim();if (!mobile || mobile.length < 10) {$('#mobileError').text('Please enter a valid 10-digit mobile number').show();return;}var btn = $(this);btn.prop('disabled', true).html('<span class="spinner"></span> Verifying...');$('#mobileError').hide();$.ajax({url: contextPath + '/lead-geo/verify-mobile',method: 'POST',data: {leadId: $('#leadId').val(), mobileNumber: mobile},success: function (resp) {if (resp.response && resp.response.verified) {// Lock step 1, reveal step 2 on the same page$('#mobileNumber').prop('disabled', true).addClass('field-verified');btn.hide();$('#mobileVerified').addClass('show');markStepsAfterVerify();$('#step2Section').css('display', 'block').addClass('reveal-soft');} else {$('#mobileError').text('Verification failed. Please try again.').show();btn.prop('disabled', false).text('Verify & Continue');}},error: function (xhr) {var msg = 'Verification failed';try {msg = JSON.parse(xhr.responseText).message || msg;} catch (e) {}$('#mobileError').text(msg).show();btn.prop('disabled', false).text('Verify & Continue');}});});$('#mobileNumber').keypress(function (e) {if (e.which === 13) $('#btnVerifyMobile').click();});// Open the camera only when the user taps "Take Store Photo".// The button stays visible and a "Close" button appears so the user// stays in control of the camera.$('#btnOpenCamera').click(function () {$('#cameraStage').show();$('#btnCloseCamera').show();startCamera();});$('#btnCloseCamera').click(function () {stopCamera();$('#cameraStage').hide();$(this).hide();});// ===== STEP 2: Live camera — live capture only (no gallery picker). =====// Geolocation is grabbed silently at the instant the photo is captured,// so location and photo are a single combined action.function startCamera() {var overlay = $('#cameraOverlay').show().text('Starting camera...');$('#photoPreview').hide();$('#cameraVideo').show();if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {overlay.text('Your browser does not support live camera. Please open this link in Chrome/Safari on your phone.');return;}navigator.mediaDevices.getUserMedia({video: {facingMode: {ideal: 'environment'}}, // prefer rear cameraaudio: false}).then(function (stream) {mediaStream = stream;var video = document.getElementById('cameraVideo');video.srcObject = stream;video.onloadedmetadata = function () {overlay.hide();$('#btnCapture').prop('disabled', false);};}).catch(function (err) {var msg = 'Camera access denied. ';if (err && err.name === 'NotAllowedError') msg += 'Please allow camera permission and reload.';else if (err && err.name === 'NotFoundError') msg += 'No camera was found on this device.';else if (location.protocol !== 'https:' && location.hostname !== 'localhost') {msg = 'Live camera requires HTTPS. Please open this link over a secure connection.';}overlay.text(msg);});}function stopCamera() {if (mediaStream) {mediaStream.getTracks().forEach(function (t) {t.stop();});mediaStream = null;}}// Capture frame + silently grab geolocation (single combined action)$('#btnCapture').click(function () {var btn = $(this);btn.prop('disabled', true);$('#captureStatus').attr('class', 'capture-status ok').text('Capturing photo and your location...');var video = document.getElementById('cameraVideo');var canvas = document.getElementById('captureCanvas');canvas.width = video.videoWidth;canvas.height = video.videoHeight;canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);// Show still preview, hide live video, allow retakevar dataUrl = canvas.toDataURL('image/jpeg', 0.9);$('#photoPreview').attr('src', dataUrl).show();$('#cameraVideo').hide();$('#btnRetake').show();canvas.toBlob(function (blob) {if (!blob) {btn.prop('disabled', false);$('#captureStatus').attr('class', 'capture-status err').text('Could not capture photo. Try again.');return;}// Upload photo + grab geolocation in parallelvar uploadDone = uploadPhoto(blob);var geoDone = captureGeo();$.when(uploadDone, geoDone).done(function () {$('#captureStatus').attr('class', 'capture-status ok').html('✔ Store photo and location captured.');stopCamera();refreshSubmitState();}).fail(function (msg) {btn.prop('disabled', false);$('#captureStatus').attr('class', 'capture-status err').text(msg || 'Capture failed. Try again.');});}, 'image/jpeg', 0.9);});$('#btnRetake').click(function () {$('#photoPreview').hide();$('#cameraVideo').show();$(this).hide();$('#imageDocumentId').val('0');$('#latitude').val('');$('#longitude').val('');$('#captureStatus').attr('class', 'capture-status').hide();refreshSubmitState();if (!mediaStream) startCamera();else $('#btnCapture').prop('disabled', false);});function uploadPhoto(blob) {var d = $.Deferred();var formData = new FormData();formData.append('file', blob, 'store-photo.jpg');$.ajax({url: contextPath + '/lead-geo/upload-image',method: 'POST',data: formData,processData: false,contentType: false,success: function (resp) {if (resp.response && resp.response.document_id) {$('#imageDocumentId').val(resp.response.document_id);d.resolve();} else {d.reject('Upload failed.');}},error: function () {d.reject('Upload failed. Please try again.');}});return d.promise();}function captureGeo() {var d = $.Deferred();if (!navigator.geolocation) {d.reject('Geolocation not supported.');return d.promise();}navigator.geolocation.getCurrentPosition(function (pos) {$('#latitude').val(pos.coords.latitude);$('#longitude').val(pos.coords.longitude);d.resolve();},function (err) {var msg = 'Unable to get location. ';if (err.code === 1) msg += 'Please allow location permission.';else if (err.code === 2) msg += 'Location unavailable.';else if (err.code === 3) msg += 'Timed out. Try again.';d.reject(msg);},{enableHighAccuracy: true, timeout: 15000, maximumAge: 0});return d.promise();}// ===== Submit gating: photo + location + consent all required =====function refreshSubmitState() {var hasLocation = $('#latitude').val() !== '' && $('#longitude').val() !== '';var hasImage = $('#imageDocumentId').val() !== '0';var consented = $('#consentCheck').is(':checked');$('#btnSubmit').prop('disabled', !(hasLocation && hasImage && consented));}$('#consentCheck').change(refreshSubmitState);// ===== Submit =====$('#btnSubmit').click(function () {var btn = $(this);btn.prop('disabled', true).html('<span class="spinner"></span> Submitting...');$('#submitError').hide();$.ajax({url: contextPath + '/lead-geo/submit',method: 'POST',data: {leadId: $('#leadId').val(),mobileNumber: $('#mobileNumber').val().trim(),latitude: $('#latitude').val(),longitude: $('#longitude').val(),imageDocumentId: $('#imageDocumentId').val()},success: function (resp) {$('.greeting').remove();$('.geo-card').html('<div class="success-wrap">' +'<svg class="success-svg" width="120" height="120" viewBox="0 0 52 52" fill="none">' +'<circle class="success-circle" cx="26" cy="26" r="24" fill="none" stroke="#22c55e"' +' stroke-width="3" stroke-linecap="round" transform="rotate(-90 26 26)"></circle>' +'<path class="success-check" d="M16 27L23 34L37 19" fill="none" stroke="#22c55e" stroke-width="4"' +' stroke-linecap="round" stroke-linejoin="round"></path>' +'</svg>' +'<div>' +'<h4 class="success-msg">Thank you for verification</h4>' +'<p class="success-msg-hi">सत्यापन के लिए धन्यवाद</p>' +'</div>' +'</div>');stopCamera();},error: function () {btn.prop('disabled', false).text('Submit Details');$('#submitError').text('Submission failed. Please try again.').show();}});});</script></body></html>