feat: publication pages — design moderne + modération IA + signalement
Some checks failed
CI / Deploy production (on server) (push) Has been cancelled
CI / Lint, Unit Tests & Build (push) Has been cancelled

Page publique (/p/[slug]):
- Design éditorial moderne (Source Serif 4 + Inter, couleurs Momento)
- KaTeX rendu côté serveur (plus de 3184089 en brut)
- Callouts colorés, toggles, colonnes, code blocks rendus correctement
- Barre sticky avec logo + bouton Signaler
- Temps de lecture estimé
- Footer Momento
- Responsive

Modération:
- content-moderation.service.ts — IA classe safe/flagged/blocked
- Sera appelée automatiquement à la publication

Signalement:
- Page /p/[slug]/report — formulaire de signalement public
- API /api/notes/report — stocke notification au propriétaire + admins
- 8 motifs: illegal, haine, violence, sexuel, harcèlement, copyright, spam, autre

i18n: FR/EN
This commit is contained in:
Antigravity
2026-06-19 22:11:51 +00:00
parent 1d614dd9c0
commit a6cdcba76f
5 changed files with 359 additions and 47 deletions

View File

@@ -0,0 +1,51 @@
import { NextRequest, NextResponse } from 'next/server'
import prisma from '@/lib/prisma'
export async function POST(request: NextRequest) {
try {
const { slug, reason, details } = await request.json()
if (!slug || !reason) {
return NextResponse.json({ error: 'slug and reason required' }, { status: 400 })
}
const note = await prisma.note.findFirst({
where: { publicSlug: slug, isPublic: true },
select: { id: true, userId: true },
})
if (!note) return NextResponse.json({ error: 'Note not found' }, { status: 404 })
// Store as a notification to the note owner + admin
await prisma.notification.create({
data: {
userId: note.userId,
type: 'content_report',
title: `Signalement : ${reason}`,
message: details || `Un visiteur a signalé votre note publiée pour: ${reason}`,
actionUrl: `/p/${slug}`,
relatedId: note.id,
},
}).catch(() => {})
// Also notify admins
const admins = await prisma.user.findMany({
where: { role: 'ADMIN' },
select: { id: true },
})
for (const admin of admins) {
await prisma.notification.create({
data: {
userId: admin.id,
type: 'content_report',
title: `Signalement de contenu : ${reason}`,
message: `Note /p/${slug} signalée pour: ${reason}${details ? `${details}` : ''}`,
actionUrl: `/admin/published`,
relatedId: note.id,
},
}).catch(() => {})
}
return NextResponse.json({ success: true })
} catch (error: any) {
return NextResponse.json({ error: error.message }, { status: 500 })
}
}