ja meti o droplist nos medicamentos

This commit is contained in:
2026-04-14 17:14:37 +01:00
parent 990eb94142
commit cbfb87d052
425 changed files with 18569 additions and 18023 deletions

View File

@@ -0,0 +1,18 @@
package com.example.cuida.data.model;
public class Comprimido {
public String nome;
public String dosagem;
public Comprimido() {}
public Comprimido(String nome, String dosagem) {
this.nome = nome;
this.dosagem = dosagem;
}
@Override
public String toString() {
return nome;
}
}

View File

@@ -0,0 +1,54 @@
package com.example.cuida.ui.medication;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.cuida.R;
import com.example.cuida.data.model.Comprimido;
import java.util.List;
public class ComprimidoRecyclerAdapter extends RecyclerView.Adapter<ComprimidoRecyclerAdapter.ViewHolder> {
private List<Comprimido> pills;
private OnItemClickListener listener;
public interface OnItemClickListener {
void onItemClick(Comprimido comprimido);
}
public ComprimidoRecyclerAdapter(List<Comprimido> pills, OnItemClickListener listener) {
this.pills = pills;
this.listener = listener;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comprimido_search, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Comprimido pill = pills.get(position);
holder.textName.setText(pill.nome);
holder.itemView.setOnClickListener(v -> listener.onItemClick(pill));
}
@Override
public int getItemCount() {
return pills.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView textName;
public ViewHolder(@NonNull View itemView) {
super(itemView);
textName = itemView.findViewById(R.id.text_pill_name);
}
}
}

View File

@@ -7,6 +7,10 @@ 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;
@@ -15,10 +19,28 @@ 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;
public class MedicationDialog extends DialogFragment {
private EditText editName, editNotes;
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 TextView textTime;
@@ -54,6 +76,7 @@ public class MedicationDialog extends DialogFragment {
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);
textTime = view.findViewById(R.id.text_med_time);
@@ -62,6 +85,44 @@ public class MedicationDialog extends DialogFragment {
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
textTime.setOnClickListener(v -> showTimePicker());
@@ -186,4 +247,94 @@ public class MedicationDialog extends DialogFragment {
String time = String.format(Locale.getDefault(), "%02d:%02d", hourOfDay, minute);
textTime.setText(time);
}
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();
}
}
}

View File

@@ -107,21 +107,14 @@ public class ScheduleAppointmentFragment extends Fragment {
}
private void setupDoctorSpinner() {
java.util.List<String> doctors = new java.util.ArrayList<>();
doctors.add("Dr. Paulo Silva - Clínica Geral");
doctors.add("Dra. Maria Mendes - Pediatria (Crianças)");
doctors.add("Dr. Rui Costa - Cardiologia (Coração)");
doctors.add("Dra. Ana Ferreira - Dermatologia (Pele)");
doctors.add("Dr. João Almeida - Ortopedia (Ossos)");
doctors.add("Dra. Sofia Martins - Oftalmologia (Olhos)");
doctors.add("Dr. Pedro Oliveira - Psiquiatria (Saúde Mental)");
doctors.add("Dra. Inês Cardoso - Ginecologia (Mulher)");
doctors.add("Dr. Tiago Santos - Neurologia (Cérebro)");
java.util.Collections.shuffle(doctors); // Randomize the names as requested
ArrayAdapter<String> adapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_dropdown_item_1line, doctors);
spinnerDoctor.setAdapter(adapter);
scheduleViewModel.getDoctorsList().observe(getViewLifecycleOwner(), doctors -> {
if (doctors != null) {
java.util.List<String> shuffledDoctors = new java.util.ArrayList<>(doctors);
java.util.Collections.shuffle(shuffledDoctors); // Randomize the names as requested
ArrayAdapter<String> adapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_dropdown_item_1line, shuffledDoctors);
spinnerDoctor.setAdapter(adapter);
}
});
}
private void setupDatePicker() {

View File

@@ -26,11 +26,46 @@ public class ScheduleViewModel extends AndroidViewModel {
private final MutableLiveData<String> selectedTime = new MutableLiveData<>();
private final MutableLiveData<List<TimeSlot>> timeSlots = new MutableLiveData<>();
private final MutableLiveData<Boolean> saveSuccess = new MutableLiveData<>();
private final MutableLiveData<List<String>> doctorsList = new MutableLiveData<>(new ArrayList<>());
public ScheduleViewModel(@NonNull Application application) {
super(application);
db = FirebaseFirestore.getInstance();
auth = FirebaseAuth.getInstance();
fetchDoctors();
}
private void fetchDoctors() {
db.collection("medicos")
.get()
.addOnCompleteListener(task -> {
if (task.isSuccessful() && task.getResult() != null) {
List<String> docs = new ArrayList<>();
for (QueryDocumentSnapshot document : task.getResult()) {
String name = document.getString("nome");
String specialty = document.getString("especialidade");
String gender = document.getString("genero");
if (name != null) {
String displayName = name;
if (specialty != null && !specialty.isEmpty()) {
displayName += " - " + specialty;
}
if (!displayName.startsWith("Dr.") && !displayName.startsWith("Dra.")) {
if ("Feminino".equalsIgnoreCase(gender)) {
displayName = "Dra. " + displayName;
} else {
displayName = "Dr. " + displayName;
}
}
docs.add(displayName);
}
}
doctorsList.postValue(docs);
} else {
Log.e("ScheduleViewModel", "Error getting doctors", task.getException());
}
});
}
public void setDate(int year, int month, int dayOfMonth) {
@@ -66,6 +101,10 @@ public class ScheduleViewModel extends AndroidViewModel {
return saveSuccess;
}
public LiveData<List<String>> getDoctorsList() {
return doctorsList;
}
private void loadTimeSlots(String date) {
// Init slots immediately to prevent "disappearing" hours while waiting for
// network.

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF" />
<stroke android:width="1dp" android:color="#DDDDDD" />
<corners android:radius="8dp" />
</shape>

View File

@@ -5,25 +5,49 @@
android:orientation="vertical"
android:padding="24dp">
<com.google.android.material.textfield.TextInputLayout
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nome do Medicamento"
android:layout_marginBottom="16dp">
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_med_name"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textCapWords" />
</com.google.android.material.textfield.TextInputLayout>
android:orientation="vertical">
<TextView
android:text="Horário"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginBottom="4dp"/>
<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>
<TextView
android:text="Horário"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginBottom="4dp"/>
<!-- O resto do conteúdo do diálogo continua aqui em baixo -->
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_search_results"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="60dp"
android:visibility="gone"
android:elevation="8dp"
android:background="@drawable/bg_search_results" />
</FrameLayout>
<TextView
android:id="@+id/text_med_time"

View File

@@ -0,0 +1,16 @@
<?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="12dp">
<TextView
android:id="@+id/text_pill_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@color/primary_color" />
</LinearLayout>