Files
echo-du-huit/extension/presentation.js
T
Pierre MartinandClaude Opus 4.8 3d86330894 feat: list upcoming events with a create button
The list page now parses the calendar feed and renders each upcoming
event (title, date, place) in chronological order, with a button that
hands the event over to the town hall form.

Sorting, date formatting and the café fallback live in a pure
presentation module rather than in liste.js, which touches the DOM and
cannot be imported under bun test. The seam to the sibling task's
content script lives in transfert.js: a single storage slot, since a
content script running on the town hall site has no way to learn a uid.
The deposit is awaited before opening the tab, otherwise the content
script could read before the write lands.

Test timezone is pinned to Europe/Paris: date formatting is the core
logic here and would otherwise pass only on machines set to Paris.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 18:23:38 +02:00

43 lines
1.7 KiB
JavaScript

// Présentation des Event pour la liste : ordre, formatage date, défaut lieu.
// Fonctions pures, sans DOM (testables). Locale et fuseau sont des constantes :
// l'appli est mono-locale (bénévoles de Cugnaux).
const LOCALE = "fr-FR";
const FUSEAU = "Europe/Paris";
// RECHERCHE.md §2 : adresse du café de l'Atelier du Huit.
export const LIEU_PAR_DEFAUT = "8 Rue du Pré Vicinal 31270 Cugnaux";
// Un événement horodaté porte un vrai instant : on l'affiche à l'heure de
// Cugnaux, quel que soit le fuseau de la machine.
const FORMAT_AVEC_HEURE = new Intl.DateTimeFormat(LOCALE, {
timeZone: FUSEAU,
dateStyle: "full",
timeStyle: "short",
});
// Sans timeZone, DÉLIBÉRÉMENT (ne pas « rétablir » FUSEAU ici) : une journée
// entière est une date *flottante* (RFC 5545), sans fuseau. ical.js la
// matérialise à minuit local ; la relire en local restitue le bon jour partout,
// alors que la convertir vers Paris la ferait glisser au 9 depuis Tokyo.
const FORMAT_SANS_HEURE = new Intl.DateTimeFormat(LOCALE, {
dateStyle: "full",
});
// Le parseur rend l'ordre du flux : l'ordre chronologique se décide ici.
export function trierParDebut(evenements) {
return [...evenements].sort((a, b) => a.debut.getTime() - b.debut.getTime());
}
// Une journée entière n'a pas d'heure : afficher « 00:00 » serait un mensonge.
export function formaterDate(evenement) {
const format = evenement.journeeEntiere ? FORMAT_SANS_HEURE : FORMAT_AVEC_HEURE;
return format.format(evenement.debut);
}
// La plupart des événements se tiennent au café et n'ont pas de LOCATION :
// afficher l'adresse par défaut plutôt qu'une ligne vide.
export function formaterLieu(evenement) {
return evenement.lieu.trim() || LIEU_PAR_DEFAUT;
}