diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..7a1537ba064 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +node_modules diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000000..123b9210c92 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "tabWidth": 4, + "singleQuote": true, + "trailingComma": "es5", + "printWidth": 120, + "endOfLine": "auto" +} diff --git a/404.html b/404.html new file mode 100644 index 00000000000..c7defe1a008 --- /dev/null +++ b/404.html @@ -0,0 +1,12 @@ + + + + Page non trouvée + + + + +

Page non trouvée

+

Vous serez redirigé vers la page d'accueil dans 5 secondes...

+ + diff --git a/README.md b/README.md index 81b2841c3ad..97ad0270d63 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,47 @@ -# Base de code du projet P6 - Parcours Front-end +![logo-fisheye](assets/images/logo.png "Titre de l'image"). -## Démarrer le projet +Ce projet vise à moderniser un site web destiné aux photographes freelances, en le transformant d'un site statique en une plateforme dynamique et interactive pour présenter les portfolios des photographes et faciliter les contacts avec des clients potentiels. Ce site permet aux photographes, de mettre en valeur leur travail et de recevoir des demandes pour des événements ou des tirages. -Rien à installer ici, il suffit d'ouvrir le fichier `index.html`. +## 🔥 Lancer le Projet +1. Cloner le dépôt sur votre machine locale. +2. Ouvrir le projet dans votre éditeur de code. +3. Lancer le fichier `index.html` à l'aide d'un serveur de développement web comme **Live Server**. + +## 🎯 Objectif du Projet + +Le site actuel, conçu il y a plus de dix ans, est obsolète et nécessite une refonte complète pour : +- Moderniser le design et l'expérience utilisateur. +- Passer d'un site statique à un site dynamique. +- Faciliter la gestion et la présentation des galeries des photographes. + + +## 📕 Pages et Fonctionnalités + +### 1. Page d'Accueil +La page d'accueil propose un aperçu de tous les photographes disponibles : +- **Liste des Photographes** : Chaque photographe est présenté avec son nom, son slogan, sa localisation, son tarif horaire, et une image miniature de son choix. +- **Navigation vers la Page du Photographe** : En cliquant sur la vignette d'un photographe, l'utilisateur est redirigé vers une page individuelle dédiée. + +### 2. Page du Photographe +Chaque photographe possède une page dédiée générée dynamiquement contenant : +- **Galerie Multimédia** : + - Une galerie affichant les photos et vidéos du photographe. + - Les vidéos apparaissent avec une image miniature. +- **Interactions avec les Médias** : + - Chaque média dispose d'un titre et d'un compteur de likes. + - Les utilisateurs peuvent liker chaque média, incrémentant ainsi le nombre de likes total du photographe. + - Les médias peuvent être triés par **popularité** ou par **titre**. +- **Affichage en Lightbox** : + - En cliquant sur un média, celui-ci s'ouvre dans une lightbox. + - Une croix permet de fermer la lightbox, et des boutons de navigation permettent de passer d'un média à l'autre. + - La navigation peut également se faire avec les touches fléchées du clavier. +- **Bouton de Contact** : + - Un bouton permettant de contacter le photographe via un formulaire de contact. + - Ce formulaire apparaît dans une modale et comprend des champs pour le nom, l'adresse électronique et le message. + - Actuellement, le contenu du formulaire est affiché dans la console à des fins de test ; l'envoi réel des messages sera implémenté ultérieurement. + +## 👩‍💻 Technologies Utilisées + +- **HTML/CSS/JavaScript** pour la structure de base, le style et l'interactivité du site. +- **JavaScript dynamique** pour la génération de contenu et les interactions (like, lightbox, tri, etc.). diff --git a/assets/icons/back-arrow.png b/assets/icons/back-arrow.png new file mode 100644 index 00000000000..bb9b7a50637 Binary files /dev/null and b/assets/icons/back-arrow.png differ diff --git a/assets/icons/close.svg b/assets/icons/close.svg index eb740dae2a9..afc220ed650 100644 --- a/assets/icons/close.svg +++ b/assets/icons/close.svg @@ -1,3 +1,4 @@ - + diff --git a/assets/icons/like-dark.png b/assets/icons/like-dark.png new file mode 100644 index 00000000000..168644eae6e Binary files /dev/null and b/assets/icons/like-dark.png differ diff --git a/assets/icons/like.png b/assets/icons/like.png new file mode 100644 index 00000000000..83fc07c32a7 Binary files /dev/null and b/assets/icons/like.png differ diff --git a/assets/icons/next-arrow.png b/assets/icons/next-arrow.png new file mode 100644 index 00000000000..6dc238a9f3f Binary files /dev/null and b/assets/icons/next-arrow.png differ diff --git a/assets/medias/Animals_Majesty.jpg b/assets/medias/Animals_Majesty.jpg new file mode 100644 index 00000000000..d06eee63d79 Binary files /dev/null and b/assets/medias/Animals_Majesty.jpg differ diff --git a/assets/medias/Animals_Puppiness.mp4 b/assets/medias/Animals_Puppiness.mp4 new file mode 100644 index 00000000000..6d50831efe2 Binary files /dev/null and b/assets/medias/Animals_Puppiness.mp4 differ diff --git a/assets/medias/Animals_Rainbow.jpg b/assets/medias/Animals_Rainbow.jpg new file mode 100644 index 00000000000..6cfc042f843 Binary files /dev/null and b/assets/medias/Animals_Rainbow.jpg differ diff --git a/assets/medias/Animals_Wild_Horses_in_the_mountains.mp4 b/assets/medias/Animals_Wild_Horses_in_the_mountains.mp4 new file mode 100644 index 00000000000..d9c560dfbbc Binary files /dev/null and b/assets/medias/Animals_Wild_Horses_in_the_mountains.mp4 differ diff --git a/assets/medias/Architecture_Connected_Curves.jpg b/assets/medias/Architecture_Connected_Curves.jpg new file mode 100644 index 00000000000..56aeeea6024 Binary files /dev/null and b/assets/medias/Architecture_Connected_Curves.jpg differ diff --git a/assets/medias/Architecture_Contrast.jpg b/assets/medias/Architecture_Contrast.jpg new file mode 100644 index 00000000000..2195a5a0d8f Binary files /dev/null and b/assets/medias/Architecture_Contrast.jpg differ diff --git a/assets/medias/Architecture_Corner_Room.jpg b/assets/medias/Architecture_Corner_Room.jpg new file mode 100644 index 00000000000..f5fdf79a85c Binary files /dev/null and b/assets/medias/Architecture_Corner_Room.jpg differ diff --git a/assets/medias/Architecture_Cross_Bar.jpg b/assets/medias/Architecture_Cross_Bar.jpg new file mode 100644 index 00000000000..efdd811878a Binary files /dev/null and b/assets/medias/Architecture_Cross_Bar.jpg differ diff --git a/assets/medias/Architecture_Dome.jpg b/assets/medias/Architecture_Dome.jpg new file mode 100644 index 00000000000..648dfa8e982 Binary files /dev/null and b/assets/medias/Architecture_Dome.jpg differ diff --git a/assets/medias/Architecture_Horseshoe.jpg b/assets/medias/Architecture_Horseshoe.jpg new file mode 100644 index 00000000000..d6f231c7dda Binary files /dev/null and b/assets/medias/Architecture_Horseshoe.jpg differ diff --git a/assets/medias/Architecture_On_a_hill.jpg b/assets/medias/Architecture_On_a_hill.jpg new file mode 100644 index 00000000000..989f2bbb7f1 Binary files /dev/null and b/assets/medias/Architecture_On_a_hill.jpg differ diff --git a/assets/medias/Architecture_Water_on_Modern.jpg b/assets/medias/Architecture_Water_on_Modern.jpg new file mode 100644 index 00000000000..af0712fad44 Binary files /dev/null and b/assets/medias/Architecture_Water_on_Modern.jpg differ diff --git a/assets/medias/Architecture_White_Light.jpg b/assets/medias/Architecture_White_Light.jpg new file mode 100644 index 00000000000..d5679f79dc7 Binary files /dev/null and b/assets/medias/Architecture_White_Light.jpg differ diff --git a/assets/medias/Architecture_coverr_circle_empty_highway_in_buenos_aires_587740985637.mp4 b/assets/medias/Architecture_coverr_circle_empty_highway_in_buenos_aires_587740985637.mp4 new file mode 100644 index 00000000000..30a926ad115 Binary files /dev/null and b/assets/medias/Architecture_coverr_circle_empty_highway_in_buenos_aires_587740985637.mp4 differ diff --git a/assets/medias/Art_Mine.jpg b/assets/medias/Art_Mine.jpg new file mode 100644 index 00000000000..35d8031f871 Binary files /dev/null and b/assets/medias/Art_Mine.jpg differ diff --git a/assets/medias/Art_Purple_light.jpg b/assets/medias/Art_Purple_light.jpg new file mode 100644 index 00000000000..02153b641e0 Binary files /dev/null and b/assets/medias/Art_Purple_light.jpg differ diff --git a/assets/medias/Art_Triangle_Man.jpg b/assets/medias/Art_Triangle_Man.jpg new file mode 100644 index 00000000000..0234e0629a9 Binary files /dev/null and b/assets/medias/Art_Triangle_Man.jpg differ diff --git a/assets/medias/Art_Wooden_Horse_Sculpture.mp4 b/assets/medias/Art_Wooden_Horse_Sculpture.mp4 new file mode 100644 index 00000000000..91791cc73a4 Binary files /dev/null and b/assets/medias/Art_Wooden_Horse_Sculpture.mp4 differ diff --git a/assets/medias/Event_18thAnniversary.jpg b/assets/medias/Event_18thAnniversary.jpg new file mode 100644 index 00000000000..1a9d7128271 Binary files /dev/null and b/assets/medias/Event_18thAnniversary.jpg differ diff --git a/assets/medias/Event_BenevidesWedding.jpg b/assets/medias/Event_BenevidesWedding.jpg new file mode 100644 index 00000000000..bf0413ce78a Binary files /dev/null and b/assets/medias/Event_BenevidesWedding.jpg differ diff --git a/assets/medias/Event_Emcee.jpg b/assets/medias/Event_Emcee.jpg new file mode 100644 index 00000000000..b553079359e Binary files /dev/null and b/assets/medias/Event_Emcee.jpg differ diff --git a/assets/medias/Event_KeyboardCheck.jpg b/assets/medias/Event_KeyboardCheck.jpg new file mode 100644 index 00000000000..4ed239031fd Binary files /dev/null and b/assets/medias/Event_KeyboardCheck.jpg differ diff --git a/assets/medias/Event_PintoWedding.jpg b/assets/medias/Event_PintoWedding.jpg new file mode 100644 index 00000000000..5912d55410f Binary files /dev/null and b/assets/medias/Event_PintoWedding.jpg differ diff --git a/assets/medias/Event_ProductPitch.jpg b/assets/medias/Event_ProductPitch.jpg new file mode 100644 index 00000000000..1f612804aee Binary files /dev/null and b/assets/medias/Event_ProductPitch.jpg differ diff --git a/assets/medias/Event_SeasideWedding.jpg b/assets/medias/Event_SeasideWedding.jpg new file mode 100644 index 00000000000..03ed8a4811f Binary files /dev/null and b/assets/medias/Event_SeasideWedding.jpg differ diff --git a/assets/medias/Event_Sparklers.jpg b/assets/medias/Event_Sparklers.jpg new file mode 100644 index 00000000000..8a8ea04c942 Binary files /dev/null and b/assets/medias/Event_Sparklers.jpg differ diff --git a/assets/medias/Event_VentureConference.jpg b/assets/medias/Event_VentureConference.jpg new file mode 100644 index 00000000000..7b9f1974d3e Binary files /dev/null and b/assets/medias/Event_VentureConference.jpg differ diff --git a/assets/medias/Event_WeddingGazebo.jpg b/assets/medias/Event_WeddingGazebo.jpg new file mode 100644 index 00000000000..3851ba5ed32 Binary files /dev/null and b/assets/medias/Event_WeddingGazebo.jpg differ diff --git a/assets/medias/Fashion_Melody_Red_on_Stripes.jpg b/assets/medias/Fashion_Melody_Red_on_Stripes.jpg new file mode 100644 index 00000000000..531ff86aa88 Binary files /dev/null and b/assets/medias/Fashion_Melody_Red_on_Stripes.jpg differ diff --git a/assets/medias/Fashion_Pattern_on_Pattern.jpg b/assets/medias/Fashion_Pattern_on_Pattern.jpg new file mode 100644 index 00000000000..856f2bd5d3d Binary files /dev/null and b/assets/medias/Fashion_Pattern_on_Pattern.jpg differ diff --git a/assets/medias/Fashion_Urban_Jungle.jpg b/assets/medias/Fashion_Urban_Jungle.jpg new file mode 100644 index 00000000000..c623ed12b7b Binary files /dev/null and b/assets/medias/Fashion_Urban_Jungle.jpg differ diff --git a/assets/medias/Fashion_Wings.jpg b/assets/medias/Fashion_Wings.jpg new file mode 100644 index 00000000000..8b34274ba5d Binary files /dev/null and b/assets/medias/Fashion_Wings.jpg differ diff --git a/assets/medias/Fashion_Yellow_Beach.jpg b/assets/medias/Fashion_Yellow_Beach.jpg new file mode 100644 index 00000000000..d7ac076640b Binary files /dev/null and b/assets/medias/Fashion_Yellow_Beach.jpg differ diff --git a/assets/medias/Portrait_AfternoonBreak.jpg b/assets/medias/Portrait_AfternoonBreak.jpg new file mode 100644 index 00000000000..3bb2ac52aee Binary files /dev/null and b/assets/medias/Portrait_AfternoonBreak.jpg differ diff --git a/assets/medias/Portrait_Alexandra.jpg b/assets/medias/Portrait_Alexandra.jpg new file mode 100644 index 00000000000..cb68ff83388 Binary files /dev/null and b/assets/medias/Portrait_Alexandra.jpg differ diff --git a/assets/medias/Portrait_Background.jpg b/assets/medias/Portrait_Background.jpg new file mode 100644 index 00000000000..417c982a84f Binary files /dev/null and b/assets/medias/Portrait_Background.jpg differ diff --git a/assets/medias/Portrait_Nora.jpg b/assets/medias/Portrait_Nora.jpg new file mode 100644 index 00000000000..1229f1d0226 Binary files /dev/null and b/assets/medias/Portrait_Nora.jpg differ diff --git a/assets/medias/Portrait_Shaw.jpg b/assets/medias/Portrait_Shaw.jpg new file mode 100644 index 00000000000..ef96d47ea21 Binary files /dev/null and b/assets/medias/Portrait_Shaw.jpg differ diff --git a/assets/medias/Portrait_Sunkissed.jpg b/assets/medias/Portrait_Sunkissed.jpg new file mode 100644 index 00000000000..564cd62780b Binary files /dev/null and b/assets/medias/Portrait_Sunkissed.jpg differ diff --git a/assets/medias/Portrait_Wednesday.jpg b/assets/medias/Portrait_Wednesday.jpg new file mode 100644 index 00000000000..4dbe4b02e4c Binary files /dev/null and b/assets/medias/Portrait_Wednesday.jpg differ diff --git a/assets/medias/Sport_2000_with_8.jpg b/assets/medias/Sport_2000_with_8.jpg new file mode 100644 index 00000000000..9b9dd1b6098 Binary files /dev/null and b/assets/medias/Sport_2000_with_8.jpg differ diff --git a/assets/medias/Sport_Butterfly.jpg b/assets/medias/Sport_Butterfly.jpg new file mode 100644 index 00000000000..d7072b8a43b Binary files /dev/null and b/assets/medias/Sport_Butterfly.jpg differ diff --git a/assets/medias/Sport_Jump.jpg b/assets/medias/Sport_Jump.jpg new file mode 100644 index 00000000000..d1582de0687 Binary files /dev/null and b/assets/medias/Sport_Jump.jpg differ diff --git a/assets/medias/Sport_Next_Hold.jpg b/assets/medias/Sport_Next_Hold.jpg new file mode 100644 index 00000000000..c0db72fd183 Binary files /dev/null and b/assets/medias/Sport_Next_Hold.jpg differ diff --git a/assets/medias/Sport_Race_End.jpg b/assets/medias/Sport_Race_End.jpg new file mode 100644 index 00000000000..74ce01abea4 Binary files /dev/null and b/assets/medias/Sport_Race_End.jpg differ diff --git a/assets/medias/Sport_Sky_Cross.jpg b/assets/medias/Sport_Sky_Cross.jpg new file mode 100644 index 00000000000..5e39b15d579 Binary files /dev/null and b/assets/medias/Sport_Sky_Cross.jpg differ diff --git a/assets/medias/Sport_Tricks_in_the_air.mp4 b/assets/medias/Sport_Tricks_in_the_air.mp4 new file mode 100644 index 00000000000..a2d592235e4 Binary files /dev/null and b/assets/medias/Sport_Tricks_in_the_air.mp4 differ diff --git a/assets/medias/Travel_Adventure_Door.jpg b/assets/medias/Travel_Adventure_Door.jpg new file mode 100644 index 00000000000..1312689296b Binary files /dev/null and b/assets/medias/Travel_Adventure_Door.jpg differ diff --git a/assets/medias/Travel_Bike_and_Stair.jpg b/assets/medias/Travel_Bike_and_Stair.jpg new file mode 100644 index 00000000000..e532050dfba Binary files /dev/null and b/assets/medias/Travel_Bike_and_Stair.jpg differ diff --git a/assets/medias/Travel_Boat_Wanderer.jpg b/assets/medias/Travel_Boat_Wanderer.jpg new file mode 100644 index 00000000000..ed41f74a9bb Binary files /dev/null and b/assets/medias/Travel_Boat_Wanderer.jpg differ diff --git a/assets/medias/Travel_Bridge_into_Forest.jpg b/assets/medias/Travel_Bridge_into_Forest.jpg new file mode 100644 index 00000000000..cd7ac1f3e4c Binary files /dev/null and b/assets/medias/Travel_Bridge_into_Forest.jpg differ diff --git a/assets/medias/Travel_HillsideColor.jpg b/assets/medias/Travel_HillsideColor.jpg new file mode 100644 index 00000000000..32323aecc29 Binary files /dev/null and b/assets/medias/Travel_HillsideColor.jpg differ diff --git a/assets/medias/Travel_Lonesome.jpg b/assets/medias/Travel_Lonesome.jpg new file mode 100644 index 00000000000..bb6fdc2e921 Binary files /dev/null and b/assets/medias/Travel_Lonesome.jpg differ diff --git a/assets/medias/Travel_On_the_Road.jpg b/assets/medias/Travel_On_the_Road.jpg new file mode 100644 index 00000000000..6962233f1a9 Binary files /dev/null and b/assets/medias/Travel_On_the_Road.jpg differ diff --git a/assets/medias/Travel_OpenMountain.jpg b/assets/medias/Travel_OpenMountain.jpg new file mode 100644 index 00000000000..86c5a3c4f7b Binary files /dev/null and b/assets/medias/Travel_OpenMountain.jpg differ diff --git a/assets/medias/Travel_Outdoor_Baths.jpg b/assets/medias/Travel_Outdoor_Baths.jpg new file mode 100644 index 00000000000..58f7dc2482f Binary files /dev/null and b/assets/medias/Travel_Outdoor_Baths.jpg differ diff --git a/assets/medias/Travel_Road_into_Hill.jpg b/assets/medias/Travel_Road_into_Hill.jpg new file mode 100644 index 00000000000..f8daa497283 Binary files /dev/null and b/assets/medias/Travel_Road_into_Hill.jpg differ diff --git a/assets/medias/Travel_Rock_Mountains.mp4 b/assets/medias/Travel_Rock_Mountains.mp4 new file mode 100644 index 00000000000..92de1f6d63d Binary files /dev/null and b/assets/medias/Travel_Rock_Mountains.mp4 differ diff --git a/assets/medias/Travel_SunsetonCanals.jpg b/assets/medias/Travel_SunsetonCanals.jpg new file mode 100644 index 00000000000..1a94e34a82d Binary files /dev/null and b/assets/medias/Travel_SunsetonCanals.jpg differ diff --git a/assets/medias/Travel_Tower.jpg b/assets/medias/Travel_Tower.jpg new file mode 100644 index 00000000000..954484d2164 Binary files /dev/null and b/assets/medias/Travel_Tower.jpg differ diff --git a/assets/medias/sport_water_tunnel.jpg b/assets/medias/sport_water_tunnel.jpg new file mode 100644 index 00000000000..df8ff6678a9 Binary files /dev/null and b/assets/medias/sport_water_tunnel.jpg differ diff --git a/assets/photographers/EllieRoseWilkens.jpg b/assets/photographers/EllieRoseWilkens.jpg new file mode 100644 index 00000000000..85b4e021200 Binary files /dev/null and b/assets/photographers/EllieRoseWilkens.jpg differ diff --git a/assets/photographers/MarcelNikolic.jpg b/assets/photographers/MarcelNikolic.jpg new file mode 100644 index 00000000000..a96a86ed8cb Binary files /dev/null and b/assets/photographers/MarcelNikolic.jpg differ diff --git a/assets/photographers/MimiKeel.jpg b/assets/photographers/MimiKeel.jpg new file mode 100644 index 00000000000..5df25f8502f Binary files /dev/null and b/assets/photographers/MimiKeel.jpg differ diff --git a/assets/photographers/NabeelBradford.jpg b/assets/photographers/NabeelBradford.jpg new file mode 100644 index 00000000000..acffb7a5fbb Binary files /dev/null and b/assets/photographers/NabeelBradford.jpg differ diff --git a/assets/photographers/RhodeDubois.jpg b/assets/photographers/RhodeDubois.jpg new file mode 100644 index 00000000000..17f4e8a4300 Binary files /dev/null and b/assets/photographers/RhodeDubois.jpg differ diff --git a/assets/photographers/TracyGalindo.jpg b/assets/photographers/TracyGalindo.jpg new file mode 100644 index 00000000000..306a6766fdb Binary files /dev/null and b/assets/photographers/TracyGalindo.jpg differ diff --git a/css/lightbox.css b/css/lightbox.css new file mode 100644 index 00000000000..a43f2600dd5 --- /dev/null +++ b/css/lightbox.css @@ -0,0 +1,73 @@ +#light-box { + position: fixed; + display: none; + z-index: 10; + left: 0; + top: 0; + height: 100vh; + width: 100vw; + justify-content: center; + align-items: center; + background-color: #fff; +} + +.light-box__modal { + display: flex; + justify-content: center; + align-items: center; + gap: 3em; + overflow: hidden; + height: fit-content; +} + +.light-box__right-side { + display: flex; + top: 0; + margin-top: 0; + position: relative; + flex-direction: column; + justify-content: space-between; + align-items: center; + height: 83vh; +} + +img.light-box__close-button { + filter: invert(17%) sepia(21%) saturate(7440%) hue-rotate(346deg) brightness(98%) contrast(93%); + align-self: flex-start; + position: fixed; + cursor: pointer; +} + +img.light-box__next-arrow { + cursor: pointer; + margin: auto 0; +} + +img.light-box__back-arrow { + cursor: pointer; + margin: auto 0; +} + +.light-box__content img { + max-width: 80vw; + max-height: 80vh; + -webkit-box-shadow: 5px 0 3px 0 rgba(0, 0, 0, 0.61); + box-shadow: 5px 0 3px 0 rgba(0, 0, 0, 0.61); + border-radius: 5px; +} + +.light-box__content h3 { + font-size: 24px; + font-weight: 400; + text-align: left; + color: #901c1c; +} + +.light-box__content video { + width: 100%; + height: 80vh; + object-fit: cover; + border-radius: 5px; + -webkit-box-shadow: 5px 0 3px 0 rgba(0, 0, 0, 0.61); + box-shadow: 5px 0 3px 0 rgba(0, 0, 0, 0.61); +} diff --git a/css/photographer.css b/css/photographer.css index 81854c023b9..abc7a8a59d8 100644 --- a/css/photographer.css +++ b/css/photographer.css @@ -1,11 +1,20 @@ +p { + margin: 0; +} + #contact_modal { display: none; } .photograph-header { - background-color: #FAFAFA; + background-color: #fafafa; height: 300px; - margin: 0 100px; + border-radius: 5px; + margin: 25px 100px; + padding: 0 3rem; + display: flex; + align-items: center; + justify-content: space-between; } .contact_button { @@ -16,15 +25,48 @@ width: 170px; height: 70px; border: none; - background-color: #901C1C; + background-color: #901c1c; border-radius: 5px; cursor: pointer; } +.photograph-header__name { + color: rgba(211, 87, 60, 1); + font-size: 64px; + margin: 0; +} + +.photograph-header__location { + color: rgba(144, 28, 28, 1); + font-size: 24px; +} + +.photograph-header__tagline { + color: rgba(82, 82, 82, 1); + font-size: 18px; +} + +.photograph-header__picture-wrapper { + width: 200px; + height: 200px; + border-radius: 50%; + overflow: hidden; + position: relative; +} + +.photograph-header__picture { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 155%; + height: auto; +} + .modal { border-radius: 5px; - background-color: #DB8876; - width: 50%; + width: 33vw; + background-color: #db8876; display: flex; flex-direction: column; align-items: center; @@ -56,7 +98,7 @@ form { } form label { - color: #312E2E; + color: #312e2e; font-size: 36px; } @@ -73,4 +115,189 @@ form input { height: 68px; border: none; border-radius: 5px; -} \ No newline at end of file +} + +.media-filters { + display: flex; + align-items: center; + position: relative; + margin-right: auto; + margin-left: 100px; + width: fit-content; + height: 30px; +} + +.select-menu { + width: 140px; + position: absolute; + box-shadow: 0 0 1px rgb(0, 0, 0, 0.1); + border-radius: 11px; + color: #fff; + text-wrap: nowrap; + top: 0; + left: 100%; +} + +.select-menu__options { + background: rgba(144, 28, 28, 1); + border-radius: 11px; + display: block; + box-shadow: 0 0 1px rgb(0, 0, 0, 0.1); +} + +.select-menu__option { + display: flex; + justify-content: space-between; + align-items: center; + gap: 1rem; + height: 30px; + padding: 10px 16px 10px 16px; + border-top: 1px solid #fff; + cursor: pointer; +} + +.select-menu__option svg { + border-top: 0; + display: block; +} + +.select-menu__option:not(:first-child) svg { + display: none; +} + +.select-menu__option:not(:first-child) { + display: none; +} + +.select-menu.active .select-menu__option:not(:first-child) { + display: block; +} + +.select-menu.active .select-menu__options { + display: block; +} + +.select-menu.active .select-menu__option svg { + transform: rotate(-180deg); +} + +.media-filters > span { + font-size: 18px; + font-weight: 700; + margin-right: 1rem; +} + +.media-card__list { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + gap: 3rem; + margin: 50px 100px; +} + +.media-card { + width: calc(33% - 3em); +} + +.media-card__desc { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 1rem; +} + +.media-card__desc h3 { + font-size: 24px; + font-weight: 400; + color: rgba(144, 28, 28, 1); + margin: 0; +} + +.media-card__like { + display: flex; + align-items: center; + gap: 5px; + cursor: pointer; +} + +.media-card__like i { + font-weight: 500; + font-size: 24px; + color: rgba(144, 28, 28, 1); +} + +.media-card__thumbnail-image { + width: 100%; + height: 351px; + object-fit: cover; + border-radius: 5px; + cursor: pointer; +} + +.media-card__thumbnail-video { + width: 100%; + height: 351px; + object-fit: cover; + border-radius: 5px; + cursor: pointer; +} + +footer { + display: flex; + justify-content: flex-end; + background: rgba(219, 136, 118, 1); + gap: 2rem; + padding: 1rem; + position: fixed; + bottom: 0; + right: 0; + border-radius: 5px 5px 0 0; + font-size: 24px; + font-weight: 500; +} + +footer span { + display: flex; + align-items: center; + gap: 0.5rem; +} + +#contact_modal { + display: none; + background: #c4c4c466; + position: fixed; + left: 0; + top: 0; + height: 100%; + width: 100%; +} + +#contact_modal div.modal { +} + +#contact_modal div.modal header { + display: flex; + align-items: baseline; + height: fit-content; +} + +#contact_modal div.modal header h2 { + margin: 0; + text-align: left; +} + +#contact_modal div.modal header img { + filter: invert(100%) sepia(0%) saturate(7500%) hue-rotate(236deg) brightness(110%) contrast(107%); +} + +#contact_modal form label { + width: 100%; +} + +#contact_modal form textarea { + width: 100%; + height: 170px; + border: none; + border-radius: 5px; +} diff --git a/css/reset.css b/css/reset.css new file mode 100644 index 00000000000..78a2339c52e --- /dev/null +++ b/css/reset.css @@ -0,0 +1,401 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; + /* 1 */ + height: 0; + /* 1 */ + overflow: visible; + /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; + /* 1 */ + font-size: 1em; + /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; + /* 1 */ + text-decoration: underline; + /* 2 */ + text-decoration: underline dotted; + /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; + /* 1 */ + font-size: 1em; + /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + line-height: 1.15; + /* 1 */ + margin: 0; + /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { + /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { + /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type='button']::-moz-focus-inner, +[type='reset']::-moz-focus-inner, +[type='submit']::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type='button']:-moz-focusring, +[type='reset']:-moz-focusring, +[type='submit']:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; + /* 1 */ + color: inherit; + /* 2 */ + display: table; + /* 1 */ + max-width: 100%; + /* 1 */ + padding: 0; + /* 3 */ + white-space: normal; + /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type='checkbox'], +[type='radio'] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type='number']::-webkit-inner-spin-button, +[type='number']::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type='search']::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} + +/** +* Custom reset +*/ +p, +h1, +h2, +h3, +h4 { + margin: 0; +} + +ul { + list-style: none; + margin: 0; + padding: 0; +} + +a { + text-decoration: none; + color: #000; +} diff --git a/css/style.css b/css/style.css index e4dafd3521b..9b73bc276fa 100644 --- a/css/style.css +++ b/css/style.css @@ -1,11 +1,12 @@ -@import url("photographer.css"); +@import url('photographer.css'); +@import url('lightbox.css'); +@import url('reset.css'); body { - font-family: "DM Sans", sans-serif; + font-family: 'DM Sans', sans-serif; margin: 0; } - header { display: flex; flex-direction: row; @@ -15,10 +16,14 @@ header { } h1 { - color: #901C1C; + color: #901c1c; margin-right: 100px; } +p { + margin-bottom: 0; +} + .logo { height: 50px; margin-left: 100px; @@ -39,12 +44,50 @@ h1 { flex-direction: column; } +.photographer_section article div { + width: 200px; + height: 200px; + border-radius: 50%; + overflow: hidden; + position: relative; +} + +.photographer_section article a { + display: flex; + flex-direction: column; + align-items: center; + text-decoration: none; +} + +.photographer_section article div img { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 155%; + height: auto; +} + .photographer_section article h2 { - color: #D3573C; + color: #d3573c; font-size: 36px; + margin: 0; } -.photographer_section article img { - height: 200px; - width: 200px; -} \ No newline at end of file +article > :nth-child(2) { + color: rgba(144, 28, 28, 1); + font-size: 13px; + margin: 0; +} + +article > :nth-child(3) { + color: rgba(0, 0, 0, 1); + font-size: 12px; + margin: 0; +} + +.photographer_section article i { + color: rgba(117, 117, 117, 1); + font-size: 11px; + margin: 0; +} diff --git a/data/photographers.json b/data/photographers.json index 2b517249787..98faec24e71 100644 --- a/data/photographers.json +++ b/data/photographers.json @@ -1,594 +1,591 @@ { - "photographers": [ - { - "name": "Mimi Keel", - "id": 243, - "city": "London", - "country": "UK", - "tagline": "Voir le beau dans le quotidien", - "price": 400, - "portrait": "MimiKeel.jpg" - }, - { - "name": "Ellie-Rose Wilkens", - "id": 930, - "city": "Paris", - "country": "France", - "tagline": "Capturer des compositions complexes", - "price": 250, - "portrait": "EllieRoseWilkens.jpg" - }, - { - "name": "Tracy Galindo", - "id": 82, - "city": "Montreal", - "country": "Canada", - "tagline": "Photographe freelance", - "price": 500, - "portrait": "TracyGalindo.jpg" - }, - { - "name": "Nabeel Bradford", - "id": 527, - "city": "Mexico City", - "country": "Mexico", - "tagline": "Toujours aller de l'avant", - "price": 350, - "portrait": "NabeelBradford.jpg" - }, - { - "name": "Rhode Dubois", - "id": 925, - "city": "Barcelona", - "country": "Spain", - "tagline": "Je crée des souvenirs", - "price": 275, - "portrait": "RhodeDubois.jpg" - }, - { - "name": "Marcel Nikolic", - "id": 195, - "city": "Berlin", - "country": "Germany", - "tagline": "Toujours à la recherche de LA photo", - "price": 300, - "portrait": "MarcelNikolic.jpg" - } - ], - "media": [ - { - "id": 342550, - "photographerId": 82, - "title": "Fashion Yellow Beach", - "image": "Fashion_Yellow_Beach.jpg", - "likes": 62, - "date": "2011-12-08", - "price": 55 - }, - { - "id": 8520927, - "photographerId": 82, - "title": "Fashion Urban Jungle", - "image": "Fashion_Urban_Jungle.jpg", - "likes": 11, - "date": "2011-11-06", - "price": 55 - }, - { - "id": 9025895, - "photographerId": 82, - "title": "Fashion Pattern on a Pattern", - "image": "Fashion_Pattern_on_Pattern.jpg", - "likes": 72, - "date": "2013-08-12", - "price": 55 - }, - { - "id": 9275938, - "photographerId": 82, - "title": "Wedding Gazebo", - "image": "Event_WeddingGazebo.jpg", - "likes": 69, - "date": "2018-02-22", - "price": 55 - }, - { - "id": 2053494, - "photographerId": 82, - "title": "Sparkles", - "image": "Event_Sparklers.jpg", - "likes": 2, - "date": "2020-05-25", - "price": 55 - }, - { - "id": 7324238, - "photographerId": 82, - "title": "18th Anniversary", - "image": "Event_18thAnniversary.jpg", - "likes": 33, - "date": "2019-06-12", - "price": 55 - }, - { - "id": 8328953, - "photographerId": 82, - "title": "Wooden sculpture of a horse", - "video": "Art_Wooden_Horse_Sculpture.mp4", - "likes": 24, - "date": "2011-12-08", - "price": 100 - }, - { - "id": 7502053, - "photographerId": 82, - "title": "Triangle Man", - "image": "Art_Triangle_Man.jpg", - "likes": 88, - "date": "2007-05-07", - "price": 55 - }, - { - "id": 8523492, - "photographerId": 82, - "title": "Purple Tunnel", - "image": "Art_Purple_light.jpg", - "likes": 24, - "date": "2018-05-05", - "price": 55 - }, - { - "id": 75902334, - "photographerId": 82, - "title": "Art Mine", - "image": "Art_Mine.jpg", - "likes": 75, - "date": "2019-11-25", - "price": 55 - }, - - { - "id": 73852953, - "photographerId": 925, - "title": "8 Rows", - "image": "Sport_2000_with_8.jpg", - "likes": 52, - "date": "2013-02-30", - "price": 70 - }, - { - "id": 92758372, - "photographerId": 925, - "title": "Fashion Wings", - "image": "Fashion_Wings.jpg", - "likes": 58, - "date": "2018-07-17", - "price": 70 - }, - { - "id": 32958383, - "photographerId": 925, - "title": "Melody Red on Stripes", - "image": "Fashion_Melody_Red_on_Stripes.jpg", - "likes": 11, - "date": "2019-08-12", - "price": 70 - }, - { - "id": 928587383, - "photographerId": 925, - "title": "Venture Conference", - "image": "Event_VentureConference.jpg", - "likes": 2, - "date": "2019-01-02", - "price": 70 - }, - { - "id": 725639493, - "photographerId": 925, - "title": "Product Pitch", - "image": "Event_ProductPitch.jpg", - "likes": 3, - "date": "2019-05-20", - "price": 70 - }, - { - "id": 23394384, - "photographerId": 925, - "title": "Musical Festival Keyboard", - "image": "Event_KeyboardCheck.jpg", - "likes": 52, - "date": "2019-07-18", - "price": 70 - }, - { - "id": 87367293, - "photographerId": 925, - "title": "Musical Festival Singer", - "image": "Event_Emcee.jpg", - "likes": 23, - "date": "2018-02-22", - "price": 70 - }, - { - "id": 593834784, - "photographerId": 925, - "title": "Animal Majesty", - "image": "Animals_Majesty.jpg", - "likes": 52, - "date": "2017-03-13", - "price": 70 - }, - { - "id": 83958935, - "photographerId": 925, - "title": "Cute puppy on sunset", - "video": "Animals_Puppiness.mp4", - "likes": 52, - "date": "2016-06-12", - "price": 70 - }, - { - "id": 394583434, - "photographerId": 527, - "title": "Rocky mountains from the air", - "video": "Travel_Rock_Mountains.mp4", - "likes": 23, - "date": "2017-03-18", - "price": 45 - }, - { - "id": 343423425, - "photographerId": 527, - "title": "Outdoor Baths", - "image": "Travel_Outdoor_Baths.jpg", - "likes": 101, - "date": "2017-04-03", - "price": 45 - }, - { - "id": 73434243, - "photographerId": 527, - "title": "Road into the Hill", - "image": "Travel_Road_into_Hill.jpg", - "likes": 99, - "date": "2018-04-30", - "price": 45 - }, - { - "id": 23425523, - "photographerId": 527, - "title": "Bridge into the Forest", - "image": "Travel_Bridge_into_Forest.jpg", - "likes": 34, - "date": "2016-04-05", - "price": 45 - }, - { - "id": 23134513, - "photographerId": 527, - "title": "Boat Wonderer", - "image": "Travel_Boat_Wanderer.jpg", - "likes": 23, - "date": "2017-03-18", - "price": 45 - }, - { - "id": 92352352, - "photographerId": 527, - "title": "Portrait Sunkiss", - "image": "Portrait_Sunkissed.jpg", - "likes": 66, - "date": "2018-05-24", - "price": 45 - }, - { - "id": 34513453, - "photographerId": 527, - "title": "Shaw Potrait", - "image": "Portrait_Shaw.jpg", - "likes": 52, - "date": "2017-04-21", - "price": 45 - }, - { - "id": 23523533, - "photographerId": 527, - "title": "Alexandra", - "image": "Portrait_Alexandra.jpg", - "likes": 95, - "date": "2018-11-02", - "price": 45 - }, - { - "id": 525834234, - "photographerId": 527, - "title": "Afternoon Break", - "image": "Portrait_AfternoonBreak.jpg", - "likes": 25, - "date": "2019-01-02", - "price": 45 - }, - - { - "id": 623534343, - "photographerId": 243, - "title": "Lonesome", - "image": "Travel_Lonesome.jpg", - "likes": 88, - "date": "2019-02-03", - "price": 45 - }, - { - "id": 625025343, - "photographerId": 243, - "title": "Hillside Color", - "image": "Travel_HillsideColor.jpg", - "likes": 85, - "date": "2019-04-03", - "price": 45 - }, - { - "id": 2525345343, - "photographerId": 243, - "title": "Wednesday Potrait", - "image": "Portrait_Wednesday.jpg", - "likes": 34, - "date": "2019-04-07", - "price": 45 - }, - { - "id": 2523434634, - "photographerId": 243, - "title": "Nora Portrait", - "image": "Portrait_Nora.jpg", - "likes": 63, - "date": "2019-04-07", - "price": 45 - }, - { - "id": 398847109, - "photographerId": 243, - "title": "Raw Black Portrait", - "image": "Portrait_Background.jpg", - "likes": 55, - "date": "2019-06-20", - "price": 45 - }, - { - "id": 2534342, - "photographerId": 243, - "title": "Seaside Wedding", - "image": "Event_SeasideWedding.jpg", - "likes": 25, - "date": "2019-06-21", - "price": 45 - }, - { - "id": 65235234, - "photographerId": 243, - "title": "Boulder Wedding", - "image": "Event_PintoWedding.jpg", - "likes": 52, - "date": "2019-06-25", - "price": 45 - }, - { - "id": 23523434, - "photographerId": 243, - "title": "Benevides Wedding", - "image": "Event_BenevidesWedding.jpg", - "likes": 77, - "date": "2019-06-28", - "price": 45 - }, - { - "id": 5234343, - "photographerId": 243, - "title": "Wild horses in the mountains", - "video": "Animals_Wild_Horses_in_the_mountains.mp4", - "likes": 142, - "date": "2019-08-23", - "price": 60 - }, - { - "id": 95234343, - "photographerId": 243, - "title": "Rainbow Bird", - "image": "Animals_Rainbow.jpg", - "likes": 59, - "date": "2019-07-02", - "price": 60 - }, - - { - "id": 52343416, - "photographerId": 195, - "title": "Japanese Tower, Kyoto", - "image": "Travel_Tower.jpg", - "likes": 25, - "date": "2019-04-03", - "price": 60 - }, - { - "id": 2523434, - "photographerId": 195, - "title": "Senset on Canals, Venice", - "image": "Travel_SunsetonCanals.jpg", - "likes": 53, - "date": "2019-05-06", - "price": 60 - }, - { - "id": 95293534, - "photographerId": 195, - "title": "Mountain and Lake", - "image": "Travel_OpenMountain.jpg", - "likes": 33, - "date": "2019-05-12", - "price": 60 - }, - { - "id": 356234343, - "photographerId": 195, - "title": "City Bike and Stair, Paris", - "image": "Travel_Bike_and_Stair.jpg", - "likes": 53, - "date": "2019-06-20", - "price": 60 - }, - { - "id": 235234343, - "photographerId": 195, - "title": "Adventure Door, India", - "image": "Travel_Adventure_Door.jpg", - "likes": 63, - "date": "2019-06-26", - "price": 60 - }, - { - "id": 6234234343, - "photographerId": 195, - "title": "Contrast, St Petersburg", - "image": "Architecture_Contrast.jpg", - "likes": 52, - "date": "2019-06-30", - "price": 60 - }, - { - "id": 6525666253, - "photographerId": 195, - "title": "On a Hill, Tibet", - "image": "Architecture_On_a_hill.jpg", - "likes": 63, - "date": "2019-07-20", - "price": 60 - }, - { - "id": 98252523433, - "photographerId": 195, - "title": "Leaning Tower, Pisa", - "image": "Architecture_Dome.jpg", - "likes": 88, - "date": "2020-01-05", - "price": 60 - }, - { - "id": 9259398453, - "photographerId": 195, - "title": "Drone shot of Buenos Aires highways", - "video": "Architecture_coverr_circle_empty_highway_in_buenos_aires_587740985637.mp4", - "likes": 57, - "date": "2020-01-20", - "price": 65 - }, - { - "id": 3523523534, - "photographerId": 195, - "title": "Corner Building and Blue Sky", - "image": "Architecture_Corner_Room.jpg", - "likes": 54, - "date": "2020-05-05", - "price": 60 - }, - { - "id": 952343423, - "photographerId": 930, - "title": "Tricks in te air", - "video": "Sport_Tricks_in_the_air.mp4", - "likes": 150, - "date": "2018-02-30", - "price": 70 - }, - { - "id": 235234343, - "photographerId": 930, - "title": "Climber", - "image": "Sport_Next_Hold.jpg", - "likes": 101, - "date": "2018-03-05", - "price": 65 - }, - { - "id": 235343222, - "photographerId": 930, - "title": "Surfer", - "image": "sport_water_tunnel.jpg", - "likes": 103, - "date": "2018-03-10", - "price": 70 - }, - { - "id": 7775342343, - "photographerId": 930, - "title": "Skier", - "image": "Sport_Sky_Cross.jpg", - "likes": 77, - "date": "2018-04-16", - "price": 50 - }, - { - "id": 9253445784, - "photographerId": 930, - "title": "Race End", - "image": "Sport_Race_End.jpg", - "likes": 88, - "date": "2018-04-22", - "price": 65 - }, - { - "id": 22299394, - "photographerId": 930, - "title": "Jump!", - "image": "Sport_Jump.jpg", - "likes": 95, - "date": "2018-04-27", - "price": 70 - }, - { - "id": 3452342633, - "photographerId": 930, - "title": "White Light", - "image": "Architecture_White_Light.jpg", - "likes": 52, - "date": "2018-05-03", - "price": 75 - }, - { - "id": 939234243, - "photographerId": 930, - "title": "Water on Modern Building", - "image": "Architecture_Water_on_Modern.jpg", - "likes": 55, - "date": "2018-05-10", - "price": 72 - }, - { - "id": 222959233, - "photographerId": 930, - "title": "Horseshoe", - "image": "Architecture_Horseshoe.jpg", - "likes": 85, - "date": "2018-05-15", - "price": 71 - }, - { - "id": 965933434, - "photographerId": 930, - "title": "Cross Bar", - "image": "Architecture_Cross_Bar.jpg", - "likes": 66, - "date": "2018-05-20", - "price": 58 - }, - { - "id": 777723343, - "photographerId": 930, - "title": "Connected Curves", - "image": "Architecture_Connected_Curves.jpg", - "likes": 79, - "date": "2018-05-21", - "price": 80 - } - ] + "photographers": [ + { + "name": "Mimi Keel", + "id": 243, + "city": "London", + "country": "UK", + "tagline": "Voir le beau dans le quotidien", + "price": 400, + "portrait": "MimiKeel.jpg" + }, + { + "name": "Ellie-Rose Wilkens", + "id": 930, + "city": "Paris", + "country": "France", + "tagline": "Capturer des compositions complexes", + "price": 250, + "portrait": "EllieRoseWilkens.jpg" + }, + { + "name": "Tracy Galindo", + "id": 82, + "city": "Montreal", + "country": "Canada", + "tagline": "Photographe freelance", + "price": 500, + "portrait": "TracyGalindo.jpg" + }, + { + "name": "Nabeel Bradford", + "id": 527, + "city": "Mexico City", + "country": "Mexico", + "tagline": "Toujours aller de l'avant", + "price": 350, + "portrait": "NabeelBradford.jpg" + }, + { + "name": "Rhode Dubois", + "id": 925, + "city": "Barcelona", + "country": "Spain", + "tagline": "Je crée des souvenirs", + "price": 275, + "portrait": "RhodeDubois.jpg" + }, + { + "name": "Marcel Nikolic", + "id": 195, + "city": "Berlin", + "country": "Germany", + "tagline": "Toujours à la recherche de LA photo", + "price": 300, + "portrait": "MarcelNikolic.jpg" + } + ], + "media": [ + { + "id": 342550, + "photographerId": 82, + "title": "Fashion Yellow Beach", + "image": "Fashion_Yellow_Beach.jpg", + "likes": 62, + "date": "2011-12-08", + "price": 55 + }, + { + "id": 8520927, + "photographerId": 82, + "title": "Fashion Urban Jungle", + "image": "Fashion_Urban_Jungle.jpg", + "likes": 11, + "date": "2011-11-06", + "price": 55 + }, + { + "id": 9025895, + "photographerId": 82, + "title": "Fashion Pattern on a Pattern", + "image": "Fashion_Pattern_on_Pattern.jpg", + "likes": 72, + "date": "2013-08-12", + "price": 55 + }, + { + "id": 9275938, + "photographerId": 82, + "title": "Wedding Gazebo", + "image": "Event_WeddingGazebo.jpg", + "likes": 69, + "date": "2018-02-22", + "price": 55 + }, + { + "id": 2053494, + "photographerId": 82, + "title": "Sparkles", + "image": "Event_Sparklers.jpg", + "likes": 2, + "date": "2020-05-25", + "price": 55 + }, + { + "id": 7324238, + "photographerId": 82, + "title": "18th Anniversary", + "image": "Event_18thAnniversary.jpg", + "likes": 33, + "date": "2019-06-12", + "price": 55 + }, + { + "id": 8328953, + "photographerId": 82, + "title": "Wooden sculpture of a horse", + "video": "Art_Wooden_Horse_Sculpture.mp4", + "likes": 24, + "date": "2011-12-08", + "price": 100 + }, + { + "id": 7502053, + "photographerId": 82, + "title": "Triangle Man", + "image": "Art_Triangle_Man.jpg", + "likes": 88, + "date": "2007-05-07", + "price": 55 + }, + { + "id": 8523492, + "photographerId": 82, + "title": "Purple Tunnel", + "image": "Art_Purple_light.jpg", + "likes": 24, + "date": "2018-05-05", + "price": 55 + }, + { + "id": 75902334, + "photographerId": 82, + "title": "Art Mine", + "image": "Art_Mine.jpg", + "likes": 75, + "date": "2019-11-25", + "price": 55 + }, + { + "id": 73852953, + "photographerId": 925, + "title": "8 Rows", + "image": "Sport_2000_with_8.jpg", + "likes": 52, + "date": "2013-02-30", + "price": 70 + }, + { + "id": 92758372, + "photographerId": 925, + "title": "Fashion Wings", + "image": "Fashion_Wings.jpg", + "likes": 58, + "date": "2018-07-17", + "price": 70 + }, + { + "id": 32958383, + "photographerId": 925, + "title": "Melody Red on Stripes", + "image": "Fashion_Melody_Red_on_Stripes.jpg", + "likes": 11, + "date": "2019-08-12", + "price": 70 + }, + { + "id": 928587383, + "photographerId": 925, + "title": "Venture Conference", + "image": "Event_VentureConference.jpg", + "likes": 2, + "date": "2019-01-02", + "price": 70 + }, + { + "id": 725639493, + "photographerId": 925, + "title": "Product Pitch", + "image": "Event_ProductPitch.jpg", + "likes": 3, + "date": "2019-05-20", + "price": 70 + }, + { + "id": 23394384, + "photographerId": 925, + "title": "Musical Festival Keyboard", + "image": "Event_KeyboardCheck.jpg", + "likes": 52, + "date": "2019-07-18", + "price": 70 + }, + { + "id": 87367293, + "photographerId": 925, + "title": "Musical Festival Singer", + "image": "Event_Emcee.jpg", + "likes": 23, + "date": "2018-02-22", + "price": 70 + }, + { + "id": 593834784, + "photographerId": 925, + "title": "Animal Majesty", + "image": "Animals_Majesty.jpg", + "likes": 52, + "date": "2017-03-13", + "price": 70 + }, + { + "id": 83958935, + "photographerId": 925, + "title": "Cute puppy on sunset", + "video": "Animals_Puppiness.mp4", + "likes": 52, + "date": "2016-06-12", + "price": 70 + }, + { + "id": 394583434, + "photographerId": 527, + "title": "Rocky mountains from the air", + "video": "Travel_Rock_Mountains.mp4", + "likes": 23, + "date": "2017-03-18", + "price": 45 + }, + { + "id": 343423425, + "photographerId": 527, + "title": "Outdoor Baths", + "image": "Travel_Outdoor_Baths.jpg", + "likes": 101, + "date": "2017-04-03", + "price": 45 + }, + { + "id": 73434243, + "photographerId": 527, + "title": "Road into the Hill", + "image": "Travel_Road_into_Hill.jpg", + "likes": 99, + "date": "2018-04-30", + "price": 45 + }, + { + "id": 23425523, + "photographerId": 527, + "title": "Bridge into the Forest", + "image": "Travel_Bridge_into_Forest.jpg", + "likes": 34, + "date": "2016-04-05", + "price": 45 + }, + { + "id": 23134513, + "photographerId": 527, + "title": "Boat Wonderer", + "image": "Travel_Boat_Wanderer.jpg", + "likes": 23, + "date": "2017-03-18", + "price": 45 + }, + { + "id": 92352352, + "photographerId": 527, + "title": "Portrait Sunkiss", + "image": "Portrait_Sunkissed.jpg", + "likes": 66, + "date": "2018-05-24", + "price": 45 + }, + { + "id": 34513453, + "photographerId": 527, + "title": "Shaw Potrait", + "image": "Portrait_Shaw.jpg", + "likes": 52, + "date": "2017-04-21", + "price": 45 + }, + { + "id": 23523533, + "photographerId": 527, + "title": "Alexandra", + "image": "Portrait_Alexandra.jpg", + "likes": 95, + "date": "2018-11-02", + "price": 45 + }, + { + "id": 525834234, + "photographerId": 527, + "title": "Afternoon Break", + "image": "Portrait_AfternoonBreak.jpg", + "likes": 25, + "date": "2019-01-02", + "price": 45 + }, + { + "id": 623534343, + "photographerId": 243, + "title": "Lonesome", + "image": "Travel_Lonesome.jpg", + "likes": 88, + "date": "2019-02-03", + "price": 45 + }, + { + "id": 625025343, + "photographerId": 243, + "title": "Hillside Color", + "image": "Travel_HillsideColor.jpg", + "likes": 85, + "date": "2019-04-03", + "price": 45 + }, + { + "id": 2525345343, + "photographerId": 243, + "title": "Wednesday Potrait", + "image": "Portrait_Wednesday.jpg", + "likes": 34, + "date": "2019-04-07", + "price": 45 + }, + { + "id": 2523434634, + "photographerId": 243, + "title": "Nora Portrait", + "image": "Portrait_Nora.jpg", + "likes": 63, + "date": "2019-04-07", + "price": 45 + }, + { + "id": 398847109, + "photographerId": 243, + "title": "Raw Black Portrait", + "image": "Portrait_Background.jpg", + "likes": 55, + "date": "2019-06-20", + "price": 45 + }, + { + "id": 2534342, + "photographerId": 243, + "title": "Seaside Wedding", + "image": "Event_SeasideWedding.jpg", + "likes": 25, + "date": "2019-06-21", + "price": 45 + }, + { + "id": 65235234, + "photographerId": 243, + "title": "Boulder Wedding", + "image": "Event_PintoWedding.jpg", + "likes": 52, + "date": "2019-06-25", + "price": 45 + }, + { + "id": 23523434, + "photographerId": 243, + "title": "Benevides Wedding", + "image": "Event_BenevidesWedding.jpg", + "likes": 77, + "date": "2019-06-28", + "price": 45 + }, + { + "id": 5234343, + "photographerId": 243, + "title": "Wild horses in the mountains", + "video": "Animals_Wild_Horses_in_the_mountains.mp4", + "likes": 142, + "date": "2019-08-23", + "price": 60 + }, + { + "id": 95234343, + "photographerId": 243, + "title": "Rainbow Bird", + "image": "Animals_Rainbow.jpg", + "likes": 59, + "date": "2019-07-02", + "price": 60 + }, + { + "id": 52343416, + "photographerId": 195, + "title": "Japanese Tower, Kyoto", + "image": "Travel_Tower.jpg", + "likes": 25, + "date": "2019-04-03", + "price": 60 + }, + { + "id": 2523434, + "photographerId": 195, + "title": "Senset on Canals, Venice", + "image": "Travel_SunsetonCanals.jpg", + "likes": 53, + "date": "2019-05-06", + "price": 60 + }, + { + "id": 95293534, + "photographerId": 195, + "title": "Mountain and Lake", + "image": "Travel_OpenMountain.jpg", + "likes": 33, + "date": "2019-05-12", + "price": 60 + }, + { + "id": 356234343, + "photographerId": 195, + "title": "City Bike and Stair, Paris", + "image": "Travel_Bike_and_Stair.jpg", + "likes": 53, + "date": "2019-06-20", + "price": 60 + }, + { + "id": 235234343, + "photographerId": 195, + "title": "Adventure Door, India", + "image": "Travel_Adventure_Door.jpg", + "likes": 63, + "date": "2019-06-26", + "price": 60 + }, + { + "id": 6234234343, + "photographerId": 195, + "title": "Contrast, St Petersburg", + "image": "Architecture_Contrast.jpg", + "likes": 52, + "date": "2019-06-30", + "price": 60 + }, + { + "id": 6525666253, + "photographerId": 195, + "title": "On a Hill, Tibet", + "image": "Architecture_On_a_hill.jpg", + "likes": 63, + "date": "2019-07-20", + "price": 60 + }, + { + "id": 98252523433, + "photographerId": 195, + "title": "Leaning Tower, Pisa", + "image": "Architecture_Dome.jpg", + "likes": 88, + "date": "2020-01-05", + "price": 60 + }, + { + "id": 9259398453, + "photographerId": 195, + "title": "Drone shot of Buenos Aires highways", + "video": "Architecture_coverr_circle_empty_highway_in_buenos_aires_587740985637.mp4", + "likes": 57, + "date": "2020-01-20", + "price": 65 + }, + { + "id": 3523523534, + "photographerId": 195, + "title": "Corner Building and Blue Sky", + "image": "Architecture_Corner_Room.jpg", + "likes": 54, + "date": "2020-05-05", + "price": 60 + }, + { + "id": 952343423, + "photographerId": 930, + "title": "Tricks in te air", + "video": "Sport_Tricks_in_the_air.mp4", + "likes": 150, + "date": "2018-02-30", + "price": 70 + }, + { + "id": 235234343, + "photographerId": 930, + "title": "Climber", + "image": "Sport_Next_Hold.jpg", + "likes": 101, + "date": "2018-03-05", + "price": 65 + }, + { + "id": 235343222, + "photographerId": 930, + "title": "Surfer", + "image": "sport_water_tunnel.jpg", + "likes": 103, + "date": "2018-03-10", + "price": 70 + }, + { + "id": 7775342343, + "photographerId": 930, + "title": "Skier", + "image": "Sport_Sky_Cross.jpg", + "likes": 77, + "date": "2018-04-16", + "price": 50 + }, + { + "id": 9253445784, + "photographerId": 930, + "title": "Race End", + "image": "Sport_Race_End.jpg", + "likes": 88, + "date": "2018-04-22", + "price": 65 + }, + { + "id": 22299394, + "photographerId": 930, + "title": "Jump!", + "image": "Sport_Jump.jpg", + "likes": 95, + "date": "2018-04-27", + "price": 70 + }, + { + "id": 3452342633, + "photographerId": 930, + "title": "White Light", + "image": "Architecture_White_Light.jpg", + "likes": 52, + "date": "2018-05-03", + "price": 75 + }, + { + "id": 939234243, + "photographerId": 930, + "title": "Water on Modern Building", + "image": "Architecture_Water_on_Modern.jpg", + "likes": 55, + "date": "2018-05-10", + "price": 72 + }, + { + "id": 222959233, + "photographerId": 930, + "title": "Horseshoe", + "image": "Architecture_Horseshoe.jpg", + "likes": 85, + "date": "2018-05-15", + "price": 71 + }, + { + "id": 965933434, + "photographerId": 930, + "title": "Cross Bar", + "image": "Architecture_Cross_Bar.jpg", + "likes": 66, + "date": "2018-05-20", + "price": 58 + }, + { + "id": 777723343, + "photographerId": 930, + "title": "Connected Curves", + "image": "Architecture_Connected_Curves.jpg", + "likes": 79, + "date": "2018-05-21", + "price": 80 + } + ] } diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000000..2edbef8ef65 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,8 @@ +import globals from "globals"; +import pluginJs from "@eslint/js"; + + +export default [ + {languageOptions: { globals: globals.browser }}, + pluginJs.configs.recommended, +]; \ No newline at end of file diff --git a/index.html b/index.html index 7927da414a0..8a8667b4ff2 100644 --- a/index.html +++ b/index.html @@ -1,21 +1,20 @@ - + - - - - + + + + Fisheye
- -

Nos photographes

+ +

Nos photographes

-
+
- - + diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 00000000000..fb94d421bdb --- /dev/null +++ b/netlify.toml @@ -0,0 +1,2 @@ +[build.environment] +NODE_ENV = "production" diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000000..39fd4f87ea5 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1092 @@ +{ + "name": "fisheye", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fisheye", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@eslint/js": "^9.12.0", + "eslint": "^9.12.0", + "globals": "^15.10.0", + "prettier": "^3.3.3" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.6.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.12.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@eslint/js/-/js-9.12.0.tgz", + "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@humanfs/core/-/core-0.19.0.tgz", + "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.5", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@humanfs/node/-/node-0.16.5.tgz", + "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.0", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.12.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/eslint/-/eslint-9.12.0.tgz", + "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.12.0", + "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.1.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.1.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.2.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "15.10.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/globals/-/globals-15.10.0.tgz", + "integrity": "sha512-tqFIbz83w4Y5TCbtgjZjApohbuh7K9BxGYFm7ifwDR240tvdb7P9x+/9VvUKlmkPoiknoJtanI8UOrqxS3a7lQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "http://registry.beluga.intra.groupama.fr/repository/npm/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000000..0c40729d93b --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "fisheye", + "version": "1.0.0", + "description": "Créez un site accessible pour une plateforme de photographes", + "main": "index.html", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/getsu7/Fisheye.git" + }, + "author": "getsu7", + "license": "ISC", + "bugs": { + "url": "https://github.com/getsu7/Fisheye/issues" + }, + "homepage": "https://github.com/getsu7/Fisheye#readme", + "devDependencies": { + "@eslint/js": "^9.12.0", + "eslint": "^9.12.0", + "globals": "^15.10.0", + "prettier": "^3.3.3" + } +} diff --git a/photographer.html b/photographer.html index d85fc10fe89..7a14e0545c8 100644 --- a/photographer.html +++ b/photographer.html @@ -1,37 +1,79 @@ - - - - - - - - Fisheye - photographe - - -
- -
-
-
- -
-
-
- -
- - - +
+
+ +
+
+ Trier par + +
+
    +
  • + Popularité + +
  • +
  • + Date +
  • +
  • + Titre +
  • +
+
+
+
+
+ +
+
+ + + diff --git a/scripts/pages/index.js b/scripts/pages/index.js deleted file mode 100644 index 42895574b83..00000000000 --- a/scripts/pages/index.js +++ /dev/null @@ -1,46 +0,0 @@ - async function getPhotographers() { - // Ceci est un exemple de données pour avoir un affichage de photographes de test dès le démarrage du projet, - // mais il sera à remplacer avec une requête sur le fichier JSON en utilisant "fetch". - let photographers = [ - { - "name": "Ma data test", - "id": 1, - "city": "Paris", - "country": "France", - "tagline": "Ceci est ma data test", - "price": 400, - "portrait": "account.png" - }, - { - "name": "Autre data test", - "id": 2, - "city": "Londres", - "country": "UK", - "tagline": "Ceci est ma data test 2", - "price": 500, - "portrait": "account.png" - }, - ] - // et bien retourner le tableau photographers seulement une fois récupéré - return ({ - photographers: [...photographers, ...photographers, ...photographers]}) - } - - async function displayData(photographers) { - const photographersSection = document.querySelector(".photographer_section"); - - photographers.forEach((photographer) => { - const photographerModel = photographerTemplate(photographer); - const userCardDOM = photographerModel.getUserCardDOM(); - photographersSection.appendChild(userCardDOM); - }); - } - - async function init() { - // Récupère les datas des photographes - const { photographers } = await getPhotographers(); - displayData(photographers); - } - - init(); - diff --git a/scripts/pages/photographer.js b/scripts/pages/photographer.js deleted file mode 100644 index cee76db76f8..00000000000 --- a/scripts/pages/photographer.js +++ /dev/null @@ -1 +0,0 @@ -//Mettre le code JavaScript lié à la page photographer.html \ No newline at end of file diff --git a/scripts/templates/photographer.js b/scripts/templates/photographer.js deleted file mode 100644 index f177ca1a8a7..00000000000 --- a/scripts/templates/photographer.js +++ /dev/null @@ -1,17 +0,0 @@ -function photographerTemplate(data) { - const { name, portrait } = data; - - const picture = `assets/photographers/${portrait}`; - - function getUserCardDOM() { - const article = document.createElement( 'article' ); - const img = document.createElement( 'img' ); - img.setAttribute("src", picture) - const h2 = document.createElement( 'h2' ); - h2.textContent = name; - article.appendChild(img); - article.appendChild(h2); - return (article); - } - return { name, picture, getUserCardDOM } -} \ No newline at end of file diff --git a/scripts/utils/contactForm.js b/scripts/utils/contactForm.js deleted file mode 100644 index 9180380082c..00000000000 --- a/scripts/utils/contactForm.js +++ /dev/null @@ -1,9 +0,0 @@ -function displayModal() { - const modal = document.getElementById("contact_modal"); - modal.style.display = "block"; -} - -function closeModal() { - const modal = document.getElementById("contact_modal"); - modal.style.display = "none"; -} diff --git a/src/api/photographerService.js b/src/api/photographerService.js new file mode 100644 index 00000000000..1b6962325de --- /dev/null +++ b/src/api/photographerService.js @@ -0,0 +1,46 @@ +export const usePhotographerService = () => { + const getPhotographers = async () => { + if (window.localStorage.getItem('photographers') === null) { + const response = await fetch('./data/photographers.json'); + const results = await response.json(); + + const photographers = results.photographers.map((photographer) => ({ + ...photographer, + media: [], + })); + + const photographersById = {}; + photographers.forEach((photographer) => { + photographersById[photographer.id] = photographer; + }); + + results.media.forEach((media) => { + const photographerId = media.photographerId; + if (photographersById[photographerId]) { + photographersById[photographerId].media.push(media); + } + }); + + window.localStorage.setItem('photographers', JSON.stringify(photographers)); + } + return JSON.parse(window.localStorage.getItem('photographers')); + }; + + const getPhotographerById = (idPhotographer, photographers) => { + if (!photographers.find((photographer) => photographer.id === idPhotographer)) { + window.location.href = '../../404.html'; + } + return photographers.find((photographer) => photographer.id === idPhotographer); + }; + + const getPhotographerLikes = (photographer) => { + let likes = 0; + + photographer.media.forEach((media) => { + likes += media.likes; + }); + + return likes; + }; + return { getPhotographers, getPhotographerById, getPhotographerLikes }; +}; diff --git a/src/components/mediaFilter.js b/src/components/mediaFilter.js new file mode 100644 index 00000000000..185aa09d2fa --- /dev/null +++ b/src/components/mediaFilter.js @@ -0,0 +1,19 @@ +const mediaFilter = document.querySelector('#media-filter'), + selectOptions = mediaFilter.querySelectorAll('.select-menu__option'); + +mediaFilter.addEventListener('click', () => { + mediaFilter.classList.toggle('active'); +}); + +mediaFilter.addEventListener('keydown', (ev) => { + if (ev.code === 'Enter' || ev.code === 'Space') { + mediaFilter.classList.toggle('active'); + selectOptions[0].focus(); + } +}); + +document.addEventListener('click', (event) => { + if (!mediaFilter.contains(event.target)) { + mediaFilter.classList.remove('active'); + } +}); diff --git a/src/constants/filterConstant.js b/src/constants/filterConstant.js new file mode 100644 index 00000000000..fa941ee1cd5 --- /dev/null +++ b/src/constants/filterConstant.js @@ -0,0 +1,10 @@ +export const retrieveFilterLabelFromValue = (value) => { + switch (value) { + case 'popularity': + return 'Popularité'; + case 'date': + return 'Date'; + case 'title': + return 'Titre'; + } +}; diff --git a/src/factories/mediaFactorie.js b/src/factories/mediaFactorie.js new file mode 100644 index 00000000000..aae2ccf1b6b --- /dev/null +++ b/src/factories/mediaFactorie.js @@ -0,0 +1,25 @@ +import { usePhotographerTemplate } from '../templates/photographer.js'; +import { useLightboxTemplate } from '../templates/lightbox.js'; + +const { getPictureCardDOM, getVideoCardDOM } = usePhotographerTemplate(); + +const { getLightBoxPictureDOM, getLightBoxVideoDOM, getLightBoxImageContent, getLightBoxVideoContent } = + useLightboxTemplate(); + +export const useMediaFactorie = () => { + const createMediaCard = (media) => { + if (media.video) return getVideoCardDOM(media); + if (media.image) return getPictureCardDOM(media); + }; + + const createLightBoxMediaView = (media) => { + if (media.video) return getLightBoxVideoDOM(media); + if (media.image) return getLightBoxPictureDOM(media); + }; + + const createLightBoxMediaContent = (media) => { + if (media.video) return getLightBoxVideoContent(media); + if (media.image) return getLightBoxImageContent(media); + }; + return { createMediaCard, createLightBoxMediaView, createLightBoxMediaContent }; +}; diff --git a/src/pages/index.js b/src/pages/index.js new file mode 100644 index 00000000000..aba7846b0a9 --- /dev/null +++ b/src/pages/index.js @@ -0,0 +1,22 @@ +import { usePhotographerService } from '../api/photographerService.js'; +import { usePhotographerTemplate } from '../templates/photographer.js'; + +const { getPhotographers } = usePhotographerService(); + +const { getUserCardDOM } = usePhotographerTemplate(); + +const displayData = async (photographers) => { + if (document.querySelector('.photographer_section')) { + const photographersSection = document.querySelector('.photographer_section'); + photographers.forEach((photographer) => { + const userCardDOM = getUserCardDOM(photographer); + photographersSection.appendChild(userCardDOM); + }); + } +}; + +const init = async () => { + const photographers = await getPhotographers(); + await displayData(photographers); +}; +init(); diff --git a/src/pages/lightbox.js b/src/pages/lightbox.js new file mode 100644 index 00000000000..6a22e2676bf --- /dev/null +++ b/src/pages/lightbox.js @@ -0,0 +1,102 @@ +import { useMediaFactorie } from '../factories/mediaFactorie.js'; +import { useListener } from '../utils/listener.js'; +import { isLightBoxOpen } from './photographer.js'; + +const { createLightBoxMediaView, createLightBoxMediaContent } = useMediaFactorie(); +const { removeAllEventListenersOfType, addEventListenerWithTracking } = useListener(); + +let lightBoxMediaCounter = 0; +let lightBox; +let lightBoxContainer = document.querySelector('#light-box'); + +const displayLightBox = (event, photographer) => { + lightBoxMediaCounter = photographer.media.findIndex((item) => item.id === parseInt(event.target.id)); + const lightBox = createLightBoxMediaView(photographer.media[lightBoxMediaCounter]); + lightBoxContainer.appendChild(lightBox); + lightBoxContainer.style.display = 'flex'; + + return lightBox; +}; + +export const onClose = () => { + removeAllEventListenersOfType(document, 'keydown'); + removeAllEventListenersOfType(document, 'closeLightBox'); + removeAllEventListenersOfType(document, 'nextArrowLightbox'); + removeAllEventListenersOfType(document, 'backArrowLightbox'); + lightBoxMediaCounter = 0; + lightBoxContainer.style.display = 'none'; + lightBoxContainer.removeChild(lightBox); +}; + +export const onNextArrow = (photographer) => { + lightBoxMediaCounter = lightBoxMediaCounter + 1; + const oldLightBoxContent = document.querySelector('.light-box__content'); + lightBox.removeChild(oldLightBoxContent); + + const newLightBoxContent = createLightBoxMediaContent(photographer.media[lightBoxMediaCounter]); + const left = document.querySelector('.light-box__left-side'); + left.after(newLightBoxContent); +}; + +export const onBackArrow = (photographer) => { + lightBoxMediaCounter = lightBoxMediaCounter - 1; + const oldLightBoxContent = document.querySelector('.light-box__content'); + lightBox.removeChild(oldLightBoxContent); + + const newLightBoxContent = createLightBoxMediaContent(photographer.media[lightBoxMediaCounter]); + const left = document.querySelector('.light-box__left-side'); + left.after(newLightBoxContent); +}; + +export const init = (e, data) => { + lightBox = displayLightBox(e, data); + + const handleNextArrow = () => { + if (lightBoxMediaCounter + 1 !== data.media.length) { + onNextArrow(data); + } + showArrow(); + }; + addEventListenerWithTracking(document, 'nextArrowLightbox', handleNextArrow); + + const handleBackArrow = () => { + if (lightBoxMediaCounter !== 0) { + onBackArrow(data); + } + showArrow(); + }; + addEventListenerWithTracking(document, 'backArrowLightbox', handleBackArrow); + + const closeLightBoxButton = document.querySelector('.light-box__close-button'); + closeLightBoxButton.addEventListener('click', () => { + onClose(); + isLightBoxOpen.value = false; + }); + + const backArrowButton = document.querySelector('.light-box__back-arrow'); + backArrowButton.addEventListener('click', () => { + onBackArrow(data); + showArrow(); + }); + + const nextArrowButton = document.querySelector('.light-box__next-arrow'); + nextArrowButton.addEventListener('click', () => { + onNextArrow(data); + showArrow(); + }); + + const showArrow = () => { + if (lightBoxMediaCounter === 0) { + backArrowButton.style.display = 'none'; + nextArrowButton.style.display = 'block'; + } else if (lightBoxMediaCounter === data.media.length - 1) { + backArrowButton.style.display = 'block'; + nextArrowButton.style.display = 'none'; + } else { + backArrowButton.style.display = 'block'; + nextArrowButton.style.display = 'block'; + } + }; + + showArrow(); +}; diff --git a/src/pages/photographer.js b/src/pages/photographer.js new file mode 100644 index 00000000000..e94ad5544b4 --- /dev/null +++ b/src/pages/photographer.js @@ -0,0 +1,225 @@ +import { usePhotographerService } from '../api/photographerService.js'; +import { usePhotographerTemplate } from '../templates/photographer.js'; +import { useMediaFactorie } from '../factories/mediaFactorie.js'; +import { orderBy } from '../utils/mediaFilter.js'; +import * as contactForm from '../utils/contactForm.js'; +import * as lightBox from './lightbox.js'; +import { onClose } from './lightbox.js'; +import { useListener } from '../utils/listener.js'; +import { retrieveFilterLabelFromValue } from '../constants/filterConstant.js'; + +const { getPhotographerById, getPhotographers, getPhotographerLikes } = usePhotographerService(); + +const { getHeaderPhotographerDOM, getFooterPhotographerDOM } = usePhotographerTemplate(); + +const { createMediaCard } = useMediaFactorie(); + +const { addEventListenerWithTracking } = useListener(); + +export let isLightBoxOpen = { value: false }; +const idPhotographer = parseInt(new URL(document.location).searchParams.get('id')); +let photographer; +let likes; + +const mediaFiltersBar = document.querySelector('.media-filters'); +const mediaFilter = document.querySelector('#media-filter'); + +const contactButton = document.querySelector('.contact_button'); +const closeContactButton = document.querySelector('.contact_modal__close-button'); + +const form = document.getElementById('contact_form'); +form.addEventListener('submit', (e) => { + e.preventDefault(); + const post = { + firsname: e.target[0].value, + lastname: e.target[1].value, + email: e.target[2].value, + message: e.target[3].value, + }; + console.log(post); +}); + +const createMediaCardList = (data) => { + const mediaCardList = document.createElement('div'); + mediaCardList.setAttribute('class', 'media-card__list'); + data.media.forEach((media) => { + const mediaCard = createMediaCard(media); + mediaCardList.appendChild(mediaCard); + }); + mediaFiltersBar.after(mediaCardList); + return mediaCardList; +}; + +const updateFooterLikesCounter = () => { + const footer = document.querySelector('#like-counter'); + likes = getPhotographerLikes(photographer); + footer.textContent = likes; +}; + +const likeMedia = (event) => { + const curr = event.currentTarget; + const media = photographer.media.find((media) => media.id === parseInt(curr.id)); + if (media.liked) { + media.likes = media.likes - 1; + media.liked = false; + event.currentTarget.children[0].textContent = media.likes; + updateFooterLikesCounter(); + } else { + media.likes = media.likes + 1; + media.liked = true; + event.currentTarget.children[0].textContent = media.likes; + updateFooterLikesCounter(); + } +}; + +const addListenerOnContact = () => { + contactButton.addEventListener('click', contactForm.useContactModal(photographer.name).displayModal); + closeContactButton.addEventListener('click', contactForm.useContactModal().closeModal); +}; + +const addListenerOnMediaFilter = () => { + const evTypes = ['click', 'keydown']; + const mediaFilterOptions = mediaFilter.querySelectorAll('.select-menu__option'); + + evTypes.forEach((evType) => { + mediaFilterOptions.forEach((mediaFilterOption) => { + mediaFilterOption.addEventListener(evType, (e) => { + if (evType === 'click' || (evType === 'keydown' && (e.code === 'Enter' || e.code === 'Space'))) + if ( + mediaFilterOptions[0].querySelector('.select-menu__text').dataset.value !== + mediaFilterOption.querySelector('.select-menu__text').dataset.value + ) { + let chevron = mediaFilterOptions[0].querySelector('.fa-chevron-down'); + let temp = mediaFilterOptions[0].querySelector('.select-menu__text').dataset.value; + + mediaFilterOptions[0].querySelector('.select-menu__text').textContent = + mediaFilterOption.querySelector('.select-menu__text').textContent; + + mediaFilterOptions[0].querySelector('.select-menu__text').dataset.value = + mediaFilterOption.querySelector('.select-menu__text').dataset.value; + + mediaFilterOption.querySelector('.select-menu__text').textContent = + retrieveFilterLabelFromValue(temp); + mediaFilterOption.querySelector('.select-menu__text').dataset.value = temp; + mediaFilterOptions[0].appendChild(chevron); + + temp = mediaFilterOptions[0].querySelector('.select-menu__text').dataset.value; + + photographer.media = orderBy(temp, photographer.media); + const oldMediaCardList = document.querySelector('.media-card__list'); + oldMediaCardList.remove(); + createMediaCardList(photographer); + addListenerOnThumbnails(); + addListenerOnLikes(); + addListenerOnContact(); + } + }); + }); + }); +}; + +const addListenerOnThumbnails = () => { + const medias = document.querySelectorAll('.thumbnail'); + medias.forEach((media) => { + media.addEventListener('click', (e) => { + lightBox.init(e, photographer); + document.dispatchEvent(new CustomEvent('openLightBox')); + }); + media.addEventListener('keydown', (ev) => { + if (ev.code === 'Space' || ev.code === 'Enter') { + lightBox.init(ev, photographer); + document.dispatchEvent(new CustomEvent('openLightBox')); + } + }); + }); +}; + +const addListenerOnLikes = () => { + const likesButtons = document.querySelectorAll('.media-card__like'); + likesButtons.forEach((likeButton) => { + likeButton.addEventListener('click', (e) => likeMedia(e)); + likeButton.addEventListener('keydown', (ev) => { + if (ev.code === 'Space' || ev.code === 'Enter') { + likeMedia(ev); + } + }); + }); +}; + +const displayData = async (data, likes) => { + const { infos, photographerPortrait } = getHeaderPhotographerDOM(data); + const footer = getFooterPhotographerDOM(data, likes); + + const contactButton = document.querySelector('.contact_button'); + contactButton.before(infos); + contactButton.after(photographerPortrait); + + const mediaCardList = createMediaCardList(data); + mediaCardList.after(footer); +}; + +const keyboardEventHandler = (ev) => { + if (isLightBoxOpen.value) { + switch (ev.code) { + case 'Escape': + case 'Esc': + document.dispatchEvent(new CustomEvent('closeLightBox')); + break; + case 'ArrowRight': + document.dispatchEvent(new CustomEvent('nextArrowLightbox')); + break; + case 'ArrowLeft': + document.dispatchEvent(new CustomEvent('backArrowLightbox')); + break; + } + } +}; + +const handleCloseLightBox = () => { + onClose(); + isLightBoxOpen.value = false; +}; + +const handleLightBoxOpen = () => { + isLightBoxOpen.value = true; + addEventListenerWithTracking(document, 'keydown', keyboardEventHandler); + addEventListenerWithTracking(document, 'closeLightBox', handleCloseLightBox); +}; + +const init = async () => { + const photographers = await getPhotographers(); + photographer = await getPhotographerById(idPhotographer, photographers); + photographer.media = orderBy('popularity', photographer.media); + likes = getPhotographerLikes(photographer); + + await displayData(photographer, likes); + addListenerOnMediaFilter(); + addListenerOnThumbnails(); + addListenerOnLikes(); + addListenerOnContact(); +}; + +init().then(() => { + photographer.media.forEach((obj) => { + Object.defineProperty(obj, 'liked', { + value: false, + writable: true, + }); + }); + + document.addEventListener('contactModalOpened', () => { + const closeButton = document.querySelector('.contact_modal__close-button'); + closeButton.addEventListener('keydown', (ev) => { + if (ev.code === 'Enter' || ev.code === 'Space') { + contactForm.useContactModal().closeModal(); + } + }); + }); + + document.addEventListener('contactModalClosed', () => { + const logoLink = document.querySelector('#logo__link'); + logoLink.focus(); + }); + + addEventListenerWithTracking(document, 'openLightBox', handleLightBoxOpen); +}); diff --git a/src/templates/lightbox.js b/src/templates/lightbox.js new file mode 100644 index 00000000000..1a3059811d1 --- /dev/null +++ b/src/templates/lightbox.js @@ -0,0 +1,57 @@ +export const useLightboxTemplate = () => { + const getLightBoxPictureDOM = (media) => { + const picturePath = `assets/medias/${media.image}`; + const lightBox = document.createElement('div'); + lightBox.setAttribute('class', 'light-box__modal'); + lightBox.setAttribute('id', 'light-box__modal'); + + lightBox.innerHTML = ` +
back-arrow
+
${media.title} picture

${media.title}

+
close modal buttonnext-arrow
+ `; + return lightBox; + }; + + const getLightBoxVideoDOM = (media) => { + const lightBox = document.createElement('div'); + lightBox.setAttribute('class', 'light-box__modal'); + const videoPath = `assets/medias/${media.video}`; + + lightBox.innerHTML = ` +
back-arrow
+

${media.title}

+
close modal buttonnext-arrow
+ `; + return lightBox; + }; + + const getLightBoxVideoContent = (media) => { + const videoPath = `assets/medias/${media.video}`; + const content = document.createElement('div'); + content.setAttribute('class', 'light-box__content'); + + content.innerHTML = ` +

${media.title}

+ `; + return content; + }; + + const getLightBoxImageContent = (media) => { + const picturePath = `assets/medias/${media.image}`; + const content = document.createElement('div'); + content.setAttribute('class', 'light-box__content'); + + content.innerHTML = ` + ${media.title} picture

${media.title}

+ `; + return content; + }; + + return { + getLightBoxPictureDOM, + getLightBoxVideoDOM, + getLightBoxImageContent, + getLightBoxVideoContent, + }; +}; diff --git a/src/templates/photographer.js b/src/templates/photographer.js new file mode 100644 index 00000000000..a09ad2e955a --- /dev/null +++ b/src/templates/photographer.js @@ -0,0 +1,114 @@ +export const usePhotographerTemplate = () => { + const getUserCardDOM = (data) => { + const { name, id, city, country, tagline, price, portrait } = data; + const picture = `assets/photographers/${portrait}`; + + const article = document.createElement('article'); + + const img = document.createElement('img'); + img.setAttribute('src', picture); + img.setAttribute('loading', 'lazy'); + img.setAttribute('alt', 'Portrait de ' + name); + + const imgContainer = document.createElement('div'); + imgContainer.append(img); + + const h2 = document.createElement('h2'); + h2.textContent = name; + + const a = document.createElement('a'); + a.setAttribute('href', `/photographer.html?id=${id}`); + a.setAttribute('aria-label', `Lien vers la page de ${name}`); + a.appendChild(imgContainer); + a.appendChild(h2); + + const h3 = document.createElement('p'); + h3.textContent = city + ', ' + country; + + const p = document.createElement('p'); + p.textContent = tagline; + + const i = document.createElement('i'); + i.textContent = price + '€/jour'; + + article.appendChild(a); + article.appendChild(h3); + article.appendChild(p); + article.appendChild(i); + return article; + }; + + const getHeaderPhotographerDOM = (data) => { + const { name, tagline, city, country, portrait } = data; + const picturePath = `assets/photographers/${portrait}`; + + const infos = document.createElement('div'); + infos.setAttribute('class', 'photograph-header__info'); + + infos.innerHTML = ` +

${name}

+

${city}, ${country}

+

${tagline}

`; + + const photographerPortrait = document.createElement('div'); + photographerPortrait.setAttribute('class', 'photograph-header__picture-wrapper'); + + photographerPortrait.innerHTML = `${name} profil picture`; + return { infos, photographerPortrait }; + }; + + const getPictureCardDOM = (media) => { + const picturePath = `assets/medias/${media.image}`; + const card = document.createElement('div'); + card.setAttribute('class', 'media-card'); + + card.innerHTML = ` + ${media.title} +
+

${media.title}

+ + ${media.likes} + ${media.likes} likes + +
+ `; + + return card; + }; + + const getVideoCardDOM = (media) => { + const videoPath = `assets/medias/${media.video}`; + const card = document.createElement('div'); + card.setAttribute('class', 'media-card'); + + card.innerHTML = ` + +
+

${media.title}

+ + ${media.likes} + ${media.likes} likes + +
+ `; + + return card; + }; + + const getFooterPhotographerDOM = (photographer, likes) => { + const { price } = photographer; + const footer = document.createElement('footer'); + footer.innerHTML = ` + + ${likes} + like icon + + + ${price}€ / jour + + `; + return footer; + }; + + return { getUserCardDOM, getHeaderPhotographerDOM, getPictureCardDOM, getVideoCardDOM, getFooterPhotographerDOM }; +}; diff --git a/src/utils/contactForm.js b/src/utils/contactForm.js new file mode 100644 index 00000000000..cc83ee029b5 --- /dev/null +++ b/src/utils/contactForm.js @@ -0,0 +1,17 @@ +export const useContactModal = (photographerName) => { + const displayModal = async () => { + document.dispatchEvent(new CustomEvent('contactModalOpened')); + const modal = document.getElementById('contact_modal'); + const headerName = document.querySelector('.contact_modal__header-name'); + const closeButton = document.querySelector('.contact_modal__close-button'); + modal.style.display = 'flex'; + headerName.textContent = `Contactez-moi ${photographerName}`; + closeButton.focus(); + }; + const closeModal = () => { + const modal = document.getElementById('contact_modal'); + modal.style.display = 'none'; + document.dispatchEvent(new CustomEvent('contactModalClosed')); + }; + return { displayModal, closeModal }; +}; diff --git a/src/utils/listener.js b/src/utils/listener.js new file mode 100644 index 00000000000..5547bea2a5a --- /dev/null +++ b/src/utils/listener.js @@ -0,0 +1,31 @@ +const eventListeners = { value: new WeakMap() }; + +export const useListener = () => { + const addEventListenerWithTracking = (element, type, callback, options) => { + element.addEventListener(type, callback, options); + + if (!eventListeners.value.has(element)) { + eventListeners.value.set(element, []); + } + eventListeners.value.get(element).push({ type, callback, options }); + }; + + const removeAllEventListenersOfType = (element, type) => { + const listeners = eventListeners.value.get(element) || []; + + listeners + .filter((listener) => listener.type === type) + .forEach((listener) => element.removeEventListener(type, listener.callback, listener.options)); + + eventListeners.value.set( + element, + listeners.filter((listener) => listener.type !== type) + ); + }; + + return { + eventListeners, + removeAllEventListenersOfType, + addEventListenerWithTracking, + }; +}; diff --git a/src/utils/mediaFilter.js b/src/utils/mediaFilter.js new file mode 100644 index 00000000000..e26dc44cd34 --- /dev/null +++ b/src/utils/mediaFilter.js @@ -0,0 +1,11 @@ +export const orderBy = (selectValue, medias) => { + switch (selectValue) { + case 'popularity': + return medias.sort((a, b) => a.likes - b.likes); + case 'date': + return medias.sort((a, b) => new Date(a.date) - new Date(b.date)); + case 'title': + return medias.sort((a, b) => a.title.localeCompare(b.title)); + default: + } +};