Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 6 additions & 28 deletions app/dashboard/success/page.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,14 @@
import { Metadata } from "next";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Check } from "lucide-react";

import { SuccessCard } from "@/components/dashboard/success-card";
import { getUserAndSubscription } from "@/lib/data-fetching";

export const metadata: Metadata = {
title: "Subscription Upgrade Success",
description: "Page for successful checkout of annual subscription upgrade",
};

export default function DashboardSuccess() {
return (
<div className="flex min-h-screen items-center justify-center bg-background">
<Card className="mx-4 w-full max-w-md">
<CardContent className="pt-6 text-center">
<div className="mb-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-full bg-green-100 dark:bg-green-900">
<Check className="h-6 w-6 text-green-600 dark:text-green-400" />
</div>
<h1 className="mb-2 text-2xl font-bold tracking-tighter">
Subscription Upgraded
</h1>
<p className="text-muted-foreground">
Thank you! Your subscription has been successfully upgraded to
annual.
</p>
</div>
<Link href="/dashboard">
<Button className="w-full">Return to Dashboard</Button>
</Link>
</CardContent>
</Card>
</div>
);
export default async function DashboardSuccess() {
const { openAppQueryParams } = await getUserAndSubscription();
return <SuccessCard openAppQueryParams={openAppQueryParams} />;
}
5 changes: 3 additions & 2 deletions app/pricing/success/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { constructMetadata } from "@/lib/utils";
import { Metadata } from "next/types";
import { createClient } from "@/utils/supabase/server";
import PricingSuccess from "@/components/pricing-success";
import { getUserAndSubscription } from "@/lib/data-fetching";

export const metadata: Metadata = constructMetadata({
title: "Pricing success",
Expand All @@ -11,10 +12,10 @@ export const metadata: Metadata = constructMetadata({

export default async function Pricing() {
const supabase = createClient();

const { openAppQueryParams } = await getUserAndSubscription();
return (
<>
<PricingSuccess />
<PricingSuccess openAppQueryParams={openAppQueryParams} />
</>
);
}
3 changes: 2 additions & 1 deletion components/dashboard/freetrial-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { DEFAULT_OPEN_APP_CALLBACK } from "@/utils/constants";

type FreeTrialCardProps = {
usage: UsageType;
openAppQueryParams: string | URLSearchParams;
loading: boolean;
};

const DEFAULT_OPEN_APP_CALLBACK = "pearai://pearai.pearai/auth";

const DEFAULT_FREE_TRIAL_MAX_QUOTA = 50; // Sync with "FREE_TRIAL_MAX_QUOTA" env var from server

export default function FreeTrialCard({
Expand Down
3 changes: 2 additions & 1 deletion components/dashboard/subscription-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { UsageType } from "../dashboard";
import { toast } from "sonner";
import { useUpgradeSubscription } from "@/hooks/useUpgradeSubscription";
import TopUpModal from "../topup-modal";
import { DEFAULT_OPEN_APP_CALLBACK } from "@/utils/constants";

type SubscriptionCardProps = {
subscription: Subscription | null;
Expand All @@ -43,7 +44,7 @@ type SubscriptionCardProps = {
loading: boolean;
};

const DEFAULT_OPEN_APP_CALLBACK = "pearai://pearai.pearai/auth";


export default function SubscriptionCard({
subscription,
Expand Down
67 changes: 67 additions & 0 deletions components/dashboard/success-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"use client";

import React, { useEffect } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Check } from "lucide-react";
import { isAllowedUrl } from "@/lib/utils";
import { toast } from "sonner";
import { DEFAULT_OPEN_APP_CALLBACK } from "@/utils/constants";


export const SuccessCard = ({
openAppQueryParams,
}: {
openAppQueryParams: string | URLSearchParams;
}) => {
const router = useRouter();

useEffect(() => {
const openApp = async () => {
const callbackUrl = DEFAULT_OPEN_APP_CALLBACK + "?" + openAppQueryParams;

try {
const finalUrl = new URL(callbackUrl);

if (!isAllowedUrl(finalUrl)) {
throw new Error("Unsafe URL detected.");
}

router.push(finalUrl.toString());
} catch (error) {
console.error("Error opening PearAI app:", error);
toast.error(
"An error occurred while opening the PearAI app. Please try again.",
);
}
};

openApp();
}, [openAppQueryParams, router]);

return (
<div className="flex min-h-screen items-center justify-center bg-background">
<Card className="mx-4 w-full max-w-md">
<CardContent className="pt-6 text-center">
<div className="mb-6">
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-full bg-green-100 dark:bg-green-900">
<Check className="h-6 w-6 text-green-600 dark:text-green-400" />
</div>
<h1 className="mb-2 text-2xl font-bold tracking-tighter">
Subscription Upgraded
</h1>
<p className="text-muted-foreground">
Thank you! Your subscription has been successfully upgraded to
annual.
</p>
</div>
<Link href="/dashboard">
<Button className="w-full">Return to Dashboard</Button>
</Link>
</CardContent>
</Card>
</div>
);
};
34 changes: 32 additions & 2 deletions components/pricing-success.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,42 @@

import { Button } from "@/components/ui/button";
import { useRouter } from "next/navigation";
import { CONTACT_EMAIL } from "@/utils/constants";
import { CONTACT_EMAIL, DEFAULT_OPEN_APP_CALLBACK } from "@/utils/constants";
import Link from "next/link";
import { toast } from "sonner";
import { useEffect } from "react";
import { isAllowedUrl } from "@/lib/utils";

export default function PricingSuccess() {
export default function PricingSuccess({
openAppQueryParams,
}: {
openAppQueryParams: string | URLSearchParams;
}) {
const router = useRouter();

useEffect(() => {
const openApp = async () => {
const callbackUrl = DEFAULT_OPEN_APP_CALLBACK + "?" + openAppQueryParams;

try {
const finalUrl = new URL(callbackUrl);

if (!isAllowedUrl(finalUrl)) {
throw new Error("Unsafe URL detected.");
}

router.push(finalUrl.toString());
} catch (error) {
console.error("Error opening PearAI app:", error);
toast.error(
"An error occurred while opening the PearAI app. Please try again.",
);
}
};

openApp();
}, [openAppQueryParams, router]);

const handleClick = () => {
router.push("/dashboard?checkout=success");
};
Expand Down
1 change: 1 addition & 0 deletions utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const TEST_MODE_ENABLED = ["true", "True", "TRUE"].includes(
);

export const BUNNY_CDN_HOST = "https://pearai.b-cdn.net";
export const DEFAULT_OPEN_APP_CALLBACK = "pearai://pearai.pearai/auth";

export const CONTACT_EMAIL = "[email protected]";

Expand Down