Q:

Custom WooCommerce datepicker checkout field saved and displayed on orders and emails

I have added a new custom datepicker field on the WooCommerce checkout page.
I am using Enabling a date-picker in Woocommerce checkout fields. All it's OK On checkout page.
But now I really don't know how can I save and add this new field on the order notes. Any help is appreciated.

A:

Section 1
The following will display a custom datepicker field on checkout, it will validate the field and save It.
The chosen date will be displayed on admin order, customer order and emails

To include this date on customer note, use the code from "section 2" at the end.

The code:
// Register main datepicker jQuery plugin script
add_action( 'wp_enqueue_scripts', 'enabling_date_picker' );
function enabling_date_picker() {
    // Only on front-end and checkout page
    if( is_admin() || ! is_checkout() ) return;

    // Load the datepicker jQuery-ui plugin script
    wp_enqueue_script('jquery-ui-datepicker');
    wp_enqueue_style('jquery-ui');
}

// Add custom checkout datepicker field
add_action( 'woocommerce_before_order_notes', 'checkout_display_datepicker_custom_field' );
function checkout_display_datepicker_custom_field( $checkout ) {
    $field_id = 'my_datepicker';

    echo '<div id="datepicker-wrapper">';

    woocommerce_form_field( $field_id, array(
        'type' => 'text',
        'class'=> array( 'form-row-wide'),
        'label' => __('Choose a date'),
        'required' => true, // Or false
        
    ), '' );

    echo '<br></div>';

    // Jquery: Enable the Datepicker
    ?>
    <script language="javascript">
    jQuery( function($){
        var a = '#<?php echo $field_id ?>';
        $(a).datepicker({
            dateFormat: 'dd-mm-yy', // ISO formatting date
        });
    });
    </script>
    <?php
}

// Field validation
add_action( 'woocommerce_after_checkout_validation', 'checkout_datepicker_custom_field_validation', 10, 2 );
function checkout_datepicker_custom_field_validation( $data, $errors ) {
    $field_id = 'my_datepicker';

    if ( isset($_POST[$field_id]) && empty($_POST[$field_id]) ) {
        $errors->add( 'validation', __('You must choose a date on datepicker field.', 'woocommerce') ); 
    }
}

// Save field
add_action( 'woocommerce_checkout_create_order', 'save_datepicker_custom_field_value', 10, 2 );
function save_datepicker_custom_field_value( $order, $data ){
    $field_id = 'my_datepicker';
    $meta_key = '_'.$field_id;

    if ( isset($_POST[$field_id]) && ! empty($_POST[$field_id]) ) {
        $order->update_meta_data( $meta_key, esc_attr($_POST[$field_id]) ); 
    }
}

// Display custom field value in admin order pages
add_action( 'woocommerce_admin_order_data_after_billing_address', 'admin_display_date_custom_field_value', 10, 1 );
function admin_display_date_custom_field_value( $order ) {
    $meta_key   = '_my_datepicker';
    $meta_value = $order->get_meta( $meta_key ); // Get carrier company

    if( ! empty($meta_value) ) {
        // Display
        echo '<p><strong>' . __("Date", "woocommerce") . '</strong>: ' . $meta_value . '</p>';
    }
}

// Display custom field value after shipping line everywhere (orders and emails)
add_filter( 'woocommerce_get_order_item_totals', 'display_date_custom_field_value_on_order_item_totals', 10, 3 );
function display_date_custom_field_value_on_order_item_totals( $total_rows, $order, $tax_display ){
    $field_id   = 'my_datepicker';
    $meta_key   = '_my_datepicker';
    $meta_value = $order->get_meta( $meta_key ); // Get carrier company

    if( ! empty($meta_value) ) {
        $new_total_rows = [];

        // Loop through order total rows
        foreach( $total_rows as $key => $values ) {
            $new_total_rows[$key] = $values;

            // Inserting the carrier company under shipping method
            if( $key === 'shipping' ) {
                $new_total_rows[$field_id] = array(
                    'label' => __("Date", "woocommerce") . ':',
                    'value' => $meta_value,
                );
            }
        }
        return $new_total_rows;
    }
    return $total_rows;
}

Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Section 2
To add this field to Customer order notes you will use the following instead:
// Register main datepicker jQuery plugin script
add_action( 'wp_enqueue_scripts', 'enabling_date_picker' );
function enabling_date_picker() {
    // Only on front-end and checkout page
    if( is_admin() || ! is_checkout() ) return;

    // Load the datepicker jQuery-ui plugin script
    wp_enqueue_script('jquery-ui-datepicker');
    wp_enqueue_style('jquery-ui');
}

// Add custom checkout datepicker field
add_action( 'woocommerce_before_order_notes', 'checkout_display_datepicker_custom_field' );
function checkout_display_datepicker_custom_field( $checkout ) {
    $field_id = 'my_datepicker';

    echo '<div id="datepicker-wrapper">';

    woocommerce_form_field( $field_id, array(
        'type' => 'text',
        'class'=> array( 'form-row-wide'),
        'label' => __('Choose a date'),
        'required' => true, // Or false
        
    ), '' );

    echo '<br></div>';

    // Jquery: Enable the Datepicker
    ?>
    <script language="javascript">
    jQuery( function($){
        var a = '#<?php echo $field_id ?>';
        $(a).datepicker({
            dateFormat: 'dd-mm-yy', // ISO formatting date
        });
    });
    </script>
    <?php
}

// Field validation
add_action( 'woocommerce_after_checkout_validation', 'checkout_datepicker_custom_field_validation', 10, 2 );
function checkout_datepicker_custom_field_validation( $data, $errors ) {
    $field_id = 'my_datepicker';

    if ( isset($_POST[$field_id]) && empty($_POST[$field_id]) ) {
        $errors->add( 'validation', __('You must choose a date on datepicker field.', 'woocommerce') ); 
    }
}

// Save field
add_action( 'woocommerce_checkout_create_order', 'save_datepicker_custom_field_value', 10, 2 );
function save_datepicker_custom_field_value( $order, $data ){
    $field_id = 'my_datepicker';
    $meta_key = '_'.$field_id;

    if ( isset($_POST[$field_id]) && ! empty($_POST[$field_id]) ) {
        $date = esc_attr($_POST[$field_id]);
        
        $order->update_meta_data( $meta_key, $date ); // Save date as order meta data
        
        $note = sprintf(__("Chosen date: %s.", "woocommerce"), $date );
        $note = isset($data['order_comments']) && ! empty($data['order_comments']) ? $data['order_comments'] . '. ' . $note : $note;
        
        // Save date on customer order note
        $order->set_customer_note( $note );

    }
}

// Display custom field value in admin order pages
add_action( 'woocommerce_admin_order_data_after_billing_address', 'admin_display_date_custom_field_value', 10, 1 );
function admin_display_date_custom_field_value( $order ) {
    $meta_key   = '_my_datepicker';
    $meta_value = $order->get_meta( $meta_key ); // Get carrier company

    if( ! empty($meta_value) ) {
        // Display
        echo '<p><strong>' . __("Chosen date", "woocommerce") . '</strong>: ' . $meta_value . '</p>';
    }
}

Code goes in functions.php file of your active child theme (or active theme). Tested and works.

