Subversion Repositories SmartDukaan

Rev

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