Files
FormulairesEnsitech_Ensup/FormulaireEnsitech_Ensup/ENSITECH/JPOEnsitech
2025-10-09 11:06:59 +02:00

1053 lines
34 KiB
Plaintext
Raw 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.
<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>
<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="JPO">
<div class="form-sections-wrapper">
<div id="section1" class="form-section form-section-step active">
<h2><i class="fas fa-calendar-alt"></i> Inscription JPO</h2>
<p class="form-description">Complétez ce formulaire pour vous inscrire.</p>
<!-- Je suis -->
<div class="form-group">
<div class="form-group-item">
<label for="OscarContactJeSuisRefIdField">Je suis <span class="oscar_input_required">(*)</span>:</label>
<select
id="OscarContactJeSuisRefIdField"
class="form-control"
name="je_suis_ref_id"
v-on:change="determineRelatedFieldsOptions"
v-on:focus="displayAvailableOptions"
required
>
<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'étudiant</option>
</select>
</div>
</div>
<!-- Nom et Prénom -->
<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>
<!-- Email et Portable -->
<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>
<!-- Campus et Formation -->
<div class="form-group" >
<div class="form-group-item" >
<div id="campus_selection_app_JPO">
<label for="campus_selection_JPO">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>
<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 class="form-group">
<label for="OscarContactComboMarketingPlanField">
Inscription à un événement <span class="oscar_input_required">(*)</span>
</label>
<select id="OscarContactComboMarketingPlanField"
class="form-control"
name="combo_marketing_plan"
required>
<option value="">Choisir un événement</option>
</select>
</div>
</div>
<!-- Consentement CNIL -->
<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>
<!-- Boutons -->
<button type="submit" class="btn-primary desktop-submit-button">M'INSCRIRE À LA JPO</button>
</div>
</div>
<!-- Mobile Submit -->
<div id="final-mobile-navigation">
<button type="submit" class="btn-primary mobile-submit-button">M'INSCRIRE À LA JPO</button>
</div>
<!-- Infos obligatoires -->
<div class="mandatory-fields-note-global">(*) Champs obligatoires</div>
<!-- Champs cachés -->
<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="">
<!-- Champ anti-bot -->
<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>
<style>
/* Ensure these global styles are either removed if they conflict with your site's main styles,
or applied very specifically to a wrapper around your custom HTML.
For now, I'm keeping them commented out to prevent global interference. */
/*
body {
margin: 0;
padding: 0;
background-color: #f0f2f5;
font-family: 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
line-height: 1.6;
color: #333;
}
*/
/* Apply valid input styling only within your form container */
#oscar_school_form_container input:valid {
border: 1px solid green;
}
/* --- Main Form Container --- */
#oscar_school_form_container {
max-width: 1200px;
margin: 20px auto;
padding: 0 15px;
/* Important: Add position: relative if you use absolute positioning inside */
position: relative;
}
/* --- Form Body Styles (The white/light gray box) --- */
#oscar_school_form_container #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_container #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_container #oscar_school_form_header p {
text-align: center;
color: #555;
font-size: 1.15em;
margin-bottom: 35px;
}
#oscar_school_form_container .form-description {
text-align: center;
margin-bottom: 25px;
padding: 0 15px;
}
/* --- Form Sections Wrapper (Desktop Flex / Mobile Stack) --- */
#oscar_school_form_container .form-sections-wrapper {
margin-bottom: 25px;
}
/* --- Individual Form Section Styles (e.g., Identité, Projet de formation) --- */
#oscar_school_form_container .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;
display: flex;
flex-direction: column;
}
#oscar_school_form_container .form-section:hover {
transform: translateY(-5px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
}
#oscar_school_form_container .form-section h2 {
margin-top: 0;
color: #0087CF;
font-size: 1.7em;
border-bottom: 2px solid #0087CF;
padding-bottom: 12px;
margin-bottom: 22px;
text-align: center;
}
#oscar_school_form_container .form-section h2 i {
margin-right: 8px;
color: #0087CF;
}
/* --- Form Group & Control Styles --- */
#oscar_school_form_container .form-group {
margin-bottom: 8px;
display: flex;
flex-wrap: wrap;
gap: 20px;
}
#oscar_school_form_container .form-group-item {
flex: 1 1 calc(50% - 10px);
max-width: calc(50% - 10px);
}
#oscar_school_form_container .form-group > .form-group-item:only-child,
#oscar_school_form_container .form-group:not(.cnil-consent-group) > label + .form-control {
flex: 1 1 100%;
max-width: 100%;
}
#oscar_school_form_container .form-group label {
display: block;
margin-bottom: 6px;
color: #444;
font-size: 0.98em;
font-weight: 500;
}
#oscar_school_form_container .cnil-info-label {
color: #6c757d;
font-size: 0.85em;
margin-top: 8px;
font-weight: normal;
}
#oscar_school_form_container .cnil-checkbox-wrapper {
display: flex;
align-items: flex-start;
gap: 8px;
width: 100%;
}
#oscar_school_form_container .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;
}
#oscar_school_form_container .form-control:focus {
border-color: #80bdff;
outline: 0;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
#oscar_school_form_container .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);
}
#oscar_school_form_container .form-control.is-invalid:focus {
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
}
#oscar_school_form_container textarea.form-control {
resize: vertical;
min-height: 90px;
}
#oscar_school_form_container .oscar_input_required {
color: #DD1B51;
font-weight: bold;
}
#oscar_school_form_container .custom-control-input {
width: 20px;
height: 20px;
border: 1px solid #ced4da;
border-radius: 4px;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
cursor: pointer;
flex-shrink: 0;
margin-top: 2px;
}
#oscar_school_form_container .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;
}
#oscar_school_form_container .custom-control-input:focus {
outline: none;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
#oscar_school_form_container .custom-control-label {
cursor: pointer;
color: #333;
flex-grow: 1;
}
#oscar_school_form_container .cnil-consent-group {
padding: 10px 0;
margin-bottom: 20px;
}
/* --- Primary Button (General Style for submit/next) --- */
#oscar_school_form_container .btn-primary {
display: block;
width: 100%;
padding: 15px 25px;
margin-top: 30px;
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);
}
#oscar_school_form_container .btn-primary:hover {
background-color: #0056b3;
transform: translateY(-3px);
box-shadow: 0 7px 20px rgba(0, 123, 255, 0.35);
}
#oscar_school_form_container .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) --- */
#oscar_school_form_container .form-section-step {
width: 100%;
display: none; /* Crucial for mobile step visibility */
}
/* --- Navigation Buttons (Prev/Next for Mobile Steps) --- */
#oscar_school_form_container .form-navigation {
display: none;
justify-content: center;
gap: 15px;
margin-top: 25px;
}
#oscar_school_form_container .form-navigation .btn-next,
#oscar_school_form_container .form-navigation .btn-prev {
flex: 1;
max-width: 160px;
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;
}
#oscar_school_form_container .form-navigation .btn-prev {
background-color: #DD1B3D;
color: #fff;
}
#oscar_school_form_container .form-navigation .btn-prev:hover {
background-color: #c71534;
transform: translateY(-2px);
}
#oscar_school_form_container .form-navigation .btn-next {
background-color: #198AB4;
color: #fff;
}
#oscar_school_form_container .form-navigation .btn-next:hover {
background-color: #147395;
transform: translateY(-2px);
}
#oscar_school_form_container .mandatory-fields-note-global {
font-size: 0.85em;
color: #555;
text-align: right;
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;
}
#oscar_school_form_container .form-sections-wrapper {
display: flex;
flex-wrap: nowrap;
justify-content: center;
gap: 30px;
align-items: stretch;
margin-bottom: 0;
}
#oscar_school_form_container .form-section-step {
flex: 1;
min-width: 0;
max-width: 50%;
display: flex !important;
margin-bottom: 0;
}
#oscar_school_form_container .form-section {
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
padding-bottom: 20px;
}
#oscar_school_form_container .form-navigation,
#oscar_school_form_container .section-navigation-mobile,
#oscar_school_form_container #final-mobile-navigation,
#oscar_school_form_container .mobile-submit-button {
display: none !important;
}
#oscar_school_form_container .desktop-submit-button {
display: block !important;
width: 100%;
margin-top: auto;
align-self: center;
padding: 15px 25px;
font-size: 1.25em;
box-shadow: 0 5px 15px rgba(0, 123, 255, 0.25);
}
#oscar_school_form_container .form-group {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
#oscar_school_form_container .form-group-item {
flex: 1 1 calc(50% - 10px);
max-width: calc(50% - 10px);
}
#oscar_school_form_container #section1 .form-group:first-of-type .form-group-item {
flex: 1 1 100%;
max-width: 100%;
}
#oscar_school_form_container .mandatory-fields-note-global {
position: absolute;
bottom: 107px;
left: 310px;
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) --- */
@media (max-width: 768px) {
#oscar_school_form_container .form-section h2 {
align-self: center;
text-align: center;
width: 100%;
}
#oscar_school_form_container {
width: 100%;
padding: 0 15px;
margin-top: 15px;
}
#oscar_school_form_container #oscar_school_form_body {
padding: 20px;
}
#oscar_school_form_container .form-sections-wrapper {
flex-direction: column;
gap: 15px;
margin-bottom: 0;
}
#oscar_school_form_container .form-section {
min-width: unset;
padding: 18px;
margin-bottom: 20px;
height: auto;
align-items: flex-start;
}
#oscar_school_form_container .form-section-step.active {
display: flex;
flex-direction: column;
}
#oscar_school_form_container .form-group {
margin-bottom: 12px;
flex-direction: column;
gap: 0;
width: 100%;
max-width: 400px;
margin-left: 0;
margin-right: auto;
}
#oscar_school_form_container .form-group-item {
flex: 1 1 100%;
max-width: 100%;
margin-bottom: 10px;
display: flex;
flex-direction: row;
align-items: center;
gap: 10px;
}
#oscar_school_form_container .form-group-item:last-child {
margin-bottom: 0;
}
#oscar_school_form_container .form-group-item label {
display: inline-block;
flex-shrink: 0;
width: 90px;
text-align: left;
margin-bottom: 0;
}
#oscar_school_form_container .form-group-item .form-control {
flex-grow: 1;
width: auto;
max-width: calc(100% - 100px);
}
#oscar_school_form_container #section1 .form-group {
flex-direction: column;
flex-wrap: nowrap;
gap: 0;
}
#oscar_school_form_container #section1 .form-group-item {
flex: 1 1 100%;
max-width: 100%;
margin-bottom: 10px;
}
#oscar_school_form_container #section1 .form-group:first-of-type .form-group-item {
flex: 1 1 100%;
max-width: 100%;
justify-content: flex-start;
}
#oscar_school_form_container #section1 .form-group:first-of-type .form-group-item label {
width: 90px;
text-align: left;
}
#oscar_school_form_container #section1 .form-group:first-of-type .form-group-item .form-control {
max-width: calc(100% - 100px);
}
#oscar_school_form_container .cnil-consent-group {
max-width: 400px;
margin-left: auto;
margin-right: auto;
flex-direction: column;
align-items: flex-start;
}
#oscar_school_form_container .desktop-submit-button {
display: none !important;
}
#oscar_school_form_container #final-mobile-navigation {
display: block !important;
margin-top: 20px;
padding: 0 15px;
text-align: center;
}
#oscar_school_form_container .mobile-submit-button {
display: block !important;
margin: 0 auto;
max-width: 400px;
width: 100%;
}
#oscar_school_form_container .mandatory-fields-note-global {
position: static;
text-align: center;
margin-top: 20px;
padding-right: 0;
}
}
/* --- Media Query for SMALL PHONES (max-width: 414px) --- */
@media (max-width: 414px) {
#oscar_school_form_container .form-group-item label {
width: 70px;
}
#oscar_school_form_container .form-group-item .form-control {
max-width: calc(100% - 80px);
}
#oscar_school_form_container #section1 .form-group:first-of-type .form-group-item label {
width: 70px;
}
#oscar_school_form_container #section1 .form-group:first-of-type .form-group-item .form-control {
max-width: calc(100% - 80px);
}
}
@media (min-width: 769px) {
#oscar_school_form_container {
max-width: none !important;
width: 100% !important;
}
.form-sections-wrapper {
flex-wrap: wrap !important; /* Si tu veux que ça aille à la ligne au besoin */
justify-content: space-between;
}
.form-section-step {
max-width: 100% !important; /* Enlève la limite à 50% */
flex: 1 1 100% !important; /* Permet au formulaire de sadapter à la largeur */
}
.form-section {
box-sizing: border-box;
width: 100% !important;
}
.desktop-submit-button {
max-width: 400px;
margin: 30px auto 0 auto;
display: block;
}
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function () {
// Fonction pour décoder les entités HTML
function decodeHTML(html) {
const txt = document.createElement('textarea');
txt.innerHTML = html;
return txt.value;
}
// --- Éléments du DOM ---
const form = document.getElementById('oscar_school_form');
const campusSelect = document.getElementById('campus_selection');
const formationSelect = document.getElementById('formation');
const cnilInputs = document.querySelectorAll('input[name="cnil"]');
const submitBtnDesktop = document.querySelector('.desktop-submit-button');
const submitBtnMobile = document.querySelector('.mobile-submit-button');
if (!form) return;
// Système de verrouillage avec localStorage pour éviter les doublons
const LOCK_KEY = 'ensitech_form_submitting';
const LOCK_DURATION = 5000; // 5 secondes
function isLocked() {
const lockTime = localStorage.getItem(LOCK_KEY);
if (!lockTime) return false;
const now = Date.now();
const locked = now - parseInt(lockTime) < LOCK_DURATION;
if (!locked) {
localStorage.removeItem(LOCK_KEY);
}
return locked;
}
function setLock() {
localStorage.setItem(LOCK_KEY, Date.now().toString());
}
function removeLock() {
localStorage.removeItem(LOCK_KEY);
}
// Variable pour éviter les soumissions multiples
let isSubmitting = false;
// --- Données par campus ---
const campusTokens = {
sqy: "U0NKi18v9N7uGSRNHi2mz",
cgy: "96UxAQKkrZDD6dGnjfzrn",
nantes: "PMJR1aGJQ070QvKQgmlIp",
marseille: "eNfHxnG7OYskuswlgzzpt"
};
const campusFormIDs = {
sqy: "124",
cgy: "134",
nantes: "112",
marseille: "29"
};
const campusConfirmationPaths = {
sqy: "confirmation-inscription-portes-ouvertes/",
cgy: "confirmation-inscription-portes-ouvertes/",
nantes: "confirmation-inscription-portes-ouvertes/",
marseille: "confirmation-inscription-portes-ouvertes/"
};
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é" }
]
};
const eventsByCampus = {
sqy: [{ value: "278", text: "Samedi 6 Décembre 2025 10h-14h" }, { value: "279", text: "Samedi 24 Janvier 2026 10h-16h" }],
cgy: [{ value: "283", text: "Samedi 6 Décembre 2025 10h-14h" }, { value: "284", text: "Samedi 24 Janvier 2026 10h-16h" }],
nantes: [{ value: "270", text: "Samedi 11 Octobre 2025 10h-14h" }, { value: "272", text: "Samedi 6 Décembre 2025 10h-14h" }],
marseille: [{ value: "274", text: "Samedi 13 Décembre 2025 10h-14h" }, { value: "275", text: "Samedi 24 Janvier 2026 10h-14h" }]
};
// --- Fonctions utilitaires ---
function updateHiddenFields(campus) {
document.getElementById("hidden_token_field").value = campusTokens[campus] || "";
document.getElementById("hidden_formID_field").value = campusFormIDs[campus] || "";
}
function updateFormationOptions(campus) {
formationSelect.innerHTML = '<option value="">Choisir une formation</option>';
if (!formationsByCampus[campus]) return;
formationsByCampus[campus].forEach(f => {
const opt = document.createElement('option');
opt.value = f.value;
opt.textContent = decodeHTML(f.text); // 👈 Ajoutez decodeHTML() ici
formationSelect.appendChild(opt);
});
}
function updateEventOptions(campus) {
const eventSelect = document.getElementById("OscarContactComboMarketingPlanField");
if (!eventSelect) return;
eventSelect.innerHTML = '<option value="">Choisir un événement</option>';
if (!eventsByCampus[campus]) return;
eventsByCampus[campus].forEach(ev => {
const opt = document.createElement('option');
opt.value = ev.value;
opt.textContent = decodeHTML(ev.text); // 👈 Ajoutez decodeHTML() ici
eventSelect.appendChild(opt);
});
}
// --- Vue instance pour campus ---
const vueInstance = new Vue({
el: "#campus_selection_app_JPO",
data: {
selectedCampus: campusSelect ? campusSelect.value : ""
},
methods: {
// Ajouter les méthodes manquantes référencées dans le HTML
determineRelatedFieldsOptions() {
// Fonction vide pour éviter les erreurs Vue
console.log('determineRelatedFieldsOptions appelée');
},
displayAvailableOptions() {
// Fonction vide pour éviter les erreurs Vue
return true;
}
},
watch: {
selectedCampus(newVal) {
updateHiddenFields(newVal);
updateFormationOptions(newVal);
updateEventOptions(newVal);
}
},
mounted() {
if (campusSelect) {
this.selectedCampus = campusSelect.value;
updateHiddenFields(this.selectedCampus);
updateFormationOptions(this.selectedCampus);
updateEventOptions(this.selectedCampus);
}
}
});
// Listener pour le changement de campus (en dehors de Vue)
if (campusSelect) {
campusSelect.addEventListener("change", function(e) {
vueInstance.selectedCampus = e.target.value;
});
}
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.value.trim() === "") {
input.classList.add('is-invalid');
allValid = false;
}
});
return allValid;
}
function toggleSubmitButton() {
const accepted = Array.from(cnilInputs).some(i => i.checked && i.value === "1");
const shouldDisable = !accepted || isSubmitting || isLocked();
if (submitBtnDesktop) submitBtnDesktop.disabled = shouldDisable;
if (submitBtnMobile) submitBtnMobile.disabled = shouldDisable;
}
function disableSubmitButtons() {
const buttons = document.querySelectorAll('#oscar_school_form button[type="submit"]');
buttons.forEach(btn => {
btn.disabled = true;
btn.style.pointerEvents = 'none';
btn.textContent = "Envoi en cours...";
});
}
toggleSubmitButton();
cnilInputs.forEach(i => i.addEventListener("change", toggleSubmitButton));
// --- Soumission du formulaire avec verrouillage localStorage ---
form.addEventListener("submit", function(e) {
e.preventDefault();
e.stopPropagation();
console.log("Submit event déclenché");
// Vérification du verrou localStorage
if (isLocked()) {
console.warn("BLOQUÉ PAR VERROU LOCALSTORAGE");
return false;
}
// Vérification de la variable isSubmitting
if (isSubmitting) {
console.warn("BLOQUÉ PAR isSubmitting");
return false;
}
if (!validateForm()) {
alert("Veuillez remplir tous les champs obligatoires et accepter le CNIL.");
return false;
}
// VERROUILLER IMMÉDIATEMENT
isSubmitting = true;
setLock();
disableSubmitButtons();
console.log("Envoi du formulaire...");
const formData = new FormData(form);
const campus = vueInstance.selectedCampus;
const confirmationPath = campusConfirmationPaths[campus] || "confirmation-generale/";
const baseUrl = "https://ensitech.eu/";
axios.post(form.action, formData)
.then(() => {
console.log("Succès, redirection...");
// Ne jamais déverrouiller en cas de succès, on redirige
window.location.href = baseUrl + confirmationPath;
})
.catch(err => {
console.error("Erreur:", err);
alert("Erreur lors de l'envoi du formulaire. Veuillez réessayer.");
// Déverrouiller seulement en cas d'erreur
isSubmitting = false;
removeLock();
toggleSubmitButton();
});
return false;
}, { capture: true, once: false });
// Nettoyer le verrou au chargement (au cas où il resterait d'une session précédente)
window.addEventListener('load', function() {
const lockTime = localStorage.getItem(LOCK_KEY);
if (lockTime) {
const elapsed = Date.now() - parseInt(lockTime);
if (elapsed > LOCK_DURATION) {
removeLock();
}
}
});
});
</script>