feat: add advanced analytics and territory management system
- Add comprehensive analytics components with export functionality - Implement territory management with manager performance tracking - Add seatmap components for venue layout management - Create customer management features with modal interface - Add advanced hooks for dashboard flags and territory data - Implement seat selection and venue management utilities - Add type definitions for ticketing and seatmap systems 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
203
reactrebuild0825/src/contexts/FirebaseAuthContext.tsx
Normal file
203
reactrebuild0825/src/contexts/FirebaseAuthContext.tsx
Normal file
@@ -0,0 +1,203 @@
|
||||
// Firebase Authentication Context for Black Canyon Tickets React Rebuild
|
||||
// This is a mock authentication context for learning purposes only
|
||||
|
||||
import React, { createContext, useContext, useEffect, useState } from 'react';
|
||||
|
||||
import {
|
||||
onAuthStateChanged,
|
||||
signOut,
|
||||
signInWithEmailAndPassword,
|
||||
GoogleAuthProvider,
|
||||
signInWithPopup,
|
||||
createUserWithEmailAndPassword
|
||||
} from 'firebase/auth';
|
||||
|
||||
import { auth } from '@/lib/firebase';
|
||||
import type { User} from '@/types/auth';
|
||||
import { MOCK_USERS, ROLE_PERMISSIONS } from '@/types/auth';
|
||||
|
||||
import type {
|
||||
User as FirebaseUser} from 'firebase/auth';
|
||||
|
||||
interface FirebaseAuthContextType {
|
||||
// Authentication state
|
||||
user: User | null;
|
||||
firebaseUser: FirebaseUser | null;
|
||||
loading: boolean;
|
||||
|
||||
// Authentication methods
|
||||
signInEmail: (email: string, password: string) => Promise<void>;
|
||||
signInGoogle: () => Promise<void>;
|
||||
signUpEmail: (email: string, password: string) => Promise<void>;
|
||||
signOut: () => Promise<void>;
|
||||
|
||||
// Utility methods
|
||||
hasRole: (role: User['role'] | User['role'][]) => boolean;
|
||||
hasPermission: (permission: string) => boolean;
|
||||
}
|
||||
|
||||
const FirebaseAuthContext = createContext<FirebaseAuthContextType | null>(null);
|
||||
|
||||
// Google Auth Provider setup
|
||||
const googleProvider = new GoogleAuthProvider();
|
||||
googleProvider.setCustomParameters({
|
||||
prompt: 'select_account'
|
||||
});
|
||||
|
||||
export const FirebaseAuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
const [firebaseUser, setFirebaseUser] = useState<FirebaseUser | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
// Map Firebase user to our User type using mock data
|
||||
const mapFirebaseUserToUser = (firebaseUser: FirebaseUser): User => {
|
||||
// In a real app, this would fetch user data from Firestore
|
||||
// For learning purposes, we'll use mock data based on email
|
||||
const mockUser = MOCK_USERS[firebaseUser.email || ''] || MOCK_USERS['organizer@example.com'];
|
||||
|
||||
if (!mockUser) {
|
||||
throw new Error('Mock user not found');
|
||||
}
|
||||
|
||||
// Filter out problematic photo URLs that cause 404 errors
|
||||
const getValidAvatar = (photoURL: string | null, fallback?: string): string | undefined => {
|
||||
if (!photoURL) return fallback;
|
||||
|
||||
// Block known problematic Unsplash URLs
|
||||
if (photoURL.includes('photo-1494790108755-2616b612b786')) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
// Add other URL validations if needed
|
||||
return photoURL;
|
||||
};
|
||||
|
||||
return {
|
||||
...mockUser,
|
||||
id: firebaseUser.uid,
|
||||
email: firebaseUser.email || mockUser.email,
|
||||
name: firebaseUser.displayName || mockUser.name,
|
||||
avatar: getValidAvatar(firebaseUser.photoURL, mockUser.avatar),
|
||||
metadata: {
|
||||
...mockUser.metadata,
|
||||
lastLogin: new Date().toISOString(),
|
||||
emailVerified: firebaseUser.emailVerified,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// Listen for authentication state changes
|
||||
useEffect(() => {
|
||||
const unsubscribe = onAuthStateChanged(auth, (firebaseUser) => {
|
||||
setFirebaseUser(firebaseUser);
|
||||
|
||||
if (firebaseUser) {
|
||||
const mappedUser = mapFirebaseUserToUser(firebaseUser);
|
||||
setUser(mappedUser);
|
||||
} else {
|
||||
setUser(null);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
});
|
||||
|
||||
return () => unsubscribe();
|
||||
}, []);
|
||||
|
||||
// Sign in with email and password
|
||||
const signInEmail = async (email: string, password: string): Promise<void> => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await signInWithEmailAndPassword(auth, email, password);
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Sign in with Google
|
||||
const signInGoogle = async (): Promise<void> => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await signInWithPopup(auth, googleProvider);
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Sign up with email and password
|
||||
const signUpEmail = async (email: string, password: string): Promise<void> => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await createUserWithEmailAndPassword(auth, email, password);
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Sign out
|
||||
const handleSignOut = async (): Promise<void> => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await signOut(auth);
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Check if user has specific role(s)
|
||||
const hasRole = (role: User['role'] | User['role'][]): boolean => {
|
||||
if (!user) {return false;}
|
||||
if (Array.isArray(role)) {
|
||||
return role.includes(user.role);
|
||||
}
|
||||
return user.role === role;
|
||||
};
|
||||
|
||||
// Check if user has specific permission
|
||||
const hasPermission = (permission: string): boolean => {
|
||||
if (!user) {return false;}
|
||||
const userPermissions = ROLE_PERMISSIONS[user.role] || [];
|
||||
|
||||
// Check for wildcard permissions (admin:* grants all admin permissions)
|
||||
return userPermissions.some(userPerm => {
|
||||
if (userPerm.endsWith(':*')) {
|
||||
const prefix = userPerm.slice(0, -1); // Remove the '*'
|
||||
return permission.startsWith(prefix);
|
||||
}
|
||||
return userPerm === permission;
|
||||
});
|
||||
};
|
||||
|
||||
const value: FirebaseAuthContextType = {
|
||||
user,
|
||||
firebaseUser,
|
||||
loading,
|
||||
signInEmail,
|
||||
signInGoogle,
|
||||
signUpEmail,
|
||||
signOut: handleSignOut,
|
||||
hasRole,
|
||||
hasPermission,
|
||||
};
|
||||
|
||||
return (
|
||||
<FirebaseAuthContext.Provider value={value}>
|
||||
{children}
|
||||
</FirebaseAuthContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
// Custom hook to use Firebase Auth context
|
||||
export const useFirebaseAuth = (): FirebaseAuthContextType => {
|
||||
const context = useContext(FirebaseAuthContext);
|
||||
if (!context) {
|
||||
throw new Error('useFirebaseAuth must be used within a FirebaseAuthProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
export default FirebaseAuthContext;
|
||||
Reference in New Issue
Block a user