From 0c652340879d0234ab9e2ade01b84b1a2b3d23c8 Mon Sep 17 00:00:00 2001 From: "Builder.io" Date: Sun, 9 Nov 2025 08:14:40 +0000 Subject: [PATCH] Create Discord OAuth callback page cgen-968f482f11f544bfae37d5e8e042a33d --- client/pages/DiscordOAuthCallback.tsx | 170 +++++++++++++++++--------- 1 file changed, 113 insertions(+), 57 deletions(-) diff --git a/client/pages/DiscordOAuthCallback.tsx b/client/pages/DiscordOAuthCallback.tsx index 477db4ec..23eedfae 100644 --- a/client/pages/DiscordOAuthCallback.tsx +++ b/client/pages/DiscordOAuthCallback.tsx @@ -1,81 +1,137 @@ -import { useEffect, useState } from 'react'; -import { useNavigate, useSearchParams } from 'react-router-dom'; -import LoadingScreen from '@/components/LoadingScreen'; -import { useToast } from '@/hooks/use-toast'; +import { useEffect, useState } from "react"; +import { useNavigate, useSearchParams } from "react-router-dom"; +import { useAuth } from "@/contexts/AuthContext"; +import Layout from "@/components/Layout"; +import SEO from "@/components/SEO"; +import { Card, CardContent } from "@/components/ui/card"; +import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; +import { Loader, AlertTriangle, CheckCircle } from "lucide-react"; export default function DiscordOAuthCallback() { const navigate = useNavigate(); const [searchParams] = useSearchParams(); - const { toast } = useToast(); - const [isProcessing, setIsProcessing] = useState(true); + const { user, signIn } = useAuth(); + + const [status, setStatus] = useState<"loading" | "success" | "error">("loading"); + const [message, setMessage] = useState("Connecting to Discord..."); useEffect(() => { const handleCallback = async () => { + const code = searchParams.get("code"); + const state = searchParams.get("state"); + const error = searchParams.get("error"); + + if (error) { + setStatus("error"); + setMessage(`Discord authorization failed: ${error}`); + return; + } + + if (!code) { + setStatus("error"); + setMessage("No authorization code received from Discord"); + return; + } + try { - const code = searchParams.get('code'); - const state = searchParams.get('state'); - const error = searchParams.get('error'); + setMessage("Processing authentication..."); - if (error) { - throw new Error(`Discord OAuth error: ${error}`); - } - - if (!code) { - throw new Error('No authorization code received from Discord'); - } - - // Send code to backend to exchange for token - const response = await fetch('/api/discord/oauth/callback', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ code, state }), + // Call backend to handle OAuth exchange + const response = await fetch("/api/discord/oauth/callback", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + code, + state: state || "/dashboard", + }), }); - if (!response.ok) { - const errorData = await response.json(); - throw new Error(errorData.error || 'Failed to process Discord OAuth'); - } - const data = await response.json(); - // Store the Discord token if provided - if (data.access_token) { - localStorage.setItem('discord_access_token', data.access_token); + if (!response.ok) { + setStatus("error"); + setMessage(data.message || "Failed to authenticate with Discord"); + return; } - toast({ - title: 'Discord connected', - description: 'Welcome to AeThex!', - }); + // Success + setStatus("success"); + setMessage("Successfully linked! Redirecting..."); - // Redirect to dashboard or home - navigate('/dashboard', { replace: true }); + // The backend handles session setup, so just redirect + const nextPath = state && state.startsWith("/") ? state : "/dashboard"; + setTimeout(() => { + navigate(nextPath); + }, 2000); } catch (error) { - console.error('Discord OAuth callback error:', error); - toast({ - variant: 'destructive', - title: 'Authentication failed', - description: error instanceof Error ? error.message : 'Failed to connect Discord', - }); - // Redirect back to login - setTimeout(() => navigate('/login', { replace: true }), 2000); - } finally { - setIsProcessing(false); + setStatus("error"); + setMessage( + error instanceof Error + ? error.message + : "An unexpected error occurred" + ); } }; handleCallback(); - }, [searchParams, navigate, toast]); + }, [searchParams, navigate]); - if (isProcessing) { - return ( - - ); - } + return ( + + - return null; +
+ + + {status === "loading" && ( +
+ +
+

{message}

+

+ Please wait while we secure your account... +

+
+
+ )} + + {status === "success" && ( +
+ +
+

{message}

+

+ You'll be taken to your dashboard shortly... +

+
+
+ )} + + {status === "error" && ( +
+
+ +
+

+ Authentication Failed +

+

{message}

+
+
+ +
+ +
+
+ )} +
+
+
+
+ ); }