Login e Criar conta

This commit is contained in:
2025-12-03 10:33:52 +00:00
parent 5a7ed084f5
commit 8fb4ceef95
22 changed files with 630 additions and 63 deletions

View File

@@ -1,5 +1,6 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.google.gms.google.services)
}
android {
@@ -37,6 +38,12 @@ dependencies {
implementation(libs.material)
implementation(libs.activity)
implementation(libs.constraintlayout)
implementation(libs.firebase.auth)
implementation(libs.credentials)
implementation(libs.credentials.play.services.auth)
implementation(libs.googleid)
implementation(libs.firebase.database)
implementation(libs.recyclerview)
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)

29
app/google-services.json Normal file
View File

@@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "1019731295596",
"project_id": "lifegrid-f6692",
"storage_bucket": "lifegrid-f6692.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:1019731295596:android:7170262ae018291b00c749",
"android_client_info": {
"package_name": "com.example.lifegrid"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyAbQ_-mob81SR07481CSJHP_z3GniS-xdk"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

View File

@@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
@@ -11,6 +13,12 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.LifeGrid">
<activity
android:name=".RecupearPasswordActivity"
android:exported="false" />
<activity
android:name=".CriarContaActivity"
android:exported="false" />
<activity
android:name=".LoginActivity"
android:exported="true">

View File

@@ -0,0 +1,24 @@
package com.example.lifegrid;
import android.os.Bundle;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
public class CriarContaActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_criar_conta);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
}
}

View File

@@ -1,6 +1,15 @@
package com.example.lifegrid;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Patterns;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
@@ -8,8 +17,26 @@ import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.google.firebase.FirebaseApp;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
public class LoginActivity extends AppCompatActivity {
private TextView textView5;
private TextView textView1;
private TextView criarContaTextView;
private TextView emailTextView;
private EditText emailEditText;
private TextView passTextView;
private EditText passwordEditText;
private TextView passesquecerTextView;
private Button loginButton;
private Button googleButton;
private TextView ouTextView;
private ProgressBar loadingProgressBar;
private FirebaseAuth firebaseAuth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -20,6 +47,126 @@ public class LoginActivity extends AppCompatActivity {
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
textView5 = findViewById(R.id.textView5);
textView1 = findViewById(R.id.textView1);
criarContaTextView = findViewById(R.id.criarContaTextView);
emailTextView = findViewById(R.id.emailTextView);
emailEditText = findViewById(R.id.emailEditText);
passTextView = findViewById(R.id.passTextView);
passwordEditText = findViewById(R.id.passwordEditText);
passesquecerTextView = findViewById(R.id.passesquecerTextView);
loginButton = findViewById(R.id.loginButton);
googleButton = findViewById(R.id.googleButton);
ouTextView = findViewById(R.id.ouTextView);
loadingProgressBar = findViewById(R.id.loadingProgressBar);
FirebaseApp.initializeApp(this);
firebaseAuth = FirebaseAuth.getInstance();
loginButton.setOnClickListener(v -> validarLogin());
criarContaTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(LoginActivity.this, CriarContaActivity.class);
startActivity(intent);
}
});
passesquecerTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(LoginActivity.this, RecupearPasswordActivity.class);
startActivity(intent);
}
});
googleButton.setOnClickListener(v ->
Toast.makeText(this, "Login com Google disponível em breve.", Toast.LENGTH_SHORT).show()
);
}
private void validarLogin() {
String email = emailEditText.getText().toString().trim();
String password = passwordEditText.getText().toString();
if (!validarEspaços(email, password)) {
return;
}
toggleLoading(true);
firebaseAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(this, task -> {
toggleLoading(false);
if (task.isSuccessful()) {
FirebaseUser user = task.getResult().getUser();
String welcome = user != null && !TextUtils.isEmpty(user.getEmail())
? "Bem-vindo, " + user.getEmail()
: "Login realizado com sucesso!";
Toast.makeText(this, welcome, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this,
task.getException() != null ? task.getException().getMessage() : "Falha no login",
Toast.LENGTH_LONG).show();
}
});
}
private void recupearPassword() {
String email = emailEditText.getText().toString().trim();
if (TextUtils.isEmpty(email)) {
emailEditText.setError("Informe o email para recuperar a palavra-passe.");
emailEditText.requestFocus();
return;
}
toggleLoading(true);
firebaseAuth.sendPasswordResetEmail(email)
.addOnCompleteListener(this, task -> {
toggleLoading(false);
if (task.isSuccessful()) {
Toast.makeText(this,
"Email de recuperação enviado para " + email,
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this,
task.getException() != null ? task.getException().getMessage() : "Erro ao enviar email",
Toast.LENGTH_LONG).show();
}
});
}
private boolean validarEspaços(String email, String password) {
if (TextUtils.isEmpty(email)) {
emailEditText.setError("Email obrigatório.");
emailEditText.requestFocus();
return false;
}
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
emailEditText.setError("Formato de email inválido.");
emailEditText.requestFocus();
return false;
}
if (TextUtils.isEmpty(password)) {
passwordEditText.setError("Palavra-passe obrigatória.");
passwordEditText.requestFocus();
return false;
}
if (password.length() < 6) {
passwordEditText.setError("Mínimo de 6 caracteres.");
passwordEditText.requestFocus();
return false;
}
return true;
}
private void toggleLoading(boolean show) {
loadingProgressBar.setVisibility(show ? View.VISIBLE : View.GONE);
loginButton.setEnabled(!show);
googleButton.setEnabled(!show);
criarContaTextView.setEnabled(!show);
passesquecerTextView.setEnabled(!show);
}
}

View File

@@ -0,0 +1,24 @@
package com.example.lifegrid;
import android.os.Bundle;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
public class RecupearPasswordActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_recupear_password);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
}
}

View File

@@ -0,0 +1,178 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CriarContaActivity">
<TextView
android:id="@+id/textView7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Começe a gerir as suas finanças hoje"
android:textColor="#8A8484"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.326"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView6" />
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="160dp"
android:text="Criar conta"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.166"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/passwordEditText2"
android:layout_width="336dp"
android:layout_height="47dp"
android:layout_marginTop="8dp"
android:background="@drawable/button_background"
android:ems="10"
android:hint="**********"
android:inputType="textPassword"
android:textSize="15dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView4" />
<EditText
android:id="@+id/passwordEditText3"
android:layout_width="336dp"
android:layout_height="47dp"
android:layout_marginTop="8dp"
android:background="@drawable/button_background"
android:ems="10"
android:hint="**********"
android:inputType="textPassword"
android:textSize="15dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3" />
<EditText
android:id="@+id/emailEditText2"
android:layout_width="338dp"
android:layout_height="49dp"
android:layout_marginTop="8dp"
android:background="@drawable/button_background"
android:ems="10"
android:hint="seu@email.com"
android:inputType="textEmailAddress"
android:textSize="15dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
<EditText
android:id="@+id/emailEditText3"
android:layout_width="338dp"
android:layout_height="49dp"
android:layout_marginTop="8dp"
android:background="@drawable/button_background"
android:ems="10"
android:hint="O seu nome"
android:inputType="textEmailAddress"
android:textSize="15dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.52"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<Button
android:id="@+id/loginButton2"
android:layout_width="315dp"
android:layout_height="50dp"
android:layout_marginTop="35dp"
android:backgroundTint="#050505"
android:text="Criar conta ->"
app:cornerRadius="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passwordEditText2" />
<TextView
android:id="@+id/ouTextView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="22dp"
android:text="_____________________ OU _____________________"
android:textColor="@color/cinza"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/loginButton2" />
<Button
android:id="@+id/googleButton2"
android:layout_width="316dp"
android:layout_height="49dp"
android:layout_marginTop="14dp"
android:backgroundTint="#FFFFFF"
android:text="Continuar com o Google"
android:textColor="#0F0E0E"
app:cornerRadius="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ouTextView2"
app:strokeColor="@color/cinza"
app:strokeWidth="1sp" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="Nome"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.128"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView7" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Email"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.125"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/emailEditText3" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Password"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.134"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/emailEditText2" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Confirmar password"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.159"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passwordEditText3" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -5,33 +5,71 @@
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:backgroundTint="#FFFFFF"
android:background="#FFFFFF"
android:padding="24dp"
tools:context=".LoginActivity">
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="192dp"
android:text="Bem-vindo/a de volta"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.113"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Entre na sua conta para continuar"
android:textColor="#8A8484"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/textView5"
app:layout_constraintTop_toBottomOf="@+id/textView5" />
<TextView
android:id="@+id/emailTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:text="Email"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.057"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView1" />
<Button
android:id="@+id/loginButton"
android:layout_width="308dp"
android:layout_height="52dp"
android:layout_marginTop="10dp"
android:layout_width="315dp"
android:layout_height="50dp"
android:layout_marginTop="28dp"
android:backgroundTint="#050505"
android:text="Entrar ->"
app:cornerRadius="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.495"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passesquecerTextView" />
<Button
android:id="@+id/googleButton"
android:layout_width="308dp"
android:layout_height="52dp"
android:layout_marginTop="4dp"
android:layout_width="316dp"
android:layout_height="49dp"
android:layout_marginTop="8dp"
android:backgroundTint="#FFFFFF"
android:text="Continuar com o Google"
android:textColor="#0F0E0E"
app:cornerRadius="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.495"
app:layout_constraintHorizontal_bias="0.483"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/loginButton"
app:strokeColor="@color/cinza"
@@ -41,63 +79,53 @@
android:id="@+id/ouTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginTop="32dp"
android:text="_____________________ OU _____________________"
android:textColor="@color/cinza"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.495"
app:layout_constraintHorizontal_bias="0.492"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/googleButton" />
<EditText
android:id="@+id/passwordEditText"
android:layout_width="303dp"
android:layout_height="48dp"
android:layout_marginTop="8dp"
android:layout_width="336dp"
android:layout_height="47dp"
android:layout_marginTop="16dp"
android:background="@drawable/button_background"
android:ems="10"
android:hint="**********"
android:inputType="textPassword"
android:textSize="15dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.444"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passTextView" />
<EditText
android:id="@+id/emailEditText"
android:layout_width="303dp"
android:layout_height="48dp"
android:layout_marginTop="8dp"
android:layout_width="338dp"
android:layout_height="49dp"
android:layout_marginTop="16dp"
android:background="@drawable/button_background"
android:ems="10"
android:hint="seu@email.com"
android:inputType="textPassword"
android:inputType="textEmailAddress"
android:textSize="15dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.48"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/emailTextView" />
<TextView
android:id="@+id/emailTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Email"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.149"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView1" />
<TextView
android:id="@+id/passTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginTop="20dp"
android:text="Password"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.159"
app:layout_constraintHorizontal_bias="0.061"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/emailEditText" />
@@ -105,44 +133,35 @@
android:id="@+id/passesquecerTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginTop="12dp"
android:text="Esqueceu-se a palavra passe?"
android:textSize="11dp"
android:textSize="13sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passwordEditText" />
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Bem-vindo/a de volta "
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.27"
app:layout_constraintStart_toStartOf="parent"
tools:layout_editor_absoluteY="179dp" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Entre na sua conta para continuar"
android:textColor="#8A8484"
android:textSize="15sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.303"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView5" />
<TextView
android:id="@+id/textView7"
android:id="@+id/criarContaTextView"
android:layout_width="181dp"
android:layout_height="24dp"
android:text="Não tens conta? Cria Conta"
tools:layout_editor_absoluteX="115dp"
tools:layout_editor_absoluteY="603dp" />
android:layout_marginTop="32dp"
android:text="Não tens conta? Clica aqui"
android:textColor="#121111"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ouTextView" />
<ProgressBar
android:id="@+id/loadingProgressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@+id/criarContaTextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".RecupearPasswordActivity">
</androidx.constraintlayout.widget.ConstraintLayout>