Compare commits
	
		
			4 Commits
		
	
	
		
			a9cb1ec425
			...
			1f4cfe0b77
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1f4cfe0b77 | |||
| 4be37ac303 | |||
| 62559810b0 | |||
| 32460062b8 | 
| @@ -1,12 +1,18 @@ | ||||
| import { FlatList } from 'react-native' | ||||
| import { Surface, Text } from 'react-native-paper' | ||||
| // import * as SecureStore from 'expo-secure-store' | ||||
| import * as SecureStore from '@/utils/SecureStore' | ||||
| import { useRouter } from 'expo-router' | ||||
| import { FAB, List, Surface } from 'react-native-paper' | ||||
|  | ||||
| export default function HistoryScreen() { | ||||
|   // const token = SecureStore.getItem("apiToken") | ||||
|   const router = useRouter() | ||||
|   const isLoggedIn = SecureStore.getItem("apiToken") !== null | ||||
|   return ( | ||||
|     <Surface> | ||||
|       <FlatList data={["Se connecter à l'API"]} renderItem={({item}) => <Text>{item}</Text>} /> | ||||
|     <Surface | ||||
|       style={{ flex: 1 }}> | ||||
|       <List.Item | ||||
|           title="Connexion au serveur" | ||||
|           description={isLoggedIn ? "Vous êtes déjà connecté⋅e" : "Vous n'êtes pas connecté⋅e"} | ||||
|           right={() => <FAB icon="login" size="small" onPress={() => router.navigate('/login')} />} | ||||
|           onPress={() => router.navigate('/login')} /> | ||||
|     </Surface> | ||||
|   ) | ||||
| } | ||||
|   | ||||
| @@ -17,6 +17,7 @@ export default function RootLayout() { | ||||
|         <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}> | ||||
|           <Stack> | ||||
|             <Stack.Screen name="(tabs)" options={{ headerShown: false }} /> | ||||
|             <Stack.Screen name="login" options={{ title: "Connexion" }} /> | ||||
|             <Stack.Screen name="+not-found" /> | ||||
|           </Stack> | ||||
|           <StatusBar style="auto" /> | ||||
|   | ||||
							
								
								
									
										85
									
								
								client/app/login.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								client/app/login.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| import * as SecureStore from "@/utils/SecureStore" | ||||
| import { useRouter } from "expo-router" | ||||
| import { useRef, useState } from "react" | ||||
| import { Platform } from "react-native" | ||||
| import { Button, Dialog, Portal, Surface, Text, TextInput } from "react-native-paper" | ||||
|  | ||||
| export default function Login() { | ||||
|   const router = useRouter() | ||||
|   const [name, setName] = useState(SecureStore.getItem('apiName') ?? "") | ||||
|   const [password, setPassword] = useState("") | ||||
|   const [errorDialogVisible, setErrorDialogVisible] = useState(false) | ||||
|   const [errorTitle, setErrorTitle] = useState("") | ||||
|   const [errorText, setErrorText] = useState("") | ||||
|  | ||||
|   const loginRef = useRef<any | null>() | ||||
|   const passwordRef = useRef<any | null>() | ||||
|  | ||||
|   const hideErrorDialog = () => setErrorDialogVisible(false) | ||||
|  | ||||
|   async function onLogin() { | ||||
|     const resp = await fetch("http://192.168.1.198:3000/auth/login/", { | ||||
|       method: "POST", | ||||
|       headers: { "Content-Type": "application/json" }, | ||||
|       body: JSON.stringify({ name: name, password: password }) | ||||
|     }) | ||||
|     .then(resp => resp.json()) | ||||
|     .catch(err => { | ||||
|       setErrorDialogVisible(true) | ||||
|       setErrorTitle("Erreur") | ||||
|       setErrorText("Une erreur inconnue est survenue lors de la connexion. Veuillez réessayer plus tard. " + err) | ||||
|     }) | ||||
|     if (!resp) | ||||
|       return | ||||
|     else if (resp.error) { | ||||
|       setErrorDialogVisible(true) | ||||
|       setErrorTitle(resp.error) | ||||
|       setErrorText(resp.message) | ||||
|       return | ||||
|     } | ||||
|     SecureStore.setItem("apiName", name) | ||||
|     if (Platform.OS !== "web") { | ||||
|       // Le stockage navigateur n'est pas sûr, on évite de stocker un mot de passe à l'intérieur | ||||
|       SecureStore.setItem("apiPassword", password) | ||||
|     } | ||||
|     SecureStore.setItem("apiToken", resp.accessToken) | ||||
|     if (router.canGoBack()) | ||||
|       router.back() | ||||
|     else | ||||
|       router.navigate('/') | ||||
|   } | ||||
|  | ||||
|   return ( | ||||
|     <Surface style={{ flex: 1 }}> | ||||
|       <TextInput | ||||
|           ref={loginRef} | ||||
|           label="Nom" | ||||
|           value={name} | ||||
|           onChangeText={(text) => setName(text)} | ||||
|           onSubmitEditing={() => passwordRef?.current.focus()} | ||||
|           style={{ margin: 8 }} /> | ||||
|       <TextInput | ||||
|           ref={passwordRef} | ||||
|           label="Mot de passe" | ||||
|           value={password} | ||||
|           onChangeText={(text) => setPassword(text)} | ||||
|           onSubmitEditing={onLogin} | ||||
|           secureTextEntry={true} | ||||
|           style={{ margin: 8 }} /> | ||||
|       <Button onPress={onLogin} mode="contained" icon="login" style={{ margin: 8 }}> | ||||
|         Se connecter | ||||
|       </Button> | ||||
|       <Portal> | ||||
|         <Dialog visible={errorDialogVisible} onDismiss={hideErrorDialog}> | ||||
|           <Dialog.Title>{errorTitle}</Dialog.Title> | ||||
|           <Dialog.Content> | ||||
|             <Text variant="bodyMedium">{errorText}</Text> | ||||
|           </Dialog.Content> | ||||
|           <Dialog.Actions> | ||||
|             <Button onPress={hideErrorDialog}>Ok</Button> | ||||
|           </Dialog.Actions> | ||||
|         </Dialog> | ||||
|       </Portal> | ||||
|     </Surface> | ||||
|   ) | ||||
| } | ||||
							
								
								
									
										3
									
								
								client/utils/SecureStore.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								client/utils/SecureStore.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| import { getItem, getItemAsync, setItem, setItemAsync } from 'expo-secure-store' | ||||
|  | ||||
| export { getItem, getItemAsync, setItem, setItemAsync } | ||||
							
								
								
									
										15
									
								
								client/utils/SecureStore.web.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								client/utils/SecureStore.web.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| export function getItem(key: string): string | null { | ||||
|   return localStorage.getItem(key) | ||||
| } | ||||
|  | ||||
| export async function getItemAsync(key: string): Promise<string | null> { | ||||
|   return localStorage.getItem(key) | ||||
| } | ||||
|  | ||||
| export function setItem(key: string, value: string): void { | ||||
|   localStorage.setItem(key, value) | ||||
| } | ||||
|  | ||||
| export async function setItemAsync(key: string, value: string): Promise<void> { | ||||
|   localStorage.setItem(key, value) | ||||
| } | ||||
| @@ -4,7 +4,7 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger' | ||||
| import { ClassSerializerInterceptor, ValidationPipe } from '@nestjs/common' | ||||
|  | ||||
| async function bootstrap() { | ||||
|   const app = await NestFactory.create(AppModule) | ||||
|   const app = await NestFactory.create(AppModule, { cors: true }) | ||||
|  | ||||
|   app.useGlobalPipes(new ValidationPipe({ transform: true })) | ||||
|   app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector))) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user