ecra principal

This commit is contained in:
2026-01-28 18:04:32 +00:00
parent 19c889fcd2
commit 906849e4b7
2 changed files with 96 additions and 52 deletions

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"

View File

@@ -34,8 +34,13 @@ public class MainActivity extends AppCompatActivity {
private static final String PREFS_NAME = "pap_prefs";
private static final String KEY_HAS_CREATED_ACCOUNT = "has_created_account";
public enum AccountType {CLIENTE, ESTABELECIMENTO}
public enum AccountAction {ENTRAR, CRIAR}
public enum AccountType {
CLIENTE, ESTABELECIMENTO
}
public enum AccountAction {
ENTRAR, CRIAR
}
private AccountType selectedAccountType = AccountType.CLIENTE;
private AccountAction selectedAccountAction = AccountAction.ENTRAR;
@@ -184,6 +189,10 @@ public class MainActivity extends AppCompatActivity {
boolean creatingAccount = selectedAccountAction == AccountAction.CRIAR;
if (creatingAccount && !isValidPassword(password)) {
return;
}
if (creatingAccount) {
if (selectedAccountType == AccountType.CLIENTE && TextUtils.isEmpty(providedName)) {
Toast.makeText(this, "Indique o seu nome para criar conta.", Toast.LENGTH_SHORT).show();
@@ -197,7 +206,8 @@ public class MainActivity extends AppCompatActivity {
|| TextUtils.isEmpty(establishmentPhone);
if (missingOwner || missingEstablishment) {
Toast.makeText(this, "Preencha os dados do proprietário e do estabelecimento.", Toast.LENGTH_SHORT).show();
Toast.makeText(this, "Preencha os dados do proprietário e do estabelecimento.", Toast.LENGTH_SHORT)
.show();
return;
}
}
@@ -216,8 +226,7 @@ public class MainActivity extends AppCompatActivity {
establishmentEmail,
establishmentPhone,
fallbackName,
resolvedRole
);
resolvedRole);
return;
}
@@ -277,12 +286,12 @@ public class MainActivity extends AppCompatActivity {
}
firebaseAuth.signInWithEmailAndPassword(email, password)
.addOnSuccessListener(authResult ->
fetchAccountAndNavigate(email, fallbackName, resolvedRole)
)
.addOnFailureListener(e ->
Toast.makeText(this, "Não foi possível iniciar sessão: " + e.getMessage(), Toast.LENGTH_SHORT).show()
);
.addOnSuccessListener(authResult -> fetchAccountAndNavigate(email, fallbackName, resolvedRole))
.addOnFailureListener(e -> {
android.util.Log.e("LoginError", "SignIn failed", e);
Toast.makeText(this, "Não foi possível iniciar sessão: " + e.getMessage(), Toast.LENGTH_SHORT)
.show();
});
}
private void createAccountInFirebase(
@@ -294,8 +303,7 @@ public class MainActivity extends AppCompatActivity {
String establishmentEmail,
String establishmentPhone,
String fallbackName,
String resolvedRole
) {
String resolvedRole) {
if (!ensureFirebaseReady()) {
return;
}
@@ -305,9 +313,10 @@ public class MainActivity extends AppCompatActivity {
if (!hasCreatedAccount) {
markAccountCreated();
}
String finalDisplayName = selectedAccountType == AccountType.ESTABELECIMENTO && !TextUtils.isEmpty(establishmentName)
? establishmentName
: fallbackName;
String finalDisplayName = selectedAccountType == AccountType.ESTABELECIMENTO
&& !TextUtils.isEmpty(establishmentName)
? establishmentName
: fallbackName;
String uid = result.getUser() != null ? result.getUser().getUid() : null;
persistAccountInFirebase(
@@ -327,17 +336,18 @@ public class MainActivity extends AppCompatActivity {
createdScreen.putExtra(EXTRA_ACCOUNT_TYPE, selectedAccountType.name());
createdScreen.putExtra(EXTRA_ROLE, resolvedRole);
startActivity(createdScreen);
}
);
});
})
.addOnFailureListener(e ->
Toast.makeText(this, "Falha ao criar conta: " + e.getMessage(), Toast.LENGTH_SHORT).show()
);
.addOnFailureListener(e -> {
android.util.Log.e("LoginError", "CreateUser failed", e);
Toast.makeText(this, "Falha ao criar conta: " + e.getMessage(), Toast.LENGTH_SHORT).show();
});
}
private void fetchAccountAndNavigate(String email, String fallbackName, String resolvedRole) {
if (firestore == null) {
Toast.makeText(this, "Firebase indisponível.", Toast.LENGTH_SHORT).show();
navigateToDashboard(email, fallbackName, resolvedRole);
return;
}
@@ -347,14 +357,17 @@ public class MainActivity extends AppCompatActivity {
.get()
.addOnSuccessListener(snapshot -> {
if (snapshot == null || !snapshot.exists()) {
Toast.makeText(this, "Conta não encontrada no Firebase.", Toast.LENGTH_SHORT).show();
Toast.makeText(this, "Conta sem perfil na cloud. A entrar em modo básico.", Toast.LENGTH_SHORT)
.show();
navigateToDashboard(email, fallbackName, resolvedRole);
return;
}
String accountTypeInFirebase = snapshot.getString("accountType");
if (accountTypeInFirebase != null
&& !accountTypeInFirebase.equalsIgnoreCase(selectedAccountType.name())) {
Toast.makeText(this, "Tipo de conta não corresponde ao registo no Firebase.", Toast.LENGTH_SHORT).show();
Toast.makeText(this, "Tipo de conta não corresponde ao registo no Firebase.",
Toast.LENGTH_SHORT).show();
return;
}
@@ -366,25 +379,32 @@ public class MainActivity extends AppCompatActivity {
String finalDisplayName = !TextUtils.isEmpty(establishmentName)
? establishmentName
: !TextUtils.isEmpty(displayNameFromDb) ? displayNameFromDb
: !TextUtils.isEmpty(ownerName) ? ownerName
: fallbackName;
: !TextUtils.isEmpty(ownerName) ? ownerName
: fallbackName;
String finalRole = !TextUtils.isEmpty(roleFromDb) ? roleFromDb : resolvedRole;
Intent nextScreen = selectedAccountType == AccountType.CLIENTE
? new Intent(this, ClientDashboardActivity.class)
: new Intent(this, EstablishmentDashboardActivity.class);
nextScreen.putExtra(EXTRA_ACTION_MODE, selectedAccountAction.name());
nextScreen.putExtra(EXTRA_DISPLAY_NAME, finalDisplayName);
nextScreen.putExtra(EXTRA_EMAIL, email);
nextScreen.putExtra(EXTRA_ACCOUNT_TYPE, selectedAccountType.name());
nextScreen.putExtra(EXTRA_ROLE, finalRole);
startActivity(nextScreen);
navigateToDashboard(email, finalDisplayName, finalRole);
})
.addOnFailureListener(e ->
Toast.makeText(this, "Erro ao verificar conta no Firebase.", Toast.LENGTH_SHORT).show()
);
.addOnFailureListener(e -> {
android.util.Log.e("LoginError", "Firestore check failed", e);
Toast.makeText(this, "Falha ao validar perfil na cloud. A entrar em modo básico.",
Toast.LENGTH_SHORT)
.show();
navigateToDashboard(email, fallbackName, resolvedRole);
});
}
private void navigateToDashboard(String email, String displayName, String role) {
Intent nextScreen = selectedAccountType == AccountType.CLIENTE
? new Intent(this, ClientDashboardActivity.class)
: new Intent(this, EstablishmentDashboardActivity.class);
nextScreen.putExtra(EXTRA_ACTION_MODE, selectedAccountAction.name());
nextScreen.putExtra(EXTRA_DISPLAY_NAME, displayName);
nextScreen.putExtra(EXTRA_EMAIL, email);
nextScreen.putExtra(EXTRA_ACCOUNT_TYPE, selectedAccountType.name());
nextScreen.putExtra(EXTRA_ROLE, role);
startActivity(nextScreen);
}
private void persistAccountInFirebase(
@@ -396,8 +416,7 @@ public class MainActivity extends AppCompatActivity {
String establishmentEmail,
String establishmentPhone,
String uid,
Runnable onSuccess
) {
Runnable onSuccess) {
if (firestore == null) {
Toast.makeText(this, "Firebase indisponível.", Toast.LENGTH_SHORT).show();
return;
@@ -426,16 +445,39 @@ public class MainActivity extends AppCompatActivity {
firestore.collection("users")
.document(documentId)
.set(payload, SetOptions.merge())
.addOnSuccessListener(unused ->
{
Toast.makeText(this, "Conta guardada na cloud.", Toast.LENGTH_SHORT).show();
if (onSuccess != null) {
onSuccess.run();
}
}
)
.addOnFailureListener(e ->
Toast.makeText(this, "Não foi possível guardar na cloud.", Toast.LENGTH_SHORT).show()
);
.addOnSuccessListener(unused -> {
Toast.makeText(this, "Conta guardada na cloud.", Toast.LENGTH_SHORT).show();
if (onSuccess != null) {
onSuccess.run();
}
})
.addOnFailureListener(
e -> Toast.makeText(this, "Não foi possível guardar na cloud.", Toast.LENGTH_SHORT).show());
}
private boolean isValidPassword(String password) {
if (password.length() < 6) {
Toast.makeText(this, "A palavra-passe deve ter pelo menos 6 caracteres.", Toast.LENGTH_SHORT).show();
return false;
}
boolean hasLower = false;
boolean hasDigit = false;
boolean hasSpecial = false;
for (char c : password.toCharArray()) {
if (Character.isLowerCase(c))
hasLower = true;
else if (Character.isDigit(c))
hasDigit = true;
else if (!Character.isLetterOrDigit(c))
hasSpecial = true;
}
if (!hasLower || !hasDigit || !hasSpecial) {
Toast.makeText(this, "A palavra-passe deve conter minúsculas, números e símbolos.", Toast.LENGTH_LONG)
.show();
return false;
}
return true;
}
}