Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WooCommerce customer order detail in BS Modal

In a WordPress website running WooCommerce, the user can login in his (default) personal area and display information like:

  • Orders history
  • Download
  • Addresses
  • Edit info
  • Logout

In the orders tab, a table is presented by default, showing a list of all orders, with a View button which redirects to the full detail page of that order.

What I'm trying to do is showing that table view in a modal window.

I don't have any problem in showing the modal with the target url loaded in it. The real problem is that the targeted url is that of the full page which is showing like in an <iframe>, and is not what I want.

I think there is some shortcode allowing to load just that table, or maybe some woocommerce function like load_order_content_by_id($id)?

Can anybody point me in the right direction?

Thanks

===SOLVED===

Thanks to Raunak Gupta for pointing me to the right function. I override the orders.php template, added Modal window html and edited $actions:

'view'   => array(
    'url'  => 'javascript:;',
    'data' => [
        'order-number' => $order->get_order_number()
    ],
    'name' => __( 'View', 'woocommerce' )
),

and on same file:

foreach ( $actions as $key => $action ) {
    echo '<a href="' . esc_url( $action['url'] ) . '" class="button ' . sanitize_html_class( $key ) . '"';
    if(isset($action['data']) && is_array($action['data'])){
        foreach($action['data'] AS $data_attr=>$data_value){
            echo 'data-' . sanitize_html_class($data_attr) .'="' .esc_html($data_value) . '" ';
        }
    }
    echo '>' . esc_html( $action['name'] ) . '</a>';
}

A little JS

$('.woocommerce-MyAccount-orders .button.view').on('click', function(e){
    e.preventDefault();
    var data = {};
    data.action = 'modal_order';
    data.order_number = $(this).data('order-number');

    $.get( ajax_script.ajax_url, data, function(response) {
        $('#modalOrderDetail').modal('show').find('.modal-body').html(response);
    });
});

and hooked into wordpress by function.php

function modal_order() {
    if(is_user_logged_in()) {
        $order_number = $_GET['order_number'];
        woocommerce_order_details_table($order_number);
    }
}

add_action('wp_ajax_modal_order', 'modal_order');
add_action('wp_ajax_nopriv_modal_order', 'modal_order');
like image 698
Yuri Avatar asked Aug 22 '16 00:08

Yuri


People also ask

How do I find the last order ID in WooCommerce?

php $latest_order_id = get_last_order_id(); // Last order ID $order = wc_get_order( $latest_order_id ); // Get an instance of the WC_Order object $order_details = $order->get_data(); // Get the order data in an array $order_status = esc_html( wc_get_order_status_name( $order->get_status() ) ); $order_items = $ ...


Video Answer


1 Answers

Here is the complete code to display curent customer orders in a modal window. Its based on a classic query to get current user orders and on the template my-account/orders.php (lightly customized)

<?php

if(is_user_logged_in()):

    // The query
    $args = array(
        // WC orders post type
        'post_type'   => 'shop_order',
        'numberposts' => -1,
        // for current user id
        'meta_key'    => '_customer_user',
        'meta_value'  => get_current_user_id(),
        // get orders statuses
        'post_status' => array_keys(wc_get_order_statuses()),
    );

    // Get all customer orders
    $customer_orders = get_posts( $args );
    $count_ord = 0;
    if (!empty($customer_orders))
        foreach ( $customer_orders as $custo_order )
            $count_ord++;

    if ( $count_ord > 0 )
        $has_orders = true;
    else
        $has_orders = false;

    // the template my-account/orders.php  ?>

    <?php do_action( 'woocommerce_before_account_orders', $has_orders ); ?>

    <?php if ( $has_orders ) : ?>

    <table class="woocommerce-MyAccount-orders shop_table shop_table_responsive my_account_orders account-orders-table">
        <thead>
            <tr>
                <?php foreach ( wc_get_account_orders_columns() as $column_id => $column_name ) : ?>
                    <th class="<?php echo esc_attr( $column_id ); ?>"><span class="nobr"><?php echo esc_html( $column_name ); ?></span></th>
                <?php endforeach; ?>
            </tr>
        </thead>

        <tbody>
            <?php foreach ( $customer_orders as $customer_order ) :
                $order      = wc_get_order( $customer_order );
                $item_count = $order->get_item_count();
                ?>
                <tr class="order">
                    <?php foreach ( wc_get_account_orders_columns() as $column_id => $column_name ) : ?>
                        <td class="<?php echo esc_attr( $column_id ); ?>" data-title="<?php echo esc_attr( $column_name ); ?>">
                            <?php if ( has_action( 'woocommerce_my_account_my_orders_column_' . $column_id ) ) : ?>
                                <?php do_action( 'woocommerce_my_account_my_orders_column_' . $column_id, $order ); ?>

                            <?php elseif ( 'order-number' === $column_id ) : ?>
                                <a href="<?php echo esc_url( $order->get_view_order_url() ); ?>">
                                    <?php echo _x( '#', 'hash before order number', 'woocommerce' ) . $order->get_order_number(); ?>
                                </a>

                            <?php elseif ( 'order-date' === $column_id ) : ?>
                                <time datetime="<?php echo date( 'Y-m-d', strtotime( $order->order_date ) ); ?>" title="<?php echo esc_attr( strtotime( $order->order_date ) ); ?>"><?php echo date_i18n( get_option( 'date_format' ), strtotime( $order->order_date ) ); ?></time>

                            <?php elseif ( 'order-status' === $column_id ) : ?>
                                <?php echo wc_get_order_status_name( $order->get_status() ); ?>

                            <?php elseif ( 'order-total' === $column_id ) : ?>
                                <?php echo sprintf( _n( '%s for %s item', '%s for %s items', $item_count, 'woocommerce' ), $order->get_formatted_order_total(), $item_count ); ?>

                            <?php elseif ( 'order-actions' === $column_id ) : ?>
                                <?php
                                    $actions = array(
                                        'pay'    => array(
                                            'url'  => $order->get_checkout_payment_url(),
                                            'name' => __( 'Pay', 'woocommerce' )
                                        ),
                                        'view'   => array(
                                            'url'  => $order->get_view_order_url(),
                                            'name' => __( 'View', 'woocommerce' )
                                        ),
                                        'cancel' => array(
                                            'url'  => $order->get_cancel_order_url( wc_get_page_permalink( 'myaccount' ) ),
                                            'name' => __( 'Cancel', 'woocommerce' )
                                        )
                                    );

                                    if ( ! $order->needs_payment() ) {
                                        unset( $actions['pay'] );
                                    }

                                    if ( ! in_array( $order->get_status(), apply_filters( 'woocommerce_valid_order_statuses_for_cancel', array( 'pending', 'failed' ), $order ) ) ) {
                                        unset( $actions['cancel'] );
                                    }

                                    if ( $actions = apply_filters( 'woocommerce_my_account_my_orders_actions', $actions, $order ) ) {
                                        foreach ( $actions as $key => $action ) {
                                            echo '<a href="' . esc_url( $action['url'] ) . '" class="button ' . sanitize_html_class( $key ) . '">' . esc_html( $action['name'] ) . '</a>';
                                        }
                                    }
                                ?>
                            <?php endif; ?>
                        </td>
                    <?php endforeach; ?>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>

    <?php do_action( 'woocommerce_before_account_orders_pagination' ); ?>

    <?php if ( 1 < $customer_orders->max_num_pages ) : ?>
        <div class="woocommerce-Pagination">
            <?php if ( 1 !== $current_page ) : ?>
                <a class="woocommerce-Button woocommerce-Button--previous button" href="<?php echo esc_url( wc_get_endpoint_url( 'orders', $current_page - 1 ) ); ?>"><?php _e( 'Previous', 'woocommerce' ); ?></a>
            <?php endif; ?>

            <?php if ( $current_page !== intval( $customer_orders->max_num_pages ) ) : ?>
                <a class="woocommerce-Button woocommerce-Button--next button" href="<?php echo esc_url( wc_get_endpoint_url( 'orders', $current_page + 1 ) ); ?>"><?php _e( 'Next', 'woocommerce' ); ?></a>
            <?php endif; ?>
        </div>
    <?php endif; ?>

<?php else : ?>
    <div class="woocommerce-Message woocommerce-Message--info woocommerce-info">
        <a class="woocommerce-Button button" href="<?php echo esc_url( apply_filters( 'woocommerce_return_to_shop_redirect', wc_get_page_permalink( 'shop' ) ) ); ?>">
            <?php _e( 'Go Shop', 'woocommerce' ) ?>
        </a>
<?php endif; ?>
        <?php _e( 'No order has been made yet.', 'woocommerce' ); ?>
    </div>

<?php do_action( 'woocommerce_after_account_orders', $has_orders ); ?>

<?php endif; ?>

You will have to add existing css rules to your modal window and/or customized that css rules.

This code is tested and fully functional.

like image 64
LoicTheAztec Avatar answered Oct 09 '22 22:10

LoicTheAztec