Search code examples
javascriptphpjquerywordpresswoocommerce

Dynamic estimated delivery date widget in WooCommerce products


I added a Estimated delivery date widget using a code snippet. I want it to show the diffrent shipping and delivery date for different product. Can I add a custom field on woocommerce product editor,so I can choose number of days?

Here is the Code :

add_action( 'woocommerce_after_add_to_cart_form', 
'delivery_status_widget', 40 );
function delivery_status_widget() {
?>
<link rel="stylesheet" 
href="https://use.fontawesome.com/releases/v5.14.0/css/all.css">
<style>
    .delivery-status-widget {
        display: flex;
        flex-direction: row;
        justify-content: space-evenly;
        align-items: center;
        font-size: 13px; 
        margin-bottom: 10px;
        line-height: 15px;
        padding: 14px 10px;
        color: #121212;
        background-color: white;
        border: 1px dotted black;
        color: #121212;
        border-radius: 6px;
    }
    .delivery-status-widget .status {
        display: flex;
        flex-direction: column;
        align-items: center;
        margin: 0 15px;
    }
    .delivery-status-widget .status-icon {
        font-size: 24px;
        margin-bottom: 5px;
        color: #121212!important;
    }
    .delivery-status-widget .status-text {
        font-weight: bold;
        margin-bottom: 5px;
    }
    .delivery-status-widget .status-date {
        font-size: 12px;
        color: gray;
    }
   </style>

<div class="delivery-status-widget">
    <div class="status">
        <i class="fas fa-shopping-bag status-icon" style="color: 
   gray;"></i>
        <div class="status-text">Ordered</div>
        <div class="status-date" id="order-date"></div>
    </div>
    <div class="status">
        <i class="fas fa-angle-double-right"></i>
    </div>
    <div class="status">
        <i class="fas fa-shipping-fast status-icon" style="color: 
grey;"></i>
        <div class="status-text">Shipped</div>
        <div class="status-date" id="ship-date"></div>
    </div>
    <div class="status">
        <i class="fas fa-angle-double-right"></i>
    </div>
    <div class="status">
        <i class="fas fa-box-open status-icon" style="color: 
grey;"></i>
        <div class="status-text">Delivered</div>
        <div class="status-date" id="delivery-date"></div>
    </div>
</div>

<script>
    jQuery(document).ready(function($) {
        var today = new Date();

        // Ordered
        var orderedDate = today.toLocaleDateString("en-US", { month: 'short', day: 'numeric' });
        document.getElementById("order-date").innerHTML = orderedDate;

        // Shipped
        var shipDate = new Date(today);
        shipDate.setDate(today.getDate() + 2);
        shipDate = shipDate.toLocaleDateString("en-US", { month: 'short', day: 'numeric' });
        document.getElementById("ship-date").innerHTML = shipDate;

        // Delivered
        var deliveryDate = new Date(today);
        deliveryDate.setDate(today.getDate() + 6);
        deliveryDate = deliveryDate.toLocaleDateString("en-US", { month: 'short', day: 'numeric' });
        document.getElementById("delivery-date").innerHTML = deliveryDate;
    });
</script>
<?php
}

I tried this code to add custom fields and it added the fields :

function add_custom_fields() {
woocommerce_wp_text_input(
    array(
        'id'          => '_shipping_days',
        'label'       => 'Shipping Days',
        'desc_tip'    => true,
        'description' => 'Enter the number of days required for 
shipping',
        'wrapper_class' => 'form-row form-row-first',
    )
);

woocommerce_wp_text_input(
    array(
        'id'          => '_delivery_days',
        'label'       => 'Delivery Days',
        'desc_tip'    => true,
        'description' => 'Enter the number of days required for 
delivery',
        'wrapper_class' => 'form-row form-row-last',
    )
);
}
add_action( 'woocommerce_product_options_general_product_data', 
'add_custom_fields' );


function save_custom_fields( $post_id ) {
$shipping_days = isset( $_POST['_shipping_days'] ) ? 
sanitize_text_field( $_POST['_shipping_days'] ) : '';
$delivery_days = isset( $_POST['_delivery_days'] ) ? 
sanitize_text_field( $_POST['_delivery_days'] ) : '';

update_post_meta( $post_id, '_shipping_days', $shipping_days );
update_post_meta( $post_id, '_delivery_days', $delivery_days );
}
add_action( 'woocommerce_process_product_meta', 'save_custom_fields' );

And Tried this javascript for the above custom fields(but it didn't show the shipping and delivery date at all, it was empty):

jQuery(document).ready(function($) {
var today = new Date();

// Ordered
var orderedDate = today.toLocaleDateString("en-US", { month: 'short', day: 'numeric' });
document.getElementById("order-date").innerHTML = orderedDate;

// Shipped
var shipDate = new Date(today);
shipDate.setDate(today.getDate() + parseInt(woocommerce_admin_meta_boxes.get_meta_value('_shipping_days')));
shipDate = shipDate.toLocaleDateString("en-US", { month: 'short', day: 'numeric' });
document.getElementById("ship-date").innerHTML = shipDate;

// Delivered
var deliveryDate = new Date(today);
deliveryDate.setDate(today.getDate() + parseInt(woocommerce_admin_meta_boxes.get_meta_value('_delivery_days')));
deliveryDate = deliveryDate.toLocaleDateString("en-US", { month: 'short', day: 'numeric' });
document.getElementById("delivery-date").innerHTML = deliveryDate;
});

Solution

  • I have revisited all your code and removed the unnecessary last function. In the first function you will get now both product sipping custom fields values, to autopopulate dynamically your shipping widget:

    add_action( 'woocommerce_after_add_to_cart_form', 'delivery_status_widget', 40 );
    function delivery_status_widget() {
        global $product;
        ?>
        <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.14.0/css/all.css">
        <style>
        .delivery-status-widget {
            display: flex;
            flex-direction: row;
            justify-content: space-evenly;
            align-items: center;
            font-size: 13px; 
            margin-bottom: 10px;
            line-height: 15px;
            padding: 14px 10px;
            color: #121212;
            background-color: white;
            border: 1px dotted black;
            color: #121212;
            border-radius: 6px;
        }
        .delivery-status-widget .status {
            display: flex;
            flex-direction: column;
            align-items: center;
            margin: 0 15px;
        }
        .delivery-status-widget .status-icon {
            font-size: 24px;
            margin-bottom: 5px;
            color: #121212!important;
        }
        .delivery-status-widget .status-text {
            font-weight: bold;
            margin-bottom: 5px;
        }
        .delivery-status-widget .status-date {
            font-size: 12px;
            color: gray;
        }
        </style>
        <div class="delivery-status-widget">
            <div class="status">
                <i class="fas fa-shopping-bag status-icon" style="color: 
        gray;"></i>
                <div class="status-text">Ordered</div>
                <div class="status-date" id="order-date"></div>
            </div>
            <div class="status">
                <i class="fas fa-angle-double-right"></i>
            </div>
            <div class="status">
                <i class="fas fa-shipping-fast status-icon" style="color: 
        grey;"></i>
                <div class="status-text">Shipped</div>
                <div class="status-date" id="ship-date"></div>
            </div>
            <div class="status">
                <i class="fas fa-angle-double-right"></i>
            </div>
            <div class="status">
                <i class="fas fa-box-open status-icon" style="color: 
        grey;"></i>
                <div class="status-text">Delivered</div>
                <div class="status-date" id="delivery-date"></div>
            </div>
        </div>
        <?php
            // Get the product "shipping""custom fields values"
            $shipval = $product->get_meta('_shipping_days');
            $delival = $product->get_meta('_delivery_days'); 
        ?>
        <script>
        jQuery(document).ready(function($) {
            var today       = new Date(),
                shipVal     = <?php echo $shipval ? intval( $shipval ) : 2; ?>, // (Default value is "2")
                deliVal     = <?php echo $delival ? intval( $delival ) : 6; ?>; // (Default value is "6")
    
            // Ordered
            var orderedDate = today.toLocaleDateString("en-US", { month: 'short', day: 'numeric' });
            $("#order-date").text(orderedDate);
    
            // Shipped
            var shipDate = new Date(today);
            shipDate.setDate(today.getDate() + shipVal);
            shipDate = shipDate.toLocaleDateString("en-US", { month: 'short', day: 'numeric' });
            $("#ship-date").text(shipDate);
    
            // Delivered
            var deliveryDate = new Date(today);
            deliveryDate.setDate(today.getDate() + deliVal);
            deliveryDate = deliveryDate.toLocaleDateString("en-US", { month: 'short', day: 'numeric' });
            $("#delivery-date").text(deliveryDate);
        });
        </script>
        <?php
    }
    
    add_action( 'woocommerce_product_options_general_product_data', 'add_shipping_custom_fields' );
    function add_shipping_custom_fields() {
        
        echo '<div class="options_group product_shipping_custom_fields">';
        
        woocommerce_wp_text_input(
            array(
                'id'          => '_shipping_days',
                'label'       => 'Shipping Days',
                'desc_tip'    => true,
                'description' => 'Enter the number of days required for shipping',
            )
        );
    
        woocommerce_wp_text_input(
            array(
                'id'          => '_delivery_days',
                'label'       => 'Delivery Days',
                'desc_tip'    => true,
                'description' => 'Enter the number of days required for delivery',
            )
        );
        
        echo '</div>';
    }
    
    add_action( 'woocommerce_admin_process_product_object', 'save_shipping_custom_fields' );
    function save_shipping_custom_fields( $product ) {
        if ( isset($_POST['_shipping_days']) ) {
            $product->update_meta_data( '_shipping_days', sanitize_text_field( $_POST['_shipping_days'] ) );
        }
        if ( isset($_POST['_delivery_days']) ) {
            $product->update_meta_data( '_delivery_days', sanitize_text_field( $_POST['_delivery_days'] ) );
        }
    }
    

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

    enter image description here