falta o esqueci a palavra passe
This commit is contained in:
@@ -1,42 +1,31 @@
|
||||
package com.example.cuida.services;
|
||||
|
||||
import com.google.ai.client.generativeai.GenerativeModel;
|
||||
import com.google.ai.client.generativeai.java.GenerativeModelFutures;
|
||||
import com.google.ai.client.generativeai.type.Content;
|
||||
import com.google.ai.client.generativeai.type.GenerateContentResponse;
|
||||
import com.google.ai.client.generativeai.type.HarmCategory;
|
||||
import com.google.ai.client.generativeai.type.SafetySetting;
|
||||
import com.google.ai.client.generativeai.type.BlockThreshold;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class Gemini {
|
||||
private final GenerativeModelFutures modelo;
|
||||
private static final String API_KEY = "AIzaSyBmLgn-SHaTDvAeDWsw2iTZRR9gahhOu7k";
|
||||
private static final String MODEL_NAME = "gemini-flash-latest"; // O gemini-1.5-flash foi descontinuado e removido da API
|
||||
private static final String API_URL = "https://generativelanguage.googleapis.com/v1beta/models/" + MODEL_NAME + ":generateContent?key=" + API_KEY;
|
||||
private final OkHttpClient client;
|
||||
private final Handler mainHandler;
|
||||
|
||||
public Gemini() {
|
||||
// 1. Configurar Segurança (Padrão para evitar bloqueio de termos médicos)
|
||||
List<SafetySetting> safetySettings = Arrays.asList(
|
||||
new SafetySetting(HarmCategory.HARASSMENT, BlockThreshold.NONE),
|
||||
new SafetySetting(HarmCategory.HATE_SPEECH, BlockThreshold.NONE),
|
||||
new SafetySetting(HarmCategory.SEXUALLY_EXPLICIT, BlockThreshold.NONE),
|
||||
new SafetySetting(HarmCategory.DANGEROUS_CONTENT, BlockThreshold.NONE)
|
||||
);
|
||||
|
||||
// 2. Modelo (Simplificado ao máximo para garantir compilação)
|
||||
GenerativeModel generativeModel = new GenerativeModel(
|
||||
"gemini-1.5-flash",
|
||||
"AIzaSyBmLgn-SHaTDvAeDWsw2iTZRR9gahhOu7k",
|
||||
null, // Usamos o GenerationConfig padrão para evitar erro de setTemperature
|
||||
safetySettings
|
||||
);
|
||||
|
||||
this.modelo = GenerativeModelFutures.from(generativeModel);
|
||||
this.client = new OkHttpClient();
|
||||
this.mainHandler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
public interface GeminiCallback {
|
||||
@@ -45,27 +34,56 @@ public class Gemini {
|
||||
}
|
||||
|
||||
public void fazerPergunta(String promptUtilizador, GeminiCallback callback) {
|
||||
Content conteudo = new Content.Builder()
|
||||
.addText(promptUtilizador)
|
||||
.build();
|
||||
try {
|
||||
JSONObject jsonBody = new JSONObject();
|
||||
JSONArray contents = new JSONArray();
|
||||
JSONObject content = new JSONObject();
|
||||
JSONArray parts = new JSONArray();
|
||||
JSONObject part = new JSONObject();
|
||||
|
||||
ListenableFuture<GenerateContentResponse> respostaFuture = modelo.generateContent(conteudo);
|
||||
Executor executor = Executors.newSingleThreadExecutor();
|
||||
part.put("text", promptUtilizador);
|
||||
parts.put(part);
|
||||
content.put("parts", parts);
|
||||
contents.put(content);
|
||||
jsonBody.put("contents", contents);
|
||||
|
||||
Futures.addCallback(respostaFuture, new FutureCallback<GenerateContentResponse>() {
|
||||
@Override
|
||||
public void onSuccess(GenerateContentResponse resultado) {
|
||||
if (resultado != null && resultado.getText() != null) {
|
||||
callback.onSuccess(resultado.getText());
|
||||
} else {
|
||||
callback.onError(new Exception("Resposta vazia da IA"));
|
||||
RequestBody body = RequestBody.create(jsonBody.toString(), MediaType.parse("application/json; charset=utf-8"));
|
||||
Request request = new Request.Builder()
|
||||
.url(API_URL)
|
||||
.post(body)
|
||||
.build();
|
||||
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
mainHandler.post(() -> callback.onError(e));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
callback.onError(t);
|
||||
}
|
||||
}, executor);
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
try {
|
||||
String responseBody = response.body().string();
|
||||
JSONObject jsonObject = new JSONObject(responseBody);
|
||||
JSONArray candidates = jsonObject.getJSONArray("candidates");
|
||||
JSONObject firstCandidate = candidates.getJSONObject(0);
|
||||
JSONObject contentObj = firstCandidate.getJSONObject("content");
|
||||
JSONArray partsArr = contentObj.getJSONArray("parts");
|
||||
String textResult = partsArr.getJSONObject(0).getString("text");
|
||||
|
||||
mainHandler.post(() -> callback.onSuccess(textResult));
|
||||
} catch (Exception e) {
|
||||
mainHandler.post(() -> callback.onError(new Exception("Erro ao ler resposta da IA", e)));
|
||||
}
|
||||
} else {
|
||||
String errorBody = response.body() != null ? response.body().string() : "Unknown error";
|
||||
mainHandler.post(() -> callback.onError(new Exception("Erro da API HTTP " + response.code() + ": " + errorBody)));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
mainHandler.post(() -> callback.onError(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,18 +11,7 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.pdf.PdfDocument;
|
||||
import androidx.core.content.FileProvider;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.example.cuida.data.model.Medication;
|
||||
import com.example.cuida.data.model.Appointment;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
@@ -59,7 +48,6 @@ public class ProfileFragment extends Fragment {
|
||||
getActivity().finish();
|
||||
});
|
||||
|
||||
binding.buttonExportReport.setOnClickListener(v -> exportMonthlyReport());
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
@@ -310,119 +298,4 @@ public class ProfileFragment extends Fragment {
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void exportMonthlyReport() {
|
||||
if (currentUser == null || auth.getCurrentUser() == null) return;
|
||||
String userId = auth.getCurrentUser().getUid();
|
||||
|
||||
Toast.makeText(getContext(), "A gerar relatório...", Toast.LENGTH_SHORT).show();
|
||||
|
||||
db.collection("medicamentos").whereEqualTo("userId", userId).get()
|
||||
.addOnSuccessListener(medSnapshots -> {
|
||||
List<Medication> meds = new ArrayList<>();
|
||||
for (com.google.firebase.firestore.DocumentSnapshot doc : medSnapshots) {
|
||||
meds.add(doc.toObject(Medication.class));
|
||||
}
|
||||
|
||||
db.collection("consultas").whereEqualTo("userId", userId).get()
|
||||
.addOnSuccessListener(apptSnapshots -> {
|
||||
List<Appointment> appts = new ArrayList<>();
|
||||
for (com.google.firebase.firestore.DocumentSnapshot doc : apptSnapshots) {
|
||||
appts.add(doc.toObject(Appointment.class));
|
||||
}
|
||||
|
||||
generateAndSharePDF(meds, appts);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void generateAndSharePDF(List<Medication> meds, List<Appointment> appts) {
|
||||
PdfDocument document = new PdfDocument();
|
||||
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(595, 842, 1).create(); // A4 size
|
||||
PdfDocument.Page page = document.startPage(pageInfo);
|
||||
Canvas canvas = page.getCanvas();
|
||||
Paint paint = new Paint();
|
||||
|
||||
int y = 50;
|
||||
paint.setTextSize(24);
|
||||
paint.setFakeBoldText(true);
|
||||
canvas.drawText("Relatório Mensal de Saúde - Cuida+", 50, y, paint);
|
||||
|
||||
y += 40;
|
||||
paint.setTextSize(14);
|
||||
paint.setFakeBoldText(false);
|
||||
canvas.drawText("Utilizador: " + currentUser.name, 50, y, paint);
|
||||
y += 20;
|
||||
canvas.drawText("Data: " + java.text.DateFormat.getDateTimeInstance().format(new java.util.Date()), 50, y, paint);
|
||||
|
||||
y += 40;
|
||||
paint.setFakeBoldText(true);
|
||||
paint.setTextSize(18);
|
||||
canvas.drawText("Medicação Atual:", 50, y, paint);
|
||||
y += 25;
|
||||
paint.setFakeBoldText(false);
|
||||
paint.setTextSize(12);
|
||||
|
||||
if (meds.isEmpty()) {
|
||||
canvas.drawText("Nenhuma medicação registada.", 70, y, paint);
|
||||
y += 20;
|
||||
} else {
|
||||
for (Medication m : meds) {
|
||||
canvas.drawText("- " + m.name + " (" + m.dosage + ") - Horários: " + m.time, 70, y, paint);
|
||||
y += 20;
|
||||
if (m.notes != null && !m.notes.isEmpty()) {
|
||||
paint.setColor(Color.GRAY);
|
||||
canvas.drawText(" Notas: " + m.notes, 70, y, paint);
|
||||
paint.setColor(Color.BLACK);
|
||||
y += 20;
|
||||
}
|
||||
if (y > 750) break; // Simple page break check
|
||||
}
|
||||
}
|
||||
|
||||
y += 20;
|
||||
paint.setFakeBoldText(true);
|
||||
paint.setTextSize(18);
|
||||
canvas.drawText("Consultas Agendadas:", 50, y, paint);
|
||||
y += 25;
|
||||
paint.setFakeBoldText(false);
|
||||
paint.setTextSize(12);
|
||||
|
||||
if (appts.isEmpty()) {
|
||||
canvas.drawText("Nenhuma consulta registada.", 70, y, paint);
|
||||
} else {
|
||||
for (Appointment a : appts) {
|
||||
canvas.drawText("- " + a.type + " em " + a.date + " às " + a.time, 70, y, paint);
|
||||
y += 20;
|
||||
canvas.drawText(" Motivo: " + a.reason, 70, y, paint);
|
||||
y += 25;
|
||||
if (y > 800) break;
|
||||
}
|
||||
}
|
||||
|
||||
document.finishPage(page);
|
||||
|
||||
File file = new File(requireContext().getCacheDir(), "Relatorio_Saude_Cuida.pdf");
|
||||
try {
|
||||
document.writeTo(new FileOutputStream(file));
|
||||
document.close();
|
||||
shareFile(file);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(getContext(), "Erro ao gerar PDF", Toast.LENGTH_SHORT).show();
|
||||
document.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void shareFile(File file) {
|
||||
android.net.Uri uri = FileProvider.getUriForFile(requireContext(),
|
||||
requireContext().getPackageName() + ".fileprovider", file);
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setDataAndType(uri, "application/pdf");
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, "Relatório de Saúde Cuida+");
|
||||
intent.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
startActivity(Intent.createChooser(intent, "Partilhar Relatório"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,11 @@ public class ScheduleAppointmentFragment extends Fragment {
|
||||
spinnerDoctor.setAdapter(adapter);
|
||||
}
|
||||
});
|
||||
|
||||
spinnerDoctor.setOnItemClickListener((parent, view, position, id) -> {
|
||||
String selectedDoctor = (String) parent.getItemAtPosition(position);
|
||||
scheduleViewModel.setSelectedDoctor(selectedDoctor);
|
||||
});
|
||||
}
|
||||
|
||||
private void setupDatePicker() {
|
||||
@@ -181,5 +186,15 @@ public class ScheduleAppointmentFragment extends Fragment {
|
||||
navController.popBackStack();
|
||||
}
|
||||
});
|
||||
|
||||
scheduleViewModel.getSaveError().observe(getViewLifecycleOwner(), errorMsg -> {
|
||||
if (errorMsg != null && !errorMsg.isEmpty()) {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle("Horário Indisponível")
|
||||
.setMessage(errorMsg)
|
||||
.setPositiveButton("OK", null)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.example.cuida.utils.AlarmScheduler;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.firestore.FirebaseFirestore;
|
||||
import com.google.firebase.firestore.QueryDocumentSnapshot;
|
||||
import com.google.firebase.firestore.ListenerRegistration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
@@ -24,9 +25,13 @@ public class ScheduleViewModel extends AndroidViewModel {
|
||||
|
||||
private final MutableLiveData<String> selectedDate = new MutableLiveData<>();
|
||||
private final MutableLiveData<String> selectedTime = new MutableLiveData<>();
|
||||
private final MutableLiveData<String> selectedDoctor = new MutableLiveData<>();
|
||||
private final MutableLiveData<List<TimeSlot>> timeSlots = new MutableLiveData<>();
|
||||
private final MutableLiveData<Boolean> saveSuccess = new MutableLiveData<>();
|
||||
private final MutableLiveData<String> saveError = new MutableLiveData<>();
|
||||
private final MutableLiveData<List<String>> doctorsList = new MutableLiveData<>(new ArrayList<>());
|
||||
|
||||
private ListenerRegistration snapshotListener;
|
||||
|
||||
public ScheduleViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
@@ -43,16 +48,19 @@ public class ScheduleViewModel extends AndroidViewModel {
|
||||
List<String> docs = new ArrayList<>();
|
||||
for (QueryDocumentSnapshot document : task.getResult()) {
|
||||
String name = document.getString("nome");
|
||||
if (name == null) name = document.getString("nome_completo");
|
||||
if (name == null) name = document.getString("name");
|
||||
|
||||
String specialty = document.getString("especialidade");
|
||||
String gender = document.getString("genero");
|
||||
|
||||
if (name != null) {
|
||||
if (name != null && !name.trim().isEmpty()) {
|
||||
String displayName = name;
|
||||
if (specialty != null && !specialty.isEmpty()) {
|
||||
if (specialty != null && !specialty.trim().isEmpty()) {
|
||||
displayName += " - " + specialty;
|
||||
}
|
||||
if (!displayName.startsWith("Dr.") && !displayName.startsWith("Dra.")) {
|
||||
if ("Feminino".equalsIgnoreCase(gender)) {
|
||||
if ("Feminino".equalsIgnoreCase(gender) || "Feminino".equals(gender)) {
|
||||
displayName = "Dra. " + displayName;
|
||||
} else {
|
||||
displayName = "Dr. " + displayName;
|
||||
@@ -74,6 +82,14 @@ public class ScheduleViewModel extends AndroidViewModel {
|
||||
loadTimeSlots(date);
|
||||
}
|
||||
|
||||
public void setSelectedDoctor(String doctor) {
|
||||
selectedDoctor.setValue(doctor);
|
||||
String date = selectedDate.getValue();
|
||||
if (date != null) {
|
||||
loadTimeSlots(date);
|
||||
}
|
||||
}
|
||||
|
||||
public LiveData<String> getSelectedDate() {
|
||||
return selectedDate;
|
||||
}
|
||||
@@ -101,40 +117,64 @@ public class ScheduleViewModel extends AndroidViewModel {
|
||||
return saveSuccess;
|
||||
}
|
||||
|
||||
public LiveData<String> getSaveError() {
|
||||
return saveError;
|
||||
}
|
||||
|
||||
public LiveData<List<String>> getDoctorsList() {
|
||||
return doctorsList;
|
||||
}
|
||||
|
||||
private void loadTimeSlots(String date) {
|
||||
// Init slots immediately to prevent "disappearing" hours while waiting for
|
||||
// network.
|
||||
if (snapshotListener != null) {
|
||||
snapshotListener.remove();
|
||||
snapshotListener = null;
|
||||
}
|
||||
|
||||
// Init slots immediately to prevent "disappearing" hours while waiting for network.
|
||||
timeSlots.setValue(generateTimeSlots(new ArrayList<>(), date));
|
||||
|
||||
if (auth.getCurrentUser() == null)
|
||||
return;
|
||||
if (auth.getCurrentUser() == null) return;
|
||||
String userId = auth.getCurrentUser().getUid();
|
||||
String doctor = selectedDoctor.getValue();
|
||||
|
||||
db.collection("consultas")
|
||||
.whereEqualTo("userId", userId)
|
||||
// Listen in REAL-TIME for all appointments on the selected date
|
||||
snapshotListener = db.collection("consultas")
|
||||
.whereEqualTo("date", date)
|
||||
.get()
|
||||
.addOnCompleteListener(task -> {
|
||||
if (task.isSuccessful()) {
|
||||
List<String> bookedTimes = new ArrayList<>();
|
||||
for (QueryDocumentSnapshot document : task.getResult()) {
|
||||
.addSnapshotListener((queryDocumentSnapshots, e) -> {
|
||||
if (e != null) {
|
||||
Log.e("ScheduleViewModel", "Listen failed.", e);
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> bookedTimes = new ArrayList<>();
|
||||
if (queryDocumentSnapshots != null) {
|
||||
for (QueryDocumentSnapshot document : queryDocumentSnapshots) {
|
||||
Appointment appt = document.toObject(Appointment.class);
|
||||
if (appt.time != null) {
|
||||
bookedTimes.add(appt.time);
|
||||
|
||||
boolean isDoctorAppointment = doctor != null && doctor.equals(appt.type);
|
||||
|
||||
if (isDoctorAppointment && appt.time != null) {
|
||||
if (!bookedTimes.contains(appt.time)) {
|
||||
bookedTimes.add(appt.time);
|
||||
}
|
||||
}
|
||||
}
|
||||
List<TimeSlot> slots = generateTimeSlots(bookedTimes, date);
|
||||
timeSlots.setValue(slots);
|
||||
} else {
|
||||
Log.e("ScheduleViewModel", "Error getting booked slots", task.getException());
|
||||
}
|
||||
|
||||
List<TimeSlot> slots = generateTimeSlots(bookedTimes, date);
|
||||
timeSlots.setValue(slots);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCleared() {
|
||||
super.onCleared();
|
||||
if (snapshotListener != null) {
|
||||
snapshotListener.remove();
|
||||
}
|
||||
}
|
||||
|
||||
private List<TimeSlot> generateTimeSlots(List<String> bookedTimes, String selectedDateStr) {
|
||||
List<TimeSlot> slots = new ArrayList<>();
|
||||
int startHour = 8;
|
||||
@@ -184,47 +224,65 @@ public class ScheduleViewModel extends AndroidViewModel {
|
||||
String userId = auth.getCurrentUser().getUid();
|
||||
|
||||
if (date != null && time != null) {
|
||||
Appointment appointment = new Appointment(type, date, time, reason, false, userId);
|
||||
saveError.setValue(null); // Resetar erro antes de validar
|
||||
|
||||
// Validar no servidor se o horário já está ocupado por este médico
|
||||
db.collection("consultas")
|
||||
.add(appointment)
|
||||
.addOnSuccessListener(documentReference -> {
|
||||
try {
|
||||
String[] dateParts = date.split("/");
|
||||
int day = Integer.parseInt(dateParts[0]);
|
||||
int month = Integer.parseInt(dateParts[1]) - 1; // 0-based
|
||||
int year = Integer.parseInt(dateParts[2]);
|
||||
.whereEqualTo("type", type)
|
||||
.whereEqualTo("date", date)
|
||||
.whereEqualTo("time", time)
|
||||
.get()
|
||||
.addOnSuccessListener(queryDocumentSnapshots -> {
|
||||
if (!queryDocumentSnapshots.isEmpty()) {
|
||||
// Já existe uma consulta!
|
||||
saveError.postValue("Este horário já foi marcado por outro paciente. Por favor, escolha outro.");
|
||||
} else {
|
||||
// O horário está livre, prosseguir com a marcação
|
||||
Appointment appointment = new Appointment(type, date, time, reason, false, userId, "Pendente");
|
||||
|
||||
String[] timeParts = time.split(":");
|
||||
int hour = Integer.parseInt(timeParts[0]);
|
||||
int minute = Integer.parseInt(timeParts[1]);
|
||||
db.collection("consultas")
|
||||
.add(appointment)
|
||||
.addOnSuccessListener(documentReference -> {
|
||||
try {
|
||||
String[] dateParts = date.split("/");
|
||||
int day = Integer.parseInt(dateParts[0]);
|
||||
int month = Integer.parseInt(dateParts[1]) - 1; // 0-based
|
||||
int year = Integer.parseInt(dateParts[2]);
|
||||
|
||||
Calendar baseCal = Calendar.getInstance();
|
||||
baseCal.set(year, month, day, hour, minute, 0);
|
||||
String[] timeParts = time.split(":");
|
||||
int hour = Integer.parseInt(timeParts[0]);
|
||||
int minute = Integer.parseInt(timeParts[1]);
|
||||
|
||||
// Schedule 24 hours before
|
||||
Calendar cal24h = (Calendar) baseCal.clone();
|
||||
cal24h.add(Calendar.DAY_OF_YEAR, -1);
|
||||
if (cal24h.getTimeInMillis() > System.currentTimeMillis()) {
|
||||
AlarmScheduler.scheduleAlarm(getApplication(), cal24h.getTimeInMillis(),
|
||||
"Lembrete de Consulta", "A sua consulta é amanhã às " + time,
|
||||
(date + time + "24h").hashCode());
|
||||
}
|
||||
Calendar baseCal = Calendar.getInstance();
|
||||
baseCal.set(year, month, day, hour, minute, 0);
|
||||
|
||||
// Schedule 30 minutes before
|
||||
Calendar cal30m = (Calendar) baseCal.clone();
|
||||
cal30m.add(Calendar.MINUTE, -30);
|
||||
if (cal30m.getTimeInMillis() > System.currentTimeMillis()) {
|
||||
AlarmScheduler.scheduleAlarm(getApplication(), cal30m.getTimeInMillis(),
|
||||
"Lembrete de Consulta", "A sua consulta é daqui a 30 minutos (" + time + ")",
|
||||
(date + time + "30m").hashCode());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
saveSuccess.postValue(true);
|
||||
})
|
||||
.addOnFailureListener(e -> Log.e("ScheduleViewModel", "Failed to confirm appt", e));
|
||||
// Schedule 24 hours before
|
||||
Calendar cal24h = (Calendar) baseCal.clone();
|
||||
cal24h.add(Calendar.DAY_OF_YEAR, -1);
|
||||
if (cal24h.getTimeInMillis() > System.currentTimeMillis()) {
|
||||
AlarmScheduler.scheduleAlarm(getApplication(), cal24h.getTimeInMillis(),
|
||||
"Lembrete de Consulta", "A sua consulta é amanhã às " + time,
|
||||
(date + time + "24h").hashCode());
|
||||
}
|
||||
|
||||
// Schedule 30 minutes before
|
||||
Calendar cal30m = (Calendar) baseCal.clone();
|
||||
cal30m.add(Calendar.MINUTE, -30);
|
||||
if (cal30m.getTimeInMillis() > System.currentTimeMillis()) {
|
||||
AlarmScheduler.scheduleAlarm(getApplication(), cal30m.getTimeInMillis(),
|
||||
"Lembrete de Consulta", "A sua consulta é daqui a 30 minutos (" + time + ")",
|
||||
(date + time + "30m").hashCode());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
saveSuccess.postValue(true);
|
||||
})
|
||||
.addOnFailureListener(e -> Log.e("ScheduleViewModel", "Failed to confirm appt", e));
|
||||
}
|
||||
}).addOnFailureListener(e -> {
|
||||
saveError.postValue("Erro ao verificar a disponibilidade do horário. Tente novamente.");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,10 +68,11 @@ public class Sns24Fragment extends Fragment {
|
||||
binding.textAiResult.setText("A analisar sintomas...");
|
||||
binding.buttonFindHospital.setVisibility(View.GONE);
|
||||
|
||||
String prompt = "Atua como um assistente de triagem médica do SNS 24. " +
|
||||
"Analisa os seguintes sintomas de forma curta e direta. " +
|
||||
"Se os sintomas parecerem graves, começa a resposta com [GRAVE]. " +
|
||||
"Sintomas: " + symptoms;
|
||||
String prompt = "Atua como triagem médica de urgência (estilo SNS 24). " +
|
||||
"Sê extremamente direto, objetivo e conciso. Não uses introduções ou saudações. " +
|
||||
"Responde apenas com: 1) Causa provável, 2) Ação imediata recomendada. " +
|
||||
"Se os sintomas indicarem perigo de vida ou necessidade de observação urgente, OBRIGATORIAMENTE começa a tua primeira linha com a palavra [GRAVE]. " +
|
||||
"Sintomas do paciente: " + symptoms;
|
||||
|
||||
gemini.fazerPergunta(prompt, new Gemini.GeminiCallback() {
|
||||
@Override
|
||||
|
||||
@@ -115,15 +115,6 @@
|
||||
android:layout_marginBottom="16dp"
|
||||
android:backgroundTint="@color/secondary_color"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_export_report"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:text="Exportar Relatório Mensal"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:strokeColor="@color/secondary_color"
|
||||
android:textColor="@color/secondary_color"/>
|
||||
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
|
||||
Reference in New Issue
Block a user