chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import { redirect, typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { BackgroundWrapper } from "~/components/BackgroundWrapper";
|
||||
import { AppContainer, PageBody } from "~/components/layout/AppLayout";
|
||||
import { Header1 } from "~/components/primitives/Headers";
|
||||
import { prisma } from "~/db.server";
|
||||
import { featuresForRequest } from "~/features.server";
|
||||
import { resolveOrgIdFromSlug } from "~/models/organization.server";
|
||||
import { getCurrentPlan, getPlans } from "~/services/platform.v3.server";
|
||||
import { dashboardLoader } from "~/services/routeBuilders/dashboardBuilder";
|
||||
import { OrganizationParamsSchema, organizationPath } from "~/utils/pathBuilder";
|
||||
import { PricingPlans } from "../resources.orgs.$organizationSlug.select-plan";
|
||||
|
||||
export const loader = dashboardLoader(
|
||||
{
|
||||
params: OrganizationParamsSchema,
|
||||
context: async (params) => {
|
||||
const organizationId = await resolveOrgIdFromSlug(params.organizationSlug);
|
||||
return organizationId ? { organizationId } : {};
|
||||
},
|
||||
authorization: { action: "manage", resource: { type: "billing" } },
|
||||
// Full-screen subscribe gate outside the org layout: keep redirecting on
|
||||
// denial rather than throwing the permission panel.
|
||||
unauthorizedRedirect: "/",
|
||||
},
|
||||
async ({ params, request }) => {
|
||||
const { organizationSlug } = params;
|
||||
|
||||
const { isManagedCloud } = featuresForRequest(request);
|
||||
if (!isManagedCloud) {
|
||||
return redirect(organizationPath({ slug: organizationSlug }));
|
||||
}
|
||||
|
||||
const plans = await getPlans();
|
||||
if (!plans) {
|
||||
throw new Response(null, { status: 404, statusText: "Plans not found" });
|
||||
}
|
||||
|
||||
const organization = await prisma.organization.findFirst({
|
||||
where: { slug: organizationSlug },
|
||||
});
|
||||
|
||||
if (!organization) {
|
||||
throw new Response(null, { status: 404, statusText: "Organization not found" });
|
||||
}
|
||||
|
||||
if (organization.isActivated) {
|
||||
return redirect(organizationPath({ slug: organizationSlug }));
|
||||
}
|
||||
|
||||
const currentPlan = await getCurrentPlan(organization.id);
|
||||
|
||||
const periodEnd = new Date();
|
||||
periodEnd.setMonth(periodEnd.getMonth() + 1);
|
||||
|
||||
return typedjson({ ...plans, ...currentPlan, organizationSlug, periodEnd });
|
||||
}
|
||||
);
|
||||
|
||||
export default function ChoosePlanPage() {
|
||||
const { plans, v3Subscription, organizationSlug, periodEnd, addOnPricing } =
|
||||
useTypedLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<AppContainer>
|
||||
<PageBody className="bg-background-deep">
|
||||
<BackgroundWrapper>
|
||||
<div className="mx-auto mt-4 flex h-fit min-h-full max-w-320 flex-col items-center justify-center gap-8 lg:mt-0">
|
||||
<Header1 className="text-center">Subscribe for full access</Header1>
|
||||
<div className="w-full rounded-lg border border-grid-bright bg-background-dimmed p-5 shadow-lg">
|
||||
<PricingPlans
|
||||
plans={plans}
|
||||
concurrencyAddOnPricing={addOnPricing.concurrency}
|
||||
subscription={v3Subscription}
|
||||
organizationSlug={organizationSlug}
|
||||
hasPromotedPlan
|
||||
periodEnd={periodEnd}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</BackgroundWrapper>
|
||||
</PageBody>
|
||||
</AppContainer>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user