From af201556c2e8fd1e9ddb673285ea4e3dc3071806 Mon Sep 17 00:00:00 2001 From: Zotov Ivan Yuryevich Date: Wed, 17 Jun 2026 22:46:41 +0300 Subject: [PATCH] chore: show menu item only if section anchor provided --- src/graphql-documents/home-page.gql.ts | 5 ++ src/graphql/graphql.ts | 15 +++-- src/lib/cms/sections/homeNav.ts | 46 ++++++++++++++ src/pages/[slug].astro | 14 ++++- src/pages/index.astro | 4 +- src/sections/Header.tsx | 86 +++++++++++++++----------- src/views/HomePage.tsx | 33 +++++++--- 7 files changed, 152 insertions(+), 51 deletions(-) create mode 100644 src/lib/cms/sections/homeNav.ts diff --git a/src/graphql-documents/home-page.gql.ts b/src/graphql-documents/home-page.gql.ts index b64b25d..8451f7d 100644 --- a/src/graphql-documents/home-page.gql.ts +++ b/src/graphql-documents/home-page.gql.ts @@ -9,6 +9,7 @@ export const homePageDocument = gql` id title description + anchor badge stats { id @@ -20,6 +21,7 @@ export const homePageDocument = gql` id title description + anchor cards { id title @@ -39,6 +41,7 @@ export const homePageDocument = gql` id title description + anchor cards { id title @@ -56,6 +59,7 @@ export const homePageDocument = gql` id title description + anchor cards { id title @@ -75,6 +79,7 @@ export const homePageDocument = gql` id title description + anchor partners(pagination: { pageSize: 100 }) { id value diff --git a/src/graphql/graphql.ts b/src/graphql/graphql.ts index 55d5827..9370e2e 100644 --- a/src/graphql/graphql.ts +++ b/src/graphql/graphql.ts @@ -1611,11 +1611,11 @@ export type HomePageQueryVariables = Exact<{ [key: string]: never; }>; export type HomePageQuery = { __typename?: 'Query', homePage?: { __typename?: 'HomePage', sections?: Array< - | { __typename: 'ComponentSectionsAbout', id: string, title?: string | null, description?: string | null, partners?: Array<{ __typename?: 'ComponentSharedString', id: string, value: string } | null> | null, cards?: Array<{ __typename?: 'ComponentCardsAdvantage', id: string, title?: string | null, description?: string | null, color?: { __typename?: 'ComponentSharedColor', value?: Enum_Componentsharedcolor_Value | null } | null, icon?: { __typename?: 'ComponentSharedIcon', value?: Enum_Componentsharedicon_Value | null } | null } | null> | null } - | { __typename: 'ComponentSectionsCases', id: string, title?: string | null, description?: string | null, cards?: Array<{ __typename?: 'ComponentCardsCase', id: string, title?: string | null, description?: string | null, pretitle?: string | null, badge?: string | null, footnote?: string | null, color?: { __typename?: 'ComponentSharedColor', value?: Enum_Componentsharedcolor_Value | null } | null, icon?: { __typename?: 'ComponentSharedIcon', value?: Enum_Componentsharedicon_Value | null } | null } | null> | null } - | { __typename: 'ComponentSectionsHomeHero', id: string, title?: string | null, description?: string | null, badge?: string | null, stats?: Array<{ __typename?: 'ComponentSharedAttribute', id: string, key?: string | null, value?: string | null } | null> | null } - | { __typename: 'ComponentSectionsServices', id: string, title?: string | null, description?: string | null, cards?: Array<{ __typename?: 'ComponentCardsService', id: string, title?: string | null, description?: string | null, icon?: { __typename?: 'ComponentSharedIcon', value?: Enum_Componentsharedicon_Value | null } | null, color?: { __typename?: 'ComponentSharedColor', value?: Enum_Componentsharedcolor_Value | null } | null, category?: { __typename?: 'Category', slug: string } | null } | null> | null } - | { __typename: 'ComponentSectionsSolutions', id: string, title?: string | null, description?: string | null, cards?: Array<{ __typename?: 'ComponentCardsSolution', id: string, title?: string | null, description?: string | null, footnote?: string | null, icon?: { __typename?: 'ComponentSharedIcon', value?: Enum_Componentsharedicon_Value | null } | null, category?: { __typename?: 'Category', slug: string } | null } | null> | null } + | { __typename: 'ComponentSectionsAbout', id: string, title?: string | null, description?: string | null, anchor?: string | null, partners?: Array<{ __typename?: 'ComponentSharedString', id: string, value: string } | null> | null, cards?: Array<{ __typename?: 'ComponentCardsAdvantage', id: string, title?: string | null, description?: string | null, color?: { __typename?: 'ComponentSharedColor', value?: Enum_Componentsharedcolor_Value | null } | null, icon?: { __typename?: 'ComponentSharedIcon', value?: Enum_Componentsharedicon_Value | null } | null } | null> | null } + | { __typename: 'ComponentSectionsCases', id: string, title?: string | null, description?: string | null, anchor?: string | null, cards?: Array<{ __typename?: 'ComponentCardsCase', id: string, title?: string | null, description?: string | null, pretitle?: string | null, badge?: string | null, footnote?: string | null, color?: { __typename?: 'ComponentSharedColor', value?: Enum_Componentsharedcolor_Value | null } | null, icon?: { __typename?: 'ComponentSharedIcon', value?: Enum_Componentsharedicon_Value | null } | null } | null> | null } + | { __typename: 'ComponentSectionsHomeHero', id: string, title?: string | null, description?: string | null, anchor?: string | null, badge?: string | null, stats?: Array<{ __typename?: 'ComponentSharedAttribute', id: string, key?: string | null, value?: string | null } | null> | null } + | { __typename: 'ComponentSectionsServices', id: string, title?: string | null, description?: string | null, anchor?: string | null, cards?: Array<{ __typename?: 'ComponentCardsService', id: string, title?: string | null, description?: string | null, icon?: { __typename?: 'ComponentSharedIcon', value?: Enum_Componentsharedicon_Value | null } | null, color?: { __typename?: 'ComponentSharedColor', value?: Enum_Componentsharedcolor_Value | null } | null, category?: { __typename?: 'Category', slug: string } | null } | null> | null } + | { __typename: 'ComponentSectionsSolutions', id: string, title?: string | null, description?: string | null, anchor?: string | null, cards?: Array<{ __typename?: 'ComponentCardsSolution', id: string, title?: string | null, description?: string | null, footnote?: string | null, icon?: { __typename?: 'ComponentSharedIcon', value?: Enum_Componentsharedicon_Value | null } | null, category?: { __typename?: 'Category', slug: string } | null } | null> | null } | { __typename: 'Error' } | null> | null } | null }; @@ -1677,6 +1677,7 @@ export const HomePageDocument = new TypedDocumentString(` id title description + anchor badge stats { id @@ -1688,6 +1689,7 @@ export const HomePageDocument = new TypedDocumentString(` id title description + anchor cards { id title @@ -1707,6 +1709,7 @@ export const HomePageDocument = new TypedDocumentString(` id title description + anchor cards { id title @@ -1724,6 +1727,7 @@ export const HomePageDocument = new TypedDocumentString(` id title description + anchor cards { id title @@ -1743,6 +1747,7 @@ export const HomePageDocument = new TypedDocumentString(` id title description + anchor partners(pagination: {pageSize: 100}) { id value diff --git a/src/lib/cms/sections/homeNav.ts b/src/lib/cms/sections/homeNav.ts new file mode 100644 index 0000000..0ac20e8 --- /dev/null +++ b/src/lib/cms/sections/homeNav.ts @@ -0,0 +1,46 @@ +import type { HomePageQuery } from '../../../graphql/graphql' +import type { Maybe } from '../../types' + +type HomePageData = NonNullable + +/** + * Anchors configured on each home-page section, keyed by section kind. A key is + * present only when its section exists and has a non-empty `anchor`, which is + * what gates the matching header menu item. + */ +export interface HomeSectionAnchors { + hero?: string + services?: string + solutions?: string + cases?: string + about?: string +} + +export function getHomeSectionAnchors(home: Maybe): HomeSectionAnchors { + const anchors: HomeSectionAnchors = {} + + for (const section of home?.sections ?? []) { + if (!section || section.__typename === 'Error') continue + const anchor = section.anchor?.trim() + if (!anchor) continue + switch (section.__typename) { + case 'ComponentSectionsHomeHero': + anchors.hero = anchor + break + case 'ComponentSectionsServices': + anchors.services = anchor + break + case 'ComponentSectionsSolutions': + anchors.solutions = anchor + break + case 'ComponentSectionsCases': + anchors.cases = anchor + break + case 'ComponentSectionsAbout': + anchors.about = anchor + break + } + } + + return anchors +} diff --git a/src/pages/[slug].astro b/src/pages/[slug].astro index e53039b..e3e7c36 100644 --- a/src/pages/[slug].astro +++ b/src/pages/[slug].astro @@ -8,12 +8,22 @@ import { CategoryView } from '../views/CategoryView' import { siteConfigQuery } from '../graphql-documents/site-config.gql.generated' import { menuItemsQuery } from '../graphql-documents/menu-items.gql.generated' import { categoryQuery } from '../graphql-documents/category.gql.generated' +import { homePageQuery } from '../graphql-documents/home-page.gql.generated' import { resolveUploadUrl } from '../lib/cms/uploads/url' +import { getHomeSectionAnchors } from '../lib/cms/sections/homeNav' -const [siteResult, menuItemsResult] = await Promise.all([siteConfigQuery.execute(), menuItemsQuery.execute()]) +const [siteResult, menuItemsResult, homeResult] = await Promise.all([ + siteConfigQuery.execute(), + menuItemsQuery.execute(), + homePageQuery.execute(), +]) if (siteResult.errors?.length) { throw new Error(siteResult.errors.map(e => e.message).join(', ')) } +if (homeResult.errors?.length) { + throw new Error(homeResult.errors.map(e => e.message).join(', ')) +} +const sectionAnchors = getHomeSectionAnchors(homeResult.data?.homePage ?? null) const siteConfig = siteResult.data?.siteConfig const siteTitle = siteConfig?.title ?? '' const siteDescription = siteConfig?.description ?? '' @@ -62,7 +72,7 @@ const vendors = (category.vendors?.filter(v => v != null) ?? []).map(vendor => ( description={description ?? siteDescription} >
-
+