janeiro
This commit is contained in:
19
.idea/deploymentTargetSelector.xml
generated
19
.idea/deploymentTargetSelector.xml
generated
@@ -4,14 +4,27 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2025-12-02T16:07:28.813132Z">
|
<DropdownSelection timestamp="2025-12-14T18:12:56.139375400Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="LocalEmulator" identifier="path=/Users/230410/.android/avd/Pixel_9_Pro.avd" />
|
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\lucas\.android\avd\Pixel_9_Pro.avd" />
|
||||||
</handle>
|
</handle>
|
||||||
</Target>
|
</Target>
|
||||||
</DropdownSelection>
|
</DropdownSelection>
|
||||||
<DialogSelection />
|
<DialogSelection>
|
||||||
|
<targets>
|
||||||
|
<Target type="DEFAULT_BOOT">
|
||||||
|
<handle>
|
||||||
|
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\lucas\.android\avd\Pixel_9_Pro.avd" />
|
||||||
|
</handle>
|
||||||
|
</Target>
|
||||||
|
<Target type="DEFAULT_BOOT">
|
||||||
|
<handle>
|
||||||
|
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\lucas\.android\avd\Medium_Phone.avd" />
|
||||||
|
</handle>
|
||||||
|
</Target>
|
||||||
|
</targets>
|
||||||
|
</DialogSelection>
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
1
.idea/misc.xml
generated
1
.idea/misc.xml
generated
@@ -1,4 +1,3 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||||
|
|||||||
@@ -36,6 +36,10 @@
|
|||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".GenerateCodeActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".InviteCodeActivity"
|
android:name=".InviteCodeActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|||||||
115
app/src/main/java/com/example/bem/GenerateCodeActivity.java
Normal file
115
app/src/main/java/com/example/bem/GenerateCodeActivity.java
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
package com.example.bem;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.CountDownTimer;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
|
import com.google.firebase.firestore.FirebaseFirestore;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class GenerateCodeActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private FirebaseFirestore db;
|
||||||
|
private FirebaseAuth mAuth;
|
||||||
|
|
||||||
|
private TextView textCode;
|
||||||
|
private TextView textTimer;
|
||||||
|
private Button btnGenerate;
|
||||||
|
private ProgressBar progressBar;
|
||||||
|
|
||||||
|
private CountDownTimer countDownTimer;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_generate_code);
|
||||||
|
|
||||||
|
db = FirebaseFirestore.getInstance();
|
||||||
|
mAuth = FirebaseAuth.getInstance();
|
||||||
|
|
||||||
|
textCode = findViewById(R.id.text_code);
|
||||||
|
textTimer = findViewById(R.id.text_timer);
|
||||||
|
btnGenerate = findViewById(R.id.btn_generate_code);
|
||||||
|
progressBar = findViewById(R.id.progress_bar);
|
||||||
|
|
||||||
|
btnGenerate.setOnClickListener(v -> generateCode());
|
||||||
|
|
||||||
|
generateCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateCode() {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
String userId = mAuth.getCurrentUser().getUid();
|
||||||
|
if (userId == null) {
|
||||||
|
Toast.makeText(this, "Erro: Utilizador não autenticado.", Toast.LENGTH_SHORT).show();
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String code = String.format("%06d", new Random().nextInt(999999));
|
||||||
|
|
||||||
|
Map<String, Object> codeData = new HashMap<>();
|
||||||
|
codeData.put("userId", userId);
|
||||||
|
codeData.put("createdAt", System.currentTimeMillis());
|
||||||
|
|
||||||
|
db.collection("inviteCodes").document(code)
|
||||||
|
.set(codeData)
|
||||||
|
.addOnSuccessListener(aVoid -> {
|
||||||
|
textCode.setText(code);
|
||||||
|
startTimer();
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
.addOnFailureListener(e -> {
|
||||||
|
Toast.makeText(GenerateCodeActivity.this, "Falha ao gerar o código.", Toast.LENGTH_SHORT).show();
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startTimer() {
|
||||||
|
if (countDownTimer != null) {
|
||||||
|
countDownTimer.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
countDownTimer = new CountDownTimer(30000, 1000) {
|
||||||
|
@Override
|
||||||
|
public void onTick(long millisUntilFinished) {
|
||||||
|
textTimer.setText(String.format("Expira em %d segundos", millisUntilFinished / 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
textTimer.setText("Código expirado");
|
||||||
|
textCode.setText("------");
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean isLoading) {
|
||||||
|
if (isLoading) {
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
btnGenerate.setEnabled(false);
|
||||||
|
} else {
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
btnGenerate.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if (countDownTimer != null) {
|
||||||
|
countDownTimer.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,44 +2,29 @@ package com.example.bem;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.CountDownTimer;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
import com.google.firebase.auth.FirebaseAuth;
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
|
import com.google.firebase.auth.FirebaseUser;
|
||||||
import com.google.firebase.firestore.FieldValue;
|
import com.google.firebase.firestore.FieldValue;
|
||||||
import com.google.firebase.firestore.FirebaseFirestore;
|
import com.google.firebase.firestore.FirebaseFirestore;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class InviteCodeActivity extends AppCompatActivity {
|
public class InviteCodeActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private EditText inputCode;
|
||||||
|
private Button btnContinue;
|
||||||
|
private ProgressBar progressBar;
|
||||||
|
|
||||||
private FirebaseAuth mAuth;
|
private FirebaseAuth mAuth;
|
||||||
private FirebaseFirestore db;
|
private FirebaseFirestore db;
|
||||||
|
|
||||||
private LinearLayout layoutGenerateCode;
|
|
||||||
private LinearLayout layoutEnterCode;
|
|
||||||
private TextView textInviteCode;
|
|
||||||
private TextView textCountdown;
|
|
||||||
private TextView textModeDescription;
|
|
||||||
private Button btnGenerateCode;
|
|
||||||
private EditText inputInviteCode;
|
|
||||||
private Button btnValidateCode;
|
|
||||||
private Button btnBack;
|
|
||||||
|
|
||||||
private String currentCode = null;
|
|
||||||
private CountDownTimer countDownTimer;
|
|
||||||
private boolean isGuardianMode = false;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -48,201 +33,77 @@ public class InviteCodeActivity extends AppCompatActivity {
|
|||||||
mAuth = FirebaseAuth.getInstance();
|
mAuth = FirebaseAuth.getInstance();
|
||||||
db = FirebaseFirestore.getInstance();
|
db = FirebaseFirestore.getInstance();
|
||||||
|
|
||||||
layoutGenerateCode = findViewById(R.id.layoutGenerateCode);
|
inputCode = findViewById(R.id.input_invite_code);
|
||||||
layoutEnterCode = findViewById(R.id.layoutEnterCode);
|
btnContinue = findViewById(R.id.btn_validate_code);
|
||||||
textInviteCode = findViewById(R.id.textInviteCode);
|
progressBar = findViewById(R.id.progress_bar_invite);
|
||||||
textCountdown = findViewById(R.id.textCountdown);
|
|
||||||
textModeDescription = findViewById(R.id.textModeDescription);
|
|
||||||
btnGenerateCode = findViewById(R.id.btnGenerateCode);
|
|
||||||
inputInviteCode = findViewById(R.id.inputInviteCode);
|
|
||||||
btnValidateCode = findViewById(R.id.btnValidateCode);
|
|
||||||
btnBack = findViewById(R.id.btnBack);
|
|
||||||
|
|
||||||
isGuardianMode = getIntent().getBooleanExtra("is_guardian", false);
|
btnContinue.setOnClickListener(v -> validateInviteCode());
|
||||||
|
|
||||||
if (isGuardianMode) {
|
|
||||||
textModeDescription.setText("Insira o código do utilizador para se vincular como responsável");
|
|
||||||
layoutGenerateCode.setVisibility(View.GONE);
|
|
||||||
layoutEnterCode.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
textModeDescription.setText("Gere um código temporário para vincular responsável");
|
|
||||||
layoutGenerateCode.setVisibility(View.VISIBLE);
|
|
||||||
layoutEnterCode.setVisibility(View.GONE);
|
|
||||||
generateCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
btnGenerateCode.setOnClickListener(v -> generateCode());
|
|
||||||
btnValidateCode.setOnClickListener(v -> validateCode());
|
|
||||||
btnBack.setOnClickListener(v -> finish());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateCode() {
|
private void validateInviteCode() {
|
||||||
if (mAuth.getCurrentUser() == null) {
|
String code = inputCode.getText().toString().trim();
|
||||||
Toast.makeText(this, "Erro: Não autenticado", Toast.LENGTH_SHORT).show();
|
FirebaseUser currentUser = mAuth.getCurrentUser();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String code = String.format("%06d", new Random().nextInt(999999));
|
|
||||||
currentCode = code;
|
|
||||||
textInviteCode.setText(code);
|
|
||||||
|
|
||||||
String userId = mAuth.getCurrentUser().getUid();
|
|
||||||
Map<String, Object> codeData = new HashMap<>();
|
|
||||||
codeData.put("code", code);
|
|
||||||
codeData.put("userId", userId);
|
|
||||||
codeData.put("createdAt", System.currentTimeMillis());
|
|
||||||
codeData.put("expiresAt", System.currentTimeMillis() + 30000);
|
|
||||||
codeData.put("used", false);
|
|
||||||
|
|
||||||
db.collection("inviteCodes").document(code)
|
|
||||||
.set(codeData)
|
|
||||||
.addOnSuccessListener(aVoid -> {
|
|
||||||
startCountdown();
|
|
||||||
Toast.makeText(this, "✓ Código gerado! Válido por 30 segundos", Toast.LENGTH_SHORT).show();
|
|
||||||
})
|
|
||||||
.addOnFailureListener(e -> {
|
|
||||||
Toast.makeText(this, "Erro ao gerar código: " + e.getMessage(), Toast.LENGTH_LONG).show();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startCountdown() {
|
|
||||||
if (countDownTimer != null) {
|
|
||||||
countDownTimer.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
countDownTimer = new CountDownTimer(30000, 1000) {
|
|
||||||
@Override
|
|
||||||
public void onTick(long millisUntilFinished) {
|
|
||||||
int seconds = (int) (millisUntilFinished / 1000);
|
|
||||||
textCountdown.setText("Expira em: " + seconds + "s");
|
|
||||||
|
|
||||||
if (seconds <= 10) {
|
|
||||||
textCountdown.setTextColor(getResources().getColor(android.R.color.holo_red_dark));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFinish() {
|
|
||||||
textCountdown.setText("Código expirado");
|
|
||||||
textInviteCode.setText("------");
|
|
||||||
currentCode = null;
|
|
||||||
|
|
||||||
btnGenerateCode.setEnabled(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
countDownTimer.start();
|
|
||||||
btnGenerateCode.setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateCode() {
|
|
||||||
String code = inputInviteCode.getText().toString().trim();
|
|
||||||
|
|
||||||
if (TextUtils.isEmpty(code) || code.length() != 6) {
|
if (TextUtils.isEmpty(code) || code.length() != 6) {
|
||||||
inputInviteCode.setError("Código deve ter 6 dígitos");
|
inputCode.setError("O código deve ter 6 dígitos.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAuth.getCurrentUser() == null) {
|
if (currentUser == null) {
|
||||||
Toast.makeText(this, "Erro: Não autenticado", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "Erro: Sessão inválida. Faça login novamente.", Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
btnValidateCode.setEnabled(false);
|
setLoading(true);
|
||||||
|
|
||||||
db.collection("inviteCodes").document(code)
|
// 1. Encontrar o código na coleção 'inviteCodes'
|
||||||
.get()
|
db.collection("inviteCodes").document(code).get().addOnSuccessListener(documentSnapshot -> {
|
||||||
.addOnSuccessListener(document -> {
|
if (!documentSnapshot.exists()) {
|
||||||
if (!document.exists()) {
|
showError("Código inválido ou expirado.");
|
||||||
btnValidateCode.setEnabled(true);
|
return;
|
||||||
Toast.makeText(this, "❌ Código inválido", Toast.LENGTH_SHORT).show();
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Boolean used = document.getBoolean("used");
|
String patientId = documentSnapshot.getString("userId");
|
||||||
Long expiresAt = document.getLong("expiresAt");
|
if (patientId == null) {
|
||||||
String targetUserId = document.getString("userId");
|
showError("Erro no código. Tente gerar um novo.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (used != null && used) {
|
String guardianId = currentUser.getUid();
|
||||||
btnValidateCode.setEnabled(true);
|
|
||||||
Toast.makeText(this, "❌ Código já utilizado", Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expiresAt != null && System.currentTimeMillis() > expiresAt) {
|
// 2. Atualizar o perfil do paciente para adicionar o ID do responsável
|
||||||
btnValidateCode.setEnabled(true);
|
db.collection("users").document(patientId)
|
||||||
Toast.makeText(this, "❌ Código expirado", Toast.LENGTH_SHORT).show();
|
.update("guardianId", guardianId)
|
||||||
return;
|
.addOnSuccessListener(aVoid -> {
|
||||||
}
|
|
||||||
|
|
||||||
linkGuardianToUser(code, targetUserId);
|
// 3. Atualizar o perfil do responsável para adicionar o ID do paciente
|
||||||
})
|
db.collection("users").document(guardianId)
|
||||||
.addOnFailureListener(e -> {
|
.update("managedUsers", FieldValue.arrayUnion(patientId))
|
||||||
btnValidateCode.setEnabled(true);
|
.addOnSuccessListener(aVoid1 -> {
|
||||||
Toast.makeText(this, "Erro: " + e.getMessage(), Toast.LENGTH_LONG).show();
|
|
||||||
});
|
// 4. Apagar o código de convite para que não seja reutilizado
|
||||||
|
db.collection("inviteCodes").document(code).delete();
|
||||||
|
|
||||||
|
Toast.makeText(this, "Utilizador associado com sucesso!", Toast.LENGTH_LONG).show();
|
||||||
|
Intent intent = new Intent(this, MainActivity.class);
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
|
||||||
|
}).addOnFailureListener(e -> showError("Falha ao atualizar o seu perfil. Tente novamente."));
|
||||||
|
|
||||||
|
}).addOnFailureListener(e -> showError("Falha ao associar. Verifique se o utilizador já tem um responsável."));
|
||||||
|
|
||||||
|
}).addOnFailureListener(e -> showError("Erro ao validar o código. Verifique a sua ligação."));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void linkGuardianToUser(String code, String targetUserId) {
|
private void setLoading(boolean loading) {
|
||||||
String guardianId = mAuth.getCurrentUser().getUid();
|
progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
btnContinue.setEnabled(!loading);
|
||||||
Map<String, Object> linkData = new HashMap<>();
|
|
||||||
linkData.put("guardianId", guardianId);
|
|
||||||
linkData.put("linkedAt", System.currentTimeMillis());
|
|
||||||
|
|
||||||
// 1. Update the Target User's document (Add guardian to their list)
|
|
||||||
db.collection("users").document(targetUserId)
|
|
||||||
.update("guardians", FieldValue.arrayUnion(guardianId))
|
|
||||||
.addOnSuccessListener(aVoid -> {
|
|
||||||
|
|
||||||
// 2. Update the Guardian's document (Add target user to their list)
|
|
||||||
db.collection("users").document(guardianId)
|
|
||||||
.update("managedUsers", FieldValue.arrayUnion(targetUserId))
|
|
||||||
.addOnSuccessListener(aVoid2 -> {
|
|
||||||
|
|
||||||
// 3. Mark code as used
|
|
||||||
db.collection("inviteCodes").document(code)
|
|
||||||
.update("used", true)
|
|
||||||
.addOnSuccessListener(aVoid3 -> {
|
|
||||||
Toast.makeText(this, "✓ Vinculado com sucesso!", Toast.LENGTH_LONG).show();
|
|
||||||
|
|
||||||
Intent intent = new Intent(this, MainActivity.class);
|
|
||||||
intent.setFlags(
|
|
||||||
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
})
|
|
||||||
.addOnFailureListener(e -> {
|
|
||||||
// Even if marking code fails, the link is done.
|
|
||||||
// But ideally we should handle this. For now, proceeding.
|
|
||||||
Intent intent = new Intent(this, MainActivity.class);
|
|
||||||
intent.setFlags(
|
|
||||||
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
|
|
||||||
})
|
|
||||||
.addOnFailureListener(e -> {
|
|
||||||
// If updating guardian fails, we should probably revert or warn.
|
|
||||||
// For MVP/Simple app: Log and warn.
|
|
||||||
btnValidateCode.setEnabled(true);
|
|
||||||
Toast.makeText(this, "Erro ao atualizar perfil do responsável: " + e.getMessage(),
|
|
||||||
Toast.LENGTH_LONG).show();
|
|
||||||
});
|
|
||||||
|
|
||||||
})
|
|
||||||
.addOnFailureListener(e -> {
|
|
||||||
btnValidateCode.setEnabled(true);
|
|
||||||
Toast.makeText(this, "Erro ao vincular: " + e.getMessage(), Toast.LENGTH_LONG).show();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void showError(String message) {
|
||||||
protected void onDestroy() {
|
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
|
||||||
super.onDestroy();
|
setLoading(false);
|
||||||
if (countDownTimer != null) {
|
|
||||||
countDownTimer.cancel();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
mAuth = FirebaseAuth.getInstance();
|
mAuth = FirebaseAuth.getInstance();
|
||||||
db = FirebaseFirestore.getInstance();
|
db = FirebaseFirestore.getInstance();
|
||||||
|
|
||||||
// Forçar login sempre que abrir a app: faz signOut se já existir sessão
|
|
||||||
if (mAuth.getCurrentUser() != null) {
|
if (mAuth.getCurrentUser() != null) {
|
||||||
mAuth.signOut();
|
mAuth.signOut();
|
||||||
}
|
}
|
||||||
@@ -242,13 +241,11 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
.apply();
|
.apply();
|
||||||
|
|
||||||
if ("guardian".equals(type)) {
|
if ("guardian".equals(type)) {
|
||||||
// Verifies if guardian is already linked to a user
|
|
||||||
java.util.List<String> managedUsers = (java.util.List<String>) document.get("managedUsers");
|
java.util.List<String> managedUsers = (java.util.List<String>) document.get("managedUsers");
|
||||||
|
|
||||||
if (managedUsers != null && !managedUsers.isEmpty()) {
|
if (managedUsers != null && !managedUsers.isEmpty()) {
|
||||||
redirectToApp();
|
redirectToApp();
|
||||||
} else {
|
} else {
|
||||||
// If not linked, redirect to enter access code
|
|
||||||
Intent intent = new Intent(LoginActivity.this, InviteCodeActivity.class);
|
Intent intent = new Intent(LoginActivity.this, InviteCodeActivity.class);
|
||||||
intent.putExtra("is_guardian", true);
|
intent.putExtra("is_guardian", true);
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
@@ -259,37 +256,45 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
redirectToApp();
|
redirectToApp();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Se o documento não existir (ex.: registo antigo sem salvar), cria um básico
|
// Se o perfil não existe, cria um com base no modo de login atual.
|
||||||
FirebaseUser user = mAuth.getCurrentUser();
|
FirebaseUser user = mAuth.getCurrentUser();
|
||||||
String email = user != null ? user.getEmail() : "";
|
String email = user != null ? user.getEmail() : "";
|
||||||
String name = (email != null && email.contains("@")) ? email.substring(0, email.indexOf("@"))
|
String name = (email != null && email.contains("@")) ? email.substring(0, email.indexOf("@")) : "Utilizador";
|
||||||
: "Utilizador";
|
String userType = isGuardianMode ? "guardian" : "user";
|
||||||
|
|
||||||
Map<String, Object> userData = new HashMap<>();
|
Map<String, Object> userData = new HashMap<>();
|
||||||
userData.put("email", email);
|
userData.put("email", email);
|
||||||
userData.put("name", name);
|
userData.put("name", name);
|
||||||
userData.put("phone", "");
|
userData.put("phone", "");
|
||||||
userData.put("type", "user");
|
userData.put("type", userType);
|
||||||
userData.put("createdAt", System.currentTimeMillis());
|
userData.put("createdAt", System.currentTimeMillis());
|
||||||
|
|
||||||
db.collection("users").document(uid)
|
db.collection("users").document(uid)
|
||||||
.set(userData)
|
.set(userData)
|
||||||
.addOnSuccessListener(aVoid -> {
|
.addOnSuccessListener(aVoid -> {
|
||||||
prefs.edit()
|
prefs.edit()
|
||||||
.putString("user_type", "user")
|
.putString("user_type", userType)
|
||||||
.putString("user_name", name)
|
.putString("user_name", name)
|
||||||
.apply();
|
.apply();
|
||||||
redirectToApp();
|
|
||||||
|
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 -> {
|
.addOnFailureListener(e -> {
|
||||||
Toast.makeText(this, "Erro ao criar perfil: " + e.getMessage(), Toast.LENGTH_SHORT)
|
Toast.makeText(this, "Erro ao criar perfil: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||||
.show();
|
|
||||||
btnLogin.setEnabled(true);
|
btnLogin.setEnabled(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.addOnFailureListener(e -> {
|
.addOnFailureListener(e -> {
|
||||||
Toast.makeText(this, "Erro ao carregar dados", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "Erro ao carregar dados do utilizador: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||||
btnLogin.setEnabled(true);
|
btnLogin.setEnabled(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
57
app/src/main/res/layout/activity_generate_code.xml
Normal file
57
app/src/main/res/layout/activity_generate_code.xml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="24dp"
|
||||||
|
android:background="@color/background_surface"
|
||||||
|
tools:context=".GenerateCodeActivity">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Código de Convite"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/neutral_dark"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="Partilhe este código com o seu responsável"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_code"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="40dp"
|
||||||
|
android:textSize="48sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/primary"
|
||||||
|
tools:text="123456"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_timer"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
tools:text="Expira em 30 segundos"/>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress_bar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_generate_code"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:text="Gerar Novo Código"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -1,148 +1,54 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/background_surface"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="32dp">
|
android:padding="24dp"
|
||||||
|
android:background="@color/background_surface"
|
||||||
<ImageView
|
tools:context=".InviteCodeActivity">
|
||||||
android:layout_width="80dp"
|
|
||||||
android:layout_height="80dp"
|
|
||||||
android:layout_marginBottom="24dp"
|
|
||||||
android:src="@android:drawable/ic_lock_lock"
|
|
||||||
android:tint="@color/guardian_purple_start" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Código de Acesso"
|
android:text="Associar a um Utilizador"
|
||||||
android:textColor="@color/neutral_dark"
|
android:textColor="@color/neutral_dark"
|
||||||
android:textSize="24sp"
|
android:textSize="22sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textModeDescription"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="Gere um código temporário para vincular responsável"
|
android:text="Insira o código de 6 dígitos fornecido pelo utilizador para começar a monitorizar os seus alarmes."
|
||||||
android:textColor="@color/neutral_medium"
|
android:textColor="@color/neutral_medium" />
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<EditText
|
||||||
android:id="@+id/layoutGenerateCode"
|
android:id="@+id/input_invite_code"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="32dp"
|
android:layout_marginTop="32dp"
|
||||||
android:background="@drawable/bg_guardian_hero"
|
android:hint="Código de 6 dígitos"
|
||||||
android:gravity="center"
|
android:inputType="number"
|
||||||
android:orientation="vertical"
|
android:maxLength="6"
|
||||||
android:padding="32dp"
|
android:textAlignment="center"
|
||||||
android:visibility="visible">
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<TextView
|
<ProgressBar
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/progress_bar_invite"
|
||||||
android:layout_height="wrap_content"
|
style="?android:attr/progressBarStyle"
|
||||||
android:text="Partilhe este código:"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textInviteCode"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="------"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="48sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:letterSpacing="0.2" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textCountdown"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:text="Expira em: 30s"
|
|
||||||
android:textColor="@color/reminder_info_bg"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btnGenerateCode"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:backgroundTint="@android:color/white"
|
|
||||||
android:padding="12dp"
|
|
||||||
android:text="Gerar Novo Código"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:textColor="@color/guardian_purple_end"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/layoutEnterCode"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="32dp"
|
|
||||||
android:background="@drawable/bg_guardian_card"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="24dp"
|
|
||||||
android:visibility="gone">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Insira o código do utilizador:"
|
|
||||||
android:textColor="@color/neutral_dark"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/inputInviteCode"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:background="@drawable/bg_search"
|
|
||||||
android:gravity="center"
|
|
||||||
android:hint="000000"
|
|
||||||
android:inputType="number"
|
|
||||||
android:letterSpacing="0.3"
|
|
||||||
android:maxLength="6"
|
|
||||||
android:padding="16dp"
|
|
||||||
android:textColor="@color/neutral_dark"
|
|
||||||
android:textSize="32sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btnValidateCode"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:background="@drawable/bg_new_button"
|
|
||||||
android:padding="14dp"
|
|
||||||
android:text="Vincular Responsável"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btnBack"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="32dp"
|
android:layout_marginTop="16dp"
|
||||||
android:background="@android:color/transparent"
|
android:visibility="gone" />
|
||||||
android:text="← Voltar"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_validate_code"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="Validar e Associar" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -20,16 +20,16 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/profileButton"
|
android:id="@+id/profileButton"
|
||||||
android:layout_width="44dp"
|
android:layout_width="56dp"
|
||||||
android:layout_height="44dp"
|
android:layout_height="56dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="24dp"
|
||||||
android:layout_marginTop="50dp"
|
android:layout_marginTop="60dp"
|
||||||
android:background="@drawable/bg_avatar"
|
android:background="@drawable/bg_avatar"
|
||||||
android:padding="8dp"
|
android:padding="12dp"
|
||||||
android:src="@mipmap/ic_launcher_round"
|
android:src="@mipmap/ic_launcher_round"
|
||||||
android:contentDescription="Perfil"
|
android:contentDescription="Perfil"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app.layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/bottomBar"
|
android:id="@+id/bottomBar"
|
||||||
@@ -151,4 +151,4 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
46
app/src/main/res/layout/dialog_intro.xml
Normal file
46
app/src/main/res/layout/dialog_intro.xml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="24dp"
|
||||||
|
android:background="@color/background_surface">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:src="@mipmap/ic_launcher_round"
|
||||||
|
android:layout_gravity="center_horizontal"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="Bem-vindo ao Bem+"
|
||||||
|
android:textColor="@color/neutral_dark"
|
||||||
|
android:textSize="22sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="Esta aplicação ajuda-o a gerir os seus medicamentos, a manter os seus responsáveis informados e a receber lembretes úteis para o seu dia a dia."
|
||||||
|
android:textColor="@color/neutral_medium"
|
||||||
|
android:lineSpacingExtra="4dp"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnSkipIntro"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:text="Começar"
|
||||||
|
android:background="@drawable/bg_new_button"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:paddingHorizontal="32dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -45,14 +45,6 @@
|
|||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/btnSettings"
|
|
||||||
android:layout_width="36dp"
|
|
||||||
android:layout_height="36dp"
|
|
||||||
android:background="@drawable/bg_icon_button"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:src="@android:drawable/ic_menu_manage"
|
|
||||||
android:tint="@android:color/white" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -77,13 +69,6 @@
|
|||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:text="Crie lembretes para cada medicamento e acompanhe facilmente."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@@ -106,68 +91,5 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingBottom="8dp" />
|
android:paddingBottom="8dp" />
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:background="@drawable/bg_reminder_info_card"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="18dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="32dp"
|
|
||||||
android:layout_height="32dp"
|
|
||||||
android:src="@android:drawable/ic_dialog_info"
|
|
||||||
android:tint="@color/primary" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="12dp"
|
|
||||||
android:text="Como confirmar medicação"
|
|
||||||
android:textColor="@color/neutral_dark"
|
|
||||||
android:textSize="17sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:lineSpacingExtra="4dp"
|
|
||||||
android:text="• Toque no botão '✓ Confirmar' de cada alarme quando tomar o medicamento\n\n• O responsável receberá automaticamente a notificação\n\n• O botão ficará marcado como 'Tomado' até amanhã"
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Personalização de notificações"
|
|
||||||
android:textColor="@color/neutral_dark"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="Configure frequência, tipos de lembretes e painel de controlos parentais."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
@@ -89,13 +89,6 @@
|
|||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="40dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:background="@drawable/bg_icon_button"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:src="@android:drawable/ic_menu_manage"
|
|
||||||
android:tint="@android:color/white" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -206,206 +199,12 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android.layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:text="Relaxe e aproveite o dia"
|
android:text="Relaxe e aproveite o dia"
|
||||||
android:textColor="@color/neutral_medium"
|
android:textColor="@color/neutral_medium"
|
||||||
android:textSize="13sp" />
|
android:textSize="13sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:background="@drawable/bg_reminder_info_card"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="18dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Sistema Inteligente"
|
|
||||||
android:textColor="@color/neutral_dark"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:text="Recebe lembretes nos momentos certos e dicas baseadas no clima. Configure tudo nas definições."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:text="Mini-Lembretes Inteligentes baseados no clima"
|
|
||||||
android:textColor="@color/neutral_dark"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:text="Sistema contextual completo"
|
|
||||||
android:textColor="@color/neutral_dark"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingBottom="16dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Temperatura alta (>25°C):"
|
|
||||||
android:textColor="@color/neutral_dark"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="• Hidratação: “Beba água regularmente, mesmo sem sede”."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:text="• Proteção: “Sol forte. Fique na sombra entre 11h-16h”."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:text="• Atividade: “Dia quente! Que tal ir à praia?”."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:text="• Conforto: “Vista roupa clara e leve”."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:text="Temperatura baixa (<15°C):"
|
|
||||||
android:textColor="@color/neutral_dark"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="• Conforto: “Dia frio. Ótimo para ficar em casa”."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:text="• Agasalho: “Vista várias camadas de roupa”."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:text="• Bem-estar: “Um chá ou café quente faz bem”."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:text="Chuva:"
|
|
||||||
android:textColor="@color/neutral_dark"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="• Lembrete: “Não se esqueça do guarda-chuva!”."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:text="• Atividade: “Leia um livro ou veja um filme”."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:text="Tempo perfeito (15-25°C):"
|
|
||||||
android:textColor="@color/neutral_dark"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="• Passeio: “Tempo ideal! Faça uma caminhada no parque”."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:text="• Ar fresco: “Abra as janelas para arejar”."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:text="Dicas gerais de saúde:"
|
|
||||||
android:textColor="@color/neutral_dark"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="• Alongamento (10h-11h)."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:text="• Postura e movimento (14h-15h)."
|
|
||||||
android:textColor="@color/neutral_medium"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
<color name="primary">#00B894</color>
|
<color name="primary">#00B894</color>
|
||||||
<color name="accent">#5FE0C5</color>
|
<color name="accent">#5FE0C5</color>
|
||||||
|
<color name="primary_light_bg">#E6F8F5</color>
|
||||||
<color name="neutral_dark">#1E2A28</color>
|
<color name="neutral_dark">#1E2A28</color>
|
||||||
<color name="neutral_medium">#5E7671</color>
|
<color name="neutral_medium">#5E7671</color>
|
||||||
<color name="background_surface">#EEFFF7</color>
|
<color name="background_surface">#EEFFF7</color>
|
||||||
|
|||||||
Reference in New Issue
Block a user