feat(membres): Ajoute la page des membres avec les membres du bureau.
```
This commit is contained in:
Serreau Jovann
2025-11-16 22:25:55 +01:00
parent 524d5a3041
commit 7bf092a674
5 changed files with 296 additions and 1 deletions

View File

@@ -25,6 +25,27 @@ class MembersController extends AbstractController
#[Route(path: '/membres', name: 'app_members', options: ['sitemap' => true], methods: ['GET'])]
public function index(): Response
{
return $this->render('home.twig');
return $this->render('members.twig',[
'board_members' => [
[
'pseudo' => 'Shoko Cosplay',
'photo_url' => '/assets/images/shoko.jpg',
'role' => 'Président',
'cosplayer' => true,
'crosscosplayer' => true,
'trans' => true,
'orientation' => 'pansexual',
],
[
'pseudo' => 'Marta Gator',
'photo_url' => '/assets/images/marta.jpg',
'role' => 'Secrétaire',
'cosplayer' => true,
'crosscosplayer' => true,
'trans' => false,
'orientation' => 'heterosexual',
]
]
]);
}
}

View File

@@ -34,6 +34,8 @@ class SitemapSubscriber
$urlMembers = new UrlConcrete($urlGenerator->generate('app_members', [], UrlGeneratorInterface::ABSOLUTE_URL));
$decoratedUrlMembers = new GoogleImageUrlDecorator($urlMembers);
$decoratedUrlMembers->addImage(new GoogleImage($this->cacheManager->resolve('assets/images/logo.jpg','webp')));
$decoratedUrlMembers->addImage(new GoogleImage($this->cacheManager->resolve('assets/images/shoko.jpg','webp')));
$decoratedUrlMembers->addImage(new GoogleImage($this->cacheManager->resolve('assets/images/marta.jpg','webp')));
$decoratedUrlMembers = new GoogleMultilangUrlDecorator($decoratedUrlMembers);
$decoratedUrlMembers->addLink($urlGenerator->generate('app_members',['lang'=>'fr'], UrlGeneratorInterface::ABSOLUTE_URL), 'fr');
$decoratedUrlMembers->addLink($urlGenerator->generate('app_members',['lang'=>'en'], UrlGeneratorInterface::ABSOLUTE_URL), 'en');
@@ -47,6 +49,8 @@ class SitemapSubscriber
$urlEvents->addLink($urlGenerator->generate('app_events',['lang'=>'en'], UrlGeneratorInterface::ABSOLUTE_URL), 'en');
$urlContainer->addUrl($urlEvents, 'default');
$urlAbout = new UrlConcrete($urlGenerator->generate('app_about', [], UrlGeneratorInterface::ABSOLUTE_URL));
$decoratedUrlAbout = new GoogleImageUrlDecorator($urlAbout);
$decoratedUrlAbout->addImage(new GoogleImage($this->cacheManager->resolve('assets/images/logo.jpg','webp')));

209
templates/members.twig Normal file
View File

@@ -0,0 +1,209 @@
{% extends 'base.twig' %}
{% block title %}{{'members_page.title'|trans}}{% endblock %}
{% block canonical_url %}<link rel="canonical" href="{{ url('app_members') }}" />{% endblock %}
{% block breadcrumb_schema %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "{{ 'breadcrumb.home'|trans }}",
"item": "{{ app.request.schemeAndHttpHost }}"
},
{
"@type": "ListItem",
"position": 2,
"name": "{{'members_page.breadcrumb'|trans}}",
"item": "{{ app.request.schemeAndHttpHost }}{{ app.request.pathInfo }}"
}
]
}
</script>
{% endblock %}
{% block body %}
<div class="container mx-auto p-4 md:p-8 pt-12">
<h1 class="text-4xl font-extrabold text-center mb-12 text-gray-800">
{{ 'members_page.title'|trans }}
</h1>
{# --- SECTION 1 : Membres du Bureau --- #}
<section class="mb-16">
<h2 class="text-3xl font-bold border-b pb-4 mb-8 text-indigo-700">
{{ 'members_page.board_title'|trans }}
</h2>
{% if board_members is defined and board_members|length > 0 %}
{# Grille de 3 colonnes sur les grands écrans #}
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 gap-8">
{% for member in board_members %}
{# Début de la carte du membre (Bureau) #}
<div class="bg-white p-6 rounded-xl shadow-lg border border-gray-100 hover:shadow-xl transition duration-300 transform hover:scale-[1.02] flex flex-col">
{# Photo et Pseudo #}
<div class="text-center mb-4">
<img src="{{ member.photo_url|default('placeholder.jpg') }}" alt="Photo de {{ member.pseudo }}" class="w-24 h-24 mx-auto rounded-full object-cover border-4 border-indigo-200 shadow-md">
<h3 class="text-xl font-bold mt-3 text-gray-800">{{ member.pseudo }}</h3>
</div>
{# Rôle #}
<div class="space-y-3 flex-grow border-t pt-4 mb-3">
<p class="text-sm">
<strong class="font-semibold text-indigo-600">{{ 'member_card.role'|trans }}:</strong>
<span class="text-gray-700">{{ member.role|default('-')|trans }}</span>
</p>
</div>
{# BADGE Cosplayer #}
<div class="mb-4">
<strong class="text-sm font-semibold text-gray-800 mr-2">{{ 'member_card.cosplay_label'|trans }}:</strong>
{% if member.cosplayer %}
<span class="inline-flex items-center px-3 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
{{ 'member_card.yes'|trans }}
</span>
{% else %}
<span class="inline-flex items-center px-3 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600">
{{ 'member_card.no'|trans }}
</span>
{% endif %}
</div>
{# BADGES Spécificités #}
{# BADGES Spécificités (Mis à jour pour n'afficher que les statuts VRAIS) #}
<div class="space-y-2 pt-3 border-t">
<p class="text-xs text-gray-500 font-semibold uppercase">{{ 'member_card.specifics'|trans }}</p>
<div class="flex flex-wrap gap-2">
{# Badge Crosscosplayer : Affiché uniquement si VRAI #}
{% if member.crosscosplayer %}
<span class="inline-flex items-center px-3 py-0.5 rounded-full text-xs font-medium bg-indigo-100 text-indigo-800">
{{ 'member_card.crosscosplay'|trans }}
</span>
{% endif %}
{# Badge Transgenre : Affiché uniquement si VRAI #}
{% if member.trans %}
<span class="inline-flex items-center px-3 py-0.5 rounded-full text-xs font-medium bg-pink-100 text-pink-800">
{{ 'member_card.trans'|trans }}
</span>
{% endif %}
{# Badge Orientation (toujours affiché, avec couleur conditionnelle) #}
{% set orientation_key = member.orientation ? 'orientation.' ~ member.orientation : null %}
{% set orientation_text = orientation_key ? orientation_key|trans : 'member_card.not_specified'|trans %}
{% set orientation_color = orientation_key ? 'bg-purple-100 text-purple-800' : 'bg-gray-100 text-gray-600' %}
<span class="inline-flex items-center px-3 py-0.5 rounded-full text-xs font-medium {{ orientation_color }}">
{{ 'member_card.orientation_label'|trans }}: {{ orientation_text }}
</span>
</div>
</div>
</div>
{# Fin de la carte du membre (Bureau) #}
{% endfor %}
</div>
{% else %}
<p class="text-center text-gray-600 p-6 border rounded-lg bg-gray-50">
{{ 'members_page.board_empty'|trans }}
</p>
{% endif %}
</section>
{# --- SECTION 2 : Tous les autres Membres --- #}
<section>
<h2 class="text-3xl font-bold border-b pb-4 mb-8 text-indigo-700">
{{ 'members_page.all_title'|trans }}
</h2>
{% if members is defined and members|length > 0 %}
{# Grille de 3 colonnes sur les grands écrans #}
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 gap-8">
{% for member in members %}
{# Début de la carte du membre (Général) #}
<div class="bg-white p-6 rounded-xl shadow-lg border border-gray-100 hover:shadow-xl transition duration-300 transform hover:scale-[1.02] flex flex-col">
{# Photo et Pseudo #}
<div class="text-center mb-4">
<img src="{{ member.photo_url | imagine_filter('filter')}} ) }}" alt="Photo de {{ member.pseudo }}" class="w-24 h-24 mx-auto rounded-full object-cover border-4 border-indigo-200 shadow-md">
<h3 class="text-xl font-bold mt-3 text-gray-800">{{ member.pseudo }}</h3>
</div>
{# Rôle #}
<div class="space-y-3 flex-grow border-t pt-4 mb-3">
<p class="text-sm">
<strong class="font-semibold text-indigo-600">{{ 'member_card.role'|trans }}:</strong>
<span class="text-gray-700">{{ member.role|default('-')|trans }}</span>
</p>
</div>
{# BADGE Cosplayer #}
<div class="mb-4">
<strong class="text-sm font-semibold text-gray-800 mr-2">{{ 'member_card.cosplay_label'|trans }}:</strong>
{% if member.cosplayer %}
<span class="inline-flex items-center px-3 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
{{ 'member_card.yes'|trans }}
</span>
{% else %}
<span class="inline-flex items-center px-3 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600">
{{ 'member_card.no'|trans }}
</span>
{% endif %}
</div>
{# BADGES Spécificités #}
{# BADGES Spécificités (Mis à jour pour n'afficher que les statuts VRAIS) #}
<div class="space-y-2 pt-3 border-t">
<p class="text-xs text-gray-500 font-semibold uppercase">{{ 'member_card.specifics'|trans }}</p>
<div class="flex flex-wrap gap-2">
{# Badge Crosscosplayer : Affiché uniquement si VRAI #}
{% if member.crosscosplayer %}
<span class="inline-flex items-center px-3 py-0.5 rounded-full text-xs font-medium bg-indigo-100 text-indigo-800">
{{ 'member_card.crosscosplay'|trans }}
</span>
{% endif %}
{# Badge Transgenre : Affiché uniquement si VRAI #}
{% if member.trans %}
<span class="inline-flex items-center px-3 py-0.5 rounded-full text-xs font-medium bg-pink-100 text-pink-800">
{{ 'member_card.trans'|trans }}
</span>
{% endif %}
{# Badge Orientation (toujours affiché, avec couleur conditionnelle) #}
{% set orientation_key = member.orientation ? 'orientation.' ~ member.orientation : null %}
{% set orientation_text = orientation_key ? orientation_key|trans : 'member_card.not_specified'|trans %}
{% set orientation_color = orientation_key ? 'bg-purple-100 text-purple-800' : 'bg-gray-100 text-gray-600' %}
<span class="inline-flex items-center px-3 py-0.5 rounded-full text-xs font-medium {{ orientation_color }}">
{{ 'member_card.orientation_label'|trans }}: {{ orientation_text }}
</span>
</div>
</div>
</div>
{# Fin de la carte du membre (Général) #}
{% endfor %}
</div>
{% else %}
<p class="text-center text-gray-600 p-6 border rounded-lg bg-gray-50">
{{ 'members_page.all_empty'|trans }}
</p>
{% endif %}
</section>
</div>
{% endblock %}

View File

@@ -447,3 +447,35 @@ contact_form.tel.label: "Phone (optional)"
contact_form.tel.placeholder: "Ex: 555-123-4567"
contact_form.message.label: "Your message"
contact_form.message.placeholder: "Type your question or request..."
members_title: 'Membres'
# --- MEMBERS PAGE (members.twig) ---
members_page.title: "Our Members & Board"
members_page.breadcrumb: "Members"
members_page.board_title: "Board Members"
members_page.board_empty: "The list of board members will be available soon."
members_page.all_title: "All Members"
members_page.all_empty: "No members have been found at this time."
# MEMBER CARD KEYS (Badges and Labels)
member_card.role: "Role"
member_card.cosplay_label: "Cosplayer"
member_card.yes: "Yes"
member_card.no: "No"
member_card.specifics: "Specifics"
member_card.crosscosplay: "Crosscosplayer"
member_card.trans: "Transgender"
member_card.orientation_label: "Orientation"
member_card.not_specified: "Not specified"
# --- SEXUAL ORIENTATIONS ---
orientation.asexual: "Asexual"
orientation.bisexual: "Bisexual"
orientation.demisexual: "Demisexual"
orientation.gay: "Gay"
orientation.heterosexual: "Heterosexual"
orientation.lesbian: "Lesbian"
orientation.pansexual: "Pansexual"
orientation.queer: "Queer"
orientation.questioning: "Questioning"
orientation.other: "Other"

View File

@@ -440,3 +440,32 @@ contact_form.subject.label: "Sujet"
contact_form.tel.label: "Téléphone (facultatif)"
contact_form.message.label: "Votre message"
form_email_label: "Adresse e-mail"
members_page.title: "Nos Membres & Bureau"
members_page.breadcrumb: "Membres"
members_page.board_title: "Membres du Bureau"
members_page.board_empty: "La liste des membres du bureau sera bientôt disponible."
members_page.all_title: "Tous les Membres"
members_page.all_empty: "Aucun membre n'a été trouvé pour le moment."
members_title: 'Membres'
# CLÉS DANS LA FICHE DE MEMBRE (Badges et Labels)
member_card.role: "Rôle"
member_card.cosplay_label: "Cosplayer"
member_card.yes: "Oui"
member_card.no: "Non"
member_card.specifics: "Spécificités"
member_card.crosscosplay: "Crosscosplayer"
member_card.trans: "Transgenre"
member_card.orientation_label: "Orientation"
member_card.not_specified: "Non spécifié"
orientation.asexual: "Asexuel(le)"
orientation.bisexual: "Bisexuel(le)"
orientation.demisexual: "Demisexuel(le)"
orientation.gay: "Gay"
orientation.heterosexual: "Hétérosexuel(le)"
orientation.lesbian: "Lesbienne"
orientation.pansexual: "Pansexuel(le)"
orientation.queer: "Queer"
orientation.questioning: "En questionnement"
orientation.other: "Autre"