57 lines
1.7 KiB
TypeScript
57 lines
1.7 KiB
TypeScript
import {Money} from '@shopify/hydrogen';
|
|
import type {MoneyV2} from '@shopify/hydrogen/storefront-api-types';
|
|
|
|
/** Free shipping threshold in major currency units (e.g. 75 = $75). Match store promos. */
|
|
const FREE_SHIPPING_THRESHOLD_MAJOR = 75;
|
|
|
|
type Props = {
|
|
subtotal?: MoneyV2 | null;
|
|
};
|
|
|
|
/**
|
|
* Figma cart drawer (node 123:13655): “Add $X more for free shipping” + progress bar.
|
|
*/
|
|
export function CartFreeShippingBar({subtotal}: Props) {
|
|
if (!subtotal?.amount || !subtotal.currencyCode) return null;
|
|
|
|
const spent = Number.parseFloat(subtotal.amount);
|
|
if (!Number.isFinite(spent) || spent < 0) return null;
|
|
|
|
const threshold = FREE_SHIPPING_THRESHOLD_MAJOR;
|
|
const pct = Math.min(100, Math.max(0, (spent / threshold) * 100));
|
|
const remaining = Math.max(0, threshold - spent);
|
|
|
|
if (remaining <= 0) {
|
|
return (
|
|
<div className="cart-free-ship cart-free-ship--met">
|
|
<p className="cart-free-ship__text">
|
|
You qualify for <strong>free shipping</strong>
|
|
</p>
|
|
<div className="cart-free-ship__track">
|
|
<div className="cart-free-ship__fill" style={{width: '100%'}} />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="cart-free-ship">
|
|
<p className="cart-free-ship__text">
|
|
Add{' '}
|
|
<span className="cart-free-ship__accent">
|
|
<Money
|
|
data={{
|
|
amount: remaining.toFixed(2),
|
|
currencyCode: subtotal.currencyCode,
|
|
}}
|
|
/>
|
|
</span>{' '}
|
|
more for free shipping
|
|
</p>
|
|
<div className="cart-free-ship__track">
|
|
<div className="cart-free-ship__fill" style={{width: `${pct}%`}} />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|