fix: update core charge appearance

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
Chloe
2024-04-26 19:24:58 +07:00
parent 3a3ff3798f
commit 3bf7fa5af9
14 changed files with 196 additions and 146 deletions

View File

@@ -0,0 +1,103 @@
'use client';
import Price from 'components/price';
import { CORE_VARIANT_ID_KEY, CORE_WAIVER } from 'lib/constants';
import { Money, ProductVariant } from 'lib/shopify/types';
import { cn, createUrl } from 'lib/utils';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
type CoreChargeProps = {
variants: ProductVariant[];
defaultPrice: Money;
};
const CoreCharge = ({ variants, defaultPrice }: CoreChargeProps) => {
const searchParams = useSearchParams();
const pathname = usePathname();
const router = useRouter();
const optionSearchParams = new URLSearchParams(searchParams);
const coreVariantIdSearchParam = optionSearchParams.get(CORE_VARIANT_ID_KEY);
const variant = variants.find((variant: ProductVariant) =>
variant.selectedOptions.every(
(option) => option.value === optionSearchParams.get(option.name.toLowerCase())
)
);
const { coreCharge, waiverAvailable } = variant ?? {};
const handleSelectCoreChargeOption = (action: 'add' | 'remove') => {
if (action === 'add' && variant?.coreVariantId) {
optionSearchParams.set(CORE_VARIANT_ID_KEY, variant.coreVariantId);
} else if (action === 'remove') {
optionSearchParams.set(CORE_VARIANT_ID_KEY, CORE_WAIVER);
}
const newUrl = createUrl(pathname, optionSearchParams);
router.replace(newUrl, { scroll: false });
};
// if the selected variant has changed, and the core change variant id is not the same as the selected variant id
// or if users have selected the core waiver but the selected variant does not have a waiver available
// we remove the core charge from the url
if (
variant?.coreVariantId &&
optionSearchParams.has(CORE_VARIANT_ID_KEY) &&
(coreVariantIdSearchParam !== CORE_WAIVER || !variant.waiverAvailable) &&
coreVariantIdSearchParam !== variant.coreVariantId
) {
optionSearchParams.delete(CORE_VARIANT_ID_KEY);
const newUrl = createUrl(pathname, optionSearchParams);
router.replace(newUrl, { scroll: false });
}
const selectedPayCoreCharge = coreVariantIdSearchParam === variant?.coreVariantId;
const selectedCoreWaiver = coreVariantIdSearchParam === CORE_WAIVER;
return (
<div className="flex flex-col text-xs lg:text-sm">
<div className="mb-2 text-base font-medium">Core Charge</div>
<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">
{waiverAvailable ? (
<li className="flex w-32">
<button
onClick={() => handleSelectCoreChargeOption('remove')}
className={cn(
'flex w-full flex-col flex-wrap items-center justify-center space-y-2 rounded-md border p-2 text-center text-xs font-medium',
{
'ring-2 ring-secondary': selectedCoreWaiver
}
)}
>
<span>Core Waiver</span>
<Price amount="0" currencyCode={defaultPrice.currencyCode} />
</button>
</li>
) : null}
{coreCharge && variant?.coreVariantId ? (
<li className="flex w-32">
<button
onClick={() => handleSelectCoreChargeOption('add')}
className={cn(
'flex w-full flex-col flex-wrap items-center justify-center space-y-2 rounded-md border p-2 text-center text-xs font-medium',
{
'ring-2 ring-secondary': selectedPayCoreCharge
}
)}
>
<span>Core Charge</span>
<Price amount={coreCharge.amount} currencyCode={coreCharge.currencyCode} />
</button>
</li>
) : null}
</ul>
</div>
);
};
export default CoreCharge;

View File

@@ -1,45 +0,0 @@
'use client';
import CoreCharge from 'components/core-charge';
import Price from 'components/price';
import { Money, ProductVariant } from 'lib/shopify/types';
import { useSearchParams } from 'next/navigation';
type PriceWithCoreChargeProps = {
variants: ProductVariant[];
defaultPrice: Money;
};
const PriceWithCoreCharge = ({ 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 (
<>
<div className="mb-4">
{variant && (
<div className="flex flex-row items-center space-x-3 text-sm text-neutral-700">
{variant.sku && <span>SKU: {variant.sku}</span>}
{variant.barcode && <span>Part Number: {variant.barcode}</span>}
</div>
)}
</div>
<div className="mr-auto flex w-auto flex-row flex-wrap items-center gap-3 text-sm">
<Price
amount={price}
currencyCode={variant?.price.currencyCode || defaultPrice.currencyCode}
className="text-2xl font-semibold"
/>
<CoreCharge variant={variant} />
</div>
</>
);
};
export default PriceWithCoreCharge;

View File

@@ -2,8 +2,9 @@ import { AddToCart } from 'components/cart/add-to-cart';
import Prose from 'components/prose';
import { Product } from 'lib/shopify/types';
import { Suspense } from 'react';
import PriceWithCoreCharge from './price-with-core-charge';
import CoreCharge from './core-charge';
import SpecialOffer from './special-offer';
import VariantPrice from './vairant-price';
import { VariantSelector } from './variant-selector';
import Warranty from './warranty';
@@ -12,7 +13,7 @@ export function ProductDescription({ product }: { product: Product }) {
<>
<div className="mb-5 flex flex-col dark:border-neutral-700">
<h1 className="mb-3 text-2xl font-bold">{product.title}</h1>
<PriceWithCoreCharge
<VariantPrice
variants={product.variants}
defaultPrice={product.priceRange.minVariantPrice}
/>
@@ -28,6 +29,10 @@ export function ProductDescription({ product }: { product: Product }) {
/>
) : null}
<div className="mb-4 border-t pb-4 pt-6 dark:border-neutral-700">
<CoreCharge variants={product.variants} defaultPrice={product.priceRange.minVariantPrice} />
</div>
<div className="mb-4 border-t py-6 dark:border-neutral-700">
<Warranty productType={product.productType} />
</div>

View File

@@ -0,0 +1,31 @@
'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

@@ -51,6 +51,7 @@ export function VariantSelector({
// Update the option params using the current option to reflect how the url *would* change,
// if the option was clicked.
optionSearchParams.set(optionNameLowerCase, value);
const optionUrl = createUrl(pathname, optionSearchParams);
// In order to determine if an option is available for sale, we need to:

View File

@@ -38,16 +38,19 @@ const WarrantySelector = () => {
return (
<ul className="flex min-h-16 flex-row space-x-4 pt-2">
{plans.map((plan) => (
<li
key={plan.key}
onClick={() => setSelectedOptions(plan.key)}
className={cn(
'flex w-32 cursor-pointer flex-col items-center justify-center space-y-2 rounded-md border p-2 text-center text-xs font-medium',
{ 'ring-2 ring-secondary': plan.key === selectedOptions }
)}
>
{plan.template}
<Price amount={String(plan.price)} currencyCode="USD" />
<li key={plan.key} className="flex w-32">
<button
onClick={() => setSelectedOptions(plan.key)}
className={cn(
'flex w-full flex-col flex-wrap items-center justify-center space-y-2 rounded-md border p-2 text-center text-xs font-medium',
{
'ring-2 ring-secondary': plan.key === selectedOptions
}
)}
>
{plan.template}
<Price amount={String(plan.price)} currencyCode="USD" />
</button>
</li>
))}
</ul>