ja acabei a app acho?

This commit is contained in:
2026-02-12 10:38:13 +00:00
parent a71553d54f
commit e01d7ae871
142 changed files with 3497 additions and 2904 deletions

View File

@@ -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);
}

View File

@@ -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));
}
});
}
}
}

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);
});
}
}
}

View 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>

View File

@@ -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>

View File

@@ -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>