Skip to content

Commit 9977144

Browse files
committed
fix(frontend): onboarding fixes... (2)
1 parent 81d61a0 commit 9977144

File tree

10 files changed

+216
-217
lines changed

10 files changed

+216
-217
lines changed

autogpt_platform/frontend/src/app/(no-navbar)/onboarding/6-congrats/page.tsx

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
"use client";
2-
import { useEffect, useRef, useState } from "react";
2+
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
33
import { cn } from "@/lib/utils";
44
import { useRouter } from "next/navigation";
5-
import { useOnboarding } from "../../../../providers/onboarding/onboarding-provider";
65
import * as party from "party-js";
6+
import { useEffect, useRef, useState } from "react";
7+
import { useOnboarding } from "../../../../providers/onboarding/onboarding-provider";
78

89
export default function Page() {
910
const { completeStep } = useOnboarding(7, "AGENT_INPUT");
1011
const router = useRouter();
12+
const api = useBackendAPI();
1113
const [showText, setShowText] = useState(false);
1214
const [showSubtext, setShowSubtext] = useState(false);
1315
const divRef = useRef(null);
@@ -31,18 +33,36 @@ export default function Page() {
3133
setShowSubtext(true);
3234
}, 500);
3335

34-
const timer2 = setTimeout(() => {
35-
// Mark CONGRATS as complete - /onboarding page will handle adding agent to library and redirect
36+
const timer2 = setTimeout(async () => {
3637
completeStep("CONGRATS");
37-
router.push("/onboarding");
38+
39+
try {
40+
const onboarding = await api.getUserOnboarding();
41+
if (onboarding?.selectedStoreListingVersionId) {
42+
try {
43+
const libraryAgent = await api.addMarketplaceAgentToLibrary(
44+
onboarding.selectedStoreListingVersionId,
45+
);
46+
router.replace(`/library/agents/${libraryAgent.id}`);
47+
} catch (error) {
48+
console.error("Failed to add agent to library:", error);
49+
router.replace("/library");
50+
}
51+
} else {
52+
router.replace("/library");
53+
}
54+
} catch (error) {
55+
console.error("Failed to get onboarding data:", error);
56+
router.replace("/library");
57+
}
3858
}, 3000);
3959

4060
return () => {
4161
clearTimeout(timer0);
4262
clearTimeout(timer1);
4363
clearTimeout(timer2);
4464
};
45-
}, [completeStep, router]);
65+
}, [completeStep, router, api]);
4666

4767
return (
4868
<div className="flex h-screen w-screen flex-col items-center justify-center bg-violet-100">

autogpt_platform/frontend/src/app/(no-navbar)/onboarding/page.tsx

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,6 @@ export default function OnboardingPage() {
2626
return;
2727
}
2828

29-
// Handle CONGRATS - add agent to library and redirect
30-
if (onboarding.completedSteps.includes("CONGRATS")) {
31-
if (onboarding.selectedStoreListingVersionId) {
32-
try {
33-
const libraryAgent = await api.addMarketplaceAgentToLibrary(
34-
onboarding.selectedStoreListingVersionId,
35-
);
36-
router.replace(`/library/agents/${libraryAgent.id}`);
37-
} catch (error) {
38-
console.error("Failed to add agent to library:", error);
39-
router.replace("/library");
40-
}
41-
} else {
42-
router.replace("/library");
43-
}
44-
return;
45-
}
46-
4729
// Redirect to appropriate step based on completed steps
4830
if (onboarding.completedSteps.includes("AGENT_INPUT")) {
4931
router.push("/onboarding/5-run");
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"use server";
2+
3+
import BackendAPI from "@/lib/autogpt-server-api";
4+
import { getServerSupabase } from "@/lib/supabase/server/getServerSupabase";
5+
import { verifyTurnstileToken } from "@/lib/turnstile";
6+
import { environment } from "@/services/environment";
7+
import { loginFormSchema } from "@/types/auth";
8+
import * as Sentry from "@sentry/nextjs";
9+
import { shouldShowOnboarding } from "../../api/helpers";
10+
11+
export async function login(
12+
email: string,
13+
password: string,
14+
turnstileToken?: string,
15+
) {
16+
try {
17+
const parsed = loginFormSchema.safeParse({ email, password });
18+
19+
if (!parsed.success) {
20+
return {
21+
success: false,
22+
error: "Invalid email or password",
23+
};
24+
}
25+
26+
const captchaOk = await verifyTurnstileToken(turnstileToken ?? "", "login");
27+
if (!captchaOk && !environment.isVercelPreview()) {
28+
return {
29+
success: false,
30+
error: "CAPTCHA verification failed. Please try again.",
31+
};
32+
}
33+
34+
const supabase = await getServerSupabase();
35+
if (!supabase) {
36+
return {
37+
success: false,
38+
error: "Authentication service unavailable",
39+
};
40+
}
41+
42+
const { error } = await supabase.auth.signInWithPassword(parsed.data);
43+
if (error) {
44+
return {
45+
success: false,
46+
error: error.message,
47+
};
48+
}
49+
50+
const api = new BackendAPI();
51+
await api.createUser();
52+
53+
const onboarding = await shouldShowOnboarding();
54+
55+
return {
56+
success: true,
57+
onboarding,
58+
next: onboarding ? "/onboarding" : "/",
59+
};
60+
} catch (err) {
61+
Sentry.captureException(err);
62+
return {
63+
success: false,
64+
error: "Failed to login. Please try again.",
65+
};
66+
}
67+
}

autogpt_platform/frontend/src/app/(platform)/login/page.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export default function LoginPage() {
2020
turnstile,
2121
captchaKey,
2222
isLoading,
23+
isGoogleLoading,
2324
isCloudEnv,
2425
isUserLoading,
2526
showNotAllowedModal,
@@ -100,6 +101,7 @@ export default function LoginPage() {
100101
<Button
101102
variant="primary"
102103
loading={isLoading}
104+
disabled={isGoogleLoading}
103105
type="submit"
104106
className="mt-6 w-full"
105107
>
@@ -109,7 +111,7 @@ export default function LoginPage() {
109111
{isCloudEnv ? (
110112
<GoogleOAuthButton
111113
onClick={() => handleProviderLogin("google")}
112-
isLoading={isLoading}
114+
isLoading={isGoogleLoading}
113115
disabled={isLoading}
114116
/>
115117
) : null}

autogpt_platform/frontend/src/app/(platform)/login/useLoginPage.ts

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { useRouter, useSearchParams } from "next/navigation";
88
import { useCallback, useState } from "react";
99
import { useForm } from "react-hook-form";
1010
import z from "zod";
11+
import { login as loginAction } from "./actions";
1112
import { computeReturnURL } from "./helpers";
1213

1314
export function useLoginPage() {
@@ -19,6 +20,7 @@ export function useLoginPage() {
1920
const returnUrl = searchParams.get("returnUrl");
2021
const { toast } = useToast();
2122
const [isLoading, setIsLoading] = useState(false);
23+
const [isGoogleLoading, setIsGoogleLoading] = useState(false);
2224
const [showNotAllowedModal, setShowNotAllowedModal] = useState(false);
2325
const isCloudEnv = environment.isCloud();
2426
const isVercelPreview = process.env.NEXT_PUBLIC_VERCEL_ENV === "preview";
@@ -43,15 +45,15 @@ export function useLoginPage() {
4345
}, [turnstile]);
4446

4547
async function handleProviderLogin(provider: LoginProvider) {
46-
setIsLoading(true);
48+
setIsGoogleLoading(true);
4749

4850
if (isCloudEnv && !turnstile.verified && !isVercelPreview) {
4951
toast({
5052
title: "Please complete the CAPTCHA challenge.",
5153
variant: "info",
5254
});
5355

54-
setIsLoading(false);
56+
setIsGoogleLoading(false);
5557
resetCaptcha();
5658
return;
5759
}
@@ -72,7 +74,7 @@ export function useLoginPage() {
7274
if (url) window.location.href = url as string;
7375
} catch (error) {
7476
resetCaptcha();
75-
setIsLoading(false);
77+
setIsGoogleLoading(false);
7678
setFeedback(
7779
error instanceof Error ? error.message : "Failed to start OAuth flow",
7880
);
@@ -105,20 +107,14 @@ export function useLoginPage() {
105107
}
106108

107109
try {
108-
const response = await fetch("/api/auth/login", {
109-
method: "POST",
110-
headers: { "Content-Type": "application/json" },
111-
body: JSON.stringify({
112-
email: data.email,
113-
password: data.password,
114-
turnstileToken: turnstile.token,
115-
}),
116-
});
117-
118-
const result = await response.json();
110+
const result = await loginAction(
111+
data.email,
112+
data.password,
113+
turnstile.token ?? undefined,
114+
);
119115

120-
if (!response.ok) {
121-
throw new Error(result?.error || "Login failed");
116+
if (!result.success) {
117+
throw new Error(result.error || "Login failed");
122118
}
123119

124120
// Prioritize returnUrl from query params over backend's onboarding logic
@@ -145,6 +141,7 @@ export function useLoginPage() {
145141
captchaKey,
146142
user,
147143
isLoading,
144+
isGoogleLoading,
148145
isCloudEnv,
149146
isUserLoading,
150147
showNotAllowedModal,
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
"use server";
2+
3+
import { getServerSupabase } from "@/lib/supabase/server/getServerSupabase";
4+
import { verifyTurnstileToken } from "@/lib/turnstile";
5+
import { environment } from "@/services/environment";
6+
import { signupFormSchema } from "@/types/auth";
7+
import * as Sentry from "@sentry/nextjs";
8+
import { isWaitlistError, logWaitlistError } from "../../api/auth/utils";
9+
import { shouldShowOnboarding } from "../../api/helpers";
10+
11+
export async function signup(
12+
email: string,
13+
password: string,
14+
confirmPassword: string,
15+
agreeToTerms: boolean,
16+
turnstileToken?: string,
17+
) {
18+
try {
19+
const parsed = signupFormSchema.safeParse({
20+
email,
21+
password,
22+
confirmPassword,
23+
agreeToTerms,
24+
});
25+
26+
if (!parsed.success) {
27+
return {
28+
success: false,
29+
error: "Invalid signup payload",
30+
};
31+
}
32+
33+
const captchaOk = await verifyTurnstileToken(
34+
turnstileToken ?? "",
35+
"signup",
36+
);
37+
38+
if (!captchaOk && !environment.isVercelPreview()) {
39+
return {
40+
success: false,
41+
error: "CAPTCHA verification failed. Please try again.",
42+
};
43+
}
44+
45+
const supabase = await getServerSupabase();
46+
if (!supabase) {
47+
return {
48+
success: false,
49+
error: "Authentication service unavailable",
50+
};
51+
}
52+
53+
const { data, error } = await supabase.auth.signUp(parsed.data);
54+
55+
if (error) {
56+
if (isWaitlistError(error?.code, error?.message)) {
57+
logWaitlistError("Signup", error.message);
58+
return { success: false, error: "not_allowed" };
59+
}
60+
61+
if ((error as any).code === "user_already_exists") {
62+
return { success: false, error: "user_already_exists" };
63+
}
64+
65+
return {
66+
success: false,
67+
error: error.message,
68+
};
69+
}
70+
71+
if (data.session) {
72+
await supabase.auth.setSession(data.session);
73+
}
74+
75+
const isOnboardingEnabled = await shouldShowOnboarding();
76+
const next = isOnboardingEnabled ? "/onboarding" : "/";
77+
78+
return { success: true, next };
79+
} catch (err) {
80+
Sentry.captureException(err);
81+
return {
82+
success: false,
83+
error: "Failed to sign up. Please try again.",
84+
};
85+
}
86+
}

autogpt_platform/frontend/src/app/(platform)/signup/page.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export default function SignupPage() {
3030
captchaKey,
3131
isLoggedIn,
3232
isLoading,
33+
isGoogleLoading,
3334
isCloudEnv,
3435
isUserLoading,
3536
showNotAllowedModal,
@@ -177,6 +178,7 @@ export default function SignupPage() {
177178
<Button
178179
variant="primary"
179180
loading={isLoading}
181+
disabled={isGoogleLoading}
180182
type="submit"
181183
className="mt-6 w-full"
182184
>
@@ -187,7 +189,7 @@ export default function SignupPage() {
187189
{isCloudEnv ? (
188190
<GoogleOAuthButton
189191
onClick={() => handleProviderSignup("google")}
190-
isLoading={isLoading}
192+
isLoading={isGoogleLoading}
191193
disabled={isLoading}
192194
/>
193195
) : null}

0 commit comments

Comments
 (0)