mirror of
https://github.com/vercel/commerce.git
synced 2025-05-18 23:46:58 +00:00
refactoring out variant specific details
This commit is contained in:
parent
5cfc48cdec
commit
4e33afc9dc
@ -1,24 +1,16 @@
|
|||||||
import { AddToCart } from 'components/cart/add-to-cart';
|
import { AddToCart } from 'components/cart/add-to-cart';
|
||||||
import Price from 'components/price';
|
|
||||||
import { Product } from 'lib/shopify/types';
|
import { Product } from 'lib/shopify/types';
|
||||||
import { DescriptionContent } from './description-content';
|
import { DescriptionContent } from './description-content';
|
||||||
import { SustainabilityInfo } from './sustainability-info';
|
import { SustainabilityInfo } from './sustainability-info';
|
||||||
import { VariantSelector } from './variant-selector';
|
import { VariantDetails } from './variant-details';
|
||||||
|
|
||||||
export function ProductDescription({ product }: { product: Product }) {
|
export function ProductDescription({ product }: { product: Product }) {
|
||||||
const filterDeterminedOptions = product.options.filter(option => option.name !== 'Wrap')
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="mb-6 flex flex-col border-b pb-6 dark:border-neutral-700">
|
<div className="flex flex-col">
|
||||||
<h1 className="mb-2 text-2xl md:text-3xl font-medium">{product.title}</h1>
|
<h1 className="mb-2 text-2xl md:text-3xl font-medium">{product.title}</h1>
|
||||||
<div className="place-self-end mr-auto w-auto rounded-full bg-gray-600 p-2 text-sm text-white">
|
|
||||||
<Price
|
|
||||||
amount={product.priceRange.maxVariantPrice.amount}
|
|
||||||
currencyCode={product.priceRange.maxVariantPrice.currencyCode}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<VariantDetails product={product} />
|
||||||
<VariantSelector options={filterDeterminedOptions} variants={product.variants} />
|
|
||||||
<AddToCart variants={product.variants} availableForSale={product.availableForSale} />
|
<AddToCart variants={product.variants} availableForSale={product.availableForSale} />
|
||||||
|
|
||||||
<DescriptionContent product={product} />
|
<DescriptionContent product={product} />
|
||||||
|
26
components/product/variant-details.tsx
Normal file
26
components/product/variant-details.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import Price from "components/price";
|
||||||
|
import { Product } from "lib/shopify/types";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { VariantSelector } from "./variant-selector";
|
||||||
|
|
||||||
|
export function VariantDetails({ product }: { product: Product }) {
|
||||||
|
const filterDeterminedOptions = product.options.filter(option => option.name !== 'Wrap');
|
||||||
|
const [selectedVariant, setSelectedVariant] = useState(product.variants[0]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className='flex flex-col border-b mb-6 dark:border-neutral-700'>
|
||||||
|
<div className="place-self-end mr-auto w-auto rounded-full bg-gray-600 p-2 text-sm text-white mb-6">
|
||||||
|
<Price
|
||||||
|
amount={selectedVariant?.price.amount || product.variants[0]!.price.amount}
|
||||||
|
currencyCode={product.priceRange.maxVariantPrice.currencyCode}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<VariantSelector options={filterDeterminedOptions} variants={product.variants} setSelectedVariant={setSelectedVariant} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -1,10 +1,11 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { ProductOption, ProductVariant } from 'lib/shopify/types';
|
import { Money, ProductOption, ProductVariant } from 'lib/shopify/types';
|
||||||
import { createUrl } from 'lib/utils';
|
import { createUrl } from 'lib/utils';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
|
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
type ParamsMap = {
|
type ParamsMap = {
|
||||||
[key: string]: string; // ie. { color: 'Red', size: 'Large', ... }
|
[key: string]: string; // ie. { color: 'Red', size: 'Large', ... }
|
||||||
@ -14,15 +15,18 @@ type OptimizedVariant = {
|
|||||||
id: string;
|
id: string;
|
||||||
availableForSale: boolean;
|
availableForSale: boolean;
|
||||||
params: URLSearchParams;
|
params: URLSearchParams;
|
||||||
[key: string]: string | boolean | URLSearchParams; // ie. { color: 'Red', size: 'Large', ... }
|
price: Money;
|
||||||
|
[key: string]: string | boolean | URLSearchParams | Money; // ie. { color: 'Red', size: 'Large', ... }
|
||||||
};
|
};
|
||||||
|
|
||||||
export function VariantSelector({
|
export function VariantSelector({
|
||||||
options,
|
options,
|
||||||
variants
|
variants,
|
||||||
|
setSelectedVariant,
|
||||||
}: {
|
}: {
|
||||||
options: ProductOption[];
|
options: ProductOption[];
|
||||||
variants: ProductVariant[];
|
variants: ProductVariant[];
|
||||||
|
setSelectedVariant: (newVariant: ProductVariant) => void,
|
||||||
}) {
|
}) {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const currentParams = useSearchParams();
|
const currentParams = useSearchParams();
|
||||||
@ -46,7 +50,8 @@ export function VariantSelector({
|
|||||||
const optimized: OptimizedVariant = {
|
const optimized: OptimizedVariant = {
|
||||||
id: variant.id,
|
id: variant.id,
|
||||||
availableForSale: variant.availableForSale,
|
availableForSale: variant.availableForSale,
|
||||||
params: new URLSearchParams()
|
params: new URLSearchParams(),
|
||||||
|
price: variant.price,
|
||||||
};
|
};
|
||||||
|
|
||||||
variant.selectedOptions.forEach((selectedOption) => {
|
variant.selectedOptions.forEach((selectedOption) => {
|
||||||
@ -79,6 +84,10 @@ export function VariantSelector({
|
|||||||
const currentUrl = createUrl(pathname, currentParams);
|
const currentUrl = createUrl(pathname, currentParams);
|
||||||
const selectedVariantUrl = createUrl(pathname, selectedVariantParams);
|
const selectedVariantUrl = createUrl(pathname, selectedVariantParams);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSelectedVariant(selectedVariant);
|
||||||
|
}, [selectedVariantUrl]);
|
||||||
|
|
||||||
if (currentUrl !== selectedVariantUrl) {
|
if (currentUrl !== selectedVariantUrl) {
|
||||||
router.replace(selectedVariantUrl);
|
router.replace(selectedVariantUrl);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user