"use client"; import React, { createContext, useContext, useState, useEffect, useCallback, } from "react"; import { useRouter } from "next/navigation"; import { User, getAuthToken, setAuthToken, getStoredUser, setStoredUser, clearAuth, isTokenExpired, } from "@/lib/auth"; interface AuthContextType { user: User | null; isLoading: boolean; isAuthenticated: boolean; login: (token: string) => Promise; logout: () => void; checkAuth: () => void; } const AuthContext = createContext(undefined); export function AuthProvider({ children }: { children: React.ReactNode }) { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); const router = useRouter(); const checkAuth = useCallback(() => { const token = getAuthToken(); const storedUser = getStoredUser(); if (token && storedUser && !isTokenExpired(token)) { setUser(storedUser); } else { clearAuth(); setUser(null); } setIsLoading(false); }, []); useEffect(() => { checkAuth(); }, [checkAuth]); const login = useCallback( async (token: string) => { try { // Decode JWT to get user info const base64Url = token.split(".")[1]; const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/"); const jsonPayload = decodeURIComponent( atob(base64) .split("") .map((c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)) .join(""), ); const claims = JSON.parse(jsonPayload); // Extract user info from JWT claims const userInfo: User = { username: claims.github_username || claims.sub, email: claims.email, name: claims.name, avatar_url: claims.avatar_url, organizations: claims.github_orgs, }; setAuthToken(token); setStoredUser(userInfo); setUser(userInfo); router.push("/"); // Redirect to home after login } catch (error) { // Clear token if we can't decode it clearAuth(); throw new Error("Failed to decode authentication token"); } }, [router], ); const logout = useCallback(() => { clearAuth(); setUser(null); router.push("/login"); }, [router]); const value = { user, isLoading, isAuthenticated: !!user, login, logout, checkAuth, }; return {children}; } export function useAuth() { const context = useContext(AuthContext); if (context === undefined) { throw new Error("useAuth must be used within an AuthProvider"); } return context; }