From 87a6fe188cbde59859a9c3383d8bd21084e12261 Mon Sep 17 00:00:00 2001 From: Chloe Date: Wed, 3 Jul 2024 12:56:50 +0700 Subject: [PATCH] feat: add inlinking transmission code block Signed-off-by: Chloe --- app/search/[collection]/loading.tsx | 31 +++++++++++++ app/search/[collection]/page.tsx | 51 ++++++++++++--------- components/layout/products-list/index.tsx | 3 +- components/manufacturers-grid/index.tsx | 2 +- components/transmission-codes/index.tsx | 52 +++++++++++++++++++++ components/transmission-model/index.tsx | 55 +++++++++++++++++++++++ lib/constants.ts | 1 + lib/shopify/index.ts | 38 ++++++++++++++-- lib/shopify/queries/collection.ts | 19 ++++++++ 9 files changed, 225 insertions(+), 27 deletions(-) create mode 100644 app/search/[collection]/loading.tsx create mode 100644 components/transmission-codes/index.tsx create mode 100644 components/transmission-model/index.tsx diff --git a/app/search/[collection]/loading.tsx b/app/search/[collection]/loading.tsx new file mode 100644 index 000000000..b2461e304 --- /dev/null +++ b/app/search/[collection]/loading.tsx @@ -0,0 +1,31 @@ +import BreadcrumbHome from 'components/breadcrumb/breadcrumb-home'; +import { YMMFiltersPlaceholder } from 'components/filters'; +import { FiltersListPlaceholder } from 'components/layout/search/filters/filters-container'; +import { HeaderPlaceholder } from 'components/layout/search/header'; +import ProductsGridPlaceholder from 'components/layout/search/placeholder'; + +const Loading = () => { + return ( +
+
+ +
+
+ +
+ + + +
+
+
+ ); +}; + +export default Loading; diff --git a/app/search/[collection]/page.tsx b/app/search/[collection]/page.tsx index 52dfb94e9..68788900d 100644 --- a/app/search/[collection]/page.tsx +++ b/app/search/[collection]/page.tsx @@ -18,6 +18,9 @@ import Header, { HeaderPlaceholder } from 'components/layout/search/header'; import HelpfulLinks from 'components/layout/search/helpful-links'; import ProductsGridPlaceholder from 'components/layout/search/placeholder'; import SortingMenu from 'components/layout/search/sorting-menu'; +import TransmissionCode from 'components/transmission-codes'; +import TransmissionModels from 'components/transmission-model'; +import { MAKE_FILTER_ID } from 'lib/constants'; import { Suspense } from 'react'; export async function generateMetadata({ @@ -79,6 +82,7 @@ export default async function CategorySearchPage(props: { params: { collection: string }; searchParams?: { [key: string]: string | string[] | undefined }; }) { + const collectionHandle = props.params.collection; return ( <>
@@ -90,44 +94,49 @@ export default async function CategorySearchPage(props: {
- +

Filters

- } - key={`filters-${props.params.collection}`} - > - - + } key={`filters-${collectionHandle}`}> + +
- } key={`breadcrumb-${props.params.collection}`}> - + } key={`breadcrumb-${collectionHandle}`}> +
- } key={`header-${props.params.collection}`}> -
+ } key={`header-${collectionHandle}`}> +
- } - key={`products-${props.params.collection}`} - > + } key={`products-${collectionHandle}`}>
+ {collectionHandle.startsWith('transmissions') && ( + <> + + + + + + + + )} diff --git a/components/layout/products-list/index.tsx b/components/layout/products-list/index.tsx index c41f9b5c0..799c1f33c 100644 --- a/components/layout/products-list/index.tsx +++ b/components/layout/products-list/index.tsx @@ -54,7 +54,7 @@ const ProductsList = ({ return ( <> - {products.map((product) => ( + {products.map((product, index) => ( 10 ? false : true} /> ))} diff --git a/components/manufacturers-grid/index.tsx b/components/manufacturers-grid/index.tsx index 76ac4f462..faa71a3c1 100644 --- a/components/manufacturers-grid/index.tsx +++ b/components/manufacturers-grid/index.tsx @@ -36,7 +36,7 @@ const ManufacturersGrid = ({ manufacturers, variant = 'home' }: ManufacturersGri )} {variant === 'home' && } - ))}{' '} + ))}
diff --git a/components/transmission-codes/index.tsx b/components/transmission-codes/index.tsx new file mode 100644 index 000000000..5edbdb1c6 --- /dev/null +++ b/components/transmission-codes/index.tsx @@ -0,0 +1,52 @@ +import { StarIcon } from '@heroicons/react/24/outline'; +import Tag from 'components/tag'; +import { MAKE_FILTER_ID, TRANSMISSION_CODE_FILTER_ID } from 'lib/constants'; +import { getProductFilters } from 'lib/shopify'; +import { getCollectionUrl } from 'lib/utils'; +import Link from 'next/link'; + +const TransmissionCode = async ({ + collectionHandle, + make +}: { + collectionHandle: string; + make?: string; +}) => { + const transmissionCodes = await getProductFilters( + { collection: collectionHandle, make }, + TRANSMISSION_CODE_FILTER_ID + ); + + if (!transmissionCodes || transmissionCodes.values.length === 0) { + return null; + } + + return ( +
+
+ +

{`Browse By Transmission Code`}

+
+

+ + Popular Transmission Codes +

+
+ {transmissionCodes.values.map((transmissionCode) => ( + +
+ {transmissionCode.label} +
+ + ))} +
+
+
+
+ ); +}; + +export default TransmissionCode; diff --git a/components/transmission-model/index.tsx b/components/transmission-model/index.tsx new file mode 100644 index 000000000..b7c37020e --- /dev/null +++ b/components/transmission-model/index.tsx @@ -0,0 +1,55 @@ +import { GlobeAltIcon } from '@heroicons/react/24/outline'; +import { MAKE_FILTER_ID, MODEL_FILTER_ID } from 'lib/constants'; +import { getProductFilters } from 'lib/shopify'; +import { getCollectionUrl } from 'lib/utils'; +import Link from 'next/link'; + +const TransmissionModels = async ({ + collectionHandle, + make +}: { + collectionHandle: string; + make?: string; +}) => { + // eg: collectionHandle = transmission-bmw-x5 + const makeFromCollectionHandle = collectionHandle.split('-')[1]; + + if (!makeFromCollectionHandle && !make) { + return null; + } + + const transmissionModels = await getProductFilters( + { collection: collectionHandle, make }, + MODEL_FILTER_ID + ); + + if (!transmissionModels || transmissionModels.values.length === 0) { + return null; + } + + return ( +
+
+

Browse By Transmission Models

+
+

+ + Models +

+
+ {transmissionModels.values.map((model) => ( + +
{model.label}
+ + ))} +
+
+
+
+ ); +}; + +export default TransmissionModels; diff --git a/lib/constants.ts b/lib/constants.ts index 5029b37ba..2cb898961 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -42,6 +42,7 @@ export const SHOPIFY_GRAPHQL_ADMIN_ADMIN_API_ENDPOINT = '/admin/api/2024-04/grap export const CORE_WAIVER = 'core-waiver'; export const CORE_VARIANT_ID_KEY = 'coreVariantId'; +export const TRANSMISSION_CODE_FILTER_ID = 'filter.p.m.custom.transmission_code'; export const AVAILABILITY_FILTER_ID = 'filter.v.availability'; export const PRICE_FILTER_ID = 'filter.v.price'; export const MAKE_FILTER_ID = 'filter.p.m.custom.make_composite'; diff --git a/lib/shopify/index.ts b/lib/shopify/index.ts index 2f20d88a3..0ffc280f1 100644 --- a/lib/shopify/index.ts +++ b/lib/shopify/index.ts @@ -38,7 +38,8 @@ import { getCartQuery } from './queries/cart'; import { getCollectionProductsQuery, getCollectionQuery, - getCollectionsQuery + getCollectionsQuery, + getTransmissionCodesQuery } from './queries/collection'; import { getCustomerQuery } from './queries/customer'; import { getMenuQuery } from './queries/menu'; @@ -373,10 +374,10 @@ const reshapeCollections = (collections: ShopifyCollection[]) => { return reshapedCollections; }; -const reshapeFilters = (filters: ShopifyFilter[]): Filter[] => { +const reshapeFilters = (filters: ShopifyFilter[], excludeYMM = true): Filter[] => { const reshapedFilters = []; - const excludedYMMFilters = filters.filter( - (filter) => ![MODEL_FILTER_ID, MAKE_FILTER_ID, YEAR_FILTER_ID].includes(filter.id) + const excludedYMMFilters = filters.filter((filter) => + excludeYMM ? ![MODEL_FILTER_ID, MAKE_FILTER_ID, YEAR_FILTER_ID].includes(filter.id) : true ); for (const filter of excludedYMMFilters) { const values = filter.values @@ -1174,3 +1175,32 @@ export const getFile = async (id: string) => { return res.body.data.node; }; + +export async function getProductFilters( + { collection, make }: { collection: string; make?: string }, + filterId: string +): Promise { + const [namespace, metafieldKey] = MAKE_FILTER_ID.split('.').slice(-2); + + const res = await shopifyFetch({ + query: getTransmissionCodesQuery, + tags: [TAGS.collections, TAGS.products], + variables: { + handle: collection, + ...(make + ? { + filters: [{ productMetafield: { namespace, key: metafieldKey, value: make } }] + } + : {}) + } + }); + + if (!res.body.data.collection) { + console.log(`No collection found for \`${collection}\``); + return null; + } + + const filters = res.body.data.collection.products.filters; + const selectedFilters = filters.find((filter) => filter.id === filterId); + return selectedFilters ? reshapeFilters([selectedFilters], false)[0] : null; +} diff --git a/lib/shopify/queries/collection.ts b/lib/shopify/queries/collection.ts index 306e3cf9e..23a403d62 100644 --- a/lib/shopify/queries/collection.ts +++ b/lib/shopify/queries/collection.ts @@ -78,3 +78,22 @@ export const getCollectionProductsQuery = /* GraphQL */ ` } ${productFragment} `; + +export const getTransmissionCodesQuery = /* GraphQL */ ` + query getTransmissionCodes($handle: String!, $filters: [ProductFilter!]) { + collection(handle: $handle) { + products(first: 1, filters: $filters) { + filters { + id + label + type + values { + id + input + label + } + } + } + } + } +`;