diff --git a/starterOnly/modal.css b/starterOnly/modal.css index d65b394cfa..c9df6fc989 100644 --- a/starterOnly/modal.css +++ b/starterOnly/modal.css @@ -3,11 +3,13 @@ --font-slab: var(--font-default); --modal-duration: 0.8s; } + * { box-sizing: border-box; margin: 0; padding: 0; } + /* Landing Page */ body { @@ -33,12 +35,15 @@ img { overflow: hidden; margin: 3.5%; } + .header-logo { - float: left; + float: left; } + .main-navbar { - float: right; + float: right; } + .topnav a { float: left; display: block; @@ -55,6 +60,9 @@ img { background-color: #ff0000; color: #ffffff; border-radius: 15px; + text-decoration: underline; + text-underline-offset: 0.3em; + text-decoration-thickness: 0.05em; } .topnav a.active { @@ -65,10 +73,19 @@ img { .topnav .icon { display: none; + color: red; } @media screen and (max-width: 768px) { - .topnav a {display: none;} + .topnav { + margin-left: 40px; + margin-top: 40px; + } + + .topnav a { + display: none; + } + .topnav a.icon { float: right; display: block; @@ -76,29 +93,50 @@ img { } @media screen and (max-width: 768px) { - .topnav.responsive {position: relative;} + .topnav.responsive { + position: relative; + } + .topnav.responsive .icon { position: absolute; right: 0; top: 0; } + .topnav.responsive a { float: none; display: block; text-align: left; } + + .topnav.responsive .main-navbar { + margin-right: 50px; + } + } +@media screen and (max-width: 768px) { + .header-logo img { + width: 80%; + } +} +@media screen and (max-width: 540px) { + .topnav a { + display: none; + } - @media screen and (max-width: 540px) { - .topnav a {display: none;} .topnav a.icon { float: right; display: block; margin-top: -15px; + } -} +} + + + + main { font-size: 130%; @@ -202,11 +240,13 @@ label { display: inline-block; margin-bottom: 11px; } + input { padding: 8px; border: 0.8px solid #ccc; outline: none; } + .text-control { margin: 0; padding: 8px; @@ -215,6 +255,7 @@ input { font-size: 20px; height: 48px; } + .formData[data-error]::after { content: attr(data-error); font-size: 0.4em; @@ -222,17 +263,19 @@ input { display: block; margin-top: 7px; margin-bottom: 7px; - text-align: right; line-height: 0.3; opacity: 0; transition: 0.3s; } + .formData[data-error-visible="true"]::after { opacity: 1; } + .formData[data-error-visible="true"] .text-control { border: 2px solid #e54858; } + /* input[data-error]::after { content: attr(data-error); @@ -246,6 +289,7 @@ input[data-error]::after { font-size: 12px; font-weight: normal; } + .checkbox-label .checkbox-icon, .checkbox2-label .checkbox-icon { display: block; @@ -260,6 +304,7 @@ input[data-error]::after { top: -1px; transition: 0.3s; } + .checkbox-label .checkbox-icon::after, .checkbox2-label .checkbox-icon::after { content: ""; @@ -276,21 +321,26 @@ input[data-error]::after { transition: 0.3s; opacity: 0; } + .checkbox-input { display: none; } -.checkbox-input:checked + .checkbox-label .checkbox-icon::after, -.checkbox-input:checked + .checkbox2-label .checkbox-icon::after { + +.checkbox-input:checked+.checkbox-label .checkbox-icon::after, +.checkbox-input:checked+.checkbox2-label .checkbox-icon::after { opacity: 1; } -.checkbox-input:checked + .checkbox2-label .checkbox-icon { + +.checkbox-input:checked+.checkbox2-label .checkbox-icon { background: #279e7a; } + .checkbox2-label .checkbox-icon { border-radius: 4px; border: 0; background: #c4c4c4; } + .checkbox2-label .checkbox-icon::after { width: 7px; height: 4px; @@ -303,6 +353,7 @@ input[data-error]::after { left: 21%; top: 19%; } + .close { position: absolute; right: 15px; @@ -313,6 +364,7 @@ input[data-error]::after { cursor: pointer; transform: scale(0.7); } + .close:before, .close:after { position: absolute; @@ -322,12 +374,15 @@ input[data-error]::after { width: 3px; background-color: #fff; } + .close:before { transform: rotate(45deg); } + .close:after { transform: rotate(-45deg); } + .btn-submit, .btn-signup { background: #fe142f; @@ -340,6 +395,7 @@ input[data-error]::after { cursor: pointer; border: 0; } + /* custom select styles */ .custom-select { position: relative; @@ -351,6 +407,7 @@ input[data-error]::after { .custom-select select { display: none; } + .select-selected { background-color: #fff; } @@ -406,20 +463,23 @@ input[data-error]::after { .same-as-selected { background-color: rgba(0, 0, 0, 0.1); } + /* custom select end */ .text-label { font-weight: normal; font-size: 16px; } + .hero-section { - min-height: 93vh; + height: 620px; border-radius: 10px; display: grid; grid-template-columns: repeat(12, 1fr); overflow: hidden; - box-shadow: 0 2px 7px 2px rgba(0, 0, 0, 0.2); + box-shadow: 0px 12px 12px 0px rgba(0, 0, 0, 0.2); margin-bottom: 10px; } + .hero-content { padding: 51px 67px; grid-column: span 4; @@ -429,6 +489,7 @@ input[data-error]::after { text-align: left; min-width: 424px; } + .hero-content::after { content: ""; width: 100%; @@ -438,21 +499,25 @@ input[data-error]::after { right: -80px; top: 0; } -.hero-content > * { + +.hero-content>* { position: relative; z-index: 1; } + .hero-headline { font-size: 6rem; font-weight: normal; white-space: nowrap; } + .hero-text { width: 146%; font-weight: normal; margin-top: 57px; padding: 0; } + .btn-signup { outline: none; text-transform: capitalize; @@ -461,76 +526,120 @@ input[data-error]::after { margin: 0; margin-top: 59px; } + .hero-img { grid-column: span 8; } + .hero-img img { width: 100%; height: 100%; display: block; padding: 0; } + .copyrights { color: #fe142f; padding: 0; font-size: 1rem; - margin: 60px 0 30px; + margin: 40px 0 30px; font-weight: bolder; } -.hero-section > .btn-signup { + +.hero-section>.btn-signup { display: none; } + footer { padding-left: 2vw; padding-right: 2vw; margin: 0 20px; } + @media screen and (max-width: 800px) { .hero-section { display: block; box-shadow: unset; + height: auto; } + .hero-content { background: #fff; color: #000; padding: 20px; + padding-left: 0px; } + .hero-content::after { content: unset; } + .hero-content .btn-signup { display: none; } + .hero-headline { font-size: 4.5rem; white-space: normal; } + .hero-text { width: unset; font-size: 1.5rem; } + .hero-img img { border-radius: 10px; margin-top: 40px; } - .hero-section > .btn-signup { + + .hero-section>.btn-signup { display: block; margin: 32px auto 10px; padding: 12px 35px; } + .copyrights { margin-top: 50px; text-align: center; } } +@media screen and (max-width: 540px) { + .hero-headline { + font-size: 2.5rem; + font-weight: bold; + } + + .hero-text { + font-size: 1rem; + margin-top: 30px; + } + + .topnav { + margin-left: 30px; + } + + .copyrights { + margin-top: 0; + } + + .topnav.responsive .icon { + top: 16px; + } + + .topnav a.icon { + margin-top: 0; + } +} + @keyframes modalopen { from { opacity: 0; transform: translateY(-150px); } + to { opacity: 1; } -} - +} \ No newline at end of file diff --git a/starterOnly/modal.js b/starterOnly/modal.js index 4f89f70ee7..1a14506756 100644 --- a/starterOnly/modal.js +++ b/starterOnly/modal.js @@ -1,33 +1,39 @@ -// Fonction pour basculer la navigation responsive +// Fonction pour basculer la classe CSS de la barre de navigation, rendant le menu responsive function editNav() { - var x = document.getElementById("myTopnav"); + let x = document.getElementById("myTopnav"); if (x.className === "topnav") { x.className += " responsive"; } else { x.className = "topnav"; } -} -// Éléments du DOM +}; + +// Sélection des éléments du DOM nécessaires pour manipuler la modale et le formulaire const modalbg = document.querySelector(".bground"); const modalBtn = document.querySelectorAll(".modal-btn"); const formData = document.querySelectorAll(".formData"); const closeBtnCross = document.querySelector(".close"); const form = document.querySelector("form"); -// Ajout des écouteurs d'événements pour afficher la modal + +// Ajoute des écouteurs d'événements sur chaque bouton pour ouvrir la modale modalBtn.forEach((btn) => btn.addEventListener("click", launchModal)); -// Fonction pour afficher la modal + +// Fonction pour afficher la modale function launchModal() { + resetFormAndModal(); // Réinitialise le formulaire et la modale avant de l'afficher modalbg.style.display = "block"; -} -// Ajout d'un écouteur d'événement pour fermer la modal +}; + +// Écouteur d'événement pour fermer la modale closeBtnCross.addEventListener("click", function () { - modalbg.style.display = "none" + modalbg.style.display = "none"; }); -// Soumission du formulaire -form.addEventListener('submit', (event) => { + +// Gère la soumission du formulaire +form.addEventListener('submit', (event) => { event.preventDefault(); // Empêche le rechargement de la page - // Vérification de chaque champ du formulaire en une seule ligne + // Vérifie la validité de chaque champ du formulaire const isValid = validateFirstName() && validateLastName() && validateEmail() && @@ -36,44 +42,67 @@ form.addEventListener('submit', (event) => { validateLocation() && validateConditions(); - newsletterSignup(); // Enregistrement de la préférence pour la newsletter, ne change pas la validité + newsletterSignup(); // Gère l'inscription à la newsletter indépendamment de la validité du formulaire - // Affichage du résultat de la validation du formulaire if (isValid) { console.log("Le formulaire est validé."); - // Masquer le formulaire - form.style.display = 'none'; - // Afficher un message de validation - displayConfirmationMessage("Merci pour votre inscription"); + form.style.display = 'none'; // Masque le formulaire + displayConfirmationMessage("Merci pour votre inscription"); // Affiche le message de confirmation } else { console.log("Le formulaire contient des erreurs. La soumission est bloquée."); } }); -// Ajout d'un écouteur d'événement pour valider le prénom à chaque changement -document.getElementById("first").addEventListener("input", function () { - validateFirstName(); -}); -// Fonction pour afficher un message de confirmation +// Écouteurs d'événements pour la validation en temps réel des champs du formulaire +document.getElementById("first").addEventListener("input", validateFirstName); +document.getElementById("last").addEventListener("input", validateLastName); +document.getElementById("email").addEventListener("input", validateEmail); +document.getElementById("birthdate").addEventListener("input", validateBirthdate); +document.getElementById("quantity").addEventListener("input", validateQuantity); +document.getElementById("checkbox1").addEventListener("change", validateConditions); + +// Réinitialise le formulaire et le contenu de la modale +function resetFormAndModal() { + form.reset(); // Réinitialise les champs du formulaire + form.style.display = 'block'; // Assure que le formulaire est visible + + // Supprime le message de confirmation s'il existe + const successMessage = document.querySelector('.form-confirmation'); + if (successMessage) { + successMessage.remove(); + } + + // Supprime le bouton fermer s'il existe + const closeButton = document.querySelector('.btn-close'); + if (closeButton) { + closeButton.remove(); + } +}; + +// Affiche un message de confirmation dans la modale function displayConfirmationMessage(message) { - // Création du message de confirmation + const existingSuccessMessage = document.querySelector('.form-confirmation'); + if (existingSuccessMessage) { + existingSuccessMessage.remove(); + } + const successMessage = document.createElement('p'); successMessage.textContent = message; successMessage.classList.add('form-confirmation'); - - // Sélectionner l'élément avec la classe "modal-body" const modalBody = document.querySelector('.modal-body'); modalBody.appendChild(successMessage); - // Création et ajout du bouton Fermer const closeButton = document.createElement('button'); closeButton.textContent = "Fermer"; - closeButton.classList.add('button', 'btn-submit'); - closeButton.addEventListener('click', function () { + closeButton.classList.add('button', 'btn-submit', 'btn-close'); + closeButton.onclick = function () { modalbg.style.display = 'none'; - }); + resetFormAndModal(); // Réinitialise la modale pour la prochaine ouverture + }; modalBody.appendChild(closeButton); -} + + form.style.display = 'none'; // Masque le formulaire pour afficher uniquement le message de confirmation +}; // Fonction de validation du prénom function validateFirstName() { @@ -81,52 +110,46 @@ function validateFirstName() { const formDataElement = firstNameInput.closest(".formData"); // Trouve le parent .formData const firstName = firstNameInput.value.trim(); const regex = new RegExp("^[A-Za-zÀ-ÿ]+$"); - if (firstName.length < 2) { + + // Si le prénom est trop court ou ne correspond pas au regex, affiche un message d'erreur. + if (firstName.length < 2 || !regex.test(firstName)) { formDataElement.setAttribute("data-error", "Le prénom doit contenir au moins 2 caractères et ne peut pas être vide."); formDataElement.setAttribute("data-error-visible", "true"); - return false; // La validation échoue, retourne false - } else if (!regex.test(firstName)) { - formDataElement.setAttribute("data-error", "Le prénom ne doit contenir que des lettres."); - formDataElement.setAttribute("data-error-visible", "true"); - return false; // La validation échoue, retourne false + return false; } else { // En cas de succès, efface les attributs pour ne pas afficher d'erreur formDataElement.setAttribute("data-error", ""); formDataElement.removeAttribute("data-error-visible"); return true; // La validation réussit, retourne true } -} -// Ajout d'un écouteur d'événement pour valider le nom à chaque changement -document.getElementById("last").addEventListener("input", validateLastName); +}; + // Fonction de validation du nom function validateLastName() { const lastNameInput = document.getElementById("last"); const formDataElement = lastNameInput.closest(".formData"); const lastName = lastNameInput.value.trim(); const regex = new RegExp("^[A-Za-zÀ-ÿ]+$"); - if (lastName.length < 2) { + + if (lastName.length < 2 || !regex.test(lastName)) { formDataElement.setAttribute("data-error", "Le nom doit contenir au moins 2 caractères et ne peut pas être vide."); formDataElement.setAttribute("data-error-visible", "true"); - return false; // La validation échoue, retourne false - } else if (!regex.test(lastName)) { - formDataElement.setAttribute("data-error", "Le nom ne doit contenir que des lettres."); - formDataElement.setAttribute("data-error-visible", "true"); - return false; // La validation échoue, retourne false + return false; } else { formDataElement.setAttribute("data-error", ""); formDataElement.removeAttribute("data-error-visible"); return true; // La validation réussit, retourne true } -} -// Ajout d'un écouteur d'événement pour valider l'email à chaque changement -document.getElementById("email").addEventListener("input", validateEmail); +}; + // Fonction de validation de l'email function validateEmail() { const emailInput = document.getElementById("email"); const formDataElement = emailInput.closest(".formData"); const email = emailInput.value.trim(); const regex = new RegExp("^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$", "i"); + if (!regex.test(email)) { formDataElement.setAttribute("data-error", "L'email est invalide"); formDataElement.setAttribute("data-error-visible", "true"); @@ -135,11 +158,10 @@ function validateEmail() { formDataElement.setAttribute("data-error", ""); formDataElement.removeAttribute("data-error-visible"); return true; // La validation réussit, retourne true - } -} -// Ajout d'un écouteur d'événement pour valider la date de naissance à chaque changement -document.getElementById("birthdate").addEventListener("input", validateBirthdate); +}; + + // Fonction de validation de la date de naissance function validateBirthdate() { const birthdateInput = document.getElementById("birthdate"); @@ -147,6 +169,7 @@ function validateBirthdate() { const birthdate = birthdateInput.value; const convertBirthdate = new Date(birthdate); const today = new Date(); + if (birthdate === "" || convertBirthdate >= today) { formDataElement.setAttribute("data-error", "La date de naissance doit être antérieure à la date d'aujourd'hui et ne peut pas être vide."); formDataElement.setAttribute("data-error-visible", "true"); @@ -156,9 +179,9 @@ function validateBirthdate() { formDataElement.removeAttribute("data-error-visible"); return true; // La validation réussit, retourne true } -} -// Ajout d'un écouteur d'événement pour valider la quantité à chaque changement -document.getElementById("quantity").addEventListener("input", validateQuantity); +}; + + // Fonction de validation de la quantité function validateQuantity() { const quantityInput = document.getElementById("quantity"); @@ -174,12 +197,14 @@ function validateQuantity() { formDataElement.removeAttribute("data-error-visible"); return true; // La validation réussit, retourne true } -} +}; + // Fonction de validation de la localisation function validateLocation() { const locationTags = document.querySelectorAll('input[name="location"]'); - let locationSelected = false; const formDataElement = document.getElementById("formData-location"); + let locationSelected = false; + for (let i = 0; i < locationTags.length; i++) { if (locationTags[i].checked) { locationSelected = true; @@ -195,9 +220,8 @@ function validateLocation() { formDataElement.removeAttribute("data-error-visible"); return true; // La validation réussit, retourne true } -} -// Ajout d'un écouteur d'événement pour valider les conditions à chaque changement -document.getElementById("checkbox1").addEventListener("change", validateConditions); +}; + // Fonction de validation des conditions function validateConditions() { const conditionsCheckbox = document.getElementById("checkbox1"); @@ -212,7 +236,8 @@ function validateConditions() { formDataElement.removeAttribute("data-error-visible"); return true; // La validation réussit, retourne true } -} +}; + // Fonction pour enregistrer la préférence pour la newsletter function newsletterSignup() { let newsletterCheckbox = document.getElementById("checkbox2");