import { useEffect, useState } from "react"; import { ListView } from "../../components/ListView/ListView"; import { SearchBar } from "../../components/SearchBar/SearchBar"; import { TitlesSortBox } from "../../components/TitlesSortBox/TitlesSortBox"; import { DefaultService } from "../../api/services/DefaultService"; import { TitleCardSquare } from "../../components/cards/TitleCardSquare"; import { TitleCardHorizontal } from "../../components/cards/TitleCardHorizontal"; import type { CursorObj, Title, TitleSort } from "../../api"; import { LayoutSwitch } from "../../components/LayoutSwitch/LayoutSwitch"; import { Link } from "react-router-dom"; const PAGE_SIZE = 10; export default function TitlesPage() { const [titles, setTitles] = useState([]); const [nextPage, setNextPage] = useState([]); const [cursor, setCursor] = useState(null); const [search, setSearch] = useState(""); const [loading, setLoading] = useState(true); const [loadingMore, setLoadingMore] = useState(false); const [sort, setSort] = useState("id"); const [sortForward, setSortForward] = useState(true); const [layout, setLayout] = useState<"square" | "horizontal">("square"); const fetchPage = async (cursorObj: CursorObj | null) => { const cursorStr = cursorObj ? btoa(JSON.stringify(cursorObj)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '') : ""; try { const result = await DefaultService.getTitles( cursorStr, sort, sortForward, search.trim() || undefined, undefined, undefined, undefined, undefined, PAGE_SIZE, undefined, "all" ); if ((result === undefined) || !result.data?.length) { return { items: [], nextCursor: null }; } return { items: result.data ?? [], nextCursor: result.cursor ?? null }; } catch (err: any) { if (err.status === 204) { return { items: [], nextCursor: null }; } throw err; } }; // Инициализация: загружаем сразу две страницы useEffect(() => { const initLoad = async () => { setLoading(true); setTitles([]); setNextPage([]); setCursor(null); const firstPage = await fetchPage(null); const secondPage = firstPage.nextCursor ? await fetchPage(firstPage.nextCursor) : { items: [], nextCursor: null }; setTitles(firstPage.items); setNextPage(secondPage.items); setCursor(secondPage.nextCursor); setLoading(false); }; initLoad(); }, [search, sort, sortForward]); const handleLoadMore = async () => { if (nextPage.length === 0) { setLoadingMore(false); return; } setLoadingMore(true); setTitles(prev => [...prev, ...nextPage]); setNextPage([]); // Подгружаем следующую страницу с сервера if (cursor) { try { const next = await fetchPage(cursor); if (next.items.length > 0) { setNextPage(next.items); } setCursor(next.nextCursor); } catch (err) { console.error(err); } } // Любой сценарий – выключаем loadingMore setLoadingMore(false); }; return (

Titles

{loading &&
Loading...
} {!loading && titles.length === 0 && (
No titles found.
)} {titles.length > 0 && ( <> items={titles} layout={layout} hasMore={!!cursor || nextPage.length > 1} loadingMore={loadingMore} onLoadMore={handleLoadMore} renderItem={(title, layout) => ( {layout === "square" ? : } )} /> {!cursor && nextPage.length == 0 && (
Результатов больше нет, было найдено {titles.length} тайтлов.
)} )}
); }