Насторил работу блога через Backend
This commit is contained in:
parent
014439d565
commit
edd730b438
33 changed files with 1019 additions and 200 deletions
|
|
@ -1,26 +1,5 @@
|
|||
---
|
||||
import { getCollection } from 'astro:content';
|
||||
|
||||
const posts = await getCollection('blog');
|
||||
|
||||
// Сортируем и форматируем для поиска
|
||||
const searchData = posts
|
||||
.sort((a, b) => b.data.date.getTime() - a.data.date.getTime())
|
||||
.map(post => ({
|
||||
title: post.data.title,
|
||||
description: post.data.description,
|
||||
slug: post.id,
|
||||
category: post.data.category,
|
||||
categoryColor: post.data.categoryColor,
|
||||
date: post.data.date.toLocaleDateString('ru-RU', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric'
|
||||
})
|
||||
}));
|
||||
|
||||
const title = 'Поиск по статьям';
|
||||
const postsJson = JSON.stringify(searchData);
|
||||
---
|
||||
|
||||
<div id="search-modal" class="modal-overlay" aria-hidden="true">
|
||||
|
|
@ -61,16 +40,33 @@ const postsJson = JSON.stringify(searchData);
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script define:vars={{ postsJson }}>
|
||||
<script>
|
||||
(function() {
|
||||
const modal = document.getElementById('search-modal');
|
||||
const closeBtn = document.getElementById('search-modal-close-btn');
|
||||
const searchInput = document.getElementById('search-input');
|
||||
const resultsContainer = document.getElementById('search-results');
|
||||
const posts = JSON.parse(postsJson);
|
||||
let postsCache = null;
|
||||
|
||||
if (!modal || !searchInput || !resultsContainer) return;
|
||||
|
||||
async function fetchPosts() {
|
||||
if (postsCache) return postsCache;
|
||||
try {
|
||||
const res = await fetch('/api/posts?per_page=100');
|
||||
const data = await res.json();
|
||||
postsCache = data.posts || [];
|
||||
return postsCache;
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function formatDate(dateStr) {
|
||||
const d = new Date(dateStr);
|
||||
return d.toLocaleDateString('ru-RU', { day: 'numeric', month: 'long', year: 'numeric' });
|
||||
}
|
||||
|
||||
function openModal() {
|
||||
modal.classList.add('active');
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
|
|
@ -86,7 +82,7 @@ const postsJson = JSON.stringify(searchData);
|
|||
resultsContainer.innerHTML = '';
|
||||
}
|
||||
|
||||
function handleSearch(query) {
|
||||
async function handleSearch(query) {
|
||||
const trimmed = query.trim().toLowerCase();
|
||||
|
||||
if (trimmed.length < 2) {
|
||||
|
|
@ -94,6 +90,8 @@ const postsJson = JSON.stringify(searchData);
|
|||
return;
|
||||
}
|
||||
|
||||
const posts = await fetchPosts();
|
||||
|
||||
const filtered = posts.filter(post =>
|
||||
post.title.toLowerCase().includes(trimmed) ||
|
||||
post.description.toLowerCase().includes(trimmed) ||
|
||||
|
|
@ -112,10 +110,9 @@ const postsJson = JSON.stringify(searchData);
|
|||
return;
|
||||
}
|
||||
|
||||
// вывод динамического списка статей
|
||||
resultsContainer.innerHTML = filtered.map(post => `
|
||||
<a href="/blog/${post.id}" class="search-result-item">
|
||||
<span class="result-date">${post.date}</span>
|
||||
<a href="/blog/${post.slug}" class="search-result-item">
|
||||
<span class="result-date">${formatDate(post.date)}</span>
|
||||
<h4 class="result-title">${post.title}</h4>
|
||||
<p class="result-description">${post.description.substring(0, 120)}...</p>
|
||||
<span class="result-arrow">
|
||||
|
|
|
|||
|
|
@ -1,29 +1,28 @@
|
|||
---
|
||||
import BlogCard from '@components/blog/BlogCard.astro';
|
||||
|
||||
interface CollectionEntry {
|
||||
interface Post {
|
||||
id: string;
|
||||
data: {
|
||||
title: string;
|
||||
description: string;
|
||||
category: string;
|
||||
categoryColor: string;
|
||||
date: Date;
|
||||
readTime: string;
|
||||
imageUrl: string;
|
||||
};
|
||||
slug: string;
|
||||
title: string;
|
||||
description: string;
|
||||
category: string;
|
||||
categoryColor: string;
|
||||
date: string;
|
||||
readTime: string;
|
||||
imageUrl: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
posts: CollectionEntry[];
|
||||
posts: Post[];
|
||||
currentSlug?: string;
|
||||
}
|
||||
|
||||
const { posts, currentSlug } = Astro.props;
|
||||
|
||||
// Форматируем дату
|
||||
const formatDate = (date: Date) => {
|
||||
return date.toLocaleDateString('ru-RU', {
|
||||
const formatDate = (date: string) => {
|
||||
return new Date(date).toLocaleDateString('ru-RU', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric'
|
||||
|
|
@ -32,7 +31,7 @@ const formatDate = (date: Date) => {
|
|||
|
||||
// Фильтруем текущую статью
|
||||
const filteredPosts = currentSlug
|
||||
? posts.filter(post => post.id !== currentSlug).slice(0, 3)
|
||||
? posts.filter(post => post.slug !== currentSlug).slice(0, 3)
|
||||
: posts.slice(0, 3);
|
||||
---
|
||||
|
||||
|
|
@ -42,14 +41,14 @@ const filteredPosts = currentSlug
|
|||
<div class="related-grid">
|
||||
{filteredPosts.map((post) => (
|
||||
<BlogCard
|
||||
title={post.data.title}
|
||||
description={post.data.description}
|
||||
category={post.data.category}
|
||||
categoryColor={post.data.categoryColor}
|
||||
date={formatDate(post.data.date)}
|
||||
readTime={post.data.readTime}
|
||||
imageUrl={post.data.imageUrl}
|
||||
slug={`/blog/${post.id}`}
|
||||
title={post.title}
|
||||
description={post.description}
|
||||
category={post.category}
|
||||
categoryColor={post.categoryColor}
|
||||
date={formatDate(post.date)}
|
||||
readTime={post.readTime}
|
||||
imageUrl={post.imageUrl}
|
||||
slug={`/blog/${post.slug}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue