Reward Progress Bar Based on Live Cart State
A progress bar that reads the shopper's cart total and shows how much more they need to add to unlock the next reward tier - updating live as the cart changes.
Example
import React from 'react';
import { Flexbox, Box, Text } from '@evlop/native-components';
import { Money, useCart, CustomBlock } from '@evlop/shopify';
const MILESTONES = [
{ label: '5% off', amount: 30 },
{ label: '10% off', amount: 100 },
{ label: '15% off', amount: 200 },
];
const CartProgressBar: CustomBlock.Section = () => {
const cart = useCart();
const total = +(cart?.totalPrice?.amount ?? 0);
const currency = cart?.totalPrice?.currencyCode ?? 'USD';
const max = MILESTONES[MILESTONES.length - 1].amount;
const progress = Math.min(total / max, 1);
const nextMilestone = MILESTONES.find((m) => total < m.amount);
return (
<Flexbox flexDirection="column" gap={8} p="md">
<Text fontWeight="Bold">
{nextMilestone ? (
<>
Add <Money amount={String(nextMilestone.amount - total)} currencyCode={currency} /> more to get {nextMilestone.label}
</>
) : (
'You unlocked the top reward!'
)}
</Text>
<Box height={8} borderRadius={4} backgroundColor="gray-100">
<Box height={8} borderRadius={4} backgroundColor="primary-500" width={`${progress * 100}%`} />
</Box>
</Flexbox>
);
};
export default CartProgressBar;
How it works
useCart()(from@evlop/shopify) returns the liveShopifyCartfor the current session and re-renders the block automatically whenever the cart changes - adding, removing, or updating quantity all flow straight through, with no manual data fetching or subscriptions. It works in any block type, not justSection.cart.totalPriceis a{ amount: string, currencyCode: string }pair -total/currencyare derived from it, and fed into<Money amount={...} currencyCode={...} />(Money's alternate form, for when you have a raw amount/currency pair rather than aMoneyV2object to pass asprice).- The bar is just two nested
Boxes - an outer one for the track, an inner one whosewidthis aprogress * 100percentage string. No animation or measuring is needed since a percentage width already resizes itself asprogresschanges.
This block needs no configurationSchema - MILESTONES is a plain constant in the file. To let a merchant configure the thresholds/labels/discount copy instead, pull them from data via an array settings panel field instead of hardcoding them.