In this tutorial, we are going to show you can add a calendar with both date a time selection on the WooCommerce checkout page. This is especially useful if you have an e-commerce website with a click and collect feature, but this can be used in various other case scenarios also.
What you will end up with is a date time selector at checkout which will be recorded in WooCommerce orders, in our example we used this for a click and collect where you could specify the date and time in which you would like to collect the item. This will look something like the below:
So, to implement this, all you have to do is add the following code to your functions.php
file:
/**
* @snippet - Display Order Delivery Date Time Picker @ WooCommerce Checkout
*/
// -------------------------------
// 1. Display Checkout Calendar if Shipping Selected
add_action( 'woocommerce_review_order_before_payment', 'silva_echo_acf_date_picker' );
function silva_echo_acf_date_picker( $checkout ) {
echo '<div id="show-if-shipping" style="display:none"><h3>Collection Date</h3>';
woocommerce_form_field( 'delivery_date', array(
'type' => 'text',
'class' => array('form-row-wide'),
'id' => 'datepicker',
'required' => true,
'label' => __('Book before 12pm, collect the same day.'),
'placeholder' => __('Click to open calendar'),
));
echo '</div>';
}
add_action( 'woocommerce_after_checkout_form', 'silva_show_hide_calendar' );
function silva_show_hide_calendar( $available_gateways ) {
?>
<script type="text/javascript">
function show_calendar( val ) {
if ( val.match("^local_pickup") ) {
jQuery('#show-if-shipping').fadeIn();
} else {
jQuery('#show-if-shipping').fadeOut();
}
}
jQuery(document).ajaxComplete(function() {
var val = jQuery('input[name^="shipping_method"]:checked').val();
show_calendar( val );
});
</script>
<?php
}
add_action( 'woocommerce_checkout_process', 'silva_validate_new_checkout_fields' );
function silva_validate_new_checkout_fields() {
if ( isset( $_POST['delivery_date'] ) && empty( $_POST['delivery_date'] ) ) wc_add_notice( __( 'Please select the Collection Date' ), 'error' );
}
// -------------------------------
// 2. Load JQuery Datepicker
add_action( 'woocommerce_after_checkout_form', 'silva_enable_datepicker', 10 );
function silva_enable_datepicker() {
?>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.css">
<style>
.xdsoft_datetimepicker .xdsoft_calendar td, .xdsoft_datetimepicker .xdsoft_calendar th {
background: #FFF;
color: #000;
}
.xdsoft_datetimepicker .xdsoft_calendar td:hover {
background: #000 !important;
color: #FFF !important;
}
.xdsoft_datetimepicker .xdsoft_calendar td:hover, .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div:hover {
background: #000;
color: #FFF;
}
.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_default, .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_current, .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div.xdsoft_current {
background: #000;
box-shadow: none;
}
.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div.xdsoft_current {
color: #FFF;
}
.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_today {
color: #000;
background: #FFF;
}
.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div:hover {
background: #000 !important;
}
</style>
<?php
}
// -------------------------------
// 3. Load Calendar Dates
add_action( 'woocommerce_after_checkout_form', 'silva_load_calendar_dates', 20 );
function silva_load_calendar_dates( $available_gateways ) {
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
jQuery.datetimepicker.setLocale('en');
var currentDate = new Date();
var minutes = currentDate.getMinutes();
var m = (Math.ceil(minutes/30) * 30) % 60;
currentDate.setMinutes(m);
jQuery('#datepicker').datetimepicker({
beforeShowDay: $.datepicker.noWeekends,
format: 'd/m/Y H:i a',
minDate: 0,
minTime: 0,
step: "30",
allowTimes:[
'09:00', '09:30', '10:00', '10:30', '11:00', '11:30', '12:00', '12:30',
'13:00', '13:30', '14:00', '14:30', '15:00', '15:30', '16:00', '16:30', '17:00'
]
});
});
</script>
<?php
}
// -------------------------------
// 4. Save & show date as order meta
add_action( 'woocommerce_checkout_update_order_meta', 'silva_save_date_weight_order' );
function silva_save_date_weight_order( $order_id ) {
global $woocommerce;
if ( $_POST['delivery_date'] ) update_post_meta( $order_id, '_delivery_date', esc_attr( $_POST['delivery_date'] ) );
}
add_action( 'woocommerce_admin_order_data_after_billing_address', 'silva_delivery_weight_display_admin_order_meta' );
function silva_delivery_weight_display_admin_order_meta( $order ) {
echo '<p><strong>Collection Date:</strong> ' . get_post_meta( $order->get_id(), '_delivery_date', true ) . '</p>';
}
In our example, we added some styles which you can find in Part #2 which we customised to tailor for the black and white that the site has, feel free to tailor this to your exact needs.
We also added some functionality so that you couldn’t select a date or time before the current date and time (to avoid human-error obviously).
Also in our example, the client requested to have the date selection to Monday-Friday; 9:00-17:00 with 30 minute increments on the time selection. Again, feel free to customise this to your requirements.
You can check the documentation of the plugin we used to achieve this here.
We sure hope this tutorial helped you achieve what you wanted in your e-commerce shop. If you need any assistance with this, feel free to leave a comment below!
Nice post and great idea.
In the current pandemic a useful feature would be to be able to select unique pickup time slots for safety reasons.
For example…say 20 time slots per hour or 1 every 5 minutes. So if a customer chooses to pick up their item at 7.35pm then no one else can have that time slot.
Do you have this feature??
Thanks, Tom
hi I’ve tried the code and nothing happened 🙁