Améliore les modales et les informations du site

This commit is contained in:
Michael committed 2026-07-17 09:00:29 +02:00
1 parent b0154d6fc1
commit b4c8967a3c
9 files changed
+268 -24

No files matched your search

+1 -1
View File
@@ -57,7 +57,7 @@ export default async function PromotionsPage() {
</div>
)}
<div className="grid grid-3" style={{ gap: 18 }}>
<div className="grid grid-3" style={{ gap: 18, width: "100%", maxWidth: 1096 }}>
{ordered.map((p) => {
const isPending = p.status === "pending";
return (
+58
View File
@@ -0,0 +1,58 @@
import type { Metadata } from "next";
import { LegalPage } from "@/components/LegalPage";
export const metadata: Metadata = {
title: "Confidentialité — Plein R",
description: "Politique de confidentialité et traitement des données personnelles par Plein R.",
};
export default function ConfidentialitePage() {
return (
<LegalPage title="Confidentialité" intro="Cette page explique quelles données sont recueillies et comment Plein R les utilise.">
<h2>Données recueillies</h2>
<p>Selon votre utilisation du site, Plein R peut recevoir :</p>
<ul>
<li>vos nom, e-mail, téléphone et message lors d’une prise de contact ou demande d’adhésion ;</li>
<li>les informations professionnelles publiées dans l’annuaire et les promotions ;</li>
<li>les données nécessaires à la connexion et à la sécurisation des espaces privés.</li>
</ul>
<h2>Finalités</h2>
<p>
Ces données servent à répondre aux demandes, gérer les adhésions, administrer l’annuaire,
modérer les promotions et sécuriser l’accès aux comptes. Elles ne sont pas vendues à des tiers.
</p>
<h2>Responsable, bases légales et destinataires</h2>
<p>
Plein R est responsable des traitements réalisés par ce site. Les traitements reposent, selon le cas,
sur les démarches précontractuelles liées à l’adhésion, l’exécution de la relation avec les adhérents,
l’intérêt légitime de l’association à répondre aux demandes et administrer son réseau, ou une obligation légale.
</p>
<p>
Seules les personnes habilitées au sein de Plein R et les prestataires techniques nécessaires au fonctionnement
du site peuvent accéder aux données, dans la limite de leurs missions.
</p>
<h2>Durée et sécurité</h2>
<p>
Les données sont conservées pendant la durée nécessaire au traitement demandé, à la gestion de la relation
avec l’association et au respect de ses obligations. Des mesures adaptées limitent accès, perte ou divulgation non autorisée.
</p>
<h2>Cookies</h2>
<p>
Le site utilise uniquement les éléments techniques nécessaires à son fonctionnement, notamment pour maintenir
une session sécurisée dans l’espace adhérent ou l’administration.
</p>
<h2>Vos droits</h2>
<p>
Vous pouvez demander accès, rectification, effacement, limitation, opposition ou portabilité concernant vos données,
selon les conditions prévues par la réglementation.
Envoyez votre demande via le formulaire « Nous contacter » en précisant votre identité et l’objet de votre demande.
</p>
<p>Vous pouvez également saisir la CNIL si vous estimez que vos droits ne sont pas respectés.</p>
</LegalPage>
);
}
+73
View File
@@ -237,6 +237,69 @@ button {
align-items: start;
}
/* ---- Public footer & legal pages ---- */
.footer-grid {
display: grid;
grid-template-columns: minmax(280px, 1.8fr) 1fr 1fr;
gap: 48px;
align-items: start;
}
.footer-title {
font-family: "Bricolage Grotesque", "Public Sans", system-ui, sans-serif;
color: var(--ink-strong);
font-size: 13px;
font-weight: 800;
margin: 3px 0 11px;
}
.footer-links {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 8px;
color: var(--muted);
font-size: 13px;
}
.footer-links a,
.footer-links button {
text-decoration: none;
cursor: pointer;
}
.footer-links a:hover,
.footer-links button:hover {
color: var(--brown) !important;
text-decoration: underline;
}
.footer-bottom {
display: flex;
justify-content: space-between;
gap: 16px;
flex-wrap: wrap;
border-top: 1px solid #ded2b9;
margin-top: 26px;
padding-top: 18px;
color: var(--muted-2);
font-size: 12.5px;
}
.legal-content h2 {
font-family: "Bricolage Grotesque", "Public Sans", system-ui, sans-serif;
color: var(--ink-strong);
font-size: 20px;
margin: 28px 0 8px;
}
.legal-content p,
.legal-content li {
color: var(--muted);
font-size: 14.5px;
line-height: 1.75;
}
.legal-content p {
margin: 0 0 12px;
}
.legal-content ul {
margin: 8px 0 14px;
padding-left: 20px;
}
@media (max-width: 1024px) {
.grid-6 {
grid-template-columns: repeat(3, 1fr);
@@ -263,6 +326,10 @@ button {
.grid-2 {
grid-template-columns: 1fr;
}
.footer-grid {
grid-template-columns: 1.5fr 1fr 1fr;
gap: 28px;
}
}
@media (max-width: 640px) {
.grid-6,
@@ -273,6 +340,12 @@ button {
.container {
padding: 0 16px;
}
.footer-grid {
grid-template-columns: 1fr 1fr;
}
.footer-grid > :first-child {
grid-column: 1 / -1;
}
}
/* Évite tout débordement horizontal sur mobile. */
+43
View File
@@ -0,0 +1,43 @@
import type { Metadata } from "next";
import { LegalPage } from "@/components/LegalPage";
export const metadata: Metadata = {
title: "Mentions légales — Plein R",
description: "Mentions légales du site de l'association Plein R.",
};
export default function MentionsLegalesPage() {
return (
<LegalPage title="Mentions légales" intro="Informations relatives à l’édition et à l’utilisation du site Plein R.">
<h2>Éditeur du site</h2>
<p>
Ce site est édité par Plein R, association des commerçants et entreprises du Bassin de Pompey.
</p>
<ul>
<li>Siège social : à compléter par l’association</li>
<li>Numéro RNA et, le cas échéant, SIREN : à compléter par l’association</li>
<li>Direction de la publication : à compléter par l’association</li>
</ul>
<p>Pour contacter Plein R, utilisez le formulaire « Nous contacter » disponible en pied de page.</p>
<h2>Hébergement</h2>
<p>
Nom, raison sociale, adresse et numéro de téléphone de l’hébergeur : à compléter par l’association
dès que l’hébergement de production est choisi.
</p>
<h2>Propriété intellectuelle</h2>
<p>
Structure, textes, éléments graphiques et identité visuelle du site sont protégés. Toute reproduction,
adaptation ou diffusion sans autorisation préalable de Plein R est interdite, hors exceptions prévues par la loi.
</p>
<p>Logos, images et contenus publiés par les adhérents restent la propriété de leurs titulaires respectifs.</p>
<h2>Responsabilité</h2>
<p>
Plein R veille à la qualité des informations publiées, sans pouvoir garantir leur exhaustivité permanente.
Les offres, coordonnées et contenus des adhérents relèvent de la responsabilité de leurs auteurs.
</p>
</LegalPage>
);
}
+8
View File
@@ -1,6 +1,7 @@
"use client";
import { useState } from "react";
import Link from "next/link";
import { Modal } from "./Modal";
import { submitContactMessage } from "@/app/actions/public";
@@ -74,6 +75,13 @@ export function ContactModalButton({
{error && <div style={errorBox}>{error}</div>}
<p style={{ margin: "0 0 12px", fontSize: 11.5, lineHeight: 1.5, color: "#8c8068" }}>
Vos informations servent uniquement à répondre à votre message. Consultez notre{" "}
<Link href="/confidentialite" target="_blank" rel="noopener noreferrer" style={{ color: "#9a6638", fontWeight: 700 }}>
politique de confidentialité
</Link>.
</p>
<button type="submit" className="lift-cta" disabled={pending} style={{ ...primaryBtn, opacity: pending ? 0.6 : 1 }}>
{pending ? "Envoi…" : "Envoyer le message"}
</button>
+31
View File
@@ -0,0 +1,31 @@
import type { ReactNode } from "react";
import Link from "next/link";
import { SiteFooter } from "./SiteFooter";
import { SiteHeader } from "./SiteHeader";
export function LegalPage({ title, intro, children }: { title: string; intro: string; children: ReactNode }) {
return (
<div style={{ background: "#F6F2E8", minHeight: "100vh", fontFamily: "'Public Sans',sans-serif", color: "#33291D" }}>
<SiteHeader logo />
<main className="container" style={{ paddingTop: 24, paddingBottom: 64 }}>
<Link href="/" style={{ color: "#9a6638", fontSize: 13.5, fontWeight: 700, textDecoration: "none" }}>
← Retour à l&apos;accueil
</Link>
<article
className="legal-content"
style={{ maxWidth: 860, marginTop: 22, background: "#fff", border: "1px solid #e6dcc6", borderRadius: 22, padding: "clamp(24px, 5vw, 48px)", boxShadow: "0 24px 55px -42px rgba(40,30,15,0.55)" }}
>
<div style={{ color: "#9a6638", fontSize: 11.5, letterSpacing: "0.14em", textTransform: "uppercase", fontWeight: 800, marginBottom: 10 }}>
Informations du site
</div>
<h1 className="font-display" style={{ fontSize: "clamp(30px, 6vw, 44px)", letterSpacing: "-0.03em", color: "#26201a", margin: "0 0 12px" }}>
{title}
</h1>
<p style={{ fontSize: 16, maxWidth: 680 }}>{intro}</p>
{children}
</article>
</main>
<SiteFooter />
</div>
);
}
+8
View File
@@ -1,6 +1,7 @@
"use client";
import { useState } from "react";
import Link from "next/link";
import { Modal } from "./Modal";
import { submitMembershipRequest } from "@/app/actions/public";
@@ -75,6 +76,13 @@ export function MembershipModalButton({
{error && <div style={errorBox}>{error}</div>}
<p style={{ margin: "0 0 12px", fontSize: 11.5, lineHeight: 1.5, color: "#8c8068" }}>
Vos informations servent uniquement à traiter votre demande. Consultez notre{" "}
<Link href="/confidentialite" target="_blank" rel="noopener noreferrer" style={{ color: "#9a6638", fontWeight: 700 }}>
politique de confidentialité
</Link>.
</p>
<button type="submit" className="lift-cta" disabled={pending} style={{ ...primaryBtn, opacity: pending ? 0.6 : 1 }}>
{pending ? "Envoi…" : "Envoyer ma demande"}
</button>
+4 -2
View File
@@ -1,6 +1,7 @@
"use client";
import { useEffect } from "react";
import { createPortal } from "react-dom";
export function Modal({
open,
@@ -31,7 +32,7 @@ export function Modal({
if (!open) return null;
return (
return createPortal(
<div
role="dialog"
aria-modal="true"
@@ -88,6 +89,7 @@ export function Modal({
</div>
{children}
</div>
</div>
</div>,
document.body,
);
}
+42 -21
View File
@@ -1,28 +1,49 @@
import Link from "next/link";
import { ContactModalButton } from "./ContactModalButton";
export function SiteFooter() {
const year = new Date().getFullYear();
return (
<footer style={{ background: "#EFE9DA", borderTop: "1px solid #e2d6bd", padding: "28px clamp(16px, 5vw, 56px)" }}>
<div
className="container"
style={{ display: "flex", justifyContent: "flex-end", alignItems: "center" }}
>
<div style={{ fontSize: 13, color: "#8c8068", textAlign: "right", lineHeight: 1.7 }}>
<ContactModalButton
label="Nous contacter"
style={{
background: "none",
border: "none",
padding: 0,
font: "inherit",
color: "#9a6638",
fontWeight: 700,
textDecoration: "underline",
}}
/>
{" · Bassin de Pompey"}
<br />
Réseau · Rencontre · Réussite
<footer style={{ background: "#EFE9DA", borderTop: "1px solid #e2d6bd" }}>
<div className="container" style={{ paddingTop: 34, paddingBottom: 24 }}>
<div className="footer-grid">
<div>
<Link href="/" aria-label="Plein R — accueil" style={{ display: "inline-flex" }}>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src="/assets/logo.png" alt="Plein R" style={{ width: 118, height: "auto", display: "block" }} />
</Link>
<p style={{ margin: "12px 0 0", maxWidth: 370, fontSize: 13.5, lineHeight: 1.65, color: "#6c6150" }}>
Association des commerçants et entreprises du Bassin de Pompey.
Réseau · Rencontre · Réussite.
</p>
</div>
<div>
<div className="footer-title">Accès rapide</div>
<div className="footer-links">
<Link href="/annuaire">Annuaire</Link>
<Link href="/#promotions">Promotions</Link>
<Link href="/login">Connexion</Link>
</div>
</div>
<div>
<div className="footer-title">Informations</div>
<div className="footer-links">
<ContactModalButton
label="Nous contacter"
style={{ background: "none", border: "none", padding: 0, font: "inherit", color: "inherit", textAlign: "left" }}
/>
<Link href="/mentions-legales">Mentions légales</Link>
<Link href="/confidentialite">Confidentialité</Link>
</div>
</div>
</div>
<div className="footer-bottom">
<span>© {year} Plein R. Tous droits réservés.</span>
<span>Bassin de Pompey</span>
</div>
</div>
</footer>