Files
Xor290 bef57d91de
Omnex Plateform App - EAS Build / build (push) Canceled after 7m42s
Omnex Plateform Client - EAS Build / build (push) Canceled after 4m43s
chore: build
2026-08-04 21:18:12 +02:00

180 lines
5.5 KiB
TypeScript

import React, { useEffect, useState } from "react";
import { StatusBar } from "expo-status-bar";
import { ActivityIndicator, View } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import * as Updates from "expo-updates";
import { AuthProvider, useAuth } from "./src/auth/AuthContext";
import { CartProvider } from "./src/context/CartContext";
import { NotificationProvider } from "./src/context/NotificationContext";
import { ThemeProvider, useTheme } from "./src/context/ThemeContext";
import { initServerBaseUrl } from "./src/api/client";
import HomeScreen from "./src/screens/HomeScreen";
import ServerConfigScreen from "./src/screens/auth/ServerConfigScreen";
import ClientLoginScreen from "./src/screens/auth/ClientLoginScreen";
import ClientTwoFAScreen from "./src/screens/auth/ClientTwoFAScreen";
import ChangePasswordScreen from "./src/screens/auth/ChangePasswordScreen";
import ClientNavigator from "./src/navigation/ClientNavigator";
import type { RootStackParamList, ChangePasswordStackParamList } from "./src/navigation/types";
const Stack = createNativeStackNavigator<RootStackParamList>();
const CPStack = createNativeStackNavigator<ChangePasswordStackParamList>();
function AuthStack() {
const { colors } = useTheme();
return (
<Stack.Navigator
initialRouteName="ServerConfig"
screenOptions={{
headerStyle: { backgroundColor: colors.bgSecondary },
headerTintColor: colors.textWhite,
}}
>
<Stack.Screen
name="ServerConfig"
component={ServerConfigScreen}
options={{ title: "Serveur API" }}
/>
<Stack.Screen
name="home"
component={HomeScreen}
options={{ title: "Accueil" }}
/>
<Stack.Screen
name="login"
component={ClientLoginScreen}
options={{ title: "Connexion" }}
/>
<Stack.Screen
name="clientTwoFA"
component={ClientTwoFAScreen}
options={{ title: "Vérification" }}
/>
</Stack.Navigator>
);
}
function ForceChangePasswordStack() {
const { colors } = useTheme();
return (
<CPStack.Navigator
screenOptions={{
headerStyle: { backgroundColor: colors.bgSecondary },
headerTintColor: colors.textWhite,
gestureEnabled: false,
}}
>
<CPStack.Screen
name="ChangePassword"
component={ChangePasswordScreen}
options={{ title: "Changer le mot de passe", headerLeft: () => null }}
/>
</CPStack.Navigator>
);
}
function RootNavigator() {
const { isAuthenticated, isLoading, role, mustChangePassword } = useAuth();
const { colors, isDark } = useTheme();
if (isLoading) {
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: colors.bgPrimary,
}}
>
<ActivityIndicator size="large" color={colors.accent} />
</View>
);
}
if (isAuthenticated && role === "client" && mustChangePassword) {
return <ForceChangePasswordStack />;
}
if (isAuthenticated && role === "client") {
return (
<CartProvider>
<NotificationProvider>
<ClientNavigator />
</NotificationProvider>
</CartProvider>
);
}
return <AuthStack />;
}
function AppContent() {
const { isDark } = useTheme();
useEffect(() => {
if (__DEV__) return;
const checkForUpdate = async () => {
try {
const update = await Updates.checkForUpdateAsync();
if (update.isAvailable) {
await Updates.fetchUpdateAsync();
await Updates.reloadAsync();
}
} catch {
// Silently ignore update errors
}
};
checkForUpdate();
}, []);
return (
<NavigationContainer>
<RootNavigator />
<StatusBar style={isDark ? "light" : "dark"} />
</NavigationContainer>
);
}
export default function App() {
return (
<ThemeProvider>
<ServerGate>
<AuthProvider>
<AppContent />
</AuthProvider>
</ServerGate>
</ThemeProvider>
);
}
// Restores a previously saved backend server URL before any screen
// (including the auth restore flow) can issue an API call.
function ServerGate({ children }: { children: React.ReactNode }) {
const [ready, setReady] = useState(false);
const { colors } = useTheme();
useEffect(() => {
initServerBaseUrl().finally(() => setReady(true));
}, []);
if (!ready) {
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: colors.bgPrimary,
}}
>
<ActivityIndicator size="large" color={colors.accent} />
</View>
);
}
return <>{children}</>;
}