1import { j as jsxRuntimeExports, r as reactExports, cQ as useRegistrationLinkLazyQuery, cC as useReactiveVar, cD as userVar } from "./chunk-BNtYH5Ky.js"; 2import { c as cn } from "./chunk-C9vQsYDo.js"; 3import { M as MemoizedFormattedMessage } from "./chunk-BTx5AHFF.js"; 4const fmtUSD = (value) => `$${value.toLocaleString("en-US", { maximumFractionDigits: 2 })}`; 5const PERIOD_INTL = { 6 monthly: "Subscription.changePlan.perMonth", 7 quarterly: "Subscription.changePlan.perQuarter", 8 annual: "Subscription.changePlan.perYear" 9}; 10const PlanSummary = ({ quote, trialDays, className }) => { 11 const billable = quote.lines.filter((line) => line.productType !== "metered"); 12 const metered = quote.lines.filter((line) => line.productType === "metered"); 13 return /* @__PURE__ */ jsxRuntimeExports.jsxs( 14 "div", 15 { 16 className: cn( 17 "rounded-xl border border-solid border-primary-200 bg-primary-50 p-4", 18 className 19 ), 20 children: [ 21 /* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { className: "m-0 list-none p-0 flex flex-col gap-1.5 pb-2.5 border-b border-dashed border-primary-200", children: [ 22 billable.map((line) => /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "flex items-baseline justify-between gap-2 text-xs", children: [
23 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-700", children: [ 24 line.name, 25 line.quantity > 1 && ` Ã ${line.quantity}` 26 ] }), 27 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("tabular-nums", line.amount === 0 && "text-success font-semibold"), children: line.amount === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(MemoizedFormattedMessage, { id: "Subscription.changePlan.includedTag" }) : fmtUSD(line.amount) }) 28 ] }, line.key)), 29 quote.setups.map((setup) => /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "flex items-baseline justify-between gap-2 text-xs", children: [ 30 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-700", children: setup.name }), 31 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "tabular-nums", children: setup.waived ? /* @__PURE__ */ jsxRuntimeExports.jsx(MemoizedFormattedMessage, { id: "Subscription.changePlan.includedTag" }) : fmtUSD(setup.amount) }) 32 ] }, setup.setupType)) 33 ] }),
34 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-baseline justify-between gap-2 pt-2.5", children: [ 35 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-bold text-dark-gray", children: /* @__PURE__ */ jsxRuntimeExports.jsx(MemoizedFormattedMessage, { id: "Onboarding.plan.total" }) }), 36 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xl font-bold tabular-nums text-dark-gray", children: [ 37 fmtUSD(quote.recurringAmount), 38 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-medium text-gray-400 ml-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(MemoizedFormattedMessage, { id: PERIOD_INTL[quote.recurrence] ?? PERIOD_INTL.monthly }) }) 39 ] }) 40 ] }), 41 quote.setupAmount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 mb-0 text-xs text-gray-600", children: /* @__PURE__ */ jsxRuntimeExports.jsx( 42 MemoizedFormattedMessage, 43 { 44 id: "Onboarding.plan.setupNote", 45 values: { amount: fmtUSD(quote.setupAmount) } 46 } 47 ) }),
48 !!trialDays && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 mb-0 rounded-lg bg-white border border-solid border-gray-200 px-3 py-2.5 text-xs leading-normal text-gray-600", children: /* @__PURE__ */ jsxRuntimeExports.jsx(MemoizedFormattedMessage, { id: "Onboarding.plan.trialNote", values: { days: trialDays } }) }), 49 trialDays === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 mb-0 rounded-lg bg-white border border-solid border-gray-200 px-3 py-2.5 text-xs leading-normal text-gray-600", children: /* @__PURE__ */ jsxRuntimeExports.jsx( 50 MemoizedFormattedMessage, 51 { 52 id: "Onboarding.plan.chargeTodayNote", 53 values: { amount: fmtUSD(quote.recurringAmount) } 54 } 55 ) }), 56 metered.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 mb-0 text-xs text-gray-400", children: /* @__PURE__ */ jsxRuntimeExports.jsx( 57 MemoizedFormattedMessage, 58 { 59 id: "Onboarding.plan.meteredNote", 60 values: { items: metered.map((line) => line.name).join(", ") } 61 } 62 ) }) 63 ] 64 } 65 ); 66}; 67const REGISTRATION_LINK_KEY = "registration-link-token"; 68const MAX_AGE_MS = 24 * 60 * 60 * 1e3; 69const read = () => { 70 let raw = null; 71 try { 72 raw = localStorage.getItem(REGISTRATION_LINK_KEY); 73 } catch { 74 return null; 75 } 76 if (!raw) return null; 77 try { 78 const parsed = JSON.parse(raw); 79 if (parsed == null ? void 0 : parsed.token) return parsed; 80 return null; 81 } catch { 82 return { token: raw, savedAt: Date.now() }; 83 } 84}; 85const write = (stored) => { 86 try { 87 localStorage.setItem(REGISTRATION_LINK_KEY, JSON.stringify(stored)); 88 } catch { 89 } 90}; 91const clearRegistrationToken = () => { 92 try { 93 localStorage.removeItem(REGISTRATION_LINK_KEY); 94 } catch { 95 } 96}; 97const resolveStoredToken = (userId) => { 98 const stored = read(); 99 if (!stored) return null; 100 const expired = Date.now() - stored.savedAt > MAX_AGE_MS; 101 const otherUser = !!stored.userId && !!userId && stored.userId !== userId; 102 if (expired || otherUser) { 103 clearRegistrationToken(); 104 return null; 105 } 106 if (userId && !stored.userId) write({ ...stored, userId }); 107 return stored.token; 108}; 109const useRegistrationLink = () => { 110 const [token, setToken] = reactExports.useState(null); 111 const [getLink, { data, loading }] = useRegistrationLinkLazyQuery({ fetchPolicy: "no-cache" }); 112 const user = useReactiveVar(userVar); 113 const userId = user == null ? void 0 : user.id; 114 reactExports.useEffect(() => { 115 const fromUrl = new URLSearchParams(window.location.search).get("ref"); 116 if (fromUrl) write({ token: fromUrl, savedAt: Date.now(), ...userId ? { userId } : {} }); 117 const usable = fromUrl ?? resolveStoredToken(userId); 118 setToken(usable); 119 if (!usable) return; 120 getLink({ variables: { token: usable } }); 121 }, [userId]); 122 const link = token ? (data == null ? void 0 : data.registrationLink) ?? null : null; 123 return { 124 token, 125 link, 126 isUnusable: !!link && link.status !== "active", 127 loading 128 }; 129}; 130export { 131 PlanSummary as P, 132 clearRegistrationToken as c, 133 useRegistrationLink as u 134};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.