fix: Add promoted item to cart

This commit is contained in:
Sol Irvine 2023-09-01 14:54:27 -07:00
parent bd4cabd16c
commit 725a43505a
18 changed files with 167 additions and 101 deletions

View File

@ -2,7 +2,8 @@ import Footer from 'components/layout/footer';
import { SupportedLocale } from 'components/layout/navbar/language-control';
import Navbar from 'components/layout/navbar';
import { getCart, getPage } from 'lib/shopify';
import { getCart, getPage, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import { Suspense } from 'react';
import AboutNaraiDetail from './about-narai-detail';
@ -26,11 +27,16 @@ export default async function Page({ params }: { params: { locale?: SupportedLoc
cart = await getCart(cartId);
}
const promotedItem: Product | undefined = await getProduct({
handle: 'gift-bag-and-postcard-set',
language: params?.locale?.toUpperCase()
});
const awardsPage = await getPage({ handle: 'awards', language: params?.locale?.toUpperCase() });
return (
<div>
<Navbar cart={cart} locale={params?.locale} compact />
<Navbar cart={cart} locale={params?.locale} compact promotedItem={promotedItem} />
<div className="pt-24 md:pt-32">
<AboutNaraiDetail awards={awardsPage.body} />
</div>

View File

@ -2,7 +2,8 @@ import Footer from 'components/layout/footer';
import { SupportedLocale } from 'components/layout/navbar/language-control';
import Navbar from 'components/layout/navbar';
import { getCart } from 'lib/shopify';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import { Suspense } from 'react';
import SagyobarDetail from './sagyobar-detail';
@ -28,9 +29,14 @@ export default async function Page({ params }: { params: { locale?: SupportedLoc
cart = await getCart(cartId);
}
const promotedItem: Product | undefined = await getProduct({
handle: 'gift-bag-and-postcard-set',
language: params?.locale?.toUpperCase()
});
return (
<div>
<Navbar cart={cart} locale={params?.locale} compact />
<Navbar cart={cart} locale={params?.locale} compact promotedItem={promotedItem} />
<div className="pt-12">
<SagyobarDetail />
</div>

View File

@ -2,7 +2,8 @@ import Footer from 'components/layout/footer';
import { SupportedLocale } from 'components/layout/navbar/language-control';
import Navbar from 'components/layout/navbar';
import { getCart } from 'lib/shopify';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import { Suspense } from 'react';
import CompanyDetail from './company-detail';
@ -28,9 +29,14 @@ export default async function Page({ params }: { params: { locale?: SupportedLoc
cart = await getCart(cartId);
}
const promotedItem: Product | undefined = await getProduct({
handle: 'gift-bag-and-postcard-set',
language: params?.locale?.toUpperCase()
});
return (
<div>
<Navbar cart={cart} locale={params?.locale} compact />
<Navbar cart={cart} locale={params?.locale} compact promotedItem={promotedItem} />
<div className="pt-12">
<CompanyDetail />
</div>

View File

@ -2,7 +2,8 @@ import Footer from 'components/layout/footer';
import { SupportedLocale } from 'components/layout/navbar/language-control';
import Navbar from 'components/layout/navbar';
import { getCart } from 'lib/shopify';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import { Suspense } from 'react';
import ConceptDetail from './concept-detail';
@ -28,9 +29,14 @@ export default async function Page({ params }: { params: { locale?: SupportedLoc
cart = await getCart(cartId);
}
const promotedItem: Product | undefined = await getProduct({
handle: 'gift-bag-and-postcard-set',
language: params?.locale?.toUpperCase()
});
return (
<div>
<Navbar cart={cart} locale={params?.locale} compact />
<Navbar cart={cart} locale={params?.locale} compact promotedItem={promotedItem} />
<div className="pt-12">
<ConceptDetail />
</div>

View File

@ -2,7 +2,8 @@ import Footer from 'components/layout/footer';
import { SupportedLocale } from 'components/layout/navbar/language-control';
import Navbar from 'components/layout/navbar';
import { getCart } from 'lib/shopify';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import { Suspense } from 'react';
import Disclosures from './disclosures';
@ -32,9 +33,14 @@ export default async function DisclosuresPage({
cart = await getCart(cartId);
}
const promotedItem: Product | undefined = await getProduct({
handle: 'gift-bag-and-postcard-set',
language: locale?.toUpperCase()
});
return (
<div>
<Navbar cart={cart} locale={locale} compact />
<Navbar cart={cart} locale={locale} compact promotedItem={promotedItem} />
<div className="py-24 md:py-48">
<Disclosures />
</div>

View File

@ -151,7 +151,7 @@ export default async function HomePage({
</div>
<Suspense>
<Footer cart={cart} />
<Footer cart={cart} promotedItem={promotedItem} />
</Suspense>
</div>
);

View File

@ -2,7 +2,8 @@ import Footer from 'components/layout/footer';
import { SupportedLocale } from 'components/layout/navbar/language-control';
import Navbar from 'components/layout/navbar';
import { getCart } from 'lib/shopify';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import { Suspense } from 'react';
import PrivacyPolicy from './privacy-policy';
@ -32,9 +33,14 @@ export default async function PrivacyPage({
cart = await getCart(cartId);
}
const promotedItem: Product | undefined = await getProduct({
handle: 'gift-bag-and-postcard-set',
language: locale?.toUpperCase()
});
return (
<div>
<Navbar cart={cart} locale={locale} compact />
<Navbar cart={cart} locale={locale} compact promotedItem={promotedItem} />
<div className="py-24 md:py-48">
<PrivacyPolicy />
</div>

View File

@ -3,7 +3,8 @@ import { SupportedLocale } from 'components/layout/navbar/language-control';
import { ProductGrid } from 'components/grid/product-grid';
import Navbar from 'components/layout/navbar';
import { getCart } from 'lib/shopify';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import { Suspense } from 'react';
@ -32,9 +33,14 @@ export default async function ProductPage({
cart = await getCart(cartId);
}
const promotedItem: Product | undefined = await getProduct({
handle: 'gift-bag-and-postcard-set',
language: locale?.toUpperCase()
});
return (
<div>
<Navbar cart={cart} locale={locale} compact />
<Navbar cart={cart} locale={locale} compact promotedItem={promotedItem} />
<div className="py-24 md:py-48">
<ProductGrid lang={locale} />
</div>

View File

@ -4,7 +4,8 @@ import Footer from 'components/layout/footer';
import Navbar from 'components/layout/navbar';
import { SupportedLocale } from 'components/layout/navbar/language-control';
import Prose from 'components/prose';
import { getCart, getPage } from 'lib/shopify';
import { getCart, getPage, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import { notFound } from 'next/navigation';
import { Suspense } from 'react';
@ -46,9 +47,14 @@ export default async function Page({ params }: { params: { locale?: SupportedLoc
if (!page) return notFound();
const promotedItem: Product | undefined = await getProduct({
handle: 'gift-bag-and-postcard-set',
language: params?.locale?.toUpperCase()
});
return (
<div>
<Navbar cart={cart} locale={params?.locale} compact showTop />
<Navbar cart={cart} locale={params?.locale} compact showTop promotedItem={promotedItem} />
<div className="mx-auto max-w-xl px-6 pb-24 pt-12 md:pb-48 md:pt-24">
<div className="pb-12">
<ShopsNav />

View File

@ -2,7 +2,8 @@ import Footer from 'components/layout/footer';
import { SupportedLocale } from 'components/layout/navbar/language-control';
import Navbar from 'components/layout/navbar';
import { getCart } from 'lib/shopify';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import { ReactNode, Suspense } from 'react';
@ -31,9 +32,14 @@ export default async function BlogLayout({
cart = await getCart(cartId);
}
const promotedItem: Product | undefined = await getProduct({
handle: 'gift-bag-and-postcard-set',
language: locale?.toUpperCase()
});
return (
<div>
<Navbar cart={cart} locale={locale} compact />
<Navbar cart={cart} locale={locale} compact promotedItem={promotedItem} />
{children}
<Suspense>
<Footer cart={cart} />

View File

@ -4,7 +4,8 @@ import { SupportedLocale } from 'components/layout/navbar/language-control';
import Navbar from 'components/layout/navbar';
import StoriesDetail from 'components/layout/stories-detail';
import { BLOG_HANDLE } from 'lib/constants';
import { getCart } from 'lib/shopify';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import { Suspense } from 'react';
@ -31,9 +32,14 @@ export default async function StoriesPage({
cart = await getCart(cartId);
}
const promotedItem: Product | undefined = await getProduct({
handle: 'gift-bag-and-postcard-set',
language: locale?.toUpperCase()
});
return (
<div>
<Navbar cart={cart} locale={locale} compact />
<Navbar cart={cart} locale={locale} compact promotedItem={promotedItem} />
<div className="py-24 md:py-48">
<StoriesDetail handle={BLOG_HANDLE} locale={locale} />
</div>

View File

@ -2,7 +2,8 @@ import Footer from 'components/layout/footer';
import { SupportedLocale } from 'components/layout/navbar/language-control';
import Navbar from 'components/layout/navbar';
import { getCart } from 'lib/shopify';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import { Suspense } from 'react';
import TermsOfUse from './terms-of-use';
@ -30,9 +31,14 @@ export default async function TermsPage({
cart = await getCart(cartId);
}
const promotedItem: Product | undefined = await getProduct({
handle: 'gift-bag-and-postcard-set',
language: locale?.toUpperCase()
});
return (
<div>
<Navbar cart={cart} locale={locale} compact />
<Navbar cart={cart} locale={locale} compact promotedItem={promotedItem} />
<div className="py-24 md:py-48">
<TermsOfUse />
</div>

View File

@ -28,7 +28,7 @@ export default function DeleteItemButton({ item }: { item: CartItem }) {
}}
disabled={isPending}
className={clsx(
'ease flex h-[17px] w-[17px] items-center justify-center rounded-full bg-neutral-500 transition-all duration-200',
'ease flex h-[17px] w-[17px] items-center justify-center rounded-full bg-dark transition-all duration-200',
{
'cursor-not-allowed px-0': isPending
}

View File

@ -1,8 +1,10 @@
import { getCart } from 'lib/shopify';
import { SupportedLocale } from 'components/layout/navbar/language-control';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import CartModal from './modal';
export default async function Cart() {
export default async function Cart({ locale }: { locale?: SupportedLocale }) {
const cartId = cookies().get('cartId')?.value;
let cart;
@ -10,5 +12,10 @@ export default async function Cart() {
cart = await getCart(cartId);
}
return <CartModal cart={cart} />;
const promotedItem: Product | undefined = await getProduct({
handle: 'gift-bag-and-postcard-set',
language: locale?.toUpperCase() || 'EN'
});
return <CartModal cart={cart} promotedItem={promotedItem} />;
}

View File

@ -1,7 +1,7 @@
'use client';
import { Dialog, Transition } from '@headlessui/react';
import { ShoppingCartIcon } from '@heroicons/react/24/outline';
import { ShoppingBagIcon } from '@heroicons/react/24/outline';
import Price from 'components/price';
import { DEFAULT_OPTION } from 'lib/constants';
import type { Cart, Product } from 'lib/shopify/types';
@ -15,6 +15,7 @@ import CloseCart from './close-cart';
import DeleteItemButton from './delete-item-button';
import EditItemQuantityButton from './edit-item-quantity-button';
import OpenCart from './open-cart';
import { PromotedCartItem } from './promoted-cart-item';
type MerchandiseSearchParams = {
[key: string]: string;
@ -84,8 +85,8 @@ export default function CartModal({
{!cart || cart.lines.length === 0 ? (
<div className="mt-20 flex w-full flex-col items-center justify-center overflow-hidden">
<ShoppingCartIcon className="h-16" />
<p className="mt-6 text-center text-2xl font-bold">Your cart is empty.</p>
<ShoppingBagIcon className="h-16" strokeWidth={1} />
<p className="mt-6 text-center font-serif text-xl">Your shopping bag is empty.</p>
</div>
) : (
<div className="flex h-full flex-col justify-between overflow-hidden p-1">
@ -156,25 +157,21 @@ export default function CartModal({
);
})}
</ul>
{/* {!!promotedItem && (
<InlineAddToCart
variants={promotedItem.variants}
{!!promotedItem && (
<PromotedCartItem
product={promotedItem}
availableForSale={promotedItem.availableForSale}
/>
)} */}
<div className="py-4 text-sm text-neutral-500 dark:text-neutral-400">
{/* <div className="mb-3 flex items-center justify-between border-b border-white/20 pb-1">
)}
<div className="pb-4 pt-12 text-sm text-neutral-500 dark:text-neutral-400">
<div className="mb-3 flex items-center justify-between border-b border-white/20 pb-1">
<p>Taxes</p>
<Price
className="text-right text-base text-white"
amount={cart.cost.totalTaxAmount.amount}
currencyCode={cart.cost.totalTaxAmount.currencyCode}
/>
</div> */}
{/* <div className="mb-3 flex items-center justify-between border-b border-white/20 py-1">
<p className="text-right text-white/50">Calculated at checkout</p>
</div>
<div className="mb-3 flex items-center justify-between border-b border-white/20 py-1">
<p>Shipping</p>
<p className="text-right text-white/50">Calculated at checkout</p>
</div> */}
</div>
<div className="mb-3 flex items-center justify-between border-b border-white/20 py-1">
<p>Total</p>
<Price

View File

@ -2,27 +2,26 @@
import { addItem } from 'components/cart/actions';
import LoadingDots from 'components/loading-dots';
import { ProductVariant } from 'lib/shopify/types';
import { useTranslations } from 'next-intl';
import Price from 'components/price';
import { Product, ProductVariant } from 'lib/shopify/types';
import Image from 'next/image';
import Link from 'next/link';
import { useRouter, useSearchParams } from 'next/navigation';
import { useTransition } from 'react';
export function PromotedCartItem({
variants,
product,
availableForSale
}: {
variants: ProductVariant[];
product: Product;
availableForSale: boolean;
}) {
const router = useRouter();
const searchParams = useSearchParams();
const t = useTranslations('Index');
const firstVariant = variants?.[0];
const [isPending, startTransition] = useTransition();
const defaultVariantId = variants.length === 1 ? variants[0]?.id : undefined;
const variant = variants.find((variant: ProductVariant) =>
const defaultVariantId = product?.variants?.length === 1 ? product?.variants?.[0]?.id : undefined;
const variant = product?.variants?.find((variant: ProductVariant) =>
variant.selectedOptions.every(
(option) => option.value === searchParams.get(option.name.toLowerCase())
)
@ -34,7 +33,7 @@ export function PromotedCartItem({
? 'Please select options'
: undefined;
return firstVariant ? (
return product ? (
<button
aria-label="Add item to cart"
disabled={isPending || !availableForSale || !selectedVariantId}
@ -56,43 +55,40 @@ export function PromotedCartItem({
}}
>
<>
{console.debug({ firstVariant })}
{/* <div key={firstVariant.slug}>
<div className="flex flex-col space-y-2 border border-dark/10 bg-white/20 p-2">
<div className="flex flex-row space-x-4">
<div className="relative z-0 h-16 w-16 cursor-pointer overflow-hidden bg-white">
<Link href={`/product/${firstVariant.path}`} passHref>
<Image
onClick={() => closeSidebarIfPresent()}
width={150}
height={150}
src={firstVariant?.image?.url}
alt={firstVariant?.image?.alt}
unoptimized
/>
</Link>
</div>
<div className="flex flex-1 flex-col text-sm text-white">
<div className="flex flex-col justify-between space-y-2 text-sm">
<span>{firstVariant.price}</span>
<div key={product.handle}>
<div className="flex flex-col space-y-2 border border-dark/10 border-y-white/20 p-2 transition-colors duration-150 hover:border-y-white/40 hover:bg-white/20">
<div className="flex flex-row space-x-4">
<div className="relative z-0 h-16 w-16 cursor-pointer overflow-hidden bg-white">
<Link href={`/product/${product.handle}`} passHref>
<Image
width={150}
height={150}
src={product?.featuredImage?.url}
alt={product?.featuredImage?.altText || product?.title}
unoptimized
/>
</Link>
</div>
<div className="flex flex-1 flex-col text-sm text-white">
<div className="flex flex-col items-start justify-between space-y-2 text-sm">
<span>{product.title}</span>
<span>
{!isPending ? (
<Price
className="flex-none"
amount={product.priceRange.maxVariantPrice.amount}
currencyCode={product.priceRange.maxVariantPrice.currencyCode}
currencyCodeClassName="hidden @[275px]/label:inline"
/>
) : (
<LoadingDots className="bg-white" />
)}
</span>
</div>
</div>
</div>
<button
type="button"
className="border border-white/30 bg-white/20 px-4 py-1 text-xs uppercase tracking-wider text-white transition-colors duration-300 hover:bg-white/40 hover:text-white"
loading={loading}
onClick={addToCart}
>
<> {t('cart.addFeaturedProduct')} </>
</button>
</div>
</div>
</div> */}
{!isPending ? (
<span>{availableForSale ? t('cart.add') : t('cart.out-of-stock')}</span>
) : (
<LoadingDots className="bg-white" />
)}
</>
</button>
) : null;

View File

@ -3,14 +3,20 @@ import CartModal from 'components/cart/modal';
import FacebookIcon from 'components/icons/facebook';
import InstagramIcon from 'components/icons/instagram';
import KanjiLogo from 'components/icons/kanji';
import { Cart } from 'lib/shopify/types';
import { Cart, Product } from 'lib/shopify/types';
import Link from 'next/link';
import FooterMenu from './footer-menu';
import NewsletterFooter from './newsletter-footer';
const { COMPANY_NAME, SITE_NAME } = process.env;
export default async function Footer({ cart }: { cart?: Cart }) {
export default async function Footer({
cart,
promotedItem
}: {
cart?: Cart;
promotedItem?: Product;
}) {
const currentYear = new Date().getFullYear();
const copyrightDate = 2023 + (currentYear > 2023 ? `-${currentYear}` : '');
const copyrightName = COMPANY_NAME || SITE_NAME || '';
@ -89,7 +95,7 @@ export default async function Footer({ cart }: { cart?: Cart }) {
<div className="flex flex-col space-y-2 pt-24">
<div className="flex flex-row justify-between space-x-4">
<CartModal cart={cart} />
<CartModal cart={cart} promotedItem={promotedItem} />
<div className="flex flex-row items-center space-x-6">
<Link
href="https://www.instagram.com/suginomoribrewery/"

View File

@ -4,11 +4,9 @@ import { Transition } from '@headlessui/react';
import { ChevronUpIcon } from '@heroicons/react/24/outline';
import clsx from 'clsx';
import CartModal from 'components/cart/modal';
import OpenCart from 'components/cart/open-cart';
import LogoNamemark from 'components/icons/namemark';
import { Cart, Product } from 'lib/shopify/types';
import Link from 'next/link';
import { Suspense } from 'react';
import { useInView } from 'react-intersection-observer';
import { MenuModal } from '../menu/modal';
import { LanguageControl, SupportedLocale } from './language-control';
@ -63,12 +61,10 @@ export default function Navbar({
</Link>
</div>
<nav className="flex flex-row items-center space-x-4 px-6">
<Suspense fallback={<OpenCart />}>
<div className="flex flex-col-reverse items-center justify-center space-y-2 px-2 md:flex-row md:space-x-6">
<CartModal cart={cart} promotedItem={promotedItem} />
<MenuModal scrolled={!inView} />
</div>
</Suspense>
<div className="flex flex-col-reverse items-center justify-center space-y-2 px-2 md:flex-row md:space-x-6">
<CartModal cart={cart} promotedItem={promotedItem} />
<MenuModal scrolled={!inView} />
</div>
</nav>
</div>
</Transition>
@ -92,9 +88,7 @@ export default function Navbar({
<LanguageControl lang={locale} />
</div>
<div className="flex flex-col-reverse items-center justify-center space-y-2 rounded md:flex-row md:space-x-6 md:space-y-0">
<Suspense fallback={<OpenCart />}>
<CartModal cart={cart} promotedItem={promotedItem} />
</Suspense>
<CartModal cart={cart} promotedItem={promotedItem} />
<MenuModal scrolled={!inView} />
</div>
</nav>