Déconnexion permise

This commit is contained in:
Emmy D'Anello 2024-12-10 00:04:35 +01:00
parent ead2a91410
commit 7becd396d3
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
7 changed files with 102 additions and 8 deletions

View File

@ -2,10 +2,18 @@ import { Tabs } from 'expo-router'
import React from 'react' import React from 'react'
import { FontAwesome6, MaterialIcons } from '@expo/vector-icons' import { FontAwesome6, MaterialIcons } from '@expo/vector-icons'
import TabBar from '@/components/ui/TabBar' import TabBar from '@/components/ui/TabBar'
import TabsHeader from '@/components/ui/TabsHeader'
export default function TabLayout() { export default function TabLayout() {
return ( return (
<Tabs tabBar={(props) => <TabBar {...props} />}> <>
<Tabs
tabBar={(props) => <TabBar {...props} />}
screenOptions={{
tabBarHideOnKeyboard: true,
header: (props) => <TabsHeader navProps={props} children={undefined} />,
}}
>
<Tabs.Screen <Tabs.Screen
name="index" name="index"
options={{ options={{
@ -47,5 +55,6 @@ export default function TabLayout() {
}} }}
/> />
</Tabs> </Tabs>
</>
) )
} }

View File

@ -9,6 +9,7 @@ import * as SecureStore from '@/utils/SecureStore'
import { useStartGeolocationServiceEffect } from '@/utils/geolocation' import { useStartGeolocationServiceEffect } from '@/utils/geolocation'
import { useEffect } from 'react' import { useEffect } from 'react'
import { useRouteInfo } from 'expo-router/build/hooks' import { useRouteInfo } from 'expo-router/build/hooks'
import TabsHeader from '@/components/ui/TabsHeader'
export default function RootLayout() { export default function RootLayout() {
useStartGeolocationServiceEffect() useStartGeolocationServiceEffect()
@ -29,7 +30,7 @@ export default function RootLayout() {
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}> <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<Stack> <Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} /> <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="login" options={{ title: "Connexion" }} /> <Stack.Screen name="login" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" /> <Stack.Screen name="+not-found" />
</Stack> </Stack>
<StatusBar style="auto" /> <StatusBar style="auto" />

View File

@ -2,10 +2,12 @@ import * as SecureStore from "@/utils/SecureStore"
import { useRouter } from "expo-router" import { useRouter } from "expo-router"
import { useRef, useState } from "react" import { useRef, useState } from "react"
import { Platform } from "react-native" import { Platform } from "react-native"
import { Button, Dialog, Portal, Surface, Text, TextInput } from "react-native-paper" import { Appbar, Button, Dialog, Portal, Surface, Text, TextInput } from "react-native-paper"
export default function Login() { export default function Login() {
const router = useRouter() const router = useRouter()
const [isLoggedIn, setIsLoggedIn] = useState(SecureStore.getItem("apiToken") !== null)
console.log(SecureStore.getItem("apiToken"))
const [name, setName] = useState(SecureStore.getItem('apiName') ?? "") const [name, setName] = useState(SecureStore.getItem('apiName') ?? "")
const [password, setPassword] = useState("") const [password, setPassword] = useState("")
const [errorDialogVisible, setErrorDialogVisible] = useState(false) const [errorDialogVisible, setErrorDialogVisible] = useState(false)
@ -17,7 +19,7 @@ export default function Login() {
const hideErrorDialog = () => setErrorDialogVisible(false) const hideErrorDialog = () => setErrorDialogVisible(false)
async function onLogin() { async function login() {
const resp = await fetch("http://192.168.1.198:3000/auth/login/", { const resp = await fetch("http://192.168.1.198:3000/auth/login/", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
@ -49,8 +51,20 @@ export default function Login() {
router.navigate('/') router.navigate('/')
} }
async function logout() {
await SecureStore.deleteItemAsync("apiName")
await SecureStore.deleteItemAsync("apiPassword")
await SecureStore.deleteItemAsync("apiToken")
setIsLoggedIn(false)
}
return ( return (
<Surface style={{ flex: 1 }}> <Surface style={{ flex: 1 }}>
<Appbar.Header>
{isLoggedIn && router.canGoBack() ? <Appbar.BackAction onPress={() => router.back()} /> : undefined}
<Appbar.Content title={"Connexion"} />
{isLoggedIn ? <Appbar.Action icon={"logout"} onPress={logout} /> : undefined}
</Appbar.Header>
<TextInput <TextInput
ref={loginRef} ref={loginRef}
label="Nom" label="Nom"
@ -63,10 +77,10 @@ export default function Login() {
label="Mot de passe" label="Mot de passe"
value={password} value={password}
onChangeText={(text) => setPassword(text)} onChangeText={(text) => setPassword(text)}
onSubmitEditing={onLogin} onSubmitEditing={login}
secureTextEntry={true} secureTextEntry={true}
style={{ margin: 8 }} /> style={{ margin: 8 }} />
<Button onPress={onLogin} mode="contained" icon="login" style={{ margin: 8 }}> <Button onPress={login} mode="contained" icon="login" style={{ margin: 8 }}>
Se connecter Se connecter
</Button> </Button>
<Portal> <Portal>

View File

View File

@ -0,0 +1,66 @@
import { BottomTabHeaderProps } from '@react-navigation/bottom-tabs'
import { getHeaderTitle } from '@react-navigation/elements'
import React from 'react'
import {
Appbar,
AppbarProps,
IconButton,
Searchbar,
SearchbarProps,
Tooltip,
} from 'react-native-paper'
interface TabsHeaderProps extends AppbarProps {
navProps: BottomTabHeaderProps
withSearchBar?: boolean
searchBarProps?: SearchbarProps
}
const TabsHeader = (props: TabsHeaderProps) => {
const [query, setQuery] = React.useState('')
return props.withSearchBar ? (
<Appbar.Header {...props}>
<Searchbar
{...props.searchBarProps}
value={query}
onChangeText={setQuery}
style={{ margin: 8, marginBottom: 16 }}
right={(p) => (
<Tooltip title="Rechercher">
<IconButton
{...p}
icon="check"
onPress={() =>
props.searchBarProps?.onChangeText
? props.searchBarProps.onChangeText(query)
: undefined
}
/>
</Tooltip>
)}
/>
</Appbar.Header>
) : (
<Appbar.Header {...props}>
{props.navProps.options.headerLeft
? props.navProps.options.headerLeft({})
: undefined}
<Appbar.Content
title={getHeaderTitle(
props.navProps.options,
props.navProps.route.name,
)}
/>
{props.navProps.options.headerRight
? props.navProps.options.headerRight({
canGoBack: props.navProps.navigation.canGoBack(),
})
: undefined}
</Appbar.Header>
)
}
export default TabsHeader

View File

@ -1,3 +1,3 @@
import { getItem, getItemAsync, setItem, setItemAsync } from 'expo-secure-store' import { deleteItemAsync, getItem, getItemAsync, setItem, setItemAsync } from 'expo-secure-store'
export { getItem, getItemAsync, setItem, setItemAsync } export { deleteItemAsync, getItem, getItemAsync, setItem, setItemAsync }

View File

@ -1,3 +1,7 @@
export async function deleteItemAsync(key: string): Promise<void> {
return localStorage.removeItem(key)
}
export function getItem(key: string): string | null { export function getItem(key: string): string | null {
return localStorage.getItem(key) return localStorage.getItem(key)
} }