/**
* @file store.js
* @description Contexte global du panier d'achat (PanierContext).
* Fournit les fonctions pour ajouter, modifier, supprimer et vider le panier,
* ainsi qu'un hook personnalisé pour y accéder depuis n'importe quel composant.
*/
import React, { createContext, useState, useContext } from 'react';
/**
* Contexte React interne du panier.
* Ne pas utiliser directement — préférer le hook {@link usePanier}.
* @type {React.Context}
*/
const PanierContext = createContext();
/**
* Fournisseur du contexte panier.
* Doit envelopper tous les composants qui ont besoin d'accéder au panier.
*
* @component
* @param {Object} props
* @param {React.ReactNode} props.children - Les composants enfants à envelopper.
* @returns {React.JSX.Element} Le Provider exposant le panier et ses actions.
*/
export const PanierProvider = ({ children }) => {
const [panier, setPanier] = useState([]);
//console.log(panier);
/**
* Ajoute un produit au panier ou incrémente sa quantité s'il est déjà présent.
* Refuse l'ajout si le produit ne possède pas d'identifiant.
*
* @param {Object} produit - Le produit à ajouter.
* @param {number|string} produit.id - L'identifiant unique du produit (obligatoire).
* @param {string} produit.designation - Le nom du produit.
* @param {number} produit.prix - Le prix unitaire HT.
* @param {string} [produit.imageUrl] - L'URL relative de l'image.
* @param {number} [produit.quantite=1] - La quantité à ajouter (défaut : 1).
*/
const ajouterAuPanier = (produit) => {
if (!produit?.id) {
console.error("Tentative d'ajout d'un produit sans ID :", produit);
return; // On bloque l'ajout silencieux
}
setPanier((prevPanier) => {
const existe = prevPanier.find(item => item.id === produit.id);
if (existe) {
return prevPanier.map(item =>
item.id === produit.id
? { ...item, quantite: item.quantite + (produit.quantite || 1) }
: item
);
}
return [...prevPanier, { ...produit, quantite: produit.quantite || 1 }];
});
};
/**
* Modifie la quantité d'un article du panier par un delta positif ou négatif.
* La quantité minimale est 1 (ne peut pas descendre en dessous).
*
* @param {number|string} id - L'identifiant de l'article à modifier.
* @param {number} delta - La variation de quantité (ex. : +1 ou -1).
*/
const modifierQuantite = (id, delta) => {
setPanier((prevPanier) =>
prevPanier.map((item) => {
if (item.id === id) {
const nouvelleQuantite = item.quantite + delta;
// On retourne l'item avec la nouvelle quantité (minimum 1)
return { ...item, quantite: nouvelleQuantite < 1 ? 1 : nouvelleQuantite };
}
return item;
})
);
};
/**
* Supprime définitivement un article du panier.
*
* @param {number|string} id - L'identifiant de l'article à supprimer.
*/
const supprimerDuPanier = (id) => {
setPanier(prevPanier => prevPanier.filter(item => item.id !== id));
};
/**
* Vide intégralement le panier (remet le tableau à zéro).
*/
const viderPanier = () => setPanier([]);
return (
<PanierContext.Provider value={{
panier,
ajouterAuPanier,
modifierQuantite,
supprimerDuPanier,
viderPanier
}}>
{children}
</PanierContext.Provider>
);
};
/**
* Hook personnalisé pour accéder au contexte du panier.
* Doit être utilisé à l'intérieur d'un composant enveloppé par {@link PanierProvider}.
*
* @returns {{
* panier: Array<Object>,
* ajouterAuPanier: Function,
* modifierQuantite: Function,
* supprimerDuPanier: Function,
* viderPanier: Function
* }} Les données et actions du panier.
*/
export const usePanier = () => useContext(PanierContext);