Subversion Repositories SmartDukaan

Rev

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

Rev 36736 Rev 36761
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','');">&times;
-
 
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, '&quot;');
-
 
823
            var existingDesc = (p.existingDescription || '').replace(/"/g, '&quot;');
-
 
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">&times;</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>