Files
e-cosplay/templates/pages/onboarding.twig
Serreau Jovann 80e4eaa907 ```
 feat(PagesController): Ajoute la vérification de disponibilité du slug.

Ajoute une route pour vérifier la disponibilité d'un slug d'EPage.
Utilise EpageService pour vérifier si le slug est disponible.
Retourne une réponse JSON indiquant la disponibilité et le slug.
```
2025-12-26 13:31:23 +01:00

212 lines
11 KiB
Twig

{% extends 'base.twig' %}
{% block title %}{{'page.onboarding.title'|trans}}{% endblock %}
{% block meta_description %}{{'page.onboarding.description'|trans}}{% endblock %}
{% block canonical_url %}<link rel="canonical" href="{{ url('app_pages_onboaring',{type:app.request.get('abo','M1')}) }}" />{% endblock %}
{% block body %}
<div class="min-h-screen bg-[#f0f0f0] py-12 px-4 italic">
{{ form_start(form) }}
<div class="max-w-4xl mx-auto">
{# EN-TÊTE DU FORMULAIRE #}
<div class="mb-12 text-center">
<h1 class="inline-block text-4xl md:text-6xl font-black bg-gray-900 text-white p-6 border-8 border-gray-900 shadow-[12px_12px_0px_rgba(239,68,68,1)] uppercase tracking-tighter">
{{ 'onboarding.form.title'|trans }}
</h1>
</div>
<div class="space-y-12">
{# SECTION 1 : INFORMATIONS PERSONNELLES #}
<div class="bg-white border-8 border-gray-900 p-8 shadow-[12px_12px_0px_#4f46e5]">
<h2 class="text-3xl font-black text-indigo-700 mb-2 uppercase flex items-center tracking-tighter">
<span class="bg-indigo-700 text-white px-3 mr-3 border-4 border-gray-900 shadow-[4px_4px_0px_rgba(0,0,0,1)]">1</span>
{{ 'onboarding.form.section1.title'|trans }}
</h2>
<p class="text-xs font-bold text-gray-500 uppercase tracking-widest mb-8 border-b-4 border-indigo-100 pb-2">
// {{ 'onboarding.form.section1.description'|trans }}
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<div class="neubrutal-input">{{ form_row(form.name) }}</div>
<div class="neubrutal-input">{{ form_row(form.surname) }}</div>
<div class="neubrutal-input">{{ form_row(form.email) }}</div>
<div class="neubrutal-input">{{ form_row(form.birdth) }}</div>
</div>
</div>
{# SECTION 2 : PROFIL COSPLAY + CHECK DISPO #}
<div class="bg-white border-8 border-gray-900 p-8 shadow-[12px_12px_0px_#eab308]">
<h2 class="text-3xl font-black text-yellow-600 mb-2 uppercase flex items-center tracking-tighter">
<span class="bg-yellow-400 text-black px-3 mr-3 border-4 border-gray-900 shadow-[4px_4px_0px_rgba(0,0,0,1)]">2</span>
{{ 'onboarding.form.section2.title'|trans }}
</h2>
<p class="text-xs font-bold text-gray-500 uppercase tracking-widest mb-8 border-b-4 border-yellow-100 pb-2">
// {{ 'onboarding.form.section2.description'|trans }}
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<div class="md:col-span-2 neubrutal-input relative">
{{ form_row(form.nameCosplayer) }}
{# Le feedback JS sera injecté ici #}
</div>
<div class="md:col-span-2 neubrutal-input">{{ form_row(form.description)}}</div>
<div class="md:col-span-2">{{ form_row(form.epage) }}</div>
</div>
</div>
{# SECTION 3 : RÉSEAUX SOCIAUX #}
<div class="bg-white border-8 border-gray-900 p-8 shadow-[12px_12px_0px_#22c55e]">
<h2 class="text-3xl font-black text-green-700 mb-2 uppercase flex items-center tracking-tighter">
<span class="bg-green-500 text-white px-3 mr-3 border-4 border-gray-900 shadow-[4px_4px_0px_rgba(0,0,0,1)]">3</span>
{{ 'onboarding.form.section3.title'|trans }}
</h2>
<p class="text-xs font-bold text-gray-500 uppercase tracking-widest mb-8 border-b-4 border-green-100 pb-2">
// {{ 'onboarding.form.section3.description'|trans }}
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<div class="neubrutal-input">{{ form_row(form.linkFacebook) }}</div>
<div class="neubrutal-input">{{ form_row(form.linkInstagram) }}</div>
<div class="neubrutal-input">{{ form_row(form.linkTiktok) }}</div>
<div class="neubrutal-input">{{ form_row(form.linkX) }}</div>
</div>
</div>
{# SECTION 4 : LIEN PERSONNALISÉ #}
<div class="bg-white border-8 border-gray-900 p-8 shadow-[12px_12px_0px_#3b82f6]">
<h2 class="text-3xl font-black text-blue-700 mb-2 uppercase flex items-center tracking-tighter">
<span class="bg-blue-600 text-white px-3 mr-3 border-4 border-gray-900 shadow-[4px_4px_0px_rgba(0,0,0,1)]">4</span>
{{ 'onboarding.form.section4.title'|trans }}
</h2>
<div class="mt-8 space-y-6">
<div class="p-4 bg-blue-50 border-4 border-blue-200 font-bold uppercase text-sm">
{{ form_row(form.useDomain) }}
</div>
<div id="custom-domain-group" class="hidden transition-all duration-300 neubrutal-input p-6 bg-gray-900 text-white border-8 border-gray-900 shadow-[8px_8px_0px_#3b82f6]">
{{ form_row(form.domain) }}
</div>
</div>
</div>
</div>
{# BOUTON SOUMISSION #}
<div class="mt-16 flex justify-center pb-20">
<button type="submit" class="group relative px-12 py-6 bg-indigo-600 text-white border-8 border-gray-900 text-3xl font-black uppercase tracking-widest shadow-[12px_12px_0px_rgba(0,0,0,1)] hover:shadow-none hover:translate-x-2 hover:translate-y-2 transition-all active:scale-95">
{{ 'onboarding.form.submit_button'|trans }}
<i class="fas fa-rocket ml-4 group-hover:-translate-y-2 transition-transform"></i>
</button>
</div>
</div>
{{ form_end(form) }}
</div>
<style>
/* Design Neubrutaliste pour les inputs Symfony */
.neubrutal-input input,
.neubrutal-input textarea,
.neubrutal-input select {
width: 100%;
padding: 1rem;
border: 4px solid #111827 !important;
background: white;
font-weight: 900;
text-transform: uppercase;
box-shadow: 4px 4px 0px #111827;
transition: all 0.2s;
}
.neubrutal-input input:focus {
box-shadow: none;
transform: translate(2px, 2px);
outline: none;
border-color: #4f46e5 !important;
}
.neubrutal-input label {
display: block;
font-weight: 900;
text-transform: uppercase;
font-size: 0.75rem;
margin-bottom: 0.5rem;
letter-spacing: 0.1em;
}
/* Classes pour le Check Pseudo */
.check-success { border-color: #22c55e !important; box-shadow: 4px 4px 0px #15803d !important; }
.check-error { border-color: #ef4444 !important; box-shadow: 4px 4px 0px #b91c1c !important; }
</style>
<script>
document.addEventListener('turbo:load', () => {
// --- LOGIQUE DOMAINE PERSONNALISÉ ---
const useDomainCheckbox = document.getElementById('e_page_onboard_useDomain');
const customDomainGroup = document.getElementById('custom-domain-group');
const customDomainInput = document.getElementById('e_page_onboard_domain');
function toggleDomainFields() {
if (useDomainCheckbox && useDomainCheckbox.checked) {
customDomainGroup.classList.remove('hidden');
customDomainInput.setAttribute('required', 'required');
} else if (useDomainCheckbox) {
customDomainGroup.classList.add('hidden');
customDomainInput.removeAttribute('required');
customDomainInput.value = '';
}
}
if (useDomainCheckbox) {
toggleDomainFields();
useDomainCheckbox.addEventListener('change', toggleDomainFields);
}
// --- LOGIQUE CHECK PSEUDO (DEBOUNCED) ---
const pseudoInput = document.getElementById('e_page_onboard_nameCosplayer');
let timeout = null;
if (pseudoInput) {
// Création du message de feedback
const feedbackMsg = document.createElement('div');
feedbackMsg.className = 'text-[10px] font-black uppercase mt-2 tracking-widest hidden';
pseudoInput.parentNode.appendChild(feedbackMsg);
pseudoInput.addEventListener('keyup', () => {
const value = pseudoInput.value.trim();
if (value.length < 2) {
resetInputState(pseudoInput, feedbackMsg);
return;
}
clearTimeout(timeout);
timeout = setTimeout(() => {
fetch(`/pages/check?q=${encodeURIComponent(value)}`)
.then(response => response.json())
.then(data => {
if (data.available === true) {
pseudoInput.classList.remove('check-error');
pseudoInput.classList.add('check-success');
feedbackMsg.textContent = "DISPONIBLE // READY TO SYNC";
feedbackMsg.className = 'text-[10px] font-black uppercase mt-2 tracking-widest text-green-600 block';
} else {
pseudoInput.classList.remove('check-success');
pseudoInput.classList.add('check-error');
feedbackMsg.textContent = "NON DISPONIBLE // ALREADY TAKEN";
feedbackMsg.className = 'text-[10px] font-black uppercase mt-2 tracking-widest text-red-600 block';
}
})
.catch(() => console.error("API Check Error"));
}, 500); // 500ms debounce
});
}
function resetInputState(el, msg) {
el.classList.remove('check-success', 'check-error');
msg.classList.add('hidden');
}
});
</script>
{% endblock %}