Subversion Repositories SmartDukaan

Rev

Rev 36642 | Rev 36689 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
36642 ranu 1
<html>
2
<head>
3
    <meta charset="UTF-8">
4
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
5
    <title>Location Verification - SmartDukaan</title>
6
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
7
    <style>
8
        body {
9
            background: #f4f6f9;
36686 ranu 10
            font-family: 'Segoe UI', Roboto, sans-serif;
36642 ranu 11
        }
12
 
13
        .geo-card {
14
            max-width: 480px;
15
            margin: 30px auto;
16
            background: #fff;
36686 ranu 17
            border-radius: 14px;
18
            box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
36642 ranu 19
            overflow: hidden;
20
        }
21
 
22
        .geo-header {
36686 ranu 23
            background: linear-gradient(135deg, #f7931e 0%, #ed1c24 100%);
36642 ranu 24
            color: #fff;
36686 ranu 25
            padding: 22px 24px;
36642 ranu 26
            text-align: center;
27
        }
28
 
36686 ranu 29
        .geo-header .brand-row {
30
            display: flex;
31
            align-items: center;
32
            justify-content: center;
33
            gap: 10px;
34
            margin-bottom: 6px;
35
        }
36
 
37
        .geo-header .brand-mark {
38
            width: 36px;
39
            height: 36px;
40
            background: #fff;
41
            color: #ed1c24;
42
            border-radius: 8px;
43
            display: inline-flex;
44
            align-items: center;
45
            justify-content: center;
46
            font-weight: 800;
47
            font-size: 20px;
48
            letter-spacing: -1px;
49
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
50
        }
51
 
36642 ranu 52
        .geo-header h4 {
53
            margin: 0;
36686 ranu 54
            font-weight: 700;
55
            letter-spacing: 0.3px;
36642 ranu 56
        }
57
 
58
        .geo-header p {
59
            margin: 8px 0 0;
36686 ranu 60
            opacity: 0.95;
61
            font-size: 13px;
36642 ranu 62
        }
63
 
64
        .geo-body {
65
            padding: 24px;
66
        }
67
 
68
        .step {
69
            display: none;
70
        }
71
 
72
        .step.active {
73
            display: block;
74
        }
75
 
76
        .step-indicator {
77
            display: flex;
78
            justify-content: center;
79
            gap: 8px;
80
            margin-bottom: 20px;
81
        }
82
 
83
        .step-dot {
84
            width: 10px;
85
            height: 10px;
86
            border-radius: 50%;
87
            background: #ddd;
88
            transition: background 0.3s;
89
        }
90
 
91
        .step-dot.done {
92
            background: #4caf50;
93
        }
94
 
95
        .step-dot.current {
36686 ranu 96
            background: #ed1c24;
36642 ranu 97
        }
98
 
99
        .btn-geo {
36686 ranu 100
            background: linear-gradient(135deg, #f7931e 0%, #ed1c24 100%);
36642 ranu 101
            color: #fff;
102
            border: none;
103
            border-radius: 8px;
104
            padding: 12px 24px;
105
            font-size: 16px;
106
            width: 100%;
107
            cursor: pointer;
36686 ranu 108
            font-weight: 600;
109
            box-shadow: 0 2px 8px rgba(237, 28, 36, 0.25);
36642 ranu 110
        }
111
 
112
        .btn-geo:hover {
36686 ranu 113
            filter: brightness(0.95);
36642 ranu 114
            color: #fff;
115
        }
116
 
117
        .btn-geo:disabled {
118
            background: #b0bec5;
119
            cursor: not-allowed;
120
        }
121
 
122
        .loc-info {
123
            background: #e8f5e9;
124
            border-radius: 8px;
125
            padding: 12px;
126
            margin: 12px 0;
127
            font-size: 13px;
128
            color: #2e7d32;
129
        }
130
 
131
        .loc-info.error {
132
            background: #fce4ec;
133
            color: #c62828;
134
        }
135
 
136
        .upload-area {
137
            border: 2px dashed #b0bec5;
138
            border-radius: 8px;
139
            padding: 24px;
140
            text-align: center;
141
            cursor: pointer;
142
            transition: border-color 0.3s;
143
        }
144
 
145
        .upload-area:hover {
36686 ranu 146
            border-color: #ed1c24;
36642 ranu 147
        }
148
 
149
        .upload-area.uploaded {
150
            border-color: #4caf50;
151
            background: #e8f5e9;
152
        }
153
 
154
        .preview-img {
155
            max-width: 100%;
156
            max-height: 200px;
157
            border-radius: 8px;
158
            margin-top: 12px;
159
        }
160
 
161
        .spinner {
162
            display: inline-block;
163
            width: 20px;
164
            height: 20px;
165
            border: 3px solid #fff;
166
            border-top-color: transparent;
167
            border-radius: 50%;
168
            animation: spin 0.8s linear infinite;
169
        }
170
 
171
        @keyframes spin {
172
            to {
173
                transform: rotate(360deg);
174
            }
175
        }
176
 
177
        .form-control:focus {
36686 ranu 178
            border-color: #ed1c24;
179
            box-shadow: 0 0 0 0.2rem rgba(237, 28, 36, 0.20);
36642 ranu 180
        }
181
    </style>
182
</head>
183
<body>
184
 
185
<div class="geo-card">
186
    <div class="geo-header">
36686 ranu 187
        <div class="brand-row">
188
            <span class="brand-mark">S</span>
189
            <h4>SmartDukaan</h4>
190
        </div>
36642 ranu 191
        <p>Location Verification</p>
192
    </div>
193
    <div class="geo-body">
194
        <div class="step-indicator">
195
            <div class="step-dot current" id="dot1"></div>
196
            <div class="step-dot" id="dot2"></div>
197
            <div class="step-dot" id="dot3"></div>
198
        </div>
199
 
200
        <p class="text-center text-muted mb-3" style="font-size:14px;">
201
            Hello <strong>$!leadName</strong>, please verify your location.
202
        </p>
203
 
204
        <!-- STEP 1: Mobile Verification -->
205
        <div class="step active" id="step1">
206
            <h6 class="mb-3">Step 1: Verify Mobile Number</h6>
207
            <div class="form-group">
208
                <input type="tel" class="form-control" id="mobileNumber" maxlength="10"
209
                       placeholder="Enter your registered mobile number" autocomplete="off">
210
            </div>
211
            <div id="mobileError" class="loc-info error" style="display:none;"></div>
212
            <button class="btn btn-geo" id="btnVerifyMobile">
213
                Verify Mobile
214
            </button>
215
        </div>
216
 
217
        <!-- STEP 2: Capture Location -->
218
        <div class="step" id="step2">
219
            <h6 class="mb-3">Step 2: Capture Your Live Location</h6>
220
            <p class="text-muted" style="font-size:13px;">
221
                Please allow location access when prompted. Stand at your store/shop location.
222
            </p>
223
            <button class="btn btn-geo" id="btnCaptureLocation">
224
                Capture My Location
225
            </button>
226
            <div id="locationInfo" class="loc-info" style="display:none;"></div>
227
            <input type="hidden" id="latitude" value="">
228
            <input type="hidden" id="longitude" value="">
229
            <button class="btn btn-geo mt-3" id="btnNextToUpload" style="display:none;">
230
                Next: Upload Photo
231
            </button>
232
        </div>
233
 
234
        <!-- STEP 3: Upload Photo & Submit -->
235
        <div class="step" id="step3">
236
            <h6 class="mb-3">Step 3: Upload Store Photo</h6>
237
            <div class="upload-area" id="uploadArea" onclick="document.getElementById('photoInput').click();">
238
                <div id="uploadPlaceholder">
36686 ranu 239
                    <svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" viewBox="0 0 24 24" fill="none"
240
                         stroke="#ed1c24" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"
241
                         style="display:block; margin: 0 auto 8px;">
242
                        <path d="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"></path>
243
                        <circle cx="12" cy="13" r="4"></circle>
244
                    </svg>
36642 ranu 245
                    <p class="text-muted mb-0">Tap to capture or upload store photo</p>
246
                </div>
247
                <img id="photoPreview" class="preview-img" style="display:none;">
248
                <input type="file" id="photoInput" accept="image/*" capture="environment" style="display:none;">
249
            </div>
250
            <div id="uploadStatus" class="loc-info" style="display:none;"></div>
251
            <input type="hidden" id="imageDocumentId" value="0">
252
            <button class="btn btn-geo mt-3" id="btnSubmit" disabled>
253
                Submit Location
254
            </button>
255
        </div>
256
    </div>
257
</div>
258
 
259
<input type="hidden" id="leadId" value="$leadId">
260
 
261
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
262
<script>
263
    var contextPath = "$rc.contextPath";
264
 
265
    function showStep(num) {
266
        $('.step').removeClass('active');
267
        $('#step' + num).addClass('active');
268
        for (var i = 1; i <= 3; i++) {
269
            var dot = $('#dot' + i);
270
            dot.removeClass('current done');
271
            if (i < num) dot.addClass('done');
272
            else if (i === num) dot.addClass('current');
273
        }
274
    }
275
 
276
    // STEP 1: Verify Mobile
277
    $('#btnVerifyMobile').click(function () {
278
        var mobile = $('#mobileNumber').val().trim();
279
        if (!mobile || mobile.length < 10) {
280
            $('#mobileError').text('Please enter a valid 10-digit mobile number').show();
281
            return;
282
        }
283
        var btn = $(this);
284
        btn.prop('disabled', true).html('<span class="spinner"></span> Verifying...');
285
        $('#mobileError').hide();
286
 
287
        $.ajax({
288
            url: contextPath + '/lead-geo/verify-mobile',
289
            method: 'POST',
290
            data: {leadId: $('#leadId').val(), mobileNumber: mobile},
291
            success: function (resp) {
292
                if (resp.response && resp.response.verified) {
293
                    showStep(2);
294
                } else {
295
                    $('#mobileError').text('Verification failed. Please try again.').show();
296
                }
297
            },
298
            error: function (xhr) {
299
                var msg = 'Verification failed';
300
                try {
301
                    msg = JSON.parse(xhr.responseText).message || msg;
302
                } catch (e) {
303
                }
304
                $('#mobileError').text(msg).show();
305
            },
306
            complete: function () {
307
                btn.prop('disabled', false).text('Verify Mobile');
308
            }
309
        });
310
    });
311
 
312
    // STEP 2: Capture Location
313
    $('#btnCaptureLocation').click(function () {
314
        var btn = $(this);
315
        btn.prop('disabled', true).html('<span class="spinner"></span> Capturing...');
316
        $('#locationInfo').hide();
317
 
318
        if (!navigator.geolocation) {
319
            $('#locationInfo').addClass('error').text('Geolocation is not supported by your browser').show();
320
            btn.prop('disabled', false).text('Capture My Location');
321
            return;
322
        }
323
 
324
        navigator.geolocation.getCurrentPosition(
325
                function (position) {
326
                    var lat = position.coords.latitude;
327
                    var lng = position.coords.longitude;
328
                    var acc = position.coords.accuracy;
329
 
330
                    $('#latitude').val(lat);
331
                    $('#longitude').val(lng);
332
                    $('#locationInfo').removeClass('error')
333
                            .html('Location captured successfully!<br>Accuracy: ' + acc.toFixed(0) + ' meters')
334
                            .show();
335
                    btn.prop('disabled', false).text('Recapture Location');
336
                    $('#btnNextToUpload').show();
337
                },
338
                function (error) {
339
                    var msg = 'Unable to get location. ';
340
                    switch (error.code) {
341
                        case 1:
342
                            msg += 'Please allow location permission.';
343
                            break;
344
                        case 2:
345
                            msg += 'Location unavailable.';
346
                            break;
347
                        case 3:
348
                            msg += 'Request timed out. Try again.';
349
                            break;
350
                    }
351
                    $('#locationInfo').addClass('error').text(msg).show();
352
                    btn.prop('disabled', false).text('Capture My Location');
353
                },
354
                {enableHighAccuracy: true, timeout: 15000, maximumAge: 0}
355
        );
356
    });
357
 
358
    $('#btnNextToUpload').click(function () {
359
        showStep(3);
360
    });
361
 
362
    // STEP 3: Upload Photo
363
    $('#photoInput').change(function () {
364
        var file = this.files[0];
365
        if (!file) return;
366
 
367
        // Preview
368
        var reader = new FileReader();
369
        reader.onload = function (e) {
370
            $('#photoPreview').attr('src', e.target.result).show();
371
            $('#uploadPlaceholder').hide();
372
            $('#uploadArea').addClass('uploaded');
373
        };
374
        reader.readAsDataURL(file);
375
 
376
        // Upload
377
        $('#uploadStatus').removeClass('error').text('Uploading...').show();
378
        var formData = new FormData();
379
        formData.append('file', file);
380
 
381
        $.ajax({
382
            url: contextPath + '/lead-geo/upload-image',
383
            method: 'POST',
384
            data: formData,
385
            processData: false,
386
            contentType: false,
387
            success: function (resp) {
388
                if (resp.response && resp.response.document_id) {
389
                    $('#imageDocumentId').val(resp.response.document_id);
390
                    $('#uploadStatus').removeClass('error').text('Photo uploaded successfully!').show();
391
                    $('#btnSubmit').prop('disabled', false);
392
                }
393
            },
394
            error: function () {
395
                $('#uploadStatus').addClass('error').text('Upload failed. Please try again.').show();
396
            }
397
        });
398
    });
399
 
400
    // SUBMIT
401
    $('#btnSubmit').click(function () {
402
        var btn = $(this);
403
        btn.prop('disabled', true).html('<span class="spinner"></span> Submitting...');
404
 
405
        $.ajax({
406
            url: contextPath + '/lead-geo/submit',
407
            method: 'POST',
408
            data: {
409
                leadId: $('#leadId').val(),
410
                mobileNumber: $('#mobileNumber').val().trim(),
411
                latitude: $('#latitude').val(),
412
                longitude: $('#longitude').val(),
413
                imageDocumentId: $('#imageDocumentId').val()
414
            },
415
            success: function (resp) {
36686 ranu 416
                // Replace body with thank you (SVG check icon — no emoji to avoid charset issues)
36642 ranu 417
                $('.geo-body').html(
418
                        '<div class="text-center py-4">' +
36686 ranu 419
                        '<svg xmlns="http://www.w3.org/2000/svg" width="72" height="72" viewBox="0 0 24 24"' +
420
                        ' fill="none" stroke="#22c55e" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"' +
421
                        ' style="display:block; margin: 0 auto;">' +
422
                        '<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline>' +
423
                        '</svg>' +
36642 ranu 424
                        '<h5 class="mt-3">Thank You!</h5>' +
425
                        '<p class="text-muted">Your location has been submitted successfully.<br>Our team will review it shortly.</p>' +
426
                        '</div>'
427
                );
428
                $('.step-indicator').remove();
429
            },
430
            error: function () {
431
                btn.prop('disabled', false).text('Submit Location');
432
                alert('Submission failed. Please try again.');
433
            }
434
        });
435
    });
436
 
437
    // Allow Enter key on mobile input
438
    $('#mobileNumber').keypress(function (e) {
439
        if (e.which === 13) $('#btnVerifyMobile').click();
440
    });
441
</script>
442
</body>
443
</html>