ja meti o droplist nos medicamentos
This commit is contained in:
92
documentacao_projecto/backups_codigo/HomeFragment.java
Normal file
92
documentacao_projecto/backups_codigo/HomeFragment.java
Normal file
@@ -0,0 +1,92 @@
|
||||
package com.example.cuida.ui.home;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import com.example.cuida.databinding.FragmentHomeBinding;
|
||||
import com.example.cuida.ui.medication.MedicationViewModel;
|
||||
import com.example.cuida.ui.appointments.AppointmentsViewModel;
|
||||
import com.example.cuida.data.model.Appointment;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
|
||||
public class HomeFragment extends Fragment {
|
||||
|
||||
private FragmentHomeBinding binding;
|
||||
private MedicationViewModel medicationViewModel;
|
||||
private AppointmentsViewModel appointmentsViewModel;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
binding = FragmentHomeBinding.inflate(inflater, container, false);
|
||||
|
||||
// --- Greeting & Profile Picture ---
|
||||
com.google.firebase.auth.FirebaseAuth auth = com.google.firebase.auth.FirebaseAuth.getInstance();
|
||||
if (auth.getCurrentUser() != null) {
|
||||
String userId = auth.getCurrentUser().getUid();
|
||||
com.google.firebase.firestore.FirebaseFirestore.getInstance().collection("utilizadores").document(userId)
|
||||
.get()
|
||||
.addOnSuccessListener(documentSnapshot -> {
|
||||
if (documentSnapshot.exists() && isAdded()) {
|
||||
String name = documentSnapshot.getString("name");
|
||||
if (name != null && !name.isEmpty()) {
|
||||
// Extract first name
|
||||
String firstName = name.split(" ")[0];
|
||||
binding.textGreeting.setText("Olá, " + firstName + "!");
|
||||
} else {
|
||||
binding.textGreeting.setText("Olá, Utilizador!");
|
||||
}
|
||||
|
||||
// Load Profile Picture
|
||||
String profilePictureUri = documentSnapshot.getString("profilePictureUri");
|
||||
if (profilePictureUri != null && !profilePictureUri.isEmpty()) {
|
||||
try {
|
||||
binding.imageProfileHome.setImageURI(android.net.Uri.parse(profilePictureUri));
|
||||
} catch (Exception e) {
|
||||
android.util.Log.e("HomeFragment", "Error loading profile pic view: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.addOnFailureListener(e -> {
|
||||
if (isAdded())
|
||||
binding.textGreeting.setText("Olá, Utilizador!");
|
||||
});
|
||||
} else {
|
||||
binding.textGreeting.setText("Olá, Utilizador!");
|
||||
}
|
||||
|
||||
// --- Next Medication ---
|
||||
medicationViewModel = new ViewModelProvider(this).get(MedicationViewModel.class);
|
||||
medicationViewModel.getNextMedication().observe(getViewLifecycleOwner(), medication -> {
|
||||
if (medication != null) {
|
||||
binding.nextMedName.setText(medication.name + " (" + medication.dosage + ")");
|
||||
binding.nextMedTime.setText("Hoje, " + medication.time);
|
||||
} else {
|
||||
binding.nextMedName.setText("Sem medicação");
|
||||
binding.nextMedTime.setText("--:--");
|
||||
}
|
||||
});
|
||||
|
||||
// --- Book Appointment ---
|
||||
appointmentsViewModel = new ViewModelProvider(this).get(AppointmentsViewModel.class);
|
||||
binding.buttonBookAppointment.setOnClickListener(v -> {
|
||||
androidx.navigation.Navigation.findNavController(v)
|
||||
.navigate(com.example.cuida.R.id.action_home_to_schedule_appointment);
|
||||
});
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
85
documentacao_projecto/backups_codigo/MedicationAdapter.java
Normal file
85
documentacao_projecto/backups_codigo/MedicationAdapter.java
Normal file
@@ -0,0 +1,85 @@
|
||||
package com.example.cuida.ui.medication;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.example.cuida.R;
|
||||
import com.example.cuida.data.model.Medication;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MedicationAdapter extends RecyclerView.Adapter<MedicationAdapter.MedicationViewHolder> {
|
||||
|
||||
private List<Medication> medicationList = new ArrayList<>();
|
||||
private final OnItemClickListener listener;
|
||||
|
||||
public interface OnItemClickListener {
|
||||
void onCheckClick(Medication medication);
|
||||
|
||||
void onItemClick(Medication medication);
|
||||
}
|
||||
|
||||
public MedicationAdapter(OnItemClickListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void setMedications(List<Medication> medications) {
|
||||
this.medicationList = medications;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MedicationViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_medication, parent, false);
|
||||
return new MedicationViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull MedicationViewHolder holder, int position) {
|
||||
Medication medication = medicationList.get(position);
|
||||
holder.textName.setText(medication.name);
|
||||
holder.textDosage.setText(medication.dosage);
|
||||
holder.textTime.setText(medication.time);
|
||||
holder.textNotes.setText(medication.notes);
|
||||
|
||||
// Remove listener temporarily to avoid triggering it during bind
|
||||
holder.checkBoxTaken.setOnCheckedChangeListener(null);
|
||||
holder.checkBoxTaken.setChecked(medication.isTaken);
|
||||
|
||||
holder.checkBoxTaken.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
medication.isTaken = isChecked;
|
||||
listener.onCheckClick(medication);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return medicationList.size();
|
||||
}
|
||||
|
||||
public class MedicationViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView textName, textDosage, textTime, textNotes;
|
||||
CheckBox checkBoxTaken;
|
||||
|
||||
public MedicationViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
textName = itemView.findViewById(R.id.text_med_name);
|
||||
textDosage = itemView.findViewById(R.id.text_med_dosage);
|
||||
textTime = itemView.findViewById(R.id.text_med_time);
|
||||
textNotes = itemView.findViewById(R.id.text_med_notes);
|
||||
checkBoxTaken = itemView.findViewById(R.id.checkbox_taken);
|
||||
|
||||
itemView.setOnClickListener(v -> {
|
||||
int position = getAdapterPosition();
|
||||
if (listener != null && position != RecyclerView.NO_POSITION) {
|
||||
listener.onItemClick(medicationList.get(position));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
368
documentacao_projecto/backups_codigo/MedicationDialog.java
Normal file
368
documentacao_projecto/backups_codigo/MedicationDialog.java
Normal file
@@ -0,0 +1,368 @@
|
||||
package com.example.cuida.ui.medication;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.app.TimePickerDialog;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import com.example.cuida.R;
|
||||
import com.example.cuida.data.model.Medication;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.google.firebase.database.DataSnapshot;
|
||||
import com.google.firebase.database.DatabaseError;
|
||||
import com.google.firebase.database.DatabaseReference;
|
||||
import com.google.firebase.database.FirebaseDatabase;
|
||||
import com.google.firebase.database.ValueEventListener;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import com.example.cuida.data.model.Comprimido;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Toast;
|
||||
import com.google.android.material.chip.Chip;
|
||||
import com.google.android.material.chip.ChipGroup;
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import java.util.Collections;
|
||||
|
||||
public class MedicationDialog extends DialogFragment {
|
||||
|
||||
private TextInputEditText editName;
|
||||
private RecyclerView recyclerResults;
|
||||
private ComprimidoRecyclerAdapter recyclerAdapter;
|
||||
private List<Comprimido> searchResults = new ArrayList<>();
|
||||
private List<Comprimido> fullPillsList = new ArrayList<>();
|
||||
private DatabaseReference medicationRef;
|
||||
private EditText editNotes;
|
||||
private android.widget.RadioButton radioOral, radioTopical, radioInhalatory;
|
||||
private android.widget.RadioGroup radioGroupRoute;
|
||||
private ChipGroup chipGroupTimes;
|
||||
private List<String> selectedTimes = new ArrayList<>();
|
||||
private Medication medicationToEdit;
|
||||
private OnMedicationSaveListener listener;
|
||||
private OnMedicationDeleteListener deleteListener;
|
||||
|
||||
public interface OnMedicationSaveListener {
|
||||
void onSave(Medication medication);
|
||||
}
|
||||
|
||||
public interface OnMedicationDeleteListener {
|
||||
void onDelete(Medication medication);
|
||||
}
|
||||
|
||||
public void setListener(OnMedicationSaveListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void setDeleteListener(OnMedicationDeleteListener listener) {
|
||||
this.deleteListener = listener;
|
||||
}
|
||||
|
||||
public void setMedicationToEdit(Medication medication) {
|
||||
this.medicationToEdit = medication;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
|
||||
LayoutInflater inflater = requireActivity().getLayoutInflater();
|
||||
View view = inflater.inflate(R.layout.dialog_add_medication, null);
|
||||
|
||||
editName = view.findViewById(R.id.edit_med_name);
|
||||
recyclerResults = view.findViewById(R.id.recycler_search_results);
|
||||
editNotes = view.findViewById(R.id.edit_med_notes);
|
||||
chipGroupTimes = view.findViewById(R.id.chip_group_times);
|
||||
MaterialButton btnAddTime = view.findViewById(R.id.btn_add_time);
|
||||
|
||||
radioGroupRoute = view.findViewById(R.id.radio_group_route);
|
||||
radioOral = view.findViewById(R.id.radio_oral);
|
||||
radioTopical = view.findViewById(R.id.radio_topical);
|
||||
radioInhalatory = view.findViewById(R.id.radio_inhalatory);
|
||||
|
||||
final android.content.Context currentContext = getContext();
|
||||
if (currentContext != null) {
|
||||
recyclerAdapter = new ComprimidoRecyclerAdapter(searchResults, selected -> {
|
||||
editName.setText(selected.nome);
|
||||
editName.setSelection(selected.nome.length());
|
||||
|
||||
// Adiciona a dosagem/informação ao campo de notas automaticamente
|
||||
if (selected.dosagem != null && !selected.dosagem.isEmpty()) {
|
||||
editNotes.setText(selected.dosagem);
|
||||
}
|
||||
|
||||
recyclerResults.setVisibility(View.GONE);
|
||||
searchResults.clear();
|
||||
});
|
||||
recyclerResults.setLayoutManager(new LinearLayoutManager(currentContext));
|
||||
recyclerResults.setAdapter(recyclerAdapter);
|
||||
|
||||
String dbUrl = "https://cuidamais-7b904-default-rtdb.firebaseio.com/";
|
||||
medicationRef = FirebaseDatabase.getInstance(dbUrl).getReference("medication");
|
||||
|
||||
// Carregar todos os medicamentos uma única vez para filtragem local rápida
|
||||
fetchAllMedsOnce();
|
||||
|
||||
editName.addTextChangedListener(new TextWatcher() {
|
||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
filterMedsLocally(s.toString().trim());
|
||||
}
|
||||
@Override public void afterTextChanged(Editable s) {}
|
||||
});
|
||||
}
|
||||
|
||||
radioGroupRoute = view.findViewById(R.id.radio_group_route);
|
||||
radioOral = view.findViewById(R.id.radio_oral);
|
||||
radioTopical = view.findViewById(R.id.radio_topical);
|
||||
radioInhalatory = view.findViewById(R.id.radio_inhalatory);
|
||||
|
||||
// Set up TimePicker
|
||||
btnAddTime.setOnClickListener(v -> showTimePicker());
|
||||
|
||||
if (medicationToEdit != null) {
|
||||
editName.setText(medicationToEdit.name);
|
||||
editNotes.setText(medicationToEdit.notes);
|
||||
if (medicationToEdit.time != null && !medicationToEdit.time.isEmpty()) {
|
||||
String[] times = medicationToEdit.time.split(",\\s*");
|
||||
for (String t : times) {
|
||||
if (!t.isEmpty()) selectedTimes.add(t);
|
||||
}
|
||||
refreshTimeChips();
|
||||
}
|
||||
|
||||
String dosage = medicationToEdit.dosage;
|
||||
if (dosage != null) {
|
||||
if (dosage.contains("Oral"))
|
||||
radioOral.setChecked(true);
|
||||
else if (dosage.contains("Tópica"))
|
||||
radioTopical.setChecked(true);
|
||||
else if (dosage.contains("Inalatória"))
|
||||
radioInhalatory.setChecked(true);
|
||||
}
|
||||
|
||||
builder.setTitle("Editar Medicamento");
|
||||
} else {
|
||||
builder.setTitle("Adicionar Medicamento");
|
||||
// Default time to current time
|
||||
Calendar cal = Calendar.getInstance();
|
||||
String defaultTime = String.format(Locale.getDefault(), "%02d:%02d", cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE));
|
||||
selectedTimes.add(defaultTime);
|
||||
refreshTimeChips();
|
||||
}
|
||||
|
||||
builder.setView(view)
|
||||
.setPositiveButton("Guardar", (dialog, id) -> {
|
||||
String name = editName.getText().toString();
|
||||
String notes = editNotes.getText().toString();
|
||||
|
||||
// Join times with comma
|
||||
StringBuilder timeBuilder = new StringBuilder();
|
||||
for (int i = 0; i < selectedTimes.size(); i++) {
|
||||
timeBuilder.append(selectedTimes.get(i));
|
||||
if (i < selectedTimes.size() - 1) timeBuilder.append(", ");
|
||||
}
|
||||
String time = timeBuilder.toString();
|
||||
|
||||
int selectedId = radioGroupRoute.getCheckedRadioButtonId();
|
||||
String dosage = "Via não especificada";
|
||||
|
||||
if (selectedId == R.id.radio_oral) {
|
||||
dosage = "Via Oral";
|
||||
} else if (selectedId == R.id.radio_topical) {
|
||||
dosage = "Via Tópica";
|
||||
} else if (selectedId == R.id.radio_inhalatory) {
|
||||
dosage = "Via Inalatória";
|
||||
}
|
||||
|
||||
if (medicationToEdit != null) {
|
||||
medicationToEdit.name = name;
|
||||
medicationToEdit.dosage = dosage;
|
||||
medicationToEdit.notes = notes;
|
||||
medicationToEdit.time = time;
|
||||
if (listener != null)
|
||||
listener.onSave(medicationToEdit);
|
||||
} else {
|
||||
Medication newMed = new Medication(name, time, dosage, notes, null);
|
||||
if (listener != null)
|
||||
listener.onSave(newMed);
|
||||
}
|
||||
});
|
||||
|
||||
if (medicationToEdit != null) {
|
||||
builder.setNeutralButton("Eliminar", (dialog, id) -> {
|
||||
if (deleteListener != null) {
|
||||
deleteListener.onDelete(medicationToEdit);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AlertDialog alertDialog = builder.create();
|
||||
|
||||
alertDialog.setOnShowListener(d -> {
|
||||
android.widget.Button btnPos = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
if (btnPos != null) {
|
||||
// Apply our custom outline drawable to "Guardar"
|
||||
btnPos.setBackgroundResource(R.drawable.btn_outline_primary);
|
||||
btnPos.setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), R.color.primary_color));
|
||||
|
||||
int paddingPx = (int) (16 * getResources().getDisplayMetrics().density);
|
||||
btnPos.setPadding(paddingPx, 0, paddingPx, 0);
|
||||
}
|
||||
|
||||
android.widget.Button btnNeu = alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL);
|
||||
if (btnNeu != null) {
|
||||
btnNeu.setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), R.color.error_color));
|
||||
btnNeu.setBackgroundResource(R.drawable.btn_outline_error);
|
||||
|
||||
int paddingPx = (int) (16 * getResources().getDisplayMetrics().density);
|
||||
btnNeu.setPadding(paddingPx, 0, paddingPx, 0);
|
||||
|
||||
android.view.ViewGroup.LayoutParams lp = btnNeu.getLayoutParams();
|
||||
if (lp instanceof android.view.ViewGroup.MarginLayoutParams) {
|
||||
android.view.ViewGroup.MarginLayoutParams marginLp = (android.view.ViewGroup.MarginLayoutParams) lp;
|
||||
int marginPx = (int) (8 * getResources().getDisplayMetrics().density);
|
||||
marginLp.setMargins(marginLp.leftMargin, marginLp.topMargin, marginLp.rightMargin + marginPx, marginLp.bottomMargin);
|
||||
btnNeu.setLayoutParams(marginLp);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return alertDialog;
|
||||
}
|
||||
|
||||
private void showTimePicker() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
int hour = cal.get(Calendar.HOUR_OF_DAY);
|
||||
int minute = cal.get(Calendar.MINUTE);
|
||||
|
||||
TimePickerDialog timePickerDialog = new TimePickerDialog(getContext(),
|
||||
(view, hourOfDay, minute1) -> {
|
||||
String time = String.format(Locale.getDefault(), "%02d:%02d", hourOfDay, minute1);
|
||||
if (!selectedTimes.contains(time)) {
|
||||
selectedTimes.add(time);
|
||||
Collections.sort(selectedTimes);
|
||||
refreshTimeChips();
|
||||
}
|
||||
},
|
||||
hour, minute, true);
|
||||
timePickerDialog.show();
|
||||
}
|
||||
|
||||
private void refreshTimeChips() {
|
||||
if (chipGroupTimes == null) return;
|
||||
chipGroupTimes.removeAllViews();
|
||||
for (String time : selectedTimes) {
|
||||
Chip chip = new Chip(requireContext());
|
||||
chip.setText(time);
|
||||
chip.setCloseIconVisible(true);
|
||||
chip.setOnCloseIconClickListener(v -> {
|
||||
selectedTimes.remove(time);
|
||||
refreshTimeChips();
|
||||
});
|
||||
chipGroupTimes.addView(chip);
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchAllMedsOnce() {
|
||||
String dbUrl = "https://cuidamais-7b904-default-rtdb.firebaseio.com/";
|
||||
DatabaseReference rootRef = FirebaseDatabase.getInstance(dbUrl).getReference();
|
||||
String[] nodes = {"medication", "medicamentos", "Medicamentos", "comprimidos"};
|
||||
|
||||
fullPillsList.clear();
|
||||
|
||||
// 1. Tentar nos nós específicos
|
||||
for (String node : nodes) {
|
||||
rootRef.child(node).addListenerForSingleValueEvent(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
if (snapshot.exists()) {
|
||||
parseSnapshot(snapshot, "Nó: " + node);
|
||||
}
|
||||
}
|
||||
@Override public void onCancelled(@NonNull DatabaseError error) {}
|
||||
});
|
||||
}
|
||||
|
||||
// 2. Tentar também na raiz (caso os medicamentos estejam diretamente no topo)
|
||||
rootRef.limitToFirst(50).addListenerForSingleValueEvent(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
if (snapshot.exists()) {
|
||||
parseSnapshot(snapshot, "Raiz");
|
||||
}
|
||||
}
|
||||
@Override public void onCancelled(@NonNull DatabaseError error) {}
|
||||
});
|
||||
}
|
||||
|
||||
private void parseSnapshot(DataSnapshot snapshot, String source) {
|
||||
int count = 0;
|
||||
for (DataSnapshot child : snapshot.getChildren()) {
|
||||
String name = child.child("nome").getValue(String.class);
|
||||
if (name == null) name = child.child("name").getValue(String.class);
|
||||
if (name == null && !(child.getValue() instanceof java.util.Map)) {
|
||||
// Se o valor for a própria string (ex: "Paracetamol")
|
||||
name = child.getValue() instanceof String ? (String) child.getValue() : null;
|
||||
}
|
||||
if (name == null) name = child.getKey();
|
||||
|
||||
String dosage = child.child("dosagem").getValue(String.class);
|
||||
if (dosage == null) dosage = child.child("dosage").getValue(String.class);
|
||||
if (dosage == null) dosage = "";
|
||||
|
||||
if (name != null && !name.isEmpty()) {
|
||||
boolean exists = false;
|
||||
for (Comprimido p : fullPillsList) {
|
||||
if (name.equals(p.nome)) { exists = true; break; }
|
||||
}
|
||||
if (!exists) {
|
||||
fullPillsList.add(new Comprimido(name, dosage));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count > 0 && getContext() != null) {
|
||||
Log.d("FirebaseSearch", "Carregados " + count + " de " + source);
|
||||
// Toast.makeText(getContext(), "Fonte: " + source + " (" + count + ")", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void filterMedsLocally(String query) {
|
||||
searchResults.clear();
|
||||
if (query.isEmpty()) {
|
||||
recyclerResults.setVisibility(View.GONE);
|
||||
recyclerAdapter.notifyDataSetChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
String lowerQuery = query.toLowerCase();
|
||||
for (Comprimido p : fullPillsList) {
|
||||
if (p.nome != null && p.nome.toLowerCase().contains(lowerQuery)) {
|
||||
searchResults.add(p);
|
||||
}
|
||||
}
|
||||
|
||||
recyclerAdapter.notifyDataSetChanged();
|
||||
recyclerResults.setVisibility(searchResults.isEmpty() ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
private void handleError(DatabaseError error) {
|
||||
Log.e("FirebaseSearch", "Erro: " + error.getMessage());
|
||||
if (getContext() != null) {
|
||||
Toast.makeText(getContext(), "Erro no Firebase: " + error.getMessage(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
141
documentacao_projecto/backups_codigo/MedicationFragment.java
Normal file
141
documentacao_projecto/backups_codigo/MedicationFragment.java
Normal file
@@ -0,0 +1,141 @@
|
||||
package com.example.cuida.ui.medication;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import com.example.cuida.data.model.Medication;
|
||||
import com.example.cuida.databinding.FragmentMedicationBinding;
|
||||
|
||||
public class MedicationFragment extends Fragment {
|
||||
|
||||
private FragmentMedicationBinding binding;
|
||||
private MedicationViewModel medicationViewModel;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
medicationViewModel = new ViewModelProvider(this).get(MedicationViewModel.class);
|
||||
|
||||
binding = FragmentMedicationBinding.inflate(inflater, container, false);
|
||||
|
||||
MedicationAdapter adapter = new MedicationAdapter(new MedicationAdapter.OnItemClickListener() {
|
||||
@Override
|
||||
public void onCheckClick(Medication medication) {
|
||||
medicationViewModel.update(medication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(Medication medication) {
|
||||
showMedicationDialog(medication);
|
||||
}
|
||||
});
|
||||
|
||||
binding.recyclerMedication.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
binding.recyclerMedication.setAdapter(adapter);
|
||||
|
||||
medicationViewModel.getAllMedications().observe(getViewLifecycleOwner(), medications -> {
|
||||
adapter.setMedications(medications);
|
||||
|
||||
if (medications != null && !medications.isEmpty()) {
|
||||
binding.recyclerMedication.setVisibility(View.VISIBLE);
|
||||
binding.textEmptyMedications.setVisibility(View.GONE);
|
||||
} else {
|
||||
binding.recyclerMedication.setVisibility(View.GONE);
|
||||
binding.textEmptyMedications.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
binding.fabAddMedication.setOnClickListener(v -> showMedicationDialog(null));
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
private void showMedicationDialog(Medication medication) {
|
||||
MedicationDialog dialog = new MedicationDialog();
|
||||
dialog.setMedicationToEdit(medication);
|
||||
dialog.setListener(medicationToSave -> {
|
||||
// If it's an edit, cancel old alarms first
|
||||
if (medication != null && medication.time != null) {
|
||||
String[] oldTimes = medication.time.split(",\\s*");
|
||||
for (String t : oldTimes) {
|
||||
if (t.isEmpty()) continue;
|
||||
try {
|
||||
int oldId = (medication.name + t).hashCode();
|
||||
com.example.cuida.utils.AlarmScheduler.cancelAlarm(requireContext(), oldId);
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}
|
||||
|
||||
if (medication == null) {
|
||||
medicationViewModel.insert(medicationToSave);
|
||||
} else {
|
||||
medicationViewModel.update(medicationToSave);
|
||||
}
|
||||
|
||||
String[] times = medicationToSave.time.split(",\\s*");
|
||||
for (String t : times) {
|
||||
if (t.isEmpty()) continue;
|
||||
try {
|
||||
String[] timeParts = t.split(":");
|
||||
int hour = Integer.parseInt(timeParts[0]);
|
||||
int minute = Integer.parseInt(timeParts[1]);
|
||||
|
||||
java.util.Calendar calendar = java.util.Calendar.getInstance();
|
||||
calendar.set(java.util.Calendar.HOUR_OF_DAY, hour);
|
||||
calendar.set(java.util.Calendar.MINUTE, minute);
|
||||
calendar.set(java.util.Calendar.SECOND, 0);
|
||||
|
||||
if (calendar.getTimeInMillis() <= System.currentTimeMillis()) {
|
||||
calendar.add(java.util.Calendar.DAY_OF_YEAR, 1);
|
||||
}
|
||||
|
||||
String title = "Hora do Medicamento";
|
||||
String msg = "É hora de tomar: " + medicationToSave.name + " (" + medicationToSave.dosage + ")";
|
||||
|
||||
int alarmId = (medicationToSave.name + t).hashCode();
|
||||
|
||||
com.example.cuida.utils.AlarmScheduler.scheduleAlarm(
|
||||
requireContext(),
|
||||
calendar.getTimeInMillis(),
|
||||
title,
|
||||
msg,
|
||||
alarmId);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.setDeleteListener(medicationToDelete -> {
|
||||
medicationViewModel.delete(medicationToDelete);
|
||||
|
||||
// Cancel all alarms for this medication
|
||||
if (medicationToDelete.time != null) {
|
||||
String[] times = medicationToDelete.time.split(",\\s*");
|
||||
for (String t : times) {
|
||||
if (t.isEmpty()) continue;
|
||||
try {
|
||||
int alarmId = (medicationToDelete.name + t).hashCode();
|
||||
com.example.cuida.utils.AlarmScheduler.cancelAlarm(requireContext(), alarmId);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dialog.show(getParentFragmentManager(), "MedicationDialog");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
118
documentacao_projecto/backups_codigo/MedicationViewModel.java
Normal file
118
documentacao_projecto/backups_codigo/MedicationViewModel.java
Normal file
@@ -0,0 +1,118 @@
|
||||
package com.example.cuida.ui.medication;
|
||||
|
||||
import android.app.Application;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import com.example.cuida.data.model.Medication;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.firestore.FirebaseFirestore;
|
||||
import com.google.firebase.firestore.Query;
|
||||
import com.google.firebase.firestore.QueryDocumentSnapshot;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MedicationViewModel extends AndroidViewModel {
|
||||
|
||||
private final MutableLiveData<List<Medication>> allMedications = new MutableLiveData<>(new ArrayList<>());
|
||||
private final MutableLiveData<Medication> nextMedication = new MutableLiveData<>(null);
|
||||
private final FirebaseFirestore db;
|
||||
private final FirebaseAuth auth;
|
||||
|
||||
public MedicationViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
db = FirebaseFirestore.getInstance();
|
||||
auth = FirebaseAuth.getInstance();
|
||||
fetchMedications();
|
||||
}
|
||||
|
||||
private void fetchMedications() {
|
||||
if (auth.getCurrentUser() == null)
|
||||
return;
|
||||
String userId = auth.getCurrentUser().getUid();
|
||||
|
||||
db.collection("medicamentos")
|
||||
.whereEqualTo("userId", userId)
|
||||
.addSnapshotListener((value, error) -> {
|
||||
if (error != null) {
|
||||
Log.e("MedicationViewModel", "Listen failed.", error);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Medication> meds = new ArrayList<>();
|
||||
if (value != null) {
|
||||
for (QueryDocumentSnapshot doc : value) {
|
||||
Medication med = doc.toObject(Medication.class);
|
||||
med.id = doc.getId(); // Ensure ID is set
|
||||
meds.add(med);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort locally to avoid needing a composite index in Firestore
|
||||
meds.sort((m1, m2) -> {
|
||||
if (m1.time == null && m2.time == null) return 0;
|
||||
if (m1.time == null) return 1;
|
||||
if (m2.time == null) return -1;
|
||||
return m1.time.compareTo(m2.time);
|
||||
});
|
||||
|
||||
allMedications.setValue(meds);
|
||||
|
||||
if (!meds.isEmpty()) {
|
||||
nextMedication.setValue(meds.get(0));
|
||||
} else {
|
||||
nextMedication.setValue(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public LiveData<List<Medication>> getAllMedications() {
|
||||
return allMedications;
|
||||
}
|
||||
|
||||
public LiveData<Medication> getNextMedication() {
|
||||
return nextMedication;
|
||||
}
|
||||
|
||||
public void insert(Medication medication) {
|
||||
if (auth.getCurrentUser() == null)
|
||||
return;
|
||||
String userId = auth.getCurrentUser().getUid();
|
||||
|
||||
medication.userId = userId;
|
||||
|
||||
db.collection("medicamentos")
|
||||
.add(medication)
|
||||
.addOnSuccessListener(documentReference -> Log.d("MedicationViewModel", "Medication added"))
|
||||
.addOnFailureListener(e -> Log.w("MedicationViewModel", "Error adding medication", e));
|
||||
}
|
||||
|
||||
public void update(Medication medication) {
|
||||
if (auth.getCurrentUser() == null || medication.id == null)
|
||||
return;
|
||||
String userId = auth.getCurrentUser().getUid();
|
||||
|
||||
medication.userId = userId;
|
||||
|
||||
db.collection("medicamentos")
|
||||
.document(medication.id)
|
||||
.set(medication)
|
||||
.addOnSuccessListener(aVoid -> Log.d("MedicationViewModel", "Medication updated"))
|
||||
.addOnFailureListener(e -> Log.w("MedicationViewModel", "Error updating medication", e));
|
||||
}
|
||||
|
||||
public void delete(Medication medication) {
|
||||
if (auth.getCurrentUser() == null || medication.id == null)
|
||||
return;
|
||||
|
||||
db.collection("medicamentos")
|
||||
.document(medication.id)
|
||||
.delete()
|
||||
.addOnSuccessListener(aVoid -> Log.d("MedicationViewModel", "Medication deleted"))
|
||||
.addOnFailureListener(e -> Log.w("MedicationViewModel", "Error deleting medication", e));
|
||||
}
|
||||
}
|
||||
111
documentacao_projecto/backups_codigo/dialog_add_medication.xml
Normal file
111
documentacao_projecto/backups_codigo/dialog_add_medication.xml
Normal file
@@ -0,0 +1,111 @@
|
||||
<?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">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/layout_med_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:hint="Nome do Medicamento"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edit_med_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textCapWords" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="4dp">
|
||||
|
||||
<TextView
|
||||
android:text="Horários"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_add_time"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Adicionar"
|
||||
android:padding="0dp"
|
||||
android:minWidth="0dp"
|
||||
android:minHeight="0dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/chip_group_times"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:padding="4dp"/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:text="Via de Administração"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/radio_group_route"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radio_oral"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Via Oral (Pela boca)" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radio_topical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Via Tópica (Na pele)" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radio_inhalatory"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Via Inalatória (Pelo nariz/boca)" />
|
||||
</RadioGroup>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Notas (Opcional)"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edit_med_notes"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="2"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
Reference in New Issue
Block a user