346 lines
14 KiB
Java
346 lines
14 KiB
Java
package com.example.bem;
|
|
|
|
import android.app.AlertDialog;
|
|
import android.content.Intent;
|
|
import android.content.SharedPreferences;
|
|
import android.os.Bundle;
|
|
import android.text.TextUtils;
|
|
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.appcompat.app.AppCompatDelegate;
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
import com.google.firebase.auth.FirebaseAuth;
|
|
import com.google.firebase.auth.FirebaseUser;
|
|
import com.google.firebase.firestore.FirebaseFirestore;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
public class LoginActivity extends AppCompatActivity {
|
|
|
|
private FirebaseAuth mAuth;
|
|
private FirebaseFirestore db;
|
|
private SharedPreferences prefs;
|
|
private static final String PREF_DARK_MODE = "dark_mode";
|
|
|
|
private EditText inputEmail;
|
|
private EditText inputPassword;
|
|
private EditText inputName;
|
|
private EditText inputPhone;
|
|
private Button btnLogin;
|
|
private TextView textLoginType;
|
|
private TextView textSwitchMode;
|
|
private TextView textForgotPassword;
|
|
private TextView textSwitchToGuardian;
|
|
private ProgressBar progressBar;
|
|
|
|
private boolean isRegisterMode = false;
|
|
private boolean isGuardianMode = false;
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
|
|
prefs = getSharedPreferences("app_prefs", MODE_PRIVATE);
|
|
applyThemeFromPrefs();
|
|
|
|
mAuth = FirebaseAuth.getInstance();
|
|
db = FirebaseFirestore.getInstance();
|
|
|
|
if (mAuth.getCurrentUser() != null) {
|
|
mAuth.signOut();
|
|
}
|
|
|
|
setContentView(R.layout.activity_login);
|
|
|
|
inputEmail = findViewById(R.id.inputEmail);
|
|
inputPassword = findViewById(R.id.inputPassword);
|
|
inputName = findViewById(R.id.inputName);
|
|
inputPhone = findViewById(R.id.inputPhone);
|
|
btnLogin = findViewById(R.id.btnLogin);
|
|
textLoginType = findViewById(R.id.textLoginType);
|
|
textSwitchMode = findViewById(R.id.textSwitchMode);
|
|
textForgotPassword = findViewById(R.id.textForgotPassword);
|
|
textSwitchToGuardian = findViewById(R.id.textSwitchToGuardian);
|
|
|
|
btnLogin.setOnClickListener(v -> handleLogin());
|
|
textSwitchMode.setOnClickListener(v -> toggleMode());
|
|
textForgotPassword.setOnClickListener(v -> showForgotPasswordDialog());
|
|
textSwitchToGuardian.setOnClickListener(v -> switchToGuardianMode());
|
|
}
|
|
|
|
private void switchToGuardianMode() {
|
|
isGuardianMode = !isGuardianMode;
|
|
|
|
if (isGuardianMode) {
|
|
textLoginType.setText("Login de Responsável");
|
|
textSwitchToGuardian.setText("👤 Sou Utilizador");
|
|
inputPhone.setVisibility(View.VISIBLE);
|
|
inputPhone.setHint("Número de telemóvel");
|
|
} else {
|
|
textLoginType.setText("Login de Utilizador");
|
|
textSwitchToGuardian.setText("🔒 Sou Responsável");
|
|
inputPhone.setVisibility(View.GONE);
|
|
}
|
|
|
|
isRegisterMode = false;
|
|
updateUI();
|
|
}
|
|
|
|
private void toggleMode() {
|
|
isRegisterMode = !isRegisterMode;
|
|
updateUI();
|
|
}
|
|
|
|
private void updateUI() {
|
|
if (isRegisterMode) {
|
|
btnLogin.setText("Criar Conta");
|
|
textSwitchMode.setText("Já tem conta? Entrar");
|
|
inputName.setVisibility(View.VISIBLE);
|
|
|
|
if (isGuardianMode) {
|
|
inputPhone.setVisibility(View.VISIBLE);
|
|
}
|
|
} else {
|
|
btnLogin.setText("Entrar");
|
|
textSwitchMode.setText("Não tem conta? Registar");
|
|
inputName.setVisibility(View.GONE);
|
|
|
|
if (!isGuardianMode) {
|
|
inputPhone.setVisibility(View.GONE);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void handleLogin() {
|
|
String email = inputEmail.getText().toString().trim();
|
|
String password = inputPassword.getText().toString().trim();
|
|
String name = inputName.getText().toString().trim();
|
|
String phone = inputPhone.getText().toString().trim();
|
|
|
|
if (TextUtils.isEmpty(email)) {
|
|
inputEmail.setError("Insira o email");
|
|
return;
|
|
}
|
|
|
|
if (!android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
|
|
inputEmail.setError("Email inválido");
|
|
return;
|
|
}
|
|
|
|
if (TextUtils.isEmpty(password)) {
|
|
inputPassword.setError("Insira a palavra-passe");
|
|
return;
|
|
}
|
|
|
|
if (password.length() < 6) {
|
|
inputPassword.setError("Mínimo 6 caracteres");
|
|
return;
|
|
}
|
|
|
|
if (isRegisterMode && TextUtils.isEmpty(name)) {
|
|
inputName.setError("Insira o nome");
|
|
return;
|
|
}
|
|
|
|
btnLogin.setEnabled(false);
|
|
|
|
if (isRegisterMode) {
|
|
registerUser(email, password, name, phone);
|
|
} else {
|
|
loginUser(email, password);
|
|
}
|
|
}
|
|
|
|
private void registerUser(String email, String password, String name, String phone) {
|
|
mAuth.createUserWithEmailAndPassword(email, password)
|
|
.addOnCompleteListener(task -> {
|
|
if (task.isSuccessful()) {
|
|
FirebaseUser user = mAuth.getCurrentUser();
|
|
if (user != null) {
|
|
saveUserData(user.getUid(), email, name, phone, true);
|
|
} else {
|
|
btnLogin.setEnabled(true);
|
|
Toast.makeText(this, "Erro ao obter utilizador. Tente entrar com o email/senha.",
|
|
Toast.LENGTH_LONG).show();
|
|
mAuth.signOut();
|
|
}
|
|
} else {
|
|
btnLogin.setEnabled(true);
|
|
String error = task.getException() != null ? task.getException().getMessage()
|
|
: "Erro desconhecido";
|
|
Toast.makeText(this, "Erro: " + error, Toast.LENGTH_LONG).show();
|
|
}
|
|
});
|
|
}
|
|
|
|
private void saveUserData(String uid, String email, String name, String phone, boolean fromRegister) {
|
|
Map<String, Object> userData = new HashMap<>();
|
|
userData.put("email", email);
|
|
userData.put("name", name);
|
|
userData.put("phone", phone != null ? phone : "");
|
|
userData.put("type", isGuardianMode ? "guardian" : "user");
|
|
userData.put("createdAt", System.currentTimeMillis());
|
|
|
|
db.collection("users").document(uid)
|
|
.set(userData)
|
|
.addOnSuccessListener(aVoid -> {
|
|
if (fromRegister) {
|
|
Toast.makeText(this, "✓ Conta criada! Faça login para continuar.", Toast.LENGTH_LONG).show();
|
|
mAuth.signOut();
|
|
btnLogin.setEnabled(true);
|
|
// Recarrega a tela limpa
|
|
Intent intent = getIntent();
|
|
finish();
|
|
startActivity(intent);
|
|
} else {
|
|
redirectToApp();
|
|
}
|
|
})
|
|
.addOnFailureListener(e -> {
|
|
btnLogin.setEnabled(true);
|
|
Toast.makeText(this, "Erro ao salvar dados: " + e.getMessage(), Toast.LENGTH_LONG).show();
|
|
});
|
|
}
|
|
|
|
private void loginUser(String email, String password) {
|
|
mAuth.signInWithEmailAndPassword(email, password)
|
|
.addOnCompleteListener(task -> {
|
|
if (task.isSuccessful()) {
|
|
FirebaseUser user = mAuth.getCurrentUser();
|
|
if (user != null) {
|
|
checkUserTypeAndRedirect(user.getUid());
|
|
} else {
|
|
btnLogin.setEnabled(true);
|
|
Toast.makeText(this, "Erro ao iniciar sessão. Tente novamente.", Toast.LENGTH_LONG).show();
|
|
}
|
|
} else {
|
|
btnLogin.setEnabled(true);
|
|
String error = task.getException() != null ? task.getException().getMessage()
|
|
: "Credenciais inválidas";
|
|
Toast.makeText(this, "Erro: " + error, Toast.LENGTH_LONG).show();
|
|
}
|
|
});
|
|
}
|
|
|
|
private void checkUserTypeAndRedirect(String uid) {
|
|
db.collection("users").document(uid)
|
|
.get()
|
|
.addOnSuccessListener(document -> {
|
|
if (document.exists()) {
|
|
String type = document.getString("type");
|
|
prefs.edit()
|
|
.putString("user_type", type != null ? type : "user")
|
|
.putString("user_name", document.getString("name"))
|
|
.apply();
|
|
|
|
if ("guardian".equals(type)) {
|
|
java.util.List<String> managedUsers = (java.util.List<String>) document.get("managedUsers");
|
|
|
|
if (managedUsers != null && !managedUsers.isEmpty()) {
|
|
redirectToApp();
|
|
} else {
|
|
Intent intent = new Intent(LoginActivity.this, InviteCodeActivity.class);
|
|
intent.putExtra("is_guardian", true);
|
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
|
startActivity(intent);
|
|
finish();
|
|
}
|
|
} else {
|
|
redirectToApp();
|
|
}
|
|
} else {
|
|
// Se o perfil não existe, cria um com base no modo de login atual.
|
|
FirebaseUser user = mAuth.getCurrentUser();
|
|
String email = user != null ? user.getEmail() : "";
|
|
String name = (email != null && email.contains("@")) ? email.substring(0, email.indexOf("@")) : "Utilizador";
|
|
String userType = isGuardianMode ? "guardian" : "user";
|
|
|
|
Map<String, Object> userData = new HashMap<>();
|
|
userData.put("email", email);
|
|
userData.put("name", name);
|
|
userData.put("phone", "");
|
|
userData.put("type", userType);
|
|
userData.put("createdAt", System.currentTimeMillis());
|
|
|
|
db.collection("users").document(uid)
|
|
.set(userData)
|
|
.addOnSuccessListener(aVoid -> {
|
|
prefs.edit()
|
|
.putString("user_type", userType)
|
|
.putString("user_name", name)
|
|
.apply();
|
|
|
|
if ("guardian".equals(userType)) {
|
|
Intent intent = new Intent(LoginActivity.this, InviteCodeActivity.class);
|
|
intent.putExtra("is_guardian", true);
|
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
|
startActivity(intent);
|
|
finish();
|
|
} else {
|
|
redirectToApp();
|
|
}
|
|
})
|
|
.addOnFailureListener(e -> {
|
|
Toast.makeText(this, "Erro ao criar perfil: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
|
btnLogin.setEnabled(true);
|
|
});
|
|
}
|
|
})
|
|
.addOnFailureListener(e -> {
|
|
Toast.makeText(this, "Erro ao carregar dados do utilizador: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
|
btnLogin.setEnabled(true);
|
|
});
|
|
}
|
|
|
|
private void redirectToApp() {
|
|
Intent intent = new Intent(this, MainActivity.class);
|
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
|
startActivity(intent);
|
|
finish();
|
|
}
|
|
|
|
private void showForgotPasswordDialog() {
|
|
View dialogView = getLayoutInflater().inflate(android.R.layout.simple_list_item_1, null);
|
|
EditText emailInput = new EditText(this);
|
|
emailInput.setHint("Email de recuperação");
|
|
emailInput.setInputType(android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
|
|
emailInput.setPadding(50, 40, 50, 40);
|
|
|
|
new AlertDialog.Builder(this)
|
|
.setTitle("Recuperar Palavra-passe")
|
|
.setMessage("Insira o email para receber o link de recuperação:")
|
|
.setView(emailInput)
|
|
.setPositiveButton("Enviar", (dialog, which) -> {
|
|
String email = emailInput.getText().toString().trim();
|
|
if (TextUtils.isEmpty(email)) {
|
|
Toast.makeText(this, "Insira um email", Toast.LENGTH_SHORT).show();
|
|
return;
|
|
}
|
|
|
|
mAuth.sendPasswordResetEmail(email)
|
|
.addOnSuccessListener(aVoid -> {
|
|
Toast.makeText(this, "✓ Email enviado! Verifique a caixa de entrada.",
|
|
Toast.LENGTH_LONG).show();
|
|
})
|
|
.addOnFailureListener(e -> {
|
|
Toast.makeText(this, "Erro: " + e.getMessage(), Toast.LENGTH_LONG).show();
|
|
});
|
|
})
|
|
.setNegativeButton("Cancelar", null)
|
|
.show();
|
|
}
|
|
|
|
private void applyThemeFromPrefs() {
|
|
boolean dark = getSharedPreferences("app_prefs", MODE_PRIVATE).getBoolean(PREF_DARK_MODE, false);
|
|
AppCompatDelegate
|
|
.setDefaultNightMode(dark ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO);
|
|
}
|
|
}
|