From ae63532503eb0b5c7a60d18ef17504c0632d508d Mon Sep 17 00:00:00 2001
From: Santo Cariotti <santo@dcariotti.me>
Date: Thu, 29 Aug 2024 18:27:23 +0200
Subject: Login page

---
 app/(tabs)/index.tsx | 204 ++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 154 insertions(+), 50 deletions(-)

(limited to 'app/(tabs)/index.tsx')

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 (
-    <ParallaxScrollView
-      headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
-      headerImage={
-        <Image
-          source={require('@/assets/images/partial-react-logo.png')}
-          style={styles.reactLogo}
-        />
-      }>
-      <ThemedView style={styles.titleContainer}>
-        <ThemedText type="title">Welcome!</ThemedText>
-        <HelloWave />
-      </ThemedView>
-      <ThemedView style={styles.stepContainer}>
-        <ThemedText type="subtitle">Step 1: Try it</ThemedText>
-        <ThemedText>
-          Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
-          Press{' '}
-          <ThemedText type="defaultSemiBold">
-            {Platform.select({ ios: 'cmd + d', android: 'cmd + m' })}
-          </ThemedText>{' '}
-          to open developer tools.
-        </ThemedText>
-      </ThemedView>
-      <ThemedView style={styles.stepContainer}>
-        <ThemedText type="subtitle">Step 2: Explore</ThemedText>
-        <ThemedText>
-          Tap the Explore tab to learn more about what's included in this starter app.
-        </ThemedText>
-      </ThemedView>
-      <ThemedView style={styles.stepContainer}>
-        <ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
-        <ThemedText>
-          When you're ready, run{' '}
-          <ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
-          <ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
-          <ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
-          <ThemedText type="defaultSemiBold">app-example</ThemedText>.
-        </ThemedText>
-      </ThemedView>
+    <ParallaxScrollView>
+      {token ? (
+        <ThemedView> 
+          <Pressable onPress={handleLogout} style={styles.formButton}>
+            <Text style={{ color: 'white', textAlign: 'center' }}>Logout</Text>
+          </Pressable>
+        </ThemedView>
+      ) : (
+        <>
+          <ThemedView style={styles.titleContainer}>
+            <ThemedText type="title">Welcome, mate!</ThemedText>
+          </ThemedView>
+          <ThemedView style={styles.formContainer}>
+            <View>
+              <ThemedText style={styles.text}>Username</ThemedText>
+              <TextInput
+                style={styles.formInput}
+                onChangeText={setUsername}
+                value={username}
+                placeholder="Username"
+              />
+            </View>
+            <View>
+              <ThemedText style={styles.text}>Password</ThemedText>
+              <TextInput
+                style={styles.formInput}
+                onChangeText={setPassword}
+                value={password}
+                placeholder="Password"
+                secureTextEntry
+              />
+            </View>
+            <View style={styles.buttonContainer}>
+              <Pressable onPress={handleLogin} style={styles.formButton}>
+                <Text style={{ color: 'white', textAlign: 'center' }}>Login</Text>
+              </Pressable>
+            </View>
+          </ThemedView>
+        </>
+      )}
     </ParallaxScrollView>
   );
 }
@@ -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

