Add "Forgot Password" screen and navigation from login page

This commit is contained in:
2026-05-13 11:26:26 +02:00
parent e4b228779c
commit f3fa22729c
3 changed files with 129 additions and 3 deletions

View File

@@ -20,6 +20,7 @@ export default function AppLayout() {
<Stack screenOptions={{ headerShown: false, animation: 'flip' }}> <Stack screenOptions={{ headerShown: false, animation: 'flip' }}>
<Stack.Screen name="(protected)" /> <Stack.Screen name="(protected)" />
<Stack.Screen name="login" /> <Stack.Screen name="login" />
<Stack.Screen name="forgot-password" />
</Stack> </Stack>
</AlertProvider> </AlertProvider>
</AuthProvider> </AuthProvider>

119
app/forgot-password.tsx Normal file
View File

@@ -0,0 +1,119 @@
import { useAlert } from '@/components/AlertComponent';
import api from '@/utils/api';
import { ArrowLeft, Mail, Send } from 'lucide-react-native';
import { useState } from 'react';
import { Image, Platform, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { KeyboardAwareScrollView } from 'react-native-keyboard-controller';
import { useRouter } from 'expo-router';
export default function ForgotPasswordScreen() {
const alert = useAlert();
const router = useRouter();
const [identifier, setIdentifier] = useState('');
const [isLoading, setIsLoading] = useState(false);
const handleSubmit = async () => {
if (!identifier.trim()) {
alert.showAlert('error', 'Attenzione', 'Inserisci email o username');
return;
}
setIsLoading(true);
try {
await api.post('/user/forgot-password', { identifier: identifier.trim() });
alert.showAlert(
'success',
'Richiesta Inviata',
'Se l\'account esiste, riceverai un\'email con il link per reimpostare la password.'
);
router.back();
} catch (error: any) {
let message = 'Si è verificato un errore. Riprova più tardi.';
if (error.request && !error.response) {
message = 'Impossibile contattare il server. Controlla la connessione.';
} else if (error.response) {
message = `Errore Server: ${error.response.data?.message || error.response.status}`;
}
alert.showAlert('error', 'Errore', message);
} finally {
setIsLoading(false);
}
};
return (
<View className="flex-1 bg-[#099499] h-screen overflow-hidden">
{/* Header with Logo */}
<View className="h-[35%] flex-column justify-center items-center">
<Image
source={require('@/assets/images/mariani-logo.png')}
className='h-24 w-80'
resizeMode="contain"
/>
</View>
{/* Form Container */}
<View className="flex-1 bg-white rounded-t-[2.5rem] px-8 pt-10 shadow-xl w-full">
<KeyboardAwareScrollView
bottomOffset={Platform.OS === 'ios' ? 50 : 80}
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
contentContainerStyle={{ paddingBottom: 40, flexGrow: 1 }}
className="flex-1"
>
<View className="gap-6 flex flex-col" style={{ gap: '1.5rem' }}>
{/* Title */}
<View>
<Text className="text-gray-800 text-2xl font-bold mb-2">Recupero Password</Text>
<Text className="text-gray-500 text-base">
Inserisci la tua email o username. Ti invieremo un link per reimpostare la password.
</Text>
</View>
{/* Input Email / Username */}
<View>
<Text className="text-gray-700 text-lg font-bold mb-3 ml-1">Email o Username</Text>
<View className="flex-row items-center bg-gray-50 border border-gray-100 rounded-2xl h-16 px-4 flex">
<Mail size={24} color="#9ca3af" pointerEvents="none" />
<TextInput
className="flex-1 ml-4 text-gray-800 text-lg font-medium h-full w-full"
placeholder="mario.rossi@esempio.com"
placeholderTextColor="#9ca3af"
value={identifier}
onChangeText={setIdentifier}
autoCapitalize="none"
keyboardType="email-address"
autoFocus
/>
</View>
</View>
{/* Submit Button */}
<TouchableOpacity
onPress={handleSubmit}
activeOpacity={0.8}
className={`bg-[#099499] h-16 rounded-2xl flex-row justify-center items-center shadow-md mt-4 flex ${isLoading ? 'opacity-70' : ''}`}
disabled={isLoading}
>
<Text className="text-white text-xl font-bold mr-2">
{isLoading ? 'Invio in corso...' : 'Invia Link'}
</Text>
{!isLoading && <Send size={24} color="white" pointerEvents="none" />}
</TouchableOpacity>
{/* Back to Login */}
<TouchableOpacity
onPress={() => router.back()}
className="flex-row justify-center items-center mt-2"
activeOpacity={0.7}
>
<ArrowLeft size={18} color="#099499" pointerEvents="none" />
<Text className="text-[#099499] font-bold text-base ml-1">Torna al Login</Text>
</TouchableOpacity>
</View>
</KeyboardAwareScrollView>
</View>
</View>
);
}

View File

@@ -5,10 +5,12 @@ import { Eye, EyeOff, Lock, LogIn, Mail } from 'lucide-react-native';
import React, { useContext, useState } from 'react'; import React, { useContext, useState } from 'react';
import { Image, Platform, Text, TextInput, TouchableOpacity, View } from 'react-native'; import { Image, Platform, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { KeyboardAwareScrollView } from 'react-native-keyboard-controller'; import { KeyboardAwareScrollView } from 'react-native-keyboard-controller';
import { useRouter } from 'expo-router';
export default function LoginScreen() { export default function LoginScreen() {
const alert = useAlert(); const alert = useAlert();
const authContext = useContext(AuthContext); const authContext = useContext(AuthContext);
const router = useRouter();
const [username, setUsername] = useState(''); const [username, setUsername] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
@@ -122,10 +124,14 @@ export default function LoginScreen() {
)} )}
</TouchableOpacity> </TouchableOpacity>
</View> </View>
{/* TODO: Implement password recovery functionality */} <TouchableOpacity
{/* <TouchableOpacity className="mt-3 self-end" style={{ alignSelf: 'flex-end' }}> className="mt-3"
style={{ alignSelf: 'flex-end' }}
onPress={() => router.push('/forgot-password')}
activeOpacity={0.7}
>
<Text className="text-[#099499] font-bold text-base">Password dimenticata?</Text> <Text className="text-[#099499] font-bold text-base">Password dimenticata?</Text>
</TouchableOpacity> */} </TouchableOpacity>
</View> </View>
{/* Login Button */} {/* Login Button */}