import Link from "next/link"; import { and, asc, desc, eq, gte, sql } from "drizzle-orm"; import { getSession } from "@/lib/session"; import { db } from "@/db"; import { categories, imageConsents, meetingRegistrations, meetings, members, promotions } from "@/db/schema"; import type { Member } from "@/db/schema"; import { memberPath } from "@/lib/seo"; import { ImageField } from "@/components/ImageField"; import { ImageConsentForm } from "@/components/ImageConsentForm"; import { HoursEditor } from "@/components/HoursEditor"; import { TagsField } from "@/components/TagsField"; import { communeOptions } from "@/lib/communes"; import { saveImageConsent, updateOwnProfile } from "../actions"; import { EspaceHeader } from "./EspaceHeader"; export const dynamic = "force-dynamic"; /** Espace adhérent, onglet Profil : fiche publique, inscriptions, droit à l'image. */ export default async function EspacePage() { const session = await getSession(); const memberId = session?.user.memberId ?? null; const fallbackName = session?.user.name ?? "Adhérent"; let memberName = fallbackName; let subtitle = "Espace adhérent"; let profile: Member | null = null; let livePromoCount = 0; let myRegistrations: { meetingId: number; title: string; startsAt: Date; location: string | null; participants: number; confirmed: boolean }[] = []; let latestConsent: { decision: string; createdAt: Date } | null = null; let profileCategory: { slug: string; label: string } | null = null; if (memberId) { const [m] = await db.select().from(members).where(eq(members.id, memberId)); if (m) { profile = m; memberName = m.name; const [cat] = m.categoryId ? await db.select({ slug: categories.slug, label: categories.label }).from(categories).where(eq(categories.id, m.categoryId)) : []; profileCategory = cat ?? null; subtitle = ["Espace adhérent", cat?.label, m.city].filter(Boolean).join(" · "); } const [live] = await db .select({ total: sql`count(*)` }) .from(promotions) .where(and(eq(promotions.memberId, memberId), eq(promotions.status, "live"))); livePromoCount = Number(live?.total ?? 0); myRegistrations = await db .select({ meetingId: meetings.id, title: meetings.title, startsAt: meetings.startsAt, location: meetings.location, participants: sql`count(${meetingRegistrations.id})`, confirmed: sql`bool_and(${meetingRegistrations.status} = 'confirmed')`, }) .from(meetingRegistrations) .innerJoin(meetings, eq(meetings.id, meetingRegistrations.meetingId)) .where(and(eq(meetingRegistrations.memberId, memberId), gte(meetings.startsAt, new Date()))) .groupBy(meetings.id) .orderBy(asc(meetings.startsAt)); const [consent] = await db .select({ decision: imageConsents.decision, createdAt: imageConsents.createdAt }) .from(imageConsents) .where(eq(imageConsents.memberId, memberId)) .orderBy(desc(imageConsents.createdAt)) .limit(1); latestConsent = consent ?? null; } function fmtDate(d: Date) { return new Date(d).toLocaleDateString("fr-FR", { day: "numeric", month: "long" }); } return (
{!memberId && (
Votre compte n'est pas encore relié à une fiche adhérent. Les promotions publiées ne seront pas rattachées à un commerce.
)} {memberId && (

Mes inscriptions

Participants inscrits aux prochaines rencontres.
Voir les rencontres
{myRegistrations.length === 0 &&
Aucune inscription à venir.
}
{myRegistrations.map((registration) => (
{registration.title}
{fmtDate(registration.startsAt)} · {registration.participants} participant{registration.participants > 1 ? "s" : ""}{registration.location ? ` · ${registration.location}` : ""}
{registration.confirmed ? "Confirmée" : "En attente"} Modifier
))}
)} {profile && (

Mon profil

Indépendant de votre identifiant de connexion. Laissé vide, la fiche affiche l'e-mail de votre compte.