diff --git a/apps/webapp/app/components/billing/PricingTiers.tsx b/apps/webapp/app/components/billing/PricingTiers.tsx
index 4f055c413..5726be8ab 100644
--- a/apps/webapp/app/components/billing/PricingTiers.tsx
+++ b/apps/webapp/app/components/billing/PricingTiers.tsx
@@ -44,10 +44,12 @@ export function PricingTiers({
organizationSlug,
plans,
className,
+ showActionText = true,
}: {
organizationSlug: string;
plans: Plans;
className?: string;
+ showActionText?: boolean;
}) {
const currentPlan = useCurrentPlan();
//if they've canceled, we set the subscription to undefined so they can re-upgrade
@@ -67,13 +69,13 @@ export function PricingTiers({
plan={plans.free}
currentSubscription={currentSubscription}
organizationSlug={organizationSlug}
- showActionText={true}
+ showActionText={showActionText}
/>
diff --git a/apps/webapp/app/routes/_app.orgs.plan/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug_.select-plan/route.tsx
similarity index 55%
rename from apps/webapp/app/routes/_app.orgs.plan/route.tsx
rename to apps/webapp/app/routes/_app.orgs.$organizationSlug_.select-plan/route.tsx
index 9c22587d2..045886112 100644
--- a/apps/webapp/app/routes/_app.orgs.plan/route.tsx
+++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug_.select-plan/route.tsx
@@ -1,4 +1,6 @@
import { ChartBarIcon } from "@heroicons/react/20/solid";
+import { LoaderFunctionArgs } from "@remix-run/server-runtime";
+import { redirect, typedjson, useTypedLoaderData } from "remix-typedjson";
import { PricingCalculator } from "~/components/billing/PricingCalculator";
import { PricingTiers, TierEnterprise, TierFree, TierPro } from "~/components/billing/PricingTiers";
import { RunsVolumeDiscountTable } from "~/components/billing/RunsVolumeDiscountTable";
@@ -11,16 +13,34 @@ import {
SheetHeader,
SheetTrigger,
} from "~/components/primitives/Sheet";
+import { featuresForRequest } from "~/features.server";
+import { OrgBillingPlanPresenter } from "~/presenters/OrgBillingPlanPresenter";
+import { OrganizationParamsSchema, organizationBillingPath } from "~/utils/pathBuilder";
+
+export async function loader({ params, request }: LoaderFunctionArgs) {
+ const { organizationSlug } = OrganizationParamsSchema.parse(params);
+
+ const { isManagedCloud } = featuresForRequest(request);
+ if (!isManagedCloud) {
+ return redirect(organizationBillingPath({ slug: organizationSlug }));
+ }
+
+ const presenter = new OrgBillingPlanPresenter();
+ const plans = await presenter.call({ slug: organizationSlug });
+ if (!plans) {
+ throw new Response(null, { status: 404 });
+ }
+
+ return typedjson({ plans, organizationSlug });
+}
export default function ChoosePlanPage() {
+ const { plans, organizationSlug } = useTypedLoaderData();
+
return (
Subscribe for full access
-
-
-
-
-
+
@@ -37,7 +57,7 @@ export default function ChoosePlanPage() {
-
+
diff --git a/apps/webapp/app/utils/pathBuilder.ts b/apps/webapp/app/utils/pathBuilder.ts
index 73f2254d9..e0144309c 100644
--- a/apps/webapp/app/utils/pathBuilder.ts
+++ b/apps/webapp/app/utils/pathBuilder.ts
@@ -105,6 +105,10 @@ export function newOrganizationPath() {
return `/orgs/new`;
}
+export function selectPlanPath(organization: OrgForPath) {
+ return `${organizationPath(organization)}/select-plan`;
+}
+
export function organizationTeamPath(organization: OrgForPath) {
return `${organizationPath(organization)}/team`;
}