Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions src/Controller/HistoriqueAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);

namespace App\Controller;

use App\Dto\Antenne;
use App\Dto\Meetup;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

#[Route(
path: '/historique/{year?}',
name: 'historique',
host: '{code}.afup.org',
)]
#[Route(
path: '/{code?}/historique/{year?}',
name: 'historique',
env: 'dev',
)]
final class HistoriqueAction extends AbstractController
{
public function __invoke(Antenne $antenne, int|string|null $year): Response
{
if ($year === null) {
$year = (int) date('Y');
} elseif ($year !== 'anciens') {
$year = (int) $year;
}

$selectedMeetups = [];

$years = [];
foreach ($antenne->meetups as $meetup) {
$meetupYear = (int) $meetup->date->format('Y');

$years[$meetupYear] = true;

if (is_int($year) && $meetupYear === $year) {
$selectedMeetups[] = $meetup;
}
}

$years = array_keys($years);
rsort($years);

$recentYears = array_slice($years, 0, 10);
$olderYears = array_slice($years, 10);

if (count($olderYears) > 0) {
$recentYears[] = 'anciens';
}

if ($year === 'anciens') {
$selectedMeetups = array_filter(
$antenne->meetups,
fn(Meetup $m) => in_array((int) $m->date->format('Y'), $olderYears),
);
}

usort($selectedMeetups, fn(Meetup $a, Meetup $b) => $b->date <=> $a->date);

return $this->render('historique.html.twig', [
'antenne' => $antenne,
'selectedYear' => $year,
'years' => $recentYears,
'selectedMeetups' => $selectedMeetups,
]);
}
}
2 changes: 2 additions & 0 deletions src/Controller/IndexAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@

#[Route(
path: '/',
name: 'home',
host: '{code}.afup.org',
)]
#[Route(
path: '/{code?}',
name: 'home',
env: 'dev',
)]
final class IndexAction extends AbstractController
Expand Down
2 changes: 2 additions & 0 deletions src/Dto/Antenne.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public function __construct(
public string $label,
public Logo $logo,
public Links $links,
/** @var array<Meetup> $meetups */
public array $meetups,
public ?Meetup $nextMeetup = null,
) {}
}
3 changes: 2 additions & 1 deletion src/Dto/Meetup.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
public function __construct(
public string $title,
public \DateTimeImmutable $date,
public string $location,
public ?string $location,
public string $description,
public string $url,
public ?string $photo,
) {}
}
45 changes: 42 additions & 3 deletions templates/base.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="x-ua-compatible" content="ie=edge">

<title>{% block title %}AFUP - Antennes{% endblock %}</title>
<title>AFUP {{ antenne.label }}</title>

{% block favicon %}
<link rel="icon" href="{{ asset('logos/afup.svg') }}" sizes="any" type="image/svg+xml">
<link rel="icon" href="{{ antenne.logo.simple }}" sizes="any" type="image/svg+xml">
{% endblock %}

{% block head %}{% endblock %}

<meta property="og:type" content="website">
<meta property="og:url" content="https://{{ antenne.code }}.afup.org">
<meta property="og:title" content="AFUP {{ antenne.label }}">
<meta property="og:description" content="Site de l'antenne AFUP {{ antenne.label }}">
<meta property="og:site_name" content="AFUP {{ antenne.label }}">

{% block stylesheets %}
<link rel="stylesheet" href="{{ asset('styles/app.css') }}">
{% endblock %}
Expand All @@ -26,7 +32,40 @@

<div class="min-h-screen flex flex-col backdrop-blur-sm">

{% block body %}{% endblock %}
<main class="container mx-auto max-w-96 sm:max-w-none">
<div class="px-5 pt-10 md:pt-20 pb-5 md:pb-10">
<div class="mx-auto sm:max-w-3xl">
<a href="{{ path('home', { code: antenne.code }) }}">
<img src="{{ asset('logos/afup-antenne-' ~ antenne.code ~ '.svg') }}"
class="drop-shadow-lg"
alt="Logo de l'antenne AFUP {{ antenne.label }}"/>
</a>
</div>
</div>

<div class="text-white text-center p-4 sm:p-0 pb-4 sm:pb-10 text-xl sm:text-2xl md:block flex justify-around items-center gap-3">
<a href="https://afup.org" class="hover:underline">afup.org</a>
<span class="md:px-3">
<twig:ux:icon name="separator" class="h-5 inline-block" />
</span>
<a href="https://afup.org/association/devenir-membre" class="hover:underline">Adhérer</a>
<span class="md:px-3">
<twig:ux:icon name="separator" class="h-5 inline-block" />
</span>
<a href="{{ path('historique', { code: antenne.code }) }}" class="hover:underline">Historique</a>
</div>

{% block body %}{% endblock %}

</main>

<footer class="mt-auto pb-4 px-5 text-slate-50 text-xs sm:text-sm flex justify-between">
<a href="https://github.com/afup/antennes" class="hover:underline">Code source</a>

<span>
Hébergé sur <a href="https://clever.cloud" class="hover:underline">Clever Cloud</a>
</span>
</footer>

</div>

Expand Down
52 changes: 52 additions & 0 deletions templates/historique.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{% extends 'base.html.twig' %}

{% block body %}

<div class="sm:mx-auto sm:max-w-5xl sm:flex flex-col p-4 sm:p-0">

<nav class="text-white mb-5 text-2xl border-b w-full flex items-start overflow-x-auto md:overflow-hidden">
<ul class="flex flex-nowrap items-end text-heading gap-4 md:gap-8">
{% for year in years %}
<li class="{% if selectedYear != year or selectedYear == 'anciens' %}hover:border-b-2{% endif %}">
<a href="{{ path('historique', { code: antenne.code, year: year }) }}"
class="{% if selectedYear == year %}font-black text-3xl md:text-4xl{% endif %}">{{ year|capitalize }}</a>
</li>
{% endfor %}
</ul>
</nav>

<main class="flex flex-col gap-5 mb-5 md:mb-0">
{% for meetup in selectedMeetups %}
<article class="group relative flex flex-col bg-white p-5 rounded shadow-xl gap-5 cursor-pointer transition-transform hover:-translate-y-0.5">
<a href="{{ meetup.url }}" class="absolute inset-0" aria-label="{{ meetup.title }}"></a>
<input type="checkbox" id="desc-{{ loop.index }}" class="hidden peer">
<div class="flex flex-col md:flex-row gap-5">
{% if meetup.photo %}
<img class="w-full rounded md:object-cover md:h-40 md:w-3xs shrink-0" src="{{ meetup.photo }}" alt="">
{% endif %}
<header class="flex flex-col flex-1">
<h5 class="text-2xl font-bold tracking-tight">{{ meetup.title }}</h5>
<small>
{{ meetup.date|format_datetime(pattern: 'EEEE d LLLL à H:mm', locale: 'fr') }}
{% if selectedYear == 'anciens' %}
{{ meetup.date.format('Y') }}
{% endif %}
</small>
<label for="desc-{{ loop.index }}"
class="relative z-10 cursor-pointer inline-block mt-auto pt-2 underline">
<span class="group-has-[:checked]:hidden">Voir la description</span>
<span class="hidden group-has-[:checked]:inline">Masquer la description</span>
</label>
</header>
</div>

<div class="hidden peer-checked:block">
{{ meetup.description|nl2br|markdown_to_html }}
</div>
</article>
{% endfor %}
</main>

</div>

{% endblock %}
98 changes: 29 additions & 69 deletions templates/index.html.twig
Original file line number Diff line number Diff line change
@@ -1,84 +1,44 @@
{% extends 'base.html.twig' %}

{% block title %}AFUP {{ antenne.label }}{% endblock %}

{% block favicon %}
<link rel="icon" href="{{ antenne.logo.simple }}" sizes="any" type="image/svg+xml">
{% endblock %}

{% block head %}

<meta property="og:type" content="website">
<meta property="og:url" content="https://{{ antenne.code }}.afup.org">
<meta property="og:title" content="AFUP {{ antenne.label }}">
<meta property="og:description" content="Site de l'antenne AFUP {{ antenne.label }}">
<meta property="og:site_name" content="AFUP {{ antenne.label }}">

{% endblock %}

{% block body %}

<main class="container mx-auto max-w-96 sm:max-w-none">
<div class="px-5 pt-20 pb-10">
<img src="{{ asset('logos/afup-antenne-' ~ antenne.code ~ '.svg') }}"
class="mx-auto sm:max-w-3xl drop-shadow-lg"
alt="Logo de l'antenne AFUP {{ antenne.label }}"/>
</div>

<div class="text-white text-center pb-5 sm:pb-10 text-xl sm:text-2xl">
<a href="https://afup.org" class="hover:underline">afup.org</a>
<span class="px-3">
<twig:ux:icon name="separator" class="h-5 inline-block" />
</span>
<a href="https://afup.org/association/devenir-membre" class="hover:underline">Devenir membre</a>
</div>

<div class="sm:mx-auto sm:max-w-5xl sm:flex">
<div class="sm:mx-auto sm:max-w-80 p-4 sm:p-0 flex flex-col gap-4 grow">
<twig:Link url="{{ antenne.links.meetup }}" icon="meetup">Meetup</twig:Link>
<div class="sm:mx-auto sm:max-w-5xl sm:flex">
<div class="sm:mx-auto sm:max-w-80 p-4 sm:p-0 flex flex-col gap-4 grow">
<twig:Link url="{{ antenne.links.meetup }}" icon="meetup">Meetup</twig:Link>

{% if antenne.links.linkedin %}
<twig:Link url="{{ antenne.links.linkedin }}" icon="linkedin">LinkedIn</twig:Link>
{% endif %}
{% if antenne.links.linkedin %}
<twig:Link url="{{ antenne.links.linkedin }}" icon="linkedin">LinkedIn</twig:Link>
{% endif %}

{% if antenne.links.bluesky %}
<twig:Link url="{{ antenne.links.bluesky }}" icon="bluesky">Bluesky</twig:Link>
{% endif %}
{% if antenne.links.bluesky %}
<twig:Link url="{{ antenne.links.bluesky }}" icon="bluesky">Bluesky</twig:Link>
{% endif %}

<hr class="border-t-white border-t-2 mx-32"/>
<hr class="border-t-white border-t-2 mx-32"/>

<twig:Link url="https://event.afup.org" icon="event" data-qa="current-event">{{ currentEvent }}</twig:Link>
</div>
<twig:Link url="https://event.afup.org" icon="event" data-qa="current-event">{{ currentEvent }}</twig:Link>
</div>

{% if antenne.nextMeetup %}
<div class="sm:mx-auto max-w-2xl px-5 pb-12 pt-3 sm:pt-0 text-white sm:block grow">
<div class="border-b-12 mb-4 flex flex-col sm:flex-row sm:items-end drop-shadow-lg">
<h2 class="text-3xl grow">Prochain meetup</h2>
<small>{{ antenne.nextMeetup.date|format_datetime(pattern: 'EEEE d LLLL à H:mm', locale: 'fr') }}</small>
</div>
{% if antenne.nextMeetup %}
<div class="sm:mx-auto max-w-2xl px-5 pb-12 pt-3 sm:pt-0 text-white sm:block grow">
<div class="border-b-12 mb-4 flex flex-col sm:flex-row sm:items-end drop-shadow-lg">
<h2 class="text-3xl grow">Prochain meetup</h2>
<small>{{ antenne.nextMeetup.date|format_datetime(pattern: 'EEEE d LLLL à H:mm', locale: 'fr') }}</small>
</div>

<a href="{{ antenne.nextMeetup.url }}" class="hover:underline italic">
<h3 class="text-xl">{{ antenne.nextMeetup.title }}</h3>
</a>
<a href="{{ antenne.nextMeetup.url }}" class="hover:underline italic">
<h3 class="text-xl">{{ antenne.nextMeetup.title }}</h3>
</a>

<div class="pt-5 text-slate-100">{{ antenne.nextMeetup.description|nl2br|markdown_to_html }}</div>
<div class="pt-5 text-slate-100">{{ antenne.nextMeetup.description|nl2br|markdown_to_html }}</div>

<div class="max-w-96 mt-6">
<twig:Link url="{{ antenne.nextMeetup.url }}">
Rejoindre<span class="inline sm:hidden"> le prochain meetup</span>
</twig:Link>
</div>
<div class="max-w-96 mt-6">
<twig:Link url="{{ antenne.nextMeetup.url }}">
Rejoindre<span class="inline sm:hidden"> le prochain meetup</span>
</twig:Link>
</div>
{% endif %}
</div>
</main>

<footer class="mt-auto pb-4 px-5 text-slate-50 text-xs sm:text-sm flex justify-between">
<a href="https://github.com/afup/antennes" class="hover:underline">Code source</a>

<span>
Hébergé sur <a href="https://clever.cloud" class="hover:underline">Clever Cloud</a>
</span>
</footer>
</div>
{% endif %}
</div>

{% endblock %}
4 changes: 4 additions & 0 deletions tests/MockClientCallback.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public function __invoke(string $method, string $url, array $options = []): Resp
'linkedin' => 'https://linkedin.example/lyon',
'bluesky' => 'https://bluesky.example/lyon',
],
'photo' => 'https://photo.example/lyon.jpeg',
'meetups' => [],
]);
}

Expand All @@ -42,6 +44,8 @@ public function __invoke(string $method, string $url, array $options = []): Resp
'linkedin' => null,
'bluesky' => null,
],
'photo' => 'https://photo.example/bordeaux.jpeg',
'meetups' => [],
]);
}

Expand Down