tenho de ver se marca as coisas
This commit is contained in:
2
.idea/deploymentTargetSelector.xml
generated
2
.idea/deploymentTargetSelector.xml
generated
@@ -4,7 +4,7 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2026-04-30T09:38:26.648780Z">
|
<DropdownSelection timestamp="2026-05-06T11:33:57.804357Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=b93659d0e5dd" />
|
<DeviceId pluginId="PhysicalDevice" identifier="serial=b93659d0e5dd" />
|
||||||
|
|||||||
@@ -15,5 +15,21 @@ public class CuidaApplication extends Application {
|
|||||||
.setPersistenceEnabled(true)
|
.setPersistenceEnabled(true)
|
||||||
.build();
|
.build();
|
||||||
db.setFirestoreSettings(settings);
|
db.setFirestoreSettings(settings);
|
||||||
|
|
||||||
|
// Forçar Locale Português
|
||||||
|
java.util.Locale ptLocale = new java.util.Locale("pt", "PT");
|
||||||
|
java.util.Locale.setDefault(ptLocale);
|
||||||
|
android.content.res.Configuration config = new android.content.res.Configuration();
|
||||||
|
config.setLocale(ptLocale);
|
||||||
|
getResources().updateConfiguration(config, getResources().getDisplayMetrics());
|
||||||
|
|
||||||
|
// --- Global Theme Initialization ---
|
||||||
|
android.content.SharedPreferences themePrefs = getSharedPreferences("theme_prefs", android.content.Context.MODE_PRIVATE);
|
||||||
|
boolean isDarkMode = themePrefs.getBoolean("dark_mode", false);
|
||||||
|
if (isDarkMode) {
|
||||||
|
androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode(androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES);
|
||||||
|
} else {
|
||||||
|
androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode(androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,16 +60,12 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
NavController navController = navHostFragment.getNavController();
|
NavController navController = navHostFragment.getNavController();
|
||||||
NavigationUI.setupWithNavController(binding.navView, navController);
|
NavigationUI.setupWithNavController(binding.navView, navController);
|
||||||
|
|
||||||
// Força o clique no Perfil com Transação Manual (Infalível)
|
// Corrige o comportamento da navegação para evitar sobreposição (Overlapping)
|
||||||
binding.navView.setOnItemSelectedListener(item -> {
|
binding.navView.setOnItemSelectedListener(item -> {
|
||||||
if (item.getItemId() == R.id.navigation_profile) {
|
// Limpa a backstack antes de navegar para evitar "fantasmas"
|
||||||
getSupportFragmentManager().beginTransaction()
|
navController.popBackStack(item.getItemId(), true);
|
||||||
.replace(R.id.nav_host_fragment, new com.example.cuida.ui.profile.ProfileFragment())
|
navController.navigate(item.getItemId());
|
||||||
.addToBackStack(null)
|
return true;
|
||||||
.commit();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return NavigationUI.onNavDestinationSelected(item, navController);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,44 +34,27 @@ public class Medication {
|
|||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Getters e Setters com compatibilidade para nomes antigos (name, time, dosage, notes) ---
|
// --- Getters e Setters ---
|
||||||
|
|
||||||
@PropertyName("nome")
|
@PropertyName("nome")
|
||||||
public String getName() { return name; }
|
public String getName() { return name; }
|
||||||
|
|
||||||
@PropertyName("nome")
|
@PropertyName("nome")
|
||||||
public void setName(String name) { this.name = name; }
|
public void setName(String name) { this.name = name; }
|
||||||
|
|
||||||
@PropertyName("name") // Suporte para dados antigos
|
|
||||||
public void setNameOld(String name) { if (this.name == null) this.name = name; }
|
|
||||||
|
|
||||||
@PropertyName("hora")
|
@PropertyName("hora")
|
||||||
public String getTime() { return time; }
|
public String getTime() { return time; }
|
||||||
|
|
||||||
@PropertyName("hora")
|
@PropertyName("hora")
|
||||||
public void setTime(String time) { this.time = time; }
|
public void setTime(String time) { this.time = time; }
|
||||||
|
|
||||||
@PropertyName("time") // Suporte para dados antigos
|
|
||||||
public void setTimeOld(String time) { if (this.time == null) this.time = time; }
|
|
||||||
|
|
||||||
@PropertyName("dosagem")
|
@PropertyName("dosagem")
|
||||||
public String getDosage() { return dosage; }
|
public String getDosage() { return dosage; }
|
||||||
|
|
||||||
@PropertyName("dosagem")
|
@PropertyName("dosagem")
|
||||||
public void setDosage(String dosage) { this.dosage = dosage; }
|
public void setDosage(String dosage) { this.dosage = dosage; }
|
||||||
|
|
||||||
@PropertyName("dosage") // Suporte para dados antigos
|
|
||||||
public void setDosageOld(String dosage) { if (this.dosage == null) this.dosage = dosage; }
|
|
||||||
|
|
||||||
@PropertyName("notas")
|
@PropertyName("notas")
|
||||||
public String getNotes() { return notes; }
|
public String getNotes() { return notes; }
|
||||||
|
|
||||||
@PropertyName("notas")
|
@PropertyName("notas")
|
||||||
public void setNotes(String notes) { this.notes = notes; }
|
public void setNotes(String notes) { this.notes = notes; }
|
||||||
|
|
||||||
@PropertyName("notes") // Suporte para dados antigos
|
|
||||||
public void setNotesOld(String notes) { if (this.notes == null) this.notes = notes; }
|
|
||||||
|
|
||||||
public String getId() { return id; }
|
public String getId() { return id; }
|
||||||
public void setId(String id) { this.id = id; }
|
public void setId(String id) { this.id = id; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,24 +41,16 @@ public class User {
|
|||||||
this.utenteNumber = utenteNumber;
|
this.utenteNumber = utenteNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
@com.google.firebase.firestore.PropertyName("nome_completo")
|
// --- Getters e Setters ---
|
||||||
public String getName() { return name; }
|
public String getName() { return name; }
|
||||||
@com.google.firebase.firestore.PropertyName("nome_completo")
|
|
||||||
public void setName(String name) { this.name = name; }
|
public void setName(String name) { this.name = name; }
|
||||||
|
|
||||||
@com.google.firebase.firestore.PropertyName("idade")
|
|
||||||
public int getAge() { return age; }
|
public int getAge() { return age; }
|
||||||
@com.google.firebase.firestore.PropertyName("idade")
|
|
||||||
public void setAge(int age) { this.age = age; }
|
public void setAge(int age) { this.age = age; }
|
||||||
|
|
||||||
@com.google.firebase.firestore.PropertyName("numero_utente")
|
|
||||||
public String getUtenteNumber() { return utenteNumber; }
|
public String getUtenteNumber() { return utenteNumber; }
|
||||||
@com.google.firebase.firestore.PropertyName("numero_utente")
|
|
||||||
public void setUtenteNumber(String utenteNumber) { this.utenteNumber = utenteNumber; }
|
public void setUtenteNumber(String utenteNumber) { this.utenteNumber = utenteNumber; }
|
||||||
|
|
||||||
@com.google.firebase.firestore.PropertyName("tipo")
|
|
||||||
public String getTipo() { return tipo; }
|
public String getTipo() { return tipo; }
|
||||||
@com.google.firebase.firestore.PropertyName("tipo")
|
|
||||||
public void setTipo(String tipo) { this.tipo = tipo; }
|
public void setTipo(String tipo) { this.tipo = tipo; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public class AppointmentsViewModel extends AndroidViewModel {
|
|||||||
return;
|
return;
|
||||||
String userId = auth.getCurrentUser().getUid();
|
String userId = auth.getCurrentUser().getUid();
|
||||||
|
|
||||||
|
Log.d("AppointmentsVM", "Fetching appointments for userId: " + userId);
|
||||||
// 1. Fetch Future Appointments
|
// 1. Fetch Future Appointments
|
||||||
db.collection("consultas")
|
db.collection("consultas")
|
||||||
.whereEqualTo("userId", userId)
|
.whereEqualTo("userId", userId)
|
||||||
@@ -45,6 +46,10 @@ public class AppointmentsViewModel extends AndroidViewModel {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
Log.d("AppointmentsVM", "Future appointments received. Count: " + value.size());
|
||||||
|
}
|
||||||
|
|
||||||
List<Appointment> apps = new ArrayList<>();
|
List<Appointment> apps = new ArrayList<>();
|
||||||
java.util.Date now = new java.util.Date();
|
java.util.Date now = new java.util.Date();
|
||||||
java.text.SimpleDateFormat format = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm",
|
java.text.SimpleDateFormat format = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm",
|
||||||
@@ -91,6 +96,10 @@ public class AppointmentsViewModel extends AndroidViewModel {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
Log.d("AppointmentsVM", "Past appointments received. Count: " + value.size());
|
||||||
|
}
|
||||||
|
|
||||||
List<Appointment> apps = new ArrayList<>();
|
List<Appointment> apps = new ArrayList<>();
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
for (QueryDocumentSnapshot doc : value) {
|
for (QueryDocumentSnapshot doc : value) {
|
||||||
|
|||||||
@@ -96,7 +96,11 @@ public class RegisterActivity extends AppCompatActivity {
|
|||||||
userMap.put("id", userId);
|
userMap.put("id", userId);
|
||||||
userMap.put("nome_completo", name);
|
userMap.put("nome_completo", name);
|
||||||
userMap.put("email", email);
|
userMap.put("email", email);
|
||||||
userMap.put("idade", ageStr);
|
try {
|
||||||
|
userMap.put("idade", Integer.parseInt(ageStr));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
userMap.put("idade", 0);
|
||||||
|
}
|
||||||
userMap.put("numero_utente", utenteStr);
|
userMap.put("numero_utente", utenteStr);
|
||||||
userMap.put("sexo", gender);
|
userMap.put("sexo", gender);
|
||||||
userMap.put("tipo", "paciente");
|
userMap.put("tipo", "paciente");
|
||||||
|
|||||||
@@ -23,62 +23,38 @@ import java.util.Collections;
|
|||||||
public class HomeFragment extends Fragment {
|
public class HomeFragment extends Fragment {
|
||||||
|
|
||||||
private FragmentHomeBinding binding;
|
private FragmentHomeBinding binding;
|
||||||
private MedicationViewModel medicationViewModel;
|
|
||||||
private AppointmentsViewModel appointmentsViewModel;
|
private AppointmentsViewModel appointmentsViewModel;
|
||||||
|
|
||||||
private AppointmentAdapter appointmentAdapter;
|
private AppointmentAdapter appointmentAdapter;
|
||||||
private MedicationAdapter medicationAdapter;
|
|
||||||
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
ViewGroup container, Bundle savedInstanceState) {
|
ViewGroup container, Bundle savedInstanceState) {
|
||||||
binding = FragmentHomeBinding.inflate(inflater, container, false);
|
binding = FragmentHomeBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
// --- Greeting & Profile Picture ---
|
// --- Greeting & Profile Picture (Real-time) ---
|
||||||
com.google.firebase.auth.FirebaseAuth auth = com.google.firebase.auth.FirebaseAuth.getInstance();
|
com.google.firebase.auth.FirebaseAuth auth = com.google.firebase.auth.FirebaseAuth.getInstance();
|
||||||
if (auth.getCurrentUser() != null) {
|
if (auth.getCurrentUser() != null) {
|
||||||
String userId = auth.getCurrentUser().getUid();
|
String userId = auth.getCurrentUser().getUid();
|
||||||
com.google.firebase.firestore.FirebaseFirestore.getInstance().collection("utilizadores").document(userId)
|
com.google.firebase.firestore.FirebaseFirestore db = com.google.firebase.firestore.FirebaseFirestore.getInstance();
|
||||||
.get()
|
|
||||||
.addOnSuccessListener(documentSnapshot -> {
|
// Listen to 'utilizadores' for basic profile info
|
||||||
if (documentSnapshot.exists() && isAdded()) {
|
db.collection("utilizadores").document(userId)
|
||||||
String name = documentSnapshot.getString("nome_completo");
|
.addSnapshotListener((documentSnapshot, error) -> {
|
||||||
if (name == null || name.isEmpty()) name = documentSnapshot.getString("name");
|
if (error != null) {
|
||||||
|
android.util.Log.e("HomeFragment", "Error loading profile", error);
|
||||||
if (name != null && !name.isEmpty()) {
|
return;
|
||||||
String firstName = name.split(" ")[0];
|
}
|
||||||
binding.textGreeting.setText("Olá, " + firstName);
|
if (documentSnapshot != null && documentSnapshot.exists() && isAdded()) {
|
||||||
} else {
|
updateGreetingUI(documentSnapshot);
|
||||||
binding.textGreeting.setText("Olá");
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
String profilePictureUri = documentSnapshot.getString("profilePictureUri");
|
// Also listen to 'Pacientes' (collection where Professional app saves data)
|
||||||
if (isAdded() && binding.imageProfileHome != null) {
|
db.collection("Pacientes").document(userId)
|
||||||
binding.imageProfileHome.setVisibility(View.VISIBLE);
|
.addSnapshotListener((documentSnapshot, error) -> {
|
||||||
if (profilePictureUri != null && !profilePictureUri.isEmpty() && getContext() != null) {
|
if (documentSnapshot != null && documentSnapshot.exists() && isAdded()) {
|
||||||
Glide.with(getContext())
|
updateGreetingUI(documentSnapshot);
|
||||||
.load(profilePictureUri)
|
|
||||||
.placeholder(R.drawable.ic_user)
|
|
||||||
.circleCrop()
|
|
||||||
.into(binding.imageProfileHome);
|
|
||||||
} else {
|
|
||||||
binding.imageProfileHome.setImageResource(R.drawable.ic_user);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clique para entrar no perfil (Manual e Infalível)
|
|
||||||
binding.imageProfileHome.setOnClickListener(v -> {
|
|
||||||
if (getActivity() != null) {
|
|
||||||
getActivity().getSupportFragmentManager().beginTransaction()
|
|
||||||
.replace(R.id.nav_host_fragment, new com.example.cuida.ui.profile.ProfileFragment())
|
|
||||||
.addToBackStack(null)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.addOnFailureListener(e -> {
|
|
||||||
if (isAdded())
|
|
||||||
binding.textGreeting.setText("Olá");
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
binding.textGreeting.setText("Olá");
|
binding.textGreeting.setText("Olá");
|
||||||
@@ -90,21 +66,17 @@ public class HomeFragment extends Fragment {
|
|||||||
binding.recyclerAppointments.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerAppointments.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
binding.recyclerAppointments.setAdapter(appointmentAdapter);
|
binding.recyclerAppointments.setAdapter(appointmentAdapter);
|
||||||
|
|
||||||
// Medications
|
// Schedule Button
|
||||||
medicationViewModel = new ViewModelProvider(this).get(MedicationViewModel.class);
|
if (binding.buttonSchedule != null) {
|
||||||
medicationAdapter = new MedicationAdapter(new MedicationAdapter.OnItemClickListener() {
|
binding.buttonSchedule.setOnClickListener(v -> {
|
||||||
@Override
|
if (getActivity() != null) {
|
||||||
public void onCheckClick(Medication medication) {
|
getActivity().getSupportFragmentManager().beginTransaction()
|
||||||
medicationViewModel.update(medication);
|
.replace(R.id.nav_host_fragment, new com.example.cuida.ui.schedule.ScheduleAppointmentFragment())
|
||||||
}
|
.addToBackStack(null)
|
||||||
|
.commit();
|
||||||
@Override
|
}
|
||||||
public void onItemClick(Medication medication) {
|
});
|
||||||
// Do nothing
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
binding.recyclerMedications.setLayoutManager(new LinearLayoutManager(getContext()));
|
|
||||||
binding.recyclerMedications.setAdapter(medicationAdapter);
|
|
||||||
|
|
||||||
// --- Load Appointments ---
|
// --- Load Appointments ---
|
||||||
appointmentsViewModel = new ViewModelProvider(this).get(AppointmentsViewModel.class);
|
appointmentsViewModel = new ViewModelProvider(this).get(AppointmentsViewModel.class);
|
||||||
@@ -123,23 +95,48 @@ public class HomeFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- Load Medications ---
|
|
||||||
medicationViewModel.getAllMedications().observe(getViewLifecycleOwner(), medications -> {
|
|
||||||
if (medications != null && !medications.isEmpty()) {
|
|
||||||
// To keep the most recent at the top, we reverse the list
|
|
||||||
Collections.reverse(medications);
|
|
||||||
binding.recyclerMedications.setVisibility(View.VISIBLE);
|
|
||||||
binding.textEmptyMedications.setVisibility(View.GONE);
|
|
||||||
medicationAdapter.setMedications(medications);
|
|
||||||
} else {
|
|
||||||
binding.recyclerMedications.setVisibility(View.GONE);
|
|
||||||
binding.textEmptyMedications.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateGreetingUI(com.google.firebase.firestore.DocumentSnapshot documentSnapshot) {
|
||||||
|
if (!isAdded() || binding == null) return;
|
||||||
|
|
||||||
|
String name = documentSnapshot.getString("nome_completo");
|
||||||
|
if (name == null || name.isEmpty()) name = documentSnapshot.getString("name");
|
||||||
|
if (name == null || name.isEmpty()) name = documentSnapshot.getString("nome");
|
||||||
|
|
||||||
|
if (name != null && !name.isEmpty()) {
|
||||||
|
String firstName = name.split(" ")[0];
|
||||||
|
binding.textGreeting.setText("Olá, " + firstName);
|
||||||
|
}
|
||||||
|
|
||||||
|
String profilePictureUri = documentSnapshot.getString("profilePictureUri");
|
||||||
|
if (binding.imageProfileHome != null) {
|
||||||
|
binding.imageProfileHome.setVisibility(View.VISIBLE);
|
||||||
|
if (profilePictureUri != null && !profilePictureUri.isEmpty() && getContext() != null) {
|
||||||
|
Glide.with(getContext())
|
||||||
|
.load(profilePictureUri)
|
||||||
|
.placeholder(R.drawable.ic_user)
|
||||||
|
.circleCrop()
|
||||||
|
.into(binding.imageProfileHome);
|
||||||
|
} else if (profilePictureUri == null || profilePictureUri.isEmpty()) {
|
||||||
|
binding.imageProfileHome.setImageResource(R.drawable.ic_user);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clique para entrar no perfil
|
||||||
|
binding.imageProfileHome.setOnClickListener(v -> {
|
||||||
|
if (getActivity() != null) {
|
||||||
|
getActivity().getSupportFragmentManager().beginTransaction()
|
||||||
|
.replace(R.id.nav_host_fragment, new com.example.cuida.ui.profile.ProfileFragment())
|
||||||
|
.addToBackStack(null)
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
|
|||||||
@@ -65,7 +65,11 @@ public class MedicationFragment extends Fragment {
|
|||||||
if (t.isEmpty()) continue;
|
if (t.isEmpty()) continue;
|
||||||
try {
|
try {
|
||||||
int oldId = (medication.name + t).hashCode();
|
int oldId = (medication.name + t).hashCode();
|
||||||
|
int oldId15m = (medication.name + t + "15m").hashCode();
|
||||||
|
int oldId5m = (medication.name + t + "5m").hashCode();
|
||||||
com.example.cuida.utils.AlarmScheduler.cancelAlarm(requireContext(), oldId);
|
com.example.cuida.utils.AlarmScheduler.cancelAlarm(requireContext(), oldId);
|
||||||
|
com.example.cuida.utils.AlarmScheduler.cancelAlarm(requireContext(), oldId15m);
|
||||||
|
com.example.cuida.utils.AlarmScheduler.cancelAlarm(requireContext(), oldId5m);
|
||||||
} catch (Exception e) {}
|
} catch (Exception e) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,6 +108,26 @@ public class MedicationFragment extends Fragment {
|
|||||||
title,
|
title,
|
||||||
msg,
|
msg,
|
||||||
alarmId);
|
alarmId);
|
||||||
|
|
||||||
|
// 15 minutes before
|
||||||
|
java.util.Calendar cal15m = (java.util.Calendar) calendar.clone();
|
||||||
|
cal15m.add(java.util.Calendar.MINUTE, -15);
|
||||||
|
if (cal15m.getTimeInMillis() > System.currentTimeMillis()) {
|
||||||
|
String msg15m = "Faltam 15 minutos para tomar: " + medicationToSave.name;
|
||||||
|
int id15m = (medicationToSave.name + t + "15m").hashCode();
|
||||||
|
com.example.cuida.utils.AlarmScheduler.scheduleAlarm(
|
||||||
|
requireContext(), cal15m.getTimeInMillis(), title, msg15m, id15m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5 minutes before
|
||||||
|
java.util.Calendar cal5m = (java.util.Calendar) calendar.clone();
|
||||||
|
cal5m.add(java.util.Calendar.MINUTE, -5);
|
||||||
|
if (cal5m.getTimeInMillis() > System.currentTimeMillis()) {
|
||||||
|
String msg5m = "Faltam 5 minutos para tomar: " + medicationToSave.name;
|
||||||
|
int id5m = (medicationToSave.name + t + "5m").hashCode();
|
||||||
|
com.example.cuida.utils.AlarmScheduler.scheduleAlarm(
|
||||||
|
requireContext(), cal5m.getTimeInMillis(), title, msg5m, id5m);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -122,7 +146,11 @@ public class MedicationFragment extends Fragment {
|
|||||||
if (t.isEmpty()) continue;
|
if (t.isEmpty()) continue;
|
||||||
try {
|
try {
|
||||||
int alarmId = (medicationToDelete.name + t).hashCode();
|
int alarmId = (medicationToDelete.name + t).hashCode();
|
||||||
|
int alarmId15m = (medicationToDelete.name + t + "15m").hashCode();
|
||||||
|
int alarmId5m = (medicationToDelete.name + t + "5m").hashCode();
|
||||||
com.example.cuida.utils.AlarmScheduler.cancelAlarm(requireContext(), alarmId);
|
com.example.cuida.utils.AlarmScheduler.cancelAlarm(requireContext(), alarmId);
|
||||||
|
com.example.cuida.utils.AlarmScheduler.cancelAlarm(requireContext(), alarmId15m);
|
||||||
|
com.example.cuida.utils.AlarmScheduler.cancelAlarm(requireContext(), alarmId5m);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public class MedicationViewModel extends AndroidViewModel {
|
|||||||
return;
|
return;
|
||||||
String userId = auth.getCurrentUser().getUid();
|
String userId = auth.getCurrentUser().getUid();
|
||||||
|
|
||||||
|
Log.d("MedicationViewModel", "Fetching medications for userId: " + userId);
|
||||||
db.collection("medicamentos")
|
db.collection("medicamentos")
|
||||||
.whereEqualTo("userId", userId)
|
.whereEqualTo("userId", userId)
|
||||||
.addSnapshotListener((value, error) -> {
|
.addSnapshotListener((value, error) -> {
|
||||||
@@ -43,6 +44,12 @@ public class MedicationViewModel extends AndroidViewModel {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
Log.d("MedicationViewModel", "Medications received. Count: " + value.size());
|
||||||
|
} else {
|
||||||
|
Log.d("MedicationViewModel", "Value is null");
|
||||||
|
}
|
||||||
|
|
||||||
List<Medication> meds = new ArrayList<>();
|
List<Medication> meds = new ArrayList<>();
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
for (QueryDocumentSnapshot doc : value) {
|
for (QueryDocumentSnapshot doc : value) {
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ public class ProfileFragment extends Fragment {
|
|||||||
new ActivityResultContracts.GetContent(), uri -> {
|
new ActivityResultContracts.GetContent(), uri -> {
|
||||||
if (uri != null && dialogImageView != null) {
|
if (uri != null && dialogImageView != null) {
|
||||||
tempProfileUri = uri;
|
tempProfileUri = uri;
|
||||||
dialogImageView.setImageURI(uri);
|
if (getContext() != null) {
|
||||||
|
Glide.with(getContext()).load(uri).circleCrop().into(dialogImageView);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -63,11 +65,43 @@ public class ProfileFragment extends Fragment {
|
|||||||
|
|
||||||
if (auth.getCurrentUser() != null) {
|
if (auth.getCurrentUser() != null) {
|
||||||
userId = auth.getCurrentUser().getUid();
|
userId = auth.getCurrentUser().getUid();
|
||||||
|
|
||||||
|
// Pré-inicializar com dados do Auth para evitar ecrã vazio
|
||||||
|
currentUser = new User();
|
||||||
|
currentUser.id = userId;
|
||||||
|
currentUser.email = auth.getCurrentUser().getEmail();
|
||||||
|
currentUser.name = auth.getCurrentUser().getDisplayName();
|
||||||
|
|
||||||
|
Log.d("ProfileFragment", "User ID: " + userId + " Email: " + currentUser.email);
|
||||||
|
|
||||||
|
// Atualizar UI inicial com o que temos do Auth
|
||||||
|
if (currentUser.email != null) binding.profileEmail.setText(currentUser.email);
|
||||||
|
if (currentUser.name != null && !currentUser.name.isEmpty()) binding.profileName.setText(currentUser.name);
|
||||||
|
|
||||||
loadUserData();
|
loadUserData();
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.buttonEditProfile.setOnClickListener(v -> showEditDialog());
|
binding.buttonEditProfile.setOnClickListener(v -> showEditDialog());
|
||||||
|
|
||||||
|
// --- Dark Mode Logic ---
|
||||||
|
android.content.SharedPreferences themePrefs = requireContext().getSharedPreferences("theme_prefs", Context.MODE_PRIVATE);
|
||||||
|
boolean isDarkMode = themePrefs.getBoolean("dark_mode", false);
|
||||||
|
|
||||||
|
// Desativar listener temporariamente para evitar loop de recriação
|
||||||
|
binding.switchDarkMode.setOnCheckedChangeListener(null);
|
||||||
|
binding.switchDarkMode.setChecked(isDarkMode);
|
||||||
|
|
||||||
|
binding.switchDarkMode.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||||
|
if (isAdded() && buttonView.isPressed()) {
|
||||||
|
themePrefs.edit().putBoolean("dark_mode", isChecked).apply();
|
||||||
|
if (isChecked) {
|
||||||
|
androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode(androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES);
|
||||||
|
} else {
|
||||||
|
androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode(androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
binding.buttonLogout.setOnClickListener(v -> {
|
binding.buttonLogout.setOnClickListener(v -> {
|
||||||
auth.signOut();
|
auth.signOut();
|
||||||
if (getContext() != null) {
|
if (getContext() != null) {
|
||||||
@@ -88,21 +122,31 @@ public class ProfileFragment extends Fragment {
|
|||||||
try {
|
try {
|
||||||
if (userId == null || !isAdded()) return;
|
if (userId == null || !isAdded()) return;
|
||||||
|
|
||||||
|
Log.d("ProfileFragment", "Starting loadUserData for " + userId);
|
||||||
// Primeiro tenta na coleção geral 'utilizadores'
|
// Primeiro tenta na coleção geral 'utilizadores'
|
||||||
db.collection("utilizadores").document(userId).addSnapshotListener((doc, error) -> {
|
db.collection("utilizadores").document(userId).addSnapshotListener((doc, error) -> {
|
||||||
|
if (error != null) {
|
||||||
|
Log.e("ProfileFragment", "Error in utilizadores listener", error);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if (doc != null && doc.exists()) {
|
if (doc != null && doc.exists()) {
|
||||||
|
Log.d("ProfileFragment", "Found in utilizadores: " + doc.getData());
|
||||||
updateUIFromDocument(doc);
|
updateUIFromDocument(doc);
|
||||||
|
} else {
|
||||||
|
Log.d("ProfileFragment", "Not found in utilizadores");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Independentemente de encontrar em 'utilizadores', tenta TAMBÉM em 'Pacientes' para completar dados
|
// Tenta TAMBÉM em 'Pacientes' para completar dados (ex: vindos da App Médica)
|
||||||
db.collection("Pacientes").document(userId).get().addOnSuccessListener(docP -> {
|
db.collection("Pacientes").document(userId).get().addOnSuccessListener(docP -> {
|
||||||
if (docP.exists()) {
|
if (docP != null && docP.exists()) {
|
||||||
|
Log.d("ProfileFragment", "Found in Pacientes: " + docP.getData());
|
||||||
updateUIFromDocument(docP);
|
updateUIFromDocument(docP);
|
||||||
|
} else {
|
||||||
|
Log.d("ProfileFragment", "Not found in Pacientes");
|
||||||
}
|
}
|
||||||
});
|
}).addOnFailureListener(e -> Log.e("ProfileFragment", "Error in Pacientes get", e));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e("ProfileFragment", "Erro no carregamento", e);
|
Log.e("ProfileFragment", "Erro no processamento de documentos", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -124,8 +168,14 @@ public class ProfileFragment extends Fragment {
|
|||||||
if (e != null && !e.isEmpty()) binding.profileEmail.setText(e);
|
if (e != null && !e.isEmpty()) binding.profileEmail.setText(e);
|
||||||
|
|
||||||
// Idade
|
// Idade
|
||||||
Long i = doc.getLong("idade");
|
Object idadeObj = doc.get("idade");
|
||||||
if (i != null) binding.profileAge.setText(String.valueOf(i));
|
Integer idadeVal = null;
|
||||||
|
if (idadeObj instanceof Long) {
|
||||||
|
idadeVal = ((Long) idadeObj).intValue();
|
||||||
|
} else if (idadeObj instanceof String) {
|
||||||
|
try { idadeVal = Integer.parseInt((String) idadeObj); } catch (Exception ignored) {}
|
||||||
|
}
|
||||||
|
if (idadeVal != null) binding.profileAge.setText(String.valueOf(idadeVal));
|
||||||
|
|
||||||
// Nº Utente
|
// Nº Utente
|
||||||
String u = doc.getString("numero_utente");
|
String u = doc.getString("numero_utente");
|
||||||
@@ -142,7 +192,7 @@ public class ProfileFragment extends Fragment {
|
|||||||
if (currentUser == null) currentUser = new User();
|
if (currentUser == null) currentUser = new User();
|
||||||
if (n != null) currentUser.name = n;
|
if (n != null) currentUser.name = n;
|
||||||
if (e != null) currentUser.email = e;
|
if (e != null) currentUser.email = e;
|
||||||
if (i != null) currentUser.age = i.intValue();
|
if (idadeVal != null) currentUser.age = idadeVal;
|
||||||
if (u != null) currentUser.utenteNumber = u;
|
if (u != null) currentUser.utenteNumber = u;
|
||||||
if (p != null) currentUser.profilePictureUri = p;
|
if (p != null) currentUser.profilePictureUri = p;
|
||||||
currentUser.id = doc.getId();
|
currentUser.id = doc.getId();
|
||||||
@@ -178,12 +228,25 @@ public class ProfileFragment extends Fragment {
|
|||||||
EditText editEmail = dialogView.findViewById(R.id.edit_email);
|
EditText editEmail = dialogView.findViewById(R.id.edit_email);
|
||||||
dialogImageView = dialogView.findViewById(R.id.edit_profile_image);
|
dialogImageView = dialogView.findViewById(R.id.edit_profile_image);
|
||||||
|
|
||||||
// Preenchimento Seguro
|
// Preenchimento Seguro e Infalível
|
||||||
|
if (currentUser == null) {
|
||||||
|
currentUser = new User();
|
||||||
|
currentUser.id = userId;
|
||||||
|
}
|
||||||
|
if (currentUser.email == null || currentUser.email.isEmpty()) {
|
||||||
|
if (auth.getCurrentUser() != null) currentUser.email = auth.getCurrentUser().getEmail();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d("ProfileFragment", "Opening EditDialog. Email to show: " + currentUser.email);
|
||||||
|
|
||||||
if (editName != null) editName.setText(currentUser.name);
|
if (editName != null) editName.setText(currentUser.name);
|
||||||
if (editAge != null) editAge.setText(String.valueOf(currentUser.age));
|
if (editAge != null) editAge.setText(currentUser.age > 0 ? String.valueOf(currentUser.age) : "");
|
||||||
if (editUtente != null) editUtente.setText(currentUser.utenteNumber);
|
if (editUtente != null) editUtente.setText(currentUser.utenteNumber);
|
||||||
if (editEmail != null) editEmail.setText(currentUser.email);
|
if (editEmail != null) {
|
||||||
if (dialogImageView != null && currentUser.profilePictureUri != null) {
|
editEmail.setText(currentUser.email);
|
||||||
|
Log.d("ProfileFragment", "editEmail set to: " + editEmail.getText().toString());
|
||||||
|
}
|
||||||
|
if (dialogImageView != null && currentUser.profilePictureUri != null && !currentUser.profilePictureUri.isEmpty()) {
|
||||||
loadSafeImage(dialogImageView, currentUser.profilePictureUri);
|
loadSafeImage(dialogImageView, currentUser.profilePictureUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,11 +264,26 @@ public class ProfileFragment extends Fragment {
|
|||||||
View btnSave = dialogView.findViewById(R.id.button_save);
|
View btnSave = dialogView.findViewById(R.id.button_save);
|
||||||
if (btnSave != null) {
|
if (btnSave != null) {
|
||||||
btnSave.setOnClickListener(v -> {
|
btnSave.setOnClickListener(v -> {
|
||||||
|
String nameStr = editName != null ? editName.getText().toString().trim() : "";
|
||||||
|
String ageStr = editAge != null ? editAge.getText().toString().trim() : "";
|
||||||
|
String utenteStr = editUtente != null ? editUtente.getText().toString().trim() : "";
|
||||||
|
String emailStr = editEmail != null ? editEmail.getText().toString().trim() : "";
|
||||||
|
|
||||||
|
if (nameStr.isEmpty() || ageStr.isEmpty() || emailStr.isEmpty() || utenteStr.isEmpty()) {
|
||||||
|
Toast.makeText(getContext(), "Preencha os campos.", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (utenteStr.length() != 9) {
|
||||||
|
Toast.makeText(getContext(), "Utente deve ter 9 dígitos.", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
btnSave.setEnabled(false);
|
btnSave.setEnabled(false);
|
||||||
if (tempProfileUri != null) {
|
if (tempProfileUri != null) {
|
||||||
uploadPhotoAndSave(editName.getText().toString(), editAge.getText().toString(), editUtente.getText().toString(), editEmail.getText().toString(), dialog);
|
uploadPhotoAndSave(nameStr, ageStr, utenteStr, emailStr, dialog);
|
||||||
} else {
|
} else {
|
||||||
saveDataToFirestore(editName.getText().toString(), editAge.getText().toString(), editUtente.getText().toString(), editEmail.getText().toString(), currentUser.profilePictureUri, dialog);
|
saveDataToFirestore(nameStr, ageStr, utenteStr, emailStr, currentUser.profilePictureUri, dialog);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,13 +145,16 @@ public class ScheduleAppointmentFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put day on left, month on right
|
|
||||||
int daySpinnerId = android.content.res.Resources.getSystem().getIdentifier("day", "id", "android");
|
int daySpinnerId = android.content.res.Resources.getSystem().getIdentifier("day", "id", "android");
|
||||||
int monthSpinnerId = android.content.res.Resources.getSystem().getIdentifier("month", "id", "android");
|
int monthSpinnerId = android.content.res.Resources.getSystem().getIdentifier("month", "id", "android");
|
||||||
if (daySpinnerId != 0 && monthSpinnerId != 0) {
|
if (daySpinnerId != 0 && monthSpinnerId != 0) {
|
||||||
View daySpinner = datePicker.findViewById(daySpinnerId);
|
View daySpinner = datePicker.findViewById(daySpinnerId);
|
||||||
View monthSpinner = datePicker.findViewById(monthSpinnerId);
|
View monthSpinner = datePicker.findViewById(monthSpinnerId);
|
||||||
if (daySpinner != null && monthSpinner != null) {
|
if (daySpinner != null && monthSpinner != null) {
|
||||||
|
if (monthSpinner instanceof android.widget.NumberPicker) {
|
||||||
|
String[] ptMonths = new String[]{"Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"};
|
||||||
|
((android.widget.NumberPicker) monthSpinner).setDisplayedValues(ptMonths);
|
||||||
|
}
|
||||||
ViewGroup parent = (ViewGroup) daySpinner.getParent();
|
ViewGroup parent = (ViewGroup) daySpinner.getParent();
|
||||||
if (parent != null && parent.equals(monthSpinner.getParent())) {
|
if (parent != null && parent.equals(monthSpinner.getParent())) {
|
||||||
int dIndex = parent.indexOfChild(daySpinner);
|
int dIndex = parent.indexOfChild(daySpinner);
|
||||||
@@ -182,8 +185,9 @@ public class ScheduleAppointmentFragment extends Fragment {
|
|||||||
scheduleViewModel.getSaveSuccess().observe(getViewLifecycleOwner(), success -> {
|
scheduleViewModel.getSaveSuccess().observe(getViewLifecycleOwner(), success -> {
|
||||||
if (success) {
|
if (success) {
|
||||||
Toast.makeText(getContext(), "Consulta agendada!", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Consulta agendada!", Toast.LENGTH_SHORT).show();
|
||||||
NavController navController = Navigation.findNavController(getView());
|
if (getActivity() != null) {
|
||||||
navController.popBackStack();
|
getActivity().getSupportFragmentManager().popBackStack();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ public class ScheduleViewModel extends AndroidViewModel {
|
|||||||
public void setSelectedDoctor(String doctor) {
|
public void setSelectedDoctor(String doctor) {
|
||||||
selectedDoctor.setValue(doctor);
|
selectedDoctor.setValue(doctor);
|
||||||
String schedule = doctorSchedules.get(doctor);
|
String schedule = doctorSchedules.get(doctor);
|
||||||
selectedDoctorSchedule.setValue(schedule != null ? "Horário: " + schedule : "Horário: 08:00 - 19:00");
|
selectedDoctorSchedule.setValue(schedule != null ? "Horário: " + schedule : "Horário: 09:00 - 23:00");
|
||||||
String date = selectedDate.getValue();
|
String date = selectedDate.getValue();
|
||||||
if (date != null) {
|
if (date != null) {
|
||||||
loadTimeSlots(date);
|
loadTimeSlots(date);
|
||||||
@@ -190,8 +190,8 @@ public class ScheduleViewModel extends AndroidViewModel {
|
|||||||
|
|
||||||
private List<TimeSlot> generateTimeSlots(List<String> bookedTimes, String selectedDateStr) {
|
private List<TimeSlot> generateTimeSlots(List<String> bookedTimes, String selectedDateStr) {
|
||||||
List<TimeSlot> slots = new ArrayList<>();
|
List<TimeSlot> slots = new ArrayList<>();
|
||||||
int startHour = 8;
|
int startHour = 9;
|
||||||
int endHour = 19;
|
int endHour = 23;
|
||||||
int startMinute = 0;
|
int startMinute = 0;
|
||||||
int endMinute = 0;
|
int endMinute = 0;
|
||||||
|
|
||||||
@@ -243,6 +243,13 @@ public class ScheduleViewModel extends AndroidViewModel {
|
|||||||
while (cursor.before(endLimit)) {
|
while (cursor.before(endLimit)) {
|
||||||
int h = cursor.get(Calendar.HOUR_OF_DAY);
|
int h = cursor.get(Calendar.HOUR_OF_DAY);
|
||||||
int m = cursor.get(Calendar.MINUTE);
|
int m = cursor.get(Calendar.MINUTE);
|
||||||
|
|
||||||
|
// Skip lunch break from 12:00 to 14:00
|
||||||
|
if (h >= 12 && h < 14) {
|
||||||
|
cursor.add(Calendar.MINUTE, 20);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
String timeStr = String.format("%02d:%02d", h, m);
|
String timeStr = String.format("%02d:%02d", h, m);
|
||||||
|
|
||||||
if (!isToday || h > currentHour || (h == currentHour && m > currentMinute)) {
|
if (!isToday || h > currentHour || (h == currentHour && m > currentMinute)) {
|
||||||
@@ -319,6 +326,27 @@ public class ScheduleViewModel extends AndroidViewModel {
|
|||||||
"Lembrete de Consulta", "A sua consulta é daqui a 30 minutos (" + time + ")",
|
"Lembrete de Consulta", "A sua consulta é daqui a 30 minutos (" + time + ")",
|
||||||
(date + time + "30m").hashCode());
|
(date + time + "30m").hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifications for morning appointments
|
||||||
|
if (hour < 12) {
|
||||||
|
// 3 hours before
|
||||||
|
Calendar cal3h = (Calendar) baseCal.clone();
|
||||||
|
cal3h.add(Calendar.HOUR_OF_DAY, -3);
|
||||||
|
if (cal3h.getTimeInMillis() > System.currentTimeMillis()) {
|
||||||
|
AlarmScheduler.scheduleAlarm(getApplication(), cal3h.getTimeInMillis(),
|
||||||
|
"Lembrete de Consulta", "A sua consulta é daqui a 3 horas (" + time + ")",
|
||||||
|
(date + time + "3h").hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1 hour before
|
||||||
|
Calendar cal1h = (Calendar) baseCal.clone();
|
||||||
|
cal1h.add(Calendar.HOUR_OF_DAY, -1);
|
||||||
|
if (cal1h.getTimeInMillis() > System.currentTimeMillis()) {
|
||||||
|
AlarmScheduler.scheduleAlarm(getApplication(), cal1h.getTimeInMillis(),
|
||||||
|
"Lembrete de Consulta", "A sua consulta é daqui a 1 hora (" + time + ")",
|
||||||
|
(date + time + "1h").hashCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 998 KiB |
@@ -1,12 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
<inset xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
<item
|
android:drawable="@drawable/ic_logo"
|
||||||
android:top="-35dp"
|
android:inset="16dp" />
|
||||||
android:bottom="-35dp"
|
|
||||||
android:left="-35dp"
|
|
||||||
android:right="-35dp">
|
|
||||||
<bitmap
|
|
||||||
android:src="@drawable/ic_logo"
|
|
||||||
android:gravity="center" />
|
|
||||||
</item>
|
|
||||||
</layer-list>
|
|
||||||
|
|||||||
@@ -14,9 +14,10 @@
|
|||||||
android:padding="24dp">
|
android:padding="24dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="161dp"
|
android:layout_width="160dp"
|
||||||
android:layout_height="160dp"
|
android:layout_height="160dp"
|
||||||
android:layout_marginBottom="32dp"
|
android:layout_marginBottom="32dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
android:contentDescription="@string/app_name"
|
android:contentDescription="@string/app_name"
|
||||||
android:src="@drawable/ic_logo" />
|
android:src="@drawable/ic_logo" />
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
android:layout_marginTop="-8dp"
|
android:layout_marginTop="-8dp"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:background="#FFFFFF"
|
android:background="@color/surface_color"
|
||||||
android:elevation="4dp" />
|
android:elevation="4dp" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/text_primary"
|
||||||
android:textSize="14sp"/>
|
android:textSize="14sp"/>
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
|
|||||||
@@ -38,11 +38,13 @@
|
|||||||
android:id="@+id/edit_profile_image"
|
android:id="@+id/edit_profile_image"
|
||||||
android:layout_width="110dp"
|
android:layout_width="110dp"
|
||||||
android:layout_height="110dp"
|
android:layout_height="110dp"
|
||||||
android:padding="4dp"
|
android:padding="20dp"
|
||||||
|
android:background="@color/primary_color"
|
||||||
|
app:tint="@android:color/white"
|
||||||
app:strokeWidth="2dp"
|
app:strokeWidth="2dp"
|
||||||
app:strokeColor="?attr/colorPrimary"
|
app:strokeColor="?attr/colorPrimary"
|
||||||
android:src="@drawable/ic_user"
|
android:src="@drawable/ic_user"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerInside"
|
||||||
app:shapeAppearanceOverlay="@style/CircleImageView" />
|
app:shapeAppearanceOverlay="@style/CircleImageView" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/background_color">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -13,7 +14,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/title_appointments"
|
android:text="@string/title_appointments"
|
||||||
android:textSize="24sp"
|
android:textSize="26sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textColor="@color/primary_color"
|
android:textColor="@color/primary_color"
|
||||||
android:layout_marginBottom="16dp"/>
|
android:layout_marginBottom="16dp"/>
|
||||||
|
|||||||
@@ -25,16 +25,19 @@
|
|||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="Olá"
|
android:text="Olá"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="38sp"
|
android:textSize="40sp"
|
||||||
android:fontFamily="sans-serif-black"
|
android:fontFamily="sans-serif-black"
|
||||||
android:gravity="center_vertical" />
|
android:gravity="center_vertical" />
|
||||||
|
|
||||||
<com.google.android.material.imageview.ShapeableImageView
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
android:id="@+id/image_profile_home"
|
android:id="@+id/image_profile_home"
|
||||||
android:layout_width="64dp"
|
android:layout_width="80dp"
|
||||||
android:layout_height="64dp"
|
android:layout_height="80dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerInside"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:background="@color/primary_color"
|
||||||
|
app:tint="@android:color/white"
|
||||||
android:src="@drawable/ic_placeholder"
|
android:src="@drawable/ic_placeholder"
|
||||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent"
|
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent"
|
||||||
app:strokeWidth="2dp"
|
app:strokeWidth="2dp"
|
||||||
@@ -58,6 +61,17 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingHorizontal="20dp">
|
android:paddingHorizontal="20dp">
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/button_schedule"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginBottom="24dp"
|
||||||
|
android:text="Marcar Consulta"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:cornerRadius="16dp" />
|
||||||
|
|
||||||
<!-- Agenda de Consultas -->
|
<!-- Agenda de Consultas -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -79,7 +93,7 @@
|
|||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:text="Agenda de Consultas"
|
android:text="Agenda de Consultas"
|
||||||
android:textColor="@color/text_primary"
|
android:textColor="@color/text_primary"
|
||||||
android:textSize="22sp"
|
android:textSize="24sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -100,47 +114,6 @@
|
|||||||
android:textColor="@color/text_secondary"
|
android:textColor="@color/text_secondary"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<!-- Tratamentos Atuais -->
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_marginTop="40dp"
|
|
||||||
android:gravity="center_vertical">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="28dp"
|
|
||||||
android:layout_height="28dp"
|
|
||||||
android:src="@android:drawable/ic_menu_agenda"
|
|
||||||
app:tint="@color/primary_color"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/title_medication"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:text="Tratamentos Atuais"
|
|
||||||
android:textColor="@color/text_primary"
|
|
||||||
android:textSize="22sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recycler_medications"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:nestedScrollingEnabled="false" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/text_empty_medications"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="Nenhum tratamento ativo."
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textColor="@color/text_secondary"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/background_color"
|
||||||
android:padding="16dp">
|
android:padding="16dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|||||||
@@ -10,12 +10,15 @@
|
|||||||
|
|
||||||
<com.google.android.material.imageview.ShapeableImageView
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
android:id="@+id/profile_image"
|
android:id="@+id/profile_image"
|
||||||
android:layout_width="100dp"
|
android:layout_width="160dp"
|
||||||
android:layout_height="100dp"
|
android:layout_height="160dp"
|
||||||
android:src="@drawable/ic_placeholder"
|
android:src="@drawable/ic_placeholder"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerInside"
|
||||||
|
android:padding="32dp"
|
||||||
|
android:background="@color/primary_color"
|
||||||
|
app:tint="@android:color/white"
|
||||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent"
|
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent"
|
||||||
android:layout_marginBottom="24dp"/>
|
android:layout_marginBottom="32dp"/>
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -37,7 +40,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Nome do Utilizador"
|
android:text="Nome do Utilizador"
|
||||||
android:textSize="22sp"
|
android:textSize="26sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textColor="@color/text_primary"
|
android:textColor="@color/text_primary"
|
||||||
android:layout_marginBottom="8dp"/>
|
android:layout_marginBottom="8dp"/>
|
||||||
@@ -47,14 +50,14 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="email@exemplo.com"
|
android:text="email@exemplo.com"
|
||||||
android:textSize="14sp"
|
android:textSize="18sp"
|
||||||
android:textColor="@color/text_secondary"
|
android:textColor="@color/text_secondary"
|
||||||
android:layout_marginBottom="24dp"/>
|
android:layout_marginBottom="24dp"/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:background="#E0E0E0"
|
android:background="@color/primary_light_color"
|
||||||
android:layout_marginBottom="16dp"/>
|
android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -107,6 +110,42 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
app:cardCornerRadius="16dp"
|
||||||
|
app:cardBackgroundColor="@color/surface_color">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/ic_dark_mode"
|
||||||
|
app:tint="?attr/colorPrimary"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:text="Modo Escuro"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="@color/text_primary"/>
|
||||||
|
|
||||||
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
|
android:id="@+id/switch_dark_mode"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/button_edit_profile"
|
android:id="@+id/button_edit_profile"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
android:background="@color/background_color"
|
||||||
android:padding="16dp">
|
android:padding="16dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -11,7 +12,7 @@
|
|||||||
android:text="Agendar Consulta"
|
android:text="Agendar Consulta"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/text_primary"
|
||||||
android:layout_marginBottom="24dp"/>
|
android:layout_marginBottom="24dp"/>
|
||||||
|
|
||||||
<!-- 1. Selecionar Data -->
|
<!-- 1. Selecionar Data -->
|
||||||
@@ -61,7 +62,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Horário: --"
|
android:text="Horário: --"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/text_secondary"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:textStyle="italic"/>
|
android:textStyle="italic"/>
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
|
android:background="@color/background_color"
|
||||||
android:gravity="center_horizontal">
|
android:gravity="center_horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -23,14 +24,16 @@
|
|||||||
android:text="Ligar SNS 24 (808 24 24 24)"
|
android:text="Ligar SNS 24 (808 24 24 24)"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
android:backgroundTint="@color/teal_700"
|
android:backgroundTint="@color/teal_700"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
app:icon="@android:drawable/ic_menu_call"
|
app:icon="@android:drawable/ic_menu_call"
|
||||||
|
app:iconTint="@android:color/white"
|
||||||
app:iconGravity="textStart"
|
app:iconGravity="textStart"
|
||||||
android:layout_marginBottom="32dp"/>
|
android:layout_marginBottom="32dp"/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:background="#CCCCCC"
|
android:background="@color/primary_light_color"
|
||||||
android:layout_marginBottom="24dp"/>
|
android:layout_marginBottom="24dp"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -74,9 +77,9 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textColor="@android:color/black"
|
android:textColor="@color/text_primary"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
android:background="#F5F5F5"
|
android:background="@color/surface_color"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:layout_marginBottom="16dp"/>
|
android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
@@ -88,6 +91,7 @@
|
|||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:backgroundTint="@android:color/holo_red_dark"
|
android:backgroundTint="@android:color/holo_red_dark"
|
||||||
app:icon="@android:drawable/ic_menu_mapmode"
|
app:icon="@android:drawable/ic_menu_mapmode"
|
||||||
|
app:iconGravity="textStart"
|
||||||
app:cornerRadius="8dp"
|
app:cornerRadius="8dp"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="16dp"
|
||||||
app:cardElevation="0dp"
|
app:cardElevation="0dp"
|
||||||
app:strokeWidth="0dp"
|
app:strokeWidth="0dp"
|
||||||
app:cardBackgroundColor="#E3F2FD"
|
app:cardBackgroundColor="@color/primary_light_color"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent">
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
@@ -42,10 +42,12 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Nome Medicamento"
|
android:text="Nome Medicamento"
|
||||||
android:textColor="@color/text_primary"
|
android:textColor="@color/text_primary"
|
||||||
android:textSize="18sp"
|
android:textSize="20sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
|
android:gravity="center_vertical"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
app:layout_constraintTop_toTopOf="@id/icon_bg"
|
app:layout_constraintTop_toTopOf="@id/icon_bg"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/text_med_dosage"
|
||||||
app:layout_constraintStart_toEndOf="@id/icon_bg"
|
app:layout_constraintStart_toEndOf="@id/icon_bg"
|
||||||
app:layout_constraintEnd_toStartOf="@id/checkbox_taken"
|
app:layout_constraintEnd_toStartOf="@id/checkbox_taken"
|
||||||
android:layout_marginEnd="8dp"/>
|
android:layout_marginEnd="8dp"/>
|
||||||
@@ -56,9 +58,10 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Dosagem"
|
android:text="Dosagem"
|
||||||
android:textColor="@color/text_secondary"
|
android:textColor="@color/text_secondary"
|
||||||
android:textSize="14sp"
|
android:textSize="16sp"
|
||||||
android:layout_marginTop="4dp"
|
android:gravity="center_vertical"
|
||||||
app:layout_constraintTop_toBottomOf="@id/text_med_name"
|
app:layout_constraintTop_toBottomOf="@id/text_med_name"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/icon_bg"
|
||||||
app:layout_constraintStart_toStartOf="@id/text_med_name"
|
app:layout_constraintStart_toStartOf="@id/text_med_name"
|
||||||
app:layout_constraintEnd_toEndOf="@id/text_med_name"/>
|
app:layout_constraintEnd_toEndOf="@id/text_med_name"/>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application' version '9.2.0' apply false
|
id 'com.android.application' version '9.2.1' apply false
|
||||||
id 'com.android.library' version '9.2.0' apply false
|
id 'com.android.library' version '9.2.1' apply false
|
||||||
id 'com.google.gms.google-services' version '4.4.4' apply false
|
id 'com.google.gms.google-services' version '4.4.4' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user