mirror of
https://github.com/vercel/commerce.git
synced 2025-05-31 21:46:58 +00:00
fix last bug
This commit is contained in:
parent
16b222a22e
commit
e938e0783d
components
@ -2,11 +2,12 @@
|
||||
|
||||
import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/24/outline';
|
||||
import { GridTileImage } from 'components/grid/tile';
|
||||
import { useProduct } from 'components/product/product-context';
|
||||
import { useProduct, useUpdateURL } from 'components/product/product-context';
|
||||
import Image from 'next/image';
|
||||
|
||||
export function Gallery({ images }: { images: { src: string; altText: string }[] }) {
|
||||
const { state, updateImage } = useProduct();
|
||||
const updateURL = useUpdateURL();
|
||||
const imageIndex = state.image ? parseInt(state.image) : 0;
|
||||
|
||||
const nextImageIndex = imageIndex + 1 < images.length ? imageIndex + 1 : 0;
|
||||
@ -33,7 +34,10 @@ export function Gallery({ images }: { images: { src: string; altText: string }[]
|
||||
<div className="absolute bottom-[15%] flex w-full justify-center">
|
||||
<div className="mx-auto flex h-11 items-center rounded-full border border-white bg-neutral-50/80 text-neutral-500 backdrop-blur dark:border-black dark:bg-neutral-900/80">
|
||||
<button
|
||||
formAction={() => updateImage(previousImageIndex.toString())}
|
||||
formAction={() => {
|
||||
const newState = updateImage(previousImageIndex.toString());
|
||||
updateURL(newState);
|
||||
}}
|
||||
aria-label="Previous product image"
|
||||
className={buttonClassName}
|
||||
>
|
||||
@ -41,7 +45,10 @@ export function Gallery({ images }: { images: { src: string; altText: string }[]
|
||||
</button>
|
||||
<div className="mx-1 h-6 w-px bg-neutral-500"></div>
|
||||
<button
|
||||
formAction={() => updateImage(nextImageIndex.toString())}
|
||||
formAction={() => {
|
||||
const newState = updateImage(nextImageIndex.toString());
|
||||
updateURL(newState);
|
||||
}}
|
||||
aria-label="Next product image"
|
||||
className={buttonClassName}
|
||||
>
|
||||
@ -60,7 +67,10 @@ export function Gallery({ images }: { images: { src: string; altText: string }[]
|
||||
return (
|
||||
<li key={image.src} className="h-20 w-20">
|
||||
<button
|
||||
formAction={() => updateImage(index.toString())}
|
||||
formAction={() => {
|
||||
const newState = updateImage(index.toString());
|
||||
updateURL(newState);
|
||||
}}
|
||||
aria-label="Select product image"
|
||||
className="h-full w-full"
|
||||
>
|
||||
|
@ -11,14 +11,13 @@ type ProductState = {
|
||||
|
||||
type ProductContextType = {
|
||||
state: ProductState;
|
||||
updateOption: (name: string, value: string) => void;
|
||||
updateImage: (index: string) => void;
|
||||
updateOption: (name: string, value: string) => ProductState;
|
||||
updateImage: (index: string) => ProductState;
|
||||
};
|
||||
|
||||
const ProductContext = createContext<ProductContextType | undefined>(undefined);
|
||||
|
||||
export function ProductProvider({ children }: { children: React.ReactNode }) {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
const getInitialState = () => {
|
||||
@ -38,17 +37,15 @@ export function ProductProvider({ children }: { children: React.ReactNode }) {
|
||||
);
|
||||
|
||||
const updateOption = (name: string, value: string) => {
|
||||
setOptimisticState({ [name]: value });
|
||||
const newParams = new URLSearchParams(window.location.search);
|
||||
newParams.set(name, value);
|
||||
router.push(`?${newParams.toString()}`, { scroll: false });
|
||||
const newState = { [name]: value };
|
||||
setOptimisticState(newState);
|
||||
return { ...state, ...newState };
|
||||
};
|
||||
|
||||
const updateImage = (index: string) => {
|
||||
setOptimisticState({ image: index });
|
||||
const newParams = new URLSearchParams(window.location.search);
|
||||
newParams.set('image', index);
|
||||
router.push(`?${newParams.toString()}`, { scroll: false });
|
||||
const newState = { image: index };
|
||||
setOptimisticState(newState);
|
||||
return { ...state, ...newState };
|
||||
};
|
||||
|
||||
const value = useMemo(
|
||||
@ -70,3 +67,15 @@ export function useProduct() {
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
export function useUpdateURL() {
|
||||
const router = useRouter();
|
||||
|
||||
return (state: ProductState) => {
|
||||
const newParams = new URLSearchParams(window.location.search);
|
||||
Object.entries(state).forEach(([key, value]) => {
|
||||
newParams.set(key, value);
|
||||
});
|
||||
router.push(`?${newParams.toString()}`, { scroll: false });
|
||||
};
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import clsx from 'clsx';
|
||||
import { useProduct } from 'components/product/product-context';
|
||||
import { useProduct, useUpdateURL } from 'components/product/product-context';
|
||||
import { ProductOption, ProductVariant } from 'lib/shopify/types';
|
||||
|
||||
type Combination = {
|
||||
@ -18,6 +18,7 @@ export function VariantSelector({
|
||||
variants: ProductVariant[];
|
||||
}) {
|
||||
const { state, updateOption } = useProduct();
|
||||
const updateURL = useUpdateURL();
|
||||
const hasNoOptionsOrJustOneOption =
|
||||
!options.length || (options.length === 1 && options[0]?.values.length === 1);
|
||||
|
||||
@ -62,7 +63,10 @@ export function VariantSelector({
|
||||
|
||||
return (
|
||||
<button
|
||||
formAction={() => updateOption(optionNameLowerCase, value)}
|
||||
formAction={() => {
|
||||
const newState = updateOption(optionNameLowerCase, value);
|
||||
updateURL(newState);
|
||||
}}
|
||||
key={value}
|
||||
aria-disabled={!isAvailableForSale}
|
||||
disabled={!isAvailableForSale}
|
||||
|
@ -8,7 +8,6 @@ export function WelcomeToast() {
|
||||
// ignore if screen height is too small
|
||||
if (window.innerHeight < 650) return;
|
||||
if (!document.cookie.includes('welcome-toast=2')) {
|
||||
console.log('Welcome to Next.js Commerce!');
|
||||
toast('🛍️ Welcome to Next.js Commerce!', {
|
||||
id: 'welcome-toast',
|
||||
duration: Infinity,
|
||||
|
Loading…
x
Reference in New Issue
Block a user