feat: add manufacturer section

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
Chloe 2024-06-14 17:31:30 +07:00
parent c5af5b3069
commit 3ac4b140c9
No known key found for this signature in database
GPG Key ID: CFD53CE570D42DF5
6 changed files with 109 additions and 49 deletions

View File

@ -4,8 +4,10 @@ import { notFound } from 'next/navigation';
import Breadcrumb from 'components/breadcrumb';
import BreadcrumbHome from 'components/breadcrumb/breadcrumb-home';
import FAQ from 'components/faq';
import YMMFilters, { YMMFiltersPlaceholder } from 'components/filters';
import Grid from 'components/grid';
import Manufacturers from 'components/home-page/manufacturers';
import ProductsList from 'components/layout/products-list';
import { getProductsInCollection } from 'components/layout/products-list/actions';
import FiltersContainer, {
@ -82,42 +84,52 @@ export default async function CategorySearchPage(props: {
}) {
return (
<>
<div className="grid lg:grid-cols-3 lg:gap-x-10 xl:grid-cols-4">
<aside className="hidden lg:block">
<div className="mb-5">
<Suspense fallback={<YMMFiltersPlaceholder />}>
<YMMFilters />
<div className="mx-auto mt-6 max-w-screen-2xl px-8 pb-10">
<div className="grid lg:grid-cols-3 lg:gap-x-10 xl:grid-cols-4">
<aside className="hidden lg:block">
<div className="mb-5">
<Suspense fallback={<YMMFiltersPlaceholder />}>
<YMMFilters />
</Suspense>
</div>
<SubMenu collection={props.params.collection} />
<h3 className="sr-only">Filters</h3>
<Suspense
fallback={<FiltersListPlaceholder />}
key={`filters-${props.params.collection}`}
>
<FiltersContainer searchParams={props.searchParams} />
<HelpfulLinks collection={props.params.collection} />
</Suspense>
</aside>
<div className="lg:col-span-2 xl:col-span-3">
<div className="mb-2">
<Suspense fallback={<BreadcrumbHome />} key={`breadcrumb-${props.params.collection}`}>
<Breadcrumb type="collection" handle={props.params.collection} />
</Suspense>
</div>
<Suspense fallback={<HeaderPlaceholder />} key={`header-${props.params.collection}`}>
<Header collection={props.params.collection} />
</Suspense>
<Suspense
fallback={<ProductsGridPlaceholder />}
key={`products-${props.params.collection}`}
>
<CategoryPage {...props} />
</Suspense>
</div>
<SubMenu collection={props.params.collection} />
<h3 className="sr-only">Filters</h3>
<Suspense
fallback={<FiltersListPlaceholder />}
key={`filters-${props.params.collection}`}
>
<FiltersContainer searchParams={props.searchParams} />
<HelpfulLinks collection={props.params.collection} />
</Suspense>
</aside>
<div className="lg:col-span-2 xl:col-span-3">
<div className="mb-2">
<Suspense fallback={<BreadcrumbHome />} key={`breadcrumb-${props.params.collection}`}>
<Breadcrumb type="collection" handle={props.params.collection} />
</Suspense>
</div>
<Suspense fallback={<HeaderPlaceholder />} key={`header-${props.params.collection}`}>
<Header collection={props.params.collection} />
</Suspense>
<Suspense
fallback={<ProductsGridPlaceholder />}
key={`products-${props.params.collection}`}
>
<CategoryPage {...props} />
</Suspense>
</div>
</div>
<FAQ handle="plp-faqs" />
<Suspense>
<Manufacturers
variant={
(props.params.collection as string).includes('engines') ? 'engines' : 'transmissions'
}
/>
</Suspense>
</>
);
}

View File

@ -1,14 +1,9 @@
import FAQ from 'components/faq';
import Footer from 'components/layout/footer';
import { Suspense } from 'react';
export default function SearchLayout({ children }: { children: React.ReactNode }) {
return (
<>
<div className="mx-auto mt-6 min-h-[500px] max-w-screen-2xl px-8 pb-10 lg:min-h-[800px]">
<Suspense>{children}</Suspense>
</div>
<FAQ handle="plp-faqs" />
<div className="min-h-[500px] lg:min-h-[800px]">{children}</div>
<Footer />
</>

View File

@ -6,7 +6,7 @@ import { Menu, Metaobject } from 'lib/shopify/types';
import { createUrl, findParentCollection } from 'lib/utils';
import get from 'lodash.get';
import { useParams, useRouter, useSearchParams } from 'next/navigation';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import FilterField from './field';
type FiltersListProps = {
@ -31,11 +31,13 @@ const FiltersList = ({ years, makes, models, menu, autoFocusField }: FiltersList
PART_TYPES.find((type) => type.value === partTypeCollection) || null
);
const makeIdFromSearchParams = searchParams.get(MAKE_FILTER_ID);
const [make, setMake] = useState<Metaobject | null>(
(partType &&
makes.find((make) =>
searchParams.get(MAKE_FILTER_ID)
? make.id === searchParams.get(MAKE_FILTER_ID)
makeIdFromSearchParams
? make.id === makeIdFromSearchParams
: params.collection?.includes(make.name!.toLowerCase())
)) ||
null
@ -52,6 +54,22 @@ const FiltersList = ({ years, makes, models, menu, autoFocusField }: FiltersList
const disabled = !partType || !make || !model || !year;
useEffect(() => {
if (partType) {
const _make = makes.find((make) =>
makeIdFromSearchParams
? make.id === makeIdFromSearchParams
: params.collection?.includes(make.name!.toLowerCase())
);
if (_make) {
setMake(_make);
setModel(null);
setYear(null);
}
}
}, [makeIdFromSearchParams, makes, params.collection, partType]);
const onChangeMake = (value: Metaobject | null) => {
setMake(value);
setModel(null);

View File

@ -2,14 +2,24 @@ import ManufacturersGrid from 'components/manufacturers-grid';
import Tag from 'components/tag';
import { getMetaobjects } from 'lib/shopify';
const Manufacturers = async () => {
const Manufacturers = async ({
variant = 'home'
}: {
variant?: 'engines' | 'transmissions' | 'home';
}) => {
const manufacturers = await getMetaobjects('make');
const title: Record<typeof variant, string> = {
engines: 'Engines',
home: 'Parts',
transmissions: 'Transmissions'
};
return (
<div className="px-6 py-20">
<div className="mx-auto flex max-w-7xl flex-col gap-3">
<Tag text="Get Started" />
<h3 className="mb-3 text-3xl font-semibold lg:text-4xl">Browse Parts By Manufacturer</h3>
<ManufacturersGrid manufacturers={manufacturers} />
<h3 className="mb-3 text-3xl font-semibold lg:text-4xl">{`Browse ${title[variant]} By Manufacturer`}</h3>
<ManufacturersGrid manufacturers={manufacturers} variant={variant} />
</div>
</div>
);

View File

@ -1,11 +1,12 @@
import { GlobeAltIcon, StarIcon } from '@heroicons/react/24/outline';
import { MAKE_FILTER_ID } from 'lib/constants';
import { Metaobject } from 'lib/shopify/types';
import ButtonGroup from './button-group';
import ManufacturerItem from './item';
type ManufacturersGridProps = {
manufacturers: Metaobject[];
variant?: 'engine' | 'transmission' | 'home';
variant?: 'engines' | 'transmissions' | 'home';
};
const ManufacturersGrid = ({ manufacturers, variant = 'home' }: ManufacturersGridProps) => {
@ -22,7 +23,15 @@ const ManufacturersGrid = ({ manufacturers, variant = 'home' }: ManufacturersGri
<div className="mt-6 grid grid-cols-2 gap-x-12 gap-y-5 md:grid-cols-3 md:gap-y-8 lg:grid-cols-4 xl:grid-cols-5">
{popularManufacturers.map((manufacturer) => (
<div key={manufacturer.id} className="flex flex-col gap-2">
<ManufacturerItem manufacturer={manufacturer} />
{variant === 'home' ? (
<ManufacturerItem manufacturer={manufacturer} />
) : (
<ManufacturerItem
manufacturer={manufacturer}
className={'rounded border border-primary px-2 py-1'}
href={`/search/${variant}?${MAKE_FILTER_ID}=${manufacturer.id}`}
/>
)}
{variant === 'home' && <ButtonGroup manufacturer={manufacturer} />}
</div>
))}
@ -37,7 +46,15 @@ const ManufacturersGrid = ({ manufacturers, variant = 'home' }: ManufacturersGri
.toSorted((a, b) => a.display_name!.localeCompare(b.display_name!))
.map((manufacturer) => (
<div key={manufacturer.id} className="flex flex-col gap-2">
<ManufacturerItem manufacturer={manufacturer} />
{variant === 'home' ? (
<ManufacturerItem manufacturer={manufacturer} />
) : (
<ManufacturerItem
manufacturer={manufacturer}
className={'rounded border border-primary px-2 py-1'}
href={`/search/${variant}?${MAKE_FILTER_ID}=${manufacturer.id}`}
/>
)}
{variant === 'home' && <ButtonGroup manufacturer={manufacturer} />}
</div>
))}

View File

@ -1,16 +1,19 @@
import ImageDisplay from 'components/page/image-display';
import { Metaobject } from 'lib/shopify/types';
import Link from 'next/link';
import { Suspense } from 'react';
import { twMerge } from 'tailwind-merge';
const ManufacturerItem = ({
manufacturer,
className
className,
href
}: {
manufacturer: Metaobject;
className?: string;
href?: string;
}) => {
return (
const children = (
<div className={twMerge('flex w-full flex-row items-center justify-between', className)}>
<span className="text-sm leading-5">{manufacturer.display_name}</span>
<div className="hidden md:block">
@ -25,6 +28,11 @@ const ManufacturerItem = ({
</div>
</div>
);
if (href) {
return <Link href={href}>{children}</Link>;
}
return children;
};
export default ManufacturerItem;