diff --git a/memento-note/app/(main)/settings/published/page.tsx b/memento-note/app/(main)/settings/published/page.tsx new file mode 100644 index 0000000..d4c4b03 --- /dev/null +++ b/memento-note/app/(main)/settings/published/page.tsx @@ -0,0 +1,103 @@ +'use client' + +import { useState, useEffect, useCallback } from 'react' +import { Globe, ExternalLink, Trash2, Loader2, Copy, Check } from 'lucide-react' +import { toast } from 'sonner' +import { useLanguage } from '@/lib/i18n' + +interface PublishedNote { + id: string + title: string | null + publicSlug: string | null + publishedAt: string | null +} + +export default function UserPublishedPage() { + const { t } = useLanguage() + const [notes, setNotes] = useState([]) + const [loading, setLoading] = useState(true) + const [copiedId, setCopiedId] = useState(null) + + const load = useCallback(async () => { + setLoading(true) + try { + const res = await fetch('/api/user/published') + const data = await res.json() + setNotes(data.notes || []) + } catch { toast.error('Erreur') } + finally { setLoading(false) } + }, []) + + useEffect(() => { load() }, [load]) + + const unpublish = async (noteId: string) => { + try { + const res = await fetch('/api/notes/publish', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ noteId, action: 'unpublish' }), + }) + if (res.ok) { toast.success(t('richTextEditor.unpublishSuccess') || 'Note dépubliée'); load() } + else { toast.error('Erreur') } + } catch { toast.error('Erreur') } + } + + const copyLink = (slug: string, noteId: string) => { + const url = `${window.location.origin}/p/${slug}` + navigator.clipboard?.writeText(url).then(() => { + setCopiedId(noteId); setTimeout(() => setCopiedId(null), 2000); toast.success('Lien copié !') + }).catch(() => { + const el = document.createElement('textarea'); el.value = url; document.body.appendChild(el); el.select() + document.execCommand('copy'); document.body.removeChild(el) + setCopiedId(noteId); setTimeout(() => setCopiedId(null), 2000); toast.success('Lien copié !') + }) + } + + return ( +
+
+

{t('settings.publishedTitle') || 'Mes pages publiées'}

+

{t('settings.publishedDesc') || 'Gérez les notes que vous avez publiées publiquement.'}

+
+ + {loading ? ( +
+ ) : notes.length === 0 ? ( +
+ +

{t('settings.publishedEmpty') || 'Aucune note publiée pour le moment.'}

+
+ ) : ( +
+ {notes.map(note => ( +
+
+ +
+
+
{note.title || 'Sans titre'}
+
+ {note.publishedAt ? new Date(note.publishedAt).toLocaleDateString() : ''} +
+
+
+ + + + + +
+
+ ))} +
+ )} +
+ ) +} diff --git a/memento-note/app/api/user/published/route.ts b/memento-note/app/api/user/published/route.ts new file mode 100644 index 0000000..2bae2d4 --- /dev/null +++ b/memento-note/app/api/user/published/route.ts @@ -0,0 +1,16 @@ +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: 'Unauthorized' }, { status: 401 }) + + const notes = await prisma.note.findMany({ + where: { userId: session.user.id, isPublic: true, trashedAt: null }, + select: { id: true, title: true, publicSlug: true, publishedAt: true }, + orderBy: { publishedAt: 'desc' }, + }) + + return NextResponse.json({ notes }) +} diff --git a/memento-note/components/admin-sidebar.tsx b/memento-note/components/admin-sidebar.tsx index d24d462..bcfa704 100644 --- a/memento-note/components/admin-sidebar.tsx +++ b/memento-note/components/admin-sidebar.tsx @@ -9,7 +9,6 @@ import { Shield, Settings, StickyNote, - Shield, ArrowLeft, User, LogOut, diff --git a/memento-note/components/settings/SettingsNav.tsx b/memento-note/components/settings/SettingsNav.tsx index 428841f..b204683 100644 --- a/memento-note/components/settings/SettingsNav.tsx +++ b/memento-note/components/settings/SettingsNav.tsx @@ -2,7 +2,7 @@ import Link from 'next/link' import { usePathname } from 'next/navigation' -import { Settings, Sparkles, Palette, User, Database, Info, Key, CreditCard, Plug } from 'lucide-react' +import { Settings, Sparkles, Palette, User, Database, Info, Key, CreditCard, Plug, Globe } from 'lucide-react' import { useLanguage } from '@/lib/i18n' import { motion } from 'motion/react' @@ -21,6 +21,7 @@ export function SettingsNav({ className }: SettingsNavProps) { { id: 'appearance', label: t('appearance.title'), icon: , href: '/settings/appearance' }, { id: 'profile', label: t('profile.title'), icon: , href: '/settings/profile' }, { id: 'data', label: t('dataManagement.title'), icon: , href: '/settings/data' }, + { id: 'published', label: t('settings.publishedTitle') || 'Mes pages', icon: , href: '/settings/published' }, { id: 'integrations', label: t('integrations.title') || 'Intégrations', icon: , href: '/settings/integrations' }, { id: 'mcp', label: t('mcpSettings.title'), icon: , href: '/settings/mcp' }, { id: 'about', label: t('about.title'), icon: , href: '/settings/about' }, diff --git a/memento-note/locales/en.json b/memento-note/locales/en.json index 6856709..f18a50c 100644 --- a/memento-note/locales/en.json +++ b/memento-note/locales/en.json @@ -2569,6 +2569,9 @@ "publish": "Publish", "publishSuccess": "Note published!", "publishLive": "Live", + "settingsPublishedTitle": "My published pages", + "settingsPublishedDesc": "Manage your publicly published notes.", + "settingsPublishedEmpty": "No published notes yet.", "unpublish": "Unpublish", "unpublishSuccess": "Note unpublished", "slashSubPage": "Sub-page", diff --git a/memento-note/locales/fr.json b/memento-note/locales/fr.json index 5e647c4..a02f75d 100644 --- a/memento-note/locales/fr.json +++ b/memento-note/locales/fr.json @@ -2573,6 +2573,9 @@ "publish": "Publier", "publishSuccess": "Note publiée !", "publishLive": "En ligne", + "settingsPublishedTitle": "Mes pages publiées", + "settingsPublishedDesc": "Gérez les notes que vous avez publiées publiquement.", + "settingsPublishedEmpty": "Aucune note publiée pour le moment.", "unpublish": "Dépublier", "unpublishSuccess": "Note dépubliée", "slashSubPage": "Sous-page",