From ae63532503eb0b5c7a60d18ef17504c0632d508d Mon Sep 17 00:00:00 2001 From: Santo Cariotti Date: Thu, 29 Aug 2024 18:27:23 +0200 Subject: Login page --- app/(tabs)/_layout.tsx | 8 +- app/(tabs)/explore.tsx | 102 ------------------------- app/(tabs)/index.tsx | 204 +++++++++++++++++++++++++++++++++++++------------ 3 files changed, 158 insertions(+), 156 deletions(-) delete mode 100644 app/(tabs)/explore.tsx (limited to 'app') diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx index 22a49b6..fcc94db 100644 --- a/app/(tabs)/_layout.tsx +++ b/app/(tabs)/_layout.tsx @@ -23,15 +23,15 @@ export default function TabLayout() { ), }} /> - ( - + ), }} - /> + />*/} ); } diff --git a/app/(tabs)/explore.tsx b/app/(tabs)/explore.tsx deleted file mode 100644 index e480218..0000000 --- a/app/(tabs)/explore.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import Ionicons from '@expo/vector-icons/Ionicons'; -import { StyleSheet, Image, Platform } from 'react-native'; - -import { Collapsible } from '@/components/Collapsible'; -import { ExternalLink } from '@/components/ExternalLink'; -import ParallaxScrollView from '@/components/ParallaxScrollView'; -import { ThemedText } from '@/components/ThemedText'; -import { ThemedView } from '@/components/ThemedView'; - -export default function TabTwoScreen() { - return ( - }> - - Explore - - This app includes example code to help you get started. - - - This app has two screens:{' '} - app/(tabs)/index.tsx and{' '} - app/(tabs)/explore.tsx - - - The layout file in app/(tabs)/_layout.tsx{' '} - sets up the tab navigator. - - - Learn more - - - - - You can open this project on Android, iOS, and the web. To open the web version, press{' '} - w in the terminal running this project. - - - - - For static images, you can use the @2x and{' '} - @3x suffixes to provide files for - different screen densities - - - - Learn more - - - - - Open app/_layout.tsx to see how to load{' '} - - custom fonts such as this one. - - - - Learn more - - - - - This template has light and dark mode support. The{' '} - useColorScheme() hook lets you inspect - what the user's current color scheme is, and so you can adjust UI colors accordingly. - - - Learn more - - - - - This template includes an example of an animated component. The{' '} - components/HelloWave.tsx component uses - the powerful react-native-reanimated library - to create a waving hand animation. - - {Platform.select({ - ios: ( - - The components/ParallaxScrollView.tsx{' '} - component provides a parallax effect for the header image. - - ), - })} - - - ); -} - -const styles = StyleSheet.create({ - headerImage: { - color: '#808080', - bottom: -90, - left: -35, - position: 'absolute', - }, - titleContainer: { - flexDirection: 'row', - gap: 8, - }, -}); diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx index 324aeb7..46a690f 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/index.tsx @@ -1,51 +1,134 @@ -import { Image, StyleSheet, Platform } from 'react-native'; +import { Alert, Platform, Pressable, StyleSheet, Text, TextInput, View } from 'react-native'; -import { HelloWave } from '@/components/HelloWave'; import ParallaxScrollView from '@/components/ParallaxScrollView'; import { ThemedText } from '@/components/ThemedText'; import { ThemedView } from '@/components/ThemedView'; +import React, { useState, useEffect } from 'react'; +import { API_URL } from '@env'; +import AsyncStorage from '@react-native-async-storage/async-storage'; + export default function HomeScreen() { + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + const [token, setToken] = useState(''); + + const storeToken = async (token: string) => { + if (Platform.OS === 'web') { + localStorage.setItem('token', token); + } else { + await AsyncStorage.setItem('token', token); + } + }; + + const handleLogin = async () => { + if (!username || !password) { + Alert.alert('Error', 'Username and password are required.'); + return; + } + + try { + const response = await fetch(`${API_URL}/graphql`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + query: ` + mutation Login($input: LoginCredentials!) { + login(input: $input) { + accessToken + tokenType + } + }`, + variables: { + input: { + email: username, + password, + }, + }, + }), + }); + + const data = await response.json(); + + if (data.errors) { + const errorMessages = data.errors.map((error: any) => error.message); + Alert.alert('Error', errorMessages.join('\n')); + } else { + const { accessToken } = data.data.login; + await storeToken(accessToken); + setToken(accessToken); + } + } catch (err) { + console.error('Login Error:', err); + Alert.alert('Error', 'An error occurred during login.'); + } + }; + + const handleLogout = async () => { + await removeToken(); + setToken(''); + }; + + const removeToken = async () => { + if (Platform.OS === 'web') { + localStorage.removeItem('token'); + } else { + await AsyncStorage.removeItem('token'); + } + }; + + useEffect(() => { + const retrieveToken = async () => { + const storedToken = Platform.OS === 'web' ? localStorage.getItem('token') : await AsyncStorage.getItem('token'); + setToken(storedToken || ''); + }; + + retrieveToken(); + }, []); + return ( - - }> - - Welcome! - - - - Step 1: Try it - - Edit app/(tabs)/index.tsx to see changes. - Press{' '} - - {Platform.select({ ios: 'cmd + d', android: 'cmd + m' })} - {' '} - to open developer tools. - - - - Step 2: Explore - - Tap the Explore tab to learn more about what's included in this starter app. - - - - Step 3: Get a fresh start - - When you're ready, run{' '} - npm run reset-project to get a fresh{' '} - app directory. This will move the current{' '} - app to{' '} - app-example. - - + + {token ? ( + + + Logout + + + ) : ( + <> + + Welcome, mate! + + + + Username + + + + Password + + + + + Login + + + + + )} ); } @@ -54,17 +137,38 @@ const styles = StyleSheet.create({ titleContainer: { flexDirection: 'row', alignItems: 'center', - gap: 8, + marginBottom: 20, }, - stepContainer: { - gap: 8, + text: { marginBottom: 8, + color: '#333', }, - reactLogo: { - height: 178, - width: 290, - bottom: 0, - left: 0, - position: 'absolute', + formContainer: { + marginTop: 20, + paddingHorizontal: 20, }, + formInput: { + width: '100%', + paddingVertical: 12, + paddingHorizontal: 16, + borderRadius: 8, + borderWidth: 1, + borderColor: '#ccc', + backgroundColor: '#f9f9f9', + marginBottom: 20, + }, + buttonContainer: { + marginTop: 20, + }, + formButton: { + paddingVertical: 12, + paddingHorizontal: 24, + backgroundColor: '#007AFF', + fontSize: 16, + fontWeight: '600', + textAlign: 'center', + borderRadius: 8, + color: 'white', + } }); + -- cgit v1.2.3-18-g5258