ba-cafe

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

useAuth.tsx (2343B)


      1 "use client";
      2 
      3 import { useState, useEffect, useContext, createContext, ReactNode } from 'react';
      4 import { createClient, User } from '@supabase/supabase-js';
      5 import OneSignal from 'react-onesignal';
      6 
      7 export const supabase = createClient(
      8   process.env.NEXT_PUBLIC_SUPABASE_URL!,
      9   process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
     10 );
     11 
     12 type AuthContextType = {
     13   user: User | null;
     14   isLoggedIn: boolean;
     15   isLoading: boolean;
     16   loginWithDiscord: () => Promise<void>;
     17   logout: () => Promise<void>;
     18   avatarUrl: string | null;
     19   displayName: string | null;
     20 };
     21 
     22 const AuthContext = createContext<AuthContextType | null>(null);
     23 
     24 export const AuthProvider = ({ children }: { children: ReactNode }) => {
     25   const [user, setUser] = useState<User | null>(null);
     26   const [isLoading, setIsLoading] = useState(true);
     27 
     28   useEffect(() => {
     29     const checkSession = async () => {
     30       const { data: { session } } = await supabase.auth.getSession();
     31       setUser(session?.user ?? null);
     32       setIsLoading(false);
     33     };
     34     checkSession();
     35 
     36     const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => {
     37       setUser(session?.user ?? null);
     38       setIsLoading(false);
     39     });
     40 
     41     return () => subscription.unsubscribe();
     42   }, []);
     43 
     44   const loginWithDiscord = async () => {
     45     const currentOrigin = typeof window !== 'undefined' ? window.location.origin : undefined;
     46     
     47     await supabase.auth.signInWithOAuth({
     48       provider: 'discord',
     49       options: {
     50         redirectTo: currentOrigin,
     51       },
     52     });
     53   };
     54 
     55   const logout = async () => {
     56     await supabase.auth.signOut();
     57     try {
     58       await OneSignal.logout();
     59     } catch (e) {
     60       console.error("OneSignal logout error", e);
     61     }
     62     setUser(null);
     63   };
     64 
     65   const avatarUrl = user?.user_metadata?.avatar_url || null;
     66   const displayName = user?.user_metadata?.full_name || user?.user_metadata?.custom_claims?.global_name || user?.email || "先生";
     67 
     68   return (
     69     <AuthContext.Provider value={{ 
     70       user, 
     71       isLoggedIn: !!user, 
     72       isLoading, 
     73       loginWithDiscord, 
     74       logout,
     75       avatarUrl,
     76       displayName
     77     }}>
     78       {children}
     79     </AuthContext.Provider>
     80   );
     81 };
     82 
     83 export const useAuth = () => {
     84   const context = useContext(AuthContext);
     85   if (!context) throw new Error("useAuth must be used within AuthProvider");
     86   return context;
     87 };