Subversion Repositories SmartDukaan

Rev

Rev 36668 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
36657 ranu 1
<section class="wrapper">
2
    <div class="row">
3
        <div class="col-lg-12">
4
            <h3 class="page-header"><i class="icon_pin_alt"></i> Auth User Base Location</h3>
5
            <ol class="breadcrumb">
6
                <li><i class="fa fa-home"></i><a href="${rc.contextPath}/dashboard">Home</a></li>
7
                <li><i class="icon_group"></i> Partner Acquisition</li>
8
                <li><i class="icon_pin_alt"></i> Base Location</li>
9
            </ol>
10
        </div>
11
    </div>
12
 
13
    <div class="row" style="margin-bottom:10px;">
14
        <div class="col-lg-12" style="display:flex; gap:10px; align-items:center; flex-wrap:wrap;">
15
            <select id="blCategory" class="form-control input-sm" style="width:140px;">
16
                <option value="4">Sales</option>
17
                <option value="20">BGC</option>
18
            </select>
19
            <select id="blLevel" class="form-control input-sm" style="width:140px;">
20
                <option value="">Level</option>
21
                #foreach($e in $escalationTypes)
22
                    <option value="$e">$e</option>
23
                #end
24
            </select>
25
            <select id="blAuthUser" class="form-control input-sm" style="width:240px;">
26
                <option value="">Select User</option>
27
            </select>
28
            <span id="blCurrent" style="color:#777; font-size:12px; margin-left:8px;"></span>
29
        </div>
30
    </div>
31
 
32
    <div class="row">
33
        <div class="col-lg-12" style="margin-bottom:10px;">
34
            <input id="blSearch" type="text" class="form-control input-sm"
35
                   placeholder="Search a place..." style="width:60%; display:inline-block;"
36
                   autocomplete="off">
37
            <span style="font-size:11px; color:#888; margin-left:8px;">
38
                or click on the map to drop a pin
39
            </span>
40
        </div>
41
    </div>
42
 
43
    <div class="row">
36681 ranu 44
        <div class="col-lg-8">
36657 ranu 45
            <div id="blMap" style="width:100%; height:520px; border-radius:8px; background:#eee;"></div>
46
        </div>
36681 ranu 47
        <div class="col-lg-4">
48
            <div style="padding:10px; background:#f8f9fa; border-radius:6px; margin-bottom:12px;">
49
                <div style="font-weight:600; font-size:13px; margin-bottom:6px;">Add new base location</div>
36657 ranu 50
                <div style="font-size:12px; color:#555;">Selected:</div>
51
                <div id="blPicked" style="font-weight:600; margin-top:4px;">-</div>
52
                <div id="blPickedCoords" style="font-size:11px; color:#888; margin-top:4px;"></div>
36681 ranu 53
                <label style="display:block; margin-top:10px; font-size:12px; font-weight:normal;">
54
                    <input type="checkbox" id="blMakeDefault"> Mark as default location
55
                </label>
56
                <button id="blSave" class="btn btn-primary btn-sm" style="width:100%; margin-top:10px;" disabled>
57
                    Save Location
36657 ranu 58
                </button>
59
                <div id="blMsg" style="margin-top:10px; font-size:12px;"></div>
60
            </div>
36681 ranu 61
 
62
            <div style="background:#fff; border:1px solid #e5e5e5; border-radius:6px;">
63
                <div style="padding:8px 12px; font-weight:600; font-size:13px; border-bottom:1px solid #eee; background:#f5f5f5;">
64
                    Saved locations
65
                </div>
66
                <div id="blList" style="max-height:400px; overflow-y:auto;">
67
                    <div style="padding:14px; color:#999; font-size:12px; text-align:center;">
68
                        Select a user to see their base locations
69
                    </div>
70
                </div>
71
            </div>
36657 ranu 72
        </div>
73
    </div>
74
</section>
75
 
76
<script>
77
    function blEnsureMaps(cb) {
78
        if (typeof google !== 'undefined' && google.maps && google.maps.places) {
79
            cb();
80
            return;
81
        }
82
        var existing = document.getElementById('gmaps-api-loader');
83
        if (existing) {
84
            var t = setInterval(function () {
85
                if (typeof google !== 'undefined' && google.maps && google.maps.places) {
86
                    clearInterval(t);
87
                    cb();
88
                }
89
            }, 100);
90
            return;
91
        }
92
        var s = document.createElement('script');
93
        s.id = 'gmaps-api-loader';
94
        s.src = 'https://maps.googleapis.com/maps/api/js?key=AIzaSyAckO0y4Z6WhBOuMjNjioWLSYZDhGEvGBc&libraries=places&v=weekly';
95
        s.async = true;
96
        s.onload = function () {
97
            cb();
98
        };
99
        document.head.appendChild(s);
100
    }
101
 
102
    blEnsureMaps(function () {
36681 ranu 103
        var blMap, blAutocomplete;
104
        var blMarkers = {};  // id → google.maps.Marker for saved locations
105
        var pickMarker = null; // the draggable "new" pin
36657 ranu 106
        var picked = {lat: null, lng: null, name: '', address: ''};
107
 
36681 ranu 108
        function readServerMsg(xhr, fallback) {
109
            try {
110
                var err = JSON.parse(xhr.responseText);
111
                if (err && err.response) {
112
                    if (typeof err.response === 'string') return err.response;
113
                    if (err.response.message) return err.response.message;
114
                }
115
            } catch (e) {
116
            }
117
            return fallback || 'Request failed';
118
        }
119
 
36657 ranu 120
        function setPicked(lat, lng, name, address) {
121
            picked.lat = lat;
122
            picked.lng = lng;
123
            picked.name = name || '';
124
            picked.address = address || name || '';
125
            $('#blPicked').text(name || '(unnamed pin)');
126
            $('#blPickedCoords').text(lat.toFixed(6) + ', ' + lng.toFixed(6));
127
            $('#blSave').prop('disabled', !$('#blAuthUser').val());
128
        }
129
 
36681 ranu 130
        function placePickMarker(lat, lng) {
36657 ranu 131
            var pos = new google.maps.LatLng(lat, lng);
36681 ranu 132
            if (!pickMarker) {
133
                pickMarker = new google.maps.Marker({
134
                    map: blMap, position: pos, draggable: true,
135
                    icon: {
136
                        path: google.maps.SymbolPath.CIRCLE, scale: 10,
137
                        fillColor: '#3b82f6', fillOpacity: 0.95, strokeColor: '#fff', strokeWeight: 2
138
                    },
139
                    zIndex: 9999
140
                });
141
                pickMarker.addListener('dragend', function (e) {
36657 ranu 142
                    setPicked(e.latLng.lat(), e.latLng.lng(), picked.name, picked.address);
143
                });
144
            } else {
36681 ranu 145
                pickMarker.setPosition(pos);
36657 ranu 146
            }
147
            blMap.panTo(pos);
148
            if (blMap.getZoom() < 12) blMap.setZoom(14);
149
        }
150
 
36681 ranu 151
        function clearSavedMarkers() {
152
            Object.keys(blMarkers).forEach(function (id) {
153
                blMarkers[id].setMap(null);
154
            });
155
            blMarkers = {};
156
        }
157
 
158
        function addSavedMarker(loc) {
159
            var pos = new google.maps.LatLng(parseFloat(loc.latitude), parseFloat(loc.longitude));
160
            var m = new google.maps.Marker({
161
                map: blMap, position: pos,
162
                title: (loc.isDefault ? '[Default] ' : '') + (loc.locationName || ''),
163
                icon: {
164
                    path: google.maps.SymbolPath.CIRCLE, scale: 8,
165
                    fillColor: loc.isDefault ? '#16a34a' : '#94a3b8', fillOpacity: 0.95,
166
                    strokeColor: '#fff', strokeWeight: 2
167
                }
168
            });
169
            blMarkers[loc.id] = m;
170
        }
171
 
36657 ranu 172
        blMap = new google.maps.Map(document.getElementById('blMap'), {
173
            center: {lat: 22.0, lng: 79.0}, zoom: 5
174
        });
175
        blMap.addListener('click', function (e) {
36681 ranu 176
            placePickMarker(e.latLng.lat(), e.latLng.lng());
36657 ranu 177
            setPicked(e.latLng.lat(), e.latLng.lng(), 'Picked location', '');
178
        });
179
 
180
        blAutocomplete = new google.maps.places.Autocomplete(
181
                document.getElementById('blSearch'),
182
                {componentRestrictions: {country: 'in'}}
183
        );
184
        blAutocomplete.addListener('place_changed', function () {
185
            var p = blAutocomplete.getPlace();
186
            if (!p.geometry) return;
187
            var lat = p.geometry.location.lat(), lng = p.geometry.location.lng();
36681 ranu 188
            placePickMarker(lat, lng);
36657 ranu 189
            setPicked(lat, lng, p.name || p.formatted_address || '', p.formatted_address || '');
190
        });
191
 
192
        $('#blLevel').off('change.bl').on('change.bl', function () {
193
            var level = $(this).val();
194
            $('#blAuthUser').html('<option value="">Select User</option>');
195
            $('#blCurrent').text('');
196
            $('#blSave').prop('disabled', true);
36681 ranu 197
            renderList(null);
36657 ranu 198
            if (!level) return;
199
            $.ajax({
200
                url: context + '/beatPlan/getAuthUsers',
36681 ranu 201
                type: 'GET', dataType: 'json',
36657 ranu 202
                data: {categoryId: $('#blCategory').val(), escalationType: level},
203
                success: function (r) {
204
                    var data = r.response || r;
205
                    var h = '<option value="">Select User</option>';
206
                    if (data && data.length) {
207
                        data.forEach(function (u) {
208
                            h += '<option value="' + u.id + '">' + u.name + '</option>';
209
                        });
210
                    } else {
211
                        h = '<option value="">No users at this level</option>';
212
                    }
213
                    $('#blAuthUser').html(h);
214
                },
36681 ranu 215
                error: function () {
36657 ranu 216
                    $('#blAuthUser').html('<option value="">Error loading users</option>');
217
                }
218
            });
219
        });
220
 
221
        $('#blCategory').off('change.bl').on('change.bl', function () {
222
            $('#blLevel').val('').trigger('change.bl');
223
        });
224
 
225
        $('#blAuthUser').off('change.bl').on('change.bl', function () {
226
            var uid = $(this).val();
227
            $('#blCurrent').text('');
228
            $('#blSave').prop('disabled', true);
36681 ranu 229
            if (pickMarker) {
230
                pickMarker.setMap(null);
231
                pickMarker = null;
232
            }
233
            picked = {lat: null, lng: null, name: '', address: ''};
234
            $('#blPicked').text('-');
235
            $('#blPickedCoords').text('');
236
            $('#blMakeDefault').prop('checked', false);
237
            if (!uid) {
238
                renderList(null);
239
                return;
240
            }
241
            loadList(uid);
242
        });
243
 
244
        function loadList(uid) {
36657 ranu 245
            $.ajax({
36681 ranu 246
                url: context + '/beatPlan/listBaseLocations',
36657 ranu 247
                type: 'GET', dataType: 'json',
248
                data: {authUserId: uid},
249
                success: function (r) {
250
                    var data = r.response || r;
36681 ranu 251
                    renderList(data.locations || []);
252
                },
253
                error: function () {
254
                    renderList([]);
36657 ranu 255
                }
256
            });
36681 ranu 257
        }
36657 ranu 258
 
36681 ranu 259
        function renderList(locations) {
260
            clearSavedMarkers();
261
            if (locations === null) {
262
                $('#blList').html('<div style="padding:14px; color:#999; font-size:12px; text-align:center;">Select a user to see their base locations</div>');
263
                $('#blCurrent').text('');
264
                return;
265
            }
266
            if (locations.length === 0) {
267
                $('#blList').html('<div style="padding:14px; color:#999; font-size:12px; text-align:center;">No base locations yet. Pick on the map and Save.</div>');
268
                $('#blCurrent').html('<em>No base location set yet</em>');
269
                return;
270
            }
271
 
272
            var html = '';
273
            var defaultLoc = null;
274
            var bounds = new google.maps.LatLngBounds();
275
            locations.forEach(function (l) {
276
                addSavedMarker(l);
277
                bounds.extend(new google.maps.LatLng(parseFloat(l.latitude), parseFloat(l.longitude)));
278
                if (l.isDefault) defaultLoc = l;
279
 
280
                var safeName = (l.locationName || '').replace(/</g, '&lt;');
281
                var badge = l.isDefault
282
                        ? '<span style="display:inline-block;background:#16a34a;color:#fff;font-size:10px;padding:1px 6px;border-radius:3px;margin-left:4px;">DEFAULT</span>'
283
                        : '';
284
                var actions = l.isDefault
285
                        ? '<button class="btn btn-default btn-xs bl-remove-btn" disabled title="Default location cannot be removed">Remove</button>'
286
                        : '<button class="btn btn-success btn-xs bl-set-default-btn" data-id="' + l.id + '">Set Default</button> '
287
                        + '<button class="btn btn-danger btn-xs bl-remove-btn" data-id="' + l.id + '">Remove</button>';
288
 
289
                html += '<div style="padding:10px 12px; border-bottom:1px solid #f0f0f0;">'
290
                        + '<div style="font-weight:600; font-size:13px;">' + safeName + badge + '</div>'
291
                        + '<div style="font-size:11px; color:#888; margin-top:2px;">' + l.latitude + ', ' + l.longitude + '</div>'
292
                        + '<div style="margin-top:6px;">' + actions + '</div>'
293
                        + '</div>';
294
            });
295
            $('#blList').html(html);
296
 
297
            if (defaultLoc) {
298
                $('#blCurrent').html('Default: <strong>' + defaultLoc.locationName + '</strong> ('
299
                        + defaultLoc.latitude + ', ' + defaultLoc.longitude + ')');
300
            } else {
301
                $('#blCurrent').html('<em>No default set (legacy)</em>');
302
            }
303
 
304
            if (locations.length === 1) {
305
                blMap.panTo(new google.maps.LatLng(parseFloat(locations[0].latitude), parseFloat(locations[0].longitude)));
306
                if (blMap.getZoom() < 12) blMap.setZoom(13);
307
            } else {
308
                blMap.fitBounds(bounds);
309
            }
310
        }
311
 
36657 ranu 312
        $('#blSave').off('click.bl').on('click.bl', function () {
313
            var uid = $('#blAuthUser').val();
314
            if (!uid) {
315
                alert('Pick a user');
316
                return;
317
            }
318
            if (picked.lat == null) {
319
                alert('Pick a location on the map');
320
                return;
321
            }
322
            var btn = $(this);
323
            btn.prop('disabled', true).text('Saving...');
324
            $('#blMsg').text('');
325
 
326
            $.ajax({
327
                url: context + '/beatPlan/updateBaseLocation',
328
                type: 'POST',
329
                data: {
330
                    authUserId: uid,
331
                    locationName: picked.name || ('Location ' + picked.lat.toFixed(4) + ',' + picked.lng.toFixed(4)),
332
                    latitude: String(picked.lat),
333
                    longitude: String(picked.lng),
36681 ranu 334
                    address: picked.address,
335
                    isDefault: $('#blMakeDefault').is(':checked')
36657 ranu 336
                },
337
                success: function (r) {
338
                    var d = r.response || r;
36681 ranu 339
                    $('#blMsg').html('<span style="color:#2e7d32;">' + (d.message || 'Saved.') + '</span>');
340
                    btn.prop('disabled', false).text('Save Location');
341
                    if (pickMarker) {
342
                        pickMarker.setMap(null);
343
                        pickMarker = null;
344
                    }
345
                    picked = {lat: null, lng: null, name: '', address: ''};
346
                    $('#blPicked').text('-');
347
                    $('#blPickedCoords').text('');
348
                    $('#blMakeDefault').prop('checked', false);
349
                    loadList(uid);
36657 ranu 350
                },
351
                error: function (xhr) {
36681 ranu 352
                    var msg = readServerMsg(xhr, 'Save failed');
353
                    if (xhr.status === 403 || xhr.status === 401) msg += ' (HTTP ' + xhr.status + ')';
36657 ranu 354
                    $('#blMsg').html('<span style="color:#c62828;">' + msg + '</span>');
36681 ranu 355
                    btn.prop('disabled', false).text('Save Location');
36657 ranu 356
                }
357
            });
358
        });
36681 ranu 359
 
360
        $(document).off('click.blset').on('click.blset', '.bl-set-default-btn', function () {
361
            var id = $(this).data('id');
362
            var uid = $('#blAuthUser').val();
363
            if (!confirm('Set this location as the default base location?')) return;
364
            $.ajax({
365
                url: context + '/beatPlan/setDefaultBaseLocation',
366
                type: 'POST',
367
                data: {id: id},
368
                success: function () {
369
                    loadList(uid);
370
                },
371
                error: function (xhr) {
372
                    alert(readServerMsg(xhr, 'Could not set default'));
373
                }
374
            });
375
        });
376
 
377
        $(document).off('click.blrm').on('click.blrm', '.bl-remove-btn', function () {
378
            if ($(this).prop('disabled')) return;
379
            var id = $(this).data('id');
380
            var uid = $('#blAuthUser').val();
381
            if (!confirm('Remove this base location? This cannot be undone.')) return;
382
            $.ajax({
383
                url: context + '/beatPlan/deleteBaseLocation',
384
                type: 'POST',
385
                data: {id: id},
386
                success: function () {
387
                    loadList(uid);
388
                },
389
                error: function (xhr) {
390
                    alert(readServerMsg(xhr, 'Could not remove'));
391
                }
392
            });
393
        });
36657 ranu 394
    });
395
</script>