ja acabei a app acho?
This commit is contained in:
@@ -18,7 +18,7 @@ public class Gemini {
|
||||
public Gemini() {
|
||||
// 1. Configurar o modelo (usa a tua API Key do Google AI Studio)
|
||||
GenerativeModel generativeModel = new GenerativeModel(
|
||||
"gemini-1.5-flash",
|
||||
"gemini-2.5-flash",
|
||||
"AIzaSyBmLgn-SHaTDvAeDWsw2iTZRR9gahhOu7k");
|
||||
this.modelo = GenerativeModelFutures.from(generativeModel);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ public class MedicationAdapter extends RecyclerView.Adapter<MedicationAdapter.Me
|
||||
|
||||
public interface OnItemClickListener {
|
||||
void onCheckClick(Medication medication);
|
||||
|
||||
void onItemClick(Medication medication);
|
||||
}
|
||||
|
||||
public MedicationAdapter(OnItemClickListener listener) {
|
||||
@@ -60,7 +62,7 @@ public class MedicationAdapter extends RecyclerView.Adapter<MedicationAdapter.Me
|
||||
return medicationList.size();
|
||||
}
|
||||
|
||||
public static class MedicationViewHolder extends RecyclerView.ViewHolder {
|
||||
public class MedicationViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView textName, textDosage, textTime, textNotes;
|
||||
CheckBox checkBoxTaken;
|
||||
|
||||
@@ -71,6 +73,13 @@ public class MedicationAdapter extends RecyclerView.Adapter<MedicationAdapter.Me
|
||||
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));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
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.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;
|
||||
|
||||
public class MedicationDialog extends DialogFragment {
|
||||
|
||||
private EditText editName, editNotes;
|
||||
private android.widget.CheckBox checkOral, checkTopical, checkInhalatory;
|
||||
private TextView textTime;
|
||||
private Medication medicationToEdit;
|
||||
private OnMedicationSaveListener listener;
|
||||
|
||||
public interface OnMedicationSaveListener {
|
||||
void onSave(Medication medication);
|
||||
}
|
||||
|
||||
public void setListener(OnMedicationSaveListener listener) {
|
||||
this.listener = 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);
|
||||
editNotes = view.findViewById(R.id.edit_med_notes);
|
||||
textTime = view.findViewById(R.id.text_med_time);
|
||||
|
||||
checkOral = view.findViewById(R.id.checkbox_oral);
|
||||
checkTopical = view.findViewById(R.id.checkbox_topical);
|
||||
checkInhalatory = view.findViewById(R.id.checkbox_inhalatory);
|
||||
|
||||
// Set up TimePicker
|
||||
textTime.setOnClickListener(v -> showTimePicker());
|
||||
|
||||
if (medicationToEdit != null) {
|
||||
editName.setText(medicationToEdit.name);
|
||||
editNotes.setText(medicationToEdit.notes);
|
||||
textTime.setText(medicationToEdit.time);
|
||||
|
||||
// Parse dosage string to set checkboxes
|
||||
String dosage = medicationToEdit.dosage;
|
||||
if (dosage != null) {
|
||||
checkOral.setChecked(dosage.contains("Oral"));
|
||||
checkTopical.setChecked(dosage.contains("Tópica"));
|
||||
checkInhalatory.setChecked(dosage.contains("Inalatória"));
|
||||
}
|
||||
|
||||
builder.setTitle("Editar Medicamento");
|
||||
} else {
|
||||
builder.setTitle("Adicionar Medicamento");
|
||||
// Default time to current time
|
||||
Calendar cal = Calendar.getInstance();
|
||||
updateTimeLabel(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE));
|
||||
}
|
||||
|
||||
builder.setView(view)
|
||||
.setPositiveButton("Guardar", (dialog, id) -> {
|
||||
String name = editName.getText().toString();
|
||||
String notes = editNotes.getText().toString();
|
||||
String time = textTime.getText().toString();
|
||||
|
||||
StringBuilder dosageBuilder = new StringBuilder();
|
||||
if (checkOral.isChecked())
|
||||
dosageBuilder.append("Via Oral, ");
|
||||
if (checkTopical.isChecked())
|
||||
dosageBuilder.append("Via Tópica, ");
|
||||
if (checkInhalatory.isChecked())
|
||||
dosageBuilder.append("Via Inalatória, ");
|
||||
|
||||
String dosage = dosageBuilder.toString();
|
||||
if (dosage.endsWith(", ")) {
|
||||
dosage = dosage.substring(0, dosage.length() - 2);
|
||||
} else if (dosage.isEmpty()) {
|
||||
dosage = "Via não especificada";
|
||||
}
|
||||
|
||||
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);
|
||||
if (listener != null)
|
||||
listener.onSave(newMed);
|
||||
}
|
||||
})
|
||||
.setNegativeButton("Cancelar", (dialog, id) -> dismiss());
|
||||
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
private void showTimePicker() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
int hour = cal.get(Calendar.HOUR_OF_DAY);
|
||||
int minute = cal.get(Calendar.MINUTE);
|
||||
|
||||
if (medicationToEdit != null) {
|
||||
try {
|
||||
String[] parts = medicationToEdit.time.split(":");
|
||||
hour = Integer.parseInt(parts[0]);
|
||||
minute = Integer.parseInt(parts[1]);
|
||||
} catch (Exception e) {
|
||||
// Use current time if parsing fails
|
||||
}
|
||||
}
|
||||
|
||||
TimePickerDialog timePickerDialog = new TimePickerDialog(getContext(),
|
||||
(view, hourOfDay, minute1) -> updateTimeLabel(hourOfDay, minute1),
|
||||
hour, minute, true);
|
||||
timePickerDialog.show();
|
||||
}
|
||||
|
||||
private void updateTimeLabel(int hourOfDay, int minute) {
|
||||
String time = String.format(Locale.getDefault(), "%02d:%02d", hourOfDay, minute);
|
||||
textTime.setText(time);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ 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 {
|
||||
@@ -21,9 +22,18 @@ public class MedicationFragment extends Fragment {
|
||||
|
||||
binding = FragmentMedicationBinding.inflate(inflater, container, false);
|
||||
|
||||
MedicationAdapter adapter = new MedicationAdapter(medication -> {
|
||||
medicationViewModel.update(medication);
|
||||
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);
|
||||
|
||||
@@ -31,9 +41,25 @@ public class MedicationFragment extends Fragment {
|
||||
adapter.setMedications(medications);
|
||||
});
|
||||
|
||||
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 (medication == null) {
|
||||
medicationViewModel.insert(medicationToSave);
|
||||
} else {
|
||||
medicationViewModel.update(medicationToSave);
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
dialog.show(getParentFragmentManager(), "MedicationDialog");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
@@ -30,6 +30,12 @@ public class MedicationViewModel extends AndroidViewModel {
|
||||
return nextMedication;
|
||||
}
|
||||
|
||||
public void insert(Medication medication) {
|
||||
AppDatabase.databaseWriteExecutor.execute(() -> {
|
||||
AppDatabase.getDatabase(getApplication()).medicationDao().insert(medication);
|
||||
});
|
||||
}
|
||||
|
||||
public void update(Medication medication) {
|
||||
AppDatabase.databaseWriteExecutor.execute(() -> {
|
||||
AppDatabase.getDatabase(getApplication()).medicationDao().update(medication);
|
||||
|
||||
@@ -45,7 +45,7 @@ public class Sns24Fragment extends Fragment {
|
||||
|
||||
// 1. Inicializar o Modelo Gemini
|
||||
// NOTA: Substitua "SUA_API_KEY" pela sua chave do Google AI Studio
|
||||
GenerativeModel gm = new GenerativeModel("gemini-1.5-flash", API_KEY);
|
||||
GenerativeModel gm = new GenerativeModel("gemini-2.5-flash", API_KEY);
|
||||
model = GenerativeModelFutures.from(gm);
|
||||
|
||||
// 2. Botão Ligar SNS 24
|
||||
@@ -71,12 +71,15 @@ public class Sns24Fragment extends Fragment {
|
||||
binding.buttonAiTriage.setEnabled(false);
|
||||
binding.textAiResult.setVisibility(View.VISIBLE);
|
||||
binding.textAiResult.setText("A analisar sintomas com IA...");
|
||||
binding.buttonFindHospital.setVisibility(View.GONE);
|
||||
|
||||
// Criar o prompt
|
||||
Content content = new Content.Builder()
|
||||
.addText("Atua como um assistente de triagem de saúde. O utilizador diz: \"" + symptoms + "\". " +
|
||||
"Dá uma resposta curta (máximo 4 linhas) sobre a urgência e se deve ligar para o SNS 24 (808242424). "
|
||||
"Se a situação exigir avaliação médica imediata ou urgência, começa a resposta com 'URGENTE: HOSPITAL'. "
|
||||
+
|
||||
"Caso contrário, dá apenas o conselho habitual. " +
|
||||
"Dá uma resposta curta (máximo 4 linhas). " +
|
||||
"Aviso: Isto não substitui aconselhamento médico.")
|
||||
.build();
|
||||
|
||||
@@ -93,8 +96,19 @@ public class Sns24Fragment extends Fragment {
|
||||
@Override
|
||||
public void onSuccess(GenerateContentResponse result) {
|
||||
if (getActivity() != null) {
|
||||
binding.textAiResult.setText(result.getText());
|
||||
String text = result.getText();
|
||||
binding.textAiResult.setText(text);
|
||||
binding.buttonAiTriage.setEnabled(true);
|
||||
|
||||
if (text != null && text.contains("URGENTE: HOSPITAL")) {
|
||||
binding.buttonFindHospital.setVisibility(View.VISIBLE);
|
||||
binding.buttonFindHospital.setOnClickListener(v -> {
|
||||
Uri gmmIntentUri = Uri.parse("geo:0,0?q=hospital");
|
||||
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
|
||||
mapIntent.setPackage("com.google.android.apps.maps");
|
||||
startActivity(mapIntent);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
79
app/src/main/res/layout/dialog_add_medication.xml
Normal file
79
app/src/main/res/layout/dialog_add_medication.xml
Normal file
@@ -0,0 +1,79 @@
|
||||
<?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">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Nome do Medicamento"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<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"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_med_time"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="08:00"
|
||||
android:textSize="18sp"
|
||||
android:padding="12dp"
|
||||
android:background="#E0E0E0"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:text="Via de Administração"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/checkbox_oral"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Via Oral (Pela boca)" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/checkbox_topical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Via Tópica (Na pele)" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/checkbox_inhalatory"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Via Inalatória (Pelo nariz/boca)"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<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>
|
||||
@@ -1,22 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/title_medication"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/primary_color"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_medication"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_title"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
</LinearLayout>
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab_add_medication"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:src="@android:drawable/ic_input_add"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:contentDescription="Adicionar Medicamento"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@@ -75,6 +75,18 @@
|
||||
android:textColor="@android:color/black"
|
||||
android:padding="16dp"
|
||||
android:background="#F5F5F5"
|
||||
android:visibility="gone"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_find_hospital"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:text="Ver Hospital Mais Próximo"
|
||||
android:textSize="16sp"
|
||||
android:backgroundTint="@android:color/holo_red_dark"
|
||||
app:icon="@android:drawable/ic_menu_mapmode"
|
||||
app:cornerRadius="8dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
Reference in New Issue
Block a user