astro_redi/frontend/src/components/blog/PostsLoop.astro

92 lines
3.3 KiB
Text
Raw Normal View History

2026-03-26 03:56:25 +00:00
---
import type { Post } from '@globalInterfaces';
interface Props {
posts: Post[];
}
const { posts } = Astro.props;
function formatDate(date: string): string {
if (!date) return '';
return new Date(date).toLocaleString('ru-RU', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
}
---
{
posts.map((post) => {
const postLink = `/blog/${post.slug}`;
const formattedDate = formatDate(post.publishDate);
const displayTitle = post.title.replace('{year}', new Date().getFullYear().toString());
return (
<div class="relative p-6 md:p-7 rounded-2xl border border-neutral-200 dark:border-neutral-800 bg-white dark:bg-neutral-950 hover:border-neutral-300 dark:hover:border-neutral-700 transition-colors duration-300 group">
{/*
ГЛАВНАЯ ССЫЛКА
z-0 - самый нижний слой
*/}
<a href={postLink} class="absolute inset-0 z-0" aria-label={`Читать: ${displayTitle}`}></a>
{/*
КОНТЕНТ
z-10 - слой выше
*/}
<div class="relative z-10 pointer-events-none">
{/*
ВЕРХНЯЯ СТРОКА:
Слева - декоративная линия
Справа - Дата
*/}
<div class="flex items-center justify-between mb-4">
{/* Слева: Декоративная линия ("строка") */}
<div class="w-12 h-0.5 bg-neutral-200 dark:bg-neutral-800 rounded-full group-hover:bg-neutral-300 dark:group-hover:bg-neutral-700 transition-colors"></div>
{/* Справа: Дата */}
<div class="flex items-center gap-2 text-xs text-neutral-500">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-4 h-4 text-neutral-400">
<path fill-rule="evenodd" d="M6.75 2.25A.75.75 0 017.5 3v1.5h9V3A.75.75 0 0118 3v1.5h.75a3 3 0 013 3v11.25a3 3 0 01-3 3H5.25a3 3 0 01-3-3V7.5a3 3 0 013-3H6V3a.75.75 0 01.75-.75zm13.5 9a1.5 1.5 0 00-1.5-1.5H5.25a1.5 1.5 0 00-1.5 1.5v7.5a1.5 1.5 0 001.5 1.5h13.5a1.5 1.5 0 001.5-1.5v-7.5z" clip-rule="evenodd" />
</svg>
<span class="font-medium">{formattedDate}</span>
</div>
</div>
{/* Заголовок */}
<h2 class="text-xl font-bold text-neutral-900 dark:text-neutral-100 mb-2 group-hover:text-indigo-600 dark:group-hover:text-indigo-400 transition-colors">
{displayTitle}
</h2>
{/* Описание */}
<p class="text-sm text-neutral-600 dark:text-neutral-400 leading-relaxed line-clamp-2 mb-4">
{post.description}
</p>
</div>
{/*
НИЗ: Теги
z-20 - верхний слой, клики включены
*/}
{post.tags && post.tags.length > 0 && (
<div class="relative z-20 mt-auto pt-4 border-t border-neutral-100 dark:border-neutral-900 flex flex-wrap gap-2 pointer-events-auto">
{post.tags.map((tag) => (
<a
href={`/blog/tags/${tag.toLowerCase()}`}
class="text-xs text-neutral-500 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors bg-neutral-50 dark:bg-neutral-900/50 px-2 py-1 rounded"
>
#{tag}
</a>
))}
</div>
)}
</div>
);
})
}