import 'react-native-gesture-handler'; import LogRocket from '@logrocket/react-native'; import React, { useEffect, useState } from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { StatusBar } from 'expo-status-bar'; import { supabase } from './src/lib/supabase'; import { COLORS } from './src/styles/theme'; import { LayoutDashboard, Ticket, User } from 'lucide-react-native'; import { View, ActivityIndicator } from 'react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'; // Notification system import { NotificationProvider } from './src/components/NotificationProvider'; // Auth Screens import OnboardingScreen from './src/screens/auth/OnboardingScreen'; import LoginScreen from './src/screens/auth/LoginScreen'; import SignupScreen from './src/screens/auth/SignupScreen'; import ForgotPasswordScreen from './src/screens/auth/ForgotPasswordScreen'; import AdminSignupScreen from './src/screens/auth/AdminSignupScreen'; import UserLobbyScreen from './src/screens/auth/UserLobbyScreen'; // User Screens import DashboardScreen from './src/screens/user/DashboardScreen'; import CreateTicketScreen from './src/screens/user/CreateTicketScreen'; import TicketDetailScreen from './src/screens/user/TicketDetailScreen'; import ProfileScreen from './src/screens/user/ProfileScreen'; import TicketsListScreen from './src/screens/user/TicketsListScreen'; import TicketTrackingScreen from './src/screens/user/TicketTrackingScreen'; import AIProcessingScreen from './src/screens/user/AIProcessingScreen'; import NotificationsScreen from './src/screens/user/NotificationsScreen'; import KnowledgeBaseScreen from './src/screens/user/KnowledgeBaseScreen'; const Stack = createNativeStackNavigator(); const Tab = createBottomTabNavigator(); const TabNavigator = () => { const insets = useSafeAreaInsets(); const tabBarHeight = 60 + insets.bottom; return ( ({ tabBarIcon: ({ color, size }) => { if (route.name === 'Dashboard') return ; if (route.name === 'Tickets') return ; if (route.name === 'Profile') return ; }, tabBarActiveTintColor: COLORS.primary, tabBarInactiveTintColor: COLORS.textMuted, tabBarLabelStyle: { fontSize: 11, fontWeight: '700' }, tabBarStyle: { height: tabBarHeight, paddingBottom: insets.bottom + 8, paddingTop: 10, backgroundColor: '#ffffff', borderTopWidth: 1, borderTopColor: '#f0f0f0', elevation: 0, shadowOpacity: 0, }, headerShown: false, })} > ); }; // Inner app that has access to SafeAreaProvider context const AppContent = () => { const insets = useSafeAreaInsets(); const [session, setSession] = useState(null); const [loading, setLoading] = useState(true); const [showOnboarding, setShowOnboarding] = useState(null); const [userStatus, setUserStatus] = useState(null); // 'active', 'pending_approval', 'rejected' useEffect(() => { // Initialize LogRocket LogRocket.init('ky7sla/helpdeskai'); const initialize = async () => { try { const { data: { session } } = await supabase.auth.getSession(); setSession(session); if (session?.user) { // Identify user in LogRocket LogRocket.identify(session.user.id, { email: session.user.email, name: session.user.user_metadata?.full_name || 'User', }); const { data } = await supabase .from('profiles') .select('status') .eq('id', session.user.id) .single(); setUserStatus(data?.status || 'active'); } const onboardingDone = await AsyncStorage.getItem('@onboarding_complete'); setShowOnboarding(onboardingDone === null); } catch (e) { console.log('Init error', e); } finally { setLoading(false); } }; initialize(); const { data: { subscription } } = supabase.auth.onAuthStateChange(async (_event, session) => { setSession(session); if (session?.user) { // Identify user in LogRocket on auth change LogRocket.identify(session.user.id, { email: session.user.email, name: session.user.user_metadata?.full_name || 'User', }); // Fetch profile status for routing const { data } = await supabase .from('profiles') .select('status') .eq('id', session.user.id) .single(); setUserStatus(data?.status || 'active'); } else { setUserStatus(null); } }); return () => subscription.unsubscribe(); }, []); // Also subscribe to profile changes to catch approval in real-time useEffect(() => { if (!session?.user?.id) return; const channel = supabase .channel(`app-profile-${session.user.id}`) .on('postgres_changes', { event: 'UPDATE', schema: 'public', table: 'profiles', filter: `id=eq.${session.user.id}`, }, (payload) => { setUserStatus(payload.new.status); }) .subscribe(); return () => supabase.removeChannel(channel); }, [session?.user?.id]); if (loading) { return ( ); } const isAuthenticated = !!session; const isActive = userStatus === 'active'; const isPending = userStatus === 'pending_approval'; const isRejected = userStatus === 'rejected'; return ( {!isAuthenticated ? ( // ─── Unauthenticated ─── <> {showOnboarding && } ) : (isPending || isRejected) ? ( // ─── Pending / Rejected ─── ) : ( // ─── Active user ─── <> )} ); }; export default function App() { return ( ); }