Skip to content

Commit

Permalink
ts
Browse files Browse the repository at this point in the history
  • Loading branch information
nlkluth committed Dec 4, 2023
1 parent 87c5c30 commit 05b4c1d
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 72 deletions.
34 changes: 8 additions & 26 deletions packages/nextjs/app/migration/products/[slug].tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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<ReturnType<typeof getRecommendations>>;
};
}

const ProductPage: NextPage<PageProps> = ({ 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 (
<React.Fragment>
Expand All @@ -41,7 +39,7 @@ const ProductPage: NextPage<PageProps> = ({ data }) => {
</div>
<div className="flex flex-col gap-6 py-6">
<AnimatePresence initial={false} mode="wait">
<React.Fragment key={`${query.slug}:${query.variant}`}>
<React.Fragment key={`${query?.get("slug")}:${query?.get("variant")}`}>
<FadeInOut>
<PageBody product={product} variant={selectedVariant} />
</FadeInOut>
Expand Down Expand Up @@ -75,7 +73,7 @@ const ProductPage: NextPage<PageProps> = ({ 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();

Expand Down Expand Up @@ -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;
7 changes: 3 additions & 4 deletions packages/nextjs/components/ProductFilters/FilterGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ export const FilterGroup: React.FC<FilterGroupProps> = ({ 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<HTMLInputElement>) => {
const { checked, value: optionValue } = e.target;
Expand All @@ -33,8 +32,8 @@ export const FilterGroup: React.FC<FilterGroupProps> = ({ 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 (
<li key={optionValue}>
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/nextjs/components/ProductPage/StyleOptions.tsx
Original file line number Diff line number Diff line change
@@ -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[];
Expand Down
4 changes: 3 additions & 1 deletion packages/nextjs/components/ProductSort.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ type ProductSortProps = Pick<BaseProps, "as" | "showTitle" | "title" | "selectCl

export const ProductSort: React.FC<ProductSortProps> = (props) => {
const { replace, clear, query } = useRouterQueryParams();
return <BaseProductSort {...props} onClear={clear} onReplace={replace} query={query} />;
const searchParams = new URLSearchParams(query ?? "");

return <BaseProductSort {...props} onClear={clear} onReplace={replace} query={Object.fromEntries(searchParams)} />;
};
70 changes: 34 additions & 36 deletions packages/nextjs/utils/getProductBySlug.ts
Original file line number Diff line number Diff line change
@@ -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 });
7 changes: 7 additions & 0 deletions packages/nextjs/utils/groqTypes/ProductDetail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { TypeFromSelection } from "groqd";
import { productBySlugSelection } from "utils/getProductBySlug";
import { NullableArrayType } from "./ProductList";

export type ProductDetail = TypeFromSelection<typeof productBySlugSelection>;
export type ProductDetailVariants = ProductDetail["variants"];
export type Style = NullableArrayType<ProductDetailVariants[number], "style">[number];
2 changes: 1 addition & 1 deletion packages/nextjs/utils/groqTypes/ProductList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export interface CategoryFilterItem {
slug: string;
}

type NullableArrayType<T, K extends keyof T> = Exclude<T[K], null>;
export type NullableArrayType<T, K extends keyof T> = Exclude<T[K], null>;

export type Flavour = NullableArrayType<Product["variants"][number], "flavour">[number];
export type Style = NullableArrayType<Product["variants"][number], "style">[number];
Expand Down

0 comments on commit 05b4c1d

Please sign in to comment.