How to display WooCommerce orders in a custom frontend dashboard with filters and pagination? [closed]

I’m trying to build a custom frontend dashboard (for shop managers) where they can view and filter WooCommerce orders.
Here’s what I need:

  • Display orders in a table (order number, date, status, total, customer, actions).

  • Add filters by date range and order status.

  • Add pagination (so not all orders load at once).

  • Make sure the query is optimized and doesn’t slow down the site when there are thousands of orders.

I’m currently using WC_Order_Query with paginate => true, which works, but I’m not sure if this is the best way to handle performance and scalability.

My questions are:

  • What is the most efficient way to query and display WooCommerce orders in the frontend with filters and pagination?

  • Should I use WC_Order_Query, WP_Query, or maybe a custom SQL query for better performance?

  • Any best practices to avoid slowing down the dashboard when there are many orders?

<?php
defined('ABSPATH') || exit;

if (! is_user_logged_in() || ! current_user_can('manage_woocommerce')) {
    echo '<p>Accesso negato.</p>';
    return;
}

$start_date   = isset($_GET['start_date'])   ? esc_attr($_GET['start_date'])   : '';
$end_date     = isset($_GET['end_date'])     ? esc_attr($_GET['end_date'])     : '';
$status       = isset($_GET['order_status']) ? sanitize_text_field($_GET['order_status']) : '';

$per_page     = 10;
$current_page = max(1, get_query_var('paged', isset($_GET['paged']) ? intval($_GET['paged']) : 1));

$query_args = [
    'paginate'     => true,
    'limit'        => $per_page,
    'paged'        => $current_page,
    'orderby'      => 'date',
    'order'        => 'DESC',
    'status'       => array_keys(wc_get_order_statuses()),
];

// Date filter
if ($start_date && ! $end_date) {
    $query_args['date_created'] = '>=' . $start_date;
} elseif (! $start_date && $end_date) {
    $query_args['date_created'] = '<=' . $end_date;
} elseif ($start_date && $end_date) {
    $query_args['date_created'] = $start_date . '...' . $end_date;
}

// Status filter
if (! empty($status)) {
    $query_args['status'] = $status;
}

// Run query
$orders_data = (new WC_Order_Query($query_args))->get_orders();
$orders      = $orders_data->orders;
$max_pages   = $orders_data->max_num_pages;
$has_orders  = ! empty($orders);
?>

<!-- FILTER FORM -->
<form action="#" method="get" class="woocommerce-order-filter-form form-data-filter">
    <input type="hidden" name="tab" value="orders" />
    
    From
    <input class="date-input" type="date" name="start_date" value="<?php echo esc_attr($start_date); ?>">
    To
    <input class="date-input" type="date" name="end_date"   value="<?php echo esc_attr($end_date); ?>">

    <select name="order_status" class="status-select">
        <option value=""><?php esc_html_e('All statuses', 'woocommerce'); ?></option>
        <?php foreach (wc_get_order_statuses() as $slug => $label): ?>
            <?php $pure_slug = str_replace('wc-', '', $slug); ?>
            <option value="<?php echo esc_attr($pure_slug); ?>" <?php selected($status, $pure_slug); ?>>
                <?php echo esc_html($label); ?>
            </option>
        <?php endforeach; ?>
    </select>

    <input class="date-submit" type="submit" value="<?php esc_attr_e('Filter', 'woocommerce'); ?>">
    <?php if ($start_date || $end_date || $status): ?>
        <a class="button reset" href="?tab=orders"><?php esc_html_e('Reset', 'woocommerce'); ?></a>
    <?php endif; ?>
</form>

<!-- ORDERS TABLE -->
<?php if ($has_orders): ?>
    <table class="gestore-tabella-ordini cpa-dasboard-table">
        <thead>
            <tr>
                <th>Order</th>
                <th>Date</th>
                <th>Status</th>
                <th>Total</th>
                <th>Customer</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($orders as $order): ?>
                <?php
                if (! is_a($order, 'WC_Order')) {
                    continue;
                }

                $status_code  = $order->get_status();
                $status_map   = [
                    'pending'        => ['label' => 'Pending',      'icon' => 'fa-clock'],
                    'processing'     => ['label' => 'Processing',   'icon' => 'fa-gear'],
                    'on-hold'        => ['label' => 'On hold',      'icon' => 'fa-spinner'],
                    'completed'      => ['label' => 'Completed',    'icon' => 'fa-circle-check'],
                    'cancelled'      => ['label' => 'Cancelled',    'icon' => 'fa-circle-xmark'],
                    'refunded'       => ['label' => 'Refunded',     'icon' => 'fa-arrow-rotate-left'],
                    'failed'         => ['label' => 'Failed',       'icon' => 'fa-triangle-exclamation'],
                    'checkout-draft' => ['label' => 'Draft',        'icon' => 'fa-spinner'],
                ];
                $status_data = $status_map[ $status_code ] ?? [
                    'label' => ucfirst($status_code),
                    'icon'  => 'fa-question-circle',
                ];
                ?>
                <tr class="woocommerce-orders-table__row status-<?php echo esc_attr($status_code); ?>">
                    <th scope="row">
                        <span class="order-number">#<?php echo esc_html($order->get_order_number()); ?></span>
                    </th>
                    <td>
                        <time datetime="<?php echo esc_attr($order->get_date_created()->date('c')); ?>">
                            <?php echo esc_html(wc_format_datetime($order->get_date_created())); ?>
                        </time>
                    </td>
                    <td>
                        <span class="status-text status-<?php echo esc_attr($status_code); ?>">
                            <i class="fa-solid <?php echo esc_attr($status_data['icon']); ?>"></i>
                            <?php echo esc_html($status_data['label']); ?>
                        </span>
                    </td>
                    <td>
                        <?php echo $order->get_formatted_order_total(); ?>
                    </td>
                    <td>
                        <?php echo esc_html($order->get_billing_first_name() . ' ' . $order->get_billing_last_name()); ?>
                    </td>
                    <td>
                        <a href="/dashboard/?dettaglio_ordine=<?php echo esc_attr($order->get_id()); ?>" class="cpa-btn-secondary">
                            <i class="fa-solid fa-magnifying-glass"></i>
                        </a>
                    </td>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>

    <!-- PAGINATION -->
    <?php if ($max_pages > 1): ?>
        <div class="woocommerce-pagination woocommerce-pagination--numeric woocommerce-Pagination">
            <?php
            $base_url = remove_query_arg('paged');
            ?>
            <?php if ($current_page > 1): ?>
                <a class="woocommerce-button woocommerce-button--previous button"
                   href="<?php echo esc_url(add_query_arg('paged', $current_page - 1, $base_url)); ?>">
                    &larr; Previous
                </a>
            <?php endif; ?>

            <?php for ($i = 1; $i <= $max_pages; $i++): ?>
                <?php if ($i === $current_page): ?>
                    <span class="page-number current"><?php echo $i; ?></span>
                <?php else: ?>
                    <a class="page-number" href="<?php echo esc_url(add_query_arg('paged', $i, $base_url)); ?>">
                        <?php echo $i; ?>
                    </a>
                <?php endif; ?>
            <?php endfor; ?>

            <?php if ($current_page < $max_pages): ?>
                <a class="woocommerce-button woocommerce-button--next button"
                   href="<?php echo esc_url(add_query_arg('paged', $current_page + 1, $base_url)); ?>">
                    Next &rarr;
                </a>
            <?php endif; ?>
        </div>
    <?php endif; ?>

<?php else: ?>
    <?php wc_print_notice('No orders found.', 'notice'); ?>
<?php endif; ?>