diff --git a/frontend/src/pages/AccountCenterPage.jsx b/frontend/src/pages/AccountCenterPage.jsx index b206356..2fdf27a 100644 --- a/frontend/src/pages/AccountCenterPage.jsx +++ b/frontend/src/pages/AccountCenterPage.jsx @@ -2,8 +2,7 @@ import { useAuth } from "../context/AuthContext"; import { useState, useEffect } from "react"; import { Link, useSearchParams } from "react-router-dom"; import { getProfile, deleteAccount } from "../services/userService"; - -const API_BASE = import.meta.env.VITE_API_BASE_URL; +import api from "../services/api"; // ── Helpers ────────────────────────────────────────────────────────────────── @@ -21,9 +20,6 @@ const RANK_COLORS = { unrated: "text-gray-400", }; -const rankColor = (rank = "") => - RANK_COLORS[(rank || "").toLowerCase()] || "text-black"; - // ── Sub-components ──────────────────────────────────────────────────────────── function SectionLabel({ text }) { @@ -103,11 +99,31 @@ function GitHubCard({ user }) { const ghUsername = ghIdentity?.username || user?.handles?.github; const ghAvatar = user?.profile?.avatar; const [msg, setMsg] = useState(""); + const [connecting, setConnecting] = useState(false); + + const handleConnect = async () => { + setConnecting(true); + setMsg(""); - const handleConnect = () => { - // Encode current path so backend redirects back here after connect - const redirectPath = encodeURIComponent("/account-center"); - window.location.href = `${API_BASE}/auth/github/connect?redirectPath=${redirectPath}`; + try { + const response = await api.post("/auth/github/connect/start", null, { + params: { redirectPath: "/account-center" }, + }); + const authUrl = response.data?.data?.authUrl; + + if (!authUrl) { + throw new Error("GitHub authorization URL was not returned."); + } + + window.location.href = authUrl; + } catch (error) { + const message = + error?.response?.data?.message || + error?.message || + "Unable to start GitHub connection."; + setMsg(message); + setConnecting(false); + } }; const handleDisconnect = () => { @@ -196,12 +212,13 @@ function GitHubCard({ user }) { )} @@ -273,7 +290,7 @@ function DangerZone({ onLogout }) { try { await deleteAccount(); onLogout(); // Logs the user out and redirects to login - } catch (err) { + } catch { alert("Failed to delete account. Please try again later."); setLoading(false); setConfirm(false); @@ -337,15 +354,19 @@ export default function AccountCenterPage() { const username = searchParams.get("githubUsername"); if (status === "connected") { - setBanner(`GitHub account @${username || "connected"} linked successfully!`); + const bannerTimer = window.setTimeout(() => { + setBanner(`GitHub account @${username || "connected"} linked successfully!`); + }, 0); // Refresh user profile so the card shows the new GitHub identity getProfile() .then((res) => setUser(res.data)) .catch(() => {}); // Clean URL window.history.replaceState({}, "", "/account-center"); + + return () => window.clearTimeout(bannerTimer); } - }, [searchParams]); + }, [searchParams, setUser]); return (
diff --git a/server/modules/auth/controller.js b/server/modules/auth/controller.js index 9143673..eda4f6a 100644 --- a/server/modules/auth/controller.js +++ b/server/modules/auth/controller.js @@ -92,6 +92,23 @@ class AuthController { } } + static async createGithubConnectUrl(req, res, next) { + try { + const { redirectPath } = req.validatedQuery || req.query; + const authUrl = AuthService.getGithubAuthorizationUrl({ + mode: "connect", + userId: req.user?._id, + redirectPath + }); + + return res.status(200).json( + ApiResponse.success("GitHub connect URL generated", { authUrl }) + ); + } catch (error) { + next(error instanceof ApiError ? error : new ApiError(500, error.message)); + } + } + static async githubCallback(req, res, next) { try { const { code, state } = req.validatedQuery || req.query; diff --git a/server/modules/auth/routes.js b/server/modules/auth/routes.js index 2920816..98625f0 100644 --- a/server/modules/auth/routes.js +++ b/server/modules/auth/routes.js @@ -41,6 +41,13 @@ router.get( validateQuery(githubStartSchema), AuthController.startGithubConnect ); +router.post( + "/github/connect/start", + githubConnectRateLimit, + authMiddleware, + validateQuery(githubStartSchema), + AuthController.createGithubConnectUrl +); router.get("/github/callback", validateQuery(githubCallbackSchema), AuthController.githubCallback); export default router;