I have out of stock products for which customer can place a preorder. Initialy I am doing this by creating a duplicate product through ajax request by sending product id. Then i am adding this duplicate product (using its id) after response is received by changing add_to_cart button href (the old way). This works correctly. However I wanted to add a notification that shows after checking if the product is in the cart. Could not do that using this method as page reloads in this case. Here is the first working method:
if(e.target.closest("button[name='pre-order-confirmation-btn']")){
e.preventDefault()
e.target.setAttribute('disabled', '')
const notif_wrapper_in_use = document.querySelector('.stock-notif- wrapper.in-use')
let btn_clicked = e.target.closest("button[name='pre-order-confirmation-btn']")
let value = btn_clicked.value
let a_add_to_cart = notif_wrapper_in_use.querySelector(`a[data-type = ${value}]`)
let product_id = btn_clicked.dataset.productId
send_request_create_preorder_product(make_duplicate_preorder_object.ajax_url,'post', product_id, a_add_to_cart, btn_clicked )
}
async function send_request_create_preorder_product(url, post, product_id, add_to_cart_btn, btn_clicked){
let formData = new FormData()
formData.append('action','send_product_id_for_preorder');
formData.append('product_id', product_id);
const options = {
method : post,
body : formData
}
const response = await fetch(url, options)
const result = await response.text()
console.log(result)
add_to_cart_btn.href = `?add-to-cart=${result}`
add_to_cart_btn.classList.remove('hide')
btn_clicked.style.display = 'none'
/* Here I wanted to add the notification if product is indeed added to cart*/
if(document.body.classList.contains('home') /*and product in cart*/){
/*show successful notification*/
}
/* ajax function using using hooks wp_ajax and wp_ajax_nopriv*/
function ajax_create_duplicate_product_preorder(){
if(isset($_POST['action']) && $_POST['action'] === 'send_product_id_for_preorder'){
$original_product_id = $_POST['product_id'];
$duplicate_product_id = add_notif_duplicate_wc_product($original_product_id);
echo $duplicate_product_id;
}
wp_die();
}
function add_notif_duplicate_wc_product($product_id){
$original_product = wc_get_product($product_id);
if(!$original_product){
return new WP_Error('invalid_product', 'Invalid product ID.');
}
$duplicate_product = new WC_Product_Simple();
$duplicate_product->set_name($original_product->get_name().'-precommande');
$duplicate_product->set_status('publish');
$duplicate_product->set_description($original_product->get_description());
$duplicate_product->set_short_description($original_product->get_short_description());
$duplicate_product->set_price($original_product->get_price());
$duplicate_product->set_regular_price($original_product->get_regular_price());
$duplicate_product->set_sale_price($original_product->get_sale_price());
$duplicate_product->set_catalog_visibility('hidden');
$duplicate_product->set_manage_stock(false);
$duplicate_product->set_stock_status('instock');
$duplicate_product->set_virtual(true);
$duplicate_product_id = $duplicate_product->save();
$duplicate_product->set_name($duplicate_product->get_name() . '-' . $duplicate_product_id);
$duplicate_product->save();
wp_set_object_terms($duplicate_product_id,'preorders', 'product_cat', false);
$thumbnail_id = get_post_thumbnail_id($product_id);
if($thumbnail_id){
set_post_thumbnail($duplicate_product_id, $thumbnail_id);
}
// echo $duplicate_product_id;
return $duplicate_product_id;
}
so as an alternative I tried using this modified async function and woocommerce woocommerce_ajax_add_to_cart (I also removed the ‘post’ parameter in the above async function when called)
async function send_request_create_preorder_product(url, product_id, add_to_cart_btn, btn_clicked) {
// Create the preorder product via AJAX
const formData = new FormData();
formData.append('action', 'send_product_id_for_preorder');
formData.append('product_id', product_id);
const response = await fetch(url, { method: 'POST', body: formData });
const duplicateProductId = await response.text();
console.log(duplicateProductId)
if (!duplicateProductId) return;
// Update the Add to Cart button
add_to_cart_btn.dataset.productId = duplicateProductId; // store the new product ID
add_to_cart_btn.classList.remove('hide');
btn_clicked.style.display = 'none';
// AJAX Add-to-Cart
add_to_cart_btn.addEventListener('click', async (e) => {
e.preventDefault(); // prevent page reload
const addFormData = new FormData();
addFormData.append('action', 'woocommerce_ajax_add_to_cart');
addFormData.append('product_id', duplicateProductId);
addFormData.append('quantity', 1);
const addResponse = await fetch(url, { method: 'POST', body: addFormData });
const addResult = await addResponse.json();
console.log(addResult)
if (addResult && addResult.added) {
// Show notification
let notifDiv = document.createElement('div');
notifDiv.className = 'preorder-notif-div-homepage';
notifDiv.textContent = 'Le produit précommandé a été ajouté au panier';
document.body.appendChild(notifDiv);
}
}, { once: true });
}
The duplicate product_id is properly console logged but then I have a 400 (Bad Request) error on this line const addResponse = await fetch(url, { method: ‘POST’, body: addFormData });
I have been turning around to solve it for 2 days but did not find any working solution.
and this is the HTML form used
<div class='stock-notif-wrapper'>
<p><button type='button' name='show-add-notif-btn' data-notify-product-id='". $product->get_id(). "'>Pre-commander 24h</button></p>
<div class='stock-notif-form-wrapper'>
<div class='pre-order-questions-input'>
<label>
<input type='radio' name='".$product->get_id()."-"."preorder-or-question[]' class='inputs radios' value='just-ask-date' checked>
Voulez vous savoir quand le produit sera en stock?
</label>
<label>
<input type='radio' name='".$product->get_id()."-"."preorder-or-question[]' class='inputs radios' value='send-preorder'>
Voulez-vous payer et pre commander directement?
</label>
</div>
<form action='' method='POST' data-type = 'just-ask-date'>
<div class='stock-notif-error-notif-div'></div>
<div id='recaptcha-container-". $product->get_id() ."'></div>
<div class='notify-inputs-wrapper'>
<input type='email' name='stock-notif-email' class='inputs' placeholder='Email' required>
<input type='tel' name='stock-notif-tel' class='inputs' placeholder='Mobile ex 22 222 222' required>
<input type='hidden' name='notify_product_id' value='{$product->get_id()}'>
</div>
<div class='button-wrapper'>
<button type='submit' name='stock-notif-submit-btn'>Envoyer</button>
<button type='button' name='show-add-notif-shown-close-btn'>Fermer</button>
</div>
<div class='company_wrapper'>
<div class='company-addition'>
<input type='text' name='company-name'>
</div>
</div>
<p class='info'>Vous recevrez un email ou SMS vous informant de la date de disponibilité sous 48h</p>
</form>
<div class='preorder-notif hide' data-type = 'send-preorder'>
<p class='pre-order-description-text'>Vous Allez payer la totalité du produit et nous vous enverrons votre code sous 24h par email si paiement en ligne ou sous 48h si paiement à la livraison</p>
<!--<form action='' metod='POST'>-->
<button name='pre-order-confirmation-btn' data-product-id ='".$product->get_id()."' value='pre-order-confirmation-add-to-cart'>Confirmer</button>
<!--</form>-->
<a href='". esc_url( "?add-to-cart=" . $product->get_id() ) . "' class='button' data-type='pre-order-confirmation-add-to-cart'>Pré-commander 24h</a>"."
<button type='button' name='show-add-notif-shown-close-btn'>Fermer</button>
</div>
</div>
</div>
";