Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
35548 aman 1
$(function () {
2
    $(document).on('click', ".lead", function () {
3
        loadLead("main-content");
4
    });
29598 tejbeer 5
 
35548 aman 6
    $(document).on('click', ".team-commitment", function () {
7
        loadTeamCommitment("main-content");
8
    });
30439 tejbeer 9
 
10
 
35548 aman 11
    $(document).on('click', ".partner-health", function () {
12
        loadPartnerHealth("main-content");
13
    });
29598 tejbeer 14
 
35548 aman 15
    $(document).on('click', ".lead-detail", function () {
16
        loadLeadDetail("main-content");
17
    });
30439 tejbeer 18
 
31370 tejbeer 19
 
35548 aman 20
    $(document).on('click', ".submitCommitment",
21
        function () {
22
            var startDateTime = getDatesFromPicker('input[name="commitmentDate"]').startDate;
23
            doGetAjaxRequestHandler(context + "/getTeamCommitment?date="
24
                + startDateTime, function (response) {
25
                $('.teamcommitmentcontainer').html(response);
31370 tejbeer 26
 
35548 aman 27
            });
28
        });
30439 tejbeer 29
 
30
 
35548 aman 31
    $(document).on('click', ".submitDateWiseLead", function () {
30439 tejbeer 32
 
35769 amit 33
        var startDate = $("#startDate").val();
34
        var endDate = $("#endDate").val();
35548 aman 35
        var status = $("#statusFilter").val();
36
        var color = $("#colorFilter").val();
31370 tejbeer 37
 
35548 aman 38
        if (color == null) {
39
            color = "";
40
        }
31370 tejbeer 41
 
35769 amit 42
        if (startDate && endDate) {
43
            var start = new Date(startDate);
44
            var end = new Date(endDate);
45
            if (end < start) {
46
                alert("End date must be after start date");
47
                return;
48
            }
49
        }
31370 tejbeer 50
 
35769 amit 51
        doGetAjaxRequestHandler(context + "/getOpenLead?leadStatus=" + status + "&color=" + color + "&startDate=" + startDate + "&endDate=" + endDate, function (response) {
35548 aman 52
            $('#' + 'main-content').html(response);
53
        });
29598 tejbeer 54
 
55
 
35548 aman 56
    })
57
    ;$(document).on('click', ".downloadDateWiseLead", function () {
29598 tejbeer 58
 
35769 amit 59
        var startDate = $("#startDate").val();
60
        var endDate = $("#endDate").val();
35548 aman 61
        var status = $("#statusFilter").val();
62
        var color = $("#colorFilter").val();
29598 tejbeer 63
 
35548 aman 64
        if (color == null) {
65
            color = "";
66
        }
29598 tejbeer 67
 
35769 amit 68
        if (startDate && endDate) {
69
            var start = new Date(startDate);
70
            var end = new Date(endDate);
71
            if (end < start) {
72
                alert("End date must be after start date");
73
                return;
74
            }
75
        }
76
 
77
        let endPoint = `${context}/downloadDateWiseLead?leadStatus=${status}&color=${color}&startDate=${startDate}&endDate=${endDate}`;
35548 aman 78
        window.location.href = endPoint;
31249 tejbeer 79
 
35548 aman 80
    });
34650 aman.kumar 81
 
37021 aman 82
    // Lead-table Search box = GLOBAL partner search: matches ANY lead by name / mobile / outlet /
83
    // city across ALL statuses and ALL dates (this year, last year, anytime) - not just the loaded
84
    // date-scoped rows. It searches AS YOU TYPE (debounced) so old partners surface without needing
85
    // to press Enter; Enter still triggers an immediate search. Results render into
86
    // #global-search-results above the date-scoped table.
87
    var leadGlobalSearchTimer = null;
88
 
89
    function runGlobalLeadSearch(term) {
90
        term = $.trim(term || "");
91
        if (term.length < 2) {
92
            $('#global-search-results').html("");
93
            return;
94
        }
95
        var safeTerm = $('<div>').text(term).html();
96
        doGetAjaxRequestHandler(context + "/globalLeadSearch?searchTerm=" + encodeURIComponent(term),
97
            function (response) {
98
                $('#global-search-results').html(
99
                    '<h4 style="margin:15px 0 8px;">Search results — all partners, any date '
100
                    + '<small class="text-muted">(matching "' + safeTerm + '")</small></h4>' + response);
101
            });
102
    }
103
 
36984 aman 104
    $(document).on('keydown', "#lead-table_filter input", function (e) {
105
        if (e.which === 13) {
106
            e.preventDefault();
37021 aman 107
            clearTimeout(leadGlobalSearchTimer);
108
            runGlobalLeadSearch($(this).val());
36984 aman 109
        }
110
    });
34650 aman.kumar 111
 
36984 aman 112
    $(document).on('input', "#lead-table_filter input", function () {
37021 aman 113
        var term = $(this).val();
114
        clearTimeout(leadGlobalSearchTimer);
115
        leadGlobalSearchTimer = setTimeout(function () {
116
            runGlobalLeadSearch(term);
117
        }, 350);
36984 aman 118
    });
119
 
120
 
35548 aman 121
    $(document).on('click', ".visit-request-plan", function () {
34650 aman.kumar 122
 
35548 aman 123
        doGetAjaxRequestHandler(context + "/visitPlan", function (response) {
124
            $('#' + 'main-content').html(response);
125
        });
34650 aman.kumar 126
 
35548 aman 127
    });
34650 aman.kumar 128
 
35548 aman 129
    $(document).on('click', ".visitPlan", function () {
25980 tejbeer 130
 
35548 aman 131
        let dateWisePlan = $("#dateVisitSearch").val();
31249 tejbeer 132
 
35548 aman 133
        doGetAjaxRequestHandler(context + "/visit/getVisitPlan?date=" + dateWisePlan, function (response) {
134
            $('#' + 'main-content').html(response);
135
        });
31249 tejbeer 136
 
35548 aman 137
    });
31249 tejbeer 138
 
35548 aman 139
    $(document).on('click', ".lead-close", function () {
140
        loadClosedLead("main-content");
141
    });
31249 tejbeer 142
 
35548 aman 143
    $(document).on('click', "#lead-close-paginated .next",
144
        function () {
31249 tejbeer 145
 
35548 aman 146
            var searchText = $("#authUser").val();
147
            // var searchTxt=$("#scheme-search-text").val();
148
            console.log(searchText);
149
            if (typeof (searchText) == "undefined" || !searchText) {
150
                searchText = "";
151
            }
31249 tejbeer 152
 
35548 aman 153
            if ((searchText)) {
154
                var params = {};
155
                params['searchTerm'] = searchText;
156
                loadPaginatedNextItems('/searchLeadPaginated', params,
157
                    'lead-close-paginated', 'close-lead-table',
158
                    'lead-close-container');
159
            } else {
31249 tejbeer 160
 
35548 aman 161
                loadPaginatedNextItems('/getPaginatedClosedLeads', null,
162
                    'lead-close-paginated', 'close-lead-table',
163
                    'lead-close-container');
164
            }
165
            $(this).blur();
166
        });
31249 tejbeer 167
 
35548 aman 168
    $(document).on('click', "#lead-close-paginated .previous",
169
        function () {
170
            var searchText = $("#authUser").val();
171
            // var searchTxt=$("#scheme-search-text").val();
172
            console.log(searchText);
173
            if (typeof (searchText) == "undefined" || !searchText) {
174
                searchText = "";
175
            }
25988 tejbeer 176
 
35548 aman 177
            if ((searchText)) {
178
                var params = {};
179
                params['searchTerm'] = searchText;
180
                loadPaginatedPreviousItems('/searchLeadPaginated', params,
181
                    'lead-close-paginated', 'close-lead-table',
182
                    'lead-close-container');
183
            } else {
184
                loadPaginatedPreviousItems('/getPaginatedClosedLeads',
185
                    null, 'lead-close-paginated', 'close-lead-table',
186
                    'lead-close-container');
187
            }
188
            $(this).blur();
189
        });
25988 tejbeer 190
 
35548 aman 191
    $(document).on('click', "#close-lead-search-button", function () {
192
        var searchText = $("#authUser").val();
193
        if (typeof (searchText) == "undefined" || !searchText) {
194
            searchText = "";
195
        }
196
        loadLeadSearchInfo(searchText);
197
    });
25988 tejbeer 198
 
35548 aman 199
    $(document).on("keyup", "#authUser", function (e) {
200
        var keyCode = e.keyCode || e.which;
201
        if (keyCode == 13) {
202
            $("#close-lead-search-button").click();
203
        }
204
    });
205
    $(document).on('click', ".view",
206
        function () {
207
            var id = $(this).data('requestid');
208
            console.log(id);
209
            doGetAjaxRequestHandler(context + "/getLeadActivity?leadId="
210
                + id, function (response) {
25988 tejbeer 211
 
35548 aman 212
                console.log(response)
25988 tejbeer 213
 
35548 aman 214
                $('#fetchLeadActivityData .modal-content').html(response);
25988 tejbeer 215
 
35548 aman 216
            });
217
        });
25988 tejbeer 218
 
35548 aman 219
    $(document).on('click', ".newLead", function () {
220
        $('#newEntryLeadModal').modal('show');
221
        $("#scheduleTime").hide();
222
    });
25988 tejbeer 223
 
35548 aman 224
    $(document).on('click', ".show-lead", function () {
225
        var status = $("#statusFilter").val();
226
        doGetAjaxRequestHandler(context + "/getOpenLead?leadStatus=" + status, function (response) {
227
            $('#' + 'main-content').html(response);
228
        });
229
    });
25980 tejbeer 230
 
31370 tejbeer 231
 
35548 aman 232
    $(document).on('click', ".show-colowise-lead", function () {
233
        var status = $("#statusFilter").val();
234
        var color = $("#colorFilter").val();
235
        doGetAjaxRequestHandler(context + "/getOpenLead?leadStatus=" + status + "&color=" + color, function (response) {
236
            $('#' + 'main-content').html(response);
237
        });
238
    });
25980 tejbeer 239
 
35548 aman 240
    $(document).on('click', "#uploadIvoryLead", function () {
25980 tejbeer 241
 
35548 aman 242
        window.location.href = context + "/downloadIvoryLead";
243
    });
25980 tejbeer 244
 
35548 aman 245
    $(document).on('click', ".submitLeadGenerate", function () {
27609 tejbeer 246
 
35548 aman 247
        console.log("hello");
248
        if (confirm('Confirm upload ?')) {
249
            var fileSelector = $(this)[0];
250
            if (fileSelector != undefined) {
251
                var url = `${context}/csvFileAndSetLead`;
252
                console.log(url);
253
                var file = $(".fileLeadGenerate")[0].files[0];
254
                let fileInput = $(this);
255
                console.log("file" + file);
256
                console.log("fileInput" + fileInput);
257
                doAjaxUploadRequestHandler(
258
                    url,
259
                    'POST',
260
                    file, function (response) {
27642 tejbeer 261
 
35548 aman 262
                        console.log("reponse" + response);
31370 tejbeer 263
 
35548 aman 264
                        if (response == true) {
265
                            alert("successfully uploaded");
31370 tejbeer 266
 
267
 
35548 aman 268
                        }
269
                    });
29598 tejbeer 270
 
35548 aman 271
            }
272
        } else {
273
            // Do nothing!
274
        }
275
    });
27642 tejbeer 276
 
277
 
35548 aman 278
    $(document).on('click', ".lead-request",
279
        function () {
29598 tejbeer 280
 
35548 aman 281
            var firstName = $('input[name="firstName"]').val();
282
            var lastName = $('input[name="lastName"]').val();
283
            var mobile = $('input[name="mobile"]').val();
284
            var address = $('input[name="address"]').val();
285
            var status = $("#status").val();
286
            var city = $('input[name="city"]').val();
287
            var state = $("#state").val();
288
            var remark = $("#createRemark").val();
289
            var assignTo = $("#createAssignTo").val();
290
            var source = $("#leadSource").val();
291
            var communicationType = $("#communicationTye").val();
29427 manish 292
 
35548 aman 293
            var conversionprobability = $("#conversionprobabilit").val();
29598 tejbeer 294
 
295
 
35548 aman 296
            var outletName = $('input[name="leadoutletName"]').val();
297
            var counterSize = $('input[name="leadcounterSize"]').val();
298
            var table = document.getElementById('brandtable');
299
            var brandValueJson = [];
300
            var leadBrands;
29598 tejbeer 301
 
35548 aman 302
            console.log(conversionprobability)
29598 tejbeer 303
 
304
 
35548 aman 305
            if (firstName === "" && lastName === "" && mobile === ""
306
                && address === "" && status === "" && city === ""
307
                && state === "" && remark === "" && source === "") {
308
                alert("Field can't be empty");
309
                return;
310
            }
29598 tejbeer 311
 
25980 tejbeer 312
 
35548 aman 313
            if (firstName === "") {
314
                alert("First Name is required");
315
                return;
316
            }
317
            if (lastName === "") {
318
                alert("Last Name is required");
319
                return;
320
            }
321
            if (mobile === "") {
322
                alert("Mobile is required");
323
                return;
324
            }
325
            if (status === "") {
326
                alert("Status is required");
327
                return;
328
            }
329
            if (address === "") {
330
                alert("address is required");
331
                return;
332
            }
333
            if (city === "") {
334
                alert("city is required");
335
                return;
336
            }
32471 tejbeer 337
 
35548 aman 338
            if (state === "") {
339
                alert("state is required");
340
                return;
341
            }
342
            if (source === "") {
343
                alert("Source is required")
344
                return;
345
            }
32471 tejbeer 346
 
35548 aman 347
            if (remark === "") {
348
                alert("Remark is required");
349
                return;
350
            }
32471 tejbeer 351
 
35548 aman 352
            if (conversionprobability === "") {
353
                alert("Conversion Probability is required");
354
                return;
355
            }
356
            if (status == "followUp" || status == "pending" || status == "finalized") {
357
                if (outletName === "") {
358
                    alert("Outlet Name is required");
359
                    return;
360
                }
25980 tejbeer 361
 
35548 aman 362
                if (counterSize === "") {
363
                    alert("Counter Size is required");
364
                    return;
365
                }
32464 tejbeer 366
 
35548 aman 367
                if (localStorage.getItem("frontph") == "undefined" && localStorage.getItem("frontph") == null) {
368
                    alert("Front Document is required");
369
                    return;
370
                }
32464 tejbeer 371
 
35548 aman 372
                if (localStorage.getItem("internalMarketh") == "undefined" || localStorage.getItem("internalMarketh") == null) {
373
                    alert("Front With Market Document is required");
374
                    return;
375
                }
25980 tejbeer 376
 
35548 aman 377
                if (localStorage.getItem("leftShoth") == "undefined" || localStorage.getItem("leftShoth") == null) {
378
                    alert("Internal Left Shot Document is required");
379
                    return;
380
                }
32464 tejbeer 381
 
35548 aman 382
                if (localStorage.getItem("leftWallh") == "undefined" || localStorage.getItem("leftWallh") == null) {
383
                    alert("Internal Left Wall Document is required");
384
                    return;
385
                }
25980 tejbeer 386
 
387
 
35548 aman 388
                if (localStorage.getItem("rightWallh") == "undefined" || localStorage.getItem("rightWallh") == null) {
389
                    alert("Internal Right Wall Document is required");
390
                    return;
391
                }
25980 tejbeer 392
 
32464 tejbeer 393
 
35548 aman 394
                for (i = 1; i < table.rows.length; i++) {
32464 tejbeer 395
 
35548 aman 396
                    var objCells = table.rows[i].cells;
32464 tejbeer 397
 
35548 aman 398
                    leadBrands = {
399
                        brand: objCells[0].innerText,
400
                        value: objCells[1].getElementsByTagName('input')[0].value
401
                    }
402
                    brandValueJson.push(leadBrands);
403
                }
32464 tejbeer 404
 
405
 
35548 aman 406
            }
32464 tejbeer 407
 
408
 
35548 aman 409
            var leaddetailData = {}
410
            leaddetailData['firstName'] = firstName;
411
            leaddetailData['lastName'] = lastName
412
            leaddetailData['mobile'] = mobile
413
            leaddetailData['address'] = address
414
            leaddetailData['city'] = city
415
            leaddetailData['state'] = state
416
            leaddetailData['status'] = status
417
            leaddetailData['remark'] = remark
418
            leaddetailData['assignTo'] = assignTo
419
            leaddetailData['source'] = source
420
            leaddetailData['colorCheck'] = conversionprobability
32464 tejbeer 421
 
422
 
35548 aman 423
            if (status == "followUp") {
424
                leaddetailData['schelduleTimestamp'] = getDatesFromPicker('#scheduleTime').startDate;
32464 tejbeer 425
 
35548 aman 426
                leaddetailData['communicationType'] = communicationType
427
            }
32464 tejbeer 428
 
429
 
35548 aman 430
            leaddetailData['outletName'] = outletName;
32464 tejbeer 431
 
35548 aman 432
            leaddetailData['counterSize'] = counterSize;
32464 tejbeer 433
 
434
 
35548 aman 435
            leaddetailData['leadBrands'] = brandValueJson;
32464 tejbeer 436
 
35548 aman 437
            console.log(localStorage.getItem("frontp"));
32464 tejbeer 438
 
439
 
35548 aman 440
            leaddetailData['frontp'] = localStorage
441
                .getItem("frontph");
31249 tejbeer 442
 
32464 tejbeer 443
 
35548 aman 444
            leaddetailData['frontWithMarket'] = localStorage
445
                .getItem("internalMarketh");
32464 tejbeer 446
 
447
 
35548 aman 448
            leaddetailData['internalLongShot'] = localStorage
449
                .getItem("leftShoth");
32464 tejbeer 450
 
451
 
35548 aman 452
            leaddetailData['internalLeftWall'] = localStorage
453
                .getItem("leftWallh");
32464 tejbeer 454
 
455
 
35548 aman 456
            leaddetailData['internalRightWall'] = localStorage
457
                .getItem("rightWallh");
32464 tejbeer 458
 
35548 aman 459
            console.log(leaddetailData);
32464 tejbeer 460
 
35548 aman 461
            if (confirm("Are you sure you want to add lead!") == true) {
462
                doPostAjaxRequestWithJsonHandler(context + "/createLead",
463
                    JSON.stringify(leaddetailData), function (response) {
464
                        if (response == 'true') {
465
                            alert("successfully Add");
466
                            $('#newEntryLeadModal').modal('hide');
467
                            $('.modal-backdrop').remove();
468
                            loadLead("main-content");
469
                        } else {
470
                            alert(response);
471
                        }
472
                    });
32464 tejbeer 473
 
35548 aman 474
                return false;
475
            }
476
        });
36642 ranu 477
    window.leadId = null;
35548 aman 478
    var row = null;
37003 ranu 479
    // Turn Assign To into a search-select. We attempt initialisation at 3 points to be
480
    // robust against ordering / DOM-timing issues:
481
    //   1. Immediately at load time (element is in DOM per lead.vm)
482
    //   2. On the modal's shown.bs.modal event (post-transition)
483
    //   3. As a fallback in the click handler with a small delay
484
    function initAssignToSelect2() {
485
        if (!$.fn.select2) {
486
            console.warn('[lead.js] select2 not loaded — falling back to native <select>');
487
            return;
488
        }
489
        var $assign = $('#assignTo');
490
        if ($assign.length === 0) return;
491
        if ($assign.hasClass('select2-hidden-accessible')) return; // already applied
492
        $assign.select2({
493
            placeholder: 'Assign To',
494
            allowClear: true,
495
            width: '100%',
496
            dropdownParent: $('#editLeadData'),
497
            // Hide disabled options — VISIT/TELEPHONIC filter uses .prop('disabled', true).
498
            matcher: function (params, data) {
499
                if (data.element && $(data.element).prop('disabled')) return null;
500
                if (!params.term || $.trim(params.term) === '') return data;
501
                if (data.text && data.text.toLowerCase().indexOf(params.term.toLowerCase()) > -1) return data;
502
                return null;
503
            }
504
        });
505
        console.log('[lead.js] select2 applied to #assignTo');
506
    }
507
 
508
    initAssignToSelect2();
509
    $(document).on('shown.bs.modal', '#editLeadData', initAssignToSelect2);
510
 
35548 aman 511
    $(document).on('click', ".editLead", function () {
512
        $('#editLeadData').modal('show');
37003 ranu 513
        // Belt-and-braces: also try after the modal transition completes.
514
        setTimeout(initAssignToSelect2, 300);
32464 tejbeer 515
 
35548 aman 516
        $("#remark").val("");
37003 ranu 517
        $("#assignTo").val("").trigger('change');
35548 aman 518
        $("#editStatus").val("");
519
        $("#reason").val("");
520
        $("#editCity").val("");
521
        $("#editState").val("");
35769 amit 522
        $("#editSource").val("");
35548 aman 523
        $("#editScheduleTime").hide();
32464 tejbeer 524
 
525
 
35548 aman 526
        localStorage.removeItem("frontph");
527
        localStorage.removeItem("leftShoth");
528
        localStorage.removeItem("rightWallh");
529
        localStorage.removeItem("leftWallh");
530
        localStorage.removeItem("internalMarketh");
32464 tejbeer 531
 
35548 aman 532
        row = $(this).closest("tr");
533
        leadId = $(this).data('leadid');
32464 tejbeer 534
 
35548 aman 535
        doAjaxRequestHandler(
536
            context + "/getLeadDetailByLeadId?leadId=" + leadId,
537
            "GET",
538
            function (response) {
32464 tejbeer 539
 
35548 aman 540
                var data = response.response;
541
                if (!data) return;
542
                console.log(data);
543
                $("#editCity").val(data.city);
544
                $("#editState").val(data.state);
545
                $("input[name='outletName']").val(data.outletName);
546
                $("input[name='counterSize']").val(data.counterSize);
547
            }
548
        );
549
    });
32464 tejbeer 550
 
551
 
35548 aman 552
    $(document).on('click', ".lead-edit-request",
553
        function () {
32464 tejbeer 554
 
36761 ranu 555
            // Gate the assign/status submit on approved geo. Modal stays open so the
556
            // user can still work the other sub-forms (lead detail, etc.).
557
            var clickedBtn = $(this);
36789 ranu 558
            // notInterested is a close-out — no geo / no beat / no assignee
559
            // needed. Skip the geo gate and submit straight through with just
560
            // the activity (status + reason + remark).
561
            var currentStatus = $('#editStatus').val();
562
            if (currentStatus === 'notInterested') {
563
                submitLeadEdit();
564
                return;
565
            }
36792 ranu 566
            // Non-sales assignees (BGC / other internal hand-offs) don't need
567
            // geo or a beat-day — the lead just routes to their queue. Skip the
568
            // geo gate and submit straight through, same as the legacy flow.
569
            var assigneeId = parseInt($('#assignTo').val(), 10);
570
            var isSalesAssignee = !isNaN(assigneeId)
571
                && typeof salesUserIds !== 'undefined'
572
                && salesUserIds.indexOf(assigneeId) !== -1;
573
            if (!isSalesAssignee) {
574
                submitLeadEdit();
575
                return;
576
            }
36761 ranu 577
            if (clickedBtn.data('geoChecking')) return;
578
            clickedBtn.data('geoChecking', true);
579
            doAjaxRequestHandler(
580
                context + "/lead-geo/check/" + leadId,
581
                "GET",
582
                function (response) {
583
                    clickedBtn.removeData('geoChecking');
584
                    var hasGeo = response && response.response && response.response.hasApprovedGeo;
585
                    if (!hasGeo) {
586
                        alert('Live geo-location for this lead has not been approved yet. Please approve the geo-location before assigning / updating status.');
587
                        return;
588
                    }
589
                    submitLeadEdit();
590
                }
591
            );
592
        });
25980 tejbeer 593
 
36761 ranu 594
    function submitLeadEdit() {
595
 
35548 aman 596
            console.log(row);
597
            var remark = $('input[name="remark"]').val();
598
            var assignTo = $("#assignTo").val();
599
            var editStatus = $("#editStatus").val();
600
            var city = $('input[name="editCity"]').val();
601
            var state = $("#editState").val();
602
            var reason = $("#reason").val();
25980 tejbeer 603
 
35769 amit 604
            var startDate = $("#startDate").val();
605
            var endDate = $("#endDate").val();
35548 aman 606
            var leadStatus = $("#statusFilter").val();
607
            var color = $("#colorFilter").val();
608
            var communicationType = $("#communicationType").val();
29640 tejbeer 609
 
35548 aman 610
            var conversionprobability = $("#conversionprobability").val();
35769 amit 611
            var editSource = $("#editSource").val();
29640 tejbeer 612
 
35548 aman 613
            console.log(conversionprobability)
29640 tejbeer 614
 
31473 tejbeer 615
 
35769 amit 616
            console.log(startDate)
35548 aman 617
            console.log(leadStatus)
31370 tejbeer 618
 
35548 aman 619
            console.log(color)
620
            console.log(reason)
31370 tejbeer 621
 
35548 aman 622
            if (remark === "" && assignTo === "" && editStatus === "") {
623
                alert("All fields is required");
624
                return;
625
            }
31370 tejbeer 626
 
36789 ranu 627
        // For notInterested (close-out) the lead doesn't need an assignee
628
        // — it's just a status + reason + remark write. Only enforce
629
        // assignTo for the other statuses where scheduling matters.
630
        if (assignTo === "" && editStatus !== "notInterested") {
35548 aman 631
                alert("assignTo is required");
632
                return;
633
            }
31409 tejbeer 634
 
35548 aman 635
            if (remark === "") {
636
                alert("Remark is required");
637
                return;
638
            }
31370 tejbeer 639
 
640
 
35548 aman 641
            if (editStatus === "") {
642
                alert("status is required");
643
                return;
644
            }
31370 tejbeer 645
 
35548 aman 646
            if (editStatus === "notInterested") {
36789 ranu 647
                if (reason == null || reason === "") {
35548 aman 648
                    alert("Reason  is required");
649
                    return;
650
                }
651
            }
652
            var leadActivityData = {}
653
            leadActivityData['id'] = leadId;
654
            leadActivityData['remark'] = remark;
655
            leadActivityData['assignTo'] = assignTo
656
            leadActivityData['status'] = editStatus
657
            leadActivityData['reason'] = reason
36741 ranu 658
            leadActivityData['colorCheck'] = (conversionprobability === "true" || conversionprobability === true)
35548 aman 659
            if (city && city.trim() !== "") {
660
                leadActivityData.city = city;
661
            }
25980 tejbeer 662
 
35548 aman 663
            if (state && state.trim() !== "") {
664
                leadActivityData.state = state;
665
            }
29473 manish 666
 
35769 amit 667
            if (editSource && editSource.trim() !== "") {
668
                leadActivityData.source = editSource;
669
            }
29598 tejbeer 670
 
35769 amit 671
 
35548 aman 672
            if (editStatus == "followUp") {
36642 ranu 673
                leadActivityData['communicationType'] = communicationType
36792 ranu 674
                var assigneeIdForBeat = parseInt(assignTo, 10);
675
                var isSalesAssigneeForBeat = !isNaN(assigneeIdForBeat)
676
                    && typeof salesUserIds !== 'undefined'
677
                    && salesUserIds.indexOf(assigneeIdForBeat) !== -1;
36741 ranu 678
                var beatVal = $('#beatDate').val();
36792 ranu 679
                // Beat-day gate only applies to sales assignees. Non-sales
680
                // (BGC / other) hand-offs are just routed to the user's queue
681
                // without a beat attachment — same as the legacy flow.
682
                if (isSalesAssigneeForBeat) {
683
                    if (!beatVal) {
684
                        var hasBadges = $('#beatBadges .beat-badge').length > 0;
685
                        if (!hasBadges) {
686
                            alert('No upcoming beat is available for this assignee. Cannot schedule the lead until they have a beat.');
687
                        } else {
688
                            alert('Please select a beat date for the assignee before submitting.');
689
                        }
690
                        return;
36761 ranu 691
                    }
36792 ranu 692
                    var beatDate = beatVal.split('|')[0];
693
                    leadActivityData['scheldule'] = beatDate + 'T12:00:00';
694
                    leadActivityData['beatSelection'] = beatVal;
36642 ranu 695
                }
35548 aman 696
            }
29598 tejbeer 697
 
35548 aman 698
            console.log(leadActivityData);
699
            if (confirm("Are you sure you want to add lead!") == true) {
700
                doPostAjaxRequestWithJsonHandler(context + "/editLead", JSON.stringify(leadActivityData), function (response) {
701
                    console.log(response);
702
                    $('#editLeadData').modal('hide');
703
                    $('.modal-backdrop').remove();
704
                    row.html(response);
705
                });
706
            }
29598 tejbeer 707
 
36761 ranu 708
    }
32477 tejbeer 709
 
710
 
35548 aman 711
    $(document).on('click', ".show-partner-health",
712
        function () {
29598 tejbeer 713
 
35548 aman 714
            var email = $("#authUserFilter").val();
25980 tejbeer 715
 
35548 aman 716
            console.log(email)
717
            doGetAjaxRequestHandler(context + "/partnerHealth?email="
718
                + email, function (response) {
719
                console.log(response)
720
                $('#' + 'main-content').html(response);
25980 tejbeer 721
 
35548 aman 722
            });
723
        });
25980 tejbeer 724
 
725
 
35548 aman 726
    $(document).on('click', ".lead-detail-entry",
727
        function () {
28200 tejbeer 728
 
35548 aman 729
            console.log("hello");
730
            var outletName = $('input[name="outletName"]').val();
731
            var counterSize = $('input[name="counterSize"]').val();
732
            var table = document.getElementById('editbrandtable');
733
            var brandValueJson = [];
734
            var leadBrands;
25980 tejbeer 735
 
35548 aman 736
            if (outletName === "") {
737
                alert("Outlet Name is required");
738
                return;
739
            }
29598 tejbeer 740
 
35548 aman 741
            if (counterSize === "") {
742
                alert("Counter Size is required");
743
                return;
744
            }
32471 tejbeer 745
 
35548 aman 746
            if (localStorage.getItem("frontph") == "undefined" && localStorage.getItem("frontph") == null) {
747
                alert("Front Document is required");
748
                return;
749
            }
31249 tejbeer 750
 
35548 aman 751
            if (localStorage.getItem("internalMarketh") == "undefined" || localStorage.getItem("internalMarketh") == null) {
752
                alert("Front With Market Document is required");
753
                return;
754
            }
25980 tejbeer 755
 
35548 aman 756
            if (localStorage.getItem("leftShoth") == "undefined" || localStorage.getItem("leftShoth") == null) {
757
                alert("Internal Left Shot Document is required");
758
                return;
759
            }
27605 tejbeer 760
 
35548 aman 761
            if (localStorage.getItem("leftWallh") == "undefined" || localStorage.getItem("leftWallh") == null) {
762
                alert("Internal Left Wall Document is required");
763
                return;
764
            }
27605 tejbeer 765
 
30185 tejbeer 766
 
35548 aman 767
            if (localStorage.getItem("rightWallh") == "undefined" || localStorage.getItem("rightWallh") == null) {
768
                alert("Internal Right Wall Document is required");
769
                return;
770
            }
30185 tejbeer 771
 
772
 
35548 aman 773
            for (i = 1; i < table.rows.length; i++) {
30185 tejbeer 774
 
35548 aman 775
                var objCells = table.rows[i].cells;
30185 tejbeer 776
 
35548 aman 777
                leadBrands = {
778
                    brand: objCells[0].innerText,
779
                    value: objCells[1].getElementsByTagName('input')[0].value
780
                }
781
                brandValueJson.push(leadBrands);
782
            }
30185 tejbeer 783
 
30416 tejbeer 784
 
35548 aman 785
            var leadDetailObject = {};
31402 tejbeer 786
 
35548 aman 787
            leadDetailObject['leadId'] = leadId;
30416 tejbeer 788
 
789
 
35548 aman 790
            leadDetailObject['outletName'] = outletName;
31370 tejbeer 791
 
35548 aman 792
            leadDetailObject['counterSize'] = counterSize;
31370 tejbeer 793
 
35548 aman 794
            leadDetailObject['leadBrands'] = brandValueJson;
31370 tejbeer 795
 
31402 tejbeer 796
 
35548 aman 797
            console.log(localStorage.getItem("frontp"));
31402 tejbeer 798
 
799
 
35548 aman 800
            leadDetailObject['frontp'] = localStorage
801
                .getItem("frontph");
31402 tejbeer 802
 
803
 
35548 aman 804
            leadDetailObject['frontWithMarket'] = localStorage
805
                .getItem("internalMarketh");
31370 tejbeer 806
 
807
 
35548 aman 808
            leadDetailObject['internalLongShot'] = localStorage
809
                .getItem("leftShoth");
31370 tejbeer 810
 
811
 
35548 aman 812
            leadDetailObject['internalLeftWall'] = localStorage
813
                .getItem("leftWallh");
31370 tejbeer 814
 
815
 
35548 aman 816
            leadDetailObject['internalRightWall'] = localStorage
817
                .getItem("rightWallh");
31370 tejbeer 818
 
35548 aman 819
            console.log(leadDetailObject);
31370 tejbeer 820
 
35548 aman 821
            if (confirm("Are you sure you want to add lead detail!") == true) {
822
                doPostAjaxRequestWithJsonHandler(context + "/leadDetail", JSON.stringify(leadDetailObject), function (response) {
823
                    console.log(response);
824
                    if (response == 'true') {
825
                        alert("Submit Successfully");
826
                    }
31370 tejbeer 827
 
35548 aman 828
                });
829
            }
31370 tejbeer 830
 
35548 aman 831
        });
31370 tejbeer 832
 
833
 
35548 aman 834
    $(document).on('change', '.frontp',
835
        function () {
31370 tejbeer 836
 
35548 aman 837
            if (confirm('Document has been selected, Do you want to upload ?')) {
31370 tejbeer 838
 
35548 aman 839
                var documentId = uploadImage(this, "frontph");
31370 tejbeer 840
 
841
 
35548 aman 842
            } else {
31370 tejbeer 843
 
35548 aman 844
            }
845
        });
31456 tejbeer 846
 
35548 aman 847
    $(document).on('change', '.internalMarket',
848
        function () {
31456 tejbeer 849
 
35548 aman 850
            if (confirm('Document has been selected, Do you want to upload ?')) {
31456 tejbeer 851
 
35548 aman 852
                var documentId = uploadImage(this, "internalMarketh");
31456 tejbeer 853
 
35548 aman 854
            } else {
31456 tejbeer 855
 
35548 aman 856
            }
857
        });
31370 tejbeer 858
 
35548 aman 859
    $(document).on('change', '.leftShot',
31370 tejbeer 860
 
35548 aman 861
        function () {
862
            if (confirm('Document has been selected, Do you want to upload ?')) {
863
                var documentId = uploadImage(this, "leftShoth");
864
            } else {
31370 tejbeer 865
 
35548 aman 866
            }
867
        });
31370 tejbeer 868
 
35548 aman 869
    $(document).on('change', '.leftWall',
870
        function () {
871
            if (confirm('Document has been selected, Do you want to upload ?')) {
872
                var documentId = uploadImage(this, "leftWallh");
873
            } else {
31370 tejbeer 874
 
35548 aman 875
            }
876
        });
31370 tejbeer 877
 
35548 aman 878
    $(document).on('change', '.rightWall',
879
        function () {
880
            if (confirm('Document has been selected, Do you want to upload ?')) {
881
                var documentId = uploadImage(this, "rightWallh");
882
            } else {
883
            }
884
        });
31370 tejbeer 885
 
886
 
25980 tejbeer 887
});
888
 
31404 tejbeer 889
function uploadImage(fileSelector, attrName) {
35548 aman 890
    var documentId;
891
    if (fileSelector != undefined
892
        && fileSelector.files[0] != undefined) {
893
        var url = context
894
            + '/document-upload';
31370 tejbeer 895
 
35548 aman 896
        console.log(url);
897
        var file = fileSelector.files[0];
31370 tejbeer 898
 
35548 aman 899
        console.log(file)
900
        doAjaxUploadRequestHandler(
901
            url,
902
            'POST',
903
            file,
904
            function (response) {
905
                console.log(response)
906
                documentId = response.response.document_id;
907
                console
908
                    .log("documentId : "
909
                        + documentId);
31370 tejbeer 910
 
911
 
35548 aman 912
                localStorage
913
                    .setItem(
914
                        attrName,
915
                        documentId);
31402 tejbeer 916
 
35548 aman 917
            });
918
        return documentId;
919
    }
31370 tejbeer 920
 
921
}
922
 
923
 
25980 tejbeer 924
function loadLead(domId) {
35548 aman 925
    doGetAjaxRequestHandler(context + "/getOpenLead", function (response) {
926
        $('#' + domId).html(response);
927
    });
25980 tejbeer 928
}
929
 
25988 tejbeer 930
function loadClosedLead(domId, searchTerm) {
35548 aman 931
    doGetAjaxRequestHandler(context + "/getClosedLead", function (response) {
932
        $('#' + domId).html(response);
933
    })
25988 tejbeer 934
}
935
 
25980 tejbeer 936
function statusAction() {
35548 aman 937
    var val = $('#status').val();
938
    if (val == "followUp") {
939
        $("#scheduleTime").show();
940
    } else {
941
        $("#scheduleTime").hide();
942
    }
25980 tejbeer 943
 
944
}
27605 tejbeer 945
 
946
 
947
function editStatusAction() {
35548 aman 948
    var val = $('#editStatus').val();
949
    if (val == "followUp") {
36642 ranu 950
        // Show communication type and schedule date
951
        $("#communicationTypeSection").show();
35548 aman 952
        $("#editScheduleTime").show();
36642 ranu 953
        $("#beatDateSelection").hide();
954
 
36761 ranu 955
        // Reset communication type only; preserve the assignee the user picked.
36642 ranu 956
        $('#communicationType').val('');
37003 ranu 957
        $('#assignTo option').prop('disabled', false);
36642 ranu 958
 
959
        // Check if lead has approved geolocation to decide VISIT option
960
        doAjaxRequestHandler(context + "/lead-geo/check/" + leadId, "GET", function (response) {
961
            var hasGeo = response.response.hasApprovedGeo;
962
            var commDropdown = $('#communicationType');
963
            commDropdown.empty();
964
            commDropdown.append('<option value="" disabled selected>Communication Type</option>');
965
            commDropdown.append('<option value="TELEPHONIC">TELEPHONIC</option>');
966
            if (hasGeo) {
967
                commDropdown.append('<option value="VISIT">VISIT</option>');
968
            }
969
        });
35548 aman 970
    } else {
36642 ranu 971
        $("#communicationTypeSection").hide();
35548 aman 972
        $("#editScheduleTime").hide();
36642 ranu 973
        $("#beatDateSelection").hide();
37003 ranu 974
        $('#assignTo option').prop('disabled', false);
35548 aman 975
    }
27605 tejbeer 976
 
977
}
978
 
25988 tejbeer 979
function loadLeadSearchInfo(search_text) {
35548 aman 980
    loadSearchLead("main-content", search_text);
25988 tejbeer 981
}
982
 
30185 tejbeer 983
function loadTeamCommitment(domId) {
35548 aman 984
    doGetAjaxRequestHandler(context + "/teamCommitment",
985
        function (response) {
986
            $('#' + domId).html(response);
987
        });
30185 tejbeer 988
}
989
 
31370 tejbeer 990
function loadLeadDetail(domId) {
35548 aman 991
    doGetAjaxRequestHandler(context + "/getLeadDetail",
992
        function (response) {
993
            $('#' + domId).html(response);
994
        });
31370 tejbeer 995
}
996
 
30416 tejbeer 997
function loadPartnerHealth(domId) {
35548 aman 998
    doGetAjaxRequestHandler(context + "/partnerHealth",
999
        function (response) {
1000
            $('#' + domId).html(response);
1001
        });
30416 tejbeer 1002
}
1003
 
25988 tejbeer 1004
function loadSearchLead(domId, search_text) {
35548 aman 1005
    doGetAjaxRequestHandler(context + "/searchLeads?searchTerm=" + search_text,
1006
        function (response) {
1007
            $('#' + domId).html(response);
1008
        });
25988 tejbeer 1009
}
33917 ranu 1010
 
1011
$(document).on('click', ".arr-button-mk",
35548 aman 1012
    function () {
1013
        var startDate = $('.arr-start_date').val();
1014
        doGetAjaxRequestHandler(context + "/rbmTodayArr?startDate=" + startDate, function (response) {
1015
            $('#main-content').html(response);
33917 ranu 1016
 
35548 aman 1017
        });
1018
    });
33917 ranu 1019
 
1020
$(document).on('click', ".rbm-today-arr",
35548 aman 1021
    function () {
1022
        doGetAjaxRequestHandler(context + "/rbmTodayArr", function (response) {
1023
            $('#main-content').html(response);
33917 ranu 1024
 
35548 aman 1025
        });
1026
    });
1027
$(document).on('click', '.reassign', function () {
1028
    $('#bulkReassignFile').val(null);
1029
    $('#bulkReassignFile').click();
1030
});
1031
 
1032
$(document).on('change', '#bulkReassignFile', function () {
1033
 
1034
    if (!confirm("Confirm bulk reassign upload?")) {
1035
        return;
1036
    }
1037
 
1038
    var file = this.files[0];
1039
    if (!file) {
1040
        alert("No file selected");
1041
        return;
1042
    }
1043
 
1044
    doAjaxUploadRequestHandler(
1045
        context + "/upload-assign-id",
1046
        'POST',
1047
        file,
1048
        function (response) {
1049
            alert("Bulk reassignment completed");
1050
            loadLead("main-content");
1051
        }
1052
    );
1053
});
1054
 
36642 ranu 1055
// ==================== GEO LOCATION HANDLERS ====================
1056
 
1057
// Communication type change: filter assignTo based on type
1058
$(document).on('change', '#communicationType', function () {
1059
    var val = $(this).val();
1060
    var assignDropdown = $('#assignTo');
1061
 
36741 ranu 1062
    // Reset beat + restore manual date input
36642 ranu 1063
    $('#beatDate').val('');
1064
    $('#beatBadges').empty();
1065
    $("#beatDateSelection").hide();
36741 ranu 1066
    $("#editScheduleTime").show();
36642 ranu 1067
 
1068
    if (val == 'VISIT') {
37003 ranu 1069
        // Filter assignTo to sales users only (no BGC). Uses .prop('disabled', ...)
1070
        // instead of .hide()/.show() because select2 doesn't respect hidden <option>s
1071
        // in its dropdown UI. Disabled options are filtered out by our matcher above.
36642 ranu 1072
        if (typeof salesUserIds !== 'undefined') {
1073
            assignDropdown.find('option').each(function () {
1074
                var optVal = parseInt($(this).val());
1075
                if (optVal && salesUserIds.indexOf(optVal) === -1) {
37003 ranu 1076
                    $(this).prop('disabled', true);
36642 ranu 1077
                } else {
37003 ranu 1078
                    $(this).prop('disabled', false);
36642 ranu 1079
                }
1080
            });
1081
        }
1082
    } else {
37003 ranu 1083
        // TELEPHONIC — enable all users
1084
        assignDropdown.find('option').prop('disabled', false);
36642 ranu 1085
    }
37003 ranu 1086
    // Nudge select2 to re-render its dropdown with the new enabled/disabled state.
1087
    if ($.fn.select2 && assignDropdown.hasClass('select2-hidden-accessible')) {
1088
        assignDropdown.trigger('change.select2');
1089
    }
36741 ranu 1090
    // Both VISIT and TELEPHONIC offer beat-day slots when an assignee is set
1091
    // (TELEPHONIC just uses the beat date as the call slot; backend won't
1092
    // attach a LeadRoute for it). Non-sales assignees simply get an empty list.
1093
    if (val && assignDropdown.val()) {
1094
        fetchBeatDates();
1095
    }
36642 ranu 1096
});
1097
 
36741 ranu 1098
// Fetch beats when assignTo changes (works for both VISIT and TELEPHONIC)
1099
$(document).on('change', '#assignTo', function () {
36642 ranu 1100
    var commType = $('#communicationType').val();
1101
    var salesAuthId = $('#assignTo').val();
36741 ranu 1102
    if (commType && salesAuthId && leadId) {
36642 ranu 1103
        fetchBeatDates();
36741 ranu 1104
    } else if (!commType) {
36642 ranu 1105
        $("#beatDateSelection").hide();
1106
    }
1107
});
1108
 
1109
function fetchBeatDates() {
1110
    var salesAuthId = $('#assignTo').val();
1111
    if (!salesAuthId || !leadId) return;
1112
 
36792 ranu 1113
    // Beat slots only make sense for sales assignees. BGC / other internal
1114
    // hand-offs skip the entire beat panel (and the visit-request CTA that
1115
    // sits inside it). Mirrors the server-side carve-out in /editLead.
1116
    var assigneeIntId = parseInt(salesAuthId, 10);
1117
    var isSalesAssigneeFetch = !isNaN(assigneeIntId)
1118
        && typeof salesUserIds !== 'undefined'
1119
        && salesUserIds.indexOf(assigneeIntId) !== -1;
1120
    if (!isSalesAssigneeFetch) {
1121
        $('#beatBadges').empty();
1122
        $('#beatDate').val('');
1123
        $('#beatDateSelection').hide();
1124
        return;
1125
    }
1126
 
36642 ranu 1127
    var badgesDiv = $('#beatBadges');
1128
    badgesDiv.html('<span style="color:#999; font-size:12px;">Loading beats...</span>');
1129
    $("#beatDateSelection").show();
1130
    $('#beatDate').val('');
1131
 
1132
    var url = context + "/lead-geo/beat-dates?leadId=" + leadId + "&salesAuthId=" + salesAuthId;
1133
 
1134
    $.ajax({
1135
        url: url,
1136
        method: 'GET',
1137
        success: function (response) {
1138
            var data = response.response || response;
1139
            badgesDiv.empty();
36644 ranu 1140
 
36741 ranu 1141
            // Stores within radius of the lead — show count + top 3 inline.
1142
            var radius = (data && data.radiusKm) ? data.radiusKm : 30;
1143
            var stores = (data && data.nearestStores) || [];
1144
            if (stores.length > 0) {
1145
                var preview = stores.slice(0, 3).map(function (s) {
1146
                    return '<strong>' + s.code + ' - ' + s.name + '</strong> (' + s.distanceKm + ' km)';
1147
                }).join(', ');
1148
                var more = stores.length > 3 ? ' +' + (stores.length - 3) + ' more' : '';
36644 ranu 1149
                badgesDiv.append('<div style="font-size:12px; color:#333; margin-bottom:6px;">' +
36741 ranu 1150
                    stores.length + ' partner store(s) within ' + radius + ' km of this lead: ' +
1151
                    preview + more + '</div>');
36644 ranu 1152
            }
1153
 
36741 ranu 1154
            // All upcoming beat-dates for the assignee that touch any nearby store.
36642 ranu 1155
            if (data && data.beats && data.beats.length > 0) {
36644 ranu 1156
                badgesDiv.append('<div style="font-weight:bold; font-size:11px; color:#666; margin-bottom:4px;">Available Slots (near this lead):</div>');
36741 ranu 1157
                var beats = data.beats;
36642 ranu 1158
                for (var i = 0; i < beats.length; i++) {
1159
                    var beat = beats[i];
36644 ranu 1160
                    var nearTxt = beat.nearStore ? ' &middot; near ' + beat.nearStore : '';
36642 ranu 1161
                    var badge = $('<span class="beat-badge" style="' +
1162
                        'display:inline-block; background:#337ab7; color:#fff; padding:6px 12px; ' +
1163
                        'margin:4px 6px 4px 0; border-radius:16px; cursor:pointer; font-size:12px; ' +
1164
                        'border:2px solid #337ab7; transition:all 0.2s;">' +
36644 ranu 1165
                        beat.planDate + ' &middot; ' + beat.beatName + ' (' + beat.stops + ' stops)' + nearTxt +
36642 ranu 1166
                        '</span>');
1167
                    badge.data('value', beat.planDate + '|' + beat.beatName + '|' + beat.planGroupId);
1168
                    badgesDiv.append(badge);
1169
                }
1170
            } else {
36787 ranu 1171
                // No beat-days available for this assignee. Surface a CTA so the
1172
                // user can fire a visit request to the assignee's hierarchy instead
1173
                // of being stuck. The pre-existing 'beats > 0' branch above is
1174
                // untouched — this only fires for the empty-beats case.
1175
                var nearestId = (stores.length > 0 && stores[0].storeId) ? stores[0].storeId : '';
1176
                badgesDiv.append(
1177
                    '<div style="background:#fff8e1; border:1px solid #f0e0a0; border-radius:6px; padding:8px 10px; margin-top:4px;">'
1178
                    + '<div style="font-size:12px; color:#7c5a00; margin-bottom:6px;">'
1179
                    + 'No upcoming beat is available for this assignee.'
1180
                    + '</div>'
1181
                    + '<div style="display:flex; gap:8px; align-items:center;">'
1182
                    + '<label style="font-size:11px; color:#666; margin:0;">Preferred date (optional):</label>'
1183
                    + '<input type="date" id="vrPreferredDate" class="input-sm" style="font-size:12px; padding:3px 6px;">'
1184
                    + '<button type="button" id="vrSendBtn" class="btn btn-warning btn-sm" '
1185
                    + 'data-nearest="' + nearestId + '" style="font-size:12px;">Send Visit Request</button>'
1186
                    + '</div>'
1187
                    + '<div style="font-size:11px; color:#888; margin-top:6px;">'
1188
                    + 'The request goes to the assignee\'s reporting head (and up). Once they approve and pick a beat-day, the lead lands on that beat.'
1189
                    + '</div>'
1190
                    + '</div>');
36642 ranu 1191
            }
1192
        },
1193
        error: function () {
1194
            badgesDiv.html('<span style="color:#d9534f; font-size:12px;">Error loading beats</span>');
1195
        }
1196
    });
1197
}
1198
 
36787 ranu 1199
// Send Visit Request when no beats are available for the chosen assignee.
1200
// Posts to /visitRequest/create. Existing beat-pick + Submit flow is unchanged.
1201
$(document).on('click', '#vrSendBtn', function () {
1202
    var $btn = $(this);
1203
    var assigneeAuthId = parseInt($('#assignTo').val());
1204
    var commType = $('#communicationType').val() || null;
1205
    var nearestStoreId = parseInt($btn.data('nearest'));
1206
    var preferred = $('#vrPreferredDate').val() || null;
1207
    if (!leadId || !assigneeAuthId) {
1208
        alert('Pick an assignee first.');
1209
        return;
1210
    }
1211
    $btn.prop('disabled', true).text('Sending...');
1212
    var payload = {
1213
        leadId: leadId,
1214
        assigneeAuthId: assigneeAuthId,
1215
        communicationType: commType,
1216
        reason: 'No upcoming beats for assignee'
1217
    };
1218
    if (!isNaN(nearestStoreId) && nearestStoreId > 0) payload.nearestStoreId = nearestStoreId;
1219
    if (preferred) payload.requestedDate = preferred;
1220
 
1221
    doPostAjaxRequestWithJsonHandler(context + '/visitRequest/create', JSON.stringify(payload),
1222
        function (response) {
1223
            $btn.prop('disabled', false).text('Send Visit Request');
1224
            var data = (response && response.response) || response || {};
1225
            if (data && data.id) {
1226
                alert('Visit request sent. The assignee\'s manager has been notified.');
1227
                $('#editLeadData').modal('hide');
1228
                $('.modal-backdrop').remove();
1229
            } else {
1230
                var msg = (data && data.message) || (data && data.error) || 'Could not send request.';
1231
                alert(msg);
1232
            }
1233
        });
1234
});
1235
 
36741 ranu 1236
// Click on beat badge to select it. A picked beat becomes the schedule
1237
// source — the manual date input is hidden (not needed when scheduling by beat).
36642 ranu 1238
$(document).on('click', '.beat-badge', function () {
1239
    $('.beat-badge').css({'background': '#337ab7', 'border-color': '#337ab7'});
1240
    $(this).css({'background': '#1a5276', 'border-color': '#f39c12', 'border-width': '2px'});
1241
    $('#beatDate').val($(this).data('value'));
36741 ranu 1242
    $("#editScheduleTime").hide();
36642 ranu 1243
});
1244
 
1245
// Generate Geo Link for lead
1246
$(document).on('click', '.generateGeoLink', function (e) {
1247
    e.stopPropagation();
1248
    var lid = $(this).data('leadid');
1249
    doAjaxRequestHandler(context + "/lead-geo/generate-link?leadId=" + lid, "GET", function (response) {
1250
        var url = response.response;
1251
        if (navigator.clipboard) {
1252
            navigator.clipboard.writeText(url).then(function () {
1253
                alert("Link copied to clipboard:\n" + url);
1254
            });
1255
        } else {
1256
            prompt("Share this link with the prospect:", url);
1257
        }
1258
    });
1259
});
1260
 
36868 ranu 1261
// Manual geo verification — for cases where the prospect refused to tap the
1262
// verification link. Team-member confirms lat/lng over phone (or pastes a
1263
// Maps URL the prospect shared) and writes it APPROVED directly.
1264
function ensureManualVerifyModal() {
1265
    if ($('#manualVerifyGeoModal').length) return;
1266
    var html =
1267
        '<div id="manualVerifyGeoModal" class="modal" role="dialog" tabindex="-1">' +
1268
        '  <div class="modal-dialog modal-lg">' +
1269
        '    <div class="modal-content">' +
1270
        '      <div class="modal-header">' +
1271
        '        <button type="button" class="close" data-dismiss="modal">&times;</button>' +
1272
        '        <h4 class="modal-title">Verify Lead Location Manually</h4>' +
1273
        '      </div>' +
1274
        '      <div class="modal-body" style="max-height:75vh;overflow-y:auto;">' +
1275
        '        <input type="hidden" id="manualVerifyLeadId">' +
1276
        '        <div class="form-group">' +
1277
        '          <label>Address <small class="text-muted">(include city, state, pincode for best result)</small></label>' +
1278
        '          <div class="input-group">' +
1279
        '            <input type="text" class="form-control" id="manualVerifyAddress" placeholder="e.g. Shop 12, Sector 18, Noida, UP, 201301">' +
1280
        '            <span class="input-group-btn">' +
1281
        '              <button type="button" class="btn btn-default" id="manualVerifyGeocodeBtn">Find on map</button>' +
1282
        '            </span>' +
1283
        '          </div>' +
1284
        '        </div>' +
1285
        '        <div class="form-group">' +
1286
        '          <label>Latitude, Longitude</label>' +
1287
        '          <div class="input-group">' +
1288
        '            <input type="text" class="form-control" id="manualVerifyLatLng" placeholder="28.6139,77.2090">' +
1289
        '            <span class="input-group-btn">' +
1290
        '              <button type="button" class="btn btn-default" id="manualVerifyPreviewBtn">Show on map</button>' +
1291
        '            </span>' +
1292
        '          </div>' +
1293
        '          <small class="text-muted">You can also paste a Google Maps URL containing coords.</small>' +
1294
        '        </div>' +
1295
        '        <div class="form-group" id="manualVerifyMapWrap" style="display:none;">' +
1296
        '          <label>Map preview <small class="text-muted">(confirm the pin is right)</small></label>' +
1297
        '          <div style="border:1px solid #ddd;border-radius:3px;overflow:hidden;">' +
1298
        '            <iframe id="manualVerifyMapFrame" width="100%" height="260" frameborder="0" style="border:0;" allowfullscreen></iframe>' +
1299
        '          </div>' +
1300
        '          <small><a href="#" id="manualVerifyOpenMap" target="_blank">Open in Google Maps</a></small>' +
1301
        '        </div>' +
1302
        '        <div class="form-group">' +
1303
        '          <label>Store-board photo <span class="text-danger">*</span> <small class="text-muted">(required &mdash; proves the verification)</small></label>' +
1304
        '          <input type="file" id="manualVerifyPhoto" accept="image/jpeg,image/png" required>' +
1305
        '          <div id="manualVerifyPhotoPreview" style="margin-top:6px;display:none;">' +
1306
        '            <img id="manualVerifyPhotoImg" src="" style="max-height:120px;border:1px solid #ddd;border-radius:3px;padding:2px;">' +
1307
        '          </div>' +
1308
        '        </div>' +
1309
        '        <div class="form-group">' +
1310
        '          <label>Remark <small class="text-muted">(optional)</small></label>' +
1311
        '          <input type="text" class="form-control" id="manualVerifyRemark" placeholder="e.g. Confirmed on call with prospect">' +
1312
        '        </div>' +
1313
        '        <div id="manualVerifyErr" class="text-danger" style="display:none;"></div>' +
1314
        '      </div>' +
1315
        '      <div class="modal-footer">' +
1316
        '        <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>' +
1317
        '        <button type="button" class="btn btn-success" id="manualVerifySaveBtn">Save &amp; Verify</button>' +
1318
        '      </div>' +
1319
        '    </div>' +
1320
        '  </div>' +
1321
        '</div>';
1322
    $('body').append(html);
1323
}
1324
 
1325
function manualVerifyShowMap(lat, lng) {
1326
    var src = 'https://www.google.com/maps?q=' + lat + ',' + lng + '&z=17&output=embed';
1327
    $('#manualVerifyMapFrame').attr('src', src);
1328
    $('#manualVerifyOpenMap').attr('href', 'https://www.google.com/maps?q=' + lat + ',' + lng);
1329
    $('#manualVerifyMapWrap').show();
1330
}
1331
 
1332
// Parses raw "lat,lng" or a Google Maps URL containing the coords.
1333
// Maps formats covered: /@lat,lng, /maps?q=lat,lng, ?ll=lat,lng, ?destination=lat,lng.
1334
function parseLatLngInput(raw) {
1335
    if (!raw) return null;
1336
    var s = String(raw).trim();
1337
    // Strip any leading "lat:" / "lng:" tokens
1338
    var direct = s.match(/(-?\d{1,3}\.\d+)\s*,\s*(-?\d{1,3}\.\d+)/);
1339
    if (direct) return {lat: parseFloat(direct[1]), lng: parseFloat(direct[2])};
1340
    return null;
1341
}
1342
 
1343
$(document).on('click', '.verifyGeoManual', function (e) {
1344
    e.stopPropagation();
1345
    var lid = $(this).data('leadid');
1346
    ensureManualVerifyModal();
1347
    $('#manualVerifyLeadId').val(lid);
1348
    $('#manualVerifyAddress').val('');
1349
    $('#manualVerifyLatLng').val('');
1350
    $('#manualVerifyRemark').val('');
1351
    $('#manualVerifyErr').hide().text('');
1352
    $('#manualVerifyMapWrap').hide();
1353
    $('#manualVerifyMapFrame').attr('src', '');
1354
    $('#manualVerifyPhoto').val('');
1355
    $('#manualVerifyPhotoImg').attr('src', '');
1356
    $('#manualVerifyPhotoPreview').hide();
1357
    $('#manualVerifyGeoModal').modal('show');
1358
});
1359
 
1360
// Local thumbnail preview as soon as the user picks a file (no upload yet —
1361
// upload happens on Save so we don't orphan documents on cancel).
1362
$(document).on('change', '#manualVerifyPhoto', function () {
1363
    var f = this.files && this.files[0];
1364
    if (!f) {
1365
        $('#manualVerifyPhotoPreview').hide();
1366
        return;
1367
    }
1368
    var reader = new FileReader();
1369
    reader.onload = function (ev) {
1370
        $('#manualVerifyPhotoImg').attr('src', ev.target.result);
1371
        $('#manualVerifyPhotoPreview').show();
1372
    };
1373
    reader.readAsDataURL(f);
1374
});
1375
 
1376
// Address -> coords via server (uses existing GeocodingService).
1377
// On success, fills the lat/lng box and renders the map preview.
1378
$(document).on('click', '#manualVerifyGeocodeBtn', function () {
1379
    var addr = ($('#manualVerifyAddress').val() || '').trim();
1380
    if (!addr) {
1381
        $('#manualVerifyErr').text('Enter an address first.').show();
1382
        return;
1383
    }
1384
    $('#manualVerifyErr').hide();
1385
    var btn = $(this);
1386
    btn.prop('disabled', true).text('Finding...');
1387
    $.ajax({
1388
        url: context + '/lead-geo/geocode-address',
1389
        type: 'POST',
1390
        data: {address: addr},
1391
        success: function (resp) {
1392
            btn.prop('disabled', false).text('Find on map');
1393
            var r = resp && resp.response ? resp.response : resp;
1394
            if (!r || !r.success) {
1395
                $('#manualVerifyErr').text((r && r.message) || 'Could not geocode that address.').show();
1396
                return;
1397
            }
1398
            $('#manualVerifyLatLng').val(r.latitude + ',' + r.longitude);
1399
            manualVerifyShowMap(r.latitude, r.longitude);
1400
        },
1401
        error: function () {
1402
            btn.prop('disabled', false).text('Find on map');
1403
            $('#manualVerifyErr').text('Geocode request failed. Try again.').show();
1404
        }
1405
    });
1406
});
1407
 
1408
// "Show on map" — re-render the iframe from whatever is in the lat/lng input.
1409
// Useful after the user nudges the coords manually.
1410
$(document).on('click', '#manualVerifyPreviewBtn', function () {
1411
    var parsed = parseLatLngInput($('#manualVerifyLatLng').val());
1412
    if (!parsed) {
1413
        $('#manualVerifyErr').text('Enter latitude,longitude first.').show();
1414
        return;
1415
    }
1416
    $('#manualVerifyErr').hide();
1417
    manualVerifyShowMap(parsed.lat, parsed.lng);
1418
});
1419
 
1420
$(document).on('click', '#manualVerifySaveBtn', function () {
1421
    var lid = $('#manualVerifyLeadId').val();
1422
    var raw = $('#manualVerifyLatLng').val();
1423
    var remark = $('#manualVerifyRemark').val() || '';
1424
    var parsed = parseLatLngInput(raw);
1425
    if (!parsed) {
1426
        $('#manualVerifyErr').text('Could not read latitude/longitude. Paste like 28.6139,77.2090').show();
1427
        return;
1428
    }
1429
    if (parsed.lat < -90 || parsed.lat > 90 || parsed.lng < -180 || parsed.lng > 180
1430
        || (parsed.lat === 0 && parsed.lng === 0)) {
1431
        $('#manualVerifyErr').text('Latitude/longitude out of range.').show();
1432
        return;
1433
    }
1434
    var fileInput = document.getElementById('manualVerifyPhoto');
1435
    var pickedFile = fileInput && fileInput.files && fileInput.files[0];
1436
    if (!pickedFile) {
1437
        $('#manualVerifyErr').text('Please attach a store-board photo to verify.').show();
1438
        return;
1439
    }
1440
    $('#manualVerifyErr').hide();
1441
    var btn = $('#manualVerifySaveBtn');
1442
    btn.prop('disabled', true).text('Verifying...');
1443
 
1444
    function callVerify(docId) {
1445
        $.ajax({
1446
            url: context + '/lead-geo/manual-verify',
1447
            type: 'POST',
1448
            data: {
1449
                leadId: lid,
1450
                latitude: parsed.lat,
1451
                longitude: parsed.lng,
1452
                remark: remark,
1453
                imageDocumentId: docId || 0
1454
            },
1455
            success: function () {
1456
                btn.prop('disabled', false).text('Save & Verify');
1457
                $('#manualVerifyGeoModal').modal('hide');
1458
                // Replace the cell of this lead row with the Verified badge so
1459
                // the user sees the result without reloading the whole list.
1460
                var $cell = $('.verifyGeoManual[data-leadid="' + lid + '"]').closest('td');
1461
                if ($cell.length) {
1462
                    var photoBtn = docId > 0
1463
                        ? '  <a href="' + context + '/open-attachment?documentId=' + docId + '" target="_blank" class="btn btn-xs btn-default" style="margin-bottom:2px;">View Photo</a>'
1464
                        : '';
1465
                    $cell.html(
1466
                        '<div class="btn-group-vertical" style="width:100%">' +
1467
                        '  <span class="label label-success" style="margin-bottom:4px;">Verified</span>' +
1468
                        '  <a href="https://www.google.com/maps?q=' + parsed.lat + ',' + parsed.lng + '" target="_blank" class="btn btn-xs btn-default" style="margin-bottom:2px;">View Map</a>' +
1469
                        photoBtn +
1470
                        '  <button class="btn btn-xs btn-danger reject-geo" data-leadid="' + lid + '">Revoke</button>' +
1471
                        '</div>'
1472
                    );
1473
                }
1474
            },
1475
            error: function (xhr) {
1476
                btn.prop('disabled', false).text('Save & Verify');
1477
                var msg = 'Failed to verify. Please try again.';
1478
                try {
1479
                    var j = xhr.responseJSON || JSON.parse(xhr.responseText || '{}');
1480
                    if (j && j.response) msg = j.response;
1481
                    else if (j && j.message) msg = j.message;
1482
                } catch (e) {
1483
                }
1484
                $('#manualVerifyErr').text(msg).show();
1485
            }
1486
        });
1487
    }
1488
 
1489
    // Upload first, then verify with the returned document id. Photo is
1490
    // required (gate at the top of the handler), so we always go through this.
1491
    btn.text('Uploading photo...');
1492
    var formData = new FormData();
1493
    formData.append('file', pickedFile, pickedFile.name || 'store-photo.jpg');
1494
    $.ajax({
1495
        url: context + '/lead-geo/upload-image',
1496
        type: 'POST',
1497
        data: formData,
1498
        processData: false,
1499
        contentType: false,
1500
        success: function (resp) {
1501
            var r = resp && resp.response ? resp.response : resp;
1502
            var docId = r && (r.document_id || r.documentId || r.id);
1503
            if (!docId) {
1504
                btn.prop('disabled', false).text('Save & Verify');
1505
                $('#manualVerifyErr').text('Photo upload failed. Try again or remove the photo.').show();
1506
                return;
1507
            }
1508
            btn.text('Verifying...');
1509
            callVerify(docId);
1510
        },
1511
        error: function () {
1512
            btn.prop('disabled', false).text('Save & Verify');
1513
            $('#manualVerifyErr').text('Photo upload failed. Try again or remove the photo.').show();
1514
        }
1515
    });
1516
});
1517
 
36642 ranu 1518
// Geo Review navigation
1519
$(document).on('click', '.geo-review', function () {
1520
    doGetAjaxRequestHandler(context + "/lead-geo/pending-reviews", function (response) {
1521
        $('#main-content').html(response);
1522
    });
1523
});
1524
 
1525
// Visit Approvals navigation
1526
$(document).on('click', '.visit-approvals', function () {
1527
    doGetAjaxRequestHandler(context + "/visit-approvals", function (response) {
1528
        $('#main-content').html(response);
1529
    });
1530
});
1531
 
36650 ranu 1532
// Beat Day View — load inline into dashboard
1533
$(document).on('click', '.beat-plan-dayview', function (e) {
1534
    e.preventDefault();
1535
    doGetAjaxRequestHandler(context + '/beatPlan/dayView', function (response) {
1536
        $('#main-content').html(response);
1537
    });
1538
});
1539
 
36655 ranu 1540
// Base Location manager — load inline into dashboard
1541
$(document).on('click', '.base-location', function (e) {
1542
    e.preventDefault();
1543
    doGetAjaxRequestHandler(context + '/beatPlan/baseLocationPage', function (response) {
1544
        $('#main-content').html(response);
1545
    });
1546
});
1547
 
36740 ranu 1548
// Deferred Partners — load inline into dashboard
1549
$(document).on('click', '.beat-plan-deferred', function (e) {
1550
    e.preventDefault();
1551
    doGetAjaxRequestHandler(context + '/beatPlan/deferredView', function (response) {
1552
        $('#main-content').html(response);
1553
    });
1554
});
1555
 
36642 ranu 1556
// Approve geolocation from lead table
1557
$(document).on('click', '.approve-geo', function (e) {
1558
    e.stopPropagation();
1559
    var lid = $(this).data('leadid');
1560
    if (!confirm('Approve geolocation for Lead #' + lid + '?')) return;
1561
 
1562
    var btn = $(this);
1563
    var cell = btn.closest('td');
1564
 
1565
    doPostAjaxRequestWithParamsHandler(
1566
        context + '/lead-geo/review',
1567
        {leadId: lid, status: 'APPROVED', remark: ''},
1568
        function (response) {
1569
            cell.html('<span class="label label-success">Verified</span>');
1570
        }
1571
    );
1572
});
1573
 
1574
// Reject geolocation from lead table
1575
$(document).on('click', '.reject-geo', function (e) {
1576
    e.stopPropagation();
1577
    var lid = $(this).data('leadid');
1578
    var reason = prompt('Reason for rejection:');
1579
    if (reason === null) return;
1580
 
1581
    var btn = $(this);
1582
    var cell = btn.closest('td');
1583
 
1584
    doPostAjaxRequestWithParamsHandler(
1585
        context + '/lead-geo/review',
1586
        {leadId: lid, status: 'REJECTED', remark: reason},
1587
        function (response) {
1588
            cell.html('<button class="btn btn-xs btn-warning generateGeoLink" data-leadid="' + lid + '">Rejected - Resend</button>');
1589
        }
1590
    );
1591
});
1592