Dans cet application Flask React, implémente la logique pour inserer les billets dans la base de données lorsqu'on clique sur le bouton "RESERVER" de menu panier, from datetime import datetime, date, time, timedelta

class Faq:
    def __init__(self, idFaq: int, question: str, reponse: str):
        self._idFaq = idFaq
        self._question = question
        self._reponse = reponse
    
    def get_idFaq(self):
        return self._idFaq
    
    def get_question(self):
        return self._question
    
    def get_reponse(self):
        return self._reponse
    
    def to_dict(self):
        return {
            "idFaq": self._idFaq,
            "question": self._question,
            "reponse": self._reponse
        }

class User:         
    def __init__(self, idUser: int, pseudoUser: str, mdpUser: str, emailUser: str, statutUser: str):
        self.__idUser = idUser
        self.__pseudoUser = pseudoUser
        self.__mdpUser = mdpUser
        self.__emailUser = emailUser
        self.__statutUser = statutUser
        
    def get_idUser(self):
        return self.__idUser
    
    def get_pseudoUser(self):
        return self.__pseudoUser
    
    def get_mdpUser(self):
        return self.__mdpUser
    
    def get_emailUser(self):
        return self.__emailUser
    
    def get_statutUser(self):
        return self.__statutUser
    
    def set_pseudoUser(self, pseudoUser):
        self.__pseudoUser = pseudoUser
        
    def set_mdpUser(self, mdpUser):
        self.__mdpUser = mdpUser
        
    def set_emailUser(self, emailUser):
        self.__emailUser = emailUser

    def to_dict(self):
        return {
            "idUser": self.__idUser,
            "pseudoUser": self.__pseudoUser,
            "emailUser": self.__emailUser
        }

class Festival:
    def __init__(self, idF: int, nomF: str, villeF: str, dateDebutF: str, dateFinF: str):
        self.__idF = idF
        self.__nomF = nomF
        self.__villeF = villeF
        self.__dateDebutF = dateDebutF if isinstance(dateDebutF, date) else datetime.strptime(dateDebutF, '%Y-%m-%d').date()
        self.__dateFinF = dateFinF if isinstance(dateFinF, date) else datetime.strptime(dateFinF, '%Y-%m-%d').date()
        
    def get_idF(self):
        return self.__idF

    def get_nomF(self):
        return self.__nomF
    
    def get_villeF(self):
        return self.__villeF
    
    def get_dateDebutF(self):
        return self.__dateDebutF
    
    def get_dateFinF(self):
        return self.__dateFinF
    
    def __repr__(self):
        return f"({self.__idF}, {self.__nomF}, {self.__villeF}, {self.__dateDebutF}, {self.__dateFinF})"
    
    def to_dict(self):
        return {
            "idF": self.__idF,
            "nomF": self.__nomF,
            "villeF": self.__villeF,
            "dateDebutF": self.__dateDebutF.isoformat(),
            "dateFinF": self.__dateFinF.isoformat()
        }

    
class Type_Billet:
    def __init__(self, idType: int, duree: int):
        self.__idType = idType
        self.__duree = duree
    
    def get_idType(self):
        return self.__idType
    
    def get_duree(self):
        return self.__duree
    
    def to_dict(self):
        return {
            "idType": self.__idType,
            "duree": self.__duree
        }
    

class Spectateur:
    def __init__(self, idS: int, nomS: str, prenomS: str, adresseS: str, emailS: str, mdpS: str):
        self.__idS = idS
        self.__nomS = nomS
        self.__prenomS = prenomS
        self.__adresseS = adresseS
        self.__emailS = emailS
        self.__mdpS = mdpS
    
    def get_idS(self):
        return self.__idS
    
    def get_nomS(self):
        return self.__nomS
    
    def get_prenomS(self):
        return self.__prenomS
    
    def get_adresseS(self):
        return self.__adresseS
    
    def get_emailS(self):
        return self.__emailS
    
    def get_mdpS(self):
        return self.__mdpS
    
    def to_dict(self):
        return {
            "idS": self.__idS,
            "nomS": self.__nomS,
            "prenomS": self.__prenomS,
            "adresseS": self.__adresseS,
            "emailS": self.__emailS,
            "mdpS": self.__mdpS
        }

class Billet:
    def __init__(self, idB: int, idF: int, idType: int, idS: int, prix: int, dateAchat: str, dateDebutB: str, dateFinB: str):
        self.__idB = idB
        self.__idF = idF
        self.__idType = idType
        self.__idS = idS
        self.__prix = prix
        self.__dateAchat = dateAchat if isinstance(dateAchat, date) else datetime.strptime(dateAchat, '%Y-%m-%d').date() or datetime.strptime('0000-00-00', '%Y-%m-%d %H:%M:%S').date() 
        if dateDebutB != None and dateFinB != None:
            self.__dateDebutB = dateDebutB if isinstance(dateDebutB, date) else datetime.strptime(dateDebutB, '%Y-%m-%d').date() or datetime.strptime('0000-00-00', '%Y-%m-%d %H:%M:%S').date() 
            self.__dateFinB = dateFinB if isinstance(dateFinB, date) else datetime.strptime(dateFinB, '%Y-%m-%d').date() or datetime.strptime('0000-00-00', '%Y-%m-%d %H:%M:%S').date() 
        else:
            self.__dateDebutB = None
            self.__dateFinB = None
            
    def get_idB(self):
        return self.__idB
    
    def get_idFestival(self):
        return self.__idF
    
    def get_idType(self):
        return self.__idType
    
    def get_idSpectateur(self):
        return self.__idS
    
    def get_prix(self):
        return self.__prix
    
    def get_dateAchat(self):
        return self.__dateAchat
    
    def get_dateDebutB(self):
        return self.__dateDebutB
    
    def get_dateFinB(self):
        return self.__dateFinB
    
    def to_dict(self):
        return {
            "idB": self.__idB,
            "idF": self.__idF,
            "idType": self.__idType,
            "idS": self.__idS,
            "prix": self.__prix,
            "dateAchat": self.__dateAchat.isoformat(),
            "dateDebutB": self.__dateDebutB.isoformat(),
            "dateFinB": self.__dateFinB.isoformat()
        }
    
    
class Lieu:
    def __init__(self, idL: int, idF: int, nomL: str, adresseL: str, jaugeL: int):
        self.__idL = idL
        self.__idF = idF
        self.__nomL = nomL
        self.__adresseL = adresseL
        self.__jaugeL = jaugeL
        
    def get_idL(self):
        return self.__idL
    
    def get_idFestival(self):
        return self.__idF
    
    def get_nomL(self):
        return self.__nomL
    
    def get_adresseL(self):
        return self.__adresseL
    
    def get_jaugeL(self):
        return self.__jaugeL
    
    def to_dict(self):
        return {
            "idL": self.__idL,
            "idF": self.__idF,
            "nomL": self.__nomL,
            "adresseL": self.__adresseL,
            "jaugeL": self.__jaugeL
        }
    

class Hebergement:
    def __init__(self, idH: int, nomH: str, limitePlacesH: int, adresseH: int):
        self.__idH = idH
        self.__nomH = nomH
        self.__limitePlacesH = limitePlacesH
        self.__adresseH = adresseH
        
    def get_idH(self):
        return self.__idH
    
    def get_nomH(self):
        return self.__nomH
    
    def get_limitePlacesH(self):
        return self.__limitePlacesH
    
    def get_adresseH(self):
        return self.__adresseH
    
    def set_nomH(self, nomH):
        self.__nomH = nomH

    def set_limitePlacesH(self, limitePlacesH):
        self.__limitePlacesH = limitePlacesH

    def set_adresseH(self, adresseH):
        self.__adresseH = adresseH
    
    def to_dict(self):
        return {
            "idH": self.__idH,
            "nomH": self.__nomH,
            "limitePlacesH": self.__limitePlacesH,
            "adresseH": self.__adresseH
        }
    
class Programmer:
    def __init__(self, idF: int, idL: int, idH: int, dateArrivee: str, heureArrivee: str, dateDepart: str, heureDepart: str):
        self.__idF = idF
        self.__idL = idL
        self.__idH = idH
        self.__dateArrivee = dateArrivee if isinstance(dateArrivee, date) else datetime.strptime(dateArrivee, '%Y-%m-%d').date()
        self.__heureArrivee = self.timedelta_to_time(heureArrivee) if isinstance(heureArrivee, timedelta) else datetime.strptime(heureArrivee, '%H:%M').time()
        self.__dateDepart = dateDepart if isinstance(dateDepart, date) else datetime.strptime(dateDepart, '%Y-%m-%d').date()
        self.__heureDepart = self.timedelta_to_time(heureDepart) if isinstance(heureDepart, timedelta) else datetime.strptime(heureDepart, '%H:%M').time()
        
    @staticmethod
    def timedelta_to_time(td):
        return (datetime.min + td).time()
        
    def get_idFestival(self):
        return self.__idF
    
    def get_idLieu(self):
        return self.__idL
    
    def get_idHebergement(self):
        return self.__idH
    
    def get_dateArrivee(self):
        return self.__dateArrivee
    
    def get_heureArrivee(self):
        return self.__heureArrivee
    
    def get_dateDepart(self):
        return self.__dateDepart
    
    def get_heureDepart(self):
        return self.__heureDepart
    
    def to_dict(self):
        return {
            "idF": self.__idF,
            "idL": self.__idL,
            "idH": self.__idH,
            "dateArrivee": self.__dateArrivee.isoformat(),
            "heureArrivee": self.__heureArrivee.strftime("%H:%M:%S"),
            "dateDepart": self.__dateDepart.isoformat(),
            "heureDepart": self.__heureDepart.strftime("%H:%M:%S")
        }
    

class Groupe:
    def __init__(self, idG: int, idH: int, nomG: str, descriptionG: str):
        self.__idG = idG
        self.__idH = idH
        self.__nomG = nomG
        self.__descriptionG = descriptionG
        
    def get_idG(self):
        return self.__idG
    
    def get_idHebergement(self):
        return self.__idH
    
    def get_nomG(self):
        return self.__nomG
    
    def get_descriptionG(self):
        return self.__descriptionG
    
    def set_idHebergement(self, idH):
        self.__idH = idH
    
    def to_dict(self):
        return {
            "idG": self.__idG,
            "idH": self.__idH,
            "nomG": self.__nomG,
            "descriptionG": self.__descriptionG
        }
        
    def set_nomG(self, nomG):
        self.__nomG = nomG
        
    def set_descriptionG(self, descriptionG):
        self.__descriptionG = descriptionG
    

class Membre_Groupe:
    def __init__(self, idMG: int, idG, nomMG: str, prenomMG: str, nomDeSceneMG: str):
        self.__idMG = idMG
        self.__idG = idG
        self.__nomMG = nomMG
        self.__prenomMG = prenomMG
        self.__nomDeSceneMG = nomDeSceneMG
        
    def get_idMG(self):
        return self.__idMG
    
    def get_idGroupe(self):
        return self.__idG
    
    def get_nomMG(self):
        return self.__nomMG
    
    def get_prenomMG(self):
        return self.__prenomMG
    
    def get_nomDeSceneMG(self):
        return self.__nomDeSceneMG
    
    def __repr__(self):
        return f"({self.__idMG}, {self.__idG}, {self.__nomMG}, {self.__prenomMG}, {self.__nomDeSceneMG})"
    
    def to_dict(self):
        return {
            "idMG": self.__idMG,
            "idG": self.__idG,
            "nomMG": self.__nomMG,
            "prenomMG": self.__prenomMG,
            "nomDeSceneMG": self.__nomDeSceneMG
        }
    
    def set_nomMG(self, nomMG):
        self.__nomMG = nomMG
        
    def set_prenomMG(self, prenomMG):
        self.__prenomMG = prenomMG
        
    def set_nomDeSceneMG(self, nomDeSceneMG):
        self.__nomDeSceneMG = nomDeSceneMG
    
class Instrument:
    def __init__(self, idI: int, nomI: str):
        self.__idI = idI
        self.__nomI = nomI
        
    def get_idI(self):
        return self.__idI
    
    def get_nomI(self):
        return self.__nomI
    
    def to_dict(self):
        return {
            "idI": self.__idI,
            "nomI": self.__nomI
        }
    
class Style_Musical:
    def __init__(self, idSt: int, nomSt: str):
        self.__idSt = idSt
        self.__nomSt = nomSt
        
    def get_idSt(self):
        return self.__idSt
    
    def get_nomSt(self):
        return self.__nomSt
    
    def to_dict(self):
        return {
            "idSt": self.__idSt,
            "nomSt": self.__nomSt
        }
    
class Lien_Video:
    def __init__(self, idLV: int, idG: int, video: str):
        self.__idLV = idLV
        self.__idG = idG
        self.__video = video
        
    def get_idLV(self):
        return self.__idLV
    
    def get_idGroupe(self):
        return self.__idG
    
    def get_video(self):
        return self.__video
    
    def to_dict(self):
        return {
            "idLV": self.__idLV,
            "idG": self.__idG,
            "video": self.__video
        }
    
class Lien_Reseaux_Sociaux:
    def __init__(self, idLRS: int, idG: int, reseau: str):
        self.__idLRS = idLRS
        self.__idG = idG
        self.__reseau = reseau
        
    def get_idLRS(self):
        return self.__idLRS
    
    def get_idGroupe(self):
        return self.__idG
    
    def get_reseau(self):
        return self.__reseau
    
    def to_dict(self):
        return {
            "idLRS": self.__idLRS,
            "idG": self.__idG,
            "reseau": self.__reseau
        }
    
class Evenement:
    def __init__(self, idE: int, idG: int, idL: int, nomE: str, heureDebutE: str, heureFinE: str, dateDebutE: str, dateFinE: str):
        self.__idE = idE
        self.__idG = idG
        self.__idL = idL
        self.__nomE = nomE
        self.__heureDebutE = self.timedelta_to_time(heureDebutE) if isinstance(heureDebutE, timedelta) else datetime.strptime(heureDebutE, '%H:%M').time()
        self.__heureFinE = self.timedelta_to_time(heureFinE) if isinstance(heureFinE, timedelta) else datetime.strptime(heureFinE, '%H:%M').time()
        self.__dateDebutE = dateDebutE if isinstance(dateDebutE, date) else datetime.strptime(dateDebutE, "%Y-%m-%d").date()
        self.__dateFinE = dateFinE if isinstance(dateFinE, date) else datetime.strptime(dateFinE, "%Y-%m-%d").date()

    @staticmethod
    def timedelta_to_time(td):
        return (datetime.min + td).time()
        
    def get_idE(self):
        return self.__idE
    
    def get_idG(self):
        return self.__idG
    
    def get_idL(self):
        return self.__idL
    
    def get_nomE(self):
        return self.__nomE
    
    def get_heureDebutE(self):
        return self.__heureDebutE
    
    def get_heureFinE(self):
        return self.__heureFinE
    
    def get_dateDebutE(self):
        return self.__dateDebutE
    
    def get_dateFinE(self):
        return self.__dateFinE
    
    def set_idG(self, idG):
        self.__idG = idG
        
    def set_idL(self, idL):
        self.__idL = idL
    
    def set_nomE(self, nomE):
        self.__nomE = nomE
        
    def set_heureDebutE(self, heureDebutE):
        self.__heureDebutE = heureDebutE
        
    def set_heureFinE(self, heureFinE):
        self.__heureFinE = heureFinE
        
    def set_dateDebutE(self, dateDebutE):
        self.__dateDebutE = dateDebutE
        
    def set_dateFinE(self, dateFinE):
        self.__dateFinE = dateFinE
    
    def to_dict(self):
        return {
            "idE": self.__idE,
            "idG": self.__idG,
            "idL": self.__idL,
            "nomE": self.__nomE,
            "heureDebutE": self.__heureDebutE.strftime("%H:%M:%S") if self.__heureDebutE else None,
            "heureFinE": self.__heureFinE.strftime("%H:%M:%S") if self.__heureFinE else None,
            "dateDebutE": self.__dateDebutE.isoformat() if self.__dateDebutE else None,
            "dateFinE": self.__dateFinE.isoformat() if self.__dateFinE else None
        }
    
class Activite_Annexe:
    def __init__(self, idE: int, typeA: str, ouvertAuPublic: bool):
        self.__idE = idE
        self.__typeA = typeA
        self.__ouvertAuPublic = ouvertAuPublic
        
    def get_idEvenement(self):
        return self.__idE
    
    def get_typeA(self):
        return self.__typeA
    
    def get_ouvertAuPublic(self):
        return self.__ouvertAuPublic
    
    def to_dict(self):
        return {
            "idE": self.__idE,
            "typeA": self.__typeA,
            "ouvertAuPublic": self.__ouvertAuPublic
        }
    
class Concert:
    def __init__(self, idE: int, tempsMontage: str, tempsDemontage: str):
        self.__idE = idE
        self.__tempsMontage = self.timedelta_to_time(tempsMontage) if isinstance(tempsMontage, timedelta) else datetime.strptime(tempsMontage, '%H:%M').time()
        self.__tempsDemontage = self.timedelta_to_time(tempsDemontage) if isinstance(tempsDemontage, timedelta) else datetime.strptime(tempsDemontage, '%H:%M').time()
        
    @staticmethod
    def timedelta_to_time(td):
        return (datetime.min + td).time()
    
    def get_idEvenement(self):
        return self.__idE
    
    def get_tempsMontage(self):
        return self.__tempsMontage
    
    def get_tempsDemontage(self):
        return self.__tempsDemontage

    def to_dict(self):
        return {
            "idE": self.__idE,
            "tempsMontage": self.__tempsMontage.strftime("%H:%M:%S"),
            "tempsDemontage": self.__tempsDemontage.strftime("%H:%M:%S")
        }

class Groupe_Style:
    def __init__(self, idG: int, idSt: int):
        self.__idG = idG
        self.__idSt = idSt
        
    def get_idG(self):
        return self.__idG
    
    def get_idSt(self):
        return self.__idSt
    
    def to_dict(self):
        return {
            "idG": self.__idG,
            "idSt": self.__idSt
        }from flask import Flask, send_file
from flask_cors import CORS
from flask import Flask, request, jsonify, render_template, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
import sys

sys.path.append('../BD')
sys.path.append('../mail')

from GroupeBD import GroupeBD
from LienRS_BD import LienRS_BD
from HebergementBD import HebergementBD
from Membre_GroupeBD import Membre_GroupeBD
from ConnexionBD import ConnexionBD
from UserBD import UserBD
from emailSender import EmailSender
from generateurCode import genererCode
from FaqBD import FaqBD
from EvenementBD import EvenementBD
from Style_MusicalBD import Style_MusicalBD
from Groupe_StyleBD import Groupe_StyleBD
from ConcertBD import ConcertBD
from Activite_AnnexeBD import Activite_AnnexeBD
from LieuBD import LieuBD
from BilletBD import BilletBD
from Type_BilletBD import Type_BilletBD
from SpectateurBD import SpectateurBD
from InstrumentBD import InstrumentBD

from BD import * 


MAIL_FESTIUTO = "festiuto@gmail.com"
MDP_FESTIUTO = "xutxiocjikqolubq"

app = Flask(__name__)
# app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://coursimault:coursimault@servinfo-mariadb/DBcoursimault'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:root@localhost/gestiuto'
CORS(app, resources={r"/*": {"origins": "*"}})
db = SQLAlchemy(app)

app.config['BOOTSTRAP_SERVE_LOCAL'] = True

@app.route('/')
def index():
    return render_template('API.html')

@app.route('/getNomsArtistes')
def getNomsArtistes():
    connexion_bd = ConnexionBD()
    membre_groupebd = Membre_GroupeBD(connexion_bd)
    res = membre_groupebd.getNomsArtistes_json()
    if res is None:
        return jsonify({"error": "Aucun artiste trouve"})
    else:
        return res

@app.route('/getArtistes')
def getArtistes():
    connexion_bd = ConnexionBD()
    groupebd = GroupeBD(connexion_bd)
    res = groupebd.get_groupes_json()
    if res is None:
            return jsonify({"error": "Aucun artiste trouve"})
    else:
        return res
    
@app.route('/filtrerArtistes')
def filtrerArtistes():
    connexion_bd = ConnexionBD()
    evenementbd = EvenementBD(connexion_bd)
    liste_groupes_21 = evenementbd.groupes_21_juillet_to_json()
    liste_groupes_22 = evenementbd.groupes_22_juillet_to_json()
    liste_groupes_23 = evenementbd.groupes_23_juillet_to_json()
    return jsonify({"21 juillet": liste_groupes_21, "22 juillet": liste_groupes_22, "23 juillet": liste_groupes_23})

@app.route('/getInformationsSupplementairesArtiste/<int:id>')
def getInformationsSupplementairesArtiste(id):
    connexion_bd = ConnexionBD()
    lienRS = LienRS_BD(connexion_bd)
    res = lienRS.get_lienRS_json(id)
    if res is None:
        return jsonify({"error": "Aucun artiste trouve"})
    else:
        return res

@app.route('/getArtiste/<int:id>')
def getArtiste(id):
    connexion_bd = ConnexionBD()
    membre_groupebd = Membre_GroupeBD(connexion_bd)
    mb = membre_groupebd.get_artiste_by_id(id)
    res = mb.to_dict()
    return jsonify({"error": "Aucun artiste trouve"}) if res is None else res

@app.route('/connecter', methods=['POST'])
def connecter():
    connexion_bd = ConnexionBD()
    userbd = UserBD(connexion_bd)
    data = request.get_json()
    print(data)
    email = data["email"]
    password = data["password"]
    if userbd.exist_user(email, password):
        return userbd.user_to_json(userbd.get_user_by_email(email))
    else:
        return jsonify({"error": "Utilisateur non trouve"})
    
@app.route('/inscription', methods=['POST'])
def inscription():
    connexion_bd = ConnexionBD()
    userbd = UserBD(connexion_bd)
    data = request.get_json()
    print(data)
    pseudo = data["pseudo"]
    email = data["email"]
    password = data["password"]
    if userbd.exist_user(email, password):
        return jsonify({"error": "Utilisateur déjà existant"})
    else:
        res = userbd.add_user(pseudo, email, password)
        if res:
            return userbd.user_to_json(userbd.get_user_by_email(email))
        elif res == "emailErr":
            return jsonify({"error": "Email déjà existant"})
        else:
            return jsonify({"error": "Erreur lors de l'ajout de l'utilisateur"})
        
@app.route('/modifierProfil', methods=['POST'])
def modifierProfil():
    connexion_bd = ConnexionBD()
    userbd = UserBD(connexion_bd)
    data = request.get_json()
    print(data)
    idUser =data['id']
    pseudo = data["pseudo"]
    email = data["email"]
    password = data["password"]
    ancien_mdp = data['oldPassword']
    if userbd.exist_user_with_id(idUser, ancien_mdp):
        res = userbd.update_user(idUser, email, pseudo, password)
        if res:
            return userbd.user_to_json(userbd.get_user_by_email(email))
        elif res == "emailErr":
            return jsonify({"error": "Email déjà existant"})
        else:
            return jsonify({"error": "Erreur lors de la modification de l'utilisateur"})
    else:
        return jsonify({"error": "Utilisateur non trouve"})

@app.route('/envoyerCodeVerification', methods=['POST'])
def envoyerCodeVerification():
    data = request.get_json()
    emailUser = data["email"]
    
    connexion_bd = ConnexionBD()
    userbd = UserBD(connexion_bd)
    
    if not userbd.email_exists(emailUser):
        return jsonify({"error": "Email non existant"})
    
    code = genererCode()
    email_sender = EmailSender(MAIL_FESTIUTO, MDP_FESTIUTO)
    res = email_sender.sendCodeVerification(emailUser, code)
    if res:
        resAjout = userbd.ajouterCodeVerification(emailUser, code)
        if resAjout:
            return jsonify({"success": "code envoyé"})
    return jsonify({"error": "erreur lors de l'envoi du code"})

@app.route('/testerCodeVerification', methods=['POST'])
def tester_code_verification():
    data = request.get_json()
    emailUser = data["email"]
    code = data["code"]
    
    connexion_bd = ConnexionBD()
    userbd = UserBD(connexion_bd)
    
    if not userbd.email_exists(emailUser):
        return jsonify({"error": "Email non existant"})
    
    if userbd.tester_code_verification(emailUser, code):
        return jsonify({"success": "code correct"})
    else:
        return jsonify({"error": "code incorrect"})

@app.route("/modifierMdp", methods=['POST'])
def modifierMdp():
    data = request.get_json()
    emailUser = data["email"]
    nouveauMdp = data["password"]
    code = data["code"]
    
    connexion_bd = ConnexionBD()
    userbd = UserBD(connexion_bd)
    
    if not userbd.email_exists(emailUser):
        return jsonify({"error": "Email non existant"})
    
    if userbd.tester_code_verification(emailUser, code):
        res = userbd.update_password(emailUser, nouveauMdp)
        if res:
            return jsonify({"success": "mot de passe modifié"})
        else:
            return jsonify({"error": "erreur lors de la modification du mot de passe"})

@app.route('/ajouterImage', methods=['POST'])
def ajouterImage():
    # permet de stocker l'image dans la base de données sous forme de blob
    idG = request.form['idG']
    image_file = request.files['img']
    if image_file:
        image = image_file.read()
        connexion_bd = ConnexionBD()
        groupebd = GroupeBD(connexion_bd)
        res = groupebd.add_image(idG, image)
        if res:
            return jsonify({"success": "image ajoutée"})
    return jsonify({"error": "erreur lors de l'ajout de l'image"})

import io

@app.route('/getImageArtiste/<int:id>')
def getImageArtiste(id):
    #get l'image en blob de l'artiste et l'affiche
    try:
        connexion_bd = ConnexionBD()
        groupebd = GroupeBD(connexion_bd)
        image_blob = groupebd.get_image(id)
        if image_blob is None:
            return jsonify({"error": "Aucune image trouve"})
        else:
                image = io.BytesIO(image_blob)
                image.seek(0)
                return send_file(image, mimetype='image/jpeg')
    except Exception as e:
        print(e)
        return jsonify({"error": "erreur lors de la récupération de l'image"})

@app.route('/getFaq')
def get_faq():
    connexion_bd = ConnexionBD()
    faqbd = FaqBD(connexion_bd)
    res = faqbd.get_faqs_json()
    if res is None:
        return jsonify({"error": "Aucune faq trouve"})
    else:
        return res
    
@app.route("/recherche/", methods=["GET", "POST"])
def recherche():
    if request.method == "POST":
        recherche = request.form.get("recherche", "")
    else:
        recherche = request.args.get("recherche", "")
    connexion_bd = ConnexionBD()
    groupebd = GroupeBD(connexion_bd)
    membre_groupebd = Membre_GroupeBD(connexion_bd)
    groupes = groupebd.search_groupes(recherche) if recherche else []
    artistes = membre_groupebd.search_membres_groupe(recherche) if recherche else []
    return render_template("recherche.html", recherche=recherche, groupes=groupes, artistes=artistes)

@app.route("/styles_musicaux", methods=["GET", "POST"])
def filtrer_styles():
    connexion_bd = ConnexionBD()
    style_musicalbd = Style_MusicalBD(connexion_bd)
    styles_musicaux = style_musicalbd.get_all_styles()
    liste_groupes = []
    if request.method == "POST":
        nomStyle = request.form.get("nomStyle", "")
        idStyle = style_musicalbd.get_id_style_by_name(nomStyle)
        if idStyle is not None:
            groupe_stylebd = Groupe_StyleBD(connexion_bd)
            liste_groupes = groupe_stylebd.get_groupes_selon_style(idStyle)
    return render_template("styles_musicaux.html", styles_musicaux=styles_musicaux, liste_groupes=liste_groupes)

@app.route("/menu_admin/", methods=["GET", "POST"])
def menu_admin():
    return render_template("menu_admin.html")

@app.route("/login_admin")
def login_admin():
    return render_template("login.html")

@app.route("/groupes_festival")
def groupes_festival():
    connexionbd = ConnexionBD()
    groupebd = GroupeBD(connexionbd)
    liste_groupes = groupebd.get_all_groupes()

    if liste_groupes is None:
        liste_groupes = []

    return render_template("groupes_festival.html", liste_groupes=liste_groupes)

@app.route("/hebergements_festival")
def hebergements_festival():
    connexionbd = ConnexionBD()
    hebergementbd = HebergementBD(connexionbd)
    liste_hebergements = hebergementbd.get_all_hebergements()

    if liste_hebergements is None:
        liste_hebergements = []

    return render_template("hebergements_festival.html", liste_hebergements=liste_hebergements)


@app.route("/modifier_groupe", methods=["POST"])
def modifier_groupe():
    connexionbd = ConnexionBD()
    groupebd = GroupeBD(connexionbd)
    id_groupe = request.form["id_groupe"]
    nom_groupe = request.form["nom_groupe"]
    description_groupe = request.form["description_groupe"]
    groupe = groupebd.get_groupe_by_id(id_groupe)
    groupe.set_nomG(nom_groupe)
    groupe.set_descriptionG(description_groupe)
    groupebd.modifier_img(id_groupe, request.files['image_groupe'].read())
    succes = groupebd.update_groupe(groupe)
    if succes:
        print(f"Le groupe {id_groupe} a été mis à jour.")
    else:
        print(f"La mise à jour du groupe {id_groupe} a échoué.")
    return redirect(url_for("groupes_festival"))

@app.route("/modifier_hebergement", methods=["POST"])
def modifier_hebergement():
    connexionbd = ConnexionBD()
    hebergementbd = HebergementBD(connexionbd)
    id_hebergement = request.form["id_hebergement"]
    nom_hebergement = request.form["nom_hebergement"]
    adresse_hebergement = request.form["adresse_hebergement"]
    limite_places_hebergement = request.form["limite_places"]
    hebergement = hebergementbd.get_hebergement_by_id(id_hebergement)
    hebergement.set_nomH(nom_hebergement)
    hebergement.set_adresseH(adresse_hebergement)
    hebergement.set_limitePlacesH(limite_places_hebergement)
    succes = hebergementbd.update_hebergement(hebergement)
    if succes:
        print(f"L'hebergement {id_hebergement} a été mis à jour.")
    else:
        print(f"La mise à jour de l'hebergement {id_hebergement} a échoué.")
    return redirect(url_for("hebergements_festival"))

@app.route("/supprimer_groupe", methods=["POST"])
def supprimer_groupe():
    connexionbd = ConnexionBD()
    groupebd = GroupeBD(connexionbd)
    id_groupe = request.form["id_groupe"]
    groupe = groupebd.get_groupe_by_id(id_groupe)
    nom_groupe = groupe.get_nomG()
    groupebd.delete_groupe_by_name(groupe, nom_groupe)
    return redirect(url_for("groupes_festival"))

@app.route("/supprimer_hebergement", methods=["POST"])
def supprimer_hebergement():
    connexionbd = ConnexionBD()
    hebergementbd = HebergementBD(connexionbd)
    id_hebergement = request.form["id_hebergement"]
    hebergementbd.delete_hebergement_by_id(id_hebergement)
    return redirect(url_for("hebergements_festival"))

@app.route("/ajouter_groupe", methods=["POST"])
def ajouter_groupe():
    connexionbd = ConnexionBD()
    groupebd = GroupeBD(connexionbd)
    nom_groupe = request.form["nom_nouveau_groupe"] if request.form["nom_nouveau_groupe"] else None
    description_groupe = request.form["description_nouveau_groupe"] if request.form["description_nouveau_groupe"] else None
    groupe = Groupe(None, None, nom_groupe, description_groupe)
    groupebd.insert_groupe(groupe)
    idG = groupebd.get_id_groupe_by_name(nom_groupe)
    image_file = request.files['image_nouveau_groupe']
    
    if image_file:
        image = image_file.read()
        connexion_bd = ConnexionBD()
        groupebd = GroupeBD(connexion_bd)
        res = groupebd.add_image(idG, image)
        if (res):
            print("image ajoutée")
        else:
            print("erreur lors de l'ajout de l'image")

    return redirect(url_for("groupes_festival"))

@app.route("/ajouter_hebergement", methods=["POST"])
def ajouter_hebergement():
    connexionbd = ConnexionBD()
    hebergementbd = HebergementBD(connexionbd)
    nom_hebergement = request.form["nom_nouveau_hebergement"]
    adresse_hebergement = request.form["adresse_hebergement"]
    limite_places_hebergement = request.form["limite_places"]
    hebergement = Hebergement(None, nom_hebergement, limite_places_hebergement, adresse_hebergement)
    hebergementbd.insert_hebergement(hebergement)
    return redirect(url_for("hebergements_festival"))

@app.route("/consulter_groupe/<int:id_groupe>")
def consulter_groupe(id_groupe):
    connexionbd = ConnexionBD()
    groupebd = GroupeBD(connexionbd)
    groupe = groupebd.get_groupe_by_id(id_groupe)
    membres_groupe = groupebd.get_membres_groupe(id_groupe)
    if not membres_groupe:
        return render_template("membres_groupe.html", groupe=groupe, membres_groupe=[])
    return render_template("membres_groupe.html", groupe=groupe, membres_groupe=membres_groupe)

@app.route("/consulter_hebergement/<int:id_hebergement>")
def consulter_hebergement(id_hebergement):
    connexionbd = ConnexionBD()
    hebergementbd = HebergementBD(connexionbd)
    hebergement = hebergementbd.get_hebergement_by_id(id_hebergement)
    groupes_hebergement = hebergementbd.get_groupes_hebergement(id_hebergement)
    groupes_not_in_hebergement = hebergementbd.get_groupes_not_in_hebergement(id_hebergement)

    dict_groupes_not_in_hebergement = {}
    for groupe in groupes_not_in_hebergement:
        id_hebergement_groupe = groupe.get_idHebergement()
        nom_hebergement_groupe = hebergementbd.get_hebergement_by_id(id_hebergement_groupe).get_nomH() if id_hebergement_groupe is not None else None
        dict_groupes_not_in_hebergement[groupe] = nom_hebergement_groupe

    return render_template("groupes_hebergement.html", hebergement=hebergement, groupes_hebergement=groupes_hebergement, dict_groupes_not_in_hebergement=dict_groupes_not_in_hebergement)

@app.route("/modifier_membre", methods=["POST"])
def modifier_membre_groupe():
    connexionbd = ConnexionBD()
    membre_groupebd = Membre_GroupeBD(connexionbd)
    nom_membre_groupe = request.form["nom_membre"]
    prenom_membre_groupe = request.form["prenom_membre"]
    nom_scene_membre_groupe = request.form["nom_scene_membre"]
    id_membre_groupe = request.form["id_membre"]
    membre_groupe = membre_groupebd.get_artiste_by_id(id_membre_groupe)
    membre_groupe.set_nomMG(nom_membre_groupe)
    membre_groupe.set_prenomMG(prenom_membre_groupe)
    membre_groupe.set_nomDeSceneMG(nom_scene_membre_groupe)
    succes = membre_groupebd.update_membre_groupe(membre_groupe)
    if succes:
        print(f"Le membre {id_membre_groupe} a été mis à jour.")
    else:
        print(f"La mise à jour du membre {id_membre_groupe} a échoué.")
    return redirect(url_for("consulter_groupe", id_groupe=membre_groupe.get_idGroupe()))

@app.route("/supprimer_membre", methods=["POST"])
def supprimer_membre_groupe():
    connexionbd = ConnexionBD()
    membre_groupebd = Membre_GroupeBD(connexionbd)
    id_membre_groupe = request.form["id_membre"]
    membre_groupe = membre_groupebd.get_artiste_by_id(id_membre_groupe)
    nom_scene_membre_groupe = membre_groupe.get_nomDeSceneMG()
    membre_groupebd.delete_membre_groupe_by_name_scene(membre_groupe, nom_scene_membre_groupe)
    return redirect(url_for("consulter_groupe", id_groupe=membre_groupe.get_idGroupe()))

@app.route("/supprimer_groupe_hebergement", methods=["POST"])
def supprimer_groupe_hebergement():
    connexionbd = ConnexionBD()
    groupebd = GroupeBD(connexionbd)
    id_hebergement = request.form["id_hebergement"]
    id_groupe = request.form["id_groupe"]
    groupe = groupebd.get_groupe_by_id(id_groupe)
    groupe.set_idHebergement(None)
    print(groupe.get_idHebergement())
    groupebd.update_groupe(groupe)
    return redirect(url_for("consulter_hebergement", id_hebergement=id_hebergement))

@app.route("/ajouter_membre", methods=["POST"])
def ajouter_membre_groupe():
    connexionbd = ConnexionBD()
    membre_groupebd = Membre_GroupeBD(connexionbd)
    id_groupe = request.form["id_groupe"]
    nom_membre_groupe = request.form["nom_nouveau_membre"] if request.form["nom_nouveau_membre"] else None
    prenom_membre_groupe = request.form["prenom_nouveau_membre"] if request.form["prenom_nouveau_membre"] else None
    nom_scene_membre_groupe = request.form["nom_scene_nouveau_membre"] if request.form["nom_scene_nouveau_membre"] else None
    membre_groupe = Membre_Groupe(None, id_groupe, nom_membre_groupe, prenom_membre_groupe, nom_scene_membre_groupe)
    membre_groupebd.insert_membre_groupe(membre_groupe)
    return redirect(url_for("consulter_groupe", id_groupe=id_groupe))

@app.route("/ajouter_groupe_hebergement", methods=["POST"])
def ajouter_groupe_hebergement():
    connexion_bd = ConnexionBD()
    groupebd = GroupeBD(connexion_bd)
    id_groupe = request.form["nom_groupe"]
    id_hebergement = request.form["id_hebergement"]
    groupe = groupebd.get_groupe_by_id(id_groupe)
    groupe.set_idHebergement(id_hebergement)
    groupebd.update_groupe(groupe)
    return redirect(url_for("consulter_hebergement", id_hebergement=id_hebergement))

@app.route("/evenements_festival")
def evenements_festival():
    connexionbd = ConnexionBD()
    evenementbd = EvenementBD(connexionbd)
    groupebd = GroupeBD(connexionbd)
    liste_groupes = groupebd.get_all_groupes()
    liste_evenements = evenementbd.get_all_evenements()
    liste_evenements_concerts = []
    liste_evenements_activites_annexes = []
    if not liste_evenements:
        return render_template("evenements_festival.html", liste_evenements=[], liste_evenements_concerts=[], liste_evenements_activites_annexes=[], liste_lieux=[], liste_groupes=[])
    lieubd = LieuBD(connexionbd)
    liste_lieux = lieubd.get_all_lieux()
    for evenement in liste_evenements:
        if evenementbd.verify_id_in_concert(evenement.get_idE()):
            liste_evenements_concerts.append(evenement)
        elif evenementbd.verify_id_in_activite_annexe(evenement.get_idE()):
            liste_evenements_activites_annexes.append(evenement)
    return render_template("evenements_festival.html", liste_evenements=liste_evenements, liste_evenements_concerts=liste_evenements_concerts, liste_evenements_activites_annexes=liste_evenements_activites_annexes, liste_lieux=liste_lieux, liste_groupes=liste_groupes)

@app.route("/modifier_evenement", methods=["POST"])
def modifier_evenement():
    connexionbd = ConnexionBD()
    evenementbd = EvenementBD(connexionbd)
    id_evenement = request.form["id_evenement"]
    id_lieu = request.form["lieu_evenement"] if request.form["lieu_evenement"] else None
    id_groupe = request.form["groupe_evenement"] if request.form["groupe_evenement"] else None
    nom_evenement = request.form["nom_evenement"]
    date_debut = request.form["date_debut"]
    date_fin = request.form["date_fin"]
    heure_debut = request.form["heure_debut"]
    heure_fin = request.form["heure_fin"]
    evenement = evenementbd.get_evenement_by_id(id_evenement)
    evenement.set_idG(id_groupe)
    evenement.set_idL(id_lieu)
    evenement.set_nomE(nom_evenement)
    evenement.set_dateDebutE(date_debut)
    evenement.set_dateFinE(date_fin)
    evenement.set_heureDebutE(heure_debut)
    evenement.set_heureFinE(heure_fin)
    succes = evenementbd.update_evenement(evenement)
    if succes:
        print(f"L'événement {id_evenement} a été mis à jour.")
    else:
        print(f"La mise à jour de l'événement {id_evenement} a échoué.")
    return redirect(url_for("evenements_festival"))

@app.route("/supprimer_evenement", methods=["POST"])
def supprimer_evenement():
    connexionbd = ConnexionBD()
    evenementbd = EvenementBD(connexionbd)
    concert_bd = ConcertBD(connexionbd)
    id_evenement = request.form["id_evenement"]
    evenement = evenementbd.get_evenement_by_id(id_evenement)
    nom_evenement = evenement.get_nomE()
    if evenementbd.verify_id_in_concert(id_evenement):
        concert_bd.delete_concert_by_id(id_evenement)
    elif evenementbd.verify_id_in_activite_annexe(id_evenement):
        activite_annexe_bd = Activite_AnnexeBD(connexionbd)
        activite_annexe_bd.delete_activite_annexe_by_id(id_evenement)
    evenementbd.delete_evenement_by_name(evenement, nom_evenement)
    return redirect(url_for("evenements_festival"))

@app.route("/ajouter_evenement", methods=["POST"])
def ajouter_evenement():
    connexionbd = ConnexionBD()
    evenementbd = EvenementBD(connexionbd)
    id_lieu = request.form["lieu_evenement"] if request.form["lieu_evenement"] else None
    id_groupe = request.form["groupe_evenement"] if request.form["groupe_evenement"] else None
    nom_evenement = request.form["nom_evenement"] if request.form["nom_evenement"] else None
    date_debut = request.form["date_debut"] if request.form["date_debut"] else None
    date_fin = request.form["date_fin"] if request.form["date_fin"] else None
    heure_debut = request.form["heure_debut"] if request.form["heure_debut"] else None
    heure_fin = request.form["heure_fin"] if request.form["heure_fin"] else None
    evenement = Evenement(None, id_groupe, id_lieu, nom_evenement, heure_debut, heure_fin, date_debut, date_fin)
    id_evenement = evenementbd.insert_evenement(evenement)
    type_evenement = request.form["type_evenement"]

    if type_evenement == "concert":
        temps_montage = request.form["temps_montage"] if request.form["temps_montage"] else None
        temps_demontage = request.form["temps_demontage"] if request.form["temps_demontage"] else None
        concert_bd = ConcertBD(connexionbd)
        concert = Concert(id_evenement, temps_montage, temps_demontage)
        concert_bd.insert_concert(concert)

    elif type_evenement == "activite":
        type_activite = request.form["type_activite"] if request.form["type_activite"] else None
        ouvert_public = True if "ouvert_public" in request.form else False
        print(ouvert_public)
        activite_annexebd = Activite_AnnexeBD(connexionbd)
        activite_annexe = Activite_Annexe(id_evenement, type_activite, ouvert_public)
        print(activite_annexe.get_ouvertAuPublic())
        activite_annexebd.insert_activite_annexe(activite_annexe)
    return redirect(url_for("evenements_festival"))

@app.route("/billets_festival")
def billets_festival():
    connexionbd = ConnexionBD()
    billetbd = BilletBD(connexionbd)
    liste_billets = billetbd.get_all_billets()
    if not liste_billets:
        return render_template("admin_billets.html", liste_billets=[])
    return render_template("admin_billets.html", liste_billets=liste_billets)

@app.route("/lieux_festival")
def lieux_festival():
    connexionbd = ConnexionBD()
    lieubd = LieuBD(connexionbd)
    liste_lieux = lieubd.get_all_lieux()
    if not liste_lieux:
        return render_template("admin_lieux.html", liste_lieux=[])
    return render_template("admin_lieux.html", liste_lieux=liste_lieux)

@app.route("/types_billet_festival")
def types_billet_festival():
    connexionbd = ConnexionBD()
    type_billetbd = Type_BilletBD(connexionbd)
    liste_types_billet = type_billetbd.get_all_types_billets()
    if not liste_types_billet:
        return render_template("admin_types_billet.html", liste_types_billet=[])
    return render_template("admin_types_billet.html", liste_types_billet=liste_types_billet)

@app.route("/spectateurs_festival")
def spectateurs_festival():
    connexionbd = ConnexionBD()
    spectateurbd = SpectateurBD(connexionbd)
    liste_spectateurs = spectateurbd.get_all_spectateurs()
    if not liste_spectateurs:
        return render_template("admin_spectateurs.html", liste_spectateurs=[])
    return render_template("admin_spectateurs.html", liste_spectateurs=liste_spectateurs)

@app.route("/styles_musicaux_festival")
def styles_musicaux_festival():
    connexionbd = ConnexionBD()
    style_musicalbd = Style_MusicalBD(connexionbd)
    liste_styles_musicaux = style_musicalbd.get_all_styles()
    if not liste_styles_musicaux:
        return render_template("admin_styles.html", liste_styles_musicaux=[])
    return render_template("admin_styles.html", liste_styles_musicaux=liste_styles_musicaux)

@app.route("/instruments_festival")
def instruments_festival():
    connexionbd = ConnexionBD()
    instrumentbd = InstrumentBD(connexionbd)
    liste_instruments = instrumentbd.get_all_instruments()
    if not liste_instruments:
        return render_template("admin_instruments.html", liste_instruments=[])
    return render_template("admin_instruments.html", liste_instruments=liste_instruments)

@app.route("/users_festival")
def users_festival():
    connexionbd = ConnexionBD()
    userbd = UserBD(connexionbd)
    liste_users = userbd.get_all_users()
    if not liste_users:
        return render_template("admin_users.html", liste_users=[])
    return render_template("admin_users.html", liste_users=liste_users)

@app.route("/ajouter_user", methods=["POST"])
def ajouter_user():
    connexionbd = ConnexionBD()
    userbd = UserBD(connexionbd)
    pseudo_user = request.form["pseudo_user"]
    email_user = request.form["email_user"]
    mdp_user = request.form["mdp_user"]
    statut_user = request.form["statut_user"]
    user = User(None, pseudo_user, mdp_user, email_user, statut_user)
    userbd.insert_user_admin(user)
    return redirect(url_for("users_festival"))

@app.route("/supprimer_user", methods=["POST"])
def supprimer_user():
    connexionbd = ConnexionBD()
    userbd = UserBD(connexionbd)
    id_user = request.form["id_user"]
    userbd.delete_user_by_id(id_user)
    return redirect(url_for("users_festival"))

@app.route("/modifier_user", methods=["POST"])
def modifier_user():
    connexionbd = ConnexionBD()
    userbd = UserBD(connexionbd)
    id_user = request.form["id_user"]
    pseudo_user = request.form["pseudo_user"]
    email_user = request.form["email_user"]
    mdp_user = request.form["mdp_user"]
    user = userbd.get_user_by_id(id_user)
    user.set_pseudoUser(pseudo_user)
    user.set_emailUser(email_user)
    user.set_mdpUser(mdp_user)
    success = userbd.update_user_admin(user)
    if success:
        print(f"L'utilisateur {id_user} a été mis à jour.")
    else:
        print(f"La mise à jour de l'utilisateur {id_user} a échoué.")
    return redirect(url_for("users_festival"))

if __name__ == '__main__':
    app.run(debug=True, port=8080)import { TargetAndTransition, 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 = {
  "20 Jui": false,
  "21 Jui": false,
  "22 Jui": false,
};

type Props = {
  id: number;
  title: string;
  price: number | string;
  nbTicket: number;
  isForfait?: boolean;
  disabled?: 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 [isLoading, setIsLoading] = useState(false);
  const [isAdded, setIsAdded] = useState(false);
  type DayKey = "20 Jui" |"21 Jui"|"22 Jui";
  const pricesByDay:{[key in DayKey]: number} = {
    "20 Jui": 60,
    "21 Jui": 80,
    "22 Jui": 90,
  };

  
  const selectedDayCount = () => {
    return Object.values(days).filter(Boolean).length;
  }
  const isDisabled = tickets === 0 || (isForfait && selectedDayCount() !== 2); 

  const handleTicketChange = (newTickets: number, event: React.MouseEvent) => {
    event.stopPropagation();
    setTickets(newTickets);
  }

  
  const addToCartHandler = async (
    event: React.MouseEvent<HTMLButtonElement>
    ) => {
      event.stopPropagation();
      setIsLoading(true);
      
      // Longueur actuelle du panier dans les cookies
      const selectedDaysSortedString = isForfait
      ? Object.entries(days)
          .filter(([_, isChosen]) => isChosen)
          .map(([day, _]) => day)
          .sort()
          .join('-')
      : null;
      
      const calculPrixSelonJourSelec = isForfait && selectedDaysSortedString
    ? selectedDaysSortedString.split('-').reduce((total, dayKey) => {
        return total + pricesByDay[dayKey as DayKey];
      }, 0)
    : (typeof price === "number" ? price : 0);
      
    const uniqueId = isForfait && selectedDaysSortedString 
          ? `${id}-${selectedDaysSortedString}` 
          : `${id}`;    

    const itemForCart = {
      id,
      uniqueId,
      title,
      price: isForfait ? calculPrixSelonJourSelec : (typeof price === "number" ? price : 0),
      quantity: tickets,
      selectedDaysSortedString: isForfait ? selectedDaysSortedString : null,
    };
    
    
    // const currentCartLength = (getCookie("cart") || []).length;
    // condition non valide car si on ajoute un typê billet déjà présent dans le panier, 
    // l'ajout des nouveaux billets ne ferons que changer la valeur de quantité dans le tableau et 
    // donc la longueur du tableau ne changera pas
     // Initialise la vérification de l'ajout
  let expectedNewQuantity = itemForCart.quantity;
  let newCart = [...cart];


  const forfaitIndex = newCart.findIndex((billet) => billet.uniqueId === uniqueId);

  // si l'article existait déjà dans le panie on garde la quantité précédente et on détermine la nouvelle quantité attendue
  if (forfaitIndex > -1) {
    // si ce type de billet existe déjà, ajoute à la quantité et calcule la nouvelle quantité attendue
    expectedNewQuantity += newCart[forfaitIndex].quantity;
    newCart[forfaitIndex].quantity = expectedNewQuantity;
  } else {
    // sinon on l'ajoute au panier
    newCart.push(itemForCart);
  }
    setCart(newCart);
  setCookie("cart", newCart, { expires: 7, sameSite: "None", secure: true });
  
  setTimeout(() => {
    // trouver l'article après la mise à jour pour vérifier que la quantité est correcte
    const newForfaitIndex = newCart.findIndex((billet) => billet.uniqueId === uniqueId);
    const hasCorrectQuantity = newForfaitIndex > -1
      ? newCart[newForfaitIndex].quantity === expectedNewQuantity
      : false;

    if (hasCorrectQuantity) {
      setIsAdded(true);
    } else {
      console.error('Erreur : la quantité dans le panier ne correspond pas à la quantité attendue.');
    }

    setIsLoading(false);

    // Afficher le message 'ARTICLE AJOUTÉ' pendant un certain temps
    setTimeout(() => {
      setIsAdded(false);
    }, 2000);
  }, 400);
};
  const displayDay = (day: string) => day.replace("Juillet", "Juillet");

  const buttonVariants: { [key: string]: TargetAndTransition } = {
    tap: { scale: 0.95 },
    selected: { scale: 1.1, backgroundColor: "#E45A3B" },
    unselected: { scale: 1, backgroundColor: "#FFFFFF" },
  };

  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" ? 160 : 150,
      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 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">
            <div className="sub-menu-left-part">
              <div className="rect">
                <img
                  className=""
                  src="images/billet_pass1j.png"
                  alt="Billet pass 1 jour"
                />
              </div>
              <div className="container"></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
                className="minusButton"
                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">
              <div className="day-checkbox-container">
                {isForfait &&
                  (Object.keys(days) as Array<keyof typeof initialDays>).map(
                    (day) => (
                      <motion.label
                        key={day}
                        className="day-checkbox"
                        whileTap="tap"
                      >
                        <input
                          type="checkbox"
                          checked={days[day]}
                          onChange={() => toggleDaySelection(day)}
                          style={{ display: "none" }}
                        />
                        <motion.div
                          className="day-button"
                          variants={buttonVariants}
                          animate={days[day] ? "selected" : "unselected"}
                        >
                          {displayDay(day)}
                        </motion.div>
                      </motion.label>
                    )
                  )}
              </div>
            <p>Sous-total</p>
            <p>{tickets * (typeof price === "number" ? price : 0)}€</p>
          </div>
          <Button
            text={
              isLoading
                ? "Chargement…"
                : isAdded
                ? "ARTICLE AJOUTÉ"
                : "AJOUT PANIER"
            }
            isLoading={isLoading}
            onClick={(event: React.MouseEvent<HTMLElement>) =>
              addToCartHandler(event as React.MouseEvent<HTMLButtonElement>)
            }
            isDisabled={isDisabled} // Passer la prop disabled ici
          />
        </div>
      </motion.div>
    </motion.div>
  );
}import React, { useContext } from 'react';
import { CartContext } from '../../../../App.tsx'; 
import { setCookie } from '../../../../cookies/CookiesLib.tsx';
import { AnimatePresence, motion } from 'framer-motion';


type Props = {
    id: number;
    uniqueId: string;
    typeBillet: number,
    title: string,
    price: number,
    quantite: number,
    selectedDays?: Array<string>;
  };



export const ItemPanier: React.FC<Props> = ({ typeBillet, price, quantite, title, selectedDays, uniqueId}) => {
  const { cart, setCart } = useContext(CartContext);

  // Fonction pour enlever un billet du panier
  const removeFromCart = () => {
    const updatedCart = cart.filter((item) => item.uniqueId !== uniqueId);
    setCart(updatedCart);
    setCookie('cart', updatedCart, { expires: 7, sameSite: 'None', secure: true });
  };

  // Fonction pour mettre à jour la quantité d'un billet dans le panier
  const updateQuantity = (newQuantity: number) => {
    const updatedCart = cart.map((item) => {
      if (item.uniqueId === uniqueId) {
        return { ...item, quantity: newQuantity };
      }
      return item;
    });
    setCart(updatedCart);
    setCookie('cart', updatedCart, { expires: 7, path: '/' }); 
  };// Ajoutez le chemin si nécessaire

  const itemVariant = {
    hidden: { opacity: 0, x: -20 },
    visible: { opacity: 1, x: 0 },
    exit: { opacity: 0, x: 20, transition: {duration: 0.1} }
  };

    
  const daysList = selectedDays && (
    <div className="selected-days-container">
      {selectedDays.map(day => (
        <span key={day} className="selected-day-badge">{day}</span>
      ))}
    </div>
  );

  return (
      <motion.div
      className="item-panier"
      layout
      initial="visible"
      animate="visible"
      exit="exit"
      variants={itemVariant}
      key={uniqueId}
      >        <div className="container-item-panier">
            <div className="container-image">
                <img src="/images/billet.png" alt="billet" />
            </div>
            <div className="informations">
              <div className='partie-texte'>
                <div className="textes">
                    <h4>{title}</h4>
                    <h5>{price}€</h5> 
                    <div className="jours">
                    {daysList}
                    </div>
                </div>
                </div>
                <div className="compteur-quantitee">
                    <span className='ajout-retrait' onClick={() => updateQuantity(Math.max(0, quantite - 1))}>-</span>
                    <input type="number" className='quantite' value={quantite} readOnly />
                    <span className='ajout-retrait' onClick={() => updateQuantity(quantite + 1)}>+</span>
                </div>
            </div>
        </div>   
              <img className='cross' src="/icones/cross.svg" alt="croix" onClick={removeFromCart} />
    </motion.div>
  );
};import React, { useContext } from 'react';
import { CartContext } from '../../../../App.tsx'; // Assurez-vous que le chemin est correct
import { ItemPanier } from './ItemPanier';
import { motion, AnimatePresence } from 'framer-motion';
import Button from '../../../../components/form/Button';


type Props = {
  isOpen: boolean;
  setIsOpen: (isOpen: boolean) => void;
};

const MenuPanier: React.FC<Props> = ({ isOpen, setIsOpen }) => {
  const { cart } = useContext(CartContext);

  // Calculer le sous-total
  const subtotal = cart.reduce((acc: number, item: { price: number; quantity: number; }) => acc + item.price * item.quantity, 0);

  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={isOpen ? "visible" : "hidden"}
    >
      <svg className="cross" onClick={() => setIsOpen(false)} 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 className="container">
        <h2>Mon panier</h2>
        <section className='le-panier'>
          <AnimatePresence>
          {cart.length > 0 ? (
            cart.map((item) => (
              <ItemPanier
                key={item.uniqueId}
                id={item.id}
                typeBillet={item.id}
                title={item.title}
                price={typeof item.price === 'number' ? item.price : parseInt(item.price, 10)}
                quantite={item.quantity}
                selectedDays={item.selectedDaysSortedString ? item.selectedDaysSortedString.split('-') : undefined}
                uniqueId={item.uniqueId}
                />
                ))
                ) : (
                  <p>Panier Vide</p>
                  )}
              </AnimatePresence>
        </section>

        <div className="sous-total">
          <h4>Sous total: </h4>
          <h4>{subtotal.toFixed(2)}€</h4>
        </div>

        <Button text="RESERVER"></Button>
      </div>
    </motion.div>
  );
};

export default MenuPanier;