@coursebuilder/commerce-next
Version:
Commerce Functionality for Course Builder with Next.js
47 lines (46 loc) • 4.04 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import React from 'react';
import { ClockIcon } from 'lucide-react';
import pluralize from 'pluralize';
import Countdown from 'react-countdown';
const SaleCountdown = ({ coupon, size = 'lg', ...rest }) => {
// storing coupon in state so that it doesn't rerender
// and cause layout shift when quantity changes
const [storedCoupon, setStoredCoupon] = React.useState(coupon);
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => {
setMounted(true);
}, []);
React.useEffect(() => {
coupon && setStoredCoupon(coupon);
}, [coupon]);
if (!storedCoupon?.expires)
return null;
return mounted ? (_jsx(Countdown, { date: storedCoupon.expires, renderer: (props) => size === 'sm' ? (_jsx(CountdownRendererSm, { ...props, ...rest })) : (_jsx(CountdownRendererLg, { ...props, ...rest })) })) : null;
};
export default SaleCountdown;
const CountdownRendererLg = ({ days, hours, minutes, seconds, completed, ...rest }) => {
const [srValues] = React.useState({
days,
hours,
minutes,
seconds,
});
const screenReaderValues = `${srValues.days} days, ${srValues.hours} hours, ${srValues.minutes} minutes, and ${srValues.seconds} seconds`;
return completed ? null : (_jsx(_Fragment, { children: _jsx("div", { className: "w-full px-10 pb-7", ...rest, children: _jsxs("div", { className: "w-full rounded-lg text-center", children: [_jsx("p", { className: "pb-5 font-medium", children: "Hurry! Price goes up in:" }), _jsxs("div", { "aria-hidden": "true", "data-grid": "", className: "mx-auto grid max-w-[300px] grid-cols-4 items-center justify-center gap-2 tabular-nums tracking-tight", children: [_jsxs("div", { className: "flex flex-col", children: [_jsx("span", { "data-number": "days", className: "text-3xl font-medium leading-none", children: days }), _jsx("span", { "data-label": "days", className: "pt-1 text-xs font-medium uppercase tracking-wide text-gray-500", children: "days" })] }), _jsxs("div", { className: "flex flex-col", children: [_jsx("span", { "data-number": "hours", className: "text-3xl font-medium leading-none", children: hours }), _jsx("span", { "data-label": "hours", className: "pt-1 text-xs font-medium uppercase tracking-wide text-gray-500", children: "hours" })] }), _jsxs("div", { className: "flex flex-col", children: [_jsx("span", { "data-number": "minutes", className: "text-3xl font-medium leading-none", children: minutes }), _jsx("span", { "data-label": "minutes", className: "pt-1 text-xs font-medium uppercase tracking-wide text-gray-500", children: "minutes" })] }), _jsxs("div", { className: "flex flex-col", children: [_jsx("span", { "data-number": "seconds", className: "text-3xl font-medium leading-none", children: seconds }), _jsx("span", { "data-label": "seconds", className: "pt-1 text-xs font-medium uppercase tracking-wide text-gray-500", children: "seconds" })] })] }), _jsx("div", { className: "sr-only", children: screenReaderValues })] }) }) }));
};
const CountdownRendererSm = ({ days, hours, minutes, seconds, completed, ...rest }) => {
const [srValues] = React.useState({
days,
hours,
minutes,
seconds,
});
return completed ? null : (_jsx(_Fragment, { children: _jsx("div", { className: "w-full px-10 pb-7", ...rest, children: _jsx("div", { className: "w-full rounded-lg text-center", children: _jsxs("p", { className: "flex items-center gap-1", children: [_jsx(ClockIcon, { className: "w-5" }), ' ', days > 0
? `${days} ${pluralize('day', days)}`
: hours > 0
? `${hours} ${pluralize('hour', hours)}`
: minutes > 0
? `${minutes} ${pluralize('minute', minutes)}`
: `${seconds} ${pluralize('second', seconds)}`, ' ', "left at this price!"] }) }) }) }));
};