- backend/ → apps/backend/, frontend/ → apps/frontend-web/, database/ → apps/database/ - mobile/ → apps/frontend-mobile/ - Updated .gitmodules, CLAUDE.md v2.0.0 - Added apps/_MAP.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
173 lines
4.7 KiB
TypeScript
173 lines
4.7 KiB
TypeScript
/**
|
|
* App Entry Point
|
|
* ERP Transportistas
|
|
* Sprint S8 - TASK-007
|
|
*
|
|
* Main application component with navigation setup.
|
|
*/
|
|
|
|
import React, { useEffect, useState } from 'react';
|
|
import { StatusBar, View, ActivityIndicator, StyleSheet } from 'react-native';
|
|
import { NavigationContainer } from '@react-navigation/native';
|
|
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
|
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
import { Ionicons } from '@expo/vector-icons';
|
|
|
|
import { useAuthStore } from './src/store';
|
|
import { offlineStorage } from './src/services';
|
|
import {
|
|
LoginScreen,
|
|
ViajeActualScreen,
|
|
ChecklistScreen,
|
|
PODScreen,
|
|
} from './src/screens';
|
|
import type { RootStackParamList, MainTabParamList } from './src/types';
|
|
|
|
const Stack = createNativeStackNavigator<RootStackParamList>();
|
|
const Tab = createBottomTabNavigator<MainTabParamList>();
|
|
|
|
// Placeholder screens for tabs
|
|
function HistorialScreen(): JSX.Element {
|
|
return <View style={styles.placeholder} />;
|
|
}
|
|
|
|
function PerfilScreen(): JSX.Element {
|
|
return <View style={styles.placeholder} />;
|
|
}
|
|
|
|
function MainTabs(): JSX.Element {
|
|
return (
|
|
<Tab.Navigator
|
|
screenOptions={({ route }) => ({
|
|
tabBarIcon: ({ focused, color, size }) => {
|
|
let iconName: keyof typeof Ionicons.glyphMap = 'car';
|
|
|
|
if (route.name === 'ViajeActual') {
|
|
iconName = focused ? 'car' : 'car-outline';
|
|
} else if (route.name === 'Historial') {
|
|
iconName = focused ? 'time' : 'time-outline';
|
|
} else if (route.name === 'Perfil') {
|
|
iconName = focused ? 'person' : 'person-outline';
|
|
}
|
|
|
|
return <Ionicons name={iconName} size={size} color={color} />;
|
|
},
|
|
tabBarActiveTintColor: '#2563eb',
|
|
tabBarInactiveTintColor: '#64748b',
|
|
headerShown: false,
|
|
})}
|
|
>
|
|
<Tab.Screen
|
|
name="ViajeActual"
|
|
component={ViajeActualScreen}
|
|
options={{ title: 'Viaje Actual' }}
|
|
/>
|
|
<Tab.Screen
|
|
name="Historial"
|
|
component={HistorialScreen}
|
|
options={{ title: 'Historial' }}
|
|
/>
|
|
<Tab.Screen
|
|
name="Perfil"
|
|
component={PerfilScreen}
|
|
options={{ title: 'Perfil' }}
|
|
/>
|
|
</Tab.Navigator>
|
|
);
|
|
}
|
|
|
|
export default function App(): JSX.Element {
|
|
const { isAuthenticated, isLoading, restoreSession } = useAuthStore();
|
|
const [isInitializing, setIsInitializing] = useState(true);
|
|
|
|
useEffect(() => {
|
|
initializeApp();
|
|
}, []);
|
|
|
|
const initializeApp = async (): Promise<void> => {
|
|
try {
|
|
// Initialize offline storage
|
|
await offlineStorage.initialize();
|
|
|
|
// Try to restore session
|
|
await restoreSession();
|
|
} catch (error) {
|
|
console.error('Error initializing app:', error);
|
|
} finally {
|
|
setIsInitializing(false);
|
|
}
|
|
};
|
|
|
|
if (isInitializing || isLoading) {
|
|
return (
|
|
<View style={styles.loadingContainer}>
|
|
<ActivityIndicator size="large" color="#2563eb" />
|
|
</View>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<SafeAreaProvider>
|
|
<StatusBar barStyle="dark-content" backgroundColor="#ffffff" />
|
|
<NavigationContainer>
|
|
<Stack.Navigator
|
|
screenOptions={{
|
|
headerStyle: {
|
|
backgroundColor: '#ffffff',
|
|
},
|
|
headerTintColor: '#1e293b',
|
|
headerTitleStyle: {
|
|
fontWeight: '600',
|
|
},
|
|
}}
|
|
>
|
|
{isAuthenticated ? (
|
|
<>
|
|
<Stack.Screen
|
|
name="Main"
|
|
component={MainTabs}
|
|
options={{ headerShown: false }}
|
|
/>
|
|
<Stack.Screen
|
|
name="ViajeDetalle"
|
|
component={ViajeActualScreen}
|
|
options={{ title: 'Detalle del Viaje' }}
|
|
/>
|
|
<Stack.Screen
|
|
name="Checklist"
|
|
component={ChecklistScreen}
|
|
options={{ title: 'Checklist Pre-viaje' }}
|
|
/>
|
|
<Stack.Screen
|
|
name="POD"
|
|
component={PODScreen}
|
|
options={{ title: 'Prueba de Entrega' }}
|
|
/>
|
|
</>
|
|
) : (
|
|
<Stack.Screen
|
|
name="Login"
|
|
component={LoginScreen}
|
|
options={{ headerShown: false }}
|
|
/>
|
|
)}
|
|
</Stack.Navigator>
|
|
</NavigationContainer>
|
|
</SafeAreaProvider>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
loadingContainer: {
|
|
flex: 1,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
backgroundColor: '#ffffff',
|
|
},
|
|
placeholder: {
|
|
flex: 1,
|
|
backgroundColor: '#f1f5f9',
|
|
},
|
|
});
|