chore: build
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
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}</>;
|
||||
}
|
||||
Reference in New Issue
Block a user