fix: create side dialog for content inside PDP

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
Chloe
2024-05-21 15:19:00 +07:00
parent 7c60e4e7f4
commit 4684d54ac3
10 changed files with 156 additions and 63 deletions

View File

@@ -2,11 +2,12 @@
import { ArrowPathRoundedSquareIcon } from '@heroicons/react/24/outline';
import Price from 'components/price';
import SideDialog from 'components/side-dialog';
import { CORE_VARIANT_ID_KEY, CORE_WAIVER } from 'lib/constants';
import { CoreChargeOption, ProductVariant } from 'lib/shopify/types';
import { cn, createUrl } from 'lib/utils';
import Link from 'next/link';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { useState } from 'react';
type CoreChargeProps = {
variants: ProductVariant[];
@@ -16,6 +17,7 @@ const CoreCharge = ({ variants }: CoreChargeProps) => {
const pathname = usePathname();
const router = useRouter();
const [isOpenDialog, setIsOpenDialog] = useState(false);
const optionSearchParams = new URLSearchParams(searchParams);
const coreVariantIdSearchParam = optionSearchParams.get(CORE_VARIANT_ID_KEY);
@@ -52,6 +54,9 @@ const CoreCharge = ({ variants }: CoreChargeProps) => {
handleSelectCoreChargeOption((coreChargeOptions[0] as CoreChargeOption).value);
}
const openDialog = () => setIsOpenDialog(true);
const closeDialog = () => setIsOpenDialog(false);
return (
<div className="flex flex-col text-xs lg:text-sm">
<div className="mb-1 flex flex-row items-center space-x-1 divide-x divide-gray-400 leading-none lg:space-x-3">
@@ -59,17 +64,21 @@ const CoreCharge = ({ variants }: CoreChargeProps) => {
<ArrowPathRoundedSquareIcon className="h-5 w-5" />
<span> Core charge </span>
</div>
<Link href="#" className="pl-2 text-blue-800 hover:underline">
<button className="pl-2 text-blue-800 hover:underline" onClick={openDialog}>
Understanding Core Charges and Returns
</Link>
</button>
<SideDialog title="Core Charges and Returns" onClose={closeDialog} open={isOpenDialog}>
<div className="mt-5 flex h-full flex-col overflow-hidden">
<p className="text-sm tracking-tight">
The core charge is a refundable deposit that is added to the price of the part. This
charge ensures that the old, worn-out part is returned to the supplier for proper
disposal or recycling. When you return the old part, you&apos;ll receive a refund of
the core charge.
</p>
</div>
</SideDialog>
</div>
{/*
Plan is to move this to within the a modal tht opens when a user clicks on Understanding Core Charges and Returns
<p className="mb-2 text-sm tracking-tight text-neutral-500">
The core charge is a refundable deposit that is added to the price of the part. This charge
ensures that the old, worn-out part is returned to the supplier for proper disposal or
recycling. When you return the old part, you&apos;ll receive a refund of the core charge.
</p> */}
<ul className="flex min-h-16 flex-row space-x-4 pt-2">
{coreChargeOptions.map((option) => (
<li className="flex w-32" key={option.value}>

View File

@@ -4,7 +4,7 @@ import { Product } from 'lib/shopify/types';
import { Suspense } from 'react';
import CoreCharge from './core-charge';
import SpecialOffer from './special-offer';
import VariantPrice from './vairant-price';
import VariantDetails from './vairant-details';
import { VariantSelector } from './variant-selector';
import Warranty from './warranty';
@@ -13,11 +13,8 @@ export function ProductDescription({ product }: { product: Product }) {
<>
<div className="mb-5 flex flex-col dark:border-neutral-700">
<h1 className="text-xl font-bold md:text-2xl">{product.title}</h1>
<div className="mb-5 flex items-center justify-start gap-x-2">
<p className="text-sm">SKU: 123456</p>
<p className="text-sm">Condition: Used</p>
</div>
<VariantPrice
<VariantDetails
variants={product.variants}
defaultPrice={product.priceRange.minVariantPrice}
/>

View File

@@ -0,0 +1,37 @@
'use client';
import Price from 'components/price';
import { Money, ProductVariant } from 'lib/shopify/types';
import { useSearchParams } from 'next/navigation';
type VariantDetailsProps = {
variants: ProductVariant[];
defaultPrice: Money;
};
const VariantDetails = ({ variants, defaultPrice }: VariantDetailsProps) => {
const searchParams = useSearchParams();
const variant = variants.find((variant: ProductVariant) =>
variant.selectedOptions.every(
(option) => option.value === searchParams.get(option.name.toLowerCase())
)
);
const price = variant?.price.amount || defaultPrice.amount;
return (
<>
<div className="mb-5 flex items-center justify-start gap-x-2">
<p className="text-sm">SKU: {variant?.sku || 'N/A'}</p>
<p className="text-sm">Condition: {variant?.condition || 'N/A'}</p>
</div>
<Price
amount={price}
currencyCode={variant?.price.currencyCode || defaultPrice.currencyCode}
className="text-2xl font-semibold"
/>
</>
);
};
export default VariantDetails;

View File

@@ -1,31 +0,0 @@
'use client';
import Price from 'components/price';
import { Money, ProductVariant } from 'lib/shopify/types';
import { useSearchParams } from 'next/navigation';
type PriceWithCoreChargeProps = {
variants: ProductVariant[];
defaultPrice: Money;
};
const VariantPrice = ({ variants, defaultPrice }: PriceWithCoreChargeProps) => {
const searchParams = useSearchParams();
const variant = variants.find((variant: ProductVariant) =>
variant.selectedOptions.every(
(option) => option.value === searchParams.get(option.name.toLowerCase())
)
);
const price = variant?.price.amount || defaultPrice.amount;
return (
<Price
amount={price}
currencyCode={variant?.price.currencyCode || defaultPrice.currencyCode}
className="text-2xl font-semibold"
/>
);
};
export default VariantPrice;

View File

@@ -1,8 +1,13 @@
'use client';
import { ShieldCheckIcon } from '@heroicons/react/24/outline';
import Link from 'next/link';
import SideDialog from 'components/side-dialog';
import { useState } from 'react';
import WarrantySelector from './warranty-selector';
const Warranty = () => {
const [openingDialog, setOpeningDialog] = useState<'included' | 'terms-conditions' | null>(null);
return (
<div className="flex flex-col text-xs lg:text-sm">
<div className="mb-3 flex flex-row items-center space-x-1 divide-x divide-gray-400 leading-none lg:space-x-3">
@@ -11,14 +16,34 @@ const Warranty = () => {
<span>Warranty</span>
</div>
<div className="pl-2">
<Link href="#" className="text-xs text-blue-800 hover:underline lg:text-sm">
<button
onClick={() => setOpeningDialog('included')}
className="text-xs text-blue-800 hover:underline lg:text-sm"
>
What&apos;s Included
</Link>
</button>
<SideDialog
title="What's Included"
onClose={() => setOpeningDialog(null)}
open={openingDialog === 'included'}
>
<p>Warranty Included</p>
</SideDialog>
</div>
<div className="pl-2">
<Link href="#" className="text-xs text-blue-800 hover:underline lg:text-sm">
<button
onClick={() => setOpeningDialog('terms-conditions')}
className="text-xs text-blue-800 hover:underline lg:text-sm"
>
Terms & Conditions
</Link>
</button>
<SideDialog
title="Terms & Conditions"
onClose={() => setOpeningDialog(null)}
open={openingDialog === 'terms-conditions'}
>
<p>Terms & Conditions</p>
</SideDialog>
</div>
</div>
<WarrantySelector />