Новые изменения в компоенты
This commit is contained in:
parent
acb7b88ff1
commit
9122756a58
11 changed files with 360 additions and 13 deletions
|
|
@ -207,5 +207,5 @@ const iconPaths: Record<string, string> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
setupAnimations();
|
setupAnimations();
|
||||||
document.addEventListener('astro:after-swap', setupAnimations);
|
document.addEventListener('astro:page-load', setupAnimations);
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -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-inner animate-on-scroll" data-animation="fade-up">
|
||||||
<div class="categories-wrapper">
|
<div class="categories-wrapper">
|
||||||
{categories.map((cat) => (
|
{categories.map((cat) => (
|
||||||
<a
|
<button
|
||||||
href={cat === 'Все' ? '/blog' : `/blog/category/${cat.toLowerCase()}`}
|
|
||||||
class={`category-btn ${cat === activeCategory ? 'active' : ''}`}
|
class={`category-btn ${cat === activeCategory ? 'active' : ''}`}
|
||||||
data-category={cat}
|
data-category={cat}
|
||||||
>
|
>
|
||||||
{cat}
|
{cat}
|
||||||
</a>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -100,7 +99,6 @@ const { categories, activeCategory = 'Все', currentPage = 1 } = Astro.props;
|
||||||
border-color: #d4af37;
|
border-color: #d4af37;
|
||||||
color: #1e293b;
|
color: #1e293b;
|
||||||
box-shadow: 0 4px 12px rgba(212, 175, 55, 0.3);
|
box-shadow: 0 4px 12px rgba(212, 175, 55, 0.3);
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Анимации */
|
/* Анимации */
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,7 @@ const colors = ['bg-gradient-1', 'bg-gradient-2', 'bg-gradient-3', 'bg-gradient-
|
||||||
setupSlider();
|
setupSlider();
|
||||||
setupAnimations();
|
setupAnimations();
|
||||||
|
|
||||||
document.addEventListener('astro:after-swap', () => {
|
document.addEventListener('astro:page-load', () => {
|
||||||
setupSlider();
|
setupSlider();
|
||||||
setupAnimations();
|
setupAnimations();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -71,11 +71,17 @@ const { title, description, canonicalLink, breadcrumbs } = Astro.props;
|
||||||
sessionStorage.setItem('scrollPosition', String(window.scrollY));
|
sessionStorage.setItem('scrollPosition', String(window.scrollY));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Восстанавливаем позицию скролла после перехода
|
// Восстанавливаем позицию скролла после перехода с плавной анимацией
|
||||||
document.addEventListener('astro:after-swap', () => {
|
document.addEventListener('astro:after-swap', () => {
|
||||||
const savedPosition = sessionStorage.getItem('scrollPosition');
|
const savedPosition = sessionStorage.getItem('scrollPosition');
|
||||||
if (savedPosition) {
|
if (savedPosition) {
|
||||||
window.scrollTo(0, parseInt(savedPosition));
|
const targetScroll = parseInt(savedPosition);
|
||||||
|
setTimeout(() => {
|
||||||
|
window.scrollTo({
|
||||||
|
top: targetScroll,
|
||||||
|
behavior: 'auto'
|
||||||
|
});
|
||||||
|
}, 50);
|
||||||
sessionStorage.removeItem('scrollPosition');
|
sessionStorage.removeItem('scrollPosition');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
171
frontend/src/pages/blog/category/[category].astro
Normal file
171
frontend/src/pages/blog/category/[category].astro
Normal 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>
|
||||||
172
frontend/src/pages/blog/category/[category]/page/[page].astro
Normal file
172
frontend/src/pages/blog/category/[category]/page/[page].astro
Normal 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>
|
||||||
|
|
@ -183,7 +183,7 @@ const formatDate = (date: string) => {
|
||||||
|
|
||||||
setupAnimations();
|
setupAnimations();
|
||||||
setupFilter();
|
setupFilter();
|
||||||
document.addEventListener('astro:after-swap', () => {
|
document.addEventListener('astro:page-load', () => {
|
||||||
setupAnimations();
|
setupAnimations();
|
||||||
setupFilter();
|
setupFilter();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -149,5 +149,5 @@ const formatDate = (date: string) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
setupAnimations();
|
setupAnimations();
|
||||||
document.addEventListener('astro:after-swap', setupAnimations);
|
document.addEventListener('astro:page-load', setupAnimations);
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -346,7 +346,7 @@ const isAuthorized = false; // Измените на true, чтобы увиде
|
||||||
setupForm();
|
setupForm();
|
||||||
|
|
||||||
// Для поддержки Astro transitions
|
// Для поддержки Astro transitions
|
||||||
document.addEventListener('astro:after-swap', () => {
|
document.addEventListener('astro:page-load', () => {
|
||||||
setupAnimations();
|
setupAnimations();
|
||||||
setupForm();
|
setupForm();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ const categories = getCategories();
|
||||||
|
|
||||||
setupFilter();
|
setupFilter();
|
||||||
|
|
||||||
document.addEventListener('astro:after-swap', () => {
|
document.addEventListener('astro:page-load', () => {
|
||||||
setupFilter();
|
setupFilter();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ import ReviewsList from '@components/reviews/ReviewsList.astro';
|
||||||
setupAnimations();
|
setupAnimations();
|
||||||
|
|
||||||
// Для поддержки View Transitions в Astro
|
// Для поддержки View Transitions в Astro
|
||||||
document.addEventListener('astro:after-swap', () => {
|
document.addEventListener('astro:page-load', () => {
|
||||||
setupAnimations();
|
setupAnimations();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue