card cosmo ambient

This commit is contained in:
2026-02-21 20:59:56 +04:00
parent 3f2fcdb5d7
commit c4dc5c4588
4 changed files with 398 additions and 165 deletions

View File

@@ -2,17 +2,26 @@
import { getCollection } from "astro:content";
import Layout from "../layouts/Layout.astro";
import Card from "../components/Card.astro";
import EventCard from "../components/EventCard.astro";
const allHumans = await getCollection("humans");
// 1. Récupération des deux types de contenu
const allHumans = await getCollection("humans", ({ id }) => {
return id.startsWith("latchimynicolas/");
});
const allEvents = await getCollection("events");
// 1. Tri par date décroissante
// 2. Tri par date décroissante pour les humains
const sortedAll = allHumans.sort(
(a, b) => new Date(b.data.date).getTime() - new Date(a.data.date).getTime(),
);
// 2. Fonction de calcul de Streak (Série) corrigée
// 3. Récupération du dernier événement (ex: Camping Châteauroux)
const latestEvent = allEvents.sort(
(a, b) => new Date(b.data.date).getTime() - new Date(a.data.date).getTime(),
)[0];
// 4. Fonction de calcul de Streak (Série) [cite: 94]
const getStreak = (name, entries) => {
// 1. On récupère les données utiles (date + si HYG était présent)
const userDates = entries
.filter((e) => e.data.name === name)
.map((e) => ({
@@ -21,13 +30,11 @@ const getStreak = (name, entries) => {
e.data.manifestations?.some((m) => m.cercle === "HYG") || false,
}));
// On dédoublonne et on trie (plus récent au plus ancien)
const uniqueDates = [...new Set(userDates)].sort().reverse();
const uniqueDates = [...new Set(userDates.map((d) => d.date))]
.sort()
.reverse();
let streak = 0;
let hygCountLast7Days = 0;
let today = new Date();
// On cale la date de vérification sur aujourd'hui à minuit
let checkDate = new Date(
today.getFullYear(),
today.getMonth(),
@@ -36,12 +43,10 @@ const getStreak = (name, entries) => {
for (let i = 0; i < 31; i++) {
const dateStr = checkDate.toISOString().split("T")[0];
if (uniqueDates.includes(dateStr)) {
streak++;
checkDate.setDate(checkDate.getDate() - 1);
} else {
// Tolérance : si pas de note aujourd'hui, on vérifie si la série continue depuis hier
if (i === 0) {
checkDate.setDate(checkDate.getDate() - 1);
const yesterdayStr = checkDate.toISOString().split("T")[0];
@@ -51,33 +56,26 @@ const getStreak = (name, entries) => {
}
}
// 2. Logique Malus HYG (7 derniers jours glissants)
const last7Days = [];
for (let j = 0; j < 7; j++) {
// Malus HYG [cite: 103, 106]
const last7Days = Array.from({ length: 7 }, (_, j) => {
let d = new Date();
d.setDate(d.getDate() - j);
last7Days.push(d.toISOString().split("T")[0]);
}
return d.toISOString().split("T")[0];
});
hygCountLast7Days = userDates.filter(
const hygCount = userDates.filter(
(e) => last7Days.includes(e.date) && e.hasHyg,
).length;
// Si moins de 3 sessions HYG sur les 7 derniers jours, malus de 1
if (hygCountLast7Days < 3 && streak > 0) {
streak = Math.max(0, streak - 1);
}
if (hygCount < 3 && streak > 0) streak = Math.max(0, streak - 1);
return streak;
};
// 3. Unicité par utilisateur pour l'affichage (dernière version de chaque profil)
// 5. Unicité par utilisateur [cite: 107]
const latestPerUser = Array.from(
sortedAll
.reduce((map, obj) => {
if (!map.has(obj.data.name)) {
map.set(obj.data.name, obj);
}
if (!map.has(obj.data.name)) map.set(obj.data.name, obj);
return map;
}, new Map())
.values(),
@@ -95,11 +93,10 @@ const latestPerUser = Array.from(
</header>
<main class="hero-flex">
{/* Affichage des cartes Humains (Hebel) [cite: 110] */}
{
latestPerUser.map((entry) => {
// On calcule la streak ICI pour l'envoyer à la carte
const currentStreak = getStreak(entry.data.name, allHumans);
return (
<div class="card-focus">
<Card
@@ -118,10 +115,23 @@ const latestPerUser = Array.from(
);
})
}
{/* Insertion de la carte Événement */}
{
latestEvent && (
<div class="card-focus">
<EventCard frontmatter={latestEvent.data} />
<div class="entry-meta">
<p>Projet Communautaire</p>
</div>
</div>
)
}
</main>
</Layout>
<style>
/* Tes styles restent identiques pour préserver la mise en page [cite: 115, 119, 120] */
.minimal-header {
position: fixed;
top: 50px;