import { FormEvent, useEffect, useState } from "react"; import { Play, Plus, Trash2 } from "lucide-react"; import type { JobDto, LibraryDto, UserDto } from "@readabook/shared"; import { api, getApiFallback } from "../api/client"; import { EmptyState, ErrorRibbon, LoadingState, Panel } from "../components/ui"; export function AdminPage() { const [libraries, setLibraries] = useState([]); const [jobs, setJobs] = useState([]); const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [name, setName] = useState("Bibliotheque locale"); const [path, setPath] = useState("/library"); const [error, setError] = useState(); const [success, setSuccess] = useState(); async function refresh() { setLoading(true); setError(undefined); const [libraryResult, jobResult, userResult] = await Promise.allSettled([api.libraries(), api.jobs(), api.users()]); const errors: string[] = []; if (libraryResult.status === "fulfilled") { setLibraries(libraryResult.value); } else { setLibraries(getApiFallback(libraryResult.reason) ?? []); errors.push("bibliotheques"); } if (jobResult.status === "fulfilled") { setJobs(jobResult.value); } else { setJobs(getApiFallback(jobResult.reason) ?? []); errors.push("travaux"); } if (userResult.status === "fulfilled") { setUsers(userResult.value); } else { setUsers(getApiFallback(userResult.reason) ?? []); errors.push("comptes"); } setError(errors.length ? `Donnees admin degradees : ${errors.join(", ")}.` : undefined); setLoading(false); } useEffect(() => { void refresh(); }, []); async function createLibrary(event: FormEvent) { event.preventDefault(); setError(undefined); setSuccess(undefined); try { await api.createLibrary({ name, path, enabled: true }); await refresh(); setSuccess(`Bibliothèque "${name}" ajoutée.`); } catch (createError) { const fallback = getApiFallback(createError); if (fallback) setLibraries((current) => [fallback, ...current]); setError(fallback ? "Creation en mode secours, synchronisation a retenter." : "Creation impossible"); } } async function scan(id: number) { setError(undefined); setSuccess(undefined); try { await api.scanLibrary(id); await refresh(); setSuccess("Scan demandé."); } catch (scanError) { const fallback = getApiFallback(scanError); if (fallback) setJobs((current) => [fallback, ...current]); setError(fallback ? "Scan place en file de secours, statut a verifier." : "Scan impossible"); } } async function deleteLibrary(library: LibraryDto) { const confirmed = window.confirm( `Supprimer la bibliothèque "${library.name}" ?\n\nLes livres restent sur le disque. ReadaBook supprimera seulement cette bibliothèque du catalogue.` ); if (!confirmed) return; setError(undefined); setSuccess(undefined); try { await api.deleteLibrary(library.id); setLibraries((current) => current.filter((item) => item.id !== library.id)); setSuccess(`Bibliothèque "${library.name}" supprimée. Les fichiers disque n'ont pas été supprimés.`); } catch (deleteError) { setError(deleteError instanceof Error ? deleteError.message : "Suppression impossible"); } } return (

Administration

{loading ? "chargement" : `${users.length} comptes`}
{success &&
{success}
} {error && (
Les formulaires restent disponibles.
)}

Travaux

{jobs.length}
{loading && !jobs.length ? ( ) : jobs.length ? (
{jobs.map((job) => (
{job.type} {job.status}
))}
) : ( )}
{loading && !libraries.length ? ( ) : libraries.length ? (
{libraries.map((library) => (
{library.name} Chemin : {library.path}
{library.enabled ? "actif" : "pause"}
))}
) : ( )}
); }