pourquoi les réseaux sociaux s'affichent 2 fois ? import { useEffect, useState, useRef, useLayoutEffect } from "react";
import SearchBar from "../../components/form/SearchBar";
import Combo from "../../components/form/Combo";
import CarteArtiste from "../../components/Artiste/CarteProgrammation";
import { motion } from "framer-motion";
import { useLocation } from "react-router-dom";
import axios from "axios";
import Footer from "../../components/footer";
import CarteProgrammation from "../../components/Artiste/CarteProgrammation";
import { AnimatePresence } from "framer-motion";


type Props = {
  isNavInFocus: boolean;
  setIsNavTransparent: (isNavTransparent: boolean) => void;
};

type Groupe = {
  idG: number;
  nomG: string;
  descriptionG: string;
  datePassage: string;
  heurePassage: string;
};

type Artiste = {
  descriptionA?: string;
  idMG?: number;
  idG: number;
  nomDeSceneMG: string;
  nomMG: string;
  prenomMG?: string;
  datePassage?: string;
  heurePassage?: string;
};

type Evenement = {
  dateDebutE: string;
  dateFinE: string;
  heureDebutE: string;
  heureFinE: string;
  idE: number;
  idG: number;
  idL: number | null;
  nomE: string;
};

type Programme = Groupe | Evenement | Artiste;

export default function Programmation(props: Props) {
  const location = useLocation();
  const idArtistComingFrom = location.state?.comesFromPageArtist;
  const oldX = location.state?.oldX;
  const oldY = location.state?.oldY;
  const oldGroupes = location.state?.oldGroupes;
  const [searchTerm, setSearchTerm] = useState("");
  

  window.history.replaceState({}, document.title);
  const [lesGroupes, setLesGroupes] = useState<Groupe[]>(location.state ? oldGroupes : []);
  const [lesArtistes, setLesArtistes] = useState<Artiste[]>([]);
  const groupePassageMap = useRef<
    Map<number, { datePassage: string; heurePassage: string }>
  >(new Map());

  useEffect(() => {
    axios.get("http://localhost:8080/getGroupesWithEvenements").then((res) => {
      const groupedData = res.data as Programme[][];
      // console.log("groupedData")
      // console.log(groupedData);

      const listeGroupes: Groupe[] = [];
      const groupSet = new Set<number>();
      const listeArtistes: Artiste[] = [];

      groupedData.forEach((groupArray) => {
        let groupeObj: Partial<Groupe> = {};
        let artisteObj: Partial<Artiste> = {};

        groupArray.forEach((item) => {
          if ("nomG" in item) {
            groupeObj = { ...groupeObj, ...item };
          } else if ("nomDeSceneMG" in item) {
            artisteObj = { ...artisteObj, ...item };
          } else if ("dateDebutE" in item) {
            const datePassage = item.dateDebutE;
            const heurePassage = item.heureDebutE;
            if (groupeObj.idG === item.idG) {
              groupeObj.datePassage = datePassage;
              groupeObj.heurePassage = heurePassage;
            }
            if (artisteObj.idG === item.idG) {
              artisteObj.datePassage = datePassage;
              artisteObj.heurePassage = heurePassage;
            }
          }
        });

        // si l'id n'a pas encore était ajoutée à la liste on ajoute le groupe
        if (groupeObj.idG !== undefined && !groupSet.has(groupeObj.idG)) {
          listeGroupes.push(groupeObj as Groupe);
          groupSet.add(groupeObj.idG);
        }
        if (artisteObj.nomDeSceneMG !== undefined) {
          listeArtistes.push(artisteObj as Artiste);
        }
      });

      setLesGroupes(listeGroupes);
      // console.log(listeGroupes);
      groupePassageMap.current.clear();
      listeGroupes.forEach((groupe) => {
        groupePassageMap.current.set(groupe.idG, {
          datePassage: groupe.datePassage,
          heurePassage: groupe.heurePassage,
        });
      });

      setLesArtistes(listeArtistes);
    });
  }, []);

  // let filteredGroupes = lesGroupes;
  //   if (searchTerm) {
  //     filteredGroupes = lesGroupes.filter((groupe) =>
  //       groupe.nomG.toLowerCase().includes(searchTerm.toLowerCase())
  //     );
  //   }
  // let filteredArtistes = lesArtistes;
  // if (searchTerm) {
  //   filteredArtistes = lesArtistes.filter((artiste) =>
  //     artiste.nomDeSceneMG.toLowerCase().includes(searchTerm.toLowerCase())
  //   )
  // }
  
  const [filtreDate, setFiltreDate] = useState("Tout");
  console.log(filtreDate)
  let termeRechercher = 'Tout';
  
  if (filtreDate === '21 Juillet') {
    termeRechercher = '07-21';
  }
  else if (filtreDate === '22 Juillet') {
    termeRechercher = '07-22';
  }
  else if (filtreDate === '23 Juillet') {
    termeRechercher = '07-23';
  }
  

  let filteredGroupes = lesGroupes;
if (searchTerm) {
  filteredGroupes = filteredGroupes.filter((groupe) => {
    console.log(groupe.nomG);
    if (searchTerm.length > 5) {
      return groupe.nomG.toLowerCase().includes(searchTerm.toLowerCase());
    } else {
      return groupe.nomG.toLowerCase().startsWith(searchTerm.toLowerCase());
    }
  });
}

if (filtreDate !== 'Tout') {
  console.log(termeRechercher)
  filteredGroupes = filteredGroupes.filter((groupe) => {
    return groupe.datePassage.includes(termeRechercher);
  });
}

let filteredArtistes = lesArtistes;
console.log("Les Artistes avant filtre:", lesArtistes);
if (searchTerm) {
  console.log("Filtered Artistes après searchTerm:", filteredArtistes);
  filteredArtistes = filteredArtistes.filter((artiste) => {
    if (searchTerm.length > 5) {
      return artiste.nomDeSceneMG.toLowerCase().includes(searchTerm.toLowerCase());
    } else {
      return artiste.nomDeSceneMG.toLowerCase().startsWith(searchTerm.toLowerCase());
    }
  });
}
if (filtreDate !== 'Tout') {
  filteredArtistes = filteredArtistes.filter((artiste) => {
    console.log("Filtered Artistes après searchTerm:", filteredArtistes);
    const groupeInfo = groupePassageMap.current.get(artiste.idG);
    return groupeInfo?.datePassage.includes(termeRechercher);
  });
}
  console.log(filteredGroupes);
  console.log(filteredArtistes);
  const [filtreAffichage, setFiltreAffichage] = useState("Grille");
  const [filtreGenre, setFiltreGenre] = useState("Tout");

  const pageRef = useRef<HTMLDivElement>(null);

  const contentVariants = {
    visible: {
      filter: "blur(0px)",
      scale: 1,
      zIndex: 1,
      transition: {
        duration: 0.5,
        ease: [1, 0, 0, 1],
      },
    },
    hidden: {
      filter: "blur(10px)",
      scale: 0.8,
      zIndex: -1,
      transition: {
        duration: 0.5,
        ease: [1, 0, 0, 1],
      },
    },
  };

  useEffect(() => {
    window.scrollTo(0, 0);
    props.setIsNavTransparent(false);
  }, []);

  return (
    <>
      <motion.div
        id="Programmation"
        className="page-defaut"
        variants={contentVariants}
        animate={props.isNavInFocus ? "hidden" : "visible"}
        ref={pageRef}
      >
        <header>
          <div className="title">
            <h2>PROGRAMMATION</h2>
            <svg
              width="64"
              height="64"
              viewBox="0 0 64 64"
              fill="none"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                d="M62.9991 27.739L42.1815 27.7675L56.8787 13.0286L50.7001 6.86056L36.0029 21.5994L35.9744 0.785744L27.2406 0.797718L27.2692 21.6114L12.5316 6.91288L6.36413 13.0979L21.1017 27.7964L0.289932 27.825L0.301899 36.5537L21.1137 36.5251L6.41646 51.2641L12.6009 57.4321L27.2981 42.6932L27.3266 63.5069L36.0603 63.4949L36.0318 42.6812L50.7694 57.3798L56.931 51.1948L42.1934 36.4962L63.011 36.4677L62.9991 27.739Z"
                fill="#FFD600"
              />
            </svg>
          </div>
          <div className="filters-container">
            <div className="filters">
              <Combo
                title="DATE"
                choices={["Tout", "21 Juillet", "22 Juillet", "23 Juillet"]}
                currentChoice={filtreDate}
                setCurrentChoice={setFiltreDate}
              />
              <Combo
                title="AFFICHAGE"
                choices={["Grille", "Horaires"]}
                currentChoice={filtreAffichage}
                setCurrentChoice={setFiltreAffichage}
              />
              <Combo
                title="GENRE"
                choices={["Tout", "Rap", "Rock", "Pop"]}
                currentChoice={filtreGenre}
                setCurrentChoice={setFiltreGenre}
              />
            </div>
            <SearchBar text="Rechercher un artiste" onSearch={setSearchTerm} />
          </div>
        </header>
        <main className="liste-artistes">
        <AnimatePresence>
  {filteredGroupes.map((groupe) => {
    console.log('idArtistComingFrom for groupe:', idArtistComingFrom);
    console.log("groupe.idG : ");
    console.log(groupe.idG);
    return (
      <CarteProgrammation
        key={groupe.idG}
        id={groupe.idG}
        nomArtiste={groupe.nomG}
        description={groupe.descriptionG}
        date={groupe.datePassage}
        heure={groupe.heurePassage}
        setIsNavTransparent={props.setIsNavTransparent}
        oldGroupes={lesGroupes}
        oldX={idArtistComingFrom == groupe.idG ? oldX : null} oldY={idArtistComingFrom == groupe.idG ? oldY : null} comesFromPageArtist={idArtistComingFrom == groupe.idG}
      />
    );
  })}
  
  {filteredArtistes.map((artiste) => {
    console.log('idArtistComingFrom for artiste:', idArtistComingFrom);
    const groupeInfo = groupePassageMap.current.get(artiste.idG);
    console.log("artiste.idMG : ");
    console.log(artiste.idMG);
    return (
      <CarteProgrammation
      
        key={artiste.idMG}
        id={artiste.idMG}
        nomArtiste={artiste.nomDeSceneMG}
        description={artiste.descriptionA}
        date={groupeInfo?.datePassage ?? "Date inconnue"}
        heure={groupeInfo?.heurePassage ?? "Heure inconnue"}
        setIsNavTransparent={props.setIsNavTransparent}
        
        oldGroupes={lesGroupes}
        
        oldX={idArtistComingFrom == artiste.idMG ? oldX : null} oldY={idArtistComingFrom == artiste.idMG ? oldY : null} comesFromPageArtist={idArtistComingFrom == artiste.idMG}

      />
    );
  })}
          </AnimatePresence>
        </main>
      </motion.div>
      <Footer />
    </>
  );
}
import { motion } from 'framer-motion'
import {useState,useRef, useEffect} from 'react'
import { Link } from 'react-router-dom'

type Props = {
    id:number|undefined,
    date: string,
    heure: string,
    nomArtiste: string,
    setIsNavTransparent: (isNavTransparent : boolean) => void;
    comesFromPageArtist?: boolean;
    oldX?: number;
    oldY?: number;
    oldGroupes?: Groupe[];
    description?: string;
}

type Groupe = {
    idG: number;
    nomG: string;
    descriptionG: string;
    datePassage: string;
    heurePassage: string;
  }

export default function CarteProgrammation(props: Props) {
  const nomArtiste = props.nomArtiste.toUpperCase().split(" ")
  const[isHovered, setIsHovered] = useState(false)
  const[isSwitching, setIsSwitching] = useState(false)
  const[delay, setDelay] = useState(props.comesFromPageArtist? 0.2 : 0)
  const refCarte = useRef<HTMLDivElement>(null);
  const[zIndexCard, setZIndexCard] = useState(props.comesFromPageArtist ? 99 : 1)

  useEffect(() => {
    console.log('oldX:', props.oldX);
    console.log('oldY:', props.oldY);
    
    setTimeout(() => {
      console.log(props.date)
      console.log(props.heure)
  
      setZIndexCard(1)
      setDelay(0)
    }, 600);
  }, [])
  

  const titleVariants = {
    hover:{
        fontSize: "2.3rem",
        color:"#FFD600",
        transition:{
            duration:0.4,
            ease: [1, 0, 0,1]
        }
    },
    default:{
        fontSize: "2.3rem",
        color:"#FFFBEE",
        transition:{
            delay:delay,
            duration:0.4,
            ease: [1, 0, 0,1]
        }
    },
    exit:{
        fontSize: "7.625rem",
        color:"#FFD600",
        transition:{
            duration:0.4,
            ease: [1, 0, 0,1]
        }
    }
  }

  // fais le variant pour l'image de l'artiste (scale 1.2 sur hover)
    const imageVariants = {
        hover:{
            scale:1.3,
            transition:{
                duration:0.4,
                ease: [1, 0, 0,1]
            }
        },
        default:{
            scale:1,
            transition:{
                duration:0.4,
                ease: [1, 0, 0,1]
            }
        }
    }

  // fais le variant pour le texte de dateHeure (x 2rem sur hover)

  const dateHeureVariants = {
    hover:{
        y:"0rem",
        fontSize: "1.875rem",
        transition:{
            duration:0.4,
            ease: [1, 0, 0,1]
        }
    },
    default:{
        y:(window.innerWidth <= 576 ? 3.1 : 2.9).toString() + "rem",
        fontSize: "1.875rem",
        transition:{
            delay:delay,
            duration:0.4,
            ease: [1, 0, 0,1]
        }
    },
    exit:{
        y:"0rem",
        fontSize: "4.6875rem",
        transition:{
            duration:0.4,
            ease: [1, 0, 0,1]
        }
    }
  }

  // default font-size: 1.875rem;
  // exit font-size: 4.6875rem;

  const heureVariants = {
    hover:{
        transition:{
            duration:0.4,
            ease: [1, 0, 0,1]
        }
    },
    default:{
        transition:{
            duration:0.4,
            ease: [1, 0, 0,1]
        }
    },
  }

  const carteVariants = {
    default:{
        zIndex:zIndexCard,
        width: "24rem",
        height: "15.5rem",
        y:0,
        x:0,
        transition:{
            delay:0.2,
            duration:0.4,
            ease: [1, 0, 0,1]
        }
    },
    exit:{
        x: refCarte.current? -refCarte.current.offsetLeft : props.oldX? -props.oldX : 0,
        y: refCarte.current? -refCarte.current.offsetTop : props.oldY? -props.oldY : 0,
        height: "100vh",
        width: "100vw",
        zIndex:99,
        transition:{
            duration:0.4,
            ease: [1, 0, 0,1]
        }
    }
  }

  const textVariants = {
    default:{
        padding: "0.5rem 1rem",
        transition:{
            delay:delay*2,
            duration:0.4,
            ease: [1, 0, 0,1]
        }
    },
    exit:{
        padding: "3rem",
        transition:{
            duration:0.4,
            ease: [1, 0, 0,1]
        }
    }
  }


  return (
    <motion.div
    className="outer-carte-artiste"
    ref={refCarte}
    variants={carteVariants}
    initial={props.comesFromPageArtist ? "exit" : "default"}
    animate="default"
    exit={isSwitching ? "exit" : "default"}
    onClick={() => window.scrollTo(0,0)}
    >
        <Link className="carte-artiste"
        onMouseEnter={() => setIsHovered(true)}
        onMouseLeave={() => setIsHovered(false)}
        to={{
            pathname:"/artiste",
            search:`?id=${props.id}`,
        }}
        state={{
            nomArtiste: props.nomArtiste,
            date: props.date,
            heure: props.heure,
            oldX: refCarte.current?.offsetLeft,
            oldY: refCarte.current?.offsetTop,
            oldGroupes: props.oldGroupes,
            description: props.description
        }}
        onClick={() => {props.setIsNavTransparent(true); setIsSwitching(true)}}
        >
            <motion.img 
            src={"http://localhost:8080/getImageArtiste/" + props.id} 
            alt="image de l'artiste" 
            variants={imageVariants}
            initial="default"
            animate={isHovered ? "hover" : "default"}
            exit="default"
            />
            <motion.div className="texts"
            variants={textVariants}
            initial={props.comesFromPageArtist ? "exit" : "default"}
            animate="default"
            exit={isSwitching ? "exit" : "default"}
            >
                <motion.h3
                variants={titleVariants}
                initial={props.comesFromPageArtist ? "exit" : "default"}
                animate={isHovered ? "hover" : "default"}
                exit={isSwitching ? "exit" : "default"}
                >{
                    nomArtiste.map((mot, index) => {
                        return(
                            <span key={index}>{mot}<br/></span>
                        )
                    })
                }</motion.h3>
                
                <motion.div className="date-heure"
                variants={dateHeureVariants}
                initial={props.comesFromPageArtist ? "exit" : "default"}
                animate={isHovered ? "hover" : "default"}
                exit={isSwitching ? "exit" : "default"}
                >
                    <h4
                    >{props.date}</h4>

                    <motion.h4 
                    variants={heureVariants} 
                    initial="default"
                    animate={isHovered ? "hover" : "default"}
                    exit={isSwitching ? "exit" : "default"}
                    >{props.heure}</motion.h4>

                </motion.div>
            </motion.div>
        </Link>
    </motion.div>
  )
}
import { useEffect, useState, useRef } from "react";
import { Link, useLocation } from "react-router-dom";
import BoutonReseau from "../../components/Artiste/BoutonReseau";
import { motion } from "framer-motion";
import axios from "axios";

export default function PageEvenement() {
  const location = useLocation();
  const oldX = location.state?.oldX;
  const oldY = location.state?.oldY;
  const oldGroupes = location.state?.oldGroupes;
  const [nomArtiste, setNomArtiste] = useState(location.state?.nomArtiste);
  const [date, setDate] = useState(location.state?.date);
  const [heure, setHeure] = useState(location.state?.heure);
  const titleRef = useRef<HTMLHeadingElement>(null);
  const [description, setDescription] = useState(
    location.state?.description ||
      "Description par défaut si aucune description n'est passée."
  );
  const [socialLinks, setSocialLinks] = useState<{ reseau: string }[]>([]);
  const params = new URLSearchParams(window.location.search);
  const idArtiste = params.get("id");

  const [windowWidth, setWindowWidth] = useState(window.innerWidth);
  const [infosGridPosition, setInfosGridPosition] = useState<"top" | "bottom">(
    "top"
  );

  

  function getSocialNetworkType(
    url: string
  ):
    | "soundcloud"
    | "spotify"
    | "instagram"
    | "twitter"
    | "youtube"
    | "inconnu" {
    if (url.includes("soundcloud")) {
      return "soundcloud";
    } else if (url.includes("spotify")) {
      return "spotify";
    } else if (url.includes("instagram")) {
      return "instagram";
    } else if (url.includes("twitter")) {
      return "twitter";
    } else if (url.includes("youtube")) {
      return "youtube";
    } else {
      return "inconnu";
    }
  }

  useEffect(() => {
    axios
      .get("http://localhost:8080/getSocialLinks/" + idArtiste)
      .then((response) => {
        setSocialLinks(response.data);
      })
      .catch((error) => {
        console.error(
          "Erreur lors de la récupération des liens de réseaux sociaux",
          error
        );
      });

    const handleResize = () => {
      setWindowWidth(window.innerWidth);
    };

    window.addEventListener("resize", handleResize);

    return () => {
      window.removeEventListener("resize", handleResize);
    };
  }, []);

  useEffect(() => {
    console.log('oldXEvenement:', oldX);
    console.log('oldYEvenement:', oldY);
    if (titleRef.current) {
      // regarde si la width du titre est plus grande que 25% de la width de la fenetre - 2*3rem
      if (titleRef.current.offsetWidth > windowWidth / 4 - 2 * 3 * 16) {
        setInfosGridPosition("top");
      } else {
        setInfosGridPosition("bottom");
      }
    }
  }, [titleRef, windowWidth]);

  const infosVariants = {
    initial: {
      opacity: 0,
      transition: {
        duration: 0.1,
        ease: "easeInOut",
      },
    },
    visible: {
      opacity: 1,
      transition: {
        delay: 0.8,
        duration: 0.6,
        ease: "easeInOut",
      },
    },
  };

  const overlayVariants = {
    initial: {
      background:
        "linear-gradient(to top, rgba(0, 0, 0, 0.7) 20%, rgba(0, 0, 0, 0) 60%)",
      transition: {
        duration: 0.1,
        ease: "easeInOut",
      },
    },
    extended: {
      background:
        "linear-gradient(to top, rgba(0, 0, 0, 0.7) 40%, rgba(0, 0, 0, 0) 100%)",
      transition: {
        delay: 0.6,
        duration: 0.6,
        ease: "easeInOut",
      },
    },
  };

  return (
    <div id="PageArtiste">
      <motion.div
        className="overlay"
        variants={overlayVariants}
        initial="initial"
        animate={infosGridPosition === "top" ? "extended" : "initial"}
      />

      <img
        src={"http://localhost:8080/getImageArtiste/" + idArtiste}
        alt="image de fond"
      />
      <div
        className="content"
        style={{
          columnGap: infosGridPosition === "top" ? "0" : "5rem",
          rowGap: windowWidth > 991 ? "0" : "5rem",
        }}
      >
        <h3 ref={titleRef}>
          {nomArtiste
            .toUpperCase()
            .split(" ")
            .map((mot: string, index: number) => {
              return (
                <span key={index}>
                  {mot}
                  <br />
                </span>
              );
            })}
        </h3>
        <motion.div
          className="infos"
          variants={infosVariants}
          initial="initial"
          animate="visible"
          exit="initial"
          style={{ gridArea: infosGridPosition }}
        >
          <p className="description">{description}</p>
          <div className="les-reseaux">
            {socialLinks.map((link, index) => {
              const type = getSocialNetworkType(link.reseau);
              if (type) {
                return (
                  <BoutonReseau key={index} href={link.reseau} type={type} />
                );
              }
              return null;
            })}
          </div>
          <Link
            to="/programmation"
            state={{
              comesFromPageArtist: idArtiste,
              oldX: oldX,
              oldY: oldY,
              oldGroupes: oldGroupes,
            }}
            className="btn-retour"
          >
            <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)"
              />
              <rect
                x="3.87891"
                y="25.5957"
                width="35.8974"
                height="3.58974"
                rx="1.79487"
                transform="rotate(-45 3.87891 25.5957)"
              />
            </svg>
          </Link>
        </motion.div>
        <div className="date-heure">
          <h4>{date}</h4>
          <h4>{heure}</h4>
        </div>
      </div>
    </div>
  );
}