add support pages
This commit is contained in:
85
src/lib/api/pages.ts
Normal file
85
src/lib/api/pages.ts
Normal file
@@ -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<PageData | null> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
---
|
||||
|
||||
<ContentLayout
|
||||
title={title}
|
||||
description="Информационное агентство Деловой журнал Профиль"
|
||||
category={category}
|
||||
title={title}
|
||||
description="Информационное агентство Деловой журнал Профиль"
|
||||
category={category}
|
||||
>
|
||||
|
||||
{/* Page (страница) */}
|
||||
{pageInfo.type === 'unknown' && (
|
||||
<div>✅ Это страница: {pageInfo.pageSlug}</div>
|
||||
)}
|
||||
{/* СТРАНИЦА */}
|
||||
{pageInfo.type === 'unknown' && page && (
|
||||
<div class="article-wrapper">
|
||||
<article class="news-single">
|
||||
<h1>{page.title}</h1>
|
||||
<div set:html={page.content} />
|
||||
</article>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Single post */}
|
||||
{pageInfo.type === 'single' && article && (
|
||||
<NewsSingle post={article} pageInfo={pageInfo} />
|
||||
)}
|
||||
|
||||
{/* Single post */}
|
||||
{pageInfo.type === 'single' && article && (
|
||||
<NewsSingle post={article} pageInfo={pageInfo} />
|
||||
)}
|
||||
|
||||
|
||||
{/* Category archive */}
|
||||
{pageInfo.type === 'archive' && posts && (
|
||||
<ContentGrid
|
||||
items={posts}
|
||||
pageInfo={result.pageInfo}
|
||||
slug={pageInfo.categorySlug}
|
||||
showCount={false}
|
||||
type='category'
|
||||
perLoad={12}
|
||||
gridColumns={3}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
|
||||
</ContentLayout>
|
||||
{/* Category archive */}
|
||||
{pageInfo.type === 'archive' && posts && (
|
||||
<ContentGrid
|
||||
items={posts}
|
||||
pageInfo={result?.pageInfo}
|
||||
slug={pageInfo.categorySlug}
|
||||
showCount={false}
|
||||
type='category'
|
||||
perLoad={12}
|
||||
gridColumns={3}
|
||||
/>
|
||||
)}
|
||||
|
||||
</ContentLayout>
|
||||
Reference in New Issue
Block a user