Subversion Repositories SmartDukaan

Rev

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