turns-00016.parquet:15356
c1a592ece425e10f8a416704
turn 1/6gpt-4-1106-previewEnglishFrance1456 words
degenerate_repetitionAbsentFinal dense release
USER
Implémente le back end du panier avec l'utilisation des cookies qui ne sont pas encore liées à ces pages : import React from 'react'
import {useState} from 'react';
import { getCookie, setCookie } from '../../../../cookies/CookiesLib.tsx';
type Props = {
typeBillet: number,
quantite: number,
}
export default function ItemPanier(props: Props) {
const [quantite, setQuantite] = useState(props.quantite);
return (
<div className="item-panier">
<div className="container-item-panier">
<div className="container-image">
<img src="/images/billet.png" alt="billet" />
</div>
<div className="informations">
<div className="textes">
<h4>Pass 1 jour - fosse</h4>
<h5>35,99€</h5>
</div>
<div className="compteur-quantitee">
<span className='ajout-retrait' onClick={() => setQuantite(quantite-1)}>-</span>
<input type="number" className='quantite' value={quantite}/>
<span className='ajout-retrait' onClick={() => setQuantite(quantite+1)}>+</span>
</div>
</div>
</div>
<img className='cross' src="/icones/cross.svg" alt="croix"/>
</div>
)
}
import { motion } from 'framer-motion'
import React from 'react'
import { Link } from 'react-router-dom'
import {useState} from 'react';
import TextField from '../../../form/TextField';
import Button from '../../../form/Button';
import ItemPanier from './ItemPanier';
type Props = {
isOpen: boolean;
setIsOpen: (isOpen : boolean) => void;
}
export default function MenuConnexion(props: Props) {
const menuVariants = {
hidden:{
x: "42rem",
transition:{
duration: 0.5,
ease: [1, -0.02, 0,1]
}
},
visible:{
x: 0,
transition:{
duration: 0.5,
ease: [1, -0.02, 0,1]
}
}
}
return (
<motion.div className='side-menu cart'
variants={menuVariants}
initial="hidden"
animate={props.isOpen ? "visible" : "hidden"}>
<div className="cross" onClick={() => props.setIsOpen(false)}>
<svg width="36" height="28" viewBox="0 0 36 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="6.52539" y="0.321533" width="35.8974" height="3.58974" rx="1.79487" transform="rotate(45 6.52539 0.321533)" fill="#E45A3B"/>
<rect x="3.87891" y="25.5957" width="35.8974" height="3.58974" rx="1.79487" transform="rotate(-45 3.87891 25.5957)" fill="#E45A3B"/>
</svg>
</div>
<div className="container">
<h2>Mon panier</h2>
<section className='le-panier'>
<ItemPanier typeBillet={1} quantite={1}/>
<ItemPanier typeBillet={1} quantite={1}/>
</section>
<div className="sous-total">
<h4>Sous total: </h4>
<h4>35,99€</h4>
</div>
<Button text="RESERVER"/>
</div>
</motion.div>
)
}
import { motion } from 'framer-motion';
import { useContext, useState } from 'react';
import Button from '../components/form/Button';
import { getCookie, setCookie } from '../cookies/CookiesLib.tsx';
import { CartContext } from '../App';
const initialDays = { '20Juillet': false, '21Juillet': false, '22Juillet': false };
type Props = {
id: number;
title: string;
price: number|string;
nbTicket: number;
isForfait?: boolean;
};
export default function TicketCard({ id, title, price, nbTicket, isForfait }: Props) {
const [isOpen, setIsOpen] = useState(false);
const [tickets, setTickets] = useState(nbTicket);
const [rotation, setRotation] = useState(0);
const [days, setDays] = useState(initialDays);
const { cart, setCart } = useContext(CartContext);
const handleTicketChange = (newTickets: number, event: React.MouseEvent) => {
event.stopPropagation();
setTickets(newTickets);
};
const addToCartHandler = () => {
const selectedDays = isForfait ?
Object.entries(days).filter(([_, isChosen]) => isChosen).map(([day, _]) => day) :
[];
const itemForCart = {
id,
title,
price: typeof price === 'number' ? price : 0,
quantity: tickets,
selectedDays,
};
let newCart = cart.slice();
const billetIndex = newCart.findIndex(billet => billet.id === itemForCart.id);
if (billetIndex > -1) {
newCart[billetIndex].quantity += itemForCart.quantity;
} else {
newCart.push(itemForCart);
}
setCart(newCart); // Met à jour l'état global du panier
setCookie('cart', newCart, { expires: 7, sameSite: 'None', secure: true }); // Met à jour le cookie
};
const contentVariants = {
closed: {
opacity: 0,
height: 0,
overflow: 'hidden',
transition: {
duration: 0.2,
ease: 'easeInOut',
when: 'afterChildren',
},
},
open: {
opacity: 1,
height: title === "Forfait 2 jours" ? 150 : 120,
transition: {
duration: 0.2,
ease: 'easeInOut',
when: 'beforeChildren',
}
},
};
const cardVariants = {
hidden: { opacity: 0, y: 50 },
visible: {
opacity: 1,
y: 0,
transition: {
type: 'spring',
stiffness: 120,
},
},
};
const maxSelectedDays = 2;
const selectedDayCount = () => {
return Object.values(days).filter(Boolean).length;
};
const toggleDaySelection = (day: keyof typeof initialDays) => {
setDays(prevDays => {
const isSelected = prevDays[day];
const count = selectedDayCount();
if (!isSelected && count >= maxSelectedDays) {
return prevDays;
}
return { ...prevDays, [day]: !prevDays[day] };
});
};
return (
<motion.div
className="ticket-card"
layout
initial="hidden"
animate="visible"
variants={cardVariants}
onClick={() => {
setIsOpen(!isOpen);
setRotation(rotation === 0 ? 90 : 0);
}}
>
<div className="content">
<div className='left-part'>
<h4>{title}</h4>
<p>Les tickets ne sont pas remboursables.</p>
<p>Dernière entrée à 11H.</p>
</div>
<div className='right-part'>
<p>{price}€</p>
<motion.div className="svg-container" animate={{ rotate: rotation }}>
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="20" viewBox="0 0 13 20" fill="none">
<path d="M2 18L10 10L2 2" stroke="#4E4E4E" strokeWidth="4" />
</svg>
</motion.div>
</div>
</div>
<motion.div
className={`sub-menu ${title === "Forfait 2 jours" ? "forfait-2j" : ""}`}
variants={contentVariants}
initial="closed"
animate={isOpen ? "open" : "closed"}
exit="closed"
>
<div className='top-partsubmenu'>
<div className='left-part-sub'>
{isForfait && (Object.keys(days) as Array<keyof typeof days>).map(day => (
<label key={day}>
<input
type="checkbox"
checked={days[day]}
onChange={() => toggleDaySelection(day)}
/>
{day}
</label>
))}
<div className='sub-menu-left-part'>
<div className ="rect">
<img src="images/billet_pass1j.png" alt="Billet pass 1 jour" />
</div>
<div className='article-select'>
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="21" viewBox="0 0 22 21" fill="none">
<path d="M22 9.03848H14.6966L19.8599 4.10947L17.6953 2.04109L12.532 6.97007V0H9.46799V6.97007L4.30475 2.04109L2.13807 4.10947L7.30131 9.03848H0V11.9615H7.30131L2.13807 16.8906L4.30475 18.9589L9.46799 14.0299V21H12.532V14.0299L17.6953 18.9589L19.8599 16.8906L14.6966 11.9615H22V9.03848Z" fill="#FFD600"/>
</svg>
<p>x{tickets} Article(s) sélectionné(s)</p>
</div>
</div>
<div className="ticket-control">
<button onClick={(event) => handleTicketChange(Math.max(tickets - 1, 0), event)}>-</button>
<span>{tickets}</span>
<button className='sommeButton' onClick={(event) => handleTicketChange(tickets + 1, event)}>+</button>
</div>
</div>
</div>
<div className='delimiter-submenu'></div>
<div className='bottom-partsubmenu'>
<div className='bottom-part-left'>
<p>Sous-total</p>
<p>{tickets * price}€</p>
</div>
<button onClick={addToCartHandler}>AJOUTER AU PANIER</button>
</div>
</motion.div>
</motion.div>
);
}import Cookies from 'js-cookie';
// Définition des types pour les données que vous souhaitez stocker dans les cookies
interface UserData {
username: string;
email: string;
// ... autres champs
}
// Fonction pour définir un cookie
export const setCookie = (key: string, value: any, options?: Cookies.CookieAttributes) => {
Cookies.set(key, JSON.stringify(value), options);
};
// Fonction pour récupérer un cookie
export const getCookie = (key: string): any | null => {
const cookie = Cookies.get(key);
return cookie ? JSON.parse(cookie) : null;
};
// Fonction pour supprimer un cookie
export const removeCookie = (key: string) => {
Cookies.remove(key);
};
// removeCookie('cart');
type userData= {
pseudoUser: string;
emailUser: string;
idUser: number;
}
export const setUserCookie = (user: userData) => {
setCookie("Connected", user, {expires: 7});
}
export const isConnected = ():boolean => {
const user = getCookie("Connected");
if (user){
return true;
}
return false;
}
export const getUserCookie = ():userData => {
const user = getCookie("Connected");
return user;
}
export const removeUserCookie = () => {
removeCookie("Connected");
}ASSISTANT
En utilisant le code fourni, vous semblez vouloir mettre en œuvre la fonctionnalité de panier d'achat en utilisant les cookies pour sauvegarder les données du panier de l'utilisateur. Voici comment vous pouvez procéder étape par étape en intégrant les cookies pour les articles ajoutés, mis à jour ou supprimés du panier :
1. **Composant `ItemPanier`** - Dans ce composant, vous voudrez ajouter des fonctions pour gérer la quantité de chaque type de billet à la fois localement et dans le cookie du panier global.
```javascript
// Importez useEffect pour gérer les changements de quantité
import { useEffect } from 'react';
// Ajouter une fonction pour mettre à jour la quantité dans le cookie
const updateCartCookie = (typeBillet, newQuantite) => {
const cart = getCookie('cart') || [];
const itemIndex = cart.findIndex(item => item.typeBillet === typeBillet);
if (itemIndex > -1) {
cart[itemIndex].quantite = newQuantite;
} else {
cart.push({ typeBillet, quantite: newQuantite });
}
// Filtrez les éléments avec une quantité de 0 pour les enlever du panier
const filteredCart = cart.filter(item => item.quantite > 0);
setCookie('cart', filteredCart, { expires: 7 });
};
// Utiliser useEffect pour mettre à jour le cookie chaque fois que la quantité change
useEffect(() => {
updateCartCookie(props.typeBillet, quantite);
}, [quantite]);
```
2. **Suppression d'un élément du panier** - Vous voudrez probablement également permettre aux utilisateurs de supprimer un élément du panier. Pour cela, vous pouvez ajouter un gestionnaire d'événements pour le clic sur l'icône de la croix :
```javascript
// Gestionnaire pour la suppression de l'item
const removeFromCart = () => {
const cart = getCookie('cart') || [];
const newCart = cart.filter(item => item.typeBillet !== props.typeBillet);
setCookie('cart', newCart, { expires: 7 });
};
// Ajoutez un attribut onClick à votre icône de croix
<img className='cross' src="/icones/cross.svg" alt="croix" onClick={removeFromCart} />
```
3. **Calculer le sous-total dans `MenuConnexion`** - Actuellement, vous affichez un sous-total statique. Pour le calculer à partir du panier, vous pouvez le faire comme suit :
```javascript
// Récupérer le panier depuis le cookie
const cart = getCookie('cart') || [];
// Calculer le sous-total
const subtotal = cart.reduce((total, item) => total + (item.quantite * /* Le prix du billet - vous devrez le déterminer */), 0);
```
4. **Afficher les éléments du panier** - Dans `MenuConnexion`, au lieu d'afficher des éléments statiques, vous pouvez les rendre dynamiques en les mappant à partir des données du cookie :
```javascript
<section className='le-panier'>
{cart.map((item, index) => (
<ItemPanier key={index} typeBillet={item.typeBillet} quantite={item.quantite}/>
))}
</section>
```
5. **Mise à jour du contexte global du panier** - Lorsque vous ajoutez ou mettez à jour le panier dans `TicketCard`, assurez-vous également de mettre à jour le contexte global que vous utilisez avec `setCart`. Notez que `setCart` devrait être utilisé pour mettre à jour le contexte, alors que `setCookie` met à jour le cookie.
En implémentant ces étapes, vous aurez un système de panier qui sauvegarde l'état du panier dans les cookies et s'assure que le panier de l'utilisateur est conservé même après la fermeture du navigateur. Assurez-vous de synchroniser l'état du cookie avec le contexte global de l'application pour maintenir la cohérence des données sur les différents composants.