From 160ddcc95c415c69c93c1e80528b0ee4fa7c1b91 Mon Sep 17 00:00:00 2001
From: 230412 <230412@epvc.pt>
Date: Tue, 12 May 2026 17:19:13 +0100
Subject: [PATCH] =?UTF-8?q?corrigir=20os=20novos=20erros=20amnh=C3=A3=20e?=
=?UTF-8?q?=20adicionar=20qual=20tipo=20de=20sexo=20a=20pessoa=20=C3=A9=20?=
=?UTF-8?q?no=20register?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/src/main/AndroidManifest.xml | 46 ++---
.../com/example/pap/DesafiosActivity.java | 179 ++++++++++++++++--
.../com/example/pap/EstatisticasActivity.java | 82 +++++++-
.../java/com/example/pap/FotoActivity.java | 54 +++++-
.../java/com/example/pap/HomeActivity.java | 10 +-
.../java/com/example/pap/Ingrediente.java | 25 ---
.../com/example/pap/IngredientesAdapter.java | 79 --------
.../java/com/example/pap/PerfilActivity.java | 38 ++--
.../main/res/layout/activity_estatisticas.xml | 115 ++++++-----
app/src/main/res/layout/activity_perfil.xml | 138 +++++---------
10 files changed, 444 insertions(+), 322 deletions(-)
delete mode 100644 app/src/main/java/com/example/pap/Ingrediente.java
delete mode 100644 app/src/main/java/com/example/pap/IngredientesAdapter.java
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1f486f2..a0f7d5e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,42 +14,26 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.PAP">
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
diff --git a/app/src/main/java/com/example/pap/DesafiosActivity.java b/app/src/main/java/com/example/pap/DesafiosActivity.java
index 2e52284..21df418 100644
--- a/app/src/main/java/com/example/pap/DesafiosActivity.java
+++ b/app/src/main/java/com/example/pap/DesafiosActivity.java
@@ -1,23 +1,43 @@
package com.example.pap;
import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.media.MediaMetadataRetriever;
+import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
+import android.util.Base64;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
+
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
+import java.io.ByteArrayOutputStream;
+import java.util.Collections;
+
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
public class DesafiosActivity extends AppCompatActivity {
private ProgressBar progressAgua;
private TextView tvStatusAgua;
- private int coposBebidos = 3; // Simulação de progresso atual
+ private Button btnGravarAgua, btnGravarEx1, btnGravarEx2;
+ private int coposBebidos = 0;
private final int META_COPOS = 8;
+ // Variável para sabermos qual botão o utilizador clicou
+ private String desafioAtual = "";
+
+ // COLA A TUA CHAVE AQUI
+ private final String MINHA_API_KEY = "sk-or-v1-e65c704789ff164d6ed1be48881dcfa83d9e7f359650f16cf7680dd822e5592bA";
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -25,57 +45,176 @@ public class DesafiosActivity extends AppCompatActivity {
progressAgua = findViewById(R.id.progressAgua);
tvStatusAgua = findViewById(R.id.tvStatusAgua);
- Button btnGravarAgua = findViewById(R.id.btnGravarAgua);
- Button btnEx1 = findViewById(R.id.btnGravarEx1);
- Button btnEx2 = findViewById(R.id.btnGravarEx2);
+ btnGravarAgua = findViewById(R.id.btnGravarAgua);
+ btnGravarEx1 = findViewById(R.id.btnGravarEx1);
+ btnGravarEx2 = findViewById(R.id.btnGravarEx2);
- // Launcher para capturar VÍDEO
+ // Carregar a água que já bebeu hoje
+ SharedPreferences prefs = getSharedPreferences("DadosGamificacao", MODE_PRIVATE);
+ coposBebidos = prefs.getInt("agua_hoje", 0);
+ atualizarProgressoAgua();
+
+ // Launcher que recebe o vídeo da câmara
ActivityResultLauncher videoLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
- if (result.getResultCode() == RESULT_OK) {
- // AQUI É ONDE A IA ENTRARIA PARA ANALISAR O VÍDEO
- validarDesafioIA();
+ if (result.getResultCode() == RESULT_OK && result.getData() != null) {
+ Uri videoUri = result.getData().getData();
+ extrairFrameEEnviarIA(videoUri);
+ } else {
+ Toast.makeText(this, "Vídeo cancelado.", Toast.LENGTH_SHORT).show();
+ desbloquearBotoes();
}
});
- // Configurar botões para abrir a câmara em modo VÍDEO
+ // Configurar Botões (Avisamos qual é o desafio antes de abrir a câmara)
btnGravarAgua.setOnClickListener(v -> {
+ desafioAtual = "agua";
+ bloquearBotoes();
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
- intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 10); // Limita a 10 segundos para ser rápido
+ intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 5); // 5 Segundos chega para beber água
videoLauncher.launch(intent);
});
- btnEx1.setOnClickListener(v -> {
+ btnGravarEx1.setOnClickListener(v -> {
+ desafioAtual = "agachamento";
+ bloquearBotoes();
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
+ intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 10);
videoLauncher.launch(intent);
});
- btnEx2.setOnClickListener(v -> {
+ btnGravarEx2.setOnClickListener(v -> {
+ desafioAtual = "flexoes";
+ bloquearBotoes();
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
+ intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 10);
videoLauncher.launch(intent);
});
findViewById(R.id.btnVoltarDesafios).setOnClickListener(v -> finish());
}
- private void validarDesafioIA() {
- // Simulação: A IA demora 2 segundos a processar e diz que está OK
- Toast.makeText(this, "IA a analisar movimento...", Toast.LENGTH_SHORT).show();
+ private void extrairFrameEEnviarIA(Uri videoUri) {
+ Toast.makeText(this, "A extrair frame do vídeo...", Toast.LENGTH_SHORT).show();
- progressAgua.postDelayed(() -> {
+ try {
+ // Isto vai ao vídeo e tira uma "foto" a meio do tempo
+ MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+ retriever.setDataSource(this, videoUri);
+
+ // Pega num frame do segundo 2 (2000000 microsegundos)
+ Bitmap frame = retriever.getFrameAtTime(2000000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
+
+ if (frame != null) {
+ enviarParaIA(frame);
+ } else {
+ Toast.makeText(this, "Erro ao ler vídeo.", Toast.LENGTH_SHORT).show();
+ desbloquearBotoes();
+ }
+ } catch (Exception e) {
+ Toast.makeText(this, "Erro técnico no vídeo.", Toast.LENGTH_SHORT).show();
+ desbloquearBotoes();
+ }
+ }
+
+ private void enviarParaIA(Bitmap bitmap) {
+ Toast.makeText(this, "IA a avaliar o teu desafio... ⏳", Toast.LENGTH_LONG).show();
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 50, os);
+ String base64 = Base64.encodeToString(os.toByteArray(), Base64.NO_WRAP);
+ String dataUrl = "data:image/jpeg;base64," + base64;
+
+ // O SEGREDO ESTÁ AQUI: Perguntas diferentes para desafios diferentes
+ String ordem = "";
+ int pontosGanhos = 0;
+
+ if (desafioAtual.equals("agua")) {
+ ordem = "Verifica se há uma pessoa a beber água ou com um copo/garrafa na mão. Responde APENAS 'SIM' se houver, ou 'NAO' se não houver. Não digas mais nada.";
+ pontosGanhos = 10;
+ } else if (desafioAtual.equals("agachamento")) {
+ ordem = "Verifica se há uma pessoa a fazer desporto ou na posição de agachamento. Responde APENAS 'SIM' ou 'NAO'.";
+ pontosGanhos = 50;
+ } else if (desafioAtual.equals("flexoes")) {
+ ordem = "Verifica se há uma pessoa no chão a fazer flexões ou desporto. Responde APENAS 'SIM' ou 'NAO'.";
+ pontosGanhos = 60;
+ }
+
+ AiRequest request = new AiRequest(Collections.singletonList(
+ new Message("user", java.util.Arrays.asList(
+ new ContentPart("text", ordem),
+ new ContentPart("image_url", new ImageUrl(dataUrl))
+ ))
+ ));
+
+ // Guarda as variáveis para usar dentro da resposta
+ final int pontosDar = pontosGanhos;
+
+ AiConfig.getRetrofit().create(AiApi.class)
+ .analisarImagem("Bearer " + MINHA_API_KEY, request)
+ .enqueue(new Callback() {
+ @Override
+ public void onResponse(Call call, Response response) {
+ desbloquearBotoes();
+ if (response.isSuccessful() && response.body() != null) {
+ String respostaIA = response.body().choices.get(0).message.content.trim().toUpperCase();
+
+ if (respostaIA.contains("SIM")) {
+ sucessoDesafio(pontosDar);
+ } else {
+ Toast.makeText(DesafiosActivity.this, "A IA diz que NÃO estás a fazer o desafio! ❌", Toast.LENGTH_LONG).show();
+ }
+ } else {
+ Toast.makeText(DesafiosActivity.this, "Erro no servidor da IA.", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable t) {
+ desbloquearBotoes();
+ Toast.makeText(DesafiosActivity.this, "Falha na Internet.", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+
+ private void sucessoDesafio(int pontos) {
+ Toast.makeText(this, "✅ IA Aprovou! Ganhaste " + pontos + " pontos!", Toast.LENGTH_LONG).show();
+
+ SharedPreferences prefs = getSharedPreferences("DadosGamificacao", MODE_PRIVATE);
+ SharedPreferences.Editor editor = prefs.edit();
+
+ // Dá os pontos e sobe o contador de desafios
+ int pontosAtuais = prefs.getInt("pontos", 0);
+ int desafiosAtuais = prefs.getInt("desafios", 0);
+ editor.putInt("pontos", pontosAtuais + pontos);
+ editor.putInt("desafios", desafiosAtuais + 1);
+
+ // Se foi o desafio da água, sobe a barra de progresso
+ if (desafioAtual.equals("agua")) {
coposBebidos++;
if (coposBebidos > META_COPOS) coposBebidos = META_COPOS;
-
+ editor.putInt("agua_hoje", coposBebidos);
atualizarProgressoAgua();
- Toast.makeText(this, "Desafio Validado! +10 pontos", Toast.LENGTH_LONG).show();
+ }
- // Aqui depois vamos enviar os pontos para o Perfil
- }, 2000);
+ editor.apply(); // Guarda tudo!
}
private void atualizarProgressoAgua() {
progressAgua.setProgress(coposBebidos);
tvStatusAgua.setText(coposBebidos + " de " + META_COPOS + " copos (" + (coposBebidos * 250) + "ml / 2L)");
}
+
+ private void bloquearBotoes() {
+ btnGravarAgua.setEnabled(false);
+ btnGravarEx1.setEnabled(false);
+ btnGravarEx2.setEnabled(false);
+ }
+
+ private void desbloquearBotoes() {
+ btnGravarAgua.setEnabled(true);
+ btnGravarEx1.setEnabled(true);
+ btnGravarEx2.setEnabled(true);
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/pap/EstatisticasActivity.java b/app/src/main/java/com/example/pap/EstatisticasActivity.java
index 365369c..785cded 100644
--- a/app/src/main/java/com/example/pap/EstatisticasActivity.java
+++ b/app/src/main/java/com/example/pap/EstatisticasActivity.java
@@ -1,18 +1,94 @@
package com.example.pap;
+import android.content.SharedPreferences;
+import android.graphics.Color;
import android.os.Bundle;
+import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
+import java.util.Locale;
+
public class EstatisticasActivity extends AppCompatActivity {
+ private TextView tvValorIMC, tvStatusIMC;
+ private TextView tvProtGramas, tvHidrGramas, tvGordGramas, tvComida1;
+ private ProgressBar progressProt, progressHidr, progressGord;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_estatisticas);
- // Funcionalidade do botão de voltar
- TextView btnVoltarStats = findViewById(R.id.btnVoltarStats);
- btnVoltarStats.setOnClickListener(v -> finish());
+ // Ligar o layout (XML) às variáveis do Java
+ tvValorIMC = findViewById(R.id.tvValorIMC);
+ tvStatusIMC = findViewById(R.id.tvStatusIMC);
+
+ tvProtGramas = findViewById(R.id.tvProtGramas);
+ tvHidrGramas = findViewById(R.id.tvHidrGramas);
+ tvGordGramas = findViewById(R.id.tvGordGramas);
+ tvComida1 = findViewById(R.id.tvComida1);
+
+ progressProt = findViewById(R.id.progressProt);
+ progressHidr = findViewById(R.id.progressHidr);
+ progressGord = findViewById(R.id.progressGord);
+
+ // Botão voltar
+ findViewById(R.id.btnVoltarStats).setOnClickListener(v -> finish());
+
+ // Chamar as duas funções que preenchem os dados
+ calcularIMC();
+ carregarMacrosDaIA();
+ }
+
+ private void calcularIMC() {
+ SharedPreferences prefs = getSharedPreferences("MeusDadosApp", MODE_PRIVATE);
+ float peso = prefs.getFloat("peso", 0);
+ float altura = prefs.getFloat("altura", 0);
+
+ if (peso > 0 && altura > 0) {
+ float imc = peso / (altura * altura);
+ tvValorIMC.setText(String.format(Locale.getDefault(), "%.1f", imc));
+
+ if (imc < 18.5) {
+ tvStatusIMC.setText("Abaixo do Peso");
+ tvStatusIMC.setTextColor(Color.parseColor("#3B82F6"));
+ } else if (imc < 25) {
+ tvStatusIMC.setText("Peso Normal");
+ tvStatusIMC.setTextColor(Color.parseColor("#10B981"));
+ } else if (imc < 30) {
+ tvStatusIMC.setText("Sobrepeso");
+ tvStatusIMC.setTextColor(Color.parseColor("#F59E0B"));
+ } else {
+ tvStatusIMC.setText("Obesidade");
+ tvStatusIMC.setTextColor(Color.parseColor("#EF4444"));
+ }
+ } else {
+ tvValorIMC.setText("--");
+ tvStatusIMC.setText("Faltam Dados");
+ }
+ }
+
+ private void carregarMacrosDaIA() {
+ // Abre a memória onde a FotoActivity guardou os dados
+ SharedPreferences prefs = getSharedPreferences("DadosSaude", MODE_PRIVATE);
+
+ int prot = prefs.getInt("prot_hoje", 0);
+ int hidr = prefs.getInt("hidr_hoje", 0);
+ int gord = prefs.getInt("gord_hoje", 0);
+ String ultimaComida = prefs.getString("ultimo_prato", "Ainda não leste nada hoje.");
+
+ // Atualizar os Textos (ex: "Proteína: 25g")
+ tvProtGramas.setText("Proteína: " + prot + "g");
+ tvHidrGramas.setText("Hidratos: " + hidr + "g");
+ tvGordGramas.setText("Gordura: " + gord + "g");
+
+ // Atualizar as Barras (Vai enchendo de 0 até ao limite máximo que definiste no XML)
+ progressProt.setProgress(prot);
+ progressHidr.setProgress(hidr);
+ progressGord.setProgress(gord);
+
+ // Atualiza a Última Comida
+ tvComida1.setText("1. " + ultimaComida);
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/pap/FotoActivity.java b/app/src/main/java/com/example/pap/FotoActivity.java
index 46a0876..a35cea4 100644
--- a/app/src/main/java/com/example/pap/FotoActivity.java
+++ b/app/src/main/java/com/example/pap/FotoActivity.java
@@ -1,6 +1,7 @@
package com.example.pap;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.ImageDecoder;
import android.net.Uri;
@@ -32,7 +33,7 @@ public class FotoActivity extends AppCompatActivity {
private Bitmap imagemCapturada;
private String textoAnalise = "";
- // COLA A TUA CHAVE AQUI
+ // MANTÉM A TUA CHAVE (cuidado para não partilhar no futuro)
private final String MINHA_API_KEY = "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";
@Override
@@ -142,6 +143,10 @@ public class FotoActivity extends AppCompatActivity {
textoAnalise = resposta.replace("**", "").replace("*", "");
tvResultadoIA.setText(textoAnalise);
btnIrParaChat.setVisibility(View.VISIBLE);
+
+ // A MAGIA ACONTECE AQUI!
+ extrairEGuardarDados(textoAnalise);
+
} catch (Exception e) { tvResultadoIA.setText("Erro na resposta."); }
} else { tvResultadoIA.setText("Erro: " + response.code()); }
}
@@ -152,4 +157,51 @@ public class FotoActivity extends AppCompatActivity {
}
});
}
+
+ // Função que "lê" a resposta da IA e guarda os números
+ private void extrairEGuardarDados(String texto) {
+ try {
+ // Apanhar o Nome do prato (tudo o que está a seguir a "Prato: " até à próxima linha)
+ int indexNomeStart = texto.indexOf("Prato: ") + 7;
+ int indexNomeEnd = texto.indexOf("\n", indexNomeStart);
+ String nomePrato = texto.substring(indexNomeStart, indexNomeEnd).trim();
+
+ // Apanhar os números
+ int calorias = extrairNumero(texto, "Calorias: ", " kcal");
+ int proteina = extrairNumero(texto, "Macros: ", "g Proteína");
+ int hidratos = extrairNumero(texto, "Proteína, ", "g Hidratos");
+ int gordura = extrairNumero(texto, "Hidratos, ", "g Gordura");
+
+ // Abrir a memória
+ SharedPreferences prefs = getSharedPreferences("DadosSaude", MODE_PRIVATE);
+ SharedPreferences.Editor editor = prefs.edit();
+
+ // Guardar nome do último prato
+ editor.putString("ultimo_prato", nomePrato);
+
+ // Somar aos valores do dia
+ editor.putInt("cal_hoje", prefs.getInt("cal_hoje", 0) + calorias);
+ editor.putInt("prot_hoje", prefs.getInt("prot_hoje", 0) + proteina);
+ editor.putInt("hidr_hoje", prefs.getInt("hidr_hoje", 0) + hidratos);
+ editor.putInt("gord_hoje", prefs.getInt("gord_hoje", 0) + gordura);
+
+ editor.apply();
+ } catch (Exception e) {
+ // Ignora se a IA responder noutro formato para não crashar
+ }
+ }
+
+ // Ferramenta que corta a fatia certa de texto para tirar os números
+ private int extrairNumero(String texto, String inicio, String fim) {
+ try {
+ int start = texto.indexOf(inicio) + inicio.length();
+ int end = texto.indexOf(fim, start);
+ String valorString = texto.substring(start, end).trim();
+ // Limpa tudo o que não for número (caso a IA escreva mal)
+ valorString = valorString.replaceAll("[^0-9]", "");
+ return Integer.parseInt(valorString);
+ } catch (Exception e) {
+ return 0; // Se não encontrar, assume 0
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/pap/HomeActivity.java b/app/src/main/java/com/example/pap/HomeActivity.java
index 76b93bc..8522a46 100644
--- a/app/src/main/java/com/example/pap/HomeActivity.java
+++ b/app/src/main/java/com/example/pap/HomeActivity.java
@@ -51,7 +51,6 @@ public class HomeActivity extends AppCompatActivity {
cardPerfil.setOnClickListener(v -> startActivity(new Intent(HomeActivity.this, PerfilActivity.class)));
-
// 5. Verifica se já passou o tempo para pedir o novo peso
verificarAtualizacaoSemanal();
}
@@ -62,11 +61,12 @@ public class HomeActivity extends AppCompatActivity {
long dataAtual = System.currentTimeMillis();
if (dataUltimaAtualizacao == 0) {
+ // Se for a primeira vez que entra, guarda a data de hoje
sharedPreferences.edit().putLong("data_ultima_atualizacao", dataAtual).apply();
} else {
- // TEMPO CONFIGURADO PARA TESTES: 10 segundos!
- // Quando fores apresentar a PAP, podes mudar isto para 1 semana.
- long tempoNecessario = 10 * 1000;
+ // TEMPO CONFIGURADO PARA 30 DIAS!
+ // 30 dias * 24 horas * 60 minutos * 60 segundos * 1000 milissegundos
+ long tempoNecessario = 30L * 24 * 60 * 60 * 1000;
if (dataAtual - dataUltimaAtualizacao >= tempoNecessario) {
mostrarPopupAtualizacao();
@@ -109,7 +109,7 @@ public class HomeActivity extends AppCompatActivity {
float novoPeso = Float.parseFloat(pesoStr);
float novaAltura = Float.parseFloat(alturaStr);
- // Grava os novos dados com as chaves corretas no bloco de notas
+ // Grava os novos dados na memória
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putFloat("peso", novoPeso);
editor.putFloat("altura", novaAltura);
diff --git a/app/src/main/java/com/example/pap/Ingrediente.java b/app/src/main/java/com/example/pap/Ingrediente.java
deleted file mode 100644
index 3354670..0000000
--- a/app/src/main/java/com/example/pap/Ingrediente.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.example.pap;
-
-// Esta classe é um modelo simples para guardar os dados de um ingrediente
-public class Ingrediente {
- private String nome;
- private int calorias;
-
- public Ingrediente(String nome, int calorias) {
- this.nome = nome;
- this.calorias = calorias;
- }
-
- public String getNome() {
- return nome;
- }
-
- public int getCalorias() {
- return calorias;
- }
-
- // Vamos precisar disto para alterar a quantidade se quisermos no futuro
- public void setCalorias(int calorias) {
- this.calorias = calorias;
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/pap/IngredientesAdapter.java b/app/src/main/java/com/example/pap/IngredientesAdapter.java
deleted file mode 100644
index a7d0fdf..0000000
--- a/app/src/main/java/com/example/pap/IngredientesAdapter.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.example.pap;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.TextView;
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.RecyclerView;
-import java.util.ArrayList;
-
-// O Adapter é o motor que liga os dados à lista visual
-public class IngredientesAdapter extends RecyclerView.Adapter {
-
- private ArrayList listaIngredientes;
- private OnItemClickListener listener;
-
- // Interface para avisar a Activity que um item foi apagado
- public interface OnItemClickListener {
- void onDeleteClick(int position);
- }
-
- public void setOnItemClickListener(OnItemClickListener listener) {
- this.listener = listener;
- }
-
- // Construtor
- public IngredientesAdapter(ArrayList listaIngredientes) {
- this.listaIngredientes = listaIngredientes;
- }
-
- // Cria a "caixinha" visual para cada linha
- @NonNull
- @Override
- public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_ingrediente, parent, false);
- return new ViewHolder(view, listener);
- }
-
- // Preenche a "caixinha" com os dados do ingrediente atual
- @Override
- public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
- Ingrediente ingredienteAtual = listaIngredientes.get(position);
- holder.tvNome.setText(ingredienteAtual.getNome());
- holder.tvCalorias.setText(ingredienteAtual.getCalorias() + " kcal");
- }
-
- @Override
- public int getItemCount() {
- return listaIngredientes.size();
- }
-
- // Classe interna que guarda as referências aos elementos do layout de cada linha
- public static class ViewHolder extends RecyclerView.ViewHolder {
- public TextView tvNome;
- public TextView tvCalorias;
- public ImageButton btnDelete;
-
- public ViewHolder(@NonNull View itemView, final OnItemClickListener listener) {
- super(itemView);
- tvNome = itemView.findViewById(R.id.tvNomeIngrediente);
- tvCalorias = itemView.findViewById(R.id.tvCaloriasIngrediente);
- btnDelete = itemView.findViewById(R.id.btnRemoverIngrediente);
-
- // Configura o clique no botão de lixo
- btnDelete.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (listener != null) {
- int position = getAdapterPosition();
- if (position != RecyclerView.NO_POSITION) {
- listener.onDeleteClick(position);
- }
- }
- }
- });
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/pap/PerfilActivity.java b/app/src/main/java/com/example/pap/PerfilActivity.java
index 5f4caa8..3e74624 100644
--- a/app/src/main/java/com/example/pap/PerfilActivity.java
+++ b/app/src/main/java/com/example/pap/PerfilActivity.java
@@ -5,47 +5,49 @@ import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
+import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class PerfilActivity extends AppCompatActivity {
- private TextView tvPerfilNome, tvPerfilPontos, tvPerfilDesafios, tvPerfilSequencia;
- private Button btnDefinicoes, btnVoltarPerfil;
+ private TextView tvPerfilPontos, tvPerfilDesafios, tvPerfilSequencia;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_perfil);
- tvPerfilNome = findViewById(R.id.tvPerfilNome);
tvPerfilPontos = findViewById(R.id.tvPerfilPontos);
tvPerfilDesafios = findViewById(R.id.tvPerfilDesafios);
tvPerfilSequencia = findViewById(R.id.tvPerfilSequencia);
- btnDefinicoes = findViewById(R.id.btnDefinicoes);
- btnVoltarPerfil = findViewById(R.id.btnVoltarPerfil);
+ Button btnDefinicoes = findViewById(R.id.btnDefinicoes);
+ TextView btnVoltar = findViewById(R.id.btnVoltarPerfil);
+
+ // Ler a pontuação guardada (vamos ligar isto mais à frente)
+ carregarProgresso();
+
+ // Botão Definições
btnDefinicoes.setOnClickListener(v -> {
- startActivity(new Intent(PerfilActivity.this, DefinicoesActivity.class));
+ // Quando tiveres o ecrã de definições criado, trocas o Toast por isto:
+ // Intent intent = new Intent(PerfilActivity.this, DefinicoesActivity.class);
+ // startActivity(intent);
+ Toast.makeText(this, "A abrir Definições...", Toast.LENGTH_SHORT).show();
});
- btnVoltarPerfil.setOnClickListener(v -> finish());
+ // Botão Voltar (manda-te de volta para o Home/Menu)
+ btnVoltar.setOnClickListener(v -> finish());
}
- // A MAGIA ACONTECE AQUI: Atualiza os dados sempre que o ecrã aparece!
- @Override
- protected void onResume() {
- super.onResume();
+ private void carregarProgresso() {
+ SharedPreferences prefs = getSharedPreferences("DadosGamificacao", MODE_PRIVATE);
- SharedPreferences prefs = getSharedPreferences("MeusDadosApp", MODE_PRIVATE);
-
- String nome = prefs.getString("nome", "Utilizador");
int pontos = prefs.getInt("pontos", 0);
- int desafios = prefs.getInt("desafios_concluidos", 0);
- int streak = prefs.getInt("sequencia_diaria", 1);
+ int desafios = prefs.getInt("desafios", 0);
+ int sequencia = prefs.getInt("sequencia", 1);
- tvPerfilNome.setText(nome);
tvPerfilPontos.setText(String.valueOf(pontos));
tvPerfilDesafios.setText(String.valueOf(desafios));
- tvPerfilSequencia.setText(String.valueOf(streak));
+ tvPerfilSequencia.setText(String.valueOf(sequencia));
}
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_estatisticas.xml b/app/src/main/res/layout/activity_estatisticas.xml
index 9af186a..b2ebe16 100644
--- a/app/src/main/res/layout/activity_estatisticas.xml
+++ b/app/src/main/res/layout/activity_estatisticas.xml
@@ -12,7 +12,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp">
-
-
+
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+ app:cardBackgroundColor="#FEF2F2">
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
+
-
+
+
-
+
+
+
-
-
-
-
-
-
+
+
diff --git a/app/src/main/res/layout/activity_perfil.xml b/app/src/main/res/layout/activity_perfil.xml
index 62e49b2..8b7ba62 100644
--- a/app/src/main/res/layout/activity_perfil.xml
+++ b/app/src/main/res/layout/activity_perfil.xml
@@ -4,29 +4,42 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:background="#F8FAFC">
+ android:background="#FFFFFF"
+ android:paddingHorizontal="24dp"
+ android:paddingTop="24dp">
-
+ android:layout_marginBottom="32dp">
+
+
-
+ android:textColor="#1C1C1E"
+ android:layout_centerInParent="true" />
+
+ android:fillViewport="true"
+ android:scrollbars="none">
+ android:padding="30dp"
+ app:tint="#C7C7CC"/>
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
+
-
-
-
+
+
+
@@ -166,23 +134,13 @@
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Definições da Conta"
- android:textAllCaps="false"
android:textSize="16sp"
android:textStyle="bold"
- android:backgroundTint="#0F172A"
- app:cornerRadius="15dp"
- android:layout_marginBottom="12dp"/>
-
-
+ android:textColor="#FFFFFF"
+ android:backgroundTint="#1C1C1E"
+ app:cornerRadius="16dp"
+ android:elevation="0dp"
+ android:layout_marginBottom="16dp"/>