import { createContext, ReactNode, useContext } from "react"; import { useQuery, useMutation } from "@tanstack/react-query"; import { getQueryFn, queryClient } from "@/lib/queryClient"; import { useToast } from "@/hooks/use-toast"; interface User { id: number; username: string; fullName?: string | null; location?: string | null; interests?: string[] | null; profession?: string | null; pets?: string | null; systemContext?: string | null; } type AuthContextType = { user: User | null; isLoading: boolean; error: Error | null; login: () => Promise; logout: () => Promise; loginMutation: any; registerMutation: any; }; export const AuthContext = createContext(null); function loginWithReplit() { const h = 500; const w = 350; const left = screen.width / 2 - w / 2; const top = screen.height / 2 - h / 2; return new Promise((resolve) => { const authWindow = window.open( `https://replit.com/auth_with_repl_site?domain=${location.host}`, "_blank", `modal=yes,toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=no,copyhistory=no,width=${w},height=${h},top=${top},left=${left}` ); window.addEventListener("message", function authComplete(e) { if (e.data !== "auth_complete") { return; } window.removeEventListener("message", authComplete); authWindow?.close(); resolve(); }); }); } export function AuthProvider({ children }: { children: ReactNode }) { const { toast } = useToast(); const { data: user, error, isLoading, } = useQuery({ queryKey: ["/api/user"], queryFn: getQueryFn({ on401: "returnNull" }), retry: false, }); const loginMutation = useMutation({ mutationFn: async () => { await loginWithReplit(); const res = await fetch("/api/auth/replit"); if (!res.ok) { throw new Error("Authentication failed"); } return res.json(); }, onSuccess: (userData) => { queryClient.setQueryData(["/api/user"], userData); toast({ title: "Welcome!", description: "You've successfully logged in.", }); }, onError: (error: Error) => { toast({ title: "Login failed", description: error.message, variant: "destructive", }); }, }); const registerMutation = useMutation({ mutationFn: async () => { await loginWithReplit(); const res = await fetch("/api/auth/replit"); if (!res.ok) { throw new Error("Registration failed"); } return res.json(); }, onSuccess: (userData) => { queryClient.setQueryData(["/api/user"], userData); toast({ title: "Welcome!", description: "Your account has been created successfully.", }); }, onError: (error: Error) => { toast({ title: "Registration failed", description: error.message, variant: "destructive", }); }, }); const logoutMutation = useMutation({ mutationFn: async () => { const res = await fetch("/api/logout", { method: "POST", credentials: "include", }); if (!res.ok) { throw new Error("Logout failed"); } // Force a full page reload to clear Replit auth state window.location.href = "/auth"; return null; }, onSuccess: () => { queryClient.clear(); queryClient.removeQueries(); queryClient.setQueryData(["/api/user"], null); }, onError: (error: Error) => { toast({ title: "Logout failed", description: error.message, variant: "destructive", }); }, }); return ( {children} ); } export function useAuth() { const context = useContext(AuthContext); if (!context) { throw new Error("useAuth must be used within an AuthProvider"); } return context; }