Files
profile-front/src/components/ContentGrid_no_infinity.astro
Profile Profile 1b4be186a7 add components
2026-03-09 22:02:36 +03:00

164 lines
4.9 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
export interface Props {
items: any[];
showCount?: boolean;
}
const {
items = [],
showCount = false,
} = Astro.props;
// Функция для извлечения класса цвета из строки
function extractColorClass(colorString: string): string {
if (!colorString) return 'bg-blue';
if (colorString.includes('фон меню:')) {
const parts = colorString.split(':');
const color = parts[1]?.trim();
const validColors = [
'black', 'yellow', 'blue', 'green', 'red', 'orange', 'gray',
'indigo', 'purple', 'pink', 'teal', 'cyan', 'white',
'gray-dark', 'light', 'dark'
];
if (color && validColors.includes(color)) {
return `bg-${color}`;
}
}
if (colorString.startsWith('bg-')) {
return colorString;
}
const simpleColor = colorString.toLowerCase();
switch(simpleColor) {
case 'black': case 'yellow': case 'blue': case 'green':
case 'red': case 'orange': case 'gray': case 'indigo':
case 'purple': case 'pink': case 'teal': case 'cyan':
case 'white': case 'dark': case 'light':
return `bg-${simpleColor}`;
case 'gray-dark': return 'bg-gray-dark';
default: return 'bg-blue';
}
}
// Функция для получения списка имен соавторов
function getCoauthorsNames(coauthors: any[]): string {
if (!coauthors || coauthors.length === 0) return '';
return coauthors
.map((coauthor: any) => coauthor?.node?.name || coauthor?.name)
.filter(Boolean)
.join(' ');
}
---
<section class="posts-section" id="posts-section">
<h2>
{showCount && items.length > 0 && (
<span id="posts-count"> ({items.length})</span>
)}
</h2>
<div id="posts-grid" class="posts-grid">
{items.map((item, index) => {
const postUrl = item.uri || `/blog/${item.databaseId}`;
const postDate = new Date(item.date);
const coauthors = item.coauthors || [];
const coauthorsNames = getCoauthorsNames(coauthors);
const rawColor = item.categories?.nodes?.[0]?.color || '';
const categoryBgClass = extractColorClass(rawColor);
let isLarge = false;
let largePosition = '';
const rowNumber = Math.floor(index / 4) + 1;
const positionInRow = index % 4;
if (index >= 8) {
const largeRowStart = (rowNumber - 3) % 3 === 0 && rowNumber >= 3;
if (largeRowStart && positionInRow === 0) {
isLarge = true;
largePosition = 'first';
}
}
return (
<article
class={`post-card ${isLarge ? 'post-card-large' : ''}`}
data-large-position={isLarge ? largePosition : ''}
data-index={index}
itemscope
itemtype="https://schema.org/BlogPosting"
>
<a href={postUrl} class="post-card-link">
<div class="post-image-container">
{item.featuredImage?.node?.sourceUrl ? (
<img
src={item.featuredImage.node.sourceUrl}
alt={item.featuredImage.node.altText || item.title}
width="400"
height="400"
loading="lazy"
class="post-image"
itemprop="image"
/>
) : (
<div class="post-image-placeholder"></div>
)}
{item.categories?.nodes?.[0]?.name && (
<div class={`post-category-badge ${categoryBgClass}`}>
{item.categories.nodes[0].name}
</div>
)}
<div class="post-content-overlay">
<div class="post-meta-overlay">
<time
datetime={item.date}
class="post-date-overlay"
itemprop="datePublished"
>
{postDate.toLocaleDateString('ru-RU', {
day: 'numeric',
month: 'short',
year: 'numeric'
}).replace(' г.', '')}
</time>
</div>
<h3 class="post-title-overlay" itemprop="headline">
{item.title}
</h3>
{coauthorsNames && (
<div class="author-name" itemprop="author">
{coauthorsNames}
</div>
)}
</div>
</div>
</a>
<div class="sr-only">
<h3 itemprop="headline">
<a href={postUrl} itemprop="url">{item.title}</a>
</h3>
<time
datetime={item.date}
itemprop="datePublished"
>
{postDate.toLocaleDateString('ru-RU')}
</time>
</div>
</article>
);
})}
</div>
</section>