From 19576d268cbd87ef480c95e9f8aa8569b77e5c9d Mon Sep 17 00:00:00 2001 From: vishal Date: Sat, 7 Dec 2024 13:20:08 +0530 Subject: [PATCH 1/2] Fixes/issue#388 --- app/dashboard/success/page.tsx | 34 +++----------- components/dashboard/success-card.tsx | 66 +++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 28 deletions(-) create mode 100644 components/dashboard/success-card.tsx diff --git a/app/dashboard/success/page.tsx b/app/dashboard/success/page.tsx index 8945065c8..fbc2a8aad 100644 --- a/app/dashboard/success/page.tsx +++ b/app/dashboard/success/page.tsx @@ -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 ( -
- - -
-
- -
-

- Subscription Upgraded -

-

- Thank you! Your subscription has been successfully upgraded to - annual. -

-
- - - -
-
-
- ); +export default async function DashboardSuccess() { + const { openAppQueryParams } = await getUserAndSubscription(); + return ; } diff --git a/components/dashboard/success-card.tsx b/components/dashboard/success-card.tsx new file mode 100644 index 000000000..cb855c115 --- /dev/null +++ b/components/dashboard/success-card.tsx @@ -0,0 +1,66 @@ +"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"; + +const DEFAULT_OPEN_APP_CALLBACK = "pearai://pearai.pearai/auth"; +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 ( +
+ + +
+
+ +
+

+ Subscription Upgraded +

+

+ Thank you! Your subscription has been successfully upgraded to + annual. +

+
+ + + +
+
+
+ ); +}; From c1f7782229a6d473ad569db3a202cc68056027b9 Mon Sep 17 00:00:00 2001 From: vishal Date: Mon, 9 Dec 2024 17:27:25 +0530 Subject: [PATCH 2/2] Fixes/issue#388-commit-2 --- app/pricing/success/page.tsx | 5 ++-- components/dashboard/freetrial-card.tsx | 3 +- components/dashboard/subscription-card.tsx | 3 +- components/dashboard/success-card.tsx | 3 +- components/pricing-success.tsx | 34 ++++++++++++++++++++-- utils/constants.ts | 1 + 6 files changed, 42 insertions(+), 7 deletions(-) diff --git a/app/pricing/success/page.tsx b/app/pricing/success/page.tsx index bc54287b3..2c2d37b97 100644 --- a/app/pricing/success/page.tsx +++ b/app/pricing/success/page.tsx @@ -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", @@ -11,10 +12,10 @@ export const metadata: Metadata = constructMetadata({ export default async function Pricing() { const supabase = createClient(); - + const { openAppQueryParams } = await getUserAndSubscription(); return ( <> - + ); } diff --git a/components/dashboard/freetrial-card.tsx b/components/dashboard/freetrial-card.tsx index 948bea5b1..95e3cac4e 100644 --- a/components/dashboard/freetrial-card.tsx +++ b/components/dashboard/freetrial-card.tsx @@ -11,6 +11,7 @@ import { TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; +import { DEFAULT_OPEN_APP_CALLBACK } from "@/utils/constants"; type FreeTrialCardProps = { usage: UsageType; @@ -18,7 +19,7 @@ type FreeTrialCardProps = { 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({ diff --git a/components/dashboard/subscription-card.tsx b/components/dashboard/subscription-card.tsx index 04afd15d8..834f64585 100644 --- a/components/dashboard/subscription-card.tsx +++ b/components/dashboard/subscription-card.tsx @@ -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; @@ -43,7 +44,7 @@ type SubscriptionCardProps = { loading: boolean; }; -const DEFAULT_OPEN_APP_CALLBACK = "pearai://pearai.pearai/auth"; + export default function SubscriptionCard({ subscription, diff --git a/components/dashboard/success-card.tsx b/components/dashboard/success-card.tsx index cb855c115..733657480 100644 --- a/components/dashboard/success-card.tsx +++ b/components/dashboard/success-card.tsx @@ -8,8 +8,9 @@ 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"; + -const DEFAULT_OPEN_APP_CALLBACK = "pearai://pearai.pearai/auth"; export const SuccessCard = ({ openAppQueryParams, }: { diff --git a/components/pricing-success.tsx b/components/pricing-success.tsx index 27ccd58c8..3dcfb0dca 100644 --- a/components/pricing-success.tsx +++ b/components/pricing-success.tsx @@ -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"); }; diff --git a/utils/constants.ts b/utils/constants.ts index 23709bfb7..3e15a1cde 100644 --- a/utils/constants.ts +++ b/utils/constants.ts @@ -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 = "pear@trypear.ai";