diff --git a/packages/opencommerce/schema.d.ts b/packages/opencommerce/schema.d.ts index 2523a0699..675b24424 100644 --- a/packages/opencommerce/schema.d.ts +++ b/packages/opencommerce/schema.d.ts @@ -8001,6 +8001,127 @@ export type CatalogItemsQuery = { } | null } +export type PrimaryShopQueryVariables = Exact<{ + language?: Scalars['String'] +}> + +export type PrimaryShopQuery = { + __typename?: 'Query' + primaryShop?: { + __typename?: 'Shop' + _id: string + description?: string | null + name: string + currency: { __typename?: 'Currency'; code: string } + defaultNavigationTree?: { + __typename?: 'NavigationTree' + _id: string + shopId: string + name: string + items?: Array<{ + __typename?: 'NavigationTreeItem' + navigationItem: { + __typename?: 'NavigationItem' + data?: { + __typename?: 'NavigationItemData' + contentForLanguage?: string | null + classNames?: string | null + url?: string | null + isUrlRelative?: boolean | null + shouldOpenInNewWindow?: boolean | null + } | null + } + items?: Array<{ + __typename?: 'NavigationTreeItem' + navigationItem: { + __typename?: 'NavigationItem' + data?: { + __typename?: 'NavigationItemData' + contentForLanguage?: string | null + classNames?: string | null + url?: string | null + isUrlRelative?: boolean | null + shouldOpenInNewWindow?: boolean | null + } | null + } + items?: Array<{ + __typename?: 'NavigationTreeItem' + navigationItem: { + __typename?: 'NavigationItem' + data?: { + __typename?: 'NavigationItemData' + contentForLanguage?: string | null + classNames?: string | null + url?: string | null + isUrlRelative?: boolean | null + shouldOpenInNewWindow?: boolean | null + } | null + } + } | null> | null + } | null> | null + } | null> | null + } | null + } | null +} + +export type NavigationTreeFragmentFragment = { + __typename?: 'NavigationTree' + _id: string + shopId: string + name: string + items?: Array<{ + __typename?: 'NavigationTreeItem' + navigationItem: { + __typename?: 'NavigationItem' + data?: { + __typename?: 'NavigationItemData' + contentForLanguage?: string | null + classNames?: string | null + url?: string | null + isUrlRelative?: boolean | null + shouldOpenInNewWindow?: boolean | null + } | null + } + items?: Array<{ + __typename?: 'NavigationTreeItem' + navigationItem: { + __typename?: 'NavigationItem' + data?: { + __typename?: 'NavigationItemData' + contentForLanguage?: string | null + classNames?: string | null + url?: string | null + isUrlRelative?: boolean | null + shouldOpenInNewWindow?: boolean | null + } | null + } + items?: Array<{ + __typename?: 'NavigationTreeItem' + navigationItem: { + __typename?: 'NavigationItem' + data?: { + __typename?: 'NavigationItemData' + contentForLanguage?: string | null + classNames?: string | null + url?: string | null + isUrlRelative?: boolean | null + shouldOpenInNewWindow?: boolean | null + } | null + } + } | null> | null + } | null> | null + } | null> | null +} + +export type NavigationItemFieldsFragment = { + __typename?: 'NavigationItemData' + contentForLanguage?: string | null + classNames?: string | null + url?: string | null + isUrlRelative?: boolean | null + shouldOpenInNewWindow?: boolean | null +} + export type GetProductBySlugQueryVariables = Exact<{ slug: Scalars['String'] }> diff --git a/packages/opencommerce/src/api/operations/get-site-info.ts b/packages/opencommerce/src/api/operations/get-site-info.ts index 4fecc98c9..dc9e2ba87 100644 --- a/packages/opencommerce/src/api/operations/get-site-info.ts +++ b/packages/opencommerce/src/api/operations/get-site-info.ts @@ -9,11 +9,16 @@ import { GetAllProductVendorsQueryVariables, } from '../../../schema' import getTagsQuery from '../queries/get-tags-query' -import { GetSiteInfoOperation, OCCategory } from '../../types/site' -import { normalizeCategory, normalizeVendors } from '../../utils/normalize' +import { GetSiteInfoOperation, OCCategory, SiteTypes } from '../../types/site' +import { + normalizeCategory, + normalizeNavigation, + normalizeVendors, +} from '../../utils/normalize' import type { OpenCommerceConfig, Provider } from '..' import filterEdges from '../utils/filter-edges' import getAllProductVendors from '../queries/get-vendors-query' +import getPrimaryShopQuery from '../queries/get-primary-shop-query' export default function getSiteInfoOperation({ commerce, @@ -39,15 +44,17 @@ export default function getSiteInfoOperation({ } = {}): Promise { const { fetch, shopId } = commerce.getConfig(cfg) - const [categoriesResponse, vendorsResponse] = await Promise.all([ - await fetch(getTagsQuery, { - variables: { first: 250, shopId }, - }), - await fetch< - GetAllProductVendorsQuery, - GetAllProductVendorsQueryVariables - >(getAllProductVendors, { variables: { shopIds: [shopId] } }), - ]) + const [categoriesResponse, vendorsResponse, primaryShopResponse] = + await Promise.all([ + await fetch(getTagsQuery, { + variables: { first: 250, shopId }, + }), + await fetch< + GetAllProductVendorsQuery, + GetAllProductVendorsQueryVariables + >(getAllProductVendors, { variables: { shopIds: [shopId] } }), + await fetch(getPrimaryShopQuery), + ]) const categories = filterEdges(categoriesResponse.data.tags?.edges).map( (edge) => normalizeCategory(edge.node! as OCCategory) @@ -57,7 +64,15 @@ export default function getSiteInfoOperation({ ...new Set(filterEdges(vendorsResponse.data.vendors?.nodes)), ].map(normalizeVendors) - return { categories, brands } + const navigationItems = + primaryShopResponse.data.primaryShop.defaultNavigationTree.items ?? [] + + console.log(normalizeNavigation(navigationItems)) + return { + categories, + brands, + navigation: normalizeNavigation(navigationItems), + } } return getSiteInfo diff --git a/packages/opencommerce/src/api/queries/get-primary-shop-query.ts b/packages/opencommerce/src/api/queries/get-primary-shop-query.ts new file mode 100644 index 000000000..ac8df4924 --- /dev/null +++ b/packages/opencommerce/src/api/queries/get-primary-shop-query.ts @@ -0,0 +1,50 @@ +const getPrimaryShopQuery = /* GraphQL */ ` + query primaryShop($language: String! = "en") { + primaryShop { + _id + currency { + code + } + defaultNavigationTree(language: $language) { + ...NavigationTreeFragment + } + description + name + } + } + fragment NavigationTreeFragment on NavigationTree { + _id + shopId + name + items { + navigationItem { + data { + ...NavigationItemFields + } + } + items { + navigationItem { + data { + ...NavigationItemFields + } + } + items { + navigationItem { + data { + ...NavigationItemFields + } + } + } + } + } + } + fragment NavigationItemFields on NavigationItemData { + contentForLanguage + classNames + url + isUrlRelative + shouldOpenInNewWindow + } +` + +export default getPrimaryShopQuery diff --git a/packages/opencommerce/src/commerce.config.json b/packages/opencommerce/src/commerce.config.json index 876b7d7e1..d45aa9d5f 100644 --- a/packages/opencommerce/src/commerce.config.json +++ b/packages/opencommerce/src/commerce.config.json @@ -1,6 +1,7 @@ { "provider": "opencommerce", "features": { - "customCheckout": true + "customCheckout": true, + "customNavigation": true } } diff --git a/packages/opencommerce/src/types/site.ts b/packages/opencommerce/src/types/site.ts index 159152b99..e399f9af9 100644 --- a/packages/opencommerce/src/types/site.ts +++ b/packages/opencommerce/src/types/site.ts @@ -1,4 +1,5 @@ import { Vendor as QueryVender, TagEdge } from '../../schema' +import { SiteTypes as CoreSiteTypes } from '@vercel/commerce/types/site' export * from '@vercel/commerce/types/site' @@ -13,3 +14,23 @@ export type Vendor = { path: string } } + +export type NavigationItem = { + url: string + label: string + isUrlRelative: boolean + shouldOpenInNewWindow: boolean + items?: NavigationItem[] +} + +export type SiteTypes = CoreSiteTypes & { + navigation: NavigationItem +} + +export type GetSiteInfoOperation = { + data: { + categories: T['category'][] + brands: T['brand'][] + navigation: T['navigation'][] + } +} diff --git a/packages/opencommerce/src/utils/normalize.ts b/packages/opencommerce/src/utils/normalize.ts index a7cb76b46..4bde65272 100644 --- a/packages/opencommerce/src/utils/normalize.ts +++ b/packages/opencommerce/src/utils/normalize.ts @@ -4,13 +4,20 @@ import type { ProductOptionValues, ProductVariant, } from '../types/product' -import { OCCategory, Category, Vendor, OCVendor } from '../types/site' +import { + OCCategory, + Category, + Vendor, + OCVendor, + NavigationItem, +} from '../types/site' import { CatalogItemProduct, CatalogProductVariant, ImageInfo, Cart as OCCart, CartItemEdge, + NavigationTreeItem, } from '../../schema' import { Cart, LineItem } from '../types/cart' @@ -300,3 +307,17 @@ function normalizeLineItem(cartItemEdge: CartItemEdge): LineItem { ], } } + +export const normalizeNavigation = ( + navigationTreeItems: NavigationTreeItem[] +): NavigationItem[] => { + return navigationTreeItems.map(({ items, navigationItem: { data } }) => { + return { + url: data?.url ?? '/', + label: data?.contentForLanguage ?? 'N/A', + isUrlRelative: !!data?.isUrlRelative, + shouldOpenInNewWindow: !!data?.shouldOpenInNewWindow, + items: normalizeNavigation((items ?? []) as NavigationTreeItem[]), + } + }) +} diff --git a/site/components/common/Layout/Layout.tsx b/site/components/common/Layout/Layout.tsx index 6dda880e4..5019fa92d 100644 --- a/site/components/common/Layout/Layout.tsx +++ b/site/components/common/Layout/Layout.tsx @@ -17,6 +17,7 @@ import { MenuSidebarView } from '@components/common/UserNav' import type { Page } from '@commerce/types/page' import type { Category } from '@commerce/types/site' import type { Link as LinkProps } from '../UserNav/MenuSidebarView' +import { NavigationItem } from '@framework/types/site' const Loading = () => (
@@ -52,6 +53,7 @@ interface Props { pageProps: { pages?: Page[] categories: Category[] + navigation: NavigationItem[] } } @@ -104,8 +106,9 @@ const SidebarUI: React.FC<{ links: LinkProps[] }> = ({ links }) => { const Layout: React.FC = ({ children, - pageProps: { categories = [], ...pageProps }, + pageProps: { categories = [], navigation = [], ...pageProps }, }) => { + console.log({ navigation }) const { acceptedCookies, onAcceptCookies } = useAcceptCookies() const { locale = 'en-US' } = useRouter() const navBarlinks = categories.slice(0, 2).map((c) => ({ @@ -116,7 +119,7 @@ const Layout: React.FC = ({ return (
- +
{children}