| Line 9... |
Line 9... |
| 9 |
<div class="col-lg-12">
|
9 |
<div class="col-lg-12">
|
| 10 |
<table class="table table-border table-condensed table-bordered table-hover" id="beatReportTable" style="width:100%">
|
10 |
<table class="table table-border table-condensed table-bordered table-hover" id="beatReportTable" style="width:100%">
|
| 11 |
<thead>
|
11 |
<thead>
|
| 12 |
<tr>
|
12 |
<tr>
|
| 13 |
<th>User Name</th>
|
13 |
<th>User Name</th>
|
| - |
|
14 |
<th>Beat</th>
|
| - |
|
15 |
<th>Day</th>
|
| - |
|
16 |
<th>Planned</th>
|
| 14 |
<th>Punch In/Out</th>
|
17 |
<th>Punch In/Out</th>
|
| 15 |
<th>Total Visits</th>
|
18 |
<th>Total Visits</th>
|
| 16 |
<th>Completed Visits</th>
|
19 |
<th>Completed Visits</th>
|
| 17 |
<th>Pending Visits</th>
|
20 |
<th>Pending Visits</th>
|
| 18 |
<th>Deferred</th>
|
21 |
<th>Deferred</th>
|
| 19 |
<th>Map</th>
|
22 |
<th>Action</th>
|
| 20 |
</tr>
|
23 |
</tr>
|
| 21 |
</thead>
|
24 |
</thead>
|
| 22 |
<tbody>
|
25 |
<tbody>
|
| 23 |
#set($rowIndex = 0)
|
26 |
#set($rowIndex = 0)
|
| 24 |
#foreach($row in $reportRows)
|
27 |
#foreach($row in $reportRows)
|
| 25 |
<tr>
|
28 |
<tr>
|
| 26 |
<td><a href="javascript:void(0);" class="beat-user-detail-link" data-userid="$row.get('userId')" style="color:#2c3e50; font-weight:bold; text-decoration:underline; cursor:pointer;">$row.get("username")</a></td>
|
29 |
<td><a href="javascript:void(0);" class="beat-user-detail-link" data-userid="$row.get('userId')" style="color:#2c3e50; font-weight:bold; text-decoration:underline; cursor:pointer;">$row.get("username")</a></td>
|
| - |
|
30 |
#set($userBeats = $row.get("beats"))
|
| - |
|
31 |
#if($userBeats && $userBeats.size() > 0)
|
| - |
|
32 |
<td>
|
| - |
|
33 |
#foreach($b in $userBeats)
|
| - |
|
34 |
<span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:#if($b.get(
|
| - |
|
35 |
'beatColor'))$b.get('beatColor')#else#3498db#end;margin-right:5px;"></span>$b.get(
|
| - |
|
36 |
"beatName")<br>
|
| - |
|
37 |
#end
|
| - |
|
38 |
</td>
|
| - |
|
39 |
<td>
|
| - |
|
40 |
#foreach($b in $userBeats)
|
| - |
|
41 |
$b.get("dayNumber")<br>
|
| - |
|
42 |
#end
|
| - |
|
43 |
</td>
|
| - |
|
44 |
<td>
|
| - |
|
45 |
#foreach($b in $userBeats)
|
| - |
|
46 |
<strong>$b.get("totalCount")</strong><br>
|
| - |
|
47 |
#end
|
| - |
|
48 |
</td>
|
| - |
|
49 |
#else
|
| - |
|
50 |
<td colspan="3" style="color:#999; text-align:center; font-style:italic;">No beat scheduled</td>
|
| - |
|
51 |
#end
|
| 27 |
<td>
|
52 |
<td>
|
| 28 |
#if($row.get("punchInTime") != "")<span class="label label-success">$row.get("punchInTime")</span>#else<span style="color:#ccc;">--</span>#end
|
53 |
#if($row.get("punchInTime") != "")<span class="label label-success">$row.get("punchInTime")</span>#else<span style="color:#ccc;">--</span>#end
|
| 29 |
#if($row.get("punchOutTime") != "")<span class="label label-danger">$row.get("punchOutTime")</span>#else<span style="color:#ccc;">--</span>#end
|
54 |
#if($row.get("punchOutTime") != "")<span class="label label-danger">$row.get("punchOutTime")</span>#else<span style="color:#ccc;">--</span>#end
|
| 30 |
</td>
|
55 |
</td>
|
| 31 |
<td><a href="javascript:void(0);" class="beat-detail-link" data-row="$rowIndex" data-type="total" style="color:#1abc9c; font-weight:bold; text-decoration:underline; cursor:pointer;">$row.get("total")</a></td>
|
56 |
<td><a href="javascript:void(0);" class="beat-detail-link" data-row="$rowIndex" data-type="total" style="color:#1abc9c; font-weight:bold; text-decoration:underline; cursor:pointer;">$row.get("total")</a></td>
|
| 32 |
<td><a href="javascript:void(0);" class="beat-detail-link" data-row="$rowIndex" data-type="completed" style="color:#1abc9c; font-weight:bold; text-decoration:underline; cursor:pointer;">$row.get("completed")</a></td>
|
57 |
<td><a href="javascript:void(0);" class="beat-detail-link" data-row="$rowIndex" data-type="completed" style="color:#1abc9c; font-weight:bold; text-decoration:underline; cursor:pointer;">$row.get("completed")</a></td>
|
| 33 |
<td><a href="javascript:void(0);" class="beat-detail-link" data-row="$rowIndex" data-type="pending" style="color:#e67e22; font-weight:bold; text-decoration:underline; cursor:pointer;">$row.get("pending")</a></td>
|
58 |
<td><a href="javascript:void(0);" class="beat-detail-link" data-row="$rowIndex" data-type="pending" style="color:#e67e22; font-weight:bold; text-decoration:underline; cursor:pointer;">$row.get("pending")</a></td>
|
| 34 |
<td><a href="javascript:void(0);" class="beat-detail-link" data-row="$rowIndex" data-type="deferred" style="color:#e74c3c; font-weight:bold; text-decoration:underline; cursor:pointer;">$row.get("deferred")</a></td>
|
59 |
<td><a href="javascript:void(0);" class="beat-detail-link" data-row="$rowIndex" data-type="deferred" style="color:#e74c3c; font-weight:bold; text-decoration:underline; cursor:pointer;">$row.get("deferred")</a></td>
|
| - |
|
60 |
<td style="white-space:nowrap;">
|
| 35 |
<td><a href="javascript:void(0);" class="beat-map-link" data-row="$rowIndex" style="cursor:pointer;"><i class="fa fa-map-marker" style="color:#1abc9c; font-size:18px;"></i></a></td>
|
61 |
<a href="javascript:void(0);" class="beat-map-link" data-row="$rowIndex" title="Map"
|
| - |
|
62 |
style="cursor:pointer; margin-right:6px;"><i class="fa fa-map-marker"
|
| - |
|
63 |
style="color:#1abc9c; font-size:18px;"></i></a>
|
| - |
|
64 |
#if($userBeats && $userBeats.size() > 0)
|
| - |
|
65 |
#foreach($b in $userBeats)
|
| - |
|
66 |
<button class="btn btn-xs btn-info beat-view-calendar" title="View Calendar"
|
| - |
|
67 |
data-userid="$b.get('authUserId')"
|
| - |
|
68 |
data-username="$row.get('username').replace('"', '\"')"><i class="fa fa-eye"></i>
|
| - |
|
69 |
</button>
|
| - |
|
70 |
<button class="btn btn-xs btn-warning beat-edit-on-date" title="Edit Beat"
|
| - |
|
71 |
data-userid="$b.get('authUserId')"
|
| - |
|
72 |
data-username="$row.get('username').replace('"', '\"')"
|
| - |
|
73 |
data-beatid="$b.get('beatId')"
|
| - |
|
74 |
data-date="$b.get('scheduleDate')"><i class="fa fa-edit"></i></button>
|
| - |
|
75 |
<button class="btn btn-xs btn-success beat-assign-visit" title="Assign Visit"
|
| - |
|
76 |
data-userid="$b.get('authUserId')"
|
| - |
|
77 |
data-username="$row.get('username').replace('"', '\"')"
|
| - |
|
78 |
data-beatid="$b.get('beatId')"
|
| - |
|
79 |
data-date="$b.get('scheduleDate')"><i class="fa fa-plus-circle"></i></button>
|
| - |
|
80 |
<br>
|
| - |
|
81 |
#end
|
| - |
|
82 |
#end
|
| - |
|
83 |
</td>
|
| 36 |
</tr>
|
84 |
</tr>
|
| 37 |
|
85 |
|
| 38 |
<script>
|
86 |
<script>
|
| 39 |
window.beatReportData = window.beatReportData || {};
|
87 |
window.beatReportData = window.beatReportData || {};
|
| 40 |
window.beatReportData[$rowIndex] = {
|
88 |
window.beatReportData[$rowIndex] = {
|
| Line 653... |
Line 701... |
| 653 |
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
701 |
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
| 654 |
</div>
|
702 |
</div>
|
| 655 |
</div>
|
703 |
</div>
|
| 656 |
</div>
|
704 |
</div>
|
| 657 |
</div>
|
705 |
</div>
|
| - |
|
706 |
|
| - |
|
707 |
<!-- Beat calendar modal (iframe loads /beatPlanWindow with auto-selected user) -->
|
| - |
|
708 |
<div class="modal fade" id="reportBeatCalendarModal" tabindex="-1" style="overflow-y:auto;">
|
| - |
|
709 |
<div class="modal-dialog" style="width:95%; max-width:1300px; margin-top:20px;">
|
| - |
|
710 |
<div class="modal-content">
|
| - |
|
711 |
<div class="modal-header">
|
| - |
|
712 |
<button type="button" class="close" data-dismiss="modal"
|
| - |
|
713 |
onclick="$('#reportBeatCalendarFrame').attr('src','');">×
|
| - |
|
714 |
</button>
|
| - |
|
715 |
<h4 class="modal-title" id="reportBeatCalendarTitle">Calendar</h4>
|
| - |
|
716 |
</div>
|
| - |
|
717 |
<div class="modal-body" style="padding:0;">
|
| - |
|
718 |
<iframe id="reportBeatCalendarFrame" style="width:100%; height:80vh; border:none;"></iframe>
|
| - |
|
719 |
</div>
|
| - |
|
720 |
</div>
|
| - |
|
721 |
</div>
|
| - |
|
722 |
</div>
|
| - |
|
723 |
|
| - |
|
724 |
<script>
|
| - |
|
725 |
$(document).on('click', '.beat-view-calendar', function () {
|
| - |
|
726 |
var userId = $(this).data('userid');
|
| - |
|
727 |
var userName = $(this).data('username') || '';
|
| - |
|
728 |
var url = context + '/beatPlanWindow?autoUserId=' + userId
|
| - |
|
729 |
+ '&autoUserName=' + encodeURIComponent(userName);
|
| - |
|
730 |
$('#reportBeatCalendarTitle').text('Calendar - ' + userName);
|
| - |
|
731 |
$('#reportBeatCalendarFrame').attr('src', url);
|
| - |
|
732 |
$('#reportBeatCalendarModal').modal('show');
|
| - |
|
733 |
});
|
| - |
|
734 |
|
| - |
|
735 |
$(document).on('click', '.beat-edit-on-date', function () {
|
| - |
|
736 |
var userId = $(this).data('userid');
|
| - |
|
737 |
var userName = $(this).data('username') || '';
|
| - |
|
738 |
var beatId = $(this).data('beatid');
|
| - |
|
739 |
var date = $(this).data('date');
|
| - |
|
740 |
var url = context + '/beatPlanWindow?autoUserId=' + userId
|
| - |
|
741 |
+ '&autoUserName=' + encodeURIComponent(userName)
|
| - |
|
742 |
+ '&editBeatId=' + beatId + '&editDate=' + date;
|
| - |
|
743 |
$('#reportBeatCalendarTitle').text('Edit Beat - ' + userName + ' on ' + date);
|
| - |
|
744 |
$('#reportBeatCalendarFrame').attr('src', url);
|
| - |
|
745 |
$('#reportBeatCalendarModal').modal('show');
|
| - |
|
746 |
});
|
| - |
|
747 |
|
| - |
|
748 |
// ---------- ASSIGN VISIT (mirrors Beat Day View; IDs/classes prefixed with `r` to avoid collisions) ----------
|
| - |
|
749 |
var rAvContext = {authUserId: null, userName: '', date: '', beatId: null, allParties: [], agendaOptions: []};
|
| - |
|
750 |
|
| - |
|
751 |
var R_AGENDA_MULTISELECT_OPTS = {
|
| - |
|
752 |
includeSelectAllOption: false,
|
| - |
|
753 |
maxHeight: 220,
|
| - |
|
754 |
buttonWidth: '240px',
|
| - |
|
755 |
numberDisplayed: 2,
|
| - |
|
756 |
nonSelectedText: 'Pick agenda(s)',
|
| - |
|
757 |
nSelectedText: ' agendas',
|
| - |
|
758 |
allSelectedText: 'All agendas',
|
| - |
|
759 |
enableFiltering: true,
|
| - |
|
760 |
enableCaseInsensitiveFiltering: true
|
| - |
|
761 |
};
|
| - |
|
762 |
|
| - |
|
763 |
function rAgendaSelectHtml(p) {
|
| - |
|
764 |
var preset = {};
|
| - |
|
765 |
(p.existingAgendas || []).forEach(function (a) {
|
| - |
|
766 |
preset[a] = true;
|
| - |
|
767 |
});
|
| - |
|
768 |
var html = '<select multiple class="r-av-party-agenda" data-fofoid="' + p.fofoStoreId + '">';
|
| - |
|
769 |
rAvContext.agendaOptions.forEach(function (opt) {
|
| - |
|
770 |
html += '<option value="' + opt + '"' + (preset[opt] ? ' selected' : '') + '>' + opt + '</option>';
|
| - |
|
771 |
});
|
| - |
|
772 |
html += '</select>';
|
| - |
|
773 |
return html;
|
| - |
|
774 |
}
|
| - |
|
775 |
|
| - |
|
776 |
function rRebuildDefaultAgenda() {
|
| - |
|
777 |
var $sel = $('#rAvDefaultAgenda');
|
| - |
|
778 |
try {
|
| - |
|
779 |
$sel.multiselect('destroy');
|
| - |
|
780 |
} catch (e) {
|
| - |
|
781 |
}
|
| - |
|
782 |
var html = '';
|
| - |
|
783 |
rAvContext.agendaOptions.forEach(function (opt) {
|
| - |
|
784 |
html += '<option value="' + opt + '">' + opt + '</option>';
|
| - |
|
785 |
});
|
| - |
|
786 |
$sel.html(html);
|
| - |
|
787 |
var defaultOpts = $.extend({}, R_AGENDA_MULTISELECT_OPTS);
|
| - |
|
788 |
defaultOpts.nonSelectedText = 'Pick agenda(s) to apply';
|
| - |
|
789 |
$sel.multiselect(defaultOpts);
|
| - |
|
790 |
}
|
| - |
|
791 |
|
| - |
|
792 |
function rInitRowMultiselects() {
|
| - |
|
793 |
$('.r-av-party-agenda').each(function () {
|
| - |
|
794 |
var $sel = $(this);
|
| - |
|
795 |
try {
|
| - |
|
796 |
$sel.multiselect('destroy');
|
| - |
|
797 |
} catch (e) {
|
| - |
|
798 |
}
|
| - |
|
799 |
$sel.multiselect(R_AGENDA_MULTISELECT_OPTS);
|
| - |
|
800 |
});
|
| - |
|
801 |
}
|
| - |
|
802 |
|
| - |
|
803 |
function rUpdateAvSelectedCount() {
|
| - |
|
804 |
var n = $('.r-av-party-chk:checked').length;
|
| - |
|
805 |
$('#rAvSelectedCount').text(n + ' selected');
|
| - |
|
806 |
$('#rAvSubmit').prop('disabled', n === 0);
|
| - |
|
807 |
}
|
| - |
|
808 |
|
| - |
|
809 |
function rRenderAvParties(list) {
|
| - |
|
810 |
if (!list || list.length === 0) {
|
| - |
|
811 |
$('#rAvPartyList').html('<div style="padding:20px; color:#999; text-align:center;">No parties found.</div>');
|
| - |
|
812 |
return;
|
| - |
|
813 |
}
|
| - |
|
814 |
var html = '<table class="table table-condensed table-hover" style="margin-bottom:0; font-size:13px;">';
|
| - |
|
815 |
html += '<thead><tr>'
|
| - |
|
816 |
+ '<th style="width:30px;"><input type="checkbox" id="rAvSelectAll" title="Select all"></th>'
|
| - |
|
817 |
+ '<th>Code</th><th>Outlet</th><th>City</th>'
|
| - |
|
818 |
+ '<th style="width:260px;">Agenda</th>'
|
| - |
|
819 |
+ '<th style="width:260px;">Description</th>'
|
| - |
|
820 |
+ '</tr></thead><tbody>';
|
| - |
|
821 |
list.forEach(function (p) {
|
| - |
|
822 |
var safeName = (p.outletName || '').replace(/"/g, '"');
|
| - |
|
823 |
var existingDesc = (p.existingDescription || '').replace(/"/g, '"');
|
| - |
|
824 |
html += '<tr>'
|
| - |
|
825 |
+ '<td><input type="checkbox" class="r-av-party-chk" '
|
| - |
|
826 |
+ 'data-fofoid="' + p.fofoStoreId + '" '
|
| - |
|
827 |
+ 'data-name="' + safeName + '" '
|
| - |
|
828 |
+ 'data-lat="' + (p.latitude || '') + '" '
|
| - |
|
829 |
+ 'data-lng="' + (p.longitude || '') + '"></td>'
|
| - |
|
830 |
+ '<td>' + (p.code || '') + '</td>'
|
| - |
|
831 |
+ '<td>' + (p.outletName || '') + '</td>'
|
| - |
|
832 |
+ '<td>' + (p.city || '') + '</td>'
|
| - |
|
833 |
+ '<td>' + rAgendaSelectHtml(p) + '</td>'
|
| - |
|
834 |
+ '<td><textarea class="form-control input-sm r-av-party-desc"'
|
| - |
|
835 |
+ ' data-fofoid="' + p.fofoStoreId + '"'
|
| - |
|
836 |
+ ' rows="2" placeholder="Optional notes..."'
|
| - |
|
837 |
+ ' style="resize:vertical; min-height:34px;">' + existingDesc + '</textarea></td>'
|
| - |
|
838 |
+ '</tr>';
|
| - |
|
839 |
});
|
| - |
|
840 |
html += '</tbody></table>';
|
| - |
|
841 |
$('#rAvPartyList').html(html);
|
| - |
|
842 |
rInitRowMultiselects();
|
| - |
|
843 |
rUpdateAvSelectedCount();
|
| - |
|
844 |
}
|
| - |
|
845 |
|
| - |
|
846 |
$(document).on('click', '.beat-assign-visit', function () {
|
| - |
|
847 |
rAvContext.authUserId = $(this).data('userid');
|
| - |
|
848 |
rAvContext.userName = $(this).data('username') || '';
|
| - |
|
849 |
rAvContext.date = $(this).data('date');
|
| - |
|
850 |
rAvContext.beatId = $(this).data('beatid');
|
| - |
|
851 |
rAvContext.allParties = [];
|
| - |
|
852 |
|
| - |
|
853 |
$('#rAvTitle').text('Assign Visit - ' + rAvContext.userName + ' on ' + rAvContext.date);
|
| - |
|
854 |
$('#rAvSearch').val('');
|
| - |
|
855 |
$('#rAvPartyList').html('<div style="padding:20px; color:#999; text-align:center;">Loading parties...</div>');
|
| - |
|
856 |
$('#rAvMsg').text('');
|
| - |
|
857 |
$('#rAvSelectedCount').text('0 selected');
|
| - |
|
858 |
$('#rAvSubmit').prop('disabled', true);
|
| - |
|
859 |
$('#rAssignVisitModal').modal('show');
|
| - |
|
860 |
|
| - |
|
861 |
$.get(context + '/beatPlan/assignVisit/parties', {
|
| - |
|
862 |
authUserId: rAvContext.authUserId,
|
| - |
|
863 |
date: rAvContext.date,
|
| - |
|
864 |
beatId: rAvContext.beatId
|
| - |
|
865 |
}).done(function (r) {
|
| - |
|
866 |
var data = r.response || r;
|
| - |
|
867 |
rAvContext.allParties = (data.parties || []).filter(function (p) {
|
| - |
|
868 |
return !p.inBeat;
|
| - |
|
869 |
});
|
| - |
|
870 |
rAvContext.agendaOptions = data.agendaOptions || [];
|
| - |
|
871 |
if (!data.dtrUserId) {
|
| - |
|
872 |
$('#rAvPartyList').html('<div style="padding:20px; color:#c62828; text-align:center;">'
|
| - |
|
873 |
+ 'This user has no dtr.users record (cannot create visit tasks).</div>');
|
| - |
|
874 |
return;
|
| - |
|
875 |
}
|
| - |
|
876 |
rRebuildDefaultAgenda();
|
| - |
|
877 |
rRenderAvParties(rAvContext.allParties);
|
| - |
|
878 |
}).fail(function (xhr) {
|
| - |
|
879 |
$('#rAvPartyList').html('<div style="padding:20px; color:#c62828; text-align:center;">'
|
| - |
|
880 |
+ 'Error loading parties: ' + (xhr.responseText || xhr.statusText) + '</div>');
|
| - |
|
881 |
});
|
| - |
|
882 |
});
|
| - |
|
883 |
|
| - |
|
884 |
$(document).on('input', '#rAvSearch', function () {
|
| - |
|
885 |
var q = $(this).val().toLowerCase().trim();
|
| - |
|
886 |
if (!q) {
|
| - |
|
887 |
rRenderAvParties(rAvContext.allParties);
|
| - |
|
888 |
return;
|
| - |
|
889 |
}
|
| - |
|
890 |
var filtered = rAvContext.allParties.filter(function (p) {
|
| - |
|
891 |
return (p.code || '').toLowerCase().indexOf(q) !== -1
|
| - |
|
892 |
|| (p.outletName || '').toLowerCase().indexOf(q) !== -1
|
| - |
|
893 |
|| (p.city || '').toLowerCase().indexOf(q) !== -1;
|
| - |
|
894 |
});
|
| - |
|
895 |
rRenderAvParties(filtered);
|
| - |
|
896 |
});
|
| - |
|
897 |
|
| - |
|
898 |
$(document).on('change', '#rAvSelectAll', function () {
|
| - |
|
899 |
$('.r-av-party-chk').prop('checked', this.checked);
|
| - |
|
900 |
rUpdateAvSelectedCount();
|
| - |
|
901 |
});
|
| - |
|
902 |
$(document).on('change', '.r-av-party-chk', rUpdateAvSelectedCount);
|
| - |
|
903 |
|
| - |
|
904 |
$(document).on('click', '#rAvApplyAgenda', function () {
|
| - |
|
905 |
var defValues = $('#rAvDefaultAgenda').val() || [];
|
| - |
|
906 |
if (defValues.length === 0) {
|
| - |
|
907 |
alert('Pick at least one agenda above first');
|
| - |
|
908 |
return;
|
| - |
|
909 |
}
|
| - |
|
910 |
$('.r-av-party-chk:checked').each(function () {
|
| - |
|
911 |
var fid = $(this).data('fofoid');
|
| - |
|
912 |
var $sel = $('.r-av-party-agenda[data-fofoid="' + fid + '"]');
|
| - |
|
913 |
var existing = $sel.val() || [];
|
| - |
|
914 |
var merged = existing.slice();
|
| - |
|
915 |
defValues.forEach(function (v) {
|
| - |
|
916 |
if (merged.indexOf(v) === -1) merged.push(v);
|
| - |
|
917 |
});
|
| - |
|
918 |
$sel.val(merged);
|
| - |
|
919 |
try {
|
| - |
|
920 |
$sel.multiselect('refresh');
|
| - |
|
921 |
} catch (e) {
|
| - |
|
922 |
}
|
| - |
|
923 |
});
|
| - |
|
924 |
});
|
| - |
|
925 |
|
| - |
|
926 |
$(document).on('click', '#rAvSubmit', function () {
|
| - |
|
927 |
var picks = [];
|
| - |
|
928 |
var missing = 0;
|
| - |
|
929 |
$('.r-av-party-chk:checked').each(function () {
|
| - |
|
930 |
var fid = parseInt($(this).data('fofoid'));
|
| - |
|
931 |
var agendas = $('.r-av-party-agenda[data-fofoid="' + fid + '"]').val() || [];
|
| - |
|
932 |
var description = ($('.r-av-party-desc[data-fofoid="' + fid + '"]').val() || '').trim();
|
| - |
|
933 |
if (agendas.length === 0) missing++;
|
| - |
|
934 |
picks.push({
|
| - |
|
935 |
fofoStoreId: fid,
|
| - |
|
936 |
outletName: $(this).data('name'),
|
| - |
|
937 |
latitude: $(this).data('lat') ? String($(this).data('lat')) : null,
|
| - |
|
938 |
longitude: $(this).data('lng') ? String($(this).data('lng')) : null,
|
| - |
|
939 |
agendas: agendas,
|
| - |
|
940 |
description: description
|
| - |
|
941 |
});
|
| - |
|
942 |
});
|
| - |
|
943 |
if (picks.length === 0) return;
|
| - |
|
944 |
if (missing > 0) {
|
| - |
|
945 |
if (!confirm(missing + ' selected row(s) have no agenda. Submit anyway with default "Visit"?')) return;
|
| - |
|
946 |
}
|
| - |
|
947 |
var btn = $(this);
|
| - |
|
948 |
btn.prop('disabled', true).text('Assigning...');
|
| - |
|
949 |
$('#rAvMsg').text('');
|
| - |
|
950 |
$.ajax({
|
| - |
|
951 |
url: context + '/beatPlan/assignVisit/submit',
|
| - |
|
952 |
type: 'POST',
|
| - |
|
953 |
contentType: 'application/json',
|
| - |
|
954 |
data: JSON.stringify({
|
| - |
|
955 |
authUserId: rAvContext.authUserId,
|
| - |
|
956 |
planDate: rAvContext.date,
|
| - |
|
957 |
parties: picks
|
| - |
|
958 |
}),
|
| - |
|
959 |
success: function (r) {
|
| - |
|
960 |
var d = r.response || r;
|
| - |
|
961 |
$('#rAvMsg').html('<span style="color:#2e7d32;">' + (d.message || 'Saved') + '</span>');
|
| - |
|
962 |
btn.prop('disabled', false).text('Save Assignments');
|
| - |
|
963 |
setTimeout(function () {
|
| - |
|
964 |
$('#rAssignVisitModal').modal('hide');
|
| - |
|
965 |
}, 1500);
|
| - |
|
966 |
},
|
| - |
|
967 |
error: function (xhr) {
|
| - |
|
968 |
var msg = 'Failed';
|
| - |
|
969 |
try {
|
| - |
|
970 |
msg = (JSON.parse(xhr.responseText).response.message) || msg;
|
| - |
|
971 |
} catch (e) {
|
| - |
|
972 |
}
|
| - |
|
973 |
$('#rAvMsg').html('<span style="color:#c62828;">' + msg + '</span>');
|
| - |
|
974 |
btn.prop('disabled', false).text('Save Assignments');
|
| - |
|
975 |
}
|
| - |
|
976 |
});
|
| - |
|
977 |
});
|
| - |
|
978 |
</script>
|
| - |
|
979 |
|
| - |
|
980 |
<!-- Assign Visit Modal (mirrors Beat Day View; prefixed IDs to avoid collisions) -->
|
| - |
|
981 |
<div class="modal fade" id="rAssignVisitModal" tabindex="-1" style="overflow-y:auto;">
|
| - |
|
982 |
<div class="modal-dialog" style="width:90%; max-width:900px; margin-top:30px;">
|
| - |
|
983 |
<div class="modal-content">
|
| - |
|
984 |
<div class="modal-header">
|
| - |
|
985 |
<button type="button" class="close" data-dismiss="modal">×</button>
|
| - |
|
986 |
<h4 class="modal-title" id="rAvTitle">Assign Visit</h4>
|
| - |
|
987 |
</div>
|
| - |
|
988 |
<div class="modal-body">
|
| - |
|
989 |
<div style="display:flex; gap:10px; align-items:flex-start; margin-bottom:10px;">
|
| - |
|
990 |
<div style="flex:1;">
|
| - |
|
991 |
<label style="font-size:11px; color:#666; font-weight:normal; margin-bottom:2px;">
|
| - |
|
992 |
Agenda - applies to selected rows
|
| - |
|
993 |
</label>
|
| - |
|
994 |
<select id="rAvDefaultAgenda" multiple></select>
|
| - |
|
995 |
</div>
|
| - |
|
996 |
<button type="button" class="btn btn-default btn-sm" id="rAvApplyAgenda" style="margin-top:18px;"
|
| - |
|
997 |
title="Add the picked agendas into all selected rows (merges with existing)">
|
| - |
|
998 |
Apply to Selected
|
| - |
|
999 |
</button>
|
| - |
|
1000 |
</div>
|
| - |
|
1001 |
<div style="display:flex; gap:10px; align-items:center; margin-bottom:10px;">
|
| - |
|
1002 |
<input type="text" id="rAvSearch" class="form-control input-sm"
|
| - |
|
1003 |
placeholder="Search by code, outlet name or city..." style="flex:1;">
|
| - |
|
1004 |
<span id="rAvSelectedCount" style="font-size:12px; color:#666;">0 selected</span>
|
| - |
|
1005 |
</div>
|
| - |
|
1006 |
<div id="rAvPartyList"
|
| - |
|
1007 |
style="max-height:50vh; overflow-y:auto; border:1px solid #e5e5e5; border-radius:4px;"></div>
|
| - |
|
1008 |
<div id="rAvMsg" style="margin-top:10px; font-size:12px;"></div>
|
| - |
|
1009 |
</div>
|
| - |
|
1010 |
<div class="modal-footer">
|
| - |
|
1011 |
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
| - |
|
1012 |
<button type="button" class="btn btn-success" id="rAvSubmit" disabled>Save Assignments</button>
|
| - |
|
1013 |
</div>
|
| - |
|
1014 |
</div>
|
| - |
|
1015 |
</div>
|
| - |
|
1016 |
</div>
|