```
✨ feat(ReserverController): Gère les options de produits au panier et en session.
Ajoute la gestion des options de produits lors de l'ajout au panier et dans la session de réservation. Inclut des corrections pour les options orphelines.
```
This commit is contained in:
@@ -43,15 +43,30 @@ export class FlowAddToCart extends HTMLElement {
|
||||
if (!response.ok) throw new Error('Network error');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.dispo) {
|
||||
// 4. Add to Cart
|
||||
const list = JSON.parse(localStorage.getItem('pl_list') || '[]');
|
||||
if (data.dispo) {
|
||||
// 4. Add to Cart
|
||||
const list = JSON.parse(localStorage.getItem('pl_list') || '[]');
|
||||
|
||||
// --- Save Options ---
|
||||
const selectedOptions = Array.from(document.querySelectorAll('.product-option-checkbox:checked'))
|
||||
.map(cb => cb.value);
|
||||
|
||||
const allOptions = JSON.parse(localStorage.getItem('pl_options') || '{}'); console.log(selectedOptions);
|
||||
if (selectedOptions.length > 0) {
|
||||
allOptions[this.productId] = selectedOptions;
|
||||
} else {
|
||||
delete allOptions[this.productId];
|
||||
}
|
||||
|
||||
localStorage.setItem('pl_options', JSON.stringify(allOptions));
|
||||
// --------------------
|
||||
|
||||
if (!list.includes(this.productId)) {
|
||||
list.push(this.productId);
|
||||
localStorage.setItem('pl_list', JSON.stringify(list));
|
||||
window.dispatchEvent(new CustomEvent('cart:updated'));
|
||||
}
|
||||
|
||||
|
||||
// Open Cart
|
||||
const cart = document.querySelector('[is="flow-reserve"]');
|
||||
if (cart) cart.open();
|
||||
|
||||
@@ -51,10 +51,26 @@ export class FlowReserve extends HTMLAnchorElement {
|
||||
}
|
||||
}
|
||||
|
||||
getOptions() {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem('pl_options') || '{}');
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
removeFromList(id) {
|
||||
let list = this.getList();
|
||||
list = list.filter(itemId => itemId.toString() !== id.toString());
|
||||
localStorage.setItem(this.storageKey, JSON.stringify(list));
|
||||
|
||||
// Remove options for this product
|
||||
const options = this.getOptions();
|
||||
if (options[id]) {
|
||||
delete options[id];
|
||||
localStorage.setItem('pl_options', JSON.stringify(options));
|
||||
}
|
||||
|
||||
window.dispatchEvent(new CustomEvent('cart:updated'));
|
||||
this.refreshContent(); // Re-fetch and render
|
||||
}
|
||||
@@ -211,6 +227,7 @@ export class FlowReserve extends HTMLAnchorElement {
|
||||
footer.innerHTML = '';
|
||||
|
||||
const ids = this.getList();
|
||||
const options = this.getOptions();
|
||||
|
||||
// Retrieve dates from localStorage
|
||||
let dates = { start: null, end: null };
|
||||
@@ -248,6 +265,7 @@ export class FlowReserve extends HTMLAnchorElement {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
ids,
|
||||
options,
|
||||
start: dates.start,
|
||||
end: dates.end
|
||||
})
|
||||
@@ -323,8 +341,22 @@ export class FlowReserve extends HTMLAnchorElement {
|
||||
`;
|
||||
}
|
||||
|
||||
// --- RENDER PRODUCTS ---
|
||||
const productsHtml = data.products.map(product => `
|
||||
const productsHtml = data.products.map(product => {
|
||||
let optionsHtml = '';
|
||||
if (product.options && product.options.length > 0) {
|
||||
optionsHtml = '<div class="mt-1 space-y-1 bg-slate-50 p-2 rounded-lg">';
|
||||
product.options.forEach(opt => {
|
||||
optionsHtml += `
|
||||
<div class="flex justify-between text-[9px] text-slate-500 font-medium">
|
||||
<span>+ ${opt.name}</span>
|
||||
<span>${this.formatPrice(opt.price)}</span>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
optionsHtml += '</div>';
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="flex gap-4 bg-white p-3 rounded-2xl shadow-sm border border-gray-100">
|
||||
<div class="w-20 h-20 bg-gray-100 rounded-xl flex-shrink-0 overflow-hidden">
|
||||
<img src="${product.image || '/provider/images/favicon.png'}" class="w-full h-full object-cover" alt="${product.name}">
|
||||
@@ -336,6 +368,7 @@ export class FlowReserve extends HTMLAnchorElement {
|
||||
<span>1J: ${this.formatPrice(product.priceHt1Day)} HT</span>
|
||||
${product.priceHTSupDay ? `<span class="text-slate-300">|</span><span>Sup: ${this.formatPrice(product.priceHTSupDay)} HT</span>` : ''}
|
||||
</div>
|
||||
${optionsHtml}
|
||||
</div>
|
||||
<div class="flex justify-between items-end mt-2">
|
||||
<span class="text-[#0782bc] font-black text-sm">${this.formatPrice(product.totalPriceTTC || product.totalPriceHT)} <span class="text-[9px] text-slate-400 font-bold">Total</span></span>
|
||||
@@ -345,7 +378,8 @@ export class FlowReserve extends HTMLAnchorElement {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
container.innerHTML = `<div class="space-y-3">${datesHtml}${productsHtml}</div>`;
|
||||
|
||||
@@ -396,6 +430,7 @@ export class FlowReserve extends HTMLAnchorElement {
|
||||
e.preventDefault();
|
||||
|
||||
const ids = this.getList();
|
||||
const options = this.getOptions();
|
||||
let dates = { start: null, end: null };
|
||||
try {
|
||||
dates = JSON.parse(localStorage.getItem('reservation_dates') || '{}');
|
||||
@@ -409,6 +444,7 @@ export class FlowReserve extends HTMLAnchorElement {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
ids,
|
||||
options,
|
||||
start: dates.start,
|
||||
end: dates.end
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user