{% extends 'base.html.twig' %}
{% block title %}Casting Kalina 2026 - Saison 4 - Formulaire {% endblock %}
{% block body %}
<div class="kalina-header">
<img src="{{ asset('img/logo-kalina.webp') }}" alt="Logo Kalina">
</div>
<div class="container mt-5">
<h2 class="text-center mb-4">đź“‹ Formulaire de Candidature Kalina</h2>
<form method="POST" id="kalinaForm" action="{{ path('form.submit') }}" enctype="multipart/form-data">
{# <div class="wizard-nav">
<button type="button" id="step1Btn">Étape 1</button>
<button type="button" id="step2Btn">Étape 2</button>
<button type="button" id="step3Btn">Étape 3</button>
</div>
<div class="progress mb-4">
<div id="progressBar" class="progress-bar bg-warning" role="progressbar" style="width: 33%;" aria-valuenow="33" aria-valuemin="0" aria-valuemax="100"></div>
</div> #}
{% for message in app.flashes('email_error') %}
<div class="form-error" style="color: #e44118; font-size: 13px;">{{ message }}</div>
{% endfor %}
{{ include('default/step/step1.html.twig') }}
{{ include('default/step/step2.html.twig') }}
{{ include('default/step/step3.html.twig') }}
</form>
</div>
<!-- Footer -->
<footer>
Site créé par <a href="https://basicom.fr" target="_blank">Basicom</a>
</footer>
<div id="formLoader" style="display: none; position: fixed; top:0; left:0; width:100%; height:100%; background-color: rgba(23, 33, 40, 0.9); z-index: 9999; justify-content: center; align-items: center;">
<div class="spinner-border text-light" style="width: 4rem; height: 4rem;" role="status">
<span class="visually-hidden">Chargement...</span>
</div>
<p class="text-white mt-3">Envoi en cours...</p>
</div>
{% endblock %}
{% block javascripts %}
<script>
document.addEventListener("DOMContentLoaded", function () {
function showStep(step) {
document.querySelectorAll(".wizard-step").forEach(el => el.classList.remove("active"));
const currentStep = document.getElementById(`step${step}`);
if (currentStep) currentStep.classList.add("active");
const progress = document.getElementById("progressBar");
if (progress) {
progress.style.width = step === 1 ? "33%" : step === 2 ? "66%" : "100%";
}
document.getElementById("kalinaForm").scrollIntoView({ behavior: "smooth" });
}
function validateStep(step) {
let valid = true;
const currentStep = document.getElementById(`step${step}`);
if (!currentStep) return false;
const requiredFields = currentStep.querySelectorAll("input[required], select[required], textarea[required]");
requiredFields.forEach(field => {
const error = field.parentNode.querySelector(".form-error");
field.classList.remove("is-invalid");
if (error) error.remove();
if (!field.value.trim()) {
valid = false;
field.classList.add("is-invalid");
const errorMsg = document.createElement("div");
errorMsg.classList.add("form-error");
errorMsg.style.color = "#e44118";
errorMsg.style.fontSize = "13px";
errorMsg.textContent = "Champ non renseigné";
field.parentNode.appendChild(errorMsg);
}
});
return valid;
}
function validateEmailsMatch(live = false) {
const email = document.querySelector("input[name='email']");
const confirmEmail = document.querySelector("input[name='confirm_email']");
if (!email || !confirmEmail) return true;
[email, confirmEmail].forEach(field => {
field.classList.remove("is-invalid", "is-valid");
const error = field.parentNode.querySelector(".form-feedback");
if (error) error.remove();
});
const feedback = document.createElement("div");
feedback.classList.add("form-feedback");
feedback.style.fontSize = "13px";
if (email.value.trim() !== confirmEmail.value.trim()) {
if (!live) {
confirmEmail.classList.add("is-invalid");
feedback.style.color = "#e44118";
feedback.textContent = "Adresse mail différente";
confirmEmail.parentNode.appendChild(feedback);
return false;
}
} else {
if (confirmEmail.value.trim() !== "") {
confirmEmail.classList.add("is-valid");
feedback.style.color = "green";
feedback.textContent = "✔️ Adresse confirmée";
confirmEmail.parentNode.appendChild(feedback);
}
}
return true;
}
function validateFile(input, maxMo, allowedExtensions = []) {
const file = input.files[0];
if (!file) return true;
const maxBytes = maxMo * 1024 * 1024;
const ext = file.name.split('.').pop().toLowerCase();
const existingError = input.parentNode.querySelector(".file-error");
if (existingError) existingError.remove();
input.classList.remove("is-invalid");
if (file.size > maxBytes) {
input.classList.add("is-invalid");
const error = document.createElement("div");
error.classList.add("file-error");
error.style.color = "#e44118";
error.style.fontSize = "13px";
error.textContent = `Fichier trop volumineux (max ${maxMo} Mo)`;
input.parentNode.appendChild(error);
return false;
}
if (allowedExtensions.length && !allowedExtensions.includes(ext)) {
input.classList.add("is-invalid");
const error = document.createElement("div");
error.classList.add("file-error");
error.style.color = "#e44118";
error.style.fontSize = "13px";
error.textContent = `Format non autorisé (${allowedExtensions.join(', ')})`;
input.parentNode.appendChild(error);
return false;
}
return true;
}
// Navigation Étapes
document.querySelectorAll(".btn-next").forEach(btn => {
btn.addEventListener("click", function () {
const next = parseInt(this.dataset.next);
const current = next - 1;
if (validateStep(current)) showStep(next);
});
});
document.querySelectorAll(".btn-prev").forEach(btn => {
btn.addEventListener("click", function () {
const prev = parseInt(this.dataset.prev);
showStep(prev);
});
});
// Live email check
const confirmEmail = document.querySelector("input[name='confirm_email']");
if (confirmEmail) {
confirmEmail.addEventListener("input", () => validateEmailsMatch(true));
}
// Reset d'erreur sur fichier quand modifié
document.querySelectorAll('input[type="file"]').forEach(input => {
input.addEventListener("change", () => {
const isVideo = input.id.includes("video");
validateFile(input, isVideo ? 100 : 3, isVideo ? ["mp4", "mov", "avi", "mkv"] : ["jpg", "jpeg", "png"]);
});
});
// Soumission finale
const form = document.getElementById("kalinaForm");
if (form) {
form.addEventListener("submit", function (e) {
e.preventDefault();
if (!validateStep(3)) return;
if (!validateEmailsMatch()) return;
const isPhoto1OK = validateFile(document.querySelector("#photo1"), 8, ["jpg", "jpeg", "png"]);
const isPhoto2OK = validateFile(document.querySelector("#photo2"), 8, ["jpg", "jpeg", "png"]);
const isPhoto3OK = validateFile(document.querySelector("#photo3"), 8, ["jpg", "jpeg", "png"]);
// const isVideoOK = validateFile(document.querySelector("#video_motivation"), 100, ["mp4", "mov", "avi", "mkv"]);
if (!isPhoto1OK || !isPhoto2OK || !isPhoto3OK /*|| !isVideoOK*/) return;
// Supprimer l'attribut "required" des champs non visibles pour éviter les erreurs de focus
form.querySelectorAll("input[required], select[required], textarea[required]").forEach(field => {
if (!field.offsetParent) {
field.removeAttribute("required");
}
});
// Affiche le loader
document.getElementById("formLoader").style.display = "flex";
setTimeout(() => {
form.submit();
}, 500); // Un petit délai pour UX, sinon instantané
});
}
showStep(1);
});
</script>
{% endblock %}