Subversion Repositories SmartDukaan

Rev

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