164 lines
4.9 KiB
Plaintext
164 lines
4.9 KiB
Plaintext
|
|
---
|
|||
|
|
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>
|