feat: add RGPD data export and legal notices page

This commit is contained in:
jessy-david-dev
2026-04-10 23:09:36 +02:00
parent 7f9d58bdf2
commit 76c7967a9a
4 changed files with 229 additions and 0 deletions
+44
View File
@@ -2,6 +2,50 @@ import { NextResponse } from "next/server";
import { auth } from "../../../auth";
import { prisma } from "../../../lib/prisma";
export async function GET() {
const session = await auth();
if (!session?.user?.id) {
return NextResponse.json({ error: "Non connecté" }, { status: 401 });
}
const user = await prisma.user.findUnique({
where: { id: session.user.id },
select: { id: true, name: true, email: true, createdAt: true },
});
const games = await prisma.game.findMany({
where: { userId: session.user.id },
select: {
id: true, mode: true, startArticle: true, targetArticle: true,
path: true, clicks: true, timeSeconds: true, won: true, playedAt: true,
},
orderBy: { playedAt: "desc" },
});
const dailyResults = await prisma.dailyResult.findMany({
where: { userId: session.user.id },
select: {
id: true, puzzleId: true, path: true, clicks: true,
timeSeconds: true, won: true, playedAt: true,
},
orderBy: { playedAt: "desc" },
});
const data = {
profile: user,
games: games.map((g) => ({ ...g, path: JSON.parse(g.path) as string[] })),
dailyResults: dailyResults.map((d) => ({ ...d, path: JSON.parse(d.path) as string[] })),
exportedAt: new Date().toISOString(),
};
return new NextResponse(JSON.stringify(data, null, 2), {
headers: {
"Content-Type": "application/json",
"Content-Disposition": `attachment; filename="wikirush-data-${session.user.id}.json"`,
},
});
}
export async function DELETE() {
const session = await auth();
if (!session?.user?.id) {
+20
View File
@@ -170,6 +170,26 @@ export function ProfileScreen({ userName, onBack }: { userName: string; onBack:
))}
</div>
{/* Mes données */}
<div className="mt-8 border border-[#2e2e2e] rounded-xl p-4 flex items-center justify-between gap-3 flex-wrap">
<div className="flex flex-col gap-0.5">
<p className="text-xs font-bold text-[#f0f0f0] uppercase tracking-wider">Mes données</p>
<p className="text-xs text-[#888]">Télécharge toutes tes données personnelles (RGPD).</p>
</div>
<a
href="/api/account"
download
className="min-h-9 px-3 rounded-lg text-xs sm:text-sm font-semibold bg-[#242424] border border-[#2e2e2e] text-[#f0f0f0] hover:bg-[#1a1a1a] transition-colors shrink-0 inline-flex items-center gap-1.5"
>
<svg viewBox="0 0 24 24" className="w-3.5 h-3.5 fill-none stroke-current stroke-2" aria-hidden>
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
<polyline points="7 10 12 15 17 10" />
<line x1="12" y1="15" x2="12" y2="3" />
</svg>
Télécharger (.json)
</a>
</div>
{/* Danger zone */}
<div className="mt-8 border border-red-900/50 rounded-xl p-4 flex flex-col gap-3">
<h3 className="text-xs font-bold text-red-400 uppercase tracking-wider">Zone dangereuse</h3>
+4
View File
@@ -52,6 +52,10 @@ export default function RootLayout({
Politique de confidentialité
</a>
<span>·</span>
<a href="/mentions-legales" className="hover:text-[#888] transition-colors">
Mentions légales
</a>
<span>·</span>
<a href="/about" className="hover:text-[#888] transition-colors">
À propos
</a>
+161
View File
@@ -0,0 +1,161 @@
import type { Metadata } from "next";
import Link from "next/link";
export const metadata: Metadata = {
title: "Mentions légales - WikiRush",
description: "Mentions légales du site WikiRush.",
};
export default function MentionsLegalesPage() {
return (
<div className="min-h-dvh bg-[#0f0f0f] text-[#f0f0f0] px-4 py-12 flex flex-col items-center">
<div className="w-full max-w-xl flex flex-col gap-10">
<Link
href="/"
className="inline-flex items-center gap-2 px-4 py-2 rounded-xl text-sm font-medium
bg-[#1f1f1f] border border-[#2e2e2e] text-[#e5e5e5]
hover:bg-[#2a2a2a] hover:border-[#3a3a3a] transition-all duration-200 self-start"
>
<span className="text-base"></span>
Retour
</Link>
<div className="flex flex-col gap-1">
<h1 className="text-2xl font-black">Mentions légales</h1>
<p className="text-[#888] text-sm">
Conformément à la loi n° 2004-575 du 21 juin 2004 pour la confiance
dans l&apos;économie numérique.
</p>
</div>
<section className="flex flex-col gap-6">
{/* Éditeur */}
<div className="flex flex-col gap-3">
<h2 className="text-xs font-bold uppercase tracking-widest text-[#555]">
Éditeur du site
</h2>
<div className="bg-[#1a1a1a] border border-[#2e2e2e] rounded-xl p-4 flex flex-col gap-1.5 text-sm">
<p>
<span className="text-[#888]">
Responsable de publication :
</span>{" "}
DAVID Jessy
</p>
<p>
<span className="text-[#888]">Contact :</span>{" "}
<a
href="mailto:contact@jessy-david.dev"
className="text-[#7c3aed] hover:underline"
>
contact@jessy-david.dev
</a>
</p>
</div>
</div>
{/* Hébergeur */}
<div className="flex flex-col gap-3">
<h2 className="text-xs font-bold uppercase tracking-widest text-[#555]">
Hébergeur
</h2>
<div className="bg-[#1a1a1a] border border-[#2e2e2e] rounded-xl p-4 flex flex-col gap-1.5 text-sm">
<p>
<span className="text-[#888]">Raison sociale :</span>{" "}
QuantumCraft Studios
</p>
<p>
<span className="text-[#888]">SIRET :</span> 932 107 758 00017
</p>
<p>
<span className="text-[#888]">Adresse :</span> 58 Rue de
Monceau, 75008 Paris, France
</p>
<p>
<span className="text-[#888]">Site web :</span>{" "}
<a
href="https://www.quantumcraft-studios.com"
target="_blank"
rel="noopener noreferrer"
className="text-[#7c3aed] hover:underline"
>
quantumcraft-studios.com
</a>
</p>
</div>
</div>
{/* Propriété intellectuelle */}
<div className="flex flex-col gap-3">
<h2 className="text-xs font-bold uppercase tracking-widest text-[#555]">
Propriété intellectuelle
</h2>
<div className="bg-[#1a1a1a] border border-[#2e2e2e] rounded-xl p-4 text-sm text-[#aaa] leading-relaxed">
<p>
L&apos;ensemble du contenu de ce site (structure, textes, logos,
visuels) est la propriété de DAVID Jessy, sauf mentions
contraires. Toute reproduction, représentation ou diffusion, en
tout ou partie, est interdite sans autorisation préalable.
</p>
<p className="mt-3">
Les articles consultés durant les parties proviennent de{" "}
<a
href="https://fr.wikipedia.org"
target="_blank"
rel="noopener noreferrer"
className="text-[#7c3aed] hover:underline"
>
Wikipédia
</a>{" "}
et sont soumis à la licence{" "}
<a
href="https://creativecommons.org/licenses/by-sa/4.0/"
target="_blank"
rel="noopener noreferrer"
className="text-[#7c3aed] hover:underline"
>
CC BY-SA 4.0
</a>
.
</p>
</div>
</div>
{/* Données personnelles */}
<div className="flex flex-col gap-3">
<h2 className="text-xs font-bold uppercase tracking-widest text-[#555]">
Données personnelles
</h2>
<div className="bg-[#1a1a1a] border border-[#2e2e2e] rounded-xl p-4 text-sm text-[#aaa] leading-relaxed">
<p>
Les données collectées (pseudo, email, historique de parties)
sont utilisées uniquement pour le fonctionnement du service.
Elles ne sont pas transmises à des tiers. Conformément au RGPD,
vous disposez d&apos;un droit d&apos;accès, de rectification et
de suppression de vos données.
</p>
<p className="mt-3">
Pour exercer ces droits :{" "}
<a
href="mailto:contact@jessy-david.dev"
className="text-[#7c3aed] hover:underline"
>
contact@jessy-david.dev
</a>
</p>
<p className="mt-3">
Consulter notre{" "}
<Link
href="/privacy"
className="text-[#7c3aed] hover:underline"
>
politique de confidentialité
</Link>
.
</p>
</div>
</div>
</section>
</div>
</div>
);
}