Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
36740 ranu 1
<section class="wrapper">
2
    <div class="row">
3
        <div class="col-lg-12">
4
            <h3 class="page-header"><i class="icon_calendar"></i> Deferred Partners</h3>
5
            <ol class="breadcrumb">
6
                <li><i class="fa fa-home"></i><a href="${rc.contextPath}/dashboard">Home</a></li>
7
                <li><i class="icon_group"></i> Partner Acquisition</li>
8
                <li><i class="icon_calendar"></i> Deferred Partners</li>
9
            </ol>
10
        </div>
11
    </div>
12
 
13
    <div class="row" style="margin-bottom:10px;">
14
        <div class="col-lg-12" style="display:flex; gap:10px; align-items:center; flex-wrap:wrap;">
36761 ranu 15
            <label style="margin:0;">Date:</label>
16
            <input type="date" id="defDate" class="form-control input-sm" style="width:160px;">
36740 ranu 17
            <button class="btn btn-primary btn-sm" id="defLoad">Load</button>
18
            <span id="defSummary" style="color:#777; font-size:12px; margin-left:10px;"></span>
19
        </div>
20
    </div>
21
 
22
    <div class="row">
23
        <div class="col-lg-12">
24
            <div class="table-responsive">
25
                <table class="table table-bordered table-striped table-hover" id="defTable">
26
                    <thead>
27
                    <tr>
28
                        <th>User</th>
29
                        <th>Date</th>
30
                        <th>Type</th>
31
                        <th>Partner / Agenda</th>
32
                        <th>Reason</th>
33
                        <th>Status</th>
34
                        <th>Next Scheduled</th>
35
                        <th>Action</th>
36
                    </tr>
37
                    </thead>
38
                    <tbody id="defRows">
39
                    <tr>
36761 ranu 40
                        <td colspan="8" style="text-align:center; color:#999;">Pick a date and click Load.</td>
36740 ranu 41
                    </tr>
42
                    </tbody>
43
                </table>
44
            </div>
45
        </div>
46
    </div>
47
</section>
48
 
49
<!-- Reschedule modal -->
50
<!-- Reschedule via the beat-plan calendar window (pick an upcoming beat to drop the item into) -->
51
<div class="modal fade" id="defCalModal" tabindex="-1">
52
    <div class="modal-dialog" style="width:95%; max-width:1300px; margin-top:20px;">
53
        <div class="modal-content">
54
            <div class="modal-header">
55
                <button type="button" class="close" data-dismiss="modal"
56
                        onclick="$('#defCalFrame').attr('src','');">&times;
57
                </button>
58
                <h4 class="modal-title" id="defCalTitle">Reschedule into a Beat</h4>
59
            </div>
60
            <div class="modal-body" style="padding:0;">
61
                <iframe id="defCalFrame" style="width:100%; height:80vh; border:none;"></iframe>
62
            </div>
63
        </div>
64
    </div>
65
</div>
66
 
67
<script>
68
    (function () {
69
        var d = new Date();
70
 
71
        function fmt(x) {
72
            return x.getFullYear() + '-' + ('0' + (x.getMonth() + 1)).slice(-2) + '-' + ('0' + x.getDate()).slice(-2);
73
        }
74
 
36761 ranu 75
        $('#defDate').val(fmt(d));
36740 ranu 76
        loadDeferred();
77
    })();
78
 
37498 amit 79
    // Fragment is re-injected with .html(), which re-runs this script; clear the
80
    // namespace first so handlers replace rather than stack.
81
    $(document).off('.beatplandeferred');
82
    $(document).on('click.beatplandeferred', '#defLoad', function () {
36740 ranu 83
        loadDeferred();
84
    });
85
 
86
    function loadDeferred() {
36761 ranu 87
        var d = $('#defDate').val();
88
        if (!d) {
89
            alert('Pick a date');
36740 ranu 90
            return;
91
        }
92
        $('#defRows').html('<tr><td colspan="8" style="text-align:center;">Loading...</td></tr>');
93
        $('#defSummary').text('');
36761 ranu 94
        $.get(context + '/beatPlan/deferred', {startDate: d, endDate: d}).done(function (r) {
36740 ranu 95
            var data = r.response || r;
96
            renderDeferredRows(data.rows || []);
36761 ranu 97
            $('#defSummary').text((data.rows || []).length + ' deferred on ' + data.startDate);
36740 ranu 98
        }).fail(function (xhr) {
99
            $('#defRows').html('<tr><td colspan="8" style="color:#d9534f; text-align:center;">Error: ' + (xhr.responseText || xhr.statusText) + '</td></tr>');
100
        });
101
    }
102
 
103
    function renderDeferredRows(rows) {
104
        if (!rows || rows.length === 0) {
36761 ranu 105
            $('#defRows').html('<tr><td colspan="8" style="text-align:center; color:#999;">No deferred items on this date.</td></tr>');
36740 ranu 106
            return;
107
        }
108
        var html = '';
109
        rows.forEach(function (r) {
110
            // "Auto-covered" = the same partner is on an upcoming beat run. Just a
111
            // hint — the row stays actionable (the next run may be far off, so the
112
            // head can still reschedule it sooner). Leads never auto-cover.
113
            var autoCovered = !!r.nextScheduledDate;
114
            var statusCell = autoCovered
115
                    ? '<span class="label label-success" title="Also scheduled on ' + r.nextScheduledDate + '">Auto-covered</span>'
116
                    : '<span class="label label-warning">Deferred</span>';
117
            var typeCell = (r.type === 'Lead')
118
                    ? '<span class="label label-warning">Lead</span>'
119
                    : '<span class="label label-info">Visit</span>';
120
            var next = autoCovered
121
                    ? '<span style="color:#2e7d32; font-weight:600;">' + r.nextScheduledDate + '</span>'
122
                    : '<span style="color:#999;">—</span>';
123
            var safeName = (r.name || '').replace(/"/g, '&quot;');
124
            var action = '<button class="btn btn-xs btn-success def-reschedule"'
125
                    + ' data-id="' + r.id + '"'
126
                    + ' data-userid="' + r.authUserId + '"'
127
                    + ' data-username="' + (r.userName || '').replace(/"/g, '&quot;') + '"'
128
                    + ' data-type="' + (r.type === 'Lead' ? 'lead' : 'visit') + '"'
129
                    + ' data-deferdate="' + (r.deferredDate || '') + '"'
130
                    + ' data-name="' + safeName + '">Reschedule</button> '
131
                    + '<button class="btn btn-xs btn-default def-cancel" data-id="' + r.id + '">Cancel</button>';
132
            html += '<tr>'
133
                    + '<td>' + (r.userName || '') + '</td>'
134
                    + '<td><span class="label label-primary">' + (r.deferredDate || '') + '</span></td>'
135
                    + '<td>' + typeCell + '</td>'
136
                    + '<td>' + (r.name || '') + '</td>'
137
                    + '<td>' + (r.reason || '') + '</td>'
138
                    + '<td>' + statusCell + '</td>'
139
                    + '<td>' + next + '</td>'
140
                    + '<td>' + action + '</td>'
141
                    + '</tr>';
142
        });
143
        $('#defRows').html(html);
144
    }
145
 
146
    // Cancel
37498 amit 147
    $(document).on('click.beatplandeferred', '.def-cancel', function () {
36740 ranu 148
        var id = $(this).data('id');
149
        if (!confirm('Cancel this deferred visit? It will be dropped (no re-visit).')) return;
150
        $.ajax({
151
            url: context + '/beatPlan/deferred/action',
152
            type: 'POST', contentType: 'application/json',
153
            data: JSON.stringify({deferredId: id, action: 'cancel'}),
154
            success: function () {
155
                loadDeferred();
156
            },
157
            error: function (xhr) {
158
                alert(serverMsg(xhr, 'Cancel failed'));
159
            }
160
        });
161
    });
162
 
163
    // Reschedule → open the beat-plan calendar window scoped to that sales person,
164
    // in "deferred-assign" mode. The head clicks an upcoming beat there to drop the
165
    // deferred lead/partner into it. On close, reload (the assigned item drops off).
37498 amit 166
    $(document).on('click.beatplandeferred', '.def-reschedule', function () {
36740 ranu 167
        var id = $(this).data('id');
168
        var userId = $(this).data('userid');
169
        var userName = $(this).data('username') || '';
170
        var type = $(this).data('type') || 'visit';
171
        var name = $(this).data('name') || '';
172
        var deferDate = $(this).data('deferdate') || '';
173
        var url = context + '/beatPlanWindow'
174
                + '?autoUserId=' + userId
175
                + '&autoUserName=' + encodeURIComponent(userName)
176
                + '&assignDeferredId=' + id
177
                + '&deferType=' + encodeURIComponent(type)
178
                + '&deferDate=' + encodeURIComponent(deferDate)
179
                + '&deferName=' + encodeURIComponent(name);
180
        $('#defCalTitle').text('Reschedule "' + name + '" into a beat — ' + userName);
181
        $('#defCalFrame').attr('src', url);
182
        $('#defCalModal').modal('show');
183
    });
184
 
185
    // Reload the list when the calendar window closes (item may have been assigned)
186
    $('#defCalModal').on('hidden.bs.modal', function () {
187
        $('#defCalFrame').attr('src', '');
188
        loadDeferred();
189
    });
190
 
191
    function serverMsg(xhr, fallback) {
192
        try {
193
            var err = JSON.parse(xhr.responseText);
194
            if (err && err.response) {
195
                if (typeof err.response === 'string') return err.response;
196
                if (err.response.message) return err.response.message;
197
            }
198
        } catch (e) {
199
        }
200
        return fallback;
201
    }
202
</script>