diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml new file mode 100644 index 0000000..4a53bee --- /dev/null +++ b/.idea/AndroidProjectSystem.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b86273d --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..b268ef3 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/deviceManager.xml b/.idea/deviceManager.xml new file mode 100644 index 0000000..91f9558 --- /dev/null +++ b/.idea/deviceManager.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..639c779 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..74dd639 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..16660f1 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/.idea/studiobot.xml b/.idea/studiobot.xml new file mode 100644 index 0000000..539e3b8 --- /dev/null +++ b/.idea/studiobot.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6496c1d..a15fd02 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -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) diff --git a/app/google-services.json b/app/google-services.json new file mode 100644 index 0000000..c40df5d --- /dev/null +++ b/app/google-services.json @@ -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" +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 98f4e71..a5fcac4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ + + + + diff --git a/app/src/main/java/com/example/lifegrid/CriarContaActivity.java b/app/src/main/java/com/example/lifegrid/CriarContaActivity.java new file mode 100644 index 0000000..d0b0c40 --- /dev/null +++ b/app/src/main/java/com/example/lifegrid/CriarContaActivity.java @@ -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; + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/lifegrid/LoginActivity.java b/app/src/main/java/com/example/lifegrid/LoginActivity.java index 078370a..d29b8ba 100644 --- a/app/src/main/java/com/example/lifegrid/LoginActivity.java +++ b/app/src/main/java/com/example/lifegrid/LoginActivity.java @@ -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); } } \ No newline at end of file diff --git a/app/src/main/java/com/example/lifegrid/RecupearPasswordActivity.java b/app/src/main/java/com/example/lifegrid/RecupearPasswordActivity.java new file mode 100644 index 0000000..a1b9afc --- /dev/null +++ b/app/src/main/java/com/example/lifegrid/RecupearPasswordActivity.java @@ -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; + }); + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_criar_conta.xml b/app/src/main/res/layout/activity_criar_conta.xml new file mode 100644 index 0000000..6e549d0 --- /dev/null +++ b/app/src/main/res/layout/activity_criar_conta.xml @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + +