How can I add additional fees/items from the checkout page in a WooCommerce store?

I have a WooCommerce store specialized in renting out beach equipment. I added a dropdown menu to the checkout page where a customer can select for the order to be delivered or that they can pick it up themselves. If they select the delivery option, a $10 fee is added to the cart total, listed as Delivery Fee. If they select pickup, a second dropdown appears where they can select a pickup location. I want to add the option for clients to purchase cold drinks from the checkout page if they select a specific pickup location (Kamini’s Kitchen), the list of which should pop up when they select this one pickup location. I wrote it so that checkboxes appear for each drink and a quantity that can be selected. When a drink is added, it should be added to the cart under its proper name and the listed price should be added to the total (times the multiplier). Lastly, the selected drink options should appear in the order e-mails and on the admin backend.

The problem is that when a drink is selected from the list, it doesn’t get added to the cart total. The cart does refresh, but nothing gets added. I have existing code that some of the folks over here helped me write, but the drink extensions part that I’m trying to do is not working for me. I made an array for all the drinks and the dollar amounts, and JS code to make the list appear conditionally. The part where they’re supposed to be added to the cart dynamically through AJAX is where I’m stuck.

Here is my code so far:

// Utility function: Get Delivery or Pickup options
function get_delivery_or_pickup_options() {
    return array(
        ''          => esc_html__( 'Select an option', 'woocommerce' ),
        'delivery'  => esc_html__( 'Delivery Service', 'woocommerce' ),
        'pickup'    => esc_html__( 'Pickup', 'woocommerce' )
    );
}

// Utility function: Get pickup location options
function get_pickup_location_options() {
    return array(
        ''                  => esc_html__( 'Select an option', 'woocommerce' ),
        'main_office'       => esc_html__( 'Pavia 20F - Main Office', 'woocommerce' ),
        'kaminis_kitchen'   => esc_html__( "Kamini's Kitchen (Baby Beach)", 'woocommerce' )
    );
}

add_action( 'woocommerce_before_order_notes', 'add_delivery_or_pickup_fields', 10 );
function add_delivery_or_pickup_fields( $checkout ) {
    // Existing dropdowns...
    woocommerce_form_field( 'delivery_or_pickup', array(
        'type'      => 'select',
        'class'     => array('form-row-wide'),
        'label'     => esc_html__( 'Delivery or Pickup?', 'woocommerce' ),
        'required'  => true,
        'options'   => get_delivery_or_pickup_options(),
    ), $checkout->get_value('delivery_or_pickup') );

    woocommerce_form_field('pickup_location', array(
        'type' => 'select',
        'class' => array('form-row-wide'),
        'label' => esc_html__( 'Select pickup location:', 'woocommerce' ),
        'required' => true,
        'options' => get_pickup_location_options(),
    ), $checkout->get_value('pickup_location'));

    // Drinks Section - Hidden by default, displayed by JS if pickup_location == kaminis_kitchen
    echo '<div id="drink_options_section" style="display:none;">';
    echo '<h3>' . esc_html__('If you’re renting a beach cooler, you have the option to pre-purchase drinks here and have the cooler loaded up with ice and drinks when picking it up', 'woocommerce') . '</h3>';

    $drink_items = array(
        'bag_of_ice'       => array('Bag of Ice', 4.00),
        'chill'            => array('Chill', 5.00),
        'balashi'          => array('Balashi', 5.00),
        'magic_mango'      => array('Magic Mango', 5.00),
        'amstel_bright'    => array('Amstel Bright', 6.00),
        'budweiser'        => array('Budweiser', 5.00),
        'bud_light'        => array('Bud Light', 5.00),
        'corona'           => array('Corona', 6.00),
        'heineken'         => array('Heineken', 5.00),
        'presidente'       => array('Presidente', 5.00),
        'modelo'           => array('Modelo', 5.00),
        'polar'            => array('Polar', 4.00),
        'guinness'         => array('Guinness', 7.00),
        'coke'             => array('Coke', 3.00),
        'coke_zero'        => array('Coke Zero', 3.00),
        'sprite'           => array('Sprite', 3.00),
        'sprite_zero'      => array('Sprite Zero', 3.00),
        'gingerale'        => array('Gingerale', 3.00),
        'fuze_tea'         => array('Fuze Tea', 3.00),
        'club_soda'        => array('Club Soda', 3.00),
        'tonic_water'      => array('Tonic Water', 3.00),
        'fanta_cherry'     => array('Fanta Cherry', 3.00),
        'fanta_grape'      => array('Fanta Grape', 3.00),
        'fanta_orange'     => array('Fanta Orange', 3.00),
        'bottled_water'    => array('Bottled Water', 2.57),
    );

    foreach ( $drink_items as $key => $item ) {
        echo '<p><label><input type="checkbox" name="drinks[' . esc_attr($key) . ']" value="1"> ' . esc_html($item[0]) . ' ($' . number_format($item[1], 2) . ')</label> ';
        echo '<input type="number" name="drink_qty[' . esc_attr($key) . ']" min="1" max="99" value="1" style="width:60px;margin-left:10px;" /></p>';
    }

    echo '</div>';
}


// JavaScript to toggle visibility of the pickup location dropdown and update delivery fee
add_action( 'woocommerce_checkout_init', 'add_delivery_or_pickup_js_script' );
function add_delivery_or_pickup_js_script() {
    wc_enqueue_js("

    const pickupField = $('#pickup_location_field');
    const drinkOptions = $('#drink_options_section');

    function toggleDrinkOptions() {
        if ($('#pickup_location').val() === 'kaminis_kitchen') {
            drinkOptions.show();
        } else {
            drinkOptions.hide();
        }
    }

    if ($('#delivery_or_pickup').val() !== 'pickup') {
        pickupField.hide();
        drinkOptions.hide();
    }

    $(document.body).on('change', '#delivery_or_pickup', function() { 
        const val = $(this).val();
        val === 'pickup' ? pickupField.show() : pickupField.hide();
        $.post(wc_checkout_params.ajax_url, {
            action: 'save_delivery_or_pickup_to_session',
            delivery_or_pickup: val
        }, function() {
            $(document.body).trigger('update_checkout');
        });
    });

    $(document.body).on('change', '#pickup_location', function() {
        toggleDrinkOptions();
        $(document.body).trigger('update_checkout');
    });

    // Send drink selections via AJAX
    function updateDrinkSessionData() {
        const selectedDrinks = {};
        $('#drink_options_section input[type=checkbox]:checked').each(function() {
            const key = $(this).attr('name').replace('drinks[', '').replace(']', '');
            const qty = $('#drink_qty_' + key).val() || 1;
            selectedDrinks[key] = qty;
        });

        $.post(wc_checkout_params.ajax_url, {
            action: 'save_drink_options_to_session',
            drinks: selectedDrinks
        }, function() {
            $(document.body).trigger('update_checkout');
        });
    }

    $(document.body).on('change', '#drink_options_section input', updateDrinkSessionData);

    toggleDrinkOptions();
");
}


// Ajax request: Save selection to WooCommerce session
add_action('wp_ajax_save_delivery_or_pickup_to_session', 'save_delivery_or_pickup_to_session');
add_action('wp_ajax_nopriv_save_delivery_or_pickup_to_session', 'save_delivery_or_pickup_to_session');
function save_delivery_or_pickup_to_session() {
    if ( isset($_POST['delivery_or_pickup']) ) {
        WC()->session->set('delivery_or_pickup', sanitize_text_field($_POST['delivery_or_pickup']));
    }
    wp_die();
}

// Add delivery fee if "Delivery Service" is selected
add_action( 'woocommerce_cart_calculate_fees', 'add_delivery_option_fee_based_on_session' );
function add_delivery_option_fee_based_on_session( $cart ) {
    if (is_admin() && !defined('DOING_AJAX')) return;

    if ( is_checkout() && WC()->session->get('delivery_or_pickup') === 'delivery' ) {
        $delivery_fee = 10;
        $cart->add_fee( esc_html__( 'Delivery Fee', 'woocommerce' ), $delivery_fee );
    }
}

// Save drink selection to WooCommerce session
add_filter('woocommerce_checkout_posted_data', 'capture_drink_data_during_ajax');
function capture_drink_data_during_ajax( $data ) {
    if ( isset($_POST['drinks']) && isset($_POST['drink_qty']) ) {
        $data['drinks'] = $_POST['drinks'];
        $data['drink_qty'] = $_POST['drink_qty'];
    }
    return $data;
}

add_action('wp_ajax_save_drink_options_to_session', 'save_drink_options_to_session');
add_action('wp_ajax_nopriv_save_drink_options_to_session', 'save_drink_options_to_session');
function save_drink_options_to_session() {
    $drinks = isset($_POST['drinks']) ? $_POST['drinks'] : array();
    $sanitized = array();

    foreach ($drinks as $drink => $qty) {
        $drink = sanitize_key($drink);
        $qty = max(1, intval($qty));
        $sanitized[$drink] = $qty;
    }
    
    WC()->session->set('drink_data', $sanitized);
    wp_die();
}


add_action('woocommerce_cart_calculate_fees', 'add_drink_fee_via_ajax', 20, 1);
function add_drink_fee_via_ajax($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return;

    $pickup_location = isset($_POST['pickup_location']) ? sanitize_text_field($_POST['pickup_location']) : WC()->session->get('pickup_location');
    if ($pickup_location !== 'kaminis_kitchen') return;

    $drink_data = WC()->session->get('drink_data', []);
    if (empty($drink_data)) return;

    $prices = array(
        'bag_of_ice' => 4.00, 'chill' => 5.00, 'balashi' => 5.00, 'magic_mango' => 5.00,
        'amstel_bright' => 6.00, 'budweiser' => 5.00, 'bud_light' => 5.00, 'corona' => 6.00,
        'heineken' => 5.00, 'presidente' => 5.00, 'modelo' => 5.00, 'polar' => 4.00, 'guinness' => 7.00,
        'coke' => 3.00, 'coke_zero' => 3.00, 'sprite' => 3.00, 'sprite_zero' => 3.00,
        'gingerale' => 3.00, 'fuze_tea' => 3.00, 'club_soda' => 3.00, 'tonic_water' => 3.00,
        'fanta_cherry' => 3.00, 'fanta_grape' => 3.00, 'fanta_orange' => 3.00, 'bottled_water' => 2.57,
    );

    $total = 0;
    foreach ($drink_data as $drink => $qty) {
        if (isset($prices[$drink])) {
            $total += $prices[$drink] * $qty;
        }
    }

    if ($total > 0) {
        $cart->add_fee(__('Drink Options', 'woocommerce'), $total);
    }
}


add_action('woocommerce_checkout_order_processed', function () {
    WC()->session->__unset('drink_data');
}, 10, 1);

// Validate custom shipping options
add_action( 'woocommerce_after_checkout_validation', 'delivery_or_pickup_validation', 20, 2 );
function delivery_or_pickup_validation( $data, $errors ) {
    // Delivery or Pickup validation
    if ( isset($_POST['delivery_or_pickup']) && empty($_POST['delivery_or_pickup']) ) {
        $errors->add( 'delivery_or_pickup', esc_html__( 'You must choose between "Delivery" or "Pickup" option.', 'woocommerce' ), 'error' );
    }
    // Pickup location validation
    elseif ( isset($_POST['delivery_or_pickup']) && $_POST['delivery_or_pickup'] === 'pickup' 
    && isset($_POST['pickup_location']) && empty($_POST['pickup_location']) ) {
        $errors->add( 'pickup_location', esc_html__( 'You must choose a pickup location.', 'woocommerce' ), 'error' );
    }
}

// Save custom chosen shipping option details as order metadata
add_action( 'woocommerce_checkout_create_order', 'save_delivery_or_pickup_as_order_metadata', 10 );
function save_delivery_or_pickup_as_order_metadata( $order ) {
    if ( isset($_POST['delivery_or_pickup']) && !empty($_POST['delivery_or_pickup']) ) {
        $order->add_meta_data('_delivery_or_pickup', esc_attr($_POST['delivery_or_pickup']), true );
    }
    if ( isset($_POST['pickup_location']) && !empty($_POST['pickup_location']) ) {
        $order->add_meta_data('_pickup_location', esc_attr($_POST['pickup_location']), true);
    }
    // Remove the WC Session Variable
    if (  WC()->session->__isset('delivery_or_pickup') ) {
        WC()->session->__unset('delivery_or_pickup');
    }
}

add_action( 'woocommerce_checkout_create_order', 'save_drinks_to_order_meta', 20, 1 );
function save_drinks_to_order_meta( $order ) {
    if ( isset($_POST['drinks']) ) {
        $items = array(
            'bag_of_ice' => 'Bag of Ice', 'chill' => 'Chill', 'balashi' => 'Balashi', 'magic_mango' => 'Magic Mango',
            'amstel_bright' => 'Amstel Bright', 'budweiser' => 'Budweiser', 'bud_light' => 'Bud Light',
            'corona' => 'Corona', 'heineken' => 'Heineken', 'presidente' => 'Presidente',
            'modelo' => 'Modelo', 'polar' => 'Polar', 'guinness' => 'Guinness', 'coke' => 'Coke',
            'coke_zero' => 'Coke Zero', 'sprite' => 'Sprite', 'sprite_zero' => 'Sprite Zero',
            'gingerale' => 'Gingerale', 'fuze_tea' => 'Fuze Tea', 'club_soda' => 'Club Soda',
            'tonic_water' => 'Tonic Water', 'fanta_cherry' => 'Fanta Cherry', 'fanta_grape' => 'Fanta Grape',
            'fanta_orange' => 'Fanta Orange', 'bottled_water' => 'Bottled Water'
        );

        $drinks_ordered = array();
        foreach ($_POST['drinks'] as $key => $val) {
            $qty = intval($_POST['drink_qty'][$key] ?? 1);
            if ($qty > 0 && isset($items[$key])) {
                $drinks_ordered[] = $items[$key] . ' x' . $qty;
            }
        }

        if ( !empty($drinks_ordered) ) {
            $order->add_meta_data('_drink_options', implode(', ', $drinks_ordered));
        }
    }
}


// Update custom chosen shipping option details as USER metadata (useful for next checkout)
add_action( 'woocommerce_checkout_update_customer', 'save_delivery_or_pickup_as_user_metadata', 10 );
function save_delivery_or_pickup_as_user_metadata( $customer ) {
    if ( isset($_POST['delivery_or_pickup']) && !empty($_POST['delivery_or_pickup']) ) {
        $customer->update_meta_data('delivery_or_pickup', esc_attr($_POST['delivery_or_pickup']));
    }
    if ( isset($_POST['pickup_location']) && !empty($_POST['pickup_location']) ) {
        $customer->update_meta_data('pickup_location', esc_attr($_POST['pickup_location']));
    }
}

// Display chosen custom shipping option details in the admin panel under shipping address
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'display_delivery_or_pickup_meta_in_admin_order', 10 );
function display_delivery_or_pickup_meta_in_admin_order( $order ) {
    // Delivery or Pickup
    if ( $value = $order->get_meta('_delivery_or_pickup') ) {
        $options = get_delivery_or_pickup_options();
        printf( '<p><strong>%s:</strong> %s', esc_html__('Shipping', 'woocommerce' ), $options[$value] );

        // Pickup location
        if ( $value = $order->get_meta('_pickup_location') ) {
            $options = get_pickup_location_options();
            printf( '<br><strong>%s:</strong> %s', esc_html__('Location', 'woocommerce' ), $options[$value] );
        }
        echo '</p>';
    }
}

// Display chosen custom shipping option details in order total lines (customer orders and email notifications)
add_filter( 'woocommerce_get_order_item_totals', 'insert_custom_line_order_item_totals', 10, 3 );
function insert_custom_line_order_item_totals( $total_rows, $order, $tax_display ){
    $shipping = $order->get_meta('_delivery_or_pickup');
    $options1  = get_delivery_or_pickup_options();
    $location = $order->get_meta('_pickup_location');
    $options2  = get_pickup_location_options();
    $key_target = array_key_exists('discount', $total_rows) ? 'discount' : 'cart_subtotal';
    $new_total_rows = array();

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

        if( 'cart_subtotal' === $key ) {
            $new_total_rows['shipping2'] = array(
                'label' => esc_html__('Shipping option:'),
                'value' => $options1[$shipping],
            );

            if ( $location ) {
                $new_total_rows['location'] = array(
                    'label' => esc_html__('Pickup location:'),
                    'value' => $options2[$location],
                );
                $new_total_rows['drink_options'] = array(
    'label' => esc_html__('Drink Options:'),
    'value' => esc_html($order->get_meta('_drink_options')),
);
            }

        }
    }
    return $new_total_rows;
}