Skip to content

Commit d91f4d5

Browse files
committed
Fix an error: Manage Subscriptions not showing up and working
1 parent ec1396d commit d91f4d5

File tree

9 files changed

+137
-182
lines changed

9 files changed

+137
-182
lines changed

app/api/github/get-installed-repos/route.ts

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export async function POST(request: Request) {
7171
return {
7272
ownerId: data.repositories[0].owner.id,
7373
ownerName: data.repositories[0].owner.login,
74+
ownerType: data.repositories[0].owner.type,
7475
repositories: data.repositories.map((repo: any) => ({
7576
repoId: repo.id,
7677
repoName: repo.name,

app/redirect-to-install/page.tsx

-49
This file was deleted.

app/sitemap.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
1616
.replace(/\/+/g, "/");
1717

1818
const isLessImportant =
19-
route === RELATIVE_URLS.PRIVACY_POLICY ||
20-
route === RELATIVE_URLS.TERMS_OF_SERVICE ||
21-
route === RELATIVE_URLS.REDIRECT_TO_INSTALL;
19+
route === RELATIVE_URLS.PRIVACY_POLICY || route === RELATIVE_URLS.TERMS_OF_SERVICE;
2220
const priority = route === "" ? 1.0 : isLessImportant ? 0.3 : 0.8;
2321
const changeFrequency = isLessImportant ? ("yearly" as const) : ("weekly" as const);
2422

components/Context/Account.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export function AccountContextWrapper({ children }: { children: React.ReactNode
111111
};
112112

113113
const { data: installationsSubscribed = null } = useSWR(
114-
userId ? `fetchSubscriptionStatus-${userId}` : null,
114+
userId && installations ? [`fetchSubscriptionStatus-${userId}`, installations] : null,
115115
fetchSubscriptionStatus,
116116
swrOptions
117117
);

components/HomePage/Pricing.tsx

+24-56
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ import Link from "next/link";
66
import { useRouter, useSearchParams } from "next/navigation";
77
import { signIn } from "next-auth/react";
88
import { usePostHog } from "posthog-js/react";
9-
import { useState, useCallback, useEffect } from "react";
9+
import { useState } from "react";
1010

1111
// Local imports
1212
import { useAccountContext } from "@/components/Context/Account";
1313
import SpinnerIcon from "@/components/SpinnerIcon";
1414
import CheckMark from "@/components/Symbol/CheckMark";
15-
import { ABSOLUTE_URLS, OPENAI_MODEL_O3_MINI, RELATIVE_URLS } from "@/config";
15+
import { ABSOLUTE_URLS, OPENAI_MODEL_O3_MINI } from "@/config";
1616
import { ANTHROPIC_MODEL_CLAUDE_37 } from "@/config/anthropic";
1717
import { DEEPSEEK_MODEL_R1 } from "@/config/deepseek";
18+
import { createPortalOrCheckoutURL } from "@/lib/stripe/createPortalOrCheckoutUrl";
1819

1920
const pricingButtonStyles = `my-4 sm:my-2 md:my-8 rounded-lg transition-colors duration-200 text-md sm:text-lg xl:text-xl py-2 sm:py-1 md:py-3 w-full shadow-lg hover:shadow-lg font-semibold text-center mx-auto`;
2021

@@ -27,9 +28,12 @@ export default function Pricing() {
2728
jwtToken,
2829
email,
2930
selectedIndex,
30-
installations,
3131
installationsSubscribed,
3232
userName,
33+
currentOwnerId,
34+
currentOwnerType,
35+
currentOwnerName,
36+
currentStripeCustomerId,
3337
} = useAccountContext();
3438

3539
const router = useRouter();
@@ -38,54 +42,33 @@ export default function Pricing() {
3842
const searchParams = useSearchParams();
3943
const [billingPeriod, setBillingPeriod] = useState<string>("Yearly");
4044

41-
const createPortalOrCheckoutURL = useCallback(async () => {
42-
let currentIndex = 0;
43-
if (selectedIndex) currentIndex = selectedIndex;
44-
45-
// If user has an installation, create portal or checkout session
46-
if (installations && installations.length > 0) {
47-
const response = await fetch("/api/stripe/create-portal-or-checkout-url", {
48-
method: "POST",
49-
body: JSON.stringify({
50-
userId: userId,
51-
jwtToken: jwtToken,
52-
customerId: installations[currentIndex].stripe_customer_id,
53-
email: email,
54-
ownerType: installations[currentIndex].owner_type,
55-
ownerId: Number(installations[currentIndex].owner_id),
56-
ownerName: installations[currentIndex].owner_name,
57-
userName,
58-
billingPeriod: billingPeriod,
59-
}),
60-
});
61-
62-
const res = await response.json();
63-
router.push(res);
64-
} else {
65-
// If not, redirect to installation page
66-
router.push(RELATIVE_URLS.REDIRECT_TO_INSTALL);
67-
}
68-
}, [email, jwtToken, router, selectedIndex, userId, installations, billingPeriod, userName]);
69-
7045
// Flow: https://docs.google.com/spreadsheets/d/1AK7VPo_68mL2s3lvsKLy3Rox-QvsT5cngiWf2k0r3Cc/edit#gid=0
7146
async function handleSubscribe() {
7247
setIsSubscribeLoading(true);
7348
posthog.capture("$click", { $event_type: "subscribe", $current_url: window.location.href });
7449

7550
try {
7651
if (!userId || !jwtToken) {
77-
await signIn("github", { callbackUrl: `/?subscribe` });
78-
return;
79-
}
80-
81-
// Signed in but no installation
82-
if (!installations || installations.length === 0) {
83-
router.push(RELATIVE_URLS.REDIRECT_TO_INSTALL);
52+
await signIn("github", { callbackUrl: "/" });
8453
return;
8554
}
8655

87-
// Has at least one installation
88-
await createPortalOrCheckoutURL();
56+
if (!currentOwnerId || !currentOwnerType || !currentOwnerName) return;
57+
if (!currentStripeCustomerId) return;
58+
if (!email) return;
59+
60+
await createPortalOrCheckoutURL({
61+
userId,
62+
jwtToken,
63+
customerId: currentStripeCustomerId,
64+
email,
65+
ownerId: currentOwnerId,
66+
ownerType: currentOwnerType,
67+
ownerName: currentOwnerName,
68+
userName,
69+
billingPeriod,
70+
router,
71+
});
8972
} catch (error) {
9073
Sentry.captureException(error);
9174
console.error("Error subscribing", error);
@@ -94,21 +77,6 @@ export default function Pricing() {
9477
}
9578
}
9679

97-
// If "subscribe" in query parameter create checkout session or portal
98-
useEffect(() => {
99-
if (searchParams.has("subscribe") && installations) {
100-
createPortalOrCheckoutURL();
101-
}
102-
}, [
103-
searchParams,
104-
installations,
105-
selectedIndex,
106-
userId,
107-
jwtToken,
108-
router,
109-
createPortalOrCheckoutURL,
110-
]);
111-
11280
return (
11381
<div
11482
id="pricing"

components/Navbar/MobileMenu.tsx

+23-38
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ import { useState } from "react";
99

1010
// Local Imports
1111
import { useAccountContext } from "@/components/Context/Account";
12-
import { ABSOLUTE_URLS } from "@/config/index";
1312
import { INTERNAL_LINKS } from "@/config/internal-links";
14-
import { Installation } from "@/types/github";
13+
import { createPortalOrCheckoutURL } from "@/lib/stripe/createPortalOrCheckoutUrl";
1514
import OwnerSelector from "../HomePage/OwnerSelector";
1615

1716
interface MobileDrawerProps {
@@ -20,10 +19,6 @@ interface MobileDrawerProps {
2019
posthog: any;
2120
}
2221

23-
const buttonStyles = `bg-pink-600 text-white rounded-lg transition-colors
24-
duration-200 sm:text-md xl:text-lg py-2 px-3 shadow-lg hover:shadow-lg
25-
cursor-pointer hover:bg-pink-700 font-semibold text-center md:w-auto `;
26-
2722
export default function MobileDrawer({ setIsNavOpen, isNavOpen, posthog }: MobileDrawerProps) {
2823
const { status } = useSession();
2924
const [isOwnerSelectorOpen, setIsOwnerSelectorOpen] = useState(false);
@@ -32,37 +27,15 @@ export default function MobileDrawer({ setIsNavOpen, isNavOpen, posthog }: Mobil
3227
jwtToken,
3328
email,
3429
installations,
35-
selectedIndex,
36-
installationsSubscribed,
3730
userName,
31+
currentOwnerId,
32+
currentOwnerType,
33+
currentOwnerName,
34+
currentStripeCustomerId,
3835
} = useAccountContext();
3936

4037
const router = useRouter();
4138

42-
const createPortalOrCheckoutURL = async (
43-
userId: number | null,
44-
jwtToken: string | null,
45-
installations: Installation[],
46-
currentIndex: number
47-
) => {
48-
const response = await fetch("/api/stripe/create-portal-or-checkout-url", {
49-
method: "POST",
50-
body: JSON.stringify({
51-
userId: userId,
52-
jwtToken: jwtToken,
53-
customerId: installations[currentIndex].stripe_customer_id,
54-
email: email,
55-
ownerType: installations[currentIndex].owner_type,
56-
ownerId: Number(installations[currentIndex].owner_id),
57-
ownerName: installations[currentIndex].owner_name,
58-
userName: userName || "Unknown User",
59-
}),
60-
});
61-
62-
const res = await response.json();
63-
router.push(res);
64-
};
65-
6639
return (
6740
<>
6841
{isNavOpen && (
@@ -100,16 +73,28 @@ export default function MobileDrawer({ setIsNavOpen, isNavOpen, posthog }: Mobil
10073
)}
10174
{status === "authenticated" && (
10275
<>
103-
{selectedIndex != null &&
104-
installations &&
105-
installations.length > 0 &&
106-
installationsSubscribed &&
107-
installationsSubscribed[selectedIndex] === true && (
76+
{userId &&
77+
jwtToken &&
78+
email &&
79+
currentOwnerId &&
80+
currentOwnerType &&
81+
currentOwnerName &&
82+
currentStripeCustomerId && (
10883
<li>
10984
<span
11085
className={`link `}
11186
onClick={() =>
112-
createPortalOrCheckoutURL(userId, jwtToken, installations, selectedIndex)
87+
createPortalOrCheckoutURL({
88+
userId,
89+
jwtToken,
90+
customerId: currentStripeCustomerId,
91+
email,
92+
ownerId: currentOwnerId,
93+
ownerType: currentOwnerType,
94+
ownerName: currentOwnerName,
95+
userName,
96+
router,
97+
})
11398
}
11499
>
115100
Manage Subscriptions

0 commit comments

Comments
 (0)