From 636bc4715575fe6cc9d69fa8ef2f52384873fef8 Mon Sep 17 00:00:00 2001 From: Profile Profile Date: Sun, 15 Mar 2026 01:17:42 +0300 Subject: [PATCH] add support pages --- src/lib/api/pages.ts | 85 ++++++++++++++++++++++++ src/lib/detect-page-type.ts | 116 +++++++++++++++++++++++--------- src/pages/[...slug].astro | 127 ++++++++++++++++++------------------ 3 files changed, 232 insertions(+), 96 deletions(-) create mode 100644 src/lib/api/pages.ts diff --git a/src/lib/api/pages.ts b/src/lib/api/pages.ts new file mode 100644 index 0000000..39908ca --- /dev/null +++ b/src/lib/api/pages.ts @@ -0,0 +1,85 @@ +import { fetchGraphQL } from './graphql-client.js'; + +/** подключаем страницу по slug */ +interface PageData { + id: string; + title: string; + content: string; + image: string | null; + imageAlt: string; + type: 'page'; +} + +// Интерфейс для ответа GraphQL +interface GraphQLResponse { + data?: { + pages?: { + nodes: Array<{ + id: string; + title: string; + content: string; + slug: string; + featuredImage?: { + node: { + sourceUrl: string; + altText: string; + }; + } | null; + }>; + }; + }; +} + +export async function getPageBySlug(slug: string): Promise { + if (!slug) return null; + + const query = ` + query GetPageBySlug($slug: String!) { + pages(where: {name: $slug}) { + nodes { + id + title + content + slug + featuredImage { + node { + sourceUrl(size: LARGE) + altText + } + } + } + } + } + `; + + try { + // Получаем данные + const response = await fetchGraphQL(query, { slug }); + + // ПРОВЕРЯЕМ СТРУКТУРУ ОТВЕТА + console.log('🔍 FULL RESPONSE:', JSON.stringify(response, null, 2)); + + // Пробуем разные варианты доступа к данным + const pages = response?.data?.pages?.nodes || response?.pages?.nodes || []; + const page = pages[0]; + + if (!page) { + console.log('❌ No page found for slug:', slug); + return null; + } + + console.log('✅ Page found:', page.title); + + return { + id: page.id, + title: page.title, + content: page.content, + image: page.featuredImage?.node?.sourceUrl || null, + imageAlt: page.featuredImage?.node?.altText || page.title || '', + type: 'page' + }; + } catch (error) { + console.error('❌ Error in getPageBySlug:', error); + return null; + } +} \ No newline at end of file diff --git a/src/lib/detect-page-type.ts b/src/lib/detect-page-type.ts index a65550a..4ae3684 100644 --- a/src/lib/detect-page-type.ts +++ b/src/lib/detect-page-type.ts @@ -1,3 +1,5 @@ +import { wpInfo } from './wpInfo'; + export interface PageTypeInfo { type: 'single' | 'archive' | 'home' | 'unknown'; contentType?: 'news' | 'post'; @@ -5,14 +7,33 @@ export interface PageTypeInfo { postSlug?: string; postId?: number; page: number; + pageSlug?: string; uriParts: string[]; } - export function detectPageType(uri: string): PageTypeInfo { + //console.log('🔍 detectPageType INPUT:', uri); + + // Убираем query параметры если есть + const uriWithoutQuery = uri.split('?')[0]; + // Убираем слэши по краям - const cleanUri = uri.replace(/^\/|\/$/g, ''); - const parts = cleanUri ? cleanUri.split('/') : []; + const cleanUri = uriWithoutQuery.replace(/^\/|\/$/g, ''); + + console.log('📌 Clean URI:', cleanUri); + + // Если URI пустой - это главная + if (cleanUri === '') { + console.log('🏠 Home page detected'); + return { + type: 'home', + page: 1, + uriParts: [] + }; + } + + const parts = cleanUri.split('/'); + console.log('📦 Parts:', parts); // Ищем пагинацию const processedParts: string[] = []; @@ -23,20 +44,27 @@ export function detectPageType(uri: string): PageTypeInfo { const pageNum = parseInt(parts[i + 1]); if (pageNum > 0) { page = pageNum; - i++; // Пропускаем номер страницы + i++; continue; } } processedParts.push(parts[i]); } + //console.log('🔄 Processed parts:', processedParts); + // Определяем, это новость или нет const isNews = processedParts[0] === 'news'; + //console.log('📰 isNews:', isNews); // Для анализа убираем 'news' из начала если есть const partsWithoutNews = isNews ? processedParts.slice(1) : processedParts; - const partsCount = partsWithoutNews.length; + //console.log('✂️ Parts without news:', partsWithoutNews); + const partsCount = partsWithoutNews.length; + //console.log('🔢 Parts count:', partsCount); + + // Домашняя страница if (partsCount === 0) { return { type: 'home', @@ -45,42 +73,66 @@ export function detectPageType(uri: string): PageTypeInfo { }; } + // Проверяем, является ли последний сегмент постом (содержит ID) + const lastPart = partsWithoutNews[partsWithoutNews.length - 1]; + //console.log('🔚 Last part:', lastPart); + + const match = lastPart.match(/-(\d+)$/); + //console.log('🎯 Post ID match:', match); + // Одиночный пост - if (partsCount === 1 || partsCount === 2) { - const lastPart = partsWithoutNews[partsWithoutNews.length - 1]; - const match = lastPart.match(/-(\d+)$/); - - if (match) { - const id = parseInt(match[1]); - if (id > 0) { - const slugWithoutId = lastPart.substring(0, lastPart.lastIndexOf('-')); - - return { - type: 'single', - contentType: isNews ? 'news' : 'post', // Теперь правильно - categorySlug: partsCount === 2 ? partsWithoutNews[0] : undefined, - postSlug: slugWithoutId, - postId: id, - page, - uriParts: processedParts // Сохраняем исходные части - }; - } + if (match) { + const id = parseInt(match[1]); + if (id > 0) { + const slugWithoutId = lastPart.substring(0, lastPart.lastIndexOf('-')); + + //console.log('📄 Single post detected:', { id, slugWithoutId }); + + return { + type: 'single', + contentType: isNews ? 'news' : 'post', + categorySlug: partsCount === 2 ? partsWithoutNews[0] : undefined, + postSlug: slugWithoutId, + postId: id, + page, + uriParts: processedParts + }; } } - // Рубрика + // Проверяем, является ли первый сегмент существующей рубрикой if (partsCount === 1) { - return { - type: 'archive', - contentType: isNews ? 'news' : undefined, - categorySlug: partsWithoutNews[0], - page, - uriParts: processedParts - }; + const potentialCategorySlug = partsWithoutNews[0]; + //console.log('📁 Checking if category exists:', potentialCategorySlug); + + // Ждем загрузки рубрик если нужно + if (!wpInfo.isLoaded()) { + //console.log('⏳ Waiting for categories to load...'); + // В синхронной функции не можем ждать, поэтому проверяем позже + } + + const category = wpInfo.getCategoryBySlug(potentialCategorySlug); + //console.log('🏷️ Category found:', category ? 'YES' : 'NO'); + + if (category) { + //console.log('📁 Archive detected (existing category):', potentialCategorySlug); + return { + type: 'archive', + contentType: isNews ? 'news' : undefined, + categorySlug: potentialCategorySlug, + page, + uriParts: processedParts + }; + } } + // Если это не рубрика - это обычная страница + const pageSlug = partsWithoutNews.join('/'); + //console.log('📄 PAGE DETECTED with slug:', pageSlug); + return { type: 'unknown', + pageSlug: pageSlug, page, uriParts: processedParts }; diff --git a/src/pages/[...slug].astro b/src/pages/[...slug].astro index a13fc19..56c2ff9 100644 --- a/src/pages/[...slug].astro +++ b/src/pages/[...slug].astro @@ -4,92 +4,91 @@ import NewsSingle from '@components/NewsSingle.astro'; import ContentGrid from '@components/ContentGrid.astro'; import { getNodeByURI } from '@lib/api/all'; -import { getProfileArticleById, getPostsByCategory } from '@lib/api/posts'; //логика +import { getProfileArticleById, getPostsByCategory } from '@lib/api/posts'; +import { getPageBySlug } from '@lib/api/pages'; - -import { getCategory } from '@lib/api/categories'; //логика +import { getCategory } from '@lib/api/categories'; import { wpInfo } from '@lib/wpInfo'; import { detectPageType } from '@lib/detect-page-type'; export const prerender = false; const pathname = Astro.url.pathname; -const pageInfo = detectPageType(pathname); //определяем тип страницы - -let response; -let article = null; -let posts = null; -let result = null; -let category; - -// Определяем категорию +// Убеждаемся что рубрики загружены перед определением типа if (!wpInfo.isLoaded()) { await wpInfo.fetchAllCategories(); } +const pageInfo = detectPageType(pathname); + +let article = null; +let posts = null; +let result = null; +let category; +let page = null; + +// Получаем категорию если есть category = wpInfo.getCategoryBySlug(pageInfo.categorySlug); +let title = 'Профиль'; -let title = 'Профиль'; //title page +console.log(pageInfo); -if (pageInfo.type === 'single') { //одиночная статья - - try { - article = await getProfileArticleById(pageInfo.postId); //получвем данные поста - title=article.title - } catch (error) { - console.error('Error fetching node:', error); - } - +if (pageInfo.type === 'single') { + try { + article = await getProfileArticleById(pageInfo.postId); + title = article?.title || title; + } catch (error) { + console.error('Error fetching node:', error); + } } else if (pageInfo.type === 'archive') { - - result = await getPostsByCategory(pageInfo.categorySlug, 21); //получвем данные поста - posts = result.posts; - - -} - - -// ISR кэширование -//Astro.response.headers.set( -// 'Cache-Control', -// 'public, s-maxage=3600, stale-while-revalidate=86400' -//); + result = await getPostsByCategory(pageInfo.categorySlug, 21); + posts = result?.posts; +} else if (pageInfo.type === 'unknown' && pageInfo.pageSlug) { + try { + page = await getPageBySlug(pageInfo.pageSlug); + if (page) { + title = page.title; + } + } catch (error) { + console.error('Error fetching page:', error); + } +} --- -{/* Page (страница) */} -{pageInfo.type === 'unknown' && ( -
✅ Это страница: {pageInfo.pageSlug}
-)} + {/* СТРАНИЦА */} + {pageInfo.type === 'unknown' && page && ( +
+
+

{page.title}

+
+
+
+ )} + {/* Single post */} + {pageInfo.type === 'single' && article && ( + + )} -{/* Single post */} -{pageInfo.type === 'single' && article && ( - -)} - - -{/* Category archive */} - {pageInfo.type === 'archive' && posts && ( - - )} - - - -
+ {/* Category archive */} + {pageInfo.type === 'archive' && posts && ( + + )} + \ No newline at end of file