mike/frontend/src/contexts/AuthContext.tsx
2026-05-08 20:45:16 +08:00

91 lines
2.1 KiB
TypeScript

"use client";
import React, {
createContext,
useContext,
useEffect,
useState,
ReactNode,
} from "react";
import { supabase } from "@/lib/supabase";
interface User {
id: string;
email: string;
}
interface AuthContextType {
user: User | null;
isAuthenticated: boolean;
authLoading: boolean;
signOut: () => Promise<void>;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const [authLoading, setAuthLoading] = useState(true);
useEffect(() => {
const checkUser = async () => {
const {
data: { session },
} = await supabase.auth.getSession();
if (session?.user) {
setUser({
id: session.user.id,
email: session.user.email || "",
});
}
setAuthLoading(false);
};
checkUser();
const {
data: { subscription },
} = supabase.auth.onAuthStateChange(async (_event, session) => {
if (session?.user) {
setUser({
id: session.user.id,
email: session.user.email || "",
});
} else {
setUser(null);
}
setAuthLoading(false);
});
return () => {
subscription.unsubscribe();
};
}, []);
const signOut = async () => {
await supabase.auth.signOut();
setUser(null);
};
return (
<AuthContext.Provider
value={{
user,
isAuthenticated: !!user,
authLoading,
signOut,
}}
>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
}