diff --git a/src/components/ContentGrid.astro b/src/components/ContentGrid.astro index f9d50f0..84fe33b 100644 --- a/src/components/ContentGrid.astro +++ b/src/components/ContentGrid.astro @@ -2,14 +2,24 @@ export interface Props { items: any[]; showCount?: boolean; + pageInfo?: { + hasNextPage: boolean; + endCursor: string | null; + }; + loadMoreConfig?: { + type: 'latest' | 'category' | 'author' | 'tag'; + slug?: string; + first?: number; + }; } const { items = [], showCount = false, + pageInfo = { hasNextPage: false, endCursor: null }, + loadMoreConfig = { type: 'latest', first: 11 } } = Astro.props; -// Функция для извлечения класса цвета из строки function extractColorClass(colorString: string): string { if (!colorString) return 'bg-blue'; @@ -44,7 +54,6 @@ function extractColorClass(colorString: string): string { } } -// Функция для получения списка имен соавторов function getCoauthorsNames(coauthors: any[]): string { if (!coauthors || coauthors.length === 0) return ''; @@ -53,6 +62,14 @@ function getCoauthorsNames(coauthors: any[]): string { .filter(Boolean) .join(' '); } + +// ✅ ИСПРАВЛЕННАЯ функция для определения больших карточек +// Большие карточки на индексах: 8, 19, 30, 41, 52... +// Формула: (index - 8) % 11 === 0 +function shouldBeLarge(index: number): boolean { + if (index < 8) return false; + return (index - 8) % 11 === 0; +} ---
@@ -72,25 +89,14 @@ function getCoauthorsNames(coauthors: any[]): string { 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'; - } - } + // ✅ ИСПРАВЛЕННАЯ логика + const isLarge = shouldBeLarge(index); + const largePosition = isLarge ? 'first' : ''; return (
+ + + + + + + + + {pageInfo.hasNextPage && ( +
+ )}
+ + diff --git a/src/pages/api/posts.ts b/src/pages/api/posts.ts new file mode 100644 index 0000000..e511543 --- /dev/null +++ b/src/pages/api/posts.ts @@ -0,0 +1,78 @@ +import type { APIRoute } from 'astro'; + +// ✅ Добавьте эту строку! +export const prerender = false; + +export const POST: APIRoute = async ({ request }) => { + console.log('[API] Request received'); + console.log('[API] Content-Type:', request.headers.get('content-type')); + + try { + // ✅ Используйте request.text() вместо request.json() + const rawBody = await request.text(); + console.log('[API] Raw body length:', rawBody?.length || 0); + console.log('[API] Raw body:', rawBody); + + if (!rawBody || rawBody.trim() === '') { + throw new Error('Request body is empty'); + } + + const body = JSON.parse(rawBody); + console.log('[API] Parsed body:', body); + + const { + first = 14, + after = null, + type = 'latest', + slug = null + } = body; + + console.log('[API] Parsed params:', { first, after, type, slug }); + + // ✅ Используйте относительный путь, НЕ алиас @api + const { getLatestPosts } = await import('../../lib/api/posts.js'); + + console.log('[API] Calling getLatestPosts with:', { first, after }); + + const data = await getLatestPosts(first, after); + + console.log('[API] Data received:', { + postsCount: data?.posts?.length || 0, + hasNextPage: data?.pageInfo?.hasNextPage, + endCursor: data?.pageInfo?.endCursor + }); + + if (!data || !data.posts) { + throw new Error('Invalid data structure returned from getLatestPosts'); + } + + return new Response(JSON.stringify(data), { + status: 200, + headers: { + 'Content-Type': 'application/json', + }, + }); + + } catch (error) { + console.error('[API] Error details:', { + message: error.message, + stack: error.stack, + name: error.name + }); + + return new Response( + JSON.stringify({ + error: error.message || 'Ошибка загрузки постов', + details: process.env.NODE_ENV === 'development' ? error.stack : undefined, + posts: [], + pageInfo: { hasNextPage: false, endCursor: null } + }), + { + status: 500, + headers: { + 'Content-Type': 'application/json', + }, + } + ); + } +}; diff --git a/src/pages/index.astro b/src/pages/index.astro index 6e31374..dbb4601 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -3,17 +3,15 @@ import { getSiteInfo } from "../lib/wp-api.js"; import { getLatestPosts } from '@api/posts.js'; const site = await getSiteInfo(); -const initialPosts = await getLatestPosts(37); // Начальная загрузка 12 постов +const { posts, pageInfo } = await getLatestPosts(41); // Сразу деструктурируем // визуальные компоненты import MainLayout from '@layouts/MainLayout.astro'; import ContentGrid from '@components/ContentGrid.astro'; import EndnewsList from '@components/EndnewsList.astro'; - //ISR export const prerender = false; -//export const revalidate = 1; --- - - + - - \ No newline at end of file + diff --git a/src/styles/components/ContentGrid.css b/src/styles/components/ContentGrid.css index a5cee93..ca49317 100644 --- a/src/styles/components/ContentGrid.css +++ b/src/styles/components/ContentGrid.css @@ -167,6 +167,34 @@ font-weight: 400; } +/* Убедитесь что индикаторы не занимают лишнее место */ +#infinity-scroll-sentinel { + height: 1px; + width: 100%; + visibility: hidden; + pointer-events: none; +} + +.loading-indicator { + text-align: center; + padding: 40px 0; + color: #666; + min-height: auto; /* ← Важно! */ +} + +.no-more-posts { + text-align: center; + padding: 30px 0; + color: #666; + font-size: 16px; + border-top: 1px solid #eee; + margin-top: 20px; + min-height: auto; /* ← Важно! */ +} + + + + /* Улучшения для больших карточек */ @media (min-width: 1200px) { .post-card-large .post-category-badge {