diff --git a/app/search/[collection]/page.tsx b/app/search/[collection]/page.tsx index 68788900d..1887d7d77 100644 --- a/app/search/[collection]/page.tsx +++ b/app/search/[collection]/page.tsx @@ -4,6 +4,7 @@ import { notFound } from 'next/navigation'; import Breadcrumb from 'components/breadcrumb'; import BreadcrumbHome from 'components/breadcrumb/breadcrumb-home'; +import EngineSizes from 'components/engine-sizes'; import FAQ from 'components/faq'; import YMMFilters, { YMMFiltersPlaceholder } from 'components/filters'; import Manufacturers from 'components/home-page/manufacturers'; @@ -18,8 +19,8 @@ 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 Models from 'components/models'; import TransmissionCode from 'components/transmission-codes'; -import TransmissionModels from 'components/transmission-model'; import { MAKE_FILTER_ID } from 'lib/constants'; import { Suspense } from 'react'; @@ -119,21 +120,30 @@ export default async function CategorySearchPage(props: { {collectionHandle.startsWith('transmissions') && ( - <> - - - - - - - + + + )} + {['transmissions', 'engines', 'remanufactured-engines'].some((url) => + collectionHandle.startsWith(url) + ) && ( + + + + )} + + {['engines', 'remanufactured-engines'].some((url) => collectionHandle.startsWith(url)) && ( + + + + )} + { + // eg: collectionHandle = transmission-bmw-x5 + const makeFromCollectionHandle = collectionHandle.split('-')[1]; + + if (!makeFromCollectionHandle && !make) { + return null; + } + const engineSizes = await getProductFilters( + { collection: collectionHandle, make }, + ENGINE_SIZE_FILTER_ID + ); + + if (!engineSizes || engineSizes.values.length === 0) { + return null; + } + + return ( +
+
+

Browse Engines By Engine Sizes

+
+
+ {engineSizes.values.map((engineSize) => ( + +
+ {engineSize.label} +
+ + ))} +
+
+
+
+ ); +}; + +export default EngineSizes; diff --git a/components/transmission-model/index.tsx b/components/models/index.tsx similarity index 89% rename from components/transmission-model/index.tsx rename to components/models/index.tsx index b7c37020e..2f91d1418 100644 --- a/components/transmission-model/index.tsx +++ b/components/models/index.tsx @@ -4,12 +4,12 @@ import { getProductFilters } from 'lib/shopify'; import { getCollectionUrl } from 'lib/utils'; import Link from 'next/link'; -const TransmissionModels = async ({ +const Models = async ({ collectionHandle, make }: { collectionHandle: string; - make?: string; + make?: string | string[]; }) => { // eg: collectionHandle = transmission-bmw-x5 const makeFromCollectionHandle = collectionHandle.split('-')[1]; @@ -17,7 +17,6 @@ const TransmissionModels = async ({ if (!makeFromCollectionHandle && !make) { return null; } - const transmissionModels = await getProductFilters( { collection: collectionHandle, make }, MODEL_FILTER_ID @@ -27,10 +26,12 @@ const TransmissionModels = async ({ return null; } + const prefix = collectionHandle.startsWith('transmissions') ? 'Transmissions' : 'Engines'; + return (
-

Browse By Transmission Models

+

{`Browse ${prefix} By Model`}

@@ -52,4 +53,4 @@ const TransmissionModels = async ({ ); }; -export default TransmissionModels; +export default Models; diff --git a/components/transmission-codes/index.tsx b/components/transmission-codes/index.tsx index 5edbdb1c6..cd21f56fe 100644 --- a/components/transmission-codes/index.tsx +++ b/components/transmission-codes/index.tsx @@ -10,7 +10,7 @@ const TransmissionCode = async ({ make }: { collectionHandle: string; - make?: string; + make?: string | string[]; }) => { const transmissionCodes = await getProductFilters( { collection: collectionHandle, make }, diff --git a/lib/constants.ts b/lib/constants.ts index 2cb898961..990b3e74e 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -43,6 +43,7 @@ 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 ENGINE_SIZE_FILTER_ID = 'filter.p.m.custom.engine_size'; 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'; @@ -69,3 +70,10 @@ export const WARRANTY_FIELDS = [ 'warranty_activation_vin', 'warranty_activation_mileage' ]; + +export const URL_PREFIXES = [ + '/transmissions', + '/engines', + '/transfer-cases', + '/remanufactured-engines' +]; diff --git a/lib/shopify/index.ts b/lib/shopify/index.ts index 0ffc280f1..f28511491 100644 --- a/lib/shopify/index.ts +++ b/lib/shopify/index.ts @@ -1177,19 +1177,22 @@ export const getFile = async (id: string) => { }; export async function getProductFilters( - { collection, make }: { collection: string; make?: string }, + { collection, make }: { collection: string; make?: string | string[] }, filterId: string ): Promise { const [namespace, metafieldKey] = MAKE_FILTER_ID.split('.').slice(-2); + const _make = Array.isArray(make) ? make : make ? [make] : undefined; const res = await shopifyFetch({ query: getTransmissionCodesQuery, tags: [TAGS.collections, TAGS.products], variables: { handle: collection, - ...(make + ...(_make ? { - filters: [{ productMetafield: { namespace, key: metafieldKey, value: make } }] + filters: _make.map((make) => ({ + productMetafield: { namespace, key: metafieldKey, value: make } + })) } : {}) } @@ -1202,5 +1205,6 @@ export async function getProductFilters( 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/utils.ts b/lib/utils.ts index e42f43804..e41b08c73 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -145,7 +145,23 @@ export const isBeforeToday = (date?: string | null) => { }; export const getCollectionUrl = (handle: string, includeSlashPrefix = true) => { - const rewriteUrl = handle.split('-').filter(Boolean).join('/'); + let rewriteUrl = ''; + const enginesPattern = /^\/?remanufactured-engines(-.+)?$/; + const transferCasesPattern = /^\/?transfer-cases(-.+)?$/; + + if (enginesPattern.test(handle)) { + rewriteUrl = handle + .replace(/-/g, '/') + .replace('/engines/', '-engines/') + .replace('/engines', '-engines'); + } else if (transferCasesPattern.test(handle)) { + rewriteUrl = handle + .replace(/-/g, '/') + .replace('/cases/', '-cases/') + .replace('/cases', '-cases'); + } else { + rewriteUrl = handle.split('-').filter(Boolean).join('/'); + } return includeSlashPrefix ? `/${rewriteUrl}` : rewriteUrl; }; diff --git a/middleware.ts b/middleware.ts index 3a5b158ef..cd8ef1fc2 100644 --- a/middleware.ts +++ b/middleware.ts @@ -1,8 +1,7 @@ +import { URL_PREFIXES } from 'lib/constants'; import { getOrigin, isLoggedIn } from 'lib/shopify/auth'; import { NextRequest, NextResponse } from 'next/server'; -const URL_PREFIXES = ['/transmissions', '/engines', '/transfer-cases', '/remanufactured-engines']; - // This function can be marked `async` if using `await` inside export async function middleware(request: NextRequest) { if (request.nextUrl.pathname.startsWith('/account')) {