| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- import dynamicImport from "next/dynamic";
- import Grid from "@/components/theme/ui/grid/Grid";
- import NotFound from "@/components/theme/search/not-found";
- import { isArray } from "@/utils/type-guards";
- import { GET_FILTER_PRODUCTS } from "@/graphql";
- import { GET_PRODUCTS, GET_PRODUCTS_PAGINATION } from "@/graphql";
- import {
- cachedGraphQLRequest,
- getFilterAttributes,
- } from "@/utils/hooks/useCache";
- import { generateMetadataForPage, buildProductFilters } from "@/utils/helper";
- import SortOrder from "@/components/theme/filters/SortOrder";
- import { SortByFields } from "@/utils/constants";
- import MobileFilter from "@/components/theme/filters/MobileFilter";
- import FilterList from "@/components/theme/filters/FilterList";
- import { ProductsResponse } from "@/components/catalog/type";
- import { MobileSearchBar } from "@components/layout/navbar/MobileSearch";
- import HotSearch from "./_components/HotSearch"
- const Pagination = dynamicImport(
- () => import("@/components/catalog/Pagination"),
- );
- const ProductGridItems = dynamicImport(
- () => import("@/components/catalog/product/ProductGridItems"),
- );
- export const dynamicParams = true;
- export async function generateStaticParams() {
- try {
- const itemsPerPage = 12;
- const commonSearches = [""];
- const params = [];
- for (const query of commonSearches) {
- const { data } = await cachedGraphQLRequest<ProductsResponse>(
- "search",
- GET_PRODUCTS,
- {
- query: query,
- first: 1,
- sortKey: "CREATED_AT",
- reverse: true,
- },
- );
- const totalCount = data?.products?.totalCount || 0;
- const totalPages = Math.ceil(totalCount / itemsPerPage);
- let cursor: string | undefined;
- for (let i = 0; i < totalPages; i++) {
- const pageParams: { page: string; cursor?: string } = {
- page: String(i + 1),
- };
- if (i > 0 && cursor) {
- pageParams.cursor = cursor;
- }
- params.push(pageParams);
- if (i < totalPages - 1) {
- const { data: pageData } =
- await cachedGraphQLRequest<ProductsResponse>(
- "search",
- GET_PRODUCTS,
- {
- query: query,
- first: itemsPerPage,
- sortKey: "CREATED_AT",
- reverse: true,
- ...(cursor && { after: cursor }),
- },
- );
- cursor = pageData?.products?.pageInfo?.endCursor;
- }
- }
- }
- return params;
- } catch (error) {
- console.error("Error generating static params:", error);
- return [];
- }
- }
- export async function generateMetadata({
- searchParams,
- }: {
- searchParams?: Promise<{ [key: string]: string | string[] | undefined }>;
- }) {
- const params = await searchParams;
- const searchQuery = params?.q as string | undefined;
- return generateMetadataForPage("search", {
- title: searchQuery ? `Search: ${searchQuery}` : "Search Products",
- description: searchQuery
- ? `Search results for "${searchQuery}"`
- : "Search for products in our store",
- image: "/search-og.jpg",
- });
- }
- export default async function SearchPage({
- searchParams,
- }: {
- searchParams?: Promise<{ [key: string]: string | string[] | undefined }>;
- }) {
- const params = await searchParams;
- const {
- q: searchValue,
- page,
- cursor,
- before,
- } = (params || {}) as {
- [key: string]: string;
- };
- const itemsPerPage = 12;
- const currentPage = page ? parseInt(page) - 1 : 0;
- const sortValue = params?.sort || "name-asc";
- const selectedSort =
- SortByFields.find((s) => s.key === sortValue) || SortByFields[0];
- const afterCursor: string | undefined = cursor;
- const beforeCursor: string | undefined = before;
- const { filterInput, isFilterApplied } = buildProductFilters(params || {});
- let dataPromise;
- if (isFilterApplied) {
- dataPromise = cachedGraphQLRequest<ProductsResponse>(
- "search",
- GET_FILTER_PRODUCTS,
- {
- query: searchValue,
- filter: filterInput,
- ...(beforeCursor
- ? { last: itemsPerPage, before: beforeCursor }
- : { first: itemsPerPage, after: afterCursor }),
- sortKey: selectedSort.sortKey,
- reverse: selectedSort.reverse,
- },
- );
- } else {
- dataPromise = (async () => {
- let currentAfterCursor: string | undefined = afterCursor;
- if (currentPage > 0 && !afterCursor) {
- const { data: cursorData } =
- await cachedGraphQLRequest<ProductsResponse>(
- "search",
- GET_PRODUCTS_PAGINATION,
- {
- query: searchValue,
- first: currentPage * itemsPerPage,
- sortKey: selectedSort.sortKey,
- reverse: selectedSort.reverse,
- },
- );
- currentAfterCursor = cursorData?.products?.pageInfo?.endCursor;
- }
- return cachedGraphQLRequest<ProductsResponse>("search", GET_PRODUCTS, {
- query: searchValue,
- ...(beforeCursor
- ? { last: itemsPerPage, before: beforeCursor }
- : { first: itemsPerPage, after: currentAfterCursor }),
- sortKey: selectedSort.sortKey,
- reverse: selectedSort.reverse,
- });
- })();
- }
- const [{ data }, filterAttributes] = await Promise.all([
- dataPromise,
- getFilterAttributes(),
- ]);
- const products = data?.products?.edges?.map((e) => e.node) || [];
- const pageInfo = data?.products?.pageInfo;
- const totalCount = data?.products?.totalCount || 0;
- return (
- <>
- <MobileSearchBar />
- <HotSearch />
- {/* <div className="my-10 hidden gap-4 md:flex md:items-baseline md:justify-between w-full mx-auto max-w-screen-2xl px-4 xss:px-7.5">
- <FilterList filterAttributes={filterAttributes} />
- <SortOrder sortOrders={SortByFields} title="Sort by" />
- </div> */}
- {isArray(products) ? (
- <div className="flex items-center justify-between gap-4 py-8 md:hidden mx-auto w-full max-w-screen-2xl px-4 xss:px-7.5">
- <MobileFilter filterAttributes={filterAttributes} />
- <SortOrder sortOrders={SortByFields} title="Sort by" />
- </div>
- ) : null}
- {!isArray(products) && (
- // <NotFound
- // msg={`${
- // searchValue
- // ? `There are no products that match Showing : ${searchValue}`
- // : "There are no products that match Showing"
- // } `}
- // />
- <div>
- <h2>There are no products that match Showing : ${searchValue}</h2>
- <h2 className="text-2xl sm:text-4xl font-semibold mx-auto mt-7.5 w-full max-w-screen-2xl my-3 mx-auto px-4 xss:px-7.5">
- All Top Products
- </h2>
- </div>
- )}
- {isArray(products) ? (
- <Grid className="grid grid-flow-row grid-cols-2 gap-5 lg:gap-11.5 w-full max-w-screen-2xl mx-auto md:grid-cols-3 lg:grid-cols-4 px-4 xss:px-7.5">
- <ProductGridItems products={products} />
- </Grid>
- ) : null}
- {!isFilterApplied && isArray(products) && totalCount > itemsPerPage && (
- <nav
- aria-label="Collection pagination"
- className="my-10 block items-center sm:flex"
- >
- <Pagination
- itemsPerPage={itemsPerPage}
- itemsTotal={totalCount || 0}
- currentPage={currentPage}
- nextCursor={pageInfo?.endCursor}
- prevCursor={pageInfo?.startCursor}
- />
- </nav>
- )}
- {isFilterApplied && isArray(products) && pageInfo?.hasNextPage && (
- <nav
- aria-label="Filtered pagination"
- className="my-10 block items-center sm:flex"
- >
- <Pagination
- itemsPerPage={itemsPerPage}
- itemsTotal={totalCount || 0}
- currentPage={currentPage}
- nextCursor={pageInfo?.endCursor}
- prevCursor={pageInfo?.startCursor}
- />
- </nav>
- )}
- </>
- );
- }
|