Implement login functionality and create profile screen with secure storage
This commit is contained in:
143
app/index.tsx
143
app/index.tsx
@@ -1,85 +1,77 @@
|
||||
import * as Notifications from 'expo-notifications';
|
||||
import axios from 'axios';
|
||||
import { useRouter } from 'expo-router';
|
||||
import * as SecureStore from 'expo-secure-store';
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Alert, Platform, StyleSheet, Text, TextInput, TouchableOpacity, View } from "react-native";
|
||||
import React, { useState } from "react";
|
||||
import { ActivityIndicator, Alert, StyleSheet, Text, TextInput, TouchableOpacity, View } from "react-native";
|
||||
|
||||
const PRIMARY = '#A24BFA';
|
||||
const BG = '#0c0a0a';
|
||||
|
||||
Notifications.setNotificationHandler({
|
||||
handleNotification: async () => ({
|
||||
shouldShowBanner: true,
|
||||
shouldShowList: true,
|
||||
shouldPlaySound: false,
|
||||
shouldSetBadge: false,
|
||||
})
|
||||
});
|
||||
|
||||
async function registerForPushNotificationsAsync() {
|
||||
const { status: existingStatus } = await Notifications.getPermissionsAsync();
|
||||
let finalStatus = existingStatus;
|
||||
if (existingStatus !== 'granted') {
|
||||
const { status } = await Notifications.requestPermissionsAsync();
|
||||
finalStatus = status;
|
||||
}
|
||||
if (finalStatus !== 'granted') {
|
||||
Alert.alert('Permission for notifications not granted!');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async function sendNotification() {
|
||||
try {
|
||||
const id = await Notifications.scheduleNotificationAsync({
|
||||
content: {
|
||||
title: "Hello!",
|
||||
body: "Ez egy értesítés példája.",
|
||||
},
|
||||
trigger: Platform.OS === 'android'
|
||||
? ({ seconds: 1, repeats: false } as any)
|
||||
: null,
|
||||
});
|
||||
Alert.alert('Notification scheduled!', `ID: ${id}`);
|
||||
} catch (e) {
|
||||
Alert.alert('Hiba történt!', String(e));
|
||||
}
|
||||
}
|
||||
|
||||
export default function Index() {
|
||||
const [username, setUsername] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
registerForPushNotificationsAsync();
|
||||
}, []);
|
||||
async function handleLogin() {
|
||||
setLoading(true);
|
||||
console.log('Login attempt:', username);
|
||||
try {
|
||||
const response = await axios.post(
|
||||
"https://mymenu.mcdonalds.hu/api/AccountApi/Login",
|
||||
{
|
||||
Data: {
|
||||
UserName: username,
|
||||
Password: password
|
||||
}
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'referer': 'https://mymenu.mcdonalds.hu/',
|
||||
'origin': 'https://mymenu.mcdonalds.hu'
|
||||
}
|
||||
}
|
||||
);
|
||||
console.log('Login response:', response.data, response.headers);
|
||||
const cookie = response.headers['set-cookie']?.join('; ');
|
||||
const userId = response.data.Data.UserID;
|
||||
const fullName = response.data.Data.FullName;
|
||||
await SecureStore.setItemAsync('cookie', cookie || '');
|
||||
await SecureStore.setItemAsync('userId', String(userId));
|
||||
await SecureStore.setItemAsync('email', username);
|
||||
await SecureStore.setItemAsync('password', password);
|
||||
await SecureStore.setItemAsync('fullName', fullName || '');
|
||||
console.log('Saved to SecureStore:', { cookie, userId, username, password, fullName });
|
||||
router.replace('/profile');
|
||||
} catch (e) {
|
||||
console.log('Login error:', e);
|
||||
Alert.alert('Hiba', 'Hibás felhasználónév vagy jelszó, vagy hálózati hiba.');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<StatusBar style="light" backgroundColor={BG} />
|
||||
<View style={styles.card}>
|
||||
<View style={{ alignItems: 'center', marginBottom: 16 }}>
|
||||
<Text style={styles.logoText}>ANGELIC{"\n"}MC</Text>
|
||||
</View>
|
||||
<Text style={styles.title}>Üdv újra</Text>
|
||||
<Text style={styles.subtitle}>Jelentkezz be a fiókodba</Text>
|
||||
<Text style={styles.subtitle}>Jelentkezz be a mymenu fiókodba</Text>
|
||||
<View style={{ height: 24 }} />
|
||||
<Text style={styles.label}>Felhasználónév</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Add meg a felhasználóneved"
|
||||
placeholder="valaki@gmail.com"
|
||||
placeholderTextColor="#aaa"
|
||||
value={username}
|
||||
onChangeText={setUsername}
|
||||
autoCapitalize="none"
|
||||
/>
|
||||
<View style={{ height: 16 }} />
|
||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Text style={styles.label}>Jelszó</Text>
|
||||
<TouchableOpacity>
|
||||
<Text style={styles.forgot}>Elfelejtetted?</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={styles.label}>Jelszó</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="••••••••"
|
||||
@@ -89,16 +81,13 @@ export default function Index() {
|
||||
secureTextEntry
|
||||
/>
|
||||
<View style={{ height: 24 }} />
|
||||
<TouchableOpacity style={styles.button} onPress={sendNotification}>
|
||||
<Text style={styles.buttonText}>Bejelentkezés</Text>
|
||||
<TouchableOpacity style={styles.button} onPress={handleLogin} disabled={loading}>
|
||||
{loading ? (
|
||||
<ActivityIndicator color="#fff" />
|
||||
) : (
|
||||
<Text style={styles.buttonText}>Bejelentkezés</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
<View style={{ height: 16 }} />
|
||||
<View style={{ flexDirection: 'row', justifyContent: 'center' }}>
|
||||
<Text style={styles.bottomText}>Nincs még fiókod? </Text>
|
||||
<TouchableOpacity>
|
||||
<Text style={styles.register}>Regisztrálj most!</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
@@ -127,14 +116,6 @@ const styles = StyleSheet.create({
|
||||
shadowOffset: { width: 0, height: 8 },
|
||||
elevation: 8,
|
||||
},
|
||||
logoText: {
|
||||
color: PRIMARY,
|
||||
fontWeight: 'bold',
|
||||
fontSize: 28,
|
||||
textAlign: 'center',
|
||||
letterSpacing: 2,
|
||||
marginBottom: 4,
|
||||
},
|
||||
title: {
|
||||
color: '#fff',
|
||||
fontWeight: 'bold',
|
||||
@@ -163,11 +144,6 @@ const styles = StyleSheet.create({
|
||||
paddingVertical: 12,
|
||||
fontSize: 16,
|
||||
},
|
||||
forgot: {
|
||||
color: PRIMARY,
|
||||
fontSize: 14,
|
||||
fontWeight: '500',
|
||||
},
|
||||
button: {
|
||||
backgroundColor: PRIMARY,
|
||||
borderRadius: 12,
|
||||
@@ -185,13 +161,4 @@ const styles = StyleSheet.create({
|
||||
fontWeight: 'bold',
|
||||
fontSize: 18,
|
||||
},
|
||||
bottomText: {
|
||||
color: '#bdbdbd',
|
||||
fontSize: 15,
|
||||
},
|
||||
register: {
|
||||
color: PRIMARY,
|
||||
fontWeight: 'bold',
|
||||
fontSize: 15,
|
||||
},
|
||||
});
|
76
app/profile.tsx
Normal file
76
app/profile.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import * as SecureStore from 'expo-secure-store';
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { StyleSheet, Text, View } from "react-native";
|
||||
|
||||
const PRIMARY = '#A24BFA';
|
||||
const BG = '#0c0a0a';
|
||||
|
||||
export default function Profile() {
|
||||
const [fullName, setFullName] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [userId, setUserId] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const name = await SecureStore.getItemAsync('fullName');
|
||||
const mail = await SecureStore.getItemAsync('email');
|
||||
const uid = await SecureStore.getItemAsync('userId');
|
||||
setFullName(name || '');
|
||||
setEmail(mail || '');
|
||||
setUserId(uid || '');
|
||||
})();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>Profil</Text>
|
||||
<View style={styles.card}>
|
||||
<Text style={styles.label}>Név:</Text>
|
||||
<Text style={styles.value}>{fullName}</Text>
|
||||
<Text style={styles.label}>Email:</Text>
|
||||
<Text style={styles.value}>{email}</Text>
|
||||
<Text style={styles.label}>UserID:</Text>
|
||||
<Text style={styles.value}>{userId}</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: BG,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
title: {
|
||||
color: '#fff',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 28,
|
||||
textAlign: 'center',
|
||||
marginBottom: 24,
|
||||
},
|
||||
card: {
|
||||
backgroundColor: 'rgba(24, 20, 28, 0.95)',
|
||||
borderRadius: 24,
|
||||
padding: 32,
|
||||
width: '90%',
|
||||
maxWidth: 400,
|
||||
shadowColor: '#000',
|
||||
shadowOpacity: 0.3,
|
||||
shadowRadius: 24,
|
||||
shadowOffset: { width: 0, height: 8 },
|
||||
elevation: 8,
|
||||
},
|
||||
label: {
|
||||
color: '#bdbdbd',
|
||||
fontSize: 16,
|
||||
marginTop: 12,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
value: {
|
||||
color: PRIMARY,
|
||||
fontSize: 18,
|
||||
marginBottom: 8,
|
||||
},
|
||||
});
|
Reference in New Issue
Block a user