add new routing

This commit is contained in:
Andrey Kuvshinov
2025-12-17 23:05:49 +03:00
parent a72d47f6d9
commit 033158e384
9 changed files with 572 additions and 73 deletions

View 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>

View File

@@ -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>

View File

@@ -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>