'use client'; import { useEffect, useMemo, useState } from 'react'; const initialForm = { name: '', url: '', icon: '/github.png', description: '', category: 'Autres' }; export default function AdminPanel() { const [isAuthenticated, setIsAuthenticated] = useState(false); const [username, setUsername] = useState('admin'); const [password, setPassword] = useState(''); const [links, setLinks] = useState([]); const [analytics, setAnalytics] = useState([]); const [form, setForm] = useState(initialForm); const [error, setError] = useState(''); const [loading, setLoading] = useState(true); async function loadAdminData() { const [linksResponse, analyticsResponse] = await Promise.all([ fetch('/api/links'), fetch('/api/analytics') ]); if (!linksResponse.ok || !analyticsResponse.ok) { setError('Impossible de charger les données admin.'); return; } const linksData = await linksResponse.json(); const analyticsData = await analyticsResponse.json(); setLinks(linksData.links || []); setAnalytics(analyticsData.analytics || []); setError(''); } useEffect(() => { async function checkSession() { const response = await fetch('/api/admin/session'); const data = await response.json(); if (data.authenticated) { setIsAuthenticated(true); await loadAdminData(); } setLoading(false); } checkSession(); }, []); async function handleLogin(event) { event.preventDefault(); setError(''); const response = await fetch('/api/admin/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); if (!response.ok) { setError('Identifiant ou mot de passe invalide.'); return; } setIsAuthenticated(true); setPassword(''); await loadAdminData(); } async function handleLogout() { await fetch('/api/admin/logout', { method: 'POST' }); setIsAuthenticated(false); setLinks([]); setAnalytics([]); } async function handleAddLink(event) { event.preventDefault(); setError(''); const response = await fetch('/api/links', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(form) }); if (!response.ok) { setError("Impossible d'ajouter le lien."); return; } setForm(initialForm); await loadAdminData(); } async function handleDeleteLink(linkId) { setError(''); const response = await fetch(`/api/links/${linkId}`, { method: 'DELETE' }); if (!response.ok) { setError('Impossible de supprimer ce lien.'); return; } setError(''); await loadAdminData(); } const totalClicks = useMemo( () => analytics.reduce((sum, item) => sum + (item.clicks || 0), 0), [analytics] ); if (loading) { return ( Chargement... ); } if (!isAuthenticated) { return ( Admin Accès protégé aux analytics et à la gestion des liens. setUsername(event.target.value)} placeholder="Identifiant" required /> setPassword(event.target.value)} placeholder="Mot de passe" required /> Se connecter {error ? {error} : null} ); } return ( Menu Admin Déconnexion Analytics Total clics: {totalClicks} {analytics.map((item) => ( {item.name} {item.url} {item.clicks} clics ))} Ajouter un lien setForm({ ...form, name: event.target.value })} placeholder="Nom" required /> setForm({ ...form, url: event.target.value })} placeholder="URL" required /> setForm({ ...form, icon: event.target.value })} placeholder="Icône (ex: /github.png)" /> setForm({ ...form, description: event.target.value })} placeholder="Description" /> setForm({ ...form, category: event.target.value })} placeholder="Catégorie" /> Ajouter Supprimer un lien {links.map((link) => ( {link.name} {link.url} handleDeleteLink(link.id)} > Supprimer ))} {error ? {error} : null} ); }
Chargement...
Accès protégé aux analytics et à la gestion des liens.
{error}
Total clics: {totalClicks}