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"/> - -