diff --git a/packages/nextjs/app/migration/products/[slug].tsx b/packages/nextjs/app/migration/products/[slug].tsx index f85e89dc..7e515843 100644 --- a/packages/nextjs/app/migration/products/[slug].tsx +++ b/packages/nextjs/app/migration/products/[slug].tsx @@ -1,15 +1,12 @@ "use client"; -import type { GetProductsAndCategoriesQuery, Product as ProductType, Variant } from "utils/groqTypes/ProductList"; import * as React from "react"; import { useState } from "react"; -import { GetServerSideProps, NextPage } from "next"; +import { NextPage } from "next"; import { AnimatePresence } from "framer-motion"; import { H6, FadeInOut, BlockContent, Price, QuantityInput, useCart } from "shared-ui"; -import { isSlug } from "utils/isSlug"; import { getRecommendations } from "utils/getRecommendationsQuery"; -import { getProductBySlug } from "utils/getProductBySlug"; import { ImageCarousel } from "components/ImageCarousel"; import { PageHead } from "components/PageHead"; @@ -18,20 +15,21 @@ import { ProductVariantSelector } from "components/ProductPage/ProductVariantSel import { Product } from "components/Product"; import { Breadcrumbs } from "components/Breadcrumbs"; import { useSearchParams, useRouter } from "next/navigation"; +import { ProductDetail, ProductDetailVariants } from "utils/groqTypes/ProductDetail"; interface PageProps { data?: { - products: GetProductsAndCategoriesQuery["products"]; - recommendations: GetProductsAndCategoriesQuery["products"]; + product: ProductDetail; + recommendations: Awaited>; }; } const ProductPage: NextPage = ({ data }) => { const query = useSearchParams(); + const product = data?.product; - const product = data?.products[0]; const selectedVariant = - (product?.variants || []).find((v) => v?.slug && v.slug === query.variant) || product?.variants?.[0]; + (product?.variants || []).find((v) => v?.slug && v.slug === query?.get("variant")) || product?.variants?.[0]; return ( @@ -41,7 +39,7 @@ const ProductPage: NextPage = ({ data }) => {
- + @@ -75,7 +73,7 @@ const ProductPage: NextPage = ({ data }) => { ); }; -const PageBody = ({ variant, product }: { product?: ProductType; variant?: Variant }) => { +const PageBody = ({ variant, product }: { product?: ProductDetail; variant?: ProductDetailVariants[number] }) => { const { replace } = useRouter(); const { updateCart, cartItems } = useCart(); @@ -144,20 +142,4 @@ const PageBody = ({ variant, product }: { product?: ProductType; variant?: Varia ); }; -export const getServerSideProps = (async ({ query }) => { - const { slug } = query; - - const products = await getProductBySlug(isSlug(slug) ? slug : ""); - const recommendations = await getRecommendations(); - - return { - props: { - data: { - products, - recommendations, - }, - }, - }; -}) satisfies GetServerSideProps; - export default ProductPage; diff --git a/packages/nextjs/components/ProductFilters/FilterGroup.tsx b/packages/nextjs/components/ProductFilters/FilterGroup.tsx index eb2e6b31..eadbb91b 100644 --- a/packages/nextjs/components/ProductFilters/FilterGroup.tsx +++ b/packages/nextjs/components/ProductFilters/FilterGroup.tsx @@ -13,8 +13,7 @@ export const FilterGroup: React.FC = ({ group }) => { const { query, add, remove } = useRouterQueryParams(); - const queryValue = query[groupValue]; - const queryValueIsString = typeof queryValue === "string" || queryValue instanceof String; + const queryValue = query?.get(groupValue); const handleChange = (e: ChangeEvent) => { const { checked, value: optionValue } = e.target; @@ -33,8 +32,8 @@ export const FilterGroup: React.FC = ({ group }) => { {options.map(({ value: optionValue, label: optionLabel }) => { const isChecked = !!queryValue && // Value exists - ((queryValueIsString && queryValue === optionValue) || // Single value matches option - (!queryValueIsString && queryValue.includes(optionValue))); // Multiple values includes option + (queryValue === optionValue || // Single value matches option + queryValue.includes(optionValue)); // Multiple values includes option return (
  • diff --git a/packages/nextjs/components/ProductPage/ProductVariantSelector.tsx b/packages/nextjs/components/ProductPage/ProductVariantSelector.tsx index d8064bc1..069afeda 100644 --- a/packages/nextjs/components/ProductPage/ProductVariantSelector.tsx +++ b/packages/nextjs/components/ProductPage/ProductVariantSelector.tsx @@ -1,11 +1,11 @@ import * as React from "react"; import { useMemo } from "react"; import { H6, Select } from "shared-ui"; -import { Variant } from "utils/groqTypes/ProductList"; +import { ProductDetailVariants } from "utils/groqTypes/ProductDetail"; interface Props { - variants: Variant[]; - selectedVariant?: Variant; + variants: ProductDetailVariants; + selectedVariant?: ProductDetailVariants[number]; onVariantChange: (slug?: string) => void; } diff --git a/packages/nextjs/components/ProductPage/StyleOptions.tsx b/packages/nextjs/components/ProductPage/StyleOptions.tsx index 4c92158d..d255eb70 100644 --- a/packages/nextjs/components/ProductPage/StyleOptions.tsx +++ b/packages/nextjs/components/ProductPage/StyleOptions.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import { H6, Pill } from "shared-ui"; -import { Style } from "utils/groqTypes/ProductList"; +import { Style } from "utils/groqTypes/ProductDetail"; interface Props { options: Style[]; diff --git a/packages/nextjs/components/ProductSort.tsx b/packages/nextjs/components/ProductSort.tsx index e0469ff7..0960db9f 100644 --- a/packages/nextjs/components/ProductSort.tsx +++ b/packages/nextjs/components/ProductSort.tsx @@ -6,5 +6,7 @@ type ProductSortProps = Pick = (props) => { const { replace, clear, query } = useRouterQueryParams(); - return ; + const searchParams = new URLSearchParams(query ?? ""); + + return ; }; diff --git a/packages/nextjs/utils/getProductBySlug.ts b/packages/nextjs/utils/getProductBySlug.ts index af9f4386..a217fde8 100644 --- a/packages/nextjs/utils/getProductBySlug.ts +++ b/packages/nextjs/utils/getProductBySlug.ts @@ -1,40 +1,38 @@ import { q, sanityImage } from "groqd"; import { runQuery } from "./sanityClient"; -export const getProductBySlug = (slug = "") => - runQuery( - q("*") - .filterByType("product") - .filter("slug.current == $slug") - .grab({ - _id: q.string(), - name: q.string(), - categories: q("categories").filter().deref().grab$({ - name: q.string(), - }), - slug: q.slug("slug"), - variants: q("variants") - .filter() - .deref() - .grab$({ - _id: q.string(), - name: q.string(), - description: q.contentBlocks(), - msrp: q.number(), - price: q.number(), - slug: q.slug("slug"), - images: sanityImage("images", { - isList: true, - }), - style: q("style") - .filter() - .deref() - .grab$({ - _id: q.string(), - name: q.string(), - }) - .nullable(), - }), +export const productBySlugSelection = { + _id: q.string(), + name: q.string(), + categories: q("categories").filter().deref().grab$({ + name: q.string(), + }), + slug: q.slug("slug"), + variants: q("variants") + .filter() + .deref() + .grab$({ + _id: q.string(), + name: q.string(), + description: q.contentBlocks(), + msrp: q.number(), + price: q.number(), + slug: q.slug("slug"), + images: sanityImage("images", { + isList: true, + withCrop: true, + withHotspot: true, }), - { slug } - ); + style: q("style") + .filter() + .deref() + .grab$({ + _id: q.string(), + name: q.string(), + }) + .nullable(), + }), +}; + +export const getProductBySlug = (slug = "") => + runQuery(q("*").filterByType("product").filter("slug.current == $slug").grab(productBySlugSelection), { slug }); diff --git a/packages/nextjs/utils/groqTypes/ProductDetail.ts b/packages/nextjs/utils/groqTypes/ProductDetail.ts new file mode 100644 index 00000000..f1cace67 --- /dev/null +++ b/packages/nextjs/utils/groqTypes/ProductDetail.ts @@ -0,0 +1,7 @@ +import { TypeFromSelection } from "groqd"; +import { productBySlugSelection } from "utils/getProductBySlug"; +import { NullableArrayType } from "./ProductList"; + +export type ProductDetail = TypeFromSelection; +export type ProductDetailVariants = ProductDetail["variants"]; +export type Style = NullableArrayType[number]; diff --git a/packages/nextjs/utils/groqTypes/ProductList.ts b/packages/nextjs/utils/groqTypes/ProductList.ts index 654fe7d3..09469f06 100644 --- a/packages/nextjs/utils/groqTypes/ProductList.ts +++ b/packages/nextjs/utils/groqTypes/ProductList.ts @@ -32,7 +32,7 @@ export interface CategoryFilterItem { slug: string; } -type NullableArrayType = Exclude; +export type NullableArrayType = Exclude; export type Flavour = NullableArrayType[number]; export type Style = NullableArrayType[number];