Files
2025-10-09 11:06:59 +02:00

883 lines
32 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
<link rel="stylesheet" href="style.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="oscar_school_form_container">
<div id="oscar_school_form_body">
<form id="oscar_school_form" method="POST" action="https://v3.oscar-campus.com/groupe_ensup/forms" ref="schoolForm">
<input type="hidden" name="type_formulaire" value="Brochure">
<div class="form-sections-wrapper">
<div id="section1" class="form-section form-section-step active ">
<h2><i class="fas fa-book"></i> Demande de brochure</h2>
<p class="form-description">Remplissez ce formulaire pour accéder à notre brochure.</p>
<div class="form-group ">
<div class="form-group-item">
<label for="je_suis_ref_id">Je suis<span class="oscar_input_required">(*)</span>:</label>
</label>
<select
id="OscarContactJeSuisRefIdField"
class="form-control"
name="je_suis_ref_id"
v-on:change="determineRelatedFieldsOptions"
v-on:focus="displayAvailableOptions"
>
<option value="">Choisir</option>
<option value="434">Lycéen(ne)</option>
<option value="435">Étudiant(e)</option>
<option value="436">En poste / reconversion</option>
<option value="437">Étudiant avec un diplôme étranger</option>
<option value="439">Parent de l&#039;étudiant(e)</option>
</select>
</div>
</div>
<div class="form-group">
<div class="form-group-item">
<label for="nom">Nom<span class="oscar_input_required">(*)</span></label>
<input type="text" id="nom" name="nom" class="form-control" required pattern="^[A-Za-zÀ-ÿ' \-]{2,50}$" maxlength="50"
title="Le nom doit contenir uniquement des lettres (pas de chiffres ou symboles)">
</div>
<div class="form-group-item">
<label for="prenom">Prénom<span class="oscar_input_required">(*)</span></label>
<input type="text" id="prenom" name="prenom" class="form-control" required pattern="^[A-Za-zÀ-ÿ' \-]{2,50}$" maxlength="50"
title="Le prénom doit contenir uniquement des lettres (pas de chiffres ou symboles)">
</div>
</div>
<div class="form-group">
<div class="form-group-item">
<label for="email">Email<span class="oscar_input_required">(*)</span></label>
<input type="email" id="email" name="email" class="form-control" required title="Veuillez saisir une adresse email valide.">
</div>
<div class="form-group-item">
<label for="portable">Portable<span class="oscar_input_required">(*)</span></label>
<input type="tel" id="portable" name="portable" class="form-control" required>
</div>
</div>
<div class="form-group" id= "campus_selection_app_Brochure">
<div class="form-group-item">
<label for="campus_selection_Brochure">Campus souhaité<span class="oscar_input_required">(*)</span></label>
<select id="campus_selection" name="campus" class="form-control" v-model="selectedCampus" required>
<option value="">Choisir un campus</option>
<option value="sqy">Saint-Quentin-en-Yvelines</option>
<option value="cgy">Cergy</option>
<option value="nantes">Nantes</option>
<option value="marseille">Marseille</option>
</select>
</div>
<div class="form-group-item">
<label for="formation">Formation souhaitée<span class="oscar_input_required">(*)</span></label>
<select id="formation" name="formation_souhaitee_formation_id" class="form-control" required>
<option value="">Choisir une formation</option>
<option value="367">BTS SIO SLAM</option>
<option value="369">BTS SIO SISR</option>
<option value="371">BTS CIEL</option>
<option value="373">Bachelor TECH &amp; DEV spé Gestion de projet IA &amp; Data</option>
<option value="374">Bachelor TECH &amp; DEV spé Développeur Full Stack</option>
<option value="376">Bachelor Systèmes &amp; Réseaux spé Infra &amp; Sécurité</option>
<option value="377">Bachelor Systèmes &amp; Réseaux spé cybersécurité</option>
<option value="378">M1/M2 Expert Solutions Data</option>
<option value="379">M1/M2 Expert Solutions IA &amp; IOT</option>
<option value="380">M1/M2 Lead Developer Full Stack</option>
<option value="382">M1/M2 Expert Architectures IA &amp; IOT</option>
<option value="383">M1/M2 Expert Réseaux &amp; Sécurité</option>
<option value="384">M1/M2 Expert Cybersécurité &amp; Cloud Computing</option>
</select>
</div>
</div>
<div class="form-group cnil-consent-group">
<div class="cnil-checkbox-wrapper">
<input type="checkbox" id="cnil_oui" name="cnil" class="custom-control-input" value="1" required>
<label for="cnil_oui" class="cnil-info-label custom-control-label">
<strong>Oui, je donne mon approbation pour le traitement de mes données personnelles à ENSITECH.</strong><br>
<span style="color: grey; font-size: small;">En soumettant ce formulaire, jaccepte que mes informations soient utilisées dans le cadre de ma demande et de la relation commerciale éthique et personnalisée qui pourrait en découler si je le souhaite. <span class="oscar_input_required">(*)</span></span>
</label>
</div>
</div>
<button type="submit" class="btn-primary desktop-submit-button">DEMANDER LA BROCHURE </button>
</div>
</div>
<div id="final-mobile-navigation">
<button type="submit" class="btn-primary mobile-submit-button">DEMANDER LA BROCHURE</button>
</div>
<div class="mandatory-fields-note-global">(*) Champs obligatoires</div>
<input type="hidden" id="hidden_token_field" name="token">
<input type="hidden" id="hidden_formID_field" name="formID">
<input type="hidden" name="utm_campaign" value="">
<input type="hidden" name="utm_source" value="">
<input type="hidden" name="utm_medium" value="">
<input type="hidden" name="utm_term" value="">
<input type="hidden" name="utm_content" value="">
<div class="username_field" style="display: none;">
<label for="username">Type your username</label>
<input type="text" id="username" name="username" value="">
</div>
</form>
</div>
</div>
</body>
</html>
<style>
.form-description {
text-align: center;
margin-bottom: 25px; /* Space between description and form */
padding: 0 15px; /* Add some horizontal padding to prevent text from touching edges on small screens */
}
input:valid {
border: 1px solid green;
}
body {
margin: 0;
padding: 0;
background-color: #f0f2f5;
font-family: 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
line-height: 1.6;
color: #333;
}
/* --- Main Form Container --- */
#oscar_school_form_container {
max-width: 1200px;
margin: 20px auto;
padding: 0 15px;
}
/* --- Form Body Styles (The white/light gray box) --- */
#oscar_school_form_body {
position: relative;
background: linear-gradient(to bottom right, #f8f9fa, #e9ecef);
padding: 25px;
border-radius: 12px;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
}
/* Optional: Form Header Styles if you uncomment them in HTML */
#oscar_school_form_header h1 {
color: #198AB4;
text-align: center;
margin-bottom: 20px;
font-size: 2.5em;
text-shadow: 1px 1px 2px rgba(0,0,0,0.05);
}
#oscar_school_form_header p {
text-align: center;
color: #555;
font-size: 1.15em;
margin-bottom: 35px;
}
/* --- Form Sections Wrapper (Desktop Flex / Mobile Stack) --- */
.form-sections-wrapper {
margin-bottom: 25px; /* Provides space if no final nav/note below */
}
/* --- Individual Form Section Styles (e.g., Identité, Projet de formation) --- */
.form-section {
padding: 20px;
border: 1px solid #e0e0e0;
border-radius: 10px;
background-color: #ffffff;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08);
transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
height: auto;
margin-bottom: 20px; /* Space between stacked sections on mobile */
display: flex; /* Makes the section a flex container for its internal content */
flex-direction: column; /* Stacks its direct children vertically */
}
.form-section:hover {
transform: translateY(-5px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
}
.form-section h2 {
margin-top: 0;
color: #198AB4;
font-size: 1.7em;
border-bottom: 2px solid #198AB4;
padding-bottom: 12px;
margin-bottom: 22px;
text-align: center;
}
.form-section h2 i {
margin-right: 8px;
color: #198AB4;
}
/* --- Form Group & Control Styles --- */
.form-group {
margin-bottom: 8px;
display: flex; /* Makes immediate children flex items */
flex-wrap: wrap; /* Allows items to wrap to the next line */
gap: 20px; /* Space between flex items */
}
/* Default for individual items in a flex form-group */
.form-group-item {
flex: 1 1 calc(50% - 10px); /* Tries to take 50% width minus half the gap */
max-width: calc(50% - 10px);
}
/* For form-groups that should always be full width (e.g., "Je suis" select, or single input lines) */
/* This rule is more for desktop, on mobile we manage this differently */
.form-group > .form-group-item:only-child,
.form-group:not(.cnil-consent-group) > label + .form-control {
flex: 1 1 100%;
max-width: 100%;
}
.form-group label {
display: block;
margin-bottom: 6px;
color: #444;
font-size: 0.98em;
font-weight: 500;
}
/* Specific style for CNIL info label */
.cnil-info-label {
color: #6c757d;
font-size: 0.85em;
margin-top: 8px;
font-weight: normal;
}
/* New wrapper for CNIL checkbox and label */
.cnil-checkbox-wrapper {
display: flex;
align-items: flex-start; /* Align checkbox and text at the top */
gap: 8px; /* Space between checkbox and text */
width: 100%; /* Ensure it takes full width within its parent */
}
.form-control {
width: 100%;
padding: 8px 12px;
border: 1px solid #ced4da;
border-radius: 6px;
font-size: 1em;
color: #495057;
transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
box-sizing: border-box;
min-height: 38px;
}
.form-control:focus {
border-color: #80bdff;
outline: 0;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
/* Styles for invalid inputs - ONLY apply when the 'is-invalid' class is present */
.form-control.is-invalid {
border-color: #dc3545;
padding-right: calc(1.5em + 0.75rem);
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right calc(0.375em + 0.1875rem) center;
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
}
.form-control.is-invalid:focus {
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
}
textarea.form-control {
resize: vertical;
min-height: 90px;
}
/* Required fields indicator */
.oscar_input_required {
color: #DD1B51;
font-weight: bold;
}
/* CNIL checkbox */
.custom-control-input {
width: 20px; /* Larger hit area */
height: 20px; /* Larger hit area */
border: 1px solid #ced4da;
border-radius: 4px; /* Slightly rounded corners for checkbox */
appearance: none; /* Hide default checkbox */
-webkit-appearance: none;
-moz-appearance: none;
cursor: pointer;
flex-shrink: 0; /* Prevent checkbox from shrinking */
margin-top: 2px; /* Adjust vertical alignment with text */
}
.custom-control-input:checked {
background-color: #198AB4;
border-color: #198AB4;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M4 8.5L6.5 11 12 5'/%3e%3csvg%3e");
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
.custom-control-input:focus {
outline: none;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
.custom-control-label {
cursor: pointer;
color: #333;
flex-grow: 1; /* Allow label to take remaining space */
}
/* Style for the CNIL group itself */
.cnil-consent-group {
padding: 10px 0;
margin-bottom: 20px; /* Space below the group */
}
/* --- Primary Button (General Style for submit/next) --- */
.btn-primary {
display: block;
width: 100%;
padding: 15px 25px;
margin-top: 30px; /* Default margin, overridden by specific rules */
font-size: 1.25em;
font-weight: bold;
color: #fff;
background-color: #198AB4;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.3s ease, transform 0.2s ease, box-shadow 0.2s ease;
box-shadow: 0 5px 15px rgba(0, 123, 255, 0.25);
}
.btn-primary:hover {
background-color: #0056b3;
transform: translateY(-3px);
box-shadow: 0 7px 20px rgba(0, 123, 255, 0.35);
}
.btn-primary:disabled {
background-color: #b0d8ff;
cursor: not-allowed;
opacity: 0.7;
transform: none;
box-shadow: none;
}
/* --- Step-by-Step Form Sections (Mobile default display controlled by JS/active class) --- */
.form-section-step {
width: 100%;
/* !!! IMPORTANT: This 'display: none;' is why your form sections are hidden on mobile
by default. JavaScript MUST add the 'active' class to make them visible. */
display: none;
}
/* --- Navigation Buttons (Prev/Next for Mobile Steps) --- */
/* IMPORTANT: All .form-navigation elements are hidden by default on mobile.
JavaScript will explicitly set 'display: flex' for the active navigation. */
.form-navigation {
display: none; /* Crucial: This ensures all mobile navs are initially hidden */
justify-content: center;
gap: 15px;
margin-top: 25px; /* Space from content above */
}
.form-navigation .btn-next,
.form-navigation .btn-prev {
flex: 1;
max-width: 160px; /* Limit button width */
padding: 14px 0;
font-size: 1.15em;
font-weight: bold;
cursor: pointer;
border-radius: 8px;
border: none;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
transition: background-color 0.3s ease, transform 0.2s ease;
}
/* Specific colors for navigation buttons */
.form-navigation .btn-prev {
background-color: #DD1B3D; /* Red color for previous */
color: #fff;
}
.form-navigation .btn-prev:hover {
background-color: #c71534;
transform: translateY(-2px);
}
.form-navigation .btn-next {
background-color: #198AB4; /* Blue color for next */
color: #fff;
}
.form-navigation .btn-next:hover {
background-color: #147395;
transform: translateY(-2px);
}
/* Mandatory fields note (global placement) */
.mandatory-fields-note-global {
font-size: 0.85em;
color: #555;
text-align: right; /* Default for desktop */
margin-top: 15px;
padding-right: 15px;
}
/* --- Media Query for DESKTOP SCREENS (min-width: 769px) --- */
@media (min-width: 769px) {
#oscar_school_form_container {
padding: 0 20px;
}
/* Form sections layout in two columns */
.form-sections-wrapper {
display: flex;
flex-wrap: nowrap; /* Prevent wrapping to new lines */
justify-content: center;
gap: 30px; /* Space between columns */
align-items: stretch; /* Make sections equal height */
margin-bottom: 0; /* No extra margin, note is positioned absolutely */
}
.form-section-step {
flex: 1; /* Each section takes equal space */
min-width: 0; /* Allow shrinking */
max-width: 50%; /* Max 50% width */
display: flex !important; /* Force display of all steps on desktop (as flex column) */
margin-bottom: 0; /* Remove mobile margin between sections */
}
.form-section {
height: 100%; /* Make sections equal height */
display: flex; /* Maintain flex column behavior for internal content */
flex-direction: column;
justify-content: space-between; /* Pushes content and the desktop submit button to ends */
padding-bottom: 20px; /* Add extra padding at the bottom of sections */
}
/* Hide all mobile-specific navigation elements on desktop */
.form-navigation, /* Targets all elements with this class */
.section-navigation-mobile,
#final-mobile-navigation,
.mobile-submit-button {
display: none !important; /* Force hide on desktop */
}
/* Show and style the desktop submit button inside the second column */
.desktop-submit-button {
display: block !important; /* Show the desktop button */
width: 100%; /* Make it full width of its column */
margin-top: auto; /* Pushes the button to the bottom of the flex column */
align-self: center; /* Centers the button */
padding: 15px 25px;
font-size: 1.25em;
box-shadow: 0 5px 15px rgba(0, 123, 255, 0.25);
}
/* Input fields layout in two columns within form-group */
.form-group {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.form-group-item {
flex: 1 1 calc(50% - 10px);
max-width: calc(50% - 10px);
}
/* "Je suis" select should take full width in its column on desktop */
#section1 .form-group:first-of-type .form-group-item {
flex: 1 1 100%;
max-width: 100%;
}
/* Mandatory fields note positioning on desktop */
.mandatory-fields-note-global {
position: absolute; /* Position relative to #oscar_school_form_body */
bottom: 20px;
left: 25px;
right: auto;
font-size: 0.9em;
color: #777;
text-align: left;
padding-right: 0;
}
}
/* --- Media Query for ALL MOBILE and TABLET DEVICES (max-width: 768px) --- */
/* This covers most phones and tablets. */
@media (max-width: 768px) {
#oscar_school_form_container {
width: 100%;
padding: 0 15px; /* Keeps a small padding on the sides of the page */
margin-top: 15px;
}
#oscar_school_form_body {
padding: 20px;
}
.form-sections-wrapper {
flex-direction: column; /* Stack sections vertically */
gap: 15px;
margin-bottom: 0; /* Controlled by JS and final-mobile-navigation */
}
.form-section {
min-width: unset;
padding: 18px;
margin-bottom: 20px; /* Space between sections if stacked by JS */
height: auto;
/* Align flex items to the start (left) of the section */
align-items: flex-start;
}
/* --- Mobile-specific section and navigation display rules --- */
/* This rule is critical: it makes a section visible ONLY IF it has the 'active' class. */
.form-section-step.active {
display: flex; /* Only show the active section on mobile */
flex-direction: column; /* Keep its internal content stacked */
}
/* All form-navigation elements are hidden by default, and ONLY shown by JS */
/* No CSS rule here to force display for specific mobile navs. JS handles it. */
/* General rule for form groups on mobile */
.form-group {
margin-bottom: 12px;
flex-direction: column; /* Each form-group-item (label+input pair) will stack vertically */
gap: 0;
width: 100%; /* Ensures form-group itself takes full width for its content */
max-width: 400px; /* Set a max-width for the form group to prevent it from being too wide */
/* IMPORTANT: Align the group to the left if the section is align-items: flex-start */
margin-left: 0; /* Ensures no auto margin on the left */
margin-right: auto; /* Allows right margin to push the group to the left if its width < max-width */
}
.form-group-item {
flex: 1 1 100%;
max-width: 100%; /* Make items fill the width of the form-group */
margin-bottom: 10px; /* Space between each label-input pair */
/* Each form-group-item contains label and input side by side */
display: flex;
flex-direction: row; /* Align label and input side by side */
align-items: center; /* Align vertically in the middle */
gap: 10px; /* Space between label and input */
}
.form-group-item:last-child {
margin-bottom: 0;
}
/* Adjustments for labels and controls within form-group-item */
.form-group-item label {
display: inline-block;
flex-shrink: 0;
width: 90px; /* Fixed width for labels to align them */
text-align: left; /* Align label text to the right */
margin-bottom: 0;
}
.form-group-item .form-control {
flex-grow: 1; /* Allow input to take remaining space */
width: auto;
max-width: calc(100% - 100px); /* Adjust max-width: Total 100% - label width - gap */
/* (100px = 90px (label width) + 10px (gap)) */
}
/* --- Specific to SECTION 1 (Example: "Identité") --- */
#section1 .form-group {
flex-direction: column; /* Ensures each field group (Nom, Prénom, etc.) is on its own line */
flex-wrap: nowrap;
gap: 0;
/* .form-group rules apply (max-width, left alignment) */
}
#section1 .form-group-item {
flex: 1 1 100%;
max-width: 100%;
margin-bottom: 10px; /* Space between each field (Nom, Prénom, etc.) */
}
/* Adjustment for the "Je suis" selector in section 1 */
#section1 .form-group:first-of-type .form-group-item {
flex: 1 1 100%;
max-width: 100%;
justify-content: flex-start;
}
#section1 .form-group:first-of-type .form-group-item label {
width: 90px; /* Keep fixed width for consistency with other labels */
text-align: left; /* Align to the right for consistency */
}
#section1 .form-group:first-of-type .form-group-item .form-control {
max-width: calc(100% - 100px); /* Apply max-width here too */
}
/* Specific for the CNIL group */
.cnil-consent-group {
max-width: 400px; /* Match other form-groups for alignment */
margin-left: auto;
margin-right: auto;
flex-direction: column; /* Ensure it stacks if needed */
align-items: flex-start;
}
/* Hide desktop submit button and show mobile submit button */
.desktop-submit-button {
display: none !important;
}
#final-mobile-navigation {
display: block !important; /* Show the container for the mobile submit button */
margin-top: 20px;
padding: 0 15px; /* Adjust padding as needed */
text-align: center; /* Center the button within its container */
}
.mobile-submit-button {
display: block !important; /* Show the mobile submit button */
margin: 0 auto; /* Center the button horizontally */
max-width: 400px; /* Align with max-width of form-groups */
width: 100%;
}
/* Mandatory fields note positioning on mobile */
.mandatory-fields-note-global {
position: static; /* Remove absolute positioning */
text-align: center; /* Center the note */
margin-top: 20px;
padding-right: 0;
}
}
/* --- Media Query for SMALL PHONES (max-width: 414px) --- */
/* This targets smaller phones (e.g., iPhone 6/7/8/SE new) and even smaller devices.
Adjust '414px' to '375px' or '320px' if you need more granular control for specific very small screens. */
@media (max-width: 414px) {
.form-group-item label {
width: 70px; /* Reduce label width to give more space to input */
}
.form-group-item .form-control {
max-width: calc(100% - 80px); /* Adjust max-width based on new label width (70px) + gap (10px) */
}
/* Re-adjust specific labels if needed for very small screens */
#section1 .form-group:first-of-type .form-group-item label {
width: 70px;
}
#section1 .form-group:first-of-type .form-group-item .form-control {
max-width: calc(100% - 80px);
}
}
</style>
<script>
(function() {
'use strict';
// Protection contre le double chargement
if (window.brochureFormLoaded) return;
window.brochureFormLoaded = true;
document.addEventListener("DOMContentLoaded", function () {
const form = document.getElementById('oscar_school_form');
if (!form) return;
const campusSelect = document.getElementById('campus_selection');
const formationSelect = document.getElementById('formation');
const cnilCheckbox = document.getElementById('cnil_oui');
let isSubmitting = false;
// Données
const campusTokens = {
sqy: "vsIu1hb1GNGrlz8WvmYId",
cgy: "7EeDfCG4JMnpVJEn0IQKX",
nantes: "PCqYmgZpmmy38TpKYh2rr",
marseille: "Q5vvHqjxtgAhcjnxwFary"
};
const campusFormIDs = {
sqy: "52", cgy: "192", nantes: "115", marseille: "26"
};
const campusConfirmationPaths = {
sqy: "confirmation-demande-de-brochure/",
cgy: "confirmation-demande-de-brochure/",
nantes: "confirmation-demande-de-brochure/",
marseille: "confirmation-demande-de-brochure/"
};
const formationsByCampus = {
sqy: [
{ value: "367", text: "BTS SIO SLAM" }, { value: "369", text: "BTS SIO SISR" },
{ value: "371", text: "BTS CIEL" }, { value: "373", text: "Bachelor TECH & DEV spé Gestion de projet IA & Data" },
{ value: "374", text: "Bachelor TECH & DEV spé Développeur Full Stack" },
{ value: "376", text: "Bachelor Systèmes & Réseaux spé Infra & Sécurité" },
{ value: "377", text: "Bachelor Systèmes & Réseaux spé cybersécurité" },
{ value: "378", text: "M1/M2 Expert Solutions Data" },
{ value: "379", text: "M1/M2 Expert Solutions IA & IOT" },
{ value: "380", text: "M1/M2 Lead Developer Full Stack" },
{ value: "382", text: "M1/M2 Expert Architectures IA & IOT" },
{ value: "383", text: "M1/M2 Expert Réseaux & Sécurité" },
{ value: "384", text: "M1/M2 Expert Cybersécurité & Cloud Computing" }
],
cgy: [
{ value: "367", text: "BTS SIO SLAM" }, { value: "369", text: "BTS SIO SISR" },
{ value: "371", text: "BTS CIEL" }, { value: "373", text: "Bachelor TECH & DEV spé Gestion de projet IA & Data" },
{ value: "374", text: "Bachelor TECH & DEV spé Développeur Full Stack" },
{ value: "376", text: "Bachelor Systèmes & Réseaux spé Infra & Sécurité" },
{ value: "377", text: "Bachelor Systèmes & Réseaux spé cybersécurité" },
{ value: "378", text: "M1/M2 Expert Solutions Data" },
{ value: "379", text: "M1/M2 Expert Solutions IA & IOT" },
{ value: "380", text: "M1/M2 Lead Developer Full Stack" },
{ value: "382", text: "M1/M2 Expert Architectures IA & IOT" },
{ value: "383", text: "M1/M2 Expert Réseaux & Sécurité" },
{ value: "384", text: "M1/M2 Expert Cybersécurité & Cloud Computing" }
],
nantes: [
{ value: "343", text: "BTS SIO SLAM" }, { value: "344", text: "BTS SIO SISR" },
{ value: "345", text: "BTS CIEL" }, { value: "363", text: "Bachelor TECH & DEV spé Gestion de projet IA & Data" },
{ value: "364", text: "Bachelor TECH & DEV spé Développeur Full Stack" },
{ value: "365", text: "Bachelor Systèmes & Réseaux spé Infra & Sécurité" },
{ value: "366", text: "Bachelor Systèmes & Réseaux spé cybersécurité" }
],
marseille: [
{ value: "402", text: "BTS SIO SLAM" }, { value: "404", text: "BTS SIO SISR" },
{ value: "406", text: "BTS CIEL" }, { value: "407", text: "Bachelor TECH & DEV spé Gestion de projet IA & Data" },
{ value: "408", text: "Bachelor TECH & DEV spé Développeur Full Stack" },
{ value: "409", text: "Bachelor Systèmes & Réseaux spé Infra & Sécurité" },
{ value: "410", text: "Bachelor Systèmes & Réseaux spé cybersécurité" }
]
};
// Fonctions
function updateHiddenFields() {
const campus = campusSelect.value;
document.getElementById("hidden_token_field").value = campusTokens[campus] || "";
document.getElementById("hidden_formID_field").value = campusFormIDs[campus] || "";
}
function updateFormationOptions() {
const campus = campusSelect.value;
formationSelect.innerHTML = '<option value="">Choisir une formation</option>';
if (campus && formationsByCampus[campus]) {
formationsByCampus[campus].forEach(f => {
const opt = document.createElement('option');
opt.value = f.value;
opt.textContent = f.text;
formationSelect.appendChild(opt);
});
}
}
function validateForm() {
const requiredInputs = form.querySelectorAll('[required]');
let allValid = true;
requiredInputs.forEach(input => {
input.classList.remove('is-invalid');
if ((input.type === "checkbox" && !input.checked) || (input.type !== "checkbox" && input.value.trim() === "")) {
input.classList.add('is-invalid');
allValid = false;
}
});
return allValid;
}
function updateSubmitButtons() {
const buttons = form.querySelectorAll('button[type="submit"]');
const canSubmit = cnilCheckbox.checked && !isSubmitting;
buttons.forEach(btn => btn.disabled = !canSubmit);
}
// Events
campusSelect.addEventListener('change', function() {
updateHiddenFields();
updateFormationOptions();
});
cnilCheckbox.addEventListener('change', updateSubmitButtons);
// CRUCIAL : Bloquer TOUTE soumission du formulaire
form.addEventListener('submit', function(e) {
e.preventDefault();
e.stopImmediatePropagation();
if (isSubmitting) {
console.warn("Déjà en cours");
return false;
}
if (!validateForm()) {
alert("Veuillez remplir tous les champs obligatoires et accepter le CNIL.");
return false;
}
isSubmitting = true;
const buttons = form.querySelectorAll('button[type="submit"]');
buttons.forEach(btn => {
btn.disabled = true;
btn.textContent = "Envoi en cours...";
});
const campus = campusSelect.value;
const redirectUrl = "https://ensitech.eu/" + (campusConfirmationPaths[campus] || "");
axios.post(form.action, new FormData(form))
.then(() => {
window.location.href = redirectUrl;
})
.catch(err => {
console.error(err);
alert("Erreur lors de l'envoi. Veuillez réessayer.");
isSubmitting = false;
buttons.forEach(btn => {
btn.disabled = false;
btn.textContent = "DEMANDER LA BROCHURE";
});
});
return false;
}, true); // true = capture phase
// Init
updateHiddenFields();
updateFormationOptions();
updateSubmitButtons();
});
})();
</script>