From bd1679f62c09483467e7c3527bf070d0ec39a1cb Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Sun, 23 Jun 2024 17:18:59 +0100 Subject: [PATCH] v3 subscription endpoints --- .../route.tsx | 32 +++++++++++++++++ .../route.tsx | 32 +++++++++++++++++ .../route.tsx | 34 +++++++++++++++++++ apps/webapp/app/utils/pathBuilder.ts | 8 +++++ 4 files changed, 106 insertions(+) create mode 100644 apps/webapp/app/routes/_app.orgs.$organizationId.subscription.v3.canceled/route.tsx create mode 100644 apps/webapp/app/routes/_app.orgs.$organizationId.subscription.v3.complete/route.tsx create mode 100644 apps/webapp/app/routes/_app.orgs.$organizationId.subscription.v3.failed/route.tsx diff --git a/apps/webapp/app/routes/_app.orgs.$organizationId.subscription.v3.canceled/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationId.subscription.v3.canceled/route.tsx new file mode 100644 index 000000000..2aa39b96d --- /dev/null +++ b/apps/webapp/app/routes/_app.orgs.$organizationId.subscription.v3.canceled/route.tsx @@ -0,0 +1,32 @@ +import { LoaderFunctionArgs } from "@remix-run/server-runtime"; +import { z } from "zod"; +import { prisma } from "~/db.server"; +import { redirectWithErrorMessage } from "~/models/message.server"; +import { v3PlansPath } from "~/utils/pathBuilder"; + +const ParamsSchema = z.object({ + organizationId: z.string(), +}); + +export const loader = async ({ request, params }: LoaderFunctionArgs) => { + const { organizationId } = ParamsSchema.parse(params); + + const org = await prisma.organization.findUnique({ + select: { + slug: true, + }, + where: { + id: organizationId, + }, + }); + + if (!org) { + throw new Response(null, { status: 404 }); + } + + return redirectWithErrorMessage( + `${v3PlansPath({ slug: org.slug })}`, + request, + "You didn't complete your details on Stripe. Please try again." + ); +}; diff --git a/apps/webapp/app/routes/_app.orgs.$organizationId.subscription.v3.complete/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationId.subscription.v3.complete/route.tsx new file mode 100644 index 000000000..baa00da0d --- /dev/null +++ b/apps/webapp/app/routes/_app.orgs.$organizationId.subscription.v3.complete/route.tsx @@ -0,0 +1,32 @@ +import { LoaderFunctionArgs } from "@remix-run/server-runtime"; +import { z } from "zod"; +import { prisma } from "~/db.server"; +import { redirectWithSuccessMessage } from "~/models/message.server"; +import { v3SubscribedPath } from "~/utils/pathBuilder"; + +const ParamsSchema = z.object({ + organizationId: z.string(), +}); + +export const loader = async ({ request, params }: LoaderFunctionArgs) => { + const { organizationId } = ParamsSchema.parse(params); + + const org = await prisma.organization.findUnique({ + select: { + slug: true, + }, + where: { + id: organizationId, + }, + }); + + if (!org) { + throw new Response(null, { status: 404 }); + } + + return redirectWithSuccessMessage( + `${v3SubscribedPath({ slug: org.slug })}`, + request, + "You are now subscribed to Trigger.dev" + ); +}; diff --git a/apps/webapp/app/routes/_app.orgs.$organizationId.subscription.v3.failed/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationId.subscription.v3.failed/route.tsx new file mode 100644 index 000000000..028740d29 --- /dev/null +++ b/apps/webapp/app/routes/_app.orgs.$organizationId.subscription.v3.failed/route.tsx @@ -0,0 +1,34 @@ +import { LoaderFunctionArgs } from "@remix-run/server-runtime"; +import { z } from "zod"; +import { prisma } from "~/db.server"; +import { redirectWithErrorMessage } from "~/models/message.server"; +import { v3PlansPath } from "~/utils/pathBuilder"; + +const ParamsSchema = z.object({ + organizationId: z.string(), +}); + +export const loader = async ({ request, params }: LoaderFunctionArgs) => { + const { organizationId } = ParamsSchema.parse(params); + + const org = await prisma.organization.findUnique({ + select: { + slug: true, + }, + where: { + id: organizationId, + }, + }); + + if (!org) { + throw new Response(null, { status: 404 }); + } + + const url = new URL(request.url); + const searchParams = new URLSearchParams(url.search); + const reason = searchParams.get("reason"); + + let errorMessage = reason ? decodeURIComponent(reason) : "Subscribing failed to complete"; + + return redirectWithErrorMessage(`${v3PlansPath({ slug: org.slug })}`, request, errorMessage); +}; diff --git a/apps/webapp/app/utils/pathBuilder.ts b/apps/webapp/app/utils/pathBuilder.ts index 9741ba831..c9ed4f4f7 100644 --- a/apps/webapp/app/utils/pathBuilder.ts +++ b/apps/webapp/app/utils/pathBuilder.ts @@ -441,6 +441,14 @@ export function v3DeploymentPath( return `${v3DeploymentsPath(organization, project)}/${deployment.shortCode}`; } +export function v3PlansPath(organization: OrgForPath) { + return `${organizationPath(organization)}/v3/billing/plans`; +} + +export function v3SubscribedPath(organization: OrgForPath) { + return `${organizationPath(organization)}/v3/subscribed`; +} + // Integration export function integrationClientPath(organization: OrgForPath, client: IntegrationForPath) { return `${organizationIntegrationsPath(organization)}/${clientParam(client)}`;