import { useEffect, useState } from "react"; import { BookOpen, LibraryBig, ScanLine } from "lucide-react"; import { api } from "../api/client"; import { hasActiveCoverWork, isBookCoverUpdating, type DashboardData } from "../api/types"; import { bookDisplayTitle, bookMetadataState, bookMetadataStateLabel, bookVolumeLabel, displayPublishedDate } from "../book/metadata"; import { BookCard } from "../components/BookCard"; import { EmptyState, LoadingState, Meter, Panel } from "../components/ui"; import { navigate } from "../router"; export function HomePage() { const [state, setState] = useState(null); const [fallback, setFallback] = useState(false); useEffect(() => { let alive = true; Promise.all([api.books(), api.continueReading(), api.libraries(), api.jobs()]) .then(([books, continueReading, libraries, jobs]) => { if (!alive) return; setFallback(books.some((book) => book.filePath.startsWith("/library/")) && jobs.length === 1); setState({ books, continueReading, libraries, jobs }); }) .catch(() => { if (alive) setState({ books: [], continueReading: [], libraries: [], jobs: [] }); }); return () => { alive = false; }; }, []); if (!state) return ; const fallbackCoverLoading = hasActiveCoverWork(state.jobs); return (

Cabinet de curiosites numerique

Ouvrir, classer, reprendre.

{fallback ? "API absente ou incomplete : specimens de demonstration actifs." : "Catalogue branche sur le serveur local."}

Reprise de lecture

{state.continueReading.length} traces
{state.continueReading.length ? (
{state.continueReading.map((item) => { const metadataState = bookMetadataState(item.book); const publishedDate = displayPublishedDate(item.book.publishedDate); const volumeLabel = bookVolumeLabel(item.book); return ( ); })}
) : ( )}

Bibliotheques

{state.libraries.map((library) => ( ))}
{state.books.map((book) => ( ))}
); }