wisperlink-app / src /contexts /auth-context.tsx
looda3131's picture
طيب اريدك ان تضيف معلومات كثير في الملف الشخصي يضيفها المستخدم تساعدنا ع
cb33096
'use client';
import { useState, useEffect, createContext, useContext, type ReactNode } from 'react';
import type { User } from 'firebase/auth';
import { auth, database } from '@/firebase/client';
import {
onAuthStateChanged,
signInWithPopup,
GoogleAuthProvider,
signOut as firebaseSignOut,
updateProfile,
signInWithEmailAndPassword,
createUserWithEmailAndPassword,
deleteUser
} from 'firebase/auth';
import { ref, set, get, update, remove } from 'firebase/database';
import { useToast } from '@/hooks/use-toast';
import { Loader2 } from 'lucide-react';
export interface UserMetadata {
age: number;
location: string;
createdAt: string;
displayName: string;
email: string;
photoURL: string;
bio?: string;
gender?: string;
occupation?: string;
interests?: string;
}
interface AuthContextType {
user: User | null;
userData: UserMetadata | null;
loading: boolean;
signInWithGoogle: () => Promise<void>;
signInWithUsername: (username: string, pass: string, age: number, location: string, extra?: Partial<UserMetadata>) => Promise<void>;
signOut: () => Promise<void>;
updateUserProfile: (data: Partial<UserMetadata>) => Promise<void>;
deleteUserAccount: () => Promise<void>;
completeProfile: (data: Partial<UserMetadata>) => Promise<void>;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export const AuthProvider = ({ children }: { children: ReactNode }) => {
const [user, setUser] = useState<User | null>(null);
const [userData, setUserData] = useState<UserMetadata | null>(null);
const [loading, setLoading] = useState(true);
const { toast } = useToast();
const fetchUserData = async (uid: string) => {
const userRef = ref(database, 'users/' + uid);
const snapshot = await get(userRef);
if (snapshot.exists()) {
setUserData(snapshot.val());
} else {
setUserData(null);
}
};
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, async (currentUser) => {
setUser(currentUser);
if (currentUser) {
await fetchUserData(currentUser.uid);
} else {
setUserData(null);
}
setLoading(false);
});
return () => unsubscribe();
}, []);
const handleNewUser = async (user: User, data: Partial<UserMetadata> & { customName?: string }) => {
const userRef = ref(database, 'users/' + user.uid);
const payload: UserMetadata = {
displayName: data.customName || user.displayName || 'مستخدم جديد',
email: user.email || '',
photoURL: user.photoURL || `https://api.dicebear.com/7.x/avataaars/svg?seed=${user.uid}`,
createdAt: new Date().toISOString(),
age: data.age || 18,
location: data.location || '',
bio: data.bio || '',
gender: data.gender || '',
occupation: data.occupation || '',
interests: data.interests || ''
};
await set(userRef, payload);
if (data.customName) {
await updateProfile(user, { displayName: data.customName });
}
setUserData(payload);
};
const signInWithGoogle = async () => {
const provider = new GoogleAuthProvider();
try {
const result = await signInWithPopup(auth, provider);
const userRef = ref(database, 'users/' + result.user.uid);
const snapshot = await get(userRef);
if (!snapshot.exists()) {
toast({ title: "يرجى إكمال بياناتك للمتابعة" });
} else {
setUserData(snapshot.val());
toast({ title: `مرحباً بك ${result.user.displayName}` });
}
} catch (error: any) {
console.error("Sign-in error:", error);
toast({ title: "فشل تسجيل الدخول", variant: "destructive" });
}
};
const signInWithUsername = async (username: string, pass: string, age: number, location: string, extra?: Partial<UserMetadata>) => {
const fakeEmail = `${username.toLowerCase().trim()}@proto.chat`;
try {
setLoading(true);
const result = await signInWithEmailAndPassword(auth, fakeEmail, pass);
await fetchUserData(result.user.uid);
} catch (error: any) {
if (error.code === 'auth/user-not-found' || error.code === 'auth/invalid-credential' || error.code === 'auth/invalid-email') {
const result = await createUserWithEmailAndPassword(auth, fakeEmail, pass);
await handleNewUser(result.user, { age, location, customName: username, ...extra });
} else {
toast({ title: "خطأ في تسجيل الدخول", variant: "destructive" });
}
} finally {
setLoading(false);
}
};
const completeProfile = async (data: Partial<UserMetadata>) => {
if (!user) return;
const userRef = ref(database, 'users/' + user.uid);
const existingData = userData || {};
const newData = {
...existingData,
...data,
displayName: data.displayName || user.displayName || 'مستخدم',
email: user.email || '',
photoURL: user.photoURL || `https://api.dicebear.com/7.x/avataaars/svg?seed=${user.uid}`,
createdAt: existingData.createdAt || new Date().toISOString(),
};
await set(userRef, newData);
setUserData(newData as UserMetadata);
};
const signOut = async () => {
await firebaseSignOut(auth);
setUser(null);
setUserData(null);
};
const updateUserProfile = async (data: Partial<UserMetadata>) => {
if (!user) return;
if (data.displayName) {
await updateProfile(user, { displayName: data.displayName });
}
const userRef = ref(database, 'users/' + user.uid);
await update(userRef, data);
await fetchUserData(user.uid);
toast({ title: "تم التحديث بنجاح" });
};
const deleteUserAccount = async () => {
if (!user) return;
const userRef = ref(database, 'users/' + user.uid);
await remove(userRef);
await deleteUser(user);
toast({ title: "تم حذف الحساب" });
};
if (loading) {
return (
<div className="flex h-screen w-full flex-col items-center justify-center bg-background gap-4">
<Loader2 className="h-12 w-12 animate-spin text-primary" />
</div>
);
}
return (
<AuthContext.Provider value={{ user, userData, loading, signInWithGoogle, signInWithUsername, signOut, updateUserProfile, deleteUserAccount, completeProfile }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) throw new Error('useAuth must be used within AuthProvider');
return context;
};