fix last bug

This commit is contained in:
Lee Robinson 2024-07-28 22:56:37 -05:00
parent 16b222a22e
commit e938e0783d
4 changed files with 40 additions and 18 deletions

View File

@ -2,11 +2,12 @@
import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/24/outline'; import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/24/outline';
import { GridTileImage } from 'components/grid/tile'; 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'; import Image from 'next/image';
export function Gallery({ images }: { images: { src: string; altText: string }[] }) { export function Gallery({ images }: { images: { src: string; altText: string }[] }) {
const { state, updateImage } = useProduct(); const { state, updateImage } = useProduct();
const updateURL = useUpdateURL();
const imageIndex = state.image ? parseInt(state.image) : 0; const imageIndex = state.image ? parseInt(state.image) : 0;
const nextImageIndex = imageIndex + 1 < images.length ? imageIndex + 1 : 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="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"> <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 <button
formAction={() => updateImage(previousImageIndex.toString())} formAction={() => {
const newState = updateImage(previousImageIndex.toString());
updateURL(newState);
}}
aria-label="Previous product image" aria-label="Previous product image"
className={buttonClassName} className={buttonClassName}
> >
@ -41,7 +45,10 @@ export function Gallery({ images }: { images: { src: string; altText: string }[]
</button> </button>
<div className="mx-1 h-6 w-px bg-neutral-500"></div> <div className="mx-1 h-6 w-px bg-neutral-500"></div>
<button <button
formAction={() => updateImage(nextImageIndex.toString())} formAction={() => {
const newState = updateImage(nextImageIndex.toString());
updateURL(newState);
}}
aria-label="Next product image" aria-label="Next product image"
className={buttonClassName} className={buttonClassName}
> >
@ -60,7 +67,10 @@ export function Gallery({ images }: { images: { src: string; altText: string }[]
return ( return (
<li key={image.src} className="h-20 w-20"> <li key={image.src} className="h-20 w-20">
<button <button
formAction={() => updateImage(index.toString())} formAction={() => {
const newState = updateImage(index.toString());
updateURL(newState);
}}
aria-label="Select product image" aria-label="Select product image"
className="h-full w-full" className="h-full w-full"
> >

View File

@ -11,14 +11,13 @@ type ProductState = {
type ProductContextType = { type ProductContextType = {
state: ProductState; state: ProductState;
updateOption: (name: string, value: string) => void; updateOption: (name: string, value: string) => ProductState;
updateImage: (index: string) => void; updateImage: (index: string) => ProductState;
}; };
const ProductContext = createContext<ProductContextType | undefined>(undefined); const ProductContext = createContext<ProductContextType | undefined>(undefined);
export function ProductProvider({ children }: { children: React.ReactNode }) { export function ProductProvider({ children }: { children: React.ReactNode }) {
const router = useRouter();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const getInitialState = () => { const getInitialState = () => {
@ -38,17 +37,15 @@ export function ProductProvider({ children }: { children: React.ReactNode }) {
); );
const updateOption = (name: string, value: string) => { const updateOption = (name: string, value: string) => {
setOptimisticState({ [name]: value }); const newState = { [name]: value };
const newParams = new URLSearchParams(window.location.search); setOptimisticState(newState);
newParams.set(name, value); return { ...state, ...newState };
router.push(`?${newParams.toString()}`, { scroll: false });
}; };
const updateImage = (index: string) => { const updateImage = (index: string) => {
setOptimisticState({ image: index }); const newState = { image: index };
const newParams = new URLSearchParams(window.location.search); setOptimisticState(newState);
newParams.set('image', index); return { ...state, ...newState };
router.push(`?${newParams.toString()}`, { scroll: false });
}; };
const value = useMemo( const value = useMemo(
@ -70,3 +67,15 @@ export function useProduct() {
} }
return context; 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 });
};
}

View File

@ -1,7 +1,7 @@
'use client'; 'use client';
import clsx from 'clsx'; 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'; import { ProductOption, ProductVariant } from 'lib/shopify/types';
type Combination = { type Combination = {
@ -18,6 +18,7 @@ export function VariantSelector({
variants: ProductVariant[]; variants: ProductVariant[];
}) { }) {
const { state, updateOption } = useProduct(); const { state, updateOption } = useProduct();
const updateURL = useUpdateURL();
const hasNoOptionsOrJustOneOption = const hasNoOptionsOrJustOneOption =
!options.length || (options.length === 1 && options[0]?.values.length === 1); !options.length || (options.length === 1 && options[0]?.values.length === 1);
@ -62,7 +63,10 @@ export function VariantSelector({
return ( return (
<button <button
formAction={() => updateOption(optionNameLowerCase, value)} formAction={() => {
const newState = updateOption(optionNameLowerCase, value);
updateURL(newState);
}}
key={value} key={value}
aria-disabled={!isAvailableForSale} aria-disabled={!isAvailableForSale}
disabled={!isAvailableForSale} disabled={!isAvailableForSale}

View File

@ -8,7 +8,6 @@ export function WelcomeToast() {
// ignore if screen height is too small // ignore if screen height is too small
if (window.innerHeight < 650) return; if (window.innerHeight < 650) return;
if (!document.cookie.includes('welcome-toast=2')) { if (!document.cookie.includes('welcome-toast=2')) {
console.log('Welcome to Next.js Commerce!');
toast('🛍️ Welcome to Next.js Commerce!', { toast('🛍️ Welcome to Next.js Commerce!', {
id: 'welcome-toast', id: 'welcome-toast',
duration: Infinity, duration: Infinity,