Viewing File: /home/markqprx/iniasli.pro/ssr/assets/billing-page-routes-98918f88.mjs
import { jsx, jsxs } from "react/jsx-runtime";
import { Navigate, Outlet, Link, useSearchParams, useParams, Routes, Route } from "react-router-dom";
import { aW as useAuth, al as useUser, U as StaticPageTitle, T as Trans, az as Navbar, X as ProgressCircle, aA as Footer, _ as useNavigate, u as useSettings, B as Button, q as queryClient, m as message, a as apiClient, ar as useProducts, bs as BillingCycleRadio, bt as findBestPrice, E as opacityAnimation, as as FormattedPrice, i as CheckIcon, S as Skeleton, b as useTrans, t as toast, s as showHttpErrorToast, l as FormattedDate, k as Chip, Z as SvgImage, bu as FormattedCurrency } from "../server-entry.mjs";
import { Fragment, useState, useRef, useEffect, createElement } from "react";
import { B as Breadcrumb, a as BreadcrumbItem, E as EditIcon } from "./Edit-18dc9207.mjs";
import { S as StripeElementsForm, B as BillingRedirectMessage } from "./billing-redirect-message-c6ae9b4e.mjs";
import { loadStripe } from "@stripe/stripe-js";
import { AnimatePresence, m } from "framer-motion";
import { useMutation, useQuery } from "@tanstack/react-query";
import { u as useCancelSubscription, a as useResumeSubscription } from "./use-resume-subscription-d02f5f4b.mjs";
import { C as CalendarTodayIcon, O as OpenInNewIcon } from "./OpenInNew-d3846190.mjs";
import "react-dom/server";
import "process";
import "http";
import "axios";
import "react-router-dom/server.mjs";
import "deepmerge";
import "clsx";
import "@internationalized/date";
import "nano-memoize";
import "zustand";
import "zustand/middleware/immer";
import "nanoid";
import "@internationalized/number";
import "@react-stately/utils";
import "@react-aria/utils";
import "@floating-ui/react-dom";
import "react-merge-refs";
import "@react-aria/focus";
import "react-dom";
import "@react-aria/ssr";
import "react-hook-form";
import "dot-object";
import "url-regex";
import "react-use-clipboard";
import "immer";
import "axios-retry";
import "tus-js-client";
import "react-use-cookie";
import "mime-match";
import "get-video-id";
import "@react-stately/color";
import "./TaskAlt-798b1c02.mjs";
function SubscribedRoute({ children }) {
const { isSubscribed } = useAuth();
if (!isSubscribed) {
return /* @__PURE__ */ jsx(Navigate, { to: "/pricing", replace: true });
}
return children || /* @__PURE__ */ jsx(Outlet, {});
}
function BillingPageLayout() {
const { user } = useAuth();
const query = useUser(user.id, {
with: ["subscriptions.product", "subscriptions.price"]
});
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(StaticPageTitle, { children: /* @__PURE__ */ jsx(Trans, { message: "Billing" }) }),
/* @__PURE__ */ jsx(Navbar, { menuPosition: "billing-page" }),
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
/* @__PURE__ */ jsx("div", { className: "container mx-auto my-24 px-24 flex-auto", children: query.isLoading ? /* @__PURE__ */ jsx(
ProgressCircle,
{
className: "my-80",
"aria-label": "Loading user..",
isIndeterminate: true
}
) : /* @__PURE__ */ jsx(Outlet, {}) }),
/* @__PURE__ */ jsx(Footer, { className: "container mx-auto px-24" })
] })
] });
}
const previousUrl$5 = "/billing";
function ChangePaymentMethodLayout() {
const navigate = useNavigate();
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(Breadcrumb, { children: [
/* @__PURE__ */ jsx(BreadcrumbItem, { isLink: true, onSelected: () => navigate(previousUrl$5), children: /* @__PURE__ */ jsx(Trans, { message: "Billing" }) }),
/* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(Trans, { message: "Payment method" }) })
] }),
/* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold my-32 md:my-64", children: /* @__PURE__ */ jsx(Trans, { message: "Change payment method" }) }),
/* @__PURE__ */ jsx(Outlet, {})
] });
}
const previousUrl$4 = "/billing";
function ChangePaymentMethodPage() {
const { base_url } = useSettings();
return /* @__PURE__ */ jsxs("div", { className: "max-w-[464px]", children: [
/* @__PURE__ */ jsx(
StripeElementsForm,
{
type: "setupIntent",
submitLabel: /* @__PURE__ */ jsx(Trans, { message: "Change" }),
returnUrl: `${base_url}/billing/change-payment-method/done`
}
),
/* @__PURE__ */ jsx(
Button,
{
variant: "outline",
className: "w-full mt-16",
size: "md",
to: previousUrl$4,
elementType: Link,
type: "button",
children: /* @__PURE__ */ jsx(Trans, { message: "Go back" })
}
)
] });
}
function useBillingUser() {
var _a, _b, _c;
const query = useUser("me", {
with: ["subscriptions.product", "subscriptions.price"]
});
const subscription = (_b = (_a = query.data) == null ? void 0 : _a.user.subscriptions) == null ? void 0 : _b[0];
return { subscription, isLoading: query.isLoading, user: (_c = query.data) == null ? void 0 : _c.user };
}
function invalidateBillingUserQuery() {
queryClient.invalidateQueries({ queryKey: ["users"] });
}
const previousUrl$3 = "/billing";
function ChangePaymentMethodDone() {
const {
billing: { stripe_public_key }
} = useSettings();
const navigate = useNavigate();
const [params] = useSearchParams();
const clientSecret = params.get("setup_intent_client_secret");
const [messageConfig, setMessageConfig] = useState();
const stripeInitiated = useRef();
useEffect(() => {
if (stripeInitiated.current || !clientSecret)
return;
loadStripe(stripe_public_key).then((stripe) => {
if (!stripe) {
setMessageConfig(getRedirectMessageConfig());
return;
}
stripe.retrieveSetupIntent(clientSecret).then(({ setupIntent }) => {
if ((setupIntent == null ? void 0 : setupIntent.status) === "succeeded") {
changeDefaultPaymentMethod(setupIntent.payment_method).then(
() => {
invalidateBillingUserQuery();
}
);
}
setMessageConfig(getRedirectMessageConfig(setupIntent == null ? void 0 : setupIntent.status));
});
});
stripeInitiated.current = true;
}, [stripe_public_key, clientSecret]);
if (!clientSecret) {
navigate(previousUrl$3);
return null;
}
return /* @__PURE__ */ jsx(BillingRedirectMessage, { config: messageConfig });
}
function getRedirectMessageConfig(status) {
switch (status) {
case "succeeded":
return {
...redirectMessageDefaults,
message: message("Payment method changed successfully!"),
status: "success"
};
case "processing":
return {
...redirectMessageDefaults,
message: message(
"Your request is processing. We'll update you when your payment method is confirmed."
),
status: "success"
};
case "requires_payment_method":
return {
...redirectMessageDefaults,
message: message(
"Payment method confirmation failed. Please try another payment method."
),
status: "error"
};
default:
return {
...redirectMessageDefaults,
message: message("Something went wrong"),
status: "error"
};
}
}
const redirectMessageDefaults = {
link: previousUrl$3,
buttonLabel: message("Go back")
};
function changeDefaultPaymentMethod(paymentMethodId) {
return apiClient.post("billing/stripe/change-default-payment-method", {
payment_method_id: paymentMethodId
});
}
function BillingPlanPanel({ title, children }) {
return /* @__PURE__ */ jsxs("div", { className: "mb-64", children: [
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium uppercase pb-16 mb-16 border-b", children: title }),
children
] });
}
function ChangePlanPage() {
const navigate = useNavigate();
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(Breadcrumb, { children: [
/* @__PURE__ */ jsx(BreadcrumbItem, { isLink: true, onSelected: () => navigate("/billing"), children: /* @__PURE__ */ jsx(Trans, { message: "Billing" }) }),
/* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(Trans, { message: "Plans" }) })
] }),
/* @__PURE__ */ jsx("h1", { className: "my-32 text-3xl font-bold md:my-64", children: /* @__PURE__ */ jsx(Trans, { message: "Change your plan" }) }),
/* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Available plans" }), children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: /* @__PURE__ */ jsx(PlanList, {}) }) })
] });
}
function PlanList() {
var _a, _b;
const query = useProducts();
const [selectedCycle, setSelectedCycle] = useState("monthly");
if (query.isLoading) {
return /* @__PURE__ */ jsx(PlanSkeleton, {}, "plan-skeleton");
}
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(
BillingCycleRadio,
{
products: (_a = query.data) == null ? void 0 : _a.products,
selectedCycle,
onChange: setSelectedCycle,
className: "mb-20",
size: "md"
}
),
(_b = query.data) == null ? void 0 : _b.products.map((plan) => {
const price = findBestPrice(selectedCycle, plan.prices);
if (!price || plan.hidden)
return null;
return /* @__PURE__ */ createElement(
m.div,
{
...opacityAnimation,
key: plan.id,
className: "justify-between gap-40 border-b py-32 md:flex"
},
/* @__PURE__ */ jsxs("div", { className: "mb-40 md:mb-0", children: [
/* @__PURE__ */ jsx("div", { className: "text-xl font-bold", children: plan.name }),
/* @__PURE__ */ jsx(FormattedPrice, { price, className: "text-lg" }),
/* @__PURE__ */ jsx("div", { className: "mt-12 text-base", children: plan.description }),
/* @__PURE__ */ jsx(FeatureList, { plan })
] }),
/* @__PURE__ */ jsx(ContinueButton, { product: plan, price })
);
})
] }, "plan-list");
}
function FeatureList({ plan }) {
if (!plan.feature_list.length)
return null;
return /* @__PURE__ */ jsxs("div", { className: "mt-32", children: [
/* @__PURE__ */ jsx("div", { className: "mb-10 text-sm font-semibold", children: /* @__PURE__ */ jsx(Trans, { message: "What's included" }) }),
plan.feature_list.map((feature) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-10 text-sm", children: [
/* @__PURE__ */ jsx(CheckIcon, { className: "text-positive", size: "sm" }),
/* @__PURE__ */ jsx(Trans, { message: feature })
] }, feature))
] });
}
function ContinueButton({ product, price }) {
const { subscription } = useBillingUser();
if (!(subscription == null ? void 0 : subscription.price) || !(subscription == null ? void 0 : subscription.product))
return null;
if (subscription.product_id === product.id && subscription.price_id === price.id) {
return /* @__PURE__ */ jsxs("div", { className: "flex w-[168px] items-center justify-center gap-10 text-muted", children: [
/* @__PURE__ */ jsx(CheckIcon, { size: "md" }),
/* @__PURE__ */ jsx(Trans, { message: "Current plan" })
] });
}
return /* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
className: "w-[168px]",
size: "md",
elementType: Link,
to: `/billing/change-plan/${product.id}/${price.id}/confirm`,
children: /* @__PURE__ */ jsx(Trans, { message: "Continue" })
}
);
}
function PlanSkeleton() {
return /* @__PURE__ */ jsxs(
m.div,
{
...opacityAnimation,
className: "border-b py-32 text-2xl",
children: [
/* @__PURE__ */ jsx(Skeleton, { className: "mb-8" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-14" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-24" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-12" })
]
},
"plan-skeleton"
);
}
function useChangeSubscriptionPlan() {
const { trans } = useTrans();
const navigate = useNavigate();
return useMutation({
mutationFn: (props) => changePlan(props),
onSuccess: () => {
toast(trans(message("Plan changed.")));
invalidateBillingUserQuery();
navigate("/billing");
},
onError: (err) => showHttpErrorToast(err)
});
}
function changePlan({ subscriptionId, ...other }) {
return apiClient.post(`billing/subscriptions/${subscriptionId}/change-plan`, other).then((r) => r.data);
}
const previousUrl$2 = "/billing/change-plan";
function ConfirmPlanChangePage() {
const { productId, priceId } = useParams();
const navigate = useNavigate();
const query = useProducts();
const { subscription } = useBillingUser();
const changePlan2 = useChangeSubscriptionPlan();
if (!query.data || (subscription == null ? void 0 : subscription.price_id) == priceId) {
return /* @__PURE__ */ jsx(Navigate, { to: "/billing/change-plan", replace: true });
}
const newProduct = query.data.products.find((p) => `${p.id}` === productId);
const newPrice = newProduct == null ? void 0 : newProduct.prices.find((p) => `${p.id}` === priceId);
if (!newProduct || !newPrice || !subscription) {
navigate(previousUrl$2);
return null;
}
const newDate = /* @__PURE__ */ jsxs("span", { className: "whitespace-nowrap", children: [
/* @__PURE__ */ jsx(FormattedDate, { date: subscription.renews_at, preset: "long" }),
";"
] });
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(Breadcrumb, { children: [
/* @__PURE__ */ jsx(BreadcrumbItem, { isLink: true, onSelected: () => navigate("/billing"), children: /* @__PURE__ */ jsx(Trans, { message: "Billing" }) }),
/* @__PURE__ */ jsx(BreadcrumbItem, { onSelected: () => navigate(previousUrl$2), children: /* @__PURE__ */ jsx(Trans, { message: "Plans" }) }),
/* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(Trans, { message: "Confirm" }) })
] }),
/* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold my-32 md:my-64", children: /* @__PURE__ */ jsx(Trans, { message: "Confirm your new plan" }) }),
/* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Changing to" }), children: /* @__PURE__ */ jsxs("div", { className: "max-w-[464px]", children: [
/* @__PURE__ */ jsx("div", { className: "text-xl font-bold", children: newProduct.name }),
/* @__PURE__ */ jsx(FormattedPrice, { price: newPrice, className: "text-lg" }),
/* @__PURE__ */ jsx("div", { className: "text-base mt-12 border-b pb-24 mb-48", children: /* @__PURE__ */ jsx(
Trans,
{
message: "You will be charged the new price starting :date",
values: { date: newDate }
}
) }),
/* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
size: "md",
className: "w-full mb-16",
onClick: () => {
changePlan2.mutate({
subscriptionId: subscription.id,
newProductId: newProduct.id,
newPriceId: newPrice.id
});
},
disabled: changePlan2.isPending,
children: /* @__PURE__ */ jsx(Trans, { message: "Confirm" })
}
) }),
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
Button,
{
variant: "outline",
className: "w-full",
to: previousUrl$2,
elementType: Link,
children: /* @__PURE__ */ jsx(Trans, { message: "Go back" })
}
) }),
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted mt-12", children: /* @__PURE__ */ jsx(Trans, { message: "By confirming your new plan, you agree to our terms of Service and privacy policy." }) })
] })
] }) })
] });
}
const previousUrl$1 = "/billing";
function ConfirmPlanCancellationPage() {
const navigate = useNavigate();
const query = useProducts();
const { subscription } = useBillingUser();
const cancelSubscription = useCancelSubscription();
const product = subscription == null ? void 0 : subscription.product;
const price = subscription == null ? void 0 : subscription.price;
if (!query.data) {
return null;
}
if (!subscription || !product || !price) {
navigate(previousUrl$1);
return null;
}
const renewDate = /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: /* @__PURE__ */ jsx(FormattedDate, { date: subscription.renews_at, preset: "long" }) });
const handleSubscriptionCancel = () => {
cancelSubscription.mutate(
{
subscriptionId: subscription.id
},
{
onSuccess: () => {
invalidateBillingUserQuery();
navigate("/billing");
}
}
);
};
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(Breadcrumb, { children: [
/* @__PURE__ */ jsx(BreadcrumbItem, { isLink: true, onSelected: () => navigate(previousUrl$1), children: /* @__PURE__ */ jsx(Trans, { message: "Billing" }) }),
/* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(Trans, { message: "Cancel" }) })
] }),
/* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold my-32 md:my-64", children: /* @__PURE__ */ jsx(Trans, { message: "Cancel your plan" }) }),
/* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Current plan" }), children: /* @__PURE__ */ jsxs("div", { className: "max-w-[464px]", children: [
/* @__PURE__ */ jsx("div", { className: "text-xl font-bold", children: product.name }),
/* @__PURE__ */ jsx(FormattedPrice, { price, className: "text-lg" }),
/* @__PURE__ */ jsxs("div", { className: "text-base mt-12 border-b pb-24 mb-48", children: [
/* @__PURE__ */ jsx(
Trans,
{
message: "Your plan will be canceled, but is still available until the end of your billing period on :date",
values: { date: renewDate }
}
),
/* @__PURE__ */ jsx("div", { className: "mt-20", children: /* @__PURE__ */ jsx(Trans, { message: "If you change your mind, you can renew your subscription." }) })
] }),
/* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
size: "md",
className: "w-full mb-16",
onClick: handleSubscriptionCancel,
disabled: cancelSubscription.isPending,
children: /* @__PURE__ */ jsx(Trans, { message: "Cancel plan" })
}
) }),
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
Button,
{
variant: "outline",
className: "w-full",
to: previousUrl$1,
elementType: Link,
children: /* @__PURE__ */ jsx(Trans, { message: "Go back" })
}
) }),
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted mt-12", children: /* @__PURE__ */ jsx(Trans, { message: "By cancelling your plan, you agree to our terms of service and privacy policy." }) })
] })
] }) })
] });
}
const previousUrl = "/billing";
function ConfirmPlanRenewalPage() {
const navigate = useNavigate();
const query = useProducts();
const { subscription } = useBillingUser();
const resumeSubscription = useResumeSubscription();
const product = subscription == null ? void 0 : subscription.product;
const price = subscription == null ? void 0 : subscription.price;
if (!query.data) {
return null;
}
if (!subscription || !product || !price) {
navigate(previousUrl);
return null;
}
const endDate = /* @__PURE__ */ jsxs("span", { className: "whitespace-nowrap", children: [
/* @__PURE__ */ jsx(FormattedDate, { date: subscription.ends_at, preset: "long" }),
";"
] });
const handleResumeSubscription = () => {
resumeSubscription.mutate(
{
subscriptionId: subscription.id
},
{
onSuccess: () => {
invalidateBillingUserQuery();
navigate("/billing");
}
}
);
};
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(Breadcrumb, { children: [
/* @__PURE__ */ jsx(BreadcrumbItem, { isLink: true, onSelected: () => navigate(previousUrl), children: /* @__PURE__ */ jsx(Trans, { message: "Billing" }) }),
/* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(Trans, { message: "Renew" }) })
] }),
/* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold my-32 md:my-64", children: /* @__PURE__ */ jsx(Trans, { message: "Renew your plan" }) }),
/* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Current plan" }), children: /* @__PURE__ */ jsxs("div", { className: "max-w-[464px]", children: [
/* @__PURE__ */ jsx("div", { className: "text-xl font-bold", children: product.name }),
/* @__PURE__ */ jsx(FormattedPrice, { price, className: "text-lg" }),
/* @__PURE__ */ jsx("div", { className: "text-base mt-12 border-b pb-24 mb-48", children: /* @__PURE__ */ jsx(
Trans,
{
message: "This plan will no longer be canceled. It will renew on :date",
values: { date: endDate }
}
) }),
/* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
size: "md",
className: "w-full mb-16",
onClick: handleResumeSubscription,
disabled: resumeSubscription.isPending,
children: /* @__PURE__ */ jsx(Trans, { message: "Renew plan" })
}
),
/* @__PURE__ */ jsx(
Button,
{
variant: "outline",
className: "w-full",
to: previousUrl,
elementType: Link,
children: /* @__PURE__ */ jsx(Trans, { message: "Go back" })
}
),
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted mt-12", children: /* @__PURE__ */ jsx(Trans, { message: "By renewing your plan, you agree to our terms of service and privacy policy." }) })
] }) })
] });
}
function CancelledPlanPanel() {
const { subscription } = useBillingUser();
if (!(subscription == null ? void 0 : subscription.price) || !(subscription == null ? void 0 : subscription.product))
return null;
const endingDate = /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: /* @__PURE__ */ jsx(FormattedDate, { preset: "long", date: subscription.ends_at }) });
return /* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Current plan" }), children: /* @__PURE__ */ jsxs("div", { className: "mt-24 flex flex-col justify-between gap-20", children: [
/* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx(
Chip,
{
className: "mb-10 w-min",
size: "xs",
radius: "rounded",
color: "danger",
children: /* @__PURE__ */ jsx(Trans, { message: "Canceled" })
}
),
/* @__PURE__ */ jsx("div", { className: "mb-2 text-xl font-bold", children: subscription.product.name }),
/* @__PURE__ */ jsx(FormattedPrice, { className: "mb-8 text-xl", price: subscription.price }),
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-8 text-base", children: [
/* @__PURE__ */ jsx(CalendarTodayIcon, { size: "sm", className: "text-muted" }),
/* @__PURE__ */ jsx("div", { className: "flex-auto", children: /* @__PURE__ */ jsx(
Trans,
{
message: "Your plan will be canceled on :date",
values: { date: endingDate }
}
) })
] })
] }),
/* @__PURE__ */ jsx("div", { className: "w-[233px]", children: /* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
size: "md",
className: "mb-12 w-full",
elementType: Link,
to: "/billing/renew",
children: /* @__PURE__ */ jsx(Trans, { message: "Renew plan" })
}
) })
] }) });
}
function ActivePlanPanel() {
const { subscription } = useBillingUser();
if (!(subscription == null ? void 0 : subscription.price) || !(subscription == null ? void 0 : subscription.product))
return null;
const renewDate = /* @__PURE__ */ jsx(FormattedDate, { preset: "long", date: subscription.renews_at });
return /* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Current plan" }), children: /* @__PURE__ */ jsxs("div", { className: "mt-24 flex justify-between gap-20", children: [
/* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx("div", { className: "mb-2 text-xl font-bold", children: subscription.product.name }),
/* @__PURE__ */ jsx(FormattedPrice, { className: "mb-2 text-xl", price: subscription.price }),
/* @__PURE__ */ jsx("div", { className: "text-base", children: /* @__PURE__ */ jsx(
Trans,
{
message: "Your plan renews on :date",
values: { date: renewDate }
}
) })
] }),
/* @__PURE__ */ jsxs("div", { className: "w-[233px]", children: [
/* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
size: "md",
className: "mb-12 w-full",
elementType: Link,
to: "/billing/change-plan",
disabled: subscription.gateway_name === "none",
children: /* @__PURE__ */ jsx(Trans, { message: "Change plan" })
}
),
/* @__PURE__ */ jsx(
Button,
{
variant: "outline",
color: "danger",
size: "md",
className: "w-full",
elementType: Link,
to: "/billing/cancel",
children: /* @__PURE__ */ jsx(Trans, { message: "Cancel plan" })
}
)
] })
] }) });
}
const paypalSvg = "/assets/paypal-c2a77c63.svg";
function PaymentMethodPanel() {
const { user, subscription } = useBillingUser();
if (!user || !subscription)
return null;
const isPaypal = subscription.gateway_name === "paypal";
const PaymentMethod = isPaypal ? PaypalPaymentMethod : CardPaymentMethod;
return /* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Payment method" }), children: /* @__PURE__ */ jsx(
PaymentMethod,
{
methodClassName: "whitespace-nowrap text-base max-w-[464px] flex items-center gap-10",
linkClassName: "flex items-center gap-4 text-muted mt-18 block hover:underline"
}
) });
}
function CardPaymentMethod({
methodClassName,
linkClassName
}) {
const { user } = useBillingUser();
if (!user)
return null;
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs("div", { className: methodClassName, children: [
/* @__PURE__ */ jsx("span", { className: "capitalize", children: user.card_brand }),
" ••••",
user.card_last_four,
user.card_expires && /* @__PURE__ */ jsx("div", { className: "ml-auto", children: /* @__PURE__ */ jsx(Trans, { message: "Expires :date", values: { date: user.card_expires } }) })
] }),
/* @__PURE__ */ jsxs(Link, { className: linkClassName, to: "/billing/change-payment-method", children: [
/* @__PURE__ */ jsx(EditIcon, { size: "sm" }),
/* @__PURE__ */ jsx(Trans, { message: "Change payment method" })
] })
] });
}
function PaypalPaymentMethod({
methodClassName,
linkClassName
}) {
const { subscription } = useBillingUser();
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx("div", { className: methodClassName, children: /* @__PURE__ */ jsx(SvgImage, { src: paypalSvg }) }),
/* @__PURE__ */ jsxs(
"a",
{
className: linkClassName,
href: `https://www.sandbox.paypal.com/myaccount/autopay/connect/${subscription == null ? void 0 : subscription.gateway_id}/funding`,
target: "_blank",
rel: "noreferrer",
children: [
/* @__PURE__ */ jsx(EditIcon, { size: "sm" }),
/* @__PURE__ */ jsx(Trans, { message: "Change payment method" })
]
}
)
] });
}
const Endpoint = "billing/invoices";
function useInvoices(userId) {
return useQuery({
queryKey: [Endpoint],
queryFn: () => fetchInvoices(userId)
});
}
function fetchInvoices(userId) {
return apiClient.get(Endpoint, { params: { userId } }).then((response) => response.data);
}
function InvoiceHistoryPanel() {
var _a;
const { user } = useBillingUser();
const query = useInvoices(user == null ? void 0 : user.id);
if (!user)
return null;
const invoices = (_a = query.data) == null ? void 0 : _a.invoices;
return /* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Payment history" }), children: /* @__PURE__ */ jsx("div", { className: "max-w-[464px]", children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: query.isLoading ? /* @__PURE__ */ jsx(LoadingSkeleton, {}, "loading-skeleton") : /* @__PURE__ */ jsx(InvoiceList, { invoices }, "invoices") }) }) });
}
function InvoiceList({ invoices }) {
const { base_url } = useSettings();
return /* @__PURE__ */ jsxs(m.div, { ...opacityAnimation, children: [
!(invoices == null ? void 0 : invoices.length) ? /* @__PURE__ */ jsx("div", { className: "text-muted italic", children: /* @__PURE__ */ jsx(Trans, { message: "No invoices yet" }) }) : void 0,
invoices == null ? void 0 : invoices.map((invoice) => {
var _a;
return /* @__PURE__ */ jsxs(
"div",
{
className: "whitespace-nowrap text-base flex items-center justify-between gap-10 mb-14",
children: [
/* @__PURE__ */ jsxs(
"a",
{
href: `${base_url}/billing/invoices/${invoice.uuid}`,
target: "_blank",
className: "flex items-center gap-8 hover:underline",
rel: "noreferrer",
children: [
/* @__PURE__ */ jsx(FormattedDate, { date: invoice.created_at }),
/* @__PURE__ */ jsx(OpenInNewIcon, { size: "xs" })
]
}
),
invoice.subscription.price && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
FormattedCurrency,
{
value: invoice.subscription.price.amount,
currency: invoice.subscription.price.currency
}
) }),
/* @__PURE__ */ jsx(
Chip,
{
size: "xs",
color: invoice.paid ? "positive" : "danger",
radius: "rounded",
children: invoice.paid ? /* @__PURE__ */ jsx(Trans, { message: "Paid" }) : /* @__PURE__ */ jsx(Trans, { message: "Unpaid" })
}
),
/* @__PURE__ */ jsx("div", { children: (_a = invoice.subscription.product) == null ? void 0 : _a.name })
]
},
invoice.id
);
})
] });
}
function LoadingSkeleton() {
return /* @__PURE__ */ jsxs(m.div, { ...opacityAnimation, children: [
/* @__PURE__ */ jsx(Skeleton, { className: "mb-14" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-14" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-14" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-14" }),
/* @__PURE__ */ jsx(Skeleton, {})
] });
}
function BillingPage() {
const { subscription } = useBillingUser();
if (!(subscription == null ? void 0 : subscription.price) || !(subscription == null ? void 0 : subscription.product))
return null;
const planPanel = subscription.ends_at ? /* @__PURE__ */ jsx(CancelledPlanPanel, {}) : /* @__PURE__ */ jsx(ActivePlanPanel, {});
return /* @__PURE__ */ jsxs("div", { children: [
planPanel,
/* @__PURE__ */ jsx(PaymentMethodPanel, {}),
/* @__PURE__ */ jsx(InvoiceHistoryPanel, {})
] });
}
function BillingPageRoutes() {
return /* @__PURE__ */ jsx(Routes, { children: /* @__PURE__ */ jsxs(
Route,
{
path: "/",
element: /* @__PURE__ */ jsx(SubscribedRoute, { children: /* @__PURE__ */ jsx(BillingPageLayout, {}) }),
children: [
/* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(BillingPage, {}) }),
/* @__PURE__ */ jsxs(
Route,
{
path: "change-payment-method",
element: /* @__PURE__ */ jsx(ChangePaymentMethodLayout, {}),
children: [
/* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(ChangePaymentMethodPage, {}) }),
/* @__PURE__ */ jsx(Route, { path: "done", element: /* @__PURE__ */ jsx(ChangePaymentMethodDone, {}) })
]
}
),
/* @__PURE__ */ jsx(Route, { path: "change-plan", element: /* @__PURE__ */ jsx(ChangePlanPage, {}) }),
/* @__PURE__ */ jsx(
Route,
{
path: "change-plan/:productId/:priceId/confirm",
element: /* @__PURE__ */ jsx(ConfirmPlanChangePage, {})
}
),
/* @__PURE__ */ jsx(Route, { path: "cancel", element: /* @__PURE__ */ jsx(ConfirmPlanCancellationPage, {}) }),
/* @__PURE__ */ jsx(Route, { path: "renew", element: /* @__PURE__ */ jsx(ConfirmPlanRenewalPage, {}) })
]
}
) });
}
export {
BillingPageRoutes as default
};
//# sourceMappingURL=billing-page-routes-98918f88.mjs.map
Back to Directory
File Manager