Blame | Last modification | View Log | RSS feed
// Location Approval — drives the #bra-* DOM in beat-report-approval.vm.// Lives in /resources/js to keep Velocity's lexer off jQuery's $(/$. patterns.(function () {var ctx = (typeof context === 'string' && context) ? context : '';function fetchRows() {var from = $('#bra-from').val();var to = $('#bra-to').val();if (!from || !to) {alert('Pick a date range first');return;}$.get(ctx + '/beat-report/approval/data', {fromDate: from,toDate: to,categoryId: $('#bra-category').val(),escalationType: $('#bra-level').val()}, function (resp) {renderRows((resp && resp.rows) || []);}).fail(function () {alert('Failed to load approval list');});}function renderRows(rows) {var $tb = $('#bra-table tbody').empty();if (!rows.length) {$tb.append('<tr><td colspan="10" style="text-align:center;color:#888;padding:20px;">No off-site check-ins pending approval in this window.</td></tr>');$('#bra-select-all').prop('checked', false);updateSelectionUi();return;}rows.forEach(function (r) {var attach = r.attachment? '<a href="javascript:void(0);" class="bra-view-attach" data-src="' + r.attachment + '"><i class="fa fa-paperclip" style="color:#27ae60;"></i> view</a>': '<span style="color:#aaa;">-</span>';var typeBadge = badgeForType(r.taskType);var time = r.checkInTime ? (r.taskDate + ' ' + r.checkInTime) : r.taskDate;var mapBoth = (r.checkInLatLng && r.visitLocation)? '<br><a href="' + mapsDirUrl(r.visitLocation, r.checkInLatLng) + '" target="_blank" style="font-size:11px;"><i class="fa fa-arrows-h"></i> compare on map</a>': '';var $tr = $('<tr></tr>').append('<td><input type="checkbox" class="bra-row-check" data-id="' + r.trackingId + '"></td>').append('<td>' + escapeHtml(r.username) + '</td>').append('<td>' + escapeHtml(time) + '</td>').append('<td>' + typeBadge + '</td>').append('<td>' + escapeHtml(r.taskName || '') + '<br><small style="color:#888;">' + escapeHtml(r.address || '') + '</small></td>').append('<td>' + latLngCell(r.visitLocation, '#27ae60') + '</td>').append('<td>' + latLngCell(r.checkInLatLng, '#e67e22') + '</td>').append('<td><span class="label label-warning">' + r.distanceM + ' m</span>' + mapBoth + '</td>').append('<td>' + attach + '</td>').append('<td><button class="btn btn-xs btn-success bra-approve-one" data-id="' + r.trackingId + '"><i class="fa fa-check"></i> Approve</button></td>');$tb.append($tr);});$('#bra-select-all').prop('checked', false);updateSelectionUi();}function latLngCell(s, color) {if (!s) return '<span style="color:#aaa;">-</span>';var safe = escapeHtml(s);return '<span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:' + color + ';margin-right:6px;vertical-align:middle;"></span>'+ '<a href="https://www.google.com/maps?q=' + encodeURIComponent(s) + '" target="_blank" style="font-family:monospace;font-size:11px;">' + safe + '</a>';}function mapsDirUrl(visit, checkin) {return 'https://www.google.com/maps/dir/?api=1&origin=' + encodeURIComponent(visit) + '&destination=' + encodeURIComponent(checkin);}function badgeForType(t) {t = (t || '').toLowerCase();if (t === 'office-visit') return '<span class="label label-primary">Office</span>';if (t === 'lead') return '<span class="label label-info">Lead</span>';return '<span class="label label-default">Partner</span>';}function escapeHtml(s) {return (s == null ? '' : String(s)).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');}function selectedIds() {return $('.bra-row-check:checked').map(function () {return $(this).data('id');}).get();}function updateSelectionUi() {var ids = selectedIds();$('#bra-sel-count').text(ids.length);$('#bra-approve-selected').prop('disabled', ids.length === 0);}$('#bra-fetch').on('click', fetchRows);$(document).on('change', '#bra-select-all', function () {var on = $(this).is(':checked');$('.bra-row-check').prop('checked', on);updateSelectionUi();});$(document).on('change', '.bra-row-check', updateSelectionUi);$(document).on('click', '.bra-view-attach', function () {$('#bra-attach-img').attr('src', $(this).data('src'));$('#bra-attach-modal').modal('show');});$(document).on('click', '.bra-approve-one', function () {var $btn = $(this);var id = $btn.data('id');$btn.prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i>');$.post(ctx + '/beat-report/approve-checkin', {trackingId: id}, function () {$btn.closest('tr').fadeOut(200, function () {$(this).remove();updateSelectionUi();});}).fail(function () {alert('Approve failed');$btn.prop('disabled', false).html('<i class="fa fa-check"></i> Approve');});});$('#bra-approve-selected').on('click', function () {var ids = selectedIds();if (!ids.length) return;if (!confirm('Approve ' + ids.length + ' off-site check-in(s)?')) return;var $btn = $(this).prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> Approving...');$.post({url: ctx + '/beat-report/approve-checkin-bulk',data: $.param({trackingIds: ids}, true)}).done(function (resp) {(resp.approved || []).forEach(function (id) {$('.bra-row-check[data-id="' + id + '"]').closest('tr').remove();});if ((resp.failed || []).length) {alert(resp.failed.length + ' row(s) could not be approved');}updateSelectionUi();}).fail(function () {alert('Bulk approve failed');}).always(function () {$btn.html('<i class="fa fa-check"></i> Approve selected (<span id="bra-sel-count">0</span>)');updateSelectionUi();});});// Auto-load on first render so the head sees pending work immediately.fetchRows();})();