add new routing
This commit is contained in:
216
src/components/ArchivePagination.astro
Normal file
216
src/components/ArchivePagination.astro
Normal file
@@ -0,0 +1,216 @@
|
||||
---
|
||||
|
||||
|
||||
interface Props {
|
||||
baseUrl: string;
|
||||
page: number;
|
||||
hasNextPage: boolean;
|
||||
window?: number; // сколько страниц вокруг текущей
|
||||
}
|
||||
|
||||
const {
|
||||
baseUrl,
|
||||
page,
|
||||
hasNextPage,
|
||||
window = 2,
|
||||
} = Astro.props;
|
||||
|
||||
const pageUrl = (p: number) =>
|
||||
p === 1 ? baseUrl : `${baseUrl}/page/${p}`;
|
||||
|
||||
// рассчитываем диапазон
|
||||
const start = Math.max(1, page - window);
|
||||
const end = page + window;
|
||||
---
|
||||
|
||||
<nav class="pagination" aria-label="Pagination">
|
||||
<ul>
|
||||
<!-- prev -->
|
||||
{page > 1 && (
|
||||
<li>
|
||||
<a href={pageUrl(page - 1)} rel="prev">←</a>
|
||||
</li>
|
||||
)}
|
||||
|
||||
<!-- первая -->
|
||||
{start > 1 && (
|
||||
<>
|
||||
<li><a href={pageUrl(1)}>1</a></li>
|
||||
{start > 2 && <li class="dots">…</li>}
|
||||
</>
|
||||
)}
|
||||
|
||||
<!-- центральные -->
|
||||
{Array.from({ length: end - start + 1 }, (_, i) => start + i).map(p => (
|
||||
<li class={p === page ? 'active' : ''}>
|
||||
<a
|
||||
href={pageUrl(p)}
|
||||
aria-current={p === page ? 'page' : undefined}
|
||||
>
|
||||
{p}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
|
||||
<!-- следующая -->
|
||||
{hasNextPage && (
|
||||
<>
|
||||
<li class="dots">…</li>
|
||||
<li>
|
||||
<a href={pageUrl(page + window + 1)}>
|
||||
{page + window + 1}
|
||||
</a>
|
||||
</li>
|
||||
</>
|
||||
)}
|
||||
|
||||
<!-- next -->
|
||||
{hasNextPage && (
|
||||
<li>
|
||||
<a href={pageUrl(page + 1)} rel="next">→</a>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
|
||||
/* Базовые стили пагинатора */
|
||||
.pagination {
|
||||
margin: 2rem 0;
|
||||
padding: 1rem 0;
|
||||
border-top: 1px solid #eaeaea;
|
||||
border-bottom: 1px solid #eaeaea;
|
||||
}
|
||||
|
||||
.pagination ul {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
/* Общие стили для элементов пагинации */
|
||||
.pagination li {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pagination a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 42px;
|
||||
height: 42px;
|
||||
padding: 0 0.5rem;
|
||||
text-decoration: none;
|
||||
color: #2c3e50;
|
||||
font-size: 1.05rem;
|
||||
font-weight: 500;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 4px;
|
||||
transition: all 0.25s ease;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.pagination a:hover {
|
||||
background-color: #e9ecef;
|
||||
border-color: #d0d7de;
|
||||
color: #1a365d;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* Активная страница */
|
||||
.pagination li.active a {
|
||||
background-color: #1a365d;
|
||||
color: white;
|
||||
border-color: #1a365d;
|
||||
font-weight: 600;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pagination li.active a:hover {
|
||||
transform: none;
|
||||
box-shadow: none;
|
||||
background-color: #1a365d;
|
||||
}
|
||||
|
||||
/* Многоточие */
|
||||
.pagination li.dots {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 42px;
|
||||
height: 42px;
|
||||
color: #6c757d;
|
||||
font-size: 1.2rem;
|
||||
letter-spacing: 1px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Стрелки (предыдущая/следующая) */
|
||||
.pagination a[rel="prev"],
|
||||
.pagination a[rel="next"] {
|
||||
font-size: 1.3rem;
|
||||
color: #495057;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
min-width: 46px;
|
||||
}
|
||||
|
||||
.pagination a[rel="prev"]:hover,
|
||||
.pagination a[rel="next"]:hover {
|
||||
background-color: #f1f3f5;
|
||||
color: #1a365d;
|
||||
}
|
||||
|
||||
/* Для первой и последней страницы (если есть отдельные классы) */
|
||||
.pagination li:first-child a,
|
||||
.pagination li:last-child a {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Адаптивность */
|
||||
@media (max-width: 768px) {
|
||||
.pagination ul {
|
||||
gap: 0.25rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.pagination a {
|
||||
min-width: 38px;
|
||||
height: 38px;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.pagination li.dots {
|
||||
min-width: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Фокус для доступности */
|
||||
.pagination a:focus {
|
||||
outline: 2px solid #1a365d;
|
||||
outline-offset: 2px;
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
/* Отключенные состояния (если понадобятся в будущем) */
|
||||
.pagination li.disabled a {
|
||||
color: #adb5bd;
|
||||
cursor: not-allowed;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.pagination li.disabled a:hover {
|
||||
transform: none;
|
||||
box-shadow: none;
|
||||
background-color: #f8f9fa;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,4 +1,8 @@
|
||||
---
|
||||
|
||||
import FooterMenu from '@components/FooterMenu.astro';
|
||||
|
||||
|
||||
interface Props {
|
||||
publicationName: string;
|
||||
organization: string;
|
||||
@@ -90,6 +94,8 @@ const footerId = `footer-profile`;
|
||||
<li><a href="">Правила применения рекомендательных технологий</a></li>
|
||||
</ul>
|
||||
|
||||
<FooterMenu />
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
|
||||
import Stores from './LazyStores.astro';
|
||||
import MainMenu from '@components/MainMenu.astro';
|
||||
|
||||
const MENU_ID = 103245;
|
||||
let menuItems = [];
|
||||
@@ -14,6 +15,8 @@
|
||||
<Stores />
|
||||
</div>
|
||||
|
||||
<MainMenu menuId={MENU_ID} />
|
||||
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user