From 104341ddc4add57f83c58cb3fabb23b6fbfdd3e4 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 2 Nov 2025 00:00:35 +0900 Subject: wip --- frontend/src/contexts/AuthContext.tsx | 95 +++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 frontend/src/contexts/AuthContext.tsx (limited to 'frontend/src/contexts/AuthContext.tsx') diff --git a/frontend/src/contexts/AuthContext.tsx b/frontend/src/contexts/AuthContext.tsx new file mode 100644 index 0000000..4f97355 --- /dev/null +++ b/frontend/src/contexts/AuthContext.tsx @@ -0,0 +1,95 @@ +import { + createContext, + type ReactNode, + useContext, + useEffect, + useState, +} from "react"; +import { useMutation, useQuery } from "urql"; +import { + GetMeDocument, + LoginDocument, + LogoutDocument, +} from "../graphql/generated/graphql"; + +interface User { + id: string; + username: string; +} + +interface AuthContextType { + user: User | null; + isLoading: boolean; + login: (username: string, password: string) => Promise; + logout: () => Promise; +} + +const AuthContext = createContext(undefined); + +export function AuthProvider({ children }: { children: ReactNode }) { + const [user, setUser] = useState(null); + const [isLoading, setIsLoading] = useState(true); + + const [, executeLogin] = useMutation(LoginDocument); + const [, executeLogout] = useMutation(LogoutDocument); + const [meResult, reexecuteMe] = useQuery({ query: GetMeDocument }); + + // Update user from Me query + useEffect(() => { + if (meResult.data?.me) { + setUser(meResult.data.me); + } else { + setUser(null); + } + if (!meResult.fetching) { + setIsLoading(false); + } + }, [meResult.data, meResult.fetching]); + + const login = async ( + username: string, + password: string, + ): Promise => { + try { + const result = await executeLogin({ username, password }); + + if (result.data?.login?.user) { + setUser(result.data.login.user); + // Refetch Me query to ensure session is established + reexecuteMe({ requestPolicy: "network-only" }); + return true; + } + + return false; + } catch (error) { + console.error("Login failed:", error); + return false; + } + }; + + const logout = async () => { + try { + await executeLogout({}); + } catch (error) { + console.error("Logout failed:", error); + } finally { + setUser(null); + // Refetch Me query to ensure session is cleared + reexecuteMe({ requestPolicy: "network-only" }); + } + }; + + return ( + + {children} + + ); +} + +export function useAuth() { + const context = useContext(AuthContext); + if (context === undefined) { + throw new Error("useAuth must be used within an AuthProvider"); + } + return context; +} -- cgit v1.2.3-70-g09d2