Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Omar_Hamwi's avatar

Bulk Edit in Yajra Datatables and larave

hey so i have a laravel project that displays the data using yajra datatables in the table i have multiple select buttons what i want to do is to select multiple rows an edit them at the same time how can i do that this is my blade file

<x-app-layout>
    <x-slot name="header">
        <h2 class="text-2xl font-semibold leading-tight text-gray-800">
            {{ __('Followup') }}
        </h2>
    </x-slot>

    <div class="py-12">
        <div class="mx-auto px-4 sm:px-6 lg:px-8">
            <!-- Removed max-w-7xl to allow the table to grow wider -->
            <div class="bg-white shadow rounded-lg p-6">
                {{-- <button id="show-chart" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Show
                    Discount Codes
                    Chart</button> --}}
                <div class="overflow-x-auto rounded-lg">
                    <table id="orders-table"
                        class="hover row-border min-w-full divide-y divide-gray-500 shadow overflow-hidden border-b border-gray-500 sm:rounded-lg">
                        <thead class="bg-gray-200">
                            <tr>
                                <th scope="col" class="text-center uppercase" style="width: 100px;">
                                    Order Number
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 150px;">
                                    Customer Name
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 150px;">
                                    Customer Phone
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 100px;">
                                    City
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 150px;">
                                    Order Date
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 100px;">
                                    Discount Code
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 200px;">
                                    Special Items
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 100px;">
                                    FollowUp Date
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 100px;">
                                    Contact Employee
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 100px;">
                                    Customer Responded ?
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 100px;">
                                    Custome Note
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 100px;">
                                    Routine Satisfaction
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 100px;">
                                    Problem Reason
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 100px;">
                                    Problem Solution
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 100px;">
                                    Different Number Repeat
                                </th>
                                <th scope="col" class="text-center uppercase" style="width: 100px;">
                                    Repeat After FollowUp
                                </th>
                            </tr>
                        </thead>
                    </table>
                </div>
            </div>
        </div>
    </div>

</x-app-layout>


<link rel="stylesheet" href="https://cdn.datatables.net/1.13.7/css/jquery.dataTables.min.css">
<link rel="stylesheet" href="https://cdn.datatables.net/buttons/2.4.2/css/buttons.dataTables.min.css">
<link rel="stylesheet" href="https://cdn.datatables.net/fixedheader/3.1.9/css/fixedHeader.dataTables.min.css">
<link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.9/css/responsive.dataTables.min.css">
<link rel="stylesheet" href="https://cdn.datatables.net/searchbuilder/1.6.0/css/searchBuilder.dataTables.min.css">
<link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" rel="stylesheet">

<script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
<script src="https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.2/js/dataTables.buttons.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.colVis.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.html5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.print.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js"></script>
<script src="https://cdn.datatables.net/fixedheader/3.1.9/js/dataTables.fixedHeader.min.js"></script>
<script src="https://cdn.datatables.net/responsive/2.2.9/js/dataTables.responsive.min.js"></script>
<script src="https://cdn.datatables.net/searchbuilder/1.6.0/js/dataTables.searchBuilder.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>



<!-- Initialize DataTables -->
<script>
    $(document).ready(function() {
        var table = $('#orders-table').DataTable({
            processing: true,
            serverSide: true,
            // fixedHeader: true,
            // responsive: true,
            scrollX: true,
            ajax: {
                url: "{{ route('orders.followup-data') }}",
                data: function(d) {
                    d.startDate = $('#start-date').val();
                    d.endDate = $('#end-date').val();
                    d.selectedColumn = $('#column-select').val();
                }
            },
            columns: [{
                    data: 'order_number',
                    name: 'order_number'
                },
                {
                    data: 'customer_name',
                    name: 'customer_name'
                },
                {
                    data: 'customer_phone',
                    name: 'customer_phone'
                },
                {
                    data: 'city',
                    name: 'city'
                },
                {
                    data: 'order_date',
                    name: 'order_date'
                },
                {
                    data: 'discount_code',
                    name: 'discount_code'
                },
                {
                    data: 'special_items',
                    name: 'special_items'
                },
                {
                    data: 'follow_up_date',
                    name: 'follow_up_date'
                },
                {
                    data: 'contact_employee',
                    name: 'contact_employee',
                    render: function(data, type, row) {
                        return `
                            <select class="contact_employee-dropdown w-40 rounded-lg bg-gray-50 border border-gray-300 text-gray-700 py-2 px-4 leading-tight focus:outline-none focus:bg-white focus:border-blue-500" data-id="${row.id}" style="font-size: 14px;">
                                <option value="">Select Employee</option>
                                <option value="manar" ${data === 'manar' ? 'selected' : ''}>Manar</option>
                                <option value="hiba" ${data === 'hiba' ? 'selected' : ''}>Hiba</option>
                                <option value="ranim" ${data === 'ranim' ? 'selected' : ''}>Ranim</option>
                                <option value="marwa" ${data === 'marwa' ? 'selected' : ''}>Marwa</option>
                            </select>
                        `;
                    }
                },
                {
                    data: 'customer_responded',
                    name: 'customer_responded',
                    render: function(data, type, row) {
                        return `
                            <select class="customer_responded-dropdown w-40 rounded-lg bg-gray-50 border border-gray-300 text-gray-700 py-2 px-4 leading-tight focus:outline-none focus:bg-white focus:border-blue-500" data-id="${row.id}" style="font-size: 14px;">
                                <option value="">Select an option</option>
                                <option value="yes" ${data === 'yes' ? 'selected' : ''}>Yes</option>
                                <option value="no" ${data === 'no' ? 'selected' : ''}>No</option>
                            </select>
                        `;
                    }
                },
                {
                    data: 'action',
                    name: 'action',
                    orderable: false,
                    searchable: false,
                    render: function(data, type, row) {
                        return `
                            <button class="edit-modal-button bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" data-id="${row.id}" onclick="openModal(${row.id})">Edit</button>
                        `;
                    }
                },
                {
                    data: 'routine_satisfaction',
                    name: 'routine_satisfaction',
                    render: function(data, type, row) {
                        return `
                            <select class="routine_satisfaction-dropdown w-40 rounded-lg bg-gray-50 border border-gray-300 text-gray-700 py-2 px-4 leading-tight focus:outline-none focus:bg-white focus:border-blue-500" data-id="${row.id}" style="font-size: 14px;">
                                <option value="">Satisfaction Level</option>
                                <option value="bad" ${data === 'bad' ? 'selected' : ''}>Bad</option>
                                <option value="good" ${data === 'good' ? 'selected' : ''}>Good</option>
                                <option value="perfect" ${data === 'perfect' ? 'selected' : ''}>Perfect</option>
                            </select>
                        `;
                    }
                },
                {
                    data: 'problem_reason',
                    name: 'problem_reason',
                    render: function(data, type, row) {
                        return `
                            <select class="problem_reason-dropdown w-40 rounded-lg bg-gray-50 border border-gray-300 text-gray-700 py-2 px-4 leading-tight focus:outline-none focus:bg-white focus:border-blue-500" data-id="${row.id}" style="font-size: 14px;">
                                <option value="">Select a reason</option>
                                <option value="allergy_from_product" ${data === 'allergy_from_product' ? 'selected' : ''}>Allergy From Product</option>
                                <option value="not_enough_routine" ${data === 'not_enough_routine' ? 'selected' : ''}>Not Enough Routine</option>
                                <option value="wrong_usage" ${data === 'wrong_usage' ? 'selected' : ''}>Wrong Usage</option>
                                <option value="lack_of_commitment" ${data === 'lack_of_commitment' ? 'selected' : ''}>Lack Of Commitment</option>
                                <option value="wrong_routine" ${data === 'wrong_routine' ? 'selected' : ''}>Wrong Routine</option>
                            </select>
                        `;
                    }
                },
                {
                    data: 'problem_solution',
                    name: 'problem_solution',
                    render: function(data, type, row) {
                        return `<button onclick="openProblemSolutionModal(${row.id}, '${data}')" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Edit</button>`;
                    }
                },

                {
                    data: 'different_number_repeat',
                    name: 'different_number_repeat',
                    render: function(data, type, row) {
                        return `
                            <select class="different_number_repeat-dropdown w-40 rounded-lg bg-gray-50 border border-gray-300 text-gray-700 py-2 px-4 leading-tight focus:outline-none focus:bg-white focus:border-blue-500" data-id="${row.id}" style="font-size: 14px;">
                                <option value="">Select an option</option>
                                <option value="yes" ${data === 'yes' ? 'selected' : ''}>Yes</option>
                                <option value="no" ${data === 'no' ? 'selected' : ''}>No</option>
                            </select>
                        `;
                    }
                },
                {
                    data: 'repeat_after_follow_up',
                    name: 'repeat_after_follow_up',
                    render: function(data, type, row) {
                        return `
                            <select class="repeat_after_follow_up-dropdown w-40 rounded-lg bg-gray-50 border border-gray-300 text-gray-700 py-2 px-4 leading-tight focus:outline-none focus:bg-white focus:border-blue-500" data-id="${row.id}" style="font-size: 14px;">
                                <option value="">Select an option</option>
                                <option value="yes" ${data === 'yes' ? 'selected' : ''}>Yes</option>
                                <option value="no" ${data === 'no' ? 'selected' : ''}>No</option>
                            </select>
                        `;
                    }

                },
            ],
            dom: "<'row'<'col-sm-12 col-md-6'B><'col-sm-12 col-md-6'f>>" +
                "<'row'<'col-sm-12'tr>>" +
                "<'row'<'col-sm-12 col-md-4'l><'col-sm-12 col-md-4'i><'col-sm-12 col-md-4'p>>",

            buttons: [{
                    extend: 'collection',
                    text: 'Export',
                    className: 'bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded',
                    buttons: [
                        'copy',
                        'csv',
                        'excel',
                        'pdf',
                        'print',
                    ]

                },
                {
                    extend: 'colvis',
                    className: 'bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded',
                    text: 'Column visibility'
                },
                {
                    text: 'Filters',
                    className: 'bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded',
                    action: function(e, dt, node, config) {
                        openFilterModal();
                    }
                }
            ],
        });


        // Custom event listener for opening the column visibility dropdown
        table.on('buttons-action', function(e, buttonApi, dataTable, node, config) {
            // Check if the button that triggered the action is ColVis
            if (config.className.indexOf('colvis') !== -1) {
                // Wait until the dropdown is actually created
                setTimeout(function() {
                    // Apply max height and overflow to the dropdown for scrolling
                    $('.dt-button-collection').css({
                        'max-height': '200px', // or 'max-h-60' in Tailwind (Tailwind's max-h-60 class must be available in your CSS build)
                        'overflow-y': 'auto'
                    });
                }, 50); // Adjust timeout if necessary
            }
        });

        $(document).on('change', 'select', function() {
            var orderId = $(this).data('id');
            var column = $(this).attr('class').split('-')[0]; // Gets 'packaging', 'contact', etc.
            var selectedValue = $(this).val();

            // AJAX request to update the database
            $.ajax({
                url: '/orders/followup/update-field',
                type: 'POST',
                data: {
                    id: orderId,
                    field: column,
                    value: selectedValue,
                    _token: "{{ csrf_token() }}"
                },
                success: function(response) {
                    // Here, you'll check for the notify object in the response
                    if (response.notify) {
                        // Use the notification data to display a message
                        // This depends on how you're handling notifications client-side
                        // For example, if you're using toastr.js or another notification library:
                        toastr[response.notify.type](response.notify.message);
                    }
                },
                error: function(error) {
                    toastr['error']('An error occurred.');
                }
            });
        });

        $('#filter-button').on('click', function() {
            table.ajax
                .reload(); // This will make DataTables call the server again with the new parameters
        });

        // Trigger the DataTables re-query when the clear filter button is clicked
        $('#clear-filter-button').on('click', function() {
            $('#start-date').val('');
            $('#end-date').val('');
            $('#column-select').val('');
            table.ajax.reload(); // This will clear the filters and reload the table
        });
    });

    function openModal(id) {
        // Use AJAX to fetch the current custom note
        $.ajax({
            url: `/followup/${id}/edit-custom-note`,
            type: 'GET',
            success: function(response) {
                // Populate the modal input with the current custom note
                $('#modal-input').val(response.custom_note);
                $('#customNoteModal').data('id', id); // Store the ID in the modal for later use
                $('#customNoteModal').show(); // Use the correct ID for the modal
            },
            error: function(error) {
                console.log(error);
                alert('Could not fetch the custom note');
            }
        });
    }

    function closeModal() {
        $('#customNoteModal').hide(); // Use the correct ID for the modal
    }

    function saveChanges() {
        var id = $('#customNoteModal').data('id'); // Retrieve the ID stored in the modal
        var customNote = $('#modal-input').val(); // Get the updated custom note from the modal input

        // Use AJAX to update the custom note
        $.ajax({
            url: `/followup/${id}/update-custom-note`,
            type: 'POST',
            data: {
                custom_note: customNote,
                _token: $('meta[name="csrf-token"]').attr('content'), // Include CSRF token
            },
            success: function(response) {
                alert('Custom note updated successfully.');
                $('#customNoteModal').hide(); // Use the correct ID for the modal
                // Optionally, refresh the DataTable or specific part of your page to show the updated note
            },
            error: function(error) {
                console.log(error);
                alert('Failed to update the custom note.');
            }
        });
    }


    function openProblemSolutionModal(id) {
        // Fetch the current problem solution before showing the modal
        $.ajax({
            url: `/followup/${id}/edit-problem-solution`,
            type: 'GET',
            success: function(response) {
                $('#problemSolutionInput').val(response.problem_solution);
                $('#problemSolutionModal').data('id', id).show();
            },
            error: function(error) {
                alert('Could not fetch the problem solution.');
                console.error(error);
            }
        });
    }

    function closeProblemSolutionModal() {
        $('#problemSolutionModal').hide(); // Use jQuery for consistency and target the correct ID
    }

    function saveProblemSolutionChanges() {
        var id = $('#problemSolutionModal').data('id');
        var problemSolution = $('#problemSolutionInput').val();

        $.ajax({
            url: `/followup/${id}/update-problem-solution`,
            type: 'POST',
            data: {
                problem_solution: problemSolution,
                _token: $('meta[name="csrf-token"]').attr('content'),
            },
            success: function(response) {
                alert('Problem solution updated successfully.');
                $('#problemSolutionModal').hide();
                // Optionally, refresh the DataTable or the specific row to reflect the updated data
            },
            error: function(error) {
                alert('Failed to update the problem solution.');
                console.error(error);
            }
        });
    }

    function closeChartModal() {
        document.getElementById('chartModal').classList.add('hidden');
    }

    document.addEventListener('DOMContentLoaded', function() {
        // This will ensure that the button element is available to attach the event listener
        var closeButton = document.querySelector('#chartModal .bi-x')
            .parentNode; // Get the parent button of the SVG
        closeButton.addEventListener('click', closeChartModal);
    });
</script>


<div id="chartModal" class="hidden fixed inset-0 z-50 overflow-y-auto bg-black bg-opacity-50">
    <div class="flex items-center justify-center min-h-screen">
        <div class="bg-white rounded-lg shadow-xl max-w-2xl mx-auto p-6"> <!-- Increased max-width -->
            <div class="flex justify-between items-center"> <!-- Added items-center for vertical alignment -->
                <h3 class="text-lg font-medium leading-6 text-gray-900">Discount Codes Chart</h3> <!-- Modal title -->
                <button class="text-black hover:text-gray-700 p-2 rounded-md">
                    <!-- SVG for close button -->
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor"
                        class="bi bi-x" viewBox="0 0 16 16">
                        <path
                            d="M4.646 4.646a.5.5 0 011.768.708L6.707 6.707l3.647 3.647a.5.5 0 01-.708.708l-3.647-3.647L5.354 5.354a.5.5 0 01-.708-.708z" />
                        <path
                            d="M5.354 10.354a.5.5 0 00-.708.708l3.647 3.647 3.647-3.647a.5.5 0 00-.708-.708L6.707 6.707 5.354 5.354a.5.5 0 00-.708.708z" />
                    </svg>
                </button>

            </div>
            <div class="mt-4 p-4"> <!-- Added padding -->
                <canvas id="discountCodesChart" width="400" height="400"></canvas>
                <!-- Specified width and height -->
            </div>
        </div>
    </div>
</div>


<!-- Modal -->
<div id="customNoteModal" class="fixed z-10 inset-0 overflow-y-auto hidden" aria-labelledby="modal-title" role="dialog"
    aria-modal="true">
    <div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
        <!-- Overlay -->
        <div class="fixed inset-0 bg-gray-600 bg-opacity-50 transition-opacity" aria-hidden="true"></div>

        <!-- Modal content -->
        <div
            class="inline-block align-middle bg-white rounded-2xl text-left overflow-hidden shadow-lg transform transition-all sm:max-w-lg sm:w-full">
            <!-- Close button -->
            <button type="button" onclick="closeModal()"
                class="absolute top-2 right-2 text-gray-400 hover:text-gray-500 focus:outline-none focus:text-gray-500">
                <svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"
                    xmlns="http://www.w3.org/2000/svg">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12">
                    </path>
                </svg>
            </button>

            <div class="bg-white px-6 pt-5 pb-4 sm:p-6 sm:pb-4">
                <div class="sm:flex sm:items-start">
                    <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left w-full">
                        <h3 class="text-xl leading-6 font-semibold text-gray-900 mb-4" id="modal-title">Edit Custom
                            Note
                        </h3>
                        <!-- Modal Body -->
                        <div class="mt-2">
                            <!-- Form inputs here -->
                            <textarea type="text" id="modal-input"
                                class="form-textarea mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring focus:ring-indigo-500 focus:ring-opacity-50 text-lg py-3"
                                placeholder="Type your note here..."></textarea>
                        </div>
                    </div>
                </div>
            </div>
            <div class="bg-gray-100 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
                <button type="button" onclick="saveChanges()"
                    class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">Save</button>
                <button type="button" onclick="closeModal()"
                    class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">Cancel</button>
            </div>
        </div>
    </div>
</div>

<!-- Modal Structure (hidden by default) -->
<div id="addNotesModal" class="hidden fixed inset-0 z-50 overflow-y-auto bg-black bg-opacity-50">
    <div class="flex items-center justify-center min-h-screen px-4 py-6">
        <div class="w-full max-w-lg p-6 bg-white rounded-lg shadow-xl">
            <div class="flex items-center justify-between mb-4">
                <h3 class="text-xl font-semibold text-gray-900">Add Note</h3>
                <button onclick="closeModal()" class="rounded hover:bg-gray-200 focus:outline-none">
                    <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"
                        xmlns="https://www.w3.org/2000/svg">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                            d="M6 18L18 6M6 6l12 12">
                        </path>
                    </svg>
                </button>
            </div>
            <div id="modal-content" class="space-y-4">
                <!-- The modal content will be loaded dynamically with the form -->
            </div>
            <div class="flex justify-end pt-2 border-t">
                <button onclick="closeModal()"
                    class="px-4 py-2 text-white bg-blue-500 rounded hover:bg-blue-700 focus:outline-none">Close</button>
            </div>
        </div>
    </div>
</div>



<!-- Problem Solution Modal -->
<div id="problemSolutionModal" class="fixed inset-0 z-10 hidden overflow-y-auto" aria-labelledby="modal-title"
    role="dialog" aria-modal="true">
    <div class="flex items-end justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
        <div class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" aria-hidden="true"></div>

        <div
            class="inline-block overflow-hidden text-left align-bottom transition-all transform bg-white rounded-lg shadow-xl sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
            <div class="px-4 pt-5 pb-4 bg-white sm:p-6 sm:pb-4">
                <div class="sm:flex sm:items-start">
                    <div class="w-full mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
                        <h3 class="text-lg font-medium leading-6 text-gray-900" id="modal-title">Edit Problem Solution
                        </h3>
                        <div class="mt-2">
                            <input type="text" id="problemSolutionInput"
                                class="w-full px-3 py-2 mt-1 text-lg leading-tight text-gray-700 border rounded shadow appearance-none focus:outline-none focus:shadow-outline"
                                placeholder="Enter problem solution">
                        </div>
                    </div>
                </div>
            </div>
            <div class="px-4 py-3 bg-gray-50 sm:px-6 sm:flex sm:flex-row-reverse">
                <button type="button" onclick="saveProblemSolutionChanges()"
                    class="inline-flex justify-center w-full px-4 py-2 text-base font-medium text-white bg-blue-600 border border-transparent rounded-md shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">Save</button>
                <button type="button" onclick="$('#problemSolutionModal').hide()"
                    class="inline-flex justify-center w-full px-4 py-2 mt-3 text-base font-medium text-gray-700 bg-white border border-gray-300 rounded-md shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">Cancel</button>
            </div>
        </div>
    </div>
</div>


<div id="filterModal" class="hidden fixed inset-0 z-50 overflow-y-auto bg-black bg-opacity-50">
    <div class="flex items-center justify-center min-h-screen">
        <div class="bg-white rounded-lg shadow-xl max-w-lg mx-auto p-6">
            <div class="flex justify-end">
                <button onclick="closeFilterModal()" class="text-black hover:text-gray-700">
                    <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"
                        xmlns="https://www.w3.org/2000/svg">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                            d="M6 18L18 6M6 6l12 12">
                        </path>
                    </svg>
                </button>
            </div>
            <div class="space-y-4">
                <div>
                    <label for="start-date" class="block text-sm font-medium text-gray-700">Start Date:</label>
                    <input type="date" id="start-date" name="start-date"
                        class="mt-1 form-input block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
                </div>
                <div>
                    <label for="end-date" class="block text-sm font-medium text-gray-700">End Date:</label>
                    <input type="date" id="end-date" name="end-date"
                        class="mt-1 form-input block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
                </div>
                <div>
                    <label for="column-select" class="block text-sm font-medium text-gray-700">Select Column:</label>
                    <select id="column-select" name="column-select"
                        class="mt-1 form-select block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
                        <!-- Add options for column selection here -->
                        <option value="order_date">Order Date</option>
                        <option value="follow_up_date">FollowUp Date</option>
                    </select>
                </div>
                <div class="flex justify-between">
                    <button id="filter-button"
                        class="px-4 py-2 text-white bg-blue-500 rounded hover:bg-blue-700 focus:outline-none">Filter</button>
                    <button id="clear-filter-button"
                        class="px-4 py-2 text-white bg-red-500 rounded hover:bg-red-700 focus:outline-none">Clear
                        Filter</button>
                </div>
            </div>
        </div>
    </div>
</div>


<script>
    function openFilterModal() {
        // Code to display the filter modal
        document.getElementById('filterModal').classList.remove('hidden');
    }

    function closeFilterModal() {
        document.getElementById('filterModal').classList.add('hidden');
    }
</script>

<script>
    // Configure toastr options
    toastr.options = {
        "closeButton": true, // Show close button
        "debug": false,
        "newestOnTop": false,
        "progressBar": true, // Show progress bar
        "positionClass": "toast-top-right", // Position
        "preventDuplicates": false,
        "onclick": null,
        "showDuration": "300",
        "hideDuration": "1000",
        "timeOut": "5000", // How long the toast will display without user interaction
        "extendedTimeOut": "1000",
        "showEasing": "swing",
        "hideEasing": "linear",
        "showMethod": "fadeIn",
        "hideMethod": "fadeOut"
    };
</script>

<style>
    .dataTables_length {
        margin-top: 20px;
    }

    .dataTables_length select {
        padding: .375rem 1.75rem .375rem .75rem;
        width: 60px;
        font-size: 1rem;
        line-height: 1.5;
        border-radius: .25rem;
        border: 1px solid #ced4da;
    }

    .dataTables_info {
        float: right;
        margin-left: 1rem;
        font-size: 1rem;
    }

    .dataTables_wrapper .row {
        clear: both;
    }
</style>

and this is my controller


class FollowUpController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index()
    {
        return view('followup');
    }

    public function getOrdersData(Request $request)
    {
        $orders = Follow_Up::query();

        if ($request->startDate && $request->endDate && $request->selectedColumn) {
            $orders->whereBetween($request->selectedColumn, [$request->startDate, $request->endDate]);
        }

        return DataTables::of($orders)
            // If you need to add additional columns or modify the data, you can do it here
            ->make(true);
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     */
    public function show(Follow_Up $follow_Up)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(Follow_Up $follow_Up)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, Follow_Up $follow_Up)
    {
        $orderId = $request->id;
        $field = $request->field;
        $value = $request->value;

        $order = Follow_Up::findOrFail($orderId);

        if (in_array($field, ['contact_employee', 'customer_responded', 'routine_satisfaction', 'problem_reason', 'problem_solution', 'different_number_repeat', 'repeat_after_follow_up'])) {
            $order->{$field} = $value;
            $order->save();

            // Assuming you want to use a success notification
            $message = ucfirst($field) . ' updated successfully.';
            // notify()->success($message);

            return response()->json(['message' => $message, 'notify' => ['type' => 'success', 'message' => $message]]);
        }

        return response()->json(['message' => 'Invalid field.'], 400); // Bad request
    }

    public function editCustomNote($id)
    {
        $followUp = Follow_Up::findOrFail($id);
        return response()->json(['custom_note' => $followUp->custom_note]);
    }

    public function updateCustomNote(Request $request, $id)
    {
        $request->validate([
            'custom_note' => 'required|string', // Validate as per your requirement
        ]);

        $followUp = Follow_Up::findOrFail($id);
        $followUp->custom_note = $request->custom_note;
        $followUp->save();

        return response()->json(['message' => 'Custom note updated successfully.']);
    }

    public function editProblemSolution($id)
    {
        $followUp = Follow_Up::findOrFail($id);
        return response()->json(['problem_solution' => $followUp->problem_solution]);
    }

    public function updateProblemSolution(Request $request, $id)
    {
        $request->validate(['problem_solution' => 'required|string']);

        $followUp = Follow_Up::findOrFail($id);
        $followUp->problem_solution = $request->problem_solution;
        $followUp->save();

        return response()->json(['message' => 'Problem solution updated successfully.']);
    }

    public function getDiscountCodesData()
    {
        $data = Follow_Up::select('discount_code', DB::raw('count(*) as total'))
            ->groupBy('discount_code')
            ->get();

        return response()->json($data);
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(Follow_Up $follow_Up)
    {
        //
    }
}

and this is my routes

    Route::get('/follow-up', [FollowUpController::class, 'index'])->name('followup_dashboard');
    Route::get('/orders/followup-data', [FollowUpController::class, 'getOrdersData'])->name('orders.followup-data');
    Route::post('/orders/followup/update-field', [FollowUpController::class, 'update'])->name('orders.followup.update-field');
    Route::get('/followup/{id}/edit-custom-note', [FollowUpController::class, 'editCustomNote'])->name('followup.editCustomNote');
    Route::post('/followup/{id}/update-custom-note', [FollowUpController::class, 'updateCustomNote'])->name('followup.updateCustomNote');
    Route::get('/followup/{id}/edit-problem-solution', [FollowUpController::class, 'editProblemSolution'])->name('followup.editProblemSolution');
    Route::post('/followup/{id}/update-problem-solution', [FollowUpController::class, 'updateProblemSolution'])->name('followup.updateProblemSolution');
    Route::post('/followup/filter-data', [FollowUpController::class, 'filterData'])->name('filter.followup-data');
    Route::get('/followup/discount-codes-data', [FollowUpController::class, 'getDiscountCodesData'])->name('followup.chart.data');
0 likes
1 reply

Please or to participate in this conversation.