tenho de ver se marca as coisas

This commit is contained in:
2026-05-04 14:33:25 +01:00
parent ae6cf5413c
commit a40a75d710
3 changed files with 146 additions and 99 deletions

View File

@@ -4,10 +4,10 @@
<selectionStates> <selectionStates>
<SelectionState runConfigName="app"> <SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" /> <option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2026-04-30T09:29:05.514328Z"> <DropdownSelection timestamp="2026-04-30T09:38:26.648780Z">
<Target type="DEFAULT_BOOT"> <Target type="DEFAULT_BOOT">
<handle> <handle>
<DeviceId pluginId="LocalEmulator" identifier="path=/Users/230405/.android/avd/Medium_Phone.avd" /> <DeviceId pluginId="PhysicalDevice" identifier="serial=b93659d0e5dd" />
</handle> </handle>
</Target> </Target>
</DropdownSelection> </DropdownSelection>

View File

@@ -1,7 +1,5 @@
package com.example.cuida.ui.home; package com.example.cuida.ui.home;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -9,12 +7,17 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.example.cuida.databinding.FragmentHomeBinding; import com.example.cuida.databinding.FragmentHomeBinding;
import com.example.cuida.ui.medication.MedicationViewModel; import com.example.cuida.ui.medication.MedicationViewModel;
import com.example.cuida.ui.medication.MedicationAdapter;
import com.example.cuida.ui.appointments.AppointmentsViewModel; import com.example.cuida.ui.appointments.AppointmentsViewModel;
import com.example.cuida.ui.appointments.AppointmentAdapter;
import com.example.cuida.data.model.Appointment; import com.example.cuida.data.model.Appointment;
import java.util.Calendar; import com.example.cuida.data.model.Medication;
import java.util.Locale;
import java.util.Collections;
public class HomeFragment extends Fragment { public class HomeFragment extends Fragment {
@@ -22,6 +25,9 @@ public class HomeFragment extends Fragment {
private MedicationViewModel medicationViewModel; private MedicationViewModel medicationViewModel;
private AppointmentsViewModel appointmentsViewModel; private AppointmentsViewModel appointmentsViewModel;
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);
@@ -34,19 +40,16 @@ public class HomeFragment extends Fragment {
.get() .get()
.addOnSuccessListener(documentSnapshot -> { .addOnSuccessListener(documentSnapshot -> {
if (documentSnapshot.exists() && isAdded()) { if (documentSnapshot.exists() && isAdded()) {
// Tenta 'nome_completo' (novo) ou 'name' (antigo)
String name = documentSnapshot.getString("nome_completo"); String name = documentSnapshot.getString("nome_completo");
if (name == null || name.isEmpty()) name = documentSnapshot.getString("name"); if (name == null || name.isEmpty()) name = documentSnapshot.getString("name");
if (name != null && !name.isEmpty()) { if (name != null && !name.isEmpty()) {
// Extract first name
String firstName = name.split(" ")[0]; String firstName = name.split(" ")[0];
binding.textGreeting.setText("Olá, " + firstName + "!"); binding.textGreeting.setText("Olá, " + firstName + "!");
} else { } else {
binding.textGreeting.setText("Olá, Utilizador!"); binding.textGreeting.setText("Olá, Utilizador!");
} }
// Load Profile Picture
String profilePictureUri = documentSnapshot.getString("profilePictureUri"); String profilePictureUri = documentSnapshot.getString("profilePictureUri");
if (profilePictureUri != null && !profilePictureUri.isEmpty()) { if (profilePictureUri != null && !profilePictureUri.isEmpty()) {
try { try {
@@ -65,32 +68,62 @@ public class HomeFragment extends Fragment {
binding.textGreeting.setText("Olá, Utilizador!"); binding.textGreeting.setText("Olá, Utilizador!");
} }
// --- Next Medication --- // --- Setup Adapters ---
// Consultations
appointmentAdapter = new AppointmentAdapter();
binding.recyclerAppointments.setLayoutManager(new LinearLayoutManager(getContext()));
binding.recyclerAppointments.setAdapter(appointmentAdapter);
// Medications
medicationViewModel = new ViewModelProvider(this).get(MedicationViewModel.class); medicationViewModel = new ViewModelProvider(this).get(MedicationViewModel.class);
medicationViewModel.getNextMedication().observe(getViewLifecycleOwner(), medication -> { medicationAdapter = new MedicationAdapter(new MedicationAdapter.OnItemClickListener() {
if (medication != null) { @Override
binding.nextMedName.setText(medication.name + " (" + medication.dosage + ")"); public void onCheckClick(Medication medication) {
binding.nextMedTime.setText("Hoje, " + medication.time); medicationViewModel.update(medication);
}
@Override
public void onItemClick(Medication medication) {
// Do nothing
}
});
binding.recyclerMedications.setLayoutManager(new LinearLayoutManager(getContext()));
binding.recyclerMedications.setAdapter(medicationAdapter);
// --- Load Appointments ---
appointmentsViewModel = new ViewModelProvider(this).get(AppointmentsViewModel.class);
appointmentsViewModel.getFutureAppointments().observe(getViewLifecycleOwner(), appointments -> {
if (appointments != null && !appointments.isEmpty()) {
// Force status "Aceite" as per prompt instructions
for(Appointment app : appointments) {
app.status = "Aceite";
}
binding.recyclerAppointments.setVisibility(View.VISIBLE);
binding.textEmptyAppointments.setVisibility(View.GONE);
appointmentAdapter.setAppointments(appointments);
} else { } else {
binding.nextMedName.setText("Sem medicação"); binding.recyclerAppointments.setVisibility(View.GONE);
binding.nextMedTime.setText("--:--"); binding.textEmptyAppointments.setVisibility(View.VISIBLE);
} }
}); });
// --- Book Appointment --- // --- Load Medications ---
appointmentsViewModel = new ViewModelProvider(this).get(AppointmentsViewModel.class); medicationViewModel.getAllMedications().observe(getViewLifecycleOwner(), medications -> {
binding.buttonBookAppointment.setOnClickListener(v -> { if (medications != null && !medications.isEmpty()) {
androidx.navigation.Navigation.findNavController(v) // To keep the most recent at the top, we reverse the list
.navigate(com.example.cuida.R.id.action_home_to_schedule_appointment); 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();
} }
@Override @Override
public void onDestroyView() { public void onDestroyView() {
super.onDestroyView(); super.onDestroyView();

View File

@@ -1,89 +1,103 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
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:padding="16dp"> android:fillViewport="true">
<com.google.android.material.imageview.ShapeableImageView <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/image_profile_home"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_placeholder"
android:scaleType="centerCrop"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/text_greeting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="Olá, utilizador!"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
app:layout_constraintTop_toTopOf="@id/image_profile_home"
app:layout_constraintBottom_toBottomOf="@id/image_profile_home"
app:layout_constraintStart_toEndOf="@id/image_profile_home"/>
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_next_medication"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp" android:padding="16dp">
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="16dp"
app:cardElevation="4dp"
app:layout_constraintTop_toBottomOf="@id/image_profile_home">
<LinearLayout <com.google.android.material.imageview.ShapeableImageView
android:id="@+id/image_profile_home"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_placeholder"
android:scaleType="centerCrop"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/text_greeting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="Olá, utilizador!"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
app:layout_constraintTop_toTopOf="@id/image_profile_home"
app:layout_constraintBottom_toBottomOf="@id/image_profile_home"
app:layout_constraintStart_toEndOf="@id/image_profile_home"/>
<!-- Agenda de Consultas -->
<TextView
android:id="@+id/title_agenda"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Agenda de Consultas"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
app:layout_constraintTop_toBottomOf="@id/image_profile_home"
app:layout_constraintStart_toStartOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_appointments"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:layout_marginTop="8dp"
android:padding="16dp"> android:nestedScrollingEnabled="false"
app:layout_constraintTop_toBottomOf="@id/title_agenda"
app:layout_constraintStart_toStartOf="parent"/>
<TextView <TextView
android:layout_width="wrap_content" android:id="@+id/text_empty_appointments"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:text="Próxima Medicação" android:layout_height="wrap_content"
android:textStyle="bold" android:text="Sem consultas agendadas."
android:textSize="18sp" android:textAlignment="center"
android:textColor="@color/primary_color"/> android:textColor="@android:color/darker_gray"
android:layout_marginTop="8dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/recycler_appointments" />
<TextView <!-- Tratamentos Atuais -->
android:id="@+id/next_med_name" <TextView
android:layout_width="wrap_content" android:id="@+id/title_medication"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:text="Paracetamol 500mg" android:layout_height="wrap_content"
android:textSize="16sp" android:layout_marginTop="24dp"
android:layout_marginTop="8dp"/> android:text="Tratamentos Atuais"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
app:layout_constraintTop_toBottomOf="@id/recycler_appointments"
app:layout_constraintStart_toStartOf="parent" />
<TextView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/next_med_time" android:id="@+id/recycler_medications"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Hoje, 14:00" android:layout_marginTop="8dp"
android:textSize="14sp" android:nestedScrollingEnabled="false"
android:textColor="@android:color/darker_gray" app:layout_constraintTop_toBottomOf="@id/title_medication"
android:layout_marginTop="4dp"/> app:layout_constraintStart_toStartOf="parent"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.button.MaterialButton <TextView
android:id="@+id/button_book_appointment" android:id="@+id/text_empty_medications"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="60dp" android:layout_height="wrap_content"
android:text="Marcar Consulta" android:text="Nenhum tratamento ativo."
android:textSize="16sp" android:textAlignment="center"
android:layout_marginTop="24dp" android:textColor="@android:color/darker_gray"
app:icon="@android:drawable/ic_menu_my_calendar" android:layout_marginTop="8dp"
app:iconGravity="textStart" android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/card_next_medication"/> app:layout_constraintTop_toBottomOf="@id/recycler_medications" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>