Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Text, View, StatusBar } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import Icon from "react-native-vector-icons/Ionicons";
import { Quicksand_400Regular, Quicksand_700Bold } from "@expo-google-fonts/quicksand";
import { useFonts } from "expo-font";

Expand All @@ -21,6 +22,7 @@ import DataPage from "./pages/DataPage";
import ProfilePage from "./pages/ProfilePage";
import HelpPage from "./pages/HelpPage";
import LoginPage from "./pages/LoginPage";
import RegisterPage from "./pages/RegisterPage";

export default function App() {
const [fontsLoaded] = useFonts({
Expand Down Expand Up @@ -107,6 +109,11 @@ export default function App() {
component={LoginPage}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Register"
component={RegisterPage}
options={{ headerShown: false }}
/>
{/* Tela HomeTabs com navbar */}
<Stack.Screen
name="HomeTabs"
Expand Down
177 changes: 177 additions & 0 deletions src/components/PasswordResetModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import React, { useState } from "react";
import { View, Text, TextInput, TouchableOpacity, Modal } from "react-native";
import { FontAwesome } from "@expo/vector-icons";

export default function PasswordResetModal({
modalVisible,
setModalVisible,
Users,
}) {
// Modal State
const [email, setEmail] = useState("");
const [code, setCode] = useState(0);
const [userCode, setUserCode] = useState("");
const [Newpass, setNewPass] = useState("");
const [PassConfirm, setPassConfirm] = useState("");
const [emailForm, setEmailForm] = useState(true);
const [error, setError] = useState(false);
const [PassChangeVal, setPassChangeVal] = useState(false);

//Function to verify email and send code to change password
function SendEmail() {
//Gets user from database
const email_exists = Users.some((user) => user.Email === email);
setCode(Math.floor(1000 + Math.random() * 9000)); // Generate a random 4-digit code

//Sends email with the code and shows new pass form or shows error
if (email_exists) {
// Need to install emailjs-com to send a E-mail
setEmailForm(false);
setError(false);
} else {
setError(true);
}
}

//Function to change password
function ChangePass() {
//Checks if new passwords matches or shows error
if (Newpass === PassConfirm) {
//Checks if the user code is the same send to email or shows error
if (userCode == code) {
setError(false);
setPassChangeVal(true);

// Clear Inputs
setNewPass("");
setPassConfirm("");
setUserCode("");

// Close Modal after success
setTimeout(() => {
setModalVisible(false);
setEmailForm(true);
setPassChangeVal(false);
}, 1000);
} else {
setError(true);
}
} else {
setError(true);
}
}

//Function to close Modal resets modal form and sucsses and error messages
function CloseModal() {
setModalVisible(false);
setEmailForm(true);
setError(false);
setPassChangeVal(false);
}

return (
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
className="relative"
>
{/* Overlay */}
<View className="bg-black opacity-50 absolute w-full h-full top-0"></View>
<View className="h-screen justify-center items-center w-screen px-5">
{/* Modal Content */}
<View className="relative bg-off-white py-20 px-6 flex-col justify-center items-center w-full border-x border-y border-light-gray rounded-lg gap-4">
{/* Email Form */}
{emailForm && (
<View className="w-full gap-4 justify-center items-center">
<Text className="text-2xl font-bold text-yellow">
Insere o teu e-mail
</Text>
<Text className="mb-10">
Vamos te mandar um código para o teu email
</Text>

<TextInput
className="bg-white w-full text-dark-gray border-solid border-x border-y border-light-gray rounded-lg p-4 placeholder:font-bold placeholder:text-xl placeholder:text-light-gray"
onChangeText={setEmail}
value={email}
placeholder="E-mail"
/>
{error && (
<Text className="text-red-500 font-bold">
Este email não está registado
</Text>
)}
<TouchableOpacity
className="bg-yellow rounded-lg w-full py-3 items-center"
onPress={SendEmail}
>
<Text className="text-xl text-white font-bold">Enviar</Text>
</TouchableOpacity>
</View>
)}

{/* New Password Form */}
{!emailForm && (
<View className="w-full gap-4 justify-center items-center">
<Text className="text-2xl font-bold text-yellow mb-10">
Cria a tua nova password
</Text>
<TextInput
secureTextEntry
className="bg-white w-full text-dark-gray border-solid border-x border-y border-light-gray rounded-lg p-4 placeholder:font-bold placeholder:text-xl placeholder:text-light-gray"
onChangeText={setNewPass}
value={Newpass}
placeholder="New Password"
/>
<TextInput
secureTextEntry
className="bg-white w-full text-dark-gray border-solid border-x border-y border-light-gray rounded-lg p-4 placeholder:font-bold placeholder:text-xl placeholder:text-light-gray"
onChangeText={setPassConfirm}
value={PassConfirm}
placeholder="Confirm Password"
/>
<Text>Código</Text>
<TextInput
className="bg-white w-full text-dark-gray border-solid border-x border-y border-light-gray rounded-lg p-4 placeholder:font-bold placeholder:text-xl placeholder:text-light-gray"
keyboardType="numeric"
maxLength={4}
placeholder="Email Code"
onChangeText={setUserCode}
value={userCode}
/>

{error && (
<Text className="text-red-500 font-bold">
Algo não correu bem
</Text>
)}

{PassChangeVal && (
<Text className="text-green-400 font-bold">
Palavra passe mudada com sucesso
</Text>
)}

<TouchableOpacity
className="bg-yellow rounded-lg w-full py-3 items-center"
onPress={ChangePass}
>
<Text className="text-xl text-white font-bold">
Mudar Password
</Text>
</TouchableOpacity>
</View>
)}

<TouchableOpacity
className="ml-2 absolute top-4 right-4"
onPress={CloseModal}
>
<FontAwesome name="close" size={24} color="#fcc766" />
</TouchableOpacity>
</View>
</View>
</Modal>
);
}
34 changes: 34 additions & 0 deletions src/components/SpeechBubble.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from "react";
import { View, Text, TouchableOpacity, Image } from "react-native";
import { useNavigation } from "@react-navigation/native";

export default function SpeechBubble() {
const navigation = useNavigation();
function RedirectToRegister() {
navigation.replace("Register");
}
return (
<View className="flex-row items-center gap-2">
{/* Imagem */}
<Image
className="w-28 h-28"
resizeMode="contain"
source={require("../../assets/Lumi.png")}
/>
{/* Bubble */}
<View className="bg-white px-4 py-6 rounded-2xl relative border border-light-gray">
<Text className="font-normal text-black text-xl text-center">
Ainda não estás registado?
</Text>
<TouchableOpacity>
<Text
className="font-bold text-orange underline underline-offset-1 text-2xl text-center"
onPress={RedirectToRegister}
>
Clica aqui
</Text>
</TouchableOpacity>
</View>
</View>
);
}
138 changes: 132 additions & 6 deletions src/pages/LoginPage.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,136 @@
import React from "react";
import { View, Text } from "react-native";
import React, { useState } from "react";
import { View, Text, TextInput, TouchableOpacity, Image } from "react-native";
import { FontAwesome } from "@expo/vector-icons";
import PasswordResetModal from "../components/PasswordResetModal";
import SpeechBubble from "../components/SpeechBubble";

export default function LoginPage() {
return (
<View className="flex-1 justify-center items-center bg-white">
<Text className="text-xl font-bold">Login</Text>
//DB Simulation
const Users = [
{
id: 0,
User_name: "reistiago",
Pass: "123",
Email: "reistiago64@gmail.com",
Idade: 26,
},
{
id: 1,
User_name: "eng_gracicha",
Pass: "123",
Email: "reistiago64@gmail.com",
Idade: 21,
},
{
id: 2,
User_name: "maezinhaVani",
Pass: "123",
Email: "reistiago64@gmail.com",
Idade: 23,
},
];

//State Variables
const [username, setUname] = useState("");
const [pass, setPass] = useState("");
const [securePass, setSecurePass] = useState(true);
const [modalVisible, setModalVisible] = useState(false);

//Login Form Actions

//Function to clear Login Form
const clearLoginForm = () => {
setUname("");
setPass("");
};

//Function to check if Username exists and if Password corresponds to user in Login Form
function handleLoginForm() {
const user = Users.find((user) => user.User_name === username);

//From Validation
if (username === "" || pass === "") {
console.log("Fill all inputs.");
} else {
if (user != undefined) {
if (user.Pass === pass) {
// !Falta a encriptação da password
console.log(username, pass);
clearLoginForm();
} else {
console.log("Wrong password.");
}
} else {
console.log("Username does not exist.");
}
}
}

return (
<View className="flex-1 bg-off-white">
{/* Modal*/}
<PasswordResetModal
modalVisible={modalVisible}
setModalVisible={setModalVisible}
Users={Users}
/>
{/* Page Title*/}
<View className="h-1/3 justify-center items-center">
<Text className=" text-5xl font-bold text-yellow">Login</Text>
</View>

{/*Form*/}
<View className="w-screen px-16 flex-col gap-6 items-end justify-end">
{/* Input do username */}
<TextInput
className="bg-white w-full text-dark-gray border-solid border-x border-y border-light-gray rounded-lg p-4 placeholder:font-bold placeholder:text-xl placeholder:text-light-gray"
onChangeText={setUname}
value={username}
placeholder="Username"
/>
<View className="w-full relative">
{/* Input da password */}
<TextInput
secureTextEntry={securePass}
className="bg-white w-full text-dark-gray border-solid border border-light-gray rounded-lg p-4 pr-12 placeholder:font-bold placeholder:text-xl placeholder:text-light-gray"
onChangeText={setPass}
value={pass}
placeholder="Password"
/>

{/* Ícone de olho */}
<TouchableOpacity
className="absolute right-4 top-5"
onPress={() => {
setSecurePass(!securePass);
}}
>
<FontAwesome
name={securePass ? "eye-slash" : "eye"}
size={20}
color="#d0d0d0"
/>
</TouchableOpacity>
</View>
);
<TouchableOpacity onPress={() => setModalVisible(true)}>
<Text className="text-dark-gray font-bold underline underline-offset-1">
Esqueceste-te da password?
</Text>
</TouchableOpacity>

{/* Botão do form */}
<TouchableOpacity
className="bg-yellow rounded-lg w-full py-3 items-center mt-10"
onPress={handleLoginForm}
>
<Text className="text-xl text-white font-bold">Entrar</Text>
</TouchableOpacity>
</View>

{/* Register redirect */}
<View className="h-1/3 w-full flex-row items-center justify-center px-10 ">
<SpeechBubble />
</View>
</View>
);
}
12 changes: 12 additions & 0 deletions src/pages/RegisterPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from "react";
import { View, Text } from "react-native";

export default function RegisterPage() {
return (
<>
<View>
<Text>Hello</Text>
</View>
</>
);
}