Subversion Repositories SmartDukaan

Rev

Rev 36690 | Rev 36710 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 36690 Rev 36709
Line 103... Line 103...
103
            #if($punchIn)
103
            #if($punchIn)
104
                <tr style="background:#d5f5e3;">
104
                <tr style="background:#d5f5e3;">
105
                    <td>--</td>
105
                    <td>--</td>
106
                    <td><strong>PUNCH IN</strong></td>
106
                    <td><strong>PUNCH IN</strong></td>
107
                    <td>$!punchIn.getTaskType()</td>
107
                    <td>$!punchIn.getTaskType()</td>
108
                    <td><span class="label label-info">PUNCHIN</span> #if($punchIn.getAttachment() && $punchIn.getAttachment() != "")<a href="https://partners.smartdukaan.com/document/$punchIn.getAttachment()" target="_blank" title="View Attachment"><i class="fa fa-paperclip" style="color:#e67e22; margin-left:5px;"></i></a>#end</td>
108
                    <td><span class="label label-info">PUNCHIN</span> #if($punchIn.getAttachment() && $punchIn.getAttachment() != "")<a href="javascript:void(0);" class="view-attachment-link" data-attachment="$punchIn.getAttachment()" data-checkin-latlng="$!punchIn.getCheckInLatLng()" data-visit-location="$!punchIn.getVisitLocation()" data-tracking-id="$punchIn.getId()" title="View Attachment"><i class="fa fa-paperclip" style="color:#e67e22; margin-left:5px;"></i></a>#end</td>
109
                    <td>$!punchIn.getAddress()</td>
109
                    <td>$!punchIn.getAddress()</td>
110
                    <td>$!punchIn.getCheckInTime()</td>
110
                    <td>$!punchIn.getCheckInTime()</td>
111
                    <td>--</td>
111
                    <td>--</td>
112
                    <td>--</td>
112
                    <td>--</td>
113
                    <td>--</td>
113
                    <td>--</td>
Line 130... Line 130...
130
                            <span class="label label-danger">$v.getMarkType()</span>
130
                            <span class="label label-danger">$v.getMarkType()</span>
131
                        #else
131
                        #else
132
                            <span class="label label-default">$!v.getMarkType()</span>
132
                            <span class="label label-default">$!v.getMarkType()</span>
133
                        #end
133
                        #end
134
                        <a href="javascript:void(0);" class="beat-history-link" data-userid="$userId" data-taskid="$v.getTaskId()" data-tasktype="$!v.getTaskType()" data-taskname="$!v.getTaskName()" title="View History" style="margin-left:5px;"><i class="fa fa-history" style="color:#3498db; font-size:14px;"></i></a>
134
                        <a href="javascript:void(0);" class="beat-history-link" data-userid="$userId" data-taskid="$v.getTaskId()" data-tasktype="$!v.getTaskType()" data-taskname="$!v.getTaskName()" title="View History" style="margin-left:5px;"><i class="fa fa-history" style="color:#3498db; font-size:14px;"></i></a>
135
                        #if($v.getAttachment() && $v.getAttachment() != "")<a href="https://partners.smartdukaan.com/document/$v.getAttachment()" target="_blank" title="View Attachment"><i class="fa fa-paperclip" style="color:#e67e22; margin-left:3px; font-size:14px;"></i></a>#end
135
                        #if($v.getAttachment() && $v.getAttachment() != "")<a href="javascript:void(0);" class="view-attachment-link" data-attachment="$v.getAttachment()" data-checkin-latlng="$!v.getCheckInLatLng()" data-visit-location="$!v.getVisitLocation()" data-tracking-id="$v.getId()" title="View Attachment"><i class="fa fa-paperclip" style="color:#e67e22; margin-left:3px; font-size:14px;"></i></a>#end
136
                    </td>
136
                    </td>
137
                    <td>$!v.getAddress()</td>
137
                    <td>$!v.getAddress()</td>
138
                    <td>$!v.getCheckInTime()</td>
138
                    <td>$!v.getCheckInTime()</td>
139
                    <td>$!v.getCheckOutTime()</td>
139
                    <td>$!v.getCheckOutTime()</td>
140
                    <td>$!v.getTimeSpent()</td>
140
                    <td>$!v.getTimeSpent()</td>
Line 147... Line 147...
147
            #if($punchOut)
147
            #if($punchOut)
148
                <tr style="background:#fadbd8;">
148
                <tr style="background:#fadbd8;">
149
                    <td>--</td>
149
                    <td>--</td>
150
                    <td><strong>PUNCH OUT</strong></td>
150
                    <td><strong>PUNCH OUT</strong></td>
151
                    <td>$!punchOut.getTaskType()</td>
151
                    <td>$!punchOut.getTaskType()</td>
152
                    <td><span class="label label-danger">PUNCHOUT</span> #if($punchOut.getAttachment() && $punchOut.getAttachment() != "")<a href="https://partners.smartdukaan.com/document/$punchOut.getAttachment()" target="_blank" title="View Attachment"><i class="fa fa-paperclip" style="color:#e67e22; margin-left:5px;"></i></a>#end</td>
152
                    <td><span class="label label-danger">PUNCHOUT</span> #if($punchOut.getAttachment() && $punchOut.getAttachment() != "")<a href="javascript:void(0);" class="view-attachment-link" data-attachment="$punchOut.getAttachment()" data-checkin-latlng="$!punchOut.getCheckInLatLng()" data-visit-location="$!punchOut.getVisitLocation()" data-tracking-id="$punchOut.getId()" title="View Attachment"><i class="fa fa-paperclip" style="color:#e67e22; margin-left:5px;"></i></a>#end</td>
153
                    <td>$!punchOut.getAddress()</td>
153
                    <td>$!punchOut.getAddress()</td>
154
                    <td>$!punchOut.getCheckInTime()</td>
154
                    <td>$!punchOut.getCheckInTime()</td>
155
                    <td>--</td>
155
                    <td>--</td>
156
                    <td>--</td>
156
                    <td>--</td>
157
                    <td>--</td>
157
                    <td>--</td>
Line 204... Line 204...
204
            <div class="modal-body" style="padding:0;">
204
            <div class="modal-body" style="padding:0;">
205
                <div id="liveTrackingInfo" style="padding:8px 15px; background:#f8f9fa; border-bottom:1px solid #ddd; font-size:13px;"></div>
205
                <div id="liveTrackingInfo" style="padding:8px 15px; background:#f8f9fa; border-bottom:1px solid #ddd; font-size:13px;"></div>
206
                <div id="liveTrackingMap" style="height:500px; width:100%;"></div>
206
                <div id="liveTrackingMap" style="height:500px; width:100%;"></div>
207
            </div>
207
            </div>
208
            <div class="modal-footer">
208
            <div class="modal-footer">
209
                <label style="float:left; margin-top:7px; font-weight:normal; font-size:13px;">
209
                #*<label style="float:left; margin-top:7px; font-weight:normal; font-size:13px;">
210
                    <input type="checkbox" id="autoRefreshToggle" checked style="margin-right:5px;"> Auto-refresh (30s)
210
                    <input type="checkbox" id="autoRefreshToggle" style="margin-right:5px;"> Auto-refresh (30s)
211
                </label>
211
                </label>*#
212
                <button type="button" class="btn btn-primary" id="refreshTrackingBtn"><i class="fa fa-refresh"></i> Refresh</button>
212
                <button type="button" class="btn btn-primary" id="refreshTrackingBtn"><i class="fa fa-refresh"></i> Refresh</button>
213
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
213
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
214
            </div>
214
            </div>
215
        </div>
215
        </div>
216
    </div>
216
    </div>
217
</div>
217
</div>
218
 
218
 
-
 
219
<!-- Attachment Viewer Modal -->
-
 
220
<div class="modal fade" id="attachmentViewerModal" tabindex="-1" role="dialog">
-
 
221
    <div class="modal-dialog" role="document" style="width:600px;">
-
 
222
        <div class="modal-content">
-
 
223
            <div class="modal-header" style="background:#e67e22; color:white;">
-
 
224
                <button type="button" class="close" data-dismiss="modal" style="color:white;">&times;</button>
-
 
225
                <h4 class="modal-title"><i class="fa fa-paperclip"></i> Attachment</h4>
-
 
226
            </div>
-
 
227
            <div class="modal-body" style="text-align:center; padding:15px;">
-
 
228
                <img id="attachmentImage" src="" style="max-width:100%; max-height:450px; border:1px solid #ddd; border-radius:4px;" />
-
 
229
                <div id="attachmentDistanceInfo" style="margin-top:10px; font-size:13px;"></div>
-
 
230
            </div>
-
 
231
            <div class="modal-footer">
-
 
232
                <button type="button" class="btn btn-success" id="approveCheckinBtn" style="display:none;">
-
 
233
                    <i class="fa fa-check"></i> Approve
-
 
234
                </button>
-
 
235
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-
 
236
            </div>
-
 
237
        </div>
-
 
238
    </div>
-
 
239
</div>
-
 
240
 
219
<script>
241
<script>
220
    $('#userDetailTable').DataTable({
242
    $('#userDetailTable').DataTable({
221
        "scrollX": true,
243
        "scrollX": true,
222
        "pageLength": 50,
244
        "pageLength": 50,
223
        "bPaginate": true,
245
        "bPaginate": true,
224
        "bLengthChange": true,
246
        "bLengthChange": true,
225
        "bFilter": true,
247
        "bFilter": true,
226
        "bInfo": true,
248
        "bInfo": true,
227
        "bAutoWidth": false
249
        "bAutoWidth": false,
-
 
250
        "ordering": false
228
    });
251
    });
229
 
252
 
230
    (function () {
253
    (function () {
231
        var level = $('#user-detail-level').data('selected');
254
        var level = $('#user-detail-level').data('selected');
232
        var selectedAuth = $('#user-detail-user').data('selected-auth');
255
        var selectedAuth = $('#user-detail-user').data('selected-auth');
Line 276... Line 299...
276
        if (markType === 'PUNCHOUT') return '#e74c3c';
299
        if (markType === 'PUNCHOUT') return '#e74c3c';
277
        return '#F4B400';
300
        return '#F4B400';
278
    }
301
    }
279
 
302
 
280
    function createTrackingMarkerIcon(color, label) {
303
    function createTrackingMarkerIcon(color, label) {
281
        var svg = '<svg xmlns="http://www.w3.org/2000/svg" width="28" height="40" viewBox="0 0 28 40">' +
304
        var svg = '<svg xmlns="http://www.w3.org/2000/svg" width="42" height="60" viewBox="0 0 42 60">' +
282
            '<path d="M14 0C6.268 0 0 6.268 0 14c0 10.5 14 26 14 26s14-15.5 14-26C28 6.268 21.732 0 14 0z" fill="' + color + '"/>' +
305
            '<path d="M21 0C9.402 0 0 9.402 0 21c0 15.75 21 39 21 39s21-23.25 21-39C42 9.402 32.598 0 21 0z" fill="' + color + '"/>' +
283
            '<circle cx="14" cy="14" r="7" fill="white"/>' +
306
            '<circle cx="21" cy="21" r="10" fill="white"/>' +
284
            '<text x="14" y="18" text-anchor="middle" font-size="10" font-weight="bold" fill="' + color + '">' + label + '</text></svg>';
307
            '<text x="21" y="26" text-anchor="middle" font-size="14" font-weight="bold" fill="' + color + '">' + label + '</text></svg>';
285
        return 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg);
308
        return 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg);
286
    }
309
    }
287
 
310
 
288
    function loadLiveTracking(userId, username) {
311
    function loadLiveTracking(userId, username) {
289
        var selectedDate = $('#user-detail-date').val();
312
        var selectedDate = $('#user-detail-date').val();
Line 430... Line 453...
430
            var marker = new google.maps.Marker({
453
            var marker = new google.maps.Marker({
431
                position: pos,
454
                position: pos,
432
                map: liveTrackingMap,
455
                map: liveTrackingMap,
433
                icon: {
456
                icon: {
434
                    url: createTrackingMarkerIcon(getMarkerColor(v.markType), label),
457
                    url: createTrackingMarkerIcon(getMarkerColor(v.markType), label),
435
                    scaledSize: new google.maps.Size(28, 40),
458
                    scaledSize: new google.maps.Size(42, 60),
436
                    anchor: new google.maps.Point(14, 40)
459
                    anchor: new google.maps.Point(21, 60)
437
                },
460
                },
438
                title: v.taskName + ' (' + v.markType + ')',
461
                title: v.taskName + ' (' + v.markType + ')',
439
                zIndex: 100
462
                zIndex: 100
440
            });
463
            });
441
 
464
 
Line 584... Line 607...
584
                    var stopMarker = new google.maps.Marker({
607
                    var stopMarker = new google.maps.Marker({
585
                        position: { lat: stop.lat, lng: stop.lng },
608
                        position: { lat: stop.lat, lng: stop.lng },
586
                        map: liveTrackingMap,
609
                        map: liveTrackingMap,
587
                        icon: {
610
                        icon: {
588
                            path: google.maps.SymbolPath.CIRCLE,
611
                            path: google.maps.SymbolPath.CIRCLE,
589
                            scale: 14,
612
                            scale: 20,
590
                            fillColor: '#f39c12',
613
                            fillColor: '#f39c12',
591
                            fillOpacity: 0.9,
614
                            fillOpacity: 0.9,
592
                            strokeColor: '#e67e22',
615
                            strokeColor: '#e67e22',
593
                            strokeWeight: 2
616
                            strokeWeight: 2
594
                        },
617
                        },
595
                        label: { text: formatDuration(stop.duration), fontSize: '9px', fontWeight: 'bold', color: '#000' },
618
                        label: { text: formatDuration(stop.duration), fontSize: '12px', fontWeight: 'bold', color: '#000' },
596
                        title: 'Stopped for ' + formatDuration(stop.duration),
619
                        title: 'Stopped for ' + formatDuration(stop.duration),
597
                        zIndex: 200
620
                        zIndex: 200
598
                    });
621
                    });
599
                    (function(marker, s) {
622
                    (function(marker, s) {
600
                        var iw = new google.maps.InfoWindow({
623
                        var iw = new google.maps.InfoWindow({
Line 617... Line 640...
617
                liveTrackingMap._currentMarker = new google.maps.Marker({
640
                liveTrackingMap._currentMarker = new google.maps.Marker({
618
                    position: lastPoint,
641
                    position: lastPoint,
619
                    map: liveTrackingMap,
642
                    map: liveTrackingMap,
620
                    icon: {
643
                    icon: {
621
                        url: '${rc.contextPath}/resources/images/Bike-Icon-SD.png',
644
                        url: '${rc.contextPath}/resources/images/Bike-Icon-SD.png',
622
                        scaledSize: new google.maps.Size(40, 40),
645
                        scaledSize: new google.maps.Size(56, 56),
623
                        anchor: new google.maps.Point(20, 20)
646
                        anchor: new google.maps.Point(28, 28)
624
                    },
647
                    },
625
                    title: 'Last Known Location',
648
                    title: 'Last Known Location',
626
                    zIndex: 999
649
                    zIndex: 999
627
                });
650
                });
628
                var lastGp = validPoints[validPoints.length - 1];
651
                var lastGp = validPoints[validPoints.length - 1];
Line 712... Line 735...
712
        document.head.appendChild(s);
735
        document.head.appendChild(s);
713
    }
736
    }
714
 
737
 
715
    var liveTrackingUsername = '';
738
    var liveTrackingUsername = '';
716
 
739
 
717
    function startAutoRefresh() {
740
    /*function startAutoRefresh() {
718
        stopAutoRefresh();
741
        stopAutoRefresh();
719
        if ($('#autoRefreshToggle').is(':checked') && liveTrackingUserId) {
742
        if ($('#autoRefreshToggle').is(':checked') && liveTrackingUserId) {
720
            liveTrackingInterval = setInterval(function () {
743
            liveTrackingInterval = setInterval(function () {
721
                loadLiveTracking(liveTrackingUserId, liveTrackingUsername);
744
                loadLiveTracking(liveTrackingUserId, liveTrackingUsername);
722
            }, 30000);
745
            }, 30000);
Line 726... Line 749...
726
    function stopAutoRefresh() {
749
    function stopAutoRefresh() {
727
        if (liveTrackingInterval) {
750
        if (liveTrackingInterval) {
728
            clearInterval(liveTrackingInterval);
751
            clearInterval(liveTrackingInterval);
729
            liveTrackingInterval = null;
752
            liveTrackingInterval = null;
730
        }
753
        }
731
    }
754
    }*/
732
 
755
 
733
    $(document).on('click.livetrack', '.live-tracking-btn', function () {
756
    $(document).on('click.livetrack', '.live-tracking-btn', function () {
734
        liveTrackingUserId = $(this).data('userid');
757
        liveTrackingUserId = $(this).data('userid');
735
        liveTrackingUsername = $(this).data('username');
758
        liveTrackingUsername = $(this).data('username');
736
        $('#liveTrackingModalTitle').html('<img src="${rc.contextPath}/resources/images/Bike-Icon-SD.png" style="height:24px; vertical-align:middle; margin-right:6px;"> Live Tracking - ' + liveTrackingUsername);
759
        $('#liveTrackingModalTitle').html('<img src="${rc.contextPath}/resources/images/Bike-Icon-SD.png" style="height:24px; vertical-align:middle; margin-right:6px;"> Live Tracking - ' + liveTrackingUsername);
Line 763... Line 786...
763
 
786
 
764
    $('#liveTrackingModal').on('hidden.bs.modal', function () {
787
    $('#liveTrackingModal').on('hidden.bs.modal', function () {
765
        stopAutoRefresh();
788
        stopAutoRefresh();
766
        liveTrackingUserId = null;
789
        liveTrackingUserId = null;
767
    });
790
    });
-
 
791
 
-
 
792
    // Attachment Viewer
-
 
793
    $(document).on('click', '.view-attachment-link', function () {
-
 
794
        var attachment = $(this).data('attachment');
-
 
795
        var checkinLatLng = $(this).data('checkin-latlng') || '';
-
 
796
        var visitLocation = $(this).data('visit-location') || '';
-
 
797
        var trackingId = $(this).data('tracking-id');
-
 
798
 
-
 
799
        var imgUrl = context + '/document/' + attachment;
-
 
800
        $('#attachmentImage').attr('src', imgUrl);
-
 
801
        $('#approveCheckinBtn').hide().removeData('tracking-id');
-
 
802
        $('#attachmentDistanceInfo').html('');
-
 
803
 
-
 
804
        var distanceM = -1;
-
 
805
        if (checkinLatLng && visitLocation && checkinLatLng.indexOf(',') > 0 && visitLocation.indexOf(',') > 0) {
-
 
806
            var cParts = checkinLatLng.toString().split(',');
-
 
807
            var vParts = visitLocation.toString().split(',');
-
 
808
            var cLat = parseFloat(cParts[0]);
-
 
809
            var cLng = parseFloat(cParts[1]);
-
 
810
            var vLat = parseFloat(vParts[0]);
-
 
811
            var vLng = parseFloat(vParts[1]);
-
 
812
            if (!isNaN(cLat) && !isNaN(cLng) && !isNaN(vLat) && !isNaN(vLng) && !(cLat === 0 && cLng === 0) && !(vLat === 0 && vLng === 0)) {
-
 
813
                distanceM = haversineMeters(cLat, cLng, vLat, vLng);
-
 
814
            }
-
 
815
        }
-
 
816
 
-
 
817
        if (distanceM > 50) {
-
 
818
            $('#attachmentDistanceInfo').html(
-
 
819
                '<span class="label label-danger" style="font-size:12px; padding:4px 10px;">' +
-
 
820
                '<i class="fa fa-exclamation-triangle"></i> Checkin Distance: ' + Math.round(distanceM) + 'm (exceeds 50m radius)</span>'
-
 
821
            );
-
 
822
            $('#approveCheckinBtn').show().data('tracking-id', trackingId);
-
 
823
        } else if (distanceM >= 0) {
-
 
824
            $('#attachmentDistanceInfo').html(
-
 
825
                '<span class="label label-success" style="font-size:12px; padding:4px 10px;">' +
-
 
826
                '<i class="fa fa-check-circle"></i> Checkin Distance: ' + Math.round(distanceM) + 'm (within 50m radius)</span>'
-
 
827
            );
-
 
828
        }
-
 
829
 
-
 
830
        $('#attachmentViewerModal').modal('show');
-
 
831
    });
-
 
832
 
-
 
833
    $(document).on('click', '#approveCheckinBtn', function () {
-
 
834
        var btn = $(this);
-
 
835
        var trackingId = btn.data('tracking-id');
-
 
836
        if (!trackingId) return;
-
 
837
 
-
 
838
        btn.prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> Approving...');
-
 
839
 
-
 
840
        $.ajax({
-
 
841
            url: context + '/beat-report/approve-checkin',
-
 
842
            type: 'POST',
-
 
843
            data: { trackingId: trackingId },
-
 
844
            success: function () {
-
 
845
                btn.html('<i class="fa fa-check"></i> Approved').removeClass('btn-success').addClass('btn-default').prop('disabled', true);
-
 
846
                alert('Checkin approved successfully');
-
 
847
            },
-
 
848
            error: function () {
-
 
849
                btn.prop('disabled', false).html('<i class="fa fa-check"></i> Approve');
-
 
850
                alert('Failed to approve checkin');
-
 
851
            }
-
 
852
        });
-
 
853
    });
768
</script>
854
</script>