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 (
);
}