feat: news pagination — replace show more/collapse with page controls
This commit is contained in:
@@ -121,11 +121,11 @@ function CompactArticle({
|
||||
);
|
||||
}
|
||||
|
||||
const INITIAL_VISIBLE = 4;
|
||||
const PER_PAGE = 4;
|
||||
|
||||
export function News({ data }: NewsProps) {
|
||||
const [selected, setSelected] = useState<NewsItem | null>(null);
|
||||
const [showAll, setShowAll] = useState(false);
|
||||
const [page, setPage] = useState(0);
|
||||
|
||||
if (!data.items || data.items.length === 0) return null;
|
||||
|
||||
@@ -135,8 +135,8 @@ export function News({ data }: NewsProps) {
|
||||
.sort((a, b) => (b.date || "").localeCompare(a.date || ""));
|
||||
if (sorted.length === 0) return null;
|
||||
const [featured, ...rest] = sorted;
|
||||
const visibleRest = showAll ? rest : rest.slice(0, INITIAL_VISIBLE - 1);
|
||||
const hasMore = rest.length > INITIAL_VISIBLE - 1 && !showAll;
|
||||
const totalPages = Math.max(1, Math.ceil(rest.length / PER_PAGE));
|
||||
const visibleRest = rest.slice(page * PER_PAGE, (page + 1) * PER_PAGE);
|
||||
|
||||
return (
|
||||
<section id="news" className="section-glow relative section-padding">
|
||||
@@ -168,17 +168,48 @@ export function News({ data }: NewsProps) {
|
||||
</Reveal>
|
||||
)}
|
||||
|
||||
{hasMore && (
|
||||
<Reveal>
|
||||
<div className="text-center">
|
||||
{totalPages > 1 && (
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<button
|
||||
onClick={() => {
|
||||
setPage((p) => Math.max(0, p - 1));
|
||||
const el = document.getElementById("news");
|
||||
if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
}}
|
||||
disabled={page === 0}
|
||||
className="rounded-full border border-white/10 bg-white/[0.03] px-4 py-2 text-sm font-medium text-neutral-400 hover:text-white hover:border-white/25 transition-colors cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed"
|
||||
>
|
||||
←
|
||||
</button>
|
||||
{Array.from({ length: totalPages }, (_, i) => (
|
||||
<button
|
||||
onClick={() => setShowAll(true)}
|
||||
className="rounded-full border border-white/10 bg-white/[0.03] px-6 py-2.5 text-sm font-medium text-neutral-400 hover:text-white hover:border-white/25 transition-colors cursor-pointer"
|
||||
key={i}
|
||||
onClick={() => {
|
||||
setPage(i);
|
||||
const el = document.getElementById("news");
|
||||
if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
}}
|
||||
className={`h-8 w-8 rounded-full text-sm font-medium transition-colors cursor-pointer ${
|
||||
i === page
|
||||
? "bg-gold text-black"
|
||||
: "border border-white/10 text-neutral-400 hover:text-white hover:border-white/25"
|
||||
}`}
|
||||
>
|
||||
Показать ещё ({rest.length - INITIAL_VISIBLE + 1})
|
||||
{i + 1}
|
||||
</button>
|
||||
</div>
|
||||
</Reveal>
|
||||
))}
|
||||
<button
|
||||
onClick={() => {
|
||||
setPage((p) => Math.min(totalPages - 1, p + 1));
|
||||
const el = document.getElementById("news");
|
||||
if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
}}
|
||||
disabled={page === totalPages - 1}
|
||||
className="rounded-full border border-white/10 bg-white/[0.03] px-4 py-2 text-sm font-medium text-neutral-400 hover:text-white hover:border-white/25 transition-colors cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed"
|
||||
>
|
||||
→
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user