a ia esta a dar eero
This commit is contained in:
@@ -1,21 +1,27 @@
|
||||
package com.example.cuida.data.model;
|
||||
|
||||
import com.google.firebase.firestore.DocumentId;
|
||||
import com.google.firebase.firestore.PropertyName;
|
||||
|
||||
public class Medication {
|
||||
private String id;
|
||||
|
||||
@DocumentId
|
||||
public String id;
|
||||
|
||||
@PropertyName("nome")
|
||||
public String name;
|
||||
public String time; // HH:mm
|
||||
public String dosage; // e.g. "1 compprimido"
|
||||
|
||||
@PropertyName("hora")
|
||||
public String time;
|
||||
|
||||
@PropertyName("dosagem")
|
||||
public String dosage;
|
||||
|
||||
@PropertyName("notas")
|
||||
public String notes;
|
||||
|
||||
public boolean isTaken;
|
||||
public String userId;
|
||||
|
||||
// Required empty constructor for Firestore deserialization
|
||||
public Medication() {
|
||||
// Obrigatório para o Firestore
|
||||
}
|
||||
|
||||
public Medication(String name, String time, String dosage, String notes, String userId) {
|
||||
@@ -26,4 +32,45 @@ public class Medication {
|
||||
this.isTaken = false;
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
// --- Getters e Setters com compatibilidade para nomes antigos (name, time, dosage, notes) ---
|
||||
|
||||
@PropertyName("nome")
|
||||
public String getName() { return name; }
|
||||
|
||||
@PropertyName("nome")
|
||||
public void setName(String name) { this.name = name; }
|
||||
|
||||
@PropertyName("name") // Suporte para dados antigos
|
||||
public void setNameOld(String name) { if (this.name == null) this.name = name; }
|
||||
|
||||
@PropertyName("hora")
|
||||
public String getTime() { return time; }
|
||||
|
||||
@PropertyName("hora")
|
||||
public void setTime(String time) { this.time = time; }
|
||||
|
||||
@PropertyName("time") // Suporte para dados antigos
|
||||
public void setTimeOld(String time) { if (this.time == null) this.time = time; }
|
||||
|
||||
@PropertyName("dosagem")
|
||||
public String getDosage() { return dosage; }
|
||||
|
||||
@PropertyName("dosagem")
|
||||
public void setDosage(String dosage) { this.dosage = dosage; }
|
||||
|
||||
@PropertyName("dosage") // Suporte para dados antigos
|
||||
public void setDosageOld(String dosage) { if (this.dosage == null) this.dosage = dosage; }
|
||||
|
||||
@PropertyName("notas")
|
||||
public String getNotes() { return notes; }
|
||||
|
||||
@PropertyName("notas")
|
||||
public void setNotes(String notes) { this.notes = notes; }
|
||||
|
||||
@PropertyName("notes") // Suporte para dados antigos
|
||||
public void setNotesOld(String notes) { if (this.notes == null) this.notes = notes; }
|
||||
|
||||
public String getId() { return id; }
|
||||
public void setId(String id) { this.id = id; }
|
||||
}
|
||||
|
||||
@@ -5,15 +5,30 @@ import com.google.firebase.firestore.DocumentId;
|
||||
public class User {
|
||||
|
||||
@DocumentId
|
||||
@com.google.firebase.firestore.Exclude
|
||||
public String id;
|
||||
|
||||
@com.google.firebase.firestore.PropertyName("nome_completo")
|
||||
public String name;
|
||||
|
||||
@com.google.firebase.firestore.PropertyName("email")
|
||||
public String email;
|
||||
|
||||
@com.google.firebase.firestore.Exclude
|
||||
public String password;
|
||||
|
||||
@com.google.firebase.firestore.PropertyName("idade")
|
||||
public int age;
|
||||
|
||||
@com.google.firebase.firestore.PropertyName("numero_utente")
|
||||
public String utenteNumber;
|
||||
|
||||
@com.google.firebase.firestore.PropertyName("profilePictureUri")
|
||||
public String profilePictureUri;
|
||||
|
||||
@com.google.firebase.firestore.PropertyName("tipo")
|
||||
public String tipo = "paciente";
|
||||
|
||||
// Required empty constructor for Firestore deserialization
|
||||
public User() {
|
||||
}
|
||||
@@ -25,4 +40,25 @@ public class User {
|
||||
this.age = age;
|
||||
this.utenteNumber = utenteNumber;
|
||||
}
|
||||
|
||||
@com.google.firebase.firestore.PropertyName("nome_completo")
|
||||
public String getName() { return name; }
|
||||
@com.google.firebase.firestore.PropertyName("nome_completo")
|
||||
public void setName(String name) { this.name = name; }
|
||||
|
||||
@com.google.firebase.firestore.PropertyName("idade")
|
||||
public int getAge() { return age; }
|
||||
@com.google.firebase.firestore.PropertyName("idade")
|
||||
public void setAge(int age) { this.age = age; }
|
||||
|
||||
@com.google.firebase.firestore.PropertyName("numero_utente")
|
||||
public String getUtenteNumber() { return utenteNumber; }
|
||||
@com.google.firebase.firestore.PropertyName("numero_utente")
|
||||
public void setUtenteNumber(String utenteNumber) { this.utenteNumber = utenteNumber; }
|
||||
|
||||
@com.google.firebase.firestore.PropertyName("tipo")
|
||||
public String getTipo() { return tipo; }
|
||||
@com.google.firebase.firestore.PropertyName("tipo")
|
||||
public void setTipo(String tipo) { this.tipo = tipo; }
|
||||
|
||||
}
|
||||
|
||||
@@ -1,29 +1,33 @@
|
||||
package com.example.cuida.services;
|
||||
|
||||
// Imports básicos do SDK do Google AI
|
||||
import com.google.ai.client.generativeai.GenerativeModel;
|
||||
import com.google.ai.client.generativeai.java.GenerativeModelFutures;
|
||||
|
||||
// Imports de tipos e configurações
|
||||
import com.google.ai.client.generativeai.type.BlockThreshold;
|
||||
import com.google.ai.client.generativeai.type.Content;
|
||||
import com.google.ai.client.generativeai.type.GenerateContentResponse;
|
||||
import com.google.ai.client.generativeai.type.GenerationConfig;
|
||||
import com.google.ai.client.generativeai.type.HarmCategory;
|
||||
import com.google.ai.client.generativeai.type.SafetySetting;
|
||||
|
||||
// Imports do Guava para processamento assíncrono
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.google.ai.client.generativeai.type.BlockThreshold;
|
||||
import com.google.ai.client.generativeai.type.HarmCategory;
|
||||
import com.google.ai.client.generativeai.type.SafetySetting;
|
||||
|
||||
// Imports standard de Java
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class Gemini {
|
||||
private final GenerativeModelFutures modelo;
|
||||
|
||||
public Gemini() {
|
||||
// 1. Configurar os SafetySettings para permitir termos médicos e partes do corpo
|
||||
// 1. Configurar Segurança
|
||||
List<SafetySetting> safetySettings = Arrays.asList(
|
||||
new SafetySetting(HarmCategory.HARASSMENT, BlockThreshold.NONE),
|
||||
new SafetySetting(HarmCategory.HATE_SPEECH, BlockThreshold.NONE),
|
||||
@@ -31,39 +35,43 @@ public class Gemini {
|
||||
new SafetySetting(HarmCategory.DANGEROUS_CONTENT, BlockThreshold.NONE)
|
||||
);
|
||||
|
||||
// 2. Configurar o modelo (usa a tua API Key do Google AI Studio)
|
||||
// 2. Configuração de Geração
|
||||
GenerationConfig config = new GenerationConfig.Builder()
|
||||
.setTemperature(0.7f)
|
||||
.build();
|
||||
|
||||
// 3. Inicialização do Modelo (Gemini 1.5 Flash)
|
||||
GenerativeModel generativeModel = new GenerativeModel(
|
||||
"gemini-2.5-flash",
|
||||
"gemini-1.5-flash",
|
||||
"AIzaSyBmLgn-SHaTDvAeDWsw2iTZRR9gahhOu7k",
|
||||
null, // generationConfig
|
||||
config,
|
||||
safetySettings
|
||||
);
|
||||
|
||||
this.modelo = GenerativeModelFutures.from(generativeModel);
|
||||
}
|
||||
|
||||
public interface GeminiCallback {
|
||||
void onSuccess(String result);
|
||||
|
||||
void onError(Throwable t);
|
||||
}
|
||||
|
||||
public void fazerPergunta(String promptUtilizador, GeminiCallback callback) {
|
||||
// 2. Preparar o conteúdo da pergunta
|
||||
Content conteudo = new Content.Builder()
|
||||
.addText(promptUtilizador)
|
||||
.build();
|
||||
|
||||
// 3. Chamar a IA de forma assíncrona
|
||||
ListenableFuture<GenerateContentResponse> respostaFuture = modelo.generateContent(conteudo);
|
||||
|
||||
Executor executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
Futures.addCallback(respostaFuture, new FutureCallback<GenerateContentResponse>() {
|
||||
@Override
|
||||
public void onSuccess(GenerateContentResponse resultado) {
|
||||
// Aqui recebes o texto da IA
|
||||
String textoResposta = resultado.getText();
|
||||
callback.onSuccess(textoResposta);
|
||||
if (resultado != null && resultado.getText() != null) {
|
||||
callback.onSuccess(resultado.getText());
|
||||
} else {
|
||||
callback.onError(new Exception("IA não devolveu texto."));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -59,56 +59,60 @@ public class RegisterActivity extends AppCompatActivity {
|
||||
mAuth = FirebaseAuth.getInstance();
|
||||
FirebaseFirestore db = FirebaseFirestore
|
||||
.getInstance();
|
||||
|
||||
mAuth.createUserWithEmailAndPassword(email, password)
|
||||
.addOnCompleteListener(this, task -> {
|
||||
if (task.isSuccessful()) {
|
||||
// Registration success, save additional info to Firestore
|
||||
FirebaseUser firebaseUser = mAuth.getCurrentUser();
|
||||
if (firebaseUser != null) {
|
||||
String userId = firebaseUser.getUid();
|
||||
|
||||
java.util.Map<String, Object> userMap = new java.util.HashMap<>();
|
||||
userMap.put("id", userId);
|
||||
userMap.put("name", name);
|
||||
userMap.put("email", email);
|
||||
userMap.put("age", age);
|
||||
userMap.put("utenteNumber", utenteStr);
|
||||
userMap.put("sexo", gender);
|
||||
userMap.put("profilePictureUri", ""); // Init empty
|
||||
|
||||
db.collection("utilizadores").document(userId)
|
||||
.set(userMap)
|
||||
.addOnSuccessListener(aVoid -> {
|
||||
Toast.makeText(RegisterActivity.this, "Conta criada com sucesso!",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
startActivity(new Intent(RegisterActivity.this, LoginActivity.class));
|
||||
finish();
|
||||
})
|
||||
.addOnFailureListener(e -> {
|
||||
binding.registerButton.setEnabled(true);
|
||||
binding.registerButton.setText("Registar");
|
||||
Toast.makeText(RegisterActivity.this, "Erro ao salvar dados: " + e.getMessage(),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
saveUserData(firebaseUser.getUid(), name, email, ageStr, utenteStr, gender);
|
||||
}
|
||||
} else {
|
||||
binding.registerButton.setEnabled(true);
|
||||
binding.registerButton.setText("Registar");
|
||||
String errorMsg = task.getException() != null ? task.getException().getMessage()
|
||||
: "Erro desconhecido";
|
||||
if (errorMsg != null) {
|
||||
if (errorMsg.contains("email address is already in use")) {
|
||||
errorMsg = "Este email já está registado!";
|
||||
} else if (errorMsg.contains("email address is badly formatted")) {
|
||||
errorMsg = "O formato do email é inválido!";
|
||||
} else if (errorMsg.contains("Password should be at least")) {
|
||||
errorMsg = "A palavra-passe deve ter pelo menos 6 caracteres.";
|
||||
}
|
||||
Exception e = task.getException();
|
||||
if (e instanceof com.google.firebase.auth.FirebaseAuthUserCollisionException) {
|
||||
// Tenta fazer login automático para reparar o perfil se ele não existir no Firestore
|
||||
mAuth.signInWithEmailAndPassword(email, password)
|
||||
.addOnSuccessListener(authResult -> {
|
||||
saveUserData(authResult.getUser().getUid(), name, email, ageStr, utenteStr, gender);
|
||||
})
|
||||
.addOnFailureListener(err -> {
|
||||
binding.registerButton.setEnabled(true);
|
||||
binding.registerButton.setText("Registar");
|
||||
Toast.makeText(RegisterActivity.this, "Este email já está registado com outra password.", Toast.LENGTH_LONG).show();
|
||||
});
|
||||
} else {
|
||||
binding.registerButton.setEnabled(true);
|
||||
binding.registerButton.setText("Registar");
|
||||
String errorMsg = e != null ? e.getMessage() : "Erro desconhecido";
|
||||
Toast.makeText(RegisterActivity.this, "Erro: " + errorMsg, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
Toast.makeText(RegisterActivity.this, "Erro: " + errorMsg, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void saveUserData(String userId, String name, String email, String ageStr, String utenteStr, String gender) {
|
||||
FirebaseFirestore db = FirebaseFirestore.getInstance();
|
||||
java.util.Map<String, Object> userMap = new java.util.HashMap<>();
|
||||
userMap.put("id", userId);
|
||||
userMap.put("nome_completo", name);
|
||||
userMap.put("email", email);
|
||||
userMap.put("idade", ageStr);
|
||||
userMap.put("numero_utente", utenteStr);
|
||||
userMap.put("sexo", gender);
|
||||
userMap.put("tipo", "paciente");
|
||||
userMap.put("profilePictureUri", "");
|
||||
|
||||
db.collection("utilizadores").document(userId)
|
||||
.set(userMap)
|
||||
.addOnSuccessListener(aVoid -> {
|
||||
Toast.makeText(RegisterActivity.this, "Conta configurada com sucesso!", Toast.LENGTH_SHORT).show();
|
||||
startActivity(new Intent(RegisterActivity.this, LoginActivity.class));
|
||||
finish();
|
||||
})
|
||||
.addOnFailureListener(e -> {
|
||||
binding.registerButton.setEnabled(true);
|
||||
binding.registerButton.setText("Registar");
|
||||
Toast.makeText(RegisterActivity.this, "Erro ao guardar no banco de dados: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,10 @@ public class HomeFragment extends Fragment {
|
||||
.get()
|
||||
.addOnSuccessListener(documentSnapshot -> {
|
||||
if (documentSnapshot.exists() && isAdded()) {
|
||||
String name = documentSnapshot.getString("name");
|
||||
// Tenta 'nome_completo' (novo) ou 'name' (antigo)
|
||||
String name = documentSnapshot.getString("nome_completo");
|
||||
if (name == null || name.isEmpty()) name = documentSnapshot.getString("name");
|
||||
|
||||
if (name != null && !name.isEmpty()) {
|
||||
// Extract first name
|
||||
String firstName = name.split(" ")[0];
|
||||
|
||||
@@ -74,12 +74,24 @@ public class ProfileFragment extends Fragment {
|
||||
if (documentSnapshot.exists()) {
|
||||
currentUser = new User();
|
||||
currentUser.id = documentSnapshot.getId();
|
||||
currentUser.name = documentSnapshot.getString("name");
|
||||
|
||||
// Campos Padronizados
|
||||
String nome = documentSnapshot.getString("nome_completo");
|
||||
if (nome == null) nome = documentSnapshot.getString("name");
|
||||
currentUser.name = nome;
|
||||
|
||||
currentUser.email = documentSnapshot.getString("email");
|
||||
currentUser.utenteNumber = documentSnapshot.getString("utenteNumber");
|
||||
|
||||
String utente = documentSnapshot.getString("numero_utente");
|
||||
if (utente == null) utente = documentSnapshot.getString("utenteNumber");
|
||||
currentUser.utenteNumber = utente;
|
||||
|
||||
currentUser.profilePictureUri = documentSnapshot.getString("profilePictureUri");
|
||||
|
||||
Object ageObj = documentSnapshot.get("age");
|
||||
// Lidar com a idade (que agora é String no registo)
|
||||
Object ageObj = documentSnapshot.get("idade");
|
||||
if (ageObj == null) ageObj = documentSnapshot.get("age");
|
||||
|
||||
if (ageObj instanceof Long) {
|
||||
currentUser.age = ((Long) ageObj).intValue();
|
||||
} else if (ageObj instanceof String) {
|
||||
@@ -91,21 +103,20 @@ public class ProfileFragment extends Fragment {
|
||||
} else {
|
||||
currentUser.age = 0;
|
||||
}
|
||||
if (currentUser != null && isAdded()) {
|
||||
binding.profileName.setText(currentUser.name);
|
||||
binding.profileEmail.setText(currentUser.email);
|
||||
binding.profileAge.setText(String.valueOf(currentUser.age));
|
||||
binding.profileUtente
|
||||
.setText(currentUser.utenteNumber != null ? currentUser.utenteNumber : "N/A");
|
||||
|
||||
if (isAdded()) {
|
||||
binding.profileName.setText(currentUser.name != null ? currentUser.name : "N/D");
|
||||
binding.profileEmail.setText(currentUser.email != null ? currentUser.email : "N/D");
|
||||
binding.profileAge.setText(currentUser.age > 0 ? String.valueOf(currentUser.age) : "N/D");
|
||||
binding.profileUtente.setText(currentUser.utenteNumber != null ? currentUser.utenteNumber : "N/D");
|
||||
|
||||
if (currentUser.profilePictureUri != null && !currentUser.profilePictureUri.isEmpty()) {
|
||||
android.widget.ImageView profileImage = binding.getRoot()
|
||||
.findViewById(R.id.profile_image);
|
||||
android.widget.ImageView profileImage = binding.getRoot().findViewById(R.id.profile_image);
|
||||
if (profileImage != null) {
|
||||
try {
|
||||
profileImage.setImageURI(android.net.Uri.parse(currentUser.profilePictureUri));
|
||||
} catch (Exception e) {
|
||||
Log.e("ProfileFragment", "Error loading profile pic view: " + e.getMessage());
|
||||
Log.e("ProfileFragment", "Error loading pic: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,79 +9,80 @@ import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.example.cuida.databinding.FragmentSns24Binding;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.firestore.FirebaseFirestore;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import com.example.cuida.services.Gemini;
|
||||
|
||||
public class Sns24Fragment extends Fragment {
|
||||
|
||||
private FragmentSns24Binding binding;
|
||||
private Gemini gemini;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(com.example.cuida.R.layout.fragment_sns24, container, false);
|
||||
binding = FragmentSns24Binding.bind(view);
|
||||
return binding.getRoot();
|
||||
}
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
binding = FragmentSns24Binding.inflate(inflater, container, false);
|
||||
View root = binding.getRoot();
|
||||
|
||||
// 2. Botão Ligar SNS 24
|
||||
gemini = new Gemini();
|
||||
|
||||
// 1. Botão de Chamada SNS 24
|
||||
binding.buttonCallSns.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(Intent.ACTION_DIAL);
|
||||
intent.setData(Uri.parse("tel:808242424"));
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
// 2. Esconder o botão de hospital inicialmente
|
||||
binding.buttonFindHospital.setVisibility(View.GONE);
|
||||
|
||||
// 3. Botão Triagem IA
|
||||
binding.buttonAiTriage.setOnClickListener(v -> {
|
||||
String symptoms = binding.inputSymptoms.getText().toString().trim();
|
||||
if (!symptoms.isEmpty()) {
|
||||
hideKeyboard();
|
||||
analyzeSymptomsWithGemini(symptoms);
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Por favor, descreva os seus sintomas.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void hideKeyboard() {
|
||||
View view = getActivity() != null ? getActivity().getCurrentFocus() : null;
|
||||
if (view != null) {
|
||||
android.view.inputmethod.InputMethodManager imm = (android.view.inputmethod.InputMethodManager)
|
||||
getActivity().getSystemService(android.content.Context.INPUT_METHOD_SERVICE);
|
||||
if (imm != null) {
|
||||
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void analyzeSymptomsWithGemini(String symptoms) {
|
||||
// Feedback visual de carregamento
|
||||
binding.buttonAiTriage.setEnabled(false);
|
||||
binding.textAiResult.setVisibility(View.VISIBLE);
|
||||
binding.textAiResult.setText("A contactar a Inteligência Artificial...");
|
||||
binding.textAiResult.setText("A analisar sintomas...");
|
||||
binding.buttonFindHospital.setVisibility(View.GONE);
|
||||
|
||||
com.example.cuida.services.Gemini gemini = new com.example.cuida.services.Gemini();
|
||||
String prompt = "Atua como um assistente de triagem médica. " +
|
||||
"Analisa os seguintes sintomas de um paciente e dá uma resposta MUITO CURTA e direta (máximo 2 a 3 frases). " +
|
||||
"Tem bom senso e calma na avaliação: não assumas automaticamente que os sintomas são severos sem analisar todo o contexto. Evita ser alarmista desnecessariamente. " +
|
||||
"Apenas se os sintomas indicarem uma situação de verdadeira emergência ou necessidade indiscutível de observação médica urgente, a tua resposta DEVE conter obrigatoriamente a palavra [GRAVE]. " +
|
||||
"Recomenda sempre qual o próximo passo adequado (ex: repouso, farmácia, médico, SNS 24, ou urgências). " +
|
||||
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;
|
||||
|
||||
gemini.fazerPergunta(prompt, new com.example.cuida.services.Gemini.GeminiCallback() {
|
||||
gemini.fazerPergunta(prompt, new Gemini.GeminiCallback() {
|
||||
@Override
|
||||
public void onSuccess(String result) {
|
||||
if (getActivity() != null && binding != null) {
|
||||
getActivity().runOnUiThread(() -> {
|
||||
if (binding == null) return;
|
||||
// Limpar a marcação da palavra [GRAVE] para não aparecer ao utilizador
|
||||
String displayResult = result.replace("[GRAVE]", "").trim();
|
||||
binding.textAiResult.setText(displayResult);
|
||||
binding.buttonAiTriage.setEnabled(true);
|
||||
|
||||
String resultLower = result.toLowerCase();
|
||||
if (result.contains("[GRAVE]") || resultLower.contains("grave") || resultLower.contains("urgência") || resultLower.contains("hospital")
|
||||
|| resultLower.contains("112")) {
|
||||
if (result.contains("[GRAVE]")) {
|
||||
binding.buttonFindHospital.setVisibility(View.VISIBLE);
|
||||
binding.buttonFindHospital.setOnClickListener(v -> {
|
||||
Uri gmmIntentUri = Uri.parse("geo:0,0?q=hospital+mais+proximo");
|
||||
@@ -90,8 +91,6 @@ public class Sns24Fragment extends Fragment {
|
||||
startActivity(mapIntent);
|
||||
});
|
||||
}
|
||||
|
||||
// Guardar no Histórico do Firestore
|
||||
saveTriageToHistory(symptoms, displayResult);
|
||||
});
|
||||
}
|
||||
@@ -101,7 +100,7 @@ public class Sns24Fragment extends Fragment {
|
||||
public void onError(Throwable t) {
|
||||
if (getActivity() != null && binding != null) {
|
||||
getActivity().runOnUiThread(() -> {
|
||||
binding.textAiResult.setText("Falha na comunicação com a IA: " + t.getMessage());
|
||||
binding.textAiResult.setText("Erro na ligação: " + t.getMessage());
|
||||
binding.buttonAiTriage.setEnabled(true);
|
||||
});
|
||||
}
|
||||
@@ -110,23 +109,19 @@ public class Sns24Fragment extends Fragment {
|
||||
}
|
||||
|
||||
private void saveTriageToHistory(String symptoms, String result) {
|
||||
FirebaseAuth auth = FirebaseAuth.getInstance();
|
||||
if (auth.getCurrentUser() == null) return;
|
||||
if (getActivity() == null) return;
|
||||
com.google.firebase.auth.FirebaseUser user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
|
||||
if (user == null) return;
|
||||
|
||||
Map<String, Object> triage = new HashMap<>();
|
||||
triage.put("userId", auth.getCurrentUser().getUid());
|
||||
triage.put("symptoms", symptoms);
|
||||
triage.put("result", result);
|
||||
triage.put("timestamp", com.google.firebase.Timestamp.now());
|
||||
java.util.Map<String, Object> triage = new java.util.HashMap<>();
|
||||
triage.put("userId", user.getUid());
|
||||
triage.put("sintomas", symptoms);
|
||||
triage.put("resultado", result);
|
||||
triage.put("data", new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm", java.util.Locale.getDefault()).format(new java.util.Date()));
|
||||
triage.put("timestamp", com.google.firebase.firestore.FieldValue.serverTimestamp());
|
||||
|
||||
FirebaseFirestore.getInstance().collection("triagens")
|
||||
.add(triage)
|
||||
.addOnSuccessListener(documentReference -> {
|
||||
// Histórico guardado com sucesso
|
||||
})
|
||||
.addOnFailureListener(e -> {
|
||||
// Falha ao guardar histórico
|
||||
});
|
||||
com.google.firebase.firestore.FirebaseFirestore.getInstance()
|
||||
.collection("triagens").add(triage);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="#40B00020">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<stroke android:width="2dp" android:color="@color/error_color" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<stroke android:width="1dp" android:color="#D32F2F" />
|
||||
<corners android:radius="28dp" />
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="#400066CC">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<stroke android:width="2dp" android:color="@color/primary_color" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<stroke android:width="1dp" android:color="#2196F3" />
|
||||
<corners android:radius="28dp" />
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
||||
|
||||
@@ -54,17 +54,17 @@
|
||||
android:textStyle="italic"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginTop="2dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_med_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="HH:mm"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/black"
|
||||
android:layout_marginEnd="16dp"/>
|
||||
<TextView
|
||||
android:id="@+id/text_med_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="HH:mm"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/black"
|
||||
android:layout_marginTop="6dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/checkbox_taken"
|
||||
|
||||
Reference in New Issue
Block a user