Новые изменения в компоенты

This commit is contained in:
Web-serfer 2026-04-29 03:12:16 +05:00
parent acb7b88ff1
commit 9122756a58
11 changed files with 360 additions and 13 deletions

View file

@ -207,5 +207,5 @@ const iconPaths: Record<string, string> = {
};
setupAnimations();
document.addEventListener('astro:after-swap', setupAnimations);
document.addEventListener('astro:page-load', setupAnimations);
</script>

View file

@ -13,13 +13,12 @@ const { categories, activeCategory = 'Все', currentPage = 1 } = Astro.props;
<div class="categories-inner animate-on-scroll" data-animation="fade-up">
<div class="categories-wrapper">
{categories.map((cat) => (
<a
href={cat === 'Все' ? '/blog' : `/blog/category/${cat.toLowerCase()}`}
<button
class={`category-btn ${cat === activeCategory ? 'active' : ''}`}
data-category={cat}
>
{cat}
</a>
</button>
))}
</div>
@ -100,7 +99,6 @@ const { categories, activeCategory = 'Все', currentPage = 1 } = Astro.props;
border-color: #d4af37;
color: #1e293b;
box-shadow: 0 4px 12px rgba(212, 175, 55, 0.3);
text-decoration: none;
}
/* Анимации */

View file

@ -282,7 +282,7 @@ const colors = ['bg-gradient-1', 'bg-gradient-2', 'bg-gradient-3', 'bg-gradient-
setupSlider();
setupAnimations();
document.addEventListener('astro:after-swap', () => {
document.addEventListener('astro:page-load', () => {
setupSlider();
setupAnimations();
});

View file

@ -71,11 +71,17 @@ const { title, description, canonicalLink, breadcrumbs } = Astro.props;
sessionStorage.setItem('scrollPosition', String(window.scrollY));
});
// Восстанавливаем позицию скролла после перехода
// Восстанавливаем позицию скролла после перехода с плавной анимацией
document.addEventListener('astro:after-swap', () => {
const savedPosition = sessionStorage.getItem('scrollPosition');
if (savedPosition) {
window.scrollTo(0, parseInt(savedPosition));
const targetScroll = parseInt(savedPosition);
setTimeout(() => {
window.scrollTo({
top: targetScroll,
behavior: 'auto'
});
}, 50);
sessionStorage.removeItem('scrollPosition');
}
});

View file

@ -0,0 +1,171 @@
---
import Layout from '@layouts/Layout.astro';
import { SITE_URL } from '@constants';
import PageHero from '@components/base/PageHero.astro';
import BlogCategories from '@components/blog/BlogCategories.astro';
import BlogCard from '@components/blog/BlogCard.astro';
import Pagination from '@components/base/Pagination.astro';
import SearchModal from '@components/base/SearchModal.astro';
import { getPosts, getAllCategories, getPostImageUrl } from '@lib/pb';
export const prerender = false;
const POSTS_PER_PAGE = 6;
const categorySlug = Astro.params.category || '';
const categories = await getAllCategories();
const categoryName = categories.find(c => c.toLowerCase() === categorySlug.toLowerCase()) || categorySlug;
const { posts, total, totalPages } = await getPosts({
category: categoryName,
page: 1,
perPage: POSTS_PER_PAGE
});
const formatDate = (date: string) => {
const d = new Date(date);
const day = d.getDate().toString().padStart(2, '0');
const month = (d.getMonth() + 1).toString().padStart(2, '0');
const year = new Date().getFullYear().toString().slice(-2);
return `${day}/${month}/${year}`;
};
---
<Layout
title={`${categoryName} — автоюрист в Сургуте`}
description={`Статьи по теме "${categoryName}" — автоюрист в Сургуте. Полезные статьи и советы по автоспорам.`}
canonicalLink={`${SITE_URL}/blog/category/${categorySlug}`}
breadcrumbs={[
{ label: 'Главная', href: '/' },
{ label: 'Блог', href: '/blog' },
{ label: categoryName }
]}
>
<PageHero
badgeText={categoryName.toUpperCase()}
titleWhite={categoryName}
titleGold="статьи"
description={`Полезные статьи и советы по теме "${categoryName}" от автоюриста в Сургуте.`}
layout="with-image"
sideImage="/images/blog/blogImg.avif"
sideImageAlt="Автоюрист Сургут"
experienceBadge={{
number: String(total),
text: "СТАТЕЙ"
}}
bgImage="/images/blog/blogBg.avif"
/>
<BlogCategories categories={categories} activeCategory={categoryName} currentPage={1} />
<section class="blog-grid-section">
<div class="site-container">
<div class="blog-grid" id="blog-grid">
{posts.length > 0 ? (
posts.map((post: any) => (
<article class="blog-card-wrapper" data-category={post.category}>
<BlogCard
title={post.title}
description={post.description}
category={post.category}
categoryColor={post.categoryColor}
date={formatDate(post.date)}
readTime={post.readTime}
readmeTime={post.readmeTime}
image={getPostImageUrl(post)}
slug={`/blog/${post.slug}`}
/>
</article>
))
) : (
<div class="no-results">
<p>Статьи по теме "{categoryName}" не найдены</p>
<a href="/blog" class="back-link">Вернуться к списку статей</a>
</div>
)}
{totalPages > 1 && (
<Pagination
currentPage={1}
totalPages={totalPages}
baseUrl={`/blog/category/${categorySlug}`}
/>
)}
</div>
</div>
</section>
<SearchModal />
</Layout>
<style>
.blog-grid-section {
padding: 3rem 0;
background: #f8fafc;
}
.blog-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
}
.no-results {
grid-column: 1 / -1;
text-align: center;
padding: 4rem 0;
color: #64748b;
}
.back-link {
display: inline-block;
margin-top: 1rem;
color: #d4af37;
text-decoration: underline;
}
@media (max-width: 1024px) {
.blog-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 768px) {
.blog-grid {
grid-template-columns: 1fr;
gap: 1.5rem;
}
}
</style>
<script>
const setupAnimations = () => {
const observerOptions = {
root: null,
rootMargin: '0px 0px -50px 0px',
threshold: 0.1
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target as HTMLElement;
const delay = parseInt(el.dataset.delay || '0');
setTimeout(() => {
el.classList.add('is-visible');
}, delay);
observer.unobserve(el);
}
});
}, observerOptions);
document.querySelectorAll('.animate-on-scroll').forEach((el) => {
observer.observe(el);
});
};
setupAnimations();
document.addEventListener('astro:page-load', setupAnimations);
</script>

View file

@ -0,0 +1,172 @@
---
import Layout from '@layouts/Layout.astro';
import { SITE_URL } from '@constants';
import PageHero from '@components/base/PageHero.astro';
import BlogCategories from '@components/blog/BlogCategories.astro';
import BlogCard from '@components/blog/BlogCard.astro';
import Pagination from '@components/base/Pagination.astro';
import SearchModal from '@components/base/SearchModal.astro';
import { getPosts, getAllCategories, getPostImageUrl } from '@lib/pb';
export const prerender = false;
const POSTS_PER_PAGE = 6;
const categorySlug = Astro.params.category || '';
const currentPage = Number(Astro.params.page) || 1;
const categories = await getAllCategories();
const categoryName = categories.find(c => c.toLowerCase() === categorySlug.toLowerCase()) || categorySlug;
const { posts, total, totalPages } = await getPosts({
category: categoryName,
page: currentPage,
perPage: POSTS_PER_PAGE
});
const formatDate = (date: string) => {
const d = new Date(date);
const day = d.getDate().toString().padStart(2, '0');
const month = (d.getMonth() + 1).toString().padStart(2, '0');
const year = new Date().getFullYear().toString().slice(-2);
return `${day}/${month}/${year}`;
};
---
<Layout
title={`${categoryName} — автоюрист в Сургуте`}
description={`Статьи по теме "${categoryName}" — автоюрист в Сургуте. Полезные статьи и советы по автоспорам.`}
canonicalLink={`${SITE_URL}/blog/category/${categorySlug}`}
breadcrumbs={[
{ label: 'Главная', href: '/' },
{ label: 'Блог', href: '/blog' },
{ label: categoryName }
]}
>
<PageHero
badgeText={categoryName.toUpperCase()}
titleWhite={categoryName}
titleGold="статьи"
description={`Полезные статьи и советы по теме "${categoryName}" от автоюриста в Сургуте.`}
layout="with-image"
sideImage="/images/blog/blogImg.avif"
sideImageAlt="Автоюрист Сургут"
experienceBadge={{
number: String(total),
text: "СТАТЕЙ"
}}
bgImage="/images/blog/blogBg.avif"
/>
<BlogCategories categories={categories} activeCategory={categoryName} currentPage={currentPage} />
<section class="blog-grid-section">
<div class="site-container">
<div class="blog-grid" id="blog-grid">
{posts.length > 0 ? (
posts.map((post: any) => (
<article class="blog-card-wrapper" data-category={post.category}>
<BlogCard
title={post.title}
description={post.description}
category={post.category}
categoryColor={post.categoryColor}
date={formatDate(post.date)}
readTime={post.readTime}
readmeTime={post.readmeTime}
image={getPostImageUrl(post)}
slug={`/blog/${post.slug}`}
/>
</article>
))
) : (
<div class="no-results">
<p>Статьи по теме "{categoryName}" не найдены</p>
<a href="/blog" class="back-link">Вернуться к списку статей</a>
</div>
)}
{totalPages > 1 && (
<Pagination
currentPage={currentPage}
totalPages={totalPages}
baseUrl={`/blog/category/${categorySlug}`}
/>
)}
</div>
</div>
</section>
<SearchModal />
</Layout>
<style>
.blog-grid-section {
padding: 3rem 0;
background: #f8fafc;
}
.blog-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
}
.no-results {
grid-column: 1 / -1;
text-align: center;
padding: 4rem 0;
color: #64748b;
}
.back-link {
display: inline-block;
margin-top: 1rem;
color: #d4af37;
text-decoration: underline;
}
@media (max-width: 1024px) {
.blog-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 768px) {
.blog-grid {
grid-template-columns: 1fr;
gap: 1.5rem;
}
}
</style>
<script>
const setupAnimations = () => {
const observerOptions = {
root: null,
rootMargin: '0px 0px -50px 0px',
threshold: 0.1
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target as HTMLElement;
const delay = parseInt(el.dataset.delay || '0');
setTimeout(() => {
el.classList.add('is-visible');
}, delay);
observer.unobserve(el);
}
});
}, observerOptions);
document.querySelectorAll('.animate-on-scroll').forEach((el) => {
observer.observe(el);
});
};
setupAnimations();
document.addEventListener('astro:page-load', setupAnimations);
</script>

View file

@ -183,7 +183,7 @@ const formatDate = (date: string) => {
setupAnimations();
setupFilter();
document.addEventListener('astro:after-swap', () => {
document.addEventListener('astro:page-load', () => {
setupAnimations();
setupFilter();
});

View file

@ -149,5 +149,5 @@ const formatDate = (date: string) => {
};
setupAnimations();
document.addEventListener('astro:after-swap', setupAnimations);
document.addEventListener('astro:page-load', setupAnimations);
</script>

View file

@ -346,7 +346,7 @@ const isAuthorized = false; // Измените на true, чтобы увиде
setupForm();
// Для поддержки Astro transitions
document.addEventListener('astro:after-swap', () => {
document.addEventListener('astro:page-load', () => {
setupAnimations();
setupForm();
});

View file

@ -182,7 +182,7 @@ const categories = getCategories();
setupFilter();
document.addEventListener('astro:after-swap', () => {
document.addEventListener('astro:page-load', () => {
setupFilter();
});
</script>

View file

@ -197,7 +197,7 @@ import ReviewsList from '@components/reviews/ReviewsList.astro';
setupAnimations();
// Для поддержки View Transitions в Astro
document.addEventListener('astro:after-swap', () => {
document.addEventListener('astro:page-load', () => {
setupAnimations();
});
</script>