@blocklet/payment-react
Version:
Reusable react components for payment kit v2
128 lines (127 loc) • 4.75 kB
JavaScript
import { fromUnitToToken } from "@ocap/util";
export { primaryContrastColor } from "../../libs/util.js";
export const INTERVAL_LOCALE_KEY = {
day: "common.daily",
week: "common.weekly",
month: "common.monthly",
year: "common.yearly"
};
export function countryCodeToFlag(code) {
if (!code || code.length !== 2) return "";
return String.fromCodePoint(
...code.toUpperCase().split("").map((c) => 127397 + c.charCodeAt(0))
);
}
export function formatTokenAmount(unitAmount, currency) {
if (!unitAmount || !currency) return "0";
try {
const tokenAmount = fromUnitToToken(String(unitAmount), currency.decimal || 0);
const num = Number(tokenAmount);
if (!Number.isFinite(num)) return "0";
const abs = Math.abs(num);
const precision = abs > 0 && abs < 0.01 ? 6 : 2;
const formatted = num.toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: precision });
return formatted.replace(/(\.\d*?)0+$/, "$1").replace(/\.$/, "") || "0";
} catch {
return "0";
}
}
export function getUnitAmountForCurrency(price, currency) {
if (!price || !currency) return "0";
const options = price.price_currency_options || price.currency_options || [];
const option = options.find((x) => x.currency_id === currency.id);
if (option) {
if (option.custom_unit_amount) {
return option.custom_unit_amount.preset || option.custom_unit_amount.presets?.[0] || option.unit_amount;
}
return option.unit_amount;
}
if (price.currency_id === currency.id) {
return price.unit_amount || "0";
}
return "0";
}
export function formatDynamicUnitPrice(price, currency, exchangeRate) {
if (!price || !currency) return null;
const isDynamic = price.pricing_type === "dynamic";
if (isDynamic && exchangeRate && price.base_amount) {
const rate = Number(exchangeRate);
if (rate > 0 && Number.isFinite(rate)) {
const baseUsd = Number(price.base_amount);
if (baseUsd > 0 && Number.isFinite(baseUsd)) {
const tokenAmount = baseUsd / rate;
const abs = Math.abs(tokenAmount);
const precision = abs > 0 && abs < 0.01 ? 6 : 2;
return tokenAmount.toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: precision }).replace(/(\.\d*?)0+$/, "$1").replace(/\.$/, "") || "0";
}
}
}
if (!exchangeRate && price.base_amount != null) {
const baseUsd = Number(price.base_amount);
if (baseUsd >= 0 && Number.isFinite(baseUsd)) {
return baseUsd.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
}
return formatTokenAmount(getUnitAmountForCurrency(price, currency), currency);
}
export function tSafe(t, key, fallback) {
const v = t(key);
return v && !v.includes(".") ? v : fallback;
}
export const whiteTooltipSx = {
"& .MuiTooltip-tooltip": {
bgcolor: "background.paper",
color: "text.primary",
border: "1px solid",
borderColor: "divider",
borderRadius: "10px",
boxShadow: "0 8px 24px rgba(0,0,0,0.12)",
p: 1.5,
maxWidth: 280,
fontSize: 12
},
"& .MuiTooltip-arrow": {
color: "background.paper",
"&::before": { border: "1px solid", borderColor: "divider" }
}
};
export function formatTrialText(t, days, interval) {
const key = interval || "day";
const intervalKey = days > 1 ? `common.${key}s` : `common.${key}`;
return t("payment.checkout.free", { count: days, interval: t(intervalKey) });
}
export function getSessionHeaderMeta(t, session, product, items) {
const mode = session?.mode || "payment";
const isSubscription = ["subscription", "setup"].includes(mode);
const isCreditTopup = items.length === 1 && mode === "payment" && items[0]?.price?.product?.type === "credit" && items[0]?.price?.metadata?.credit_config;
let badge;
if (isCreditTopup) {
badge = "topup";
} else if (isSubscription) {
badge = "subscription";
} else {
badge = "oneTime";
}
const badgeLabel = t(`payment.checkout.typeBadge.${badge}`);
const productName = product?.name || items[0]?.price?.product?.name || "";
let title = productName;
if (productName) {
if (isSubscription) {
title = t("payment.checkout.headerTitle.subscribe", { name: productName });
} else if (!isCreditTopup) {
title = t("payment.checkout.headerTitle.purchase", { name: productName });
}
}
let subtitle = "";
if (isCreditTopup) {
subtitle = t("payment.checkout.subtitle.creditsTopup");
} else if (isSubscription) {
const planName = product?.metadata?.plan_name || product?.metadata?.plan_display_name;
if (planName) {
subtitle = planName;
}
} else {
subtitle = t("payment.checkout.subtitle.oneTime");
}
return { badge, badgeLabel, title, subtitle };
}