Onboarding price selection working

This commit is contained in:
Matt Aitken
2023-12-03 12:10:25 +00:00
parent bae2b05967
commit 6101084439
3 changed files with 52 additions and 16 deletions
@@ -5,7 +5,7 @@ import { Form, useActionData, useNavigation } from "@remix-run/react";
import { ActiveSubscription, Plan, Plans, SetPlanBodySchema } from "@trigger.dev/billing";
import { cn } from "~/utils/cn";
import { DefinitionTip } from "../DefinitionTooltip";
import { Button } from "../primitives/Buttons";
import { Button, LinkButton } from "../primitives/Buttons";
import { Paragraph } from "../primitives/Paragraph";
import SegmentedControl from "../primitives/SegmentedControl";
import { formatNumberCompact } from "~/utils/numberFormatter";
@@ -45,11 +45,13 @@ export function PricingTiers({
plans,
className,
showActionText = true,
freeButtonPath,
}: {
organizationSlug: string;
plans: Plans;
className?: string;
showActionText?: boolean;
freeButtonPath?: string;
}) {
const currentPlan = useCurrentPlan();
//if they've canceled, we set the subscription to undefined so they can re-upgrade
@@ -70,6 +72,7 @@ export function PricingTiers({
currentSubscription={currentSubscription}
organizationSlug={organizationSlug}
showActionText={showActionText}
buttonPath={freeButtonPath}
/>
<TierPro
plan={plans.paid}
@@ -87,11 +90,13 @@ export function TierFree({
organizationSlug,
showActionText,
currentSubscription,
buttonPath,
}: {
plan: Plan;
organizationSlug: string;
showActionText: boolean;
currentSubscription?: ActiveSubscription;
buttonPath?: string;
}) {
const lastSubmission = useActionData();
const [form] = useForm({
@@ -133,15 +138,26 @@ export function TierFree({
</DefinitionTip>
</TierLimit>
<input type="hidden" name="type" value="free" />
<Button
variant="secondary/large"
fullWidth
className="text-md my-6 font-medium"
disabled={isLoading || isCurrentPlan}
LeadingIcon={isLoading ? "spinner-white" : undefined}
>
{isLoading ? "Updating plan" : actionText}
</Button>
{buttonPath ? (
<LinkButton
variant="secondary/large"
fullWidth
className="text-md my-6 font-medium"
to={buttonPath}
>
{actionText}
</LinkButton>
) : (
<Button
variant="secondary/large"
fullWidth
className="text-md my-6 font-medium"
disabled={isLoading || isCurrentPlan}
LeadingIcon={isLoading ? "spinner-white" : undefined}
>
{isLoading ? "Updating plan" : actionText}
</Button>
)}
<ul className="flex flex-col gap-2.5">
<FeatureItem checked>
Up to {plan.runs?.freeAllowance ? formatNumberCompact(plan.runs.freeAllowance) : ""}{" "}
@@ -15,7 +15,11 @@ import {
} from "~/components/primitives/Sheet";
import { featuresForRequest } from "~/features.server";
import { OrgBillingPlanPresenter } from "~/presenters/OrgBillingPlanPresenter";
import { OrganizationParamsSchema, organizationBillingPath } from "~/utils/pathBuilder";
import {
OrganizationParamsSchema,
organizationBillingPath,
organizationPath,
} from "~/utils/pathBuilder";
export async function loader({ params, request }: LoaderFunctionArgs) {
const { organizationSlug } = OrganizationParamsSchema.parse(params);
@@ -40,7 +44,12 @@ export default function ChoosePlanPage() {
return (
<div className="mx-auto flex h-full w-full max-w-[80rem] flex-col items-center justify-center gap-12 overflow-y-auto px-12">
<Header1>Subscribe for full access</Header1>
<PricingTiers organizationSlug={organizationSlug} plans={plans} showActionText={false} />
<PricingTiers
organizationSlug={organizationSlug}
plans={plans}
showActionText={false}
freeButtonPath={organizationPath({ slug: organizationSlug })}
/>
<Sheet>
<SheetTrigger asChild>
+15 -4
View File
@@ -17,12 +17,13 @@ import { Input } from "~/components/primitives/Input";
import { InputGroup } from "~/components/primitives/InputGroup";
import { Label } from "~/components/primitives/Label";
import { RadioGroupItem } from "~/components/primitives/RadioButton";
import { featuresForRequest } from "~/features.server";
import { useFeatures } from "~/hooks/useFeatures";
import { createOrganization } from "~/models/organization.server";
import { NewOrganizationPresenter } from "~/presenters/NewOrganizationPresenter.server";
import { commitCurrentProjectSession, setCurrentProjectId } from "~/services/currentProject.server";
import { requireUserId } from "~/services/session.server";
import { projectPath, rootPath } from "~/utils/pathBuilder";
import { plansPath, projectPath, rootPath, selectPlanPath } from "~/utils/pathBuilder";
const schema = z.object({
orgName: z.string().min(3).max(50),
@@ -61,10 +62,20 @@ export const action: ActionFunction = async ({ request }) => {
const project = organization.projects[0];
const session = await setCurrentProjectId(project.id, request);
const { isManagedCloud } = featuresForRequest(request);
const headers = {
"Set-Cookie": await commitCurrentProjectSession(session),
};
if (isManagedCloud) {
return redirect(selectPlanPath(organization), {
headers,
});
}
return redirect(projectPath(organization, project), {
headers: {
"Set-Cookie": await commitCurrentProjectSession(session),
},
headers,
});
} catch (error: any) {
return json({ errors: { body: error.message } }, { status: 400 });