PHP /**
* Snippet Name: Local Pickup Points Selector
* Snippet Author: coding-bunny.com
* Description: Allows customers to select a local pickup location during checkout.
*/
/* Add here your pickup points */
function cblpp_get_pickup_points () {
return array (
' store_milan ' => array (
' label ' => ' Milan Store ' ,
' address ' => ' Via Roma 1, 20100 Milan (MI) ' ,
),
' store_rome ' => array (
' label ' => ' Rome Store ' ,
' address ' => ' Piazza Navona 10, 00186 Rome (RM) ' ,
),
' store_turin ' => array (
' label ' => ' Turin Store ' ,
' address ' => ' Corso Francia 100, 10143 Turin (TO) ' ,
),
) ;
}
add_action ( ' woocommerce_after_shipping_rate ' , function ( $ method , $ index ){
if ( strpos ( $ method -> id , ' local_pickup ' ) !== false ) {
$ pickup_points = cblpp_get_pickup_points () ;
$ selected = isset ( $ _POST [ ' pickup_point ' ]) ? sanitize_text_field ( $ _POST [ ' pickup_point ' ]) : '' ;
echo '
<style>
.cblpp-pickup-point-selector {
margin: 10px 0 0 32px;
padding: 10px 12px 12px 12px;
background: #f7fafd;
border: 1px solid #e2edef;
border-radius: 8px;
max-width: 400px;
}
.cblpp-pickup-point-selector strong {
display: block;
margin-bottom: 8px;
font-size: 15px;
font-weight: 700;
color: #222;
}
.cblpp-pickup-radio-label {
display: flex;
align-items: flex-start;
gap: 10px;
margin-bottom: 7px;
background: #fcfcfc;
padding: 8px 10px;
border-radius: 6px;
border: 1px solid #e2edef;
cursor: pointer;
transition: border-color 0.2s;
}
.cblpp-pickup-radio-label input[type="radio"] {
margin: 2px 12px 0 0;
width: 20px;
height: 20px;
accent-color: #142520;
flex-shrink: 0;
cursor: pointer;
}
.cblpp-pickup-radio-label span {
display: flex;
flex-direction: column;
gap: 1px;
}
.cblpp-pickup-radio-label .label-title {
font-weight: 700;
font-size: 15px;
color: #222;
}
.cblpp-pickup-radio-label .label-address {
font-size: 13px;
color: #666;
}
.cblpp-pickup-radio-label input[type="radio"]:checked + span .label-title {
color: #142520;
}
@media (max-width: 600px) {
.cblpp-pickup-point-selector { max-width: 100%; }
.cblpp-pickup-radio-label { flex-direction: column; align-items: flex-start; }
.cblpp-pickup-radio-label input[type="radio"] { margin-bottom: 8px; }
}
</style>
' ;
echo ' <div class="cblpp-pickup-point-selector"> ' ;
echo ' <strong>Select pickup location:</strong> ' ;
foreach ( $ pickup_points as $ key => $ point ) {
$ radio_id = ' pickup_point_ ' . esc_attr ( $ key ) ;
printf (
' <label class="cblpp-pickup-radio-label" for="%s">
<input type="radio" id="%s" name="pickup_point" value="%s" %s required>
<span>
<span class="label-title">%s</span>
<span class="label-address">%s</span>
</span>
</label> ' ,
$ radio_id ,
$ radio_id ,
esc_attr ( $ key ),
checked ( $ selected , $ key , false ),
esc_html ( $ point [ ' label ' ]),
esc_html ( $ point [ ' address ' ])
) ;
}
echo ' </div> ' ;
?>
< script >
jQuery ( function ( $ ){
function togglePickupPoints () {
var sel = $ ( ' input[name^="shipping_method"]:checked ' ) ;
var show = sel . length && sel . val () && sel . val () . indexOf ( ' local_pickup ' ) !== - 1 ;
$ ( ' .cblpp-pickup-point-selector ' ) . toggle ( show ) ;
}
$ ( document ) . on ( ' change ' , ' input[name^="shipping_method"] ' , togglePickupPoints ) ;
$ ( document . body ) . on ( ' updated_checkout ' , togglePickupPoints ) ;
togglePickupPoints () ;
}) ;
</ script >
<? php
}
} , 10 , 2 ) ;
add_action ( ' woocommerce_checkout_process ' , function (){
$ chosen_methods = WC () -> session -> get ( ' chosen_shipping_methods ' , array ()) ;
if ( is_array ( $ chosen_methods ) && array_filter ( $ chosen_methods , function ( $ m ){ return strpos ( $ m , ' local_pickup ' ) !== false; }) ) {
$ points = cblpp_get_pickup_points () ;
if ( empty ( $ _POST [ ' pickup_point ' ]) || ! array_key_exists ( $ _POST [ ' pickup_point ' ], $ points ) ) {
wc_add_notice ( ' Please select a pickup location. ' , ' error ' ) ;
}
}
}) ;
add_action ( ' woocommerce_checkout_create_order ' , function ( $ order , $ data ){
if ( !empty ( $ _POST [ ' pickup_point ' ]) ) {
$ points = cblpp_get_pickup_points () ;
$ key = sanitize_text_field ( $ _POST [ ' pickup_point ' ]) ;
if ( isset ( $ points [ $ key ]) ) {
$ order -> update_meta_data ( ' pickup_point_label ' , $ points [ $ key ][ ' label ' ]) ;
$ order -> update_meta_data ( ' pickup_point_address ' , $ points [ $ key ][ ' address ' ]) ;
}
}
}, 10 , 2 ) ;
add_action ( ' woocommerce_admin_order_data_after_shipping_address ' , function ( $ order ){
$ label = $ order -> get_meta ( ' pickup_point_label ' ) ;
$ address = $ order -> get_meta ( ' pickup_point_address ' ) ;
if ( $ label && $ address ) {
echo ' <p><strong>Pickup location:</strong> ' . esc_html ( $ label ) . ' <br><small> ' . esc_html ( $ address ) . ' </small></p> ' ;
}
}) ;
add_action ( ' woocommerce_order_details_after_customer_details ' , function ( $ order ){
$ label = $ order -> get_meta ( ' pickup_point_label ' ) ;
$ address = $ order -> get_meta ( ' pickup_point_address ' ) ;
if ( $ label && $ address ) {
echo ' <section class="woocommerce-customer-details"> ' ;
echo ' <h2>Pickup location</h2> ' ;
echo ' <p> ' . esc_html ( $ label ) . ' <br><small> ' . esc_html ( $ address ) . ' </small></p> ' ;
echo ' </section> ' ;
}
}) ;
add_action ( ' woocommerce_email_after_order_table ' , function ( $ order , $ sent_to_admin , $ plain_text , $ email ){
$ label = $ order -> get_meta ( ' pickup_point_label ' ) ;
$ address = $ order -> get_meta ( ' pickup_point_address ' ) ;
if ( $ label && $ address ) {
if ( $ plain_text ) {
echo " \n Pickup location: " . $ label . " - " . $ address . " \n " ;
} else {
echo ' <h3>Pickup location</h3> ' ;
echo ' <p> ' . esc_html ( $ label ) . ' <br><small> ' . esc_html ( $ address ) . ' </small></p> ' ;
}
}
}, 10 , 4 ) ;
How To Implement This Solution?