diff --git a/apps/dashboard/app/(app)/authorization/roles/[roleId]/tree.tsx b/apps/dashboard/app/(app)/authorization/roles/[roleId]/tree.tsx index ed46c569e4..f70efd7758 100644 --- a/apps/dashboard/app/(app)/authorization/roles/[roleId]/tree.tsx +++ b/apps/dashboard/app/(app)/authorization/roles/[roleId]/tree.tsx @@ -103,11 +103,13 @@ export const RecursivePermission: React.FC< align: "start", }} > -
- -
{k}
+
+
+ +
{k}
+
+ {description &&

{description}

}
- {description &&

{description}

} ); } diff --git a/apps/dashboard/app/(app)/settings/billing/client.tsx b/apps/dashboard/app/(app)/settings/billing/client.tsx index 94ff98f3dc..312506a36b 100644 --- a/apps/dashboard/app/(app)/settings/billing/client.tsx +++ b/apps/dashboard/app/(app)/settings/billing/client.tsx @@ -40,7 +40,7 @@ type Props = { }>; }; -export const Client: React.FC = (props) => { +const Mutations = () => { const router = useRouter(); const createSubscription = trpc.stripe.createSubscription.useMutation({ @@ -70,6 +70,21 @@ export const Client: React.FC = (props) => { toast.error(err.message); }, }); + const uncancelSubscription = trpc.stripe.uncancelSubscription.useMutation({ + onSuccess: () => { + router.refresh(); + toast.info("Subscription resumed"); + }, + onError: (err) => { + toast.error(err.message); + }, + }); + + return { createSubscription, updateSubscription, cancelSubscription, uncancelSubscription }; +}; + +export const Client: React.FC = (props) => { + const mutations = Mutations(); const allowUpdate = props.subscription && ["active", "trialing"].includes(props.subscription.status); @@ -142,7 +157,7 @@ export const Client: React.FC = (props) => { p.quotas.requestsPerMonth, )} per month immediately.`} onConfirm={async () => - updateSubscription.mutateAsync({ + mutations.updateSubscription.mutateAsync({ oldProductId: props.currentProductId!, newProductId: p.id, }) @@ -161,7 +176,9 @@ export const Client: React.FC = (props) => { } updates your request quota to ${formatNumber( p.quotas.requestsPerMonth, )} per month immediately.`} - onConfirm={() => createSubscription.mutateAsync({ productId: p.id })} + onConfirm={() => + mutations.createSubscription.mutateAsync({ productId: p.id }) + } fineprint={ props.hasPreviousSubscriptions ? "Do you need another trial? Contact support.unkey.dev" @@ -220,7 +237,7 @@ export const Client: React.FC = (props) => { cancelSubscription.mutateAsync()} + onConfirm={() => mutations.cancelSubscription.mutateAsync()} trigger={(onClick) => ( diff --git a/apps/dashboard/app/(app)/settings/billing/components/confirmation.tsx b/apps/dashboard/app/(app)/settings/billing/components/confirmation.tsx index caa205ec08..0523bf615d 100644 --- a/apps/dashboard/app/(app)/settings/billing/components/confirmation.tsx +++ b/apps/dashboard/app/(app)/settings/billing/components/confirmation.tsx @@ -36,9 +36,8 @@ export const Confirm: React.FC = (props) => { className="w-full rounded-lg" onClick={async () => { setLoading(true); - await props.onConfirm(); - setOpen(false); + await props.onConfirm(); setLoading(false); }} > diff --git a/apps/dashboard/app/(app)/settings/billing/page.tsx b/apps/dashboard/app/(app)/settings/billing/page.tsx index 0e065f4443..94a554aa70 100644 --- a/apps/dashboard/app/(app)/settings/billing/page.tsx +++ b/apps/dashboard/app/(app)/settings/billing/page.tsx @@ -7,11 +7,11 @@ import { SettingCard } from "@unkey/ui"; import { Button, Empty, Input } from "@unkey/ui"; import Link from "next/link"; import { redirect } from "next/navigation"; +import { Suspense } from "react"; import Stripe from "stripe"; import { WorkspaceNavbar } from "../workspace-navbar"; import { Client } from "./client"; import { Shell } from "./components/shell"; - export const dynamic = "force-dynamic"; export const revalidate = 0; @@ -165,25 +165,39 @@ export default async function BillingPage() { ]); return ( - + + +
+ +
} - currentProductId={subscription?.items.data.at(0)?.plan.product?.toString() ?? undefined} - /> + > + + ); }