Correção de bugs e melhoramento de design

This commit is contained in:
2026-05-11 17:17:56 +01:00
parent 53c5839750
commit 57372a5379
27 changed files with 1657 additions and 935 deletions

View File

@@ -48,6 +48,8 @@
<activity android:name=".LockActivity" android:exported="false" /> <activity android:name=".LockActivity" android:exported="false" />
<activity android:name=".AlterarPasswordActivity" android:exported="false" />
<activity <activity
android:name=".NovaPasswordActivity" android:name=".NovaPasswordActivity"
android:exported="true"> android:exported="true">

View File

@@ -0,0 +1,57 @@
package com.example.finzora;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class AlterarPasswordActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alterar_password);
ImageView btnVoltar = findViewById(R.id.btnVoltarPassword);
EditText editPasswordAtual = findViewById(R.id.editPasswordAtual);
EditText editPasswordNova = findViewById(R.id.editPasswordNova);
EditText editPasswordConfirmar = findViewById(R.id.editPasswordConfirmar);
Button btnGuardar = findViewById(R.id.btnGuardarPassword);
// Voltar atrás
btnVoltar.setOnClickListener(v -> finish());
// Guardar Nova Palavra-passe
btnGuardar.setOnClickListener(v -> {
String passAtual = editPasswordAtual.getText().toString();
String passNova = editPasswordNova.getText().toString();
String passConfirma = editPasswordConfirmar.getText().toString();
// 1. Validar se os campos estão preenchidos
if (passAtual.isEmpty() || passNova.isEmpty() || passConfirma.isEmpty()) {
Toast.makeText(this, "Preenche todos os campos!", Toast.LENGTH_SHORT).show();
return;
}
// 2. Validar o tamanho
if (passNova.length() < 6) {
editPasswordNova.setError("Tem de ter pelo menos 6 caracteres");
return;
}
// 3. Validar se as palavras-passe novas coincidem
if (!passNova.equals(passConfirma)) {
editPasswordConfirmar.setError("As palavras-passe não coincidem!");
return;
}
// AQUI DEVE ENTRAR O TEU CÓDIGO DO SUPABASE PARA MUDAR A PASS!
// Por agora, damos a sensação de sucesso:
Toast.makeText(this, "Palavra-passe atualizada com segurança! 🔒", Toast.LENGTH_LONG).show();
finish();
});
}
}

View File

@@ -11,13 +11,15 @@ import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.Switch; import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
import com.google.android.material.switchmaterial.SwitchMaterial;
import java.io.IOException; import java.io.IOException;
@@ -36,20 +38,21 @@ public class DefinicoesActivity extends AppCompatActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_definicoes); setContentView(R.layout.activity_definicoes);
TextView btnVoltarDefinicoes = findViewById(R.id.btnVoltarDefinicoes); // --- VINCULAR OS NOVOS JOGADORES DO DESIGN PREMIUM ---
TextView btnEditarPerfil = findViewById(R.id.btnEditarPerfil); Toolbar toolbar = findViewById(R.id.toolbarDefinicoes);
Switch switchModoEscuro = findViewById(R.id.switchModoEscuro); LinearLayout itemEditarPerfil = findViewById(R.id.itemEditarPerfil);
Switch switchNotificacoes = findViewById(R.id.switchNotificacoes); SwitchMaterial switchModoEscuro = findViewById(R.id.switchModoEscuro);
Switch switchBiometria = findViewById(R.id.switchBiometria); SwitchMaterial switchNotificacoes = findViewById(R.id.switchNotificacoes);
TextView btnSuporte = findViewById(R.id.btnSuporte); SwitchMaterial switchBiometria = findViewById(R.id.switchBiometria);
LinearLayout itemCentroSuporte = findViewById(R.id.itemCentroSuporte);
Button btnTerminarSessao = findViewById(R.id.btnTerminarSessao); Button btnTerminarSessao = findViewById(R.id.btnTerminarSessao);
Button btnEliminarConta = findViewById(R.id.btnEliminarConta); Button btnApagarConta = findViewById(R.id.btnApagarConta);
// --- 0. BOTÃO DE VOLTAR --- // --- 0. BOTÃO DE VOLTAR (Na nova Toolbar) ---
btnVoltarDefinicoes.setOnClickListener(v -> finish()); toolbar.setNavigationOnClickListener(v -> finish());
// --- 1. EDITAR PERFIL --- // --- 1. EDITAR PERFIL (Agora é um item clicável) ---
btnEditarPerfil.setOnClickListener(v -> { itemEditarPerfil.setOnClickListener(v -> {
startActivity(new Intent(DefinicoesActivity.this, EditarPerfilActivity.class)); startActivity(new Intent(DefinicoesActivity.this, EditarPerfilActivity.class));
}); });
@@ -95,13 +98,13 @@ public class DefinicoesActivity extends AppCompatActivity {
}); });
// --- 5. CENTRO DE SUPORTE (POP-UP) --- // --- 5. CENTRO DE SUPORTE (POP-UP) ---
btnSuporte.setOnClickListener(v -> mostrarDialogSuporte()); itemCentroSuporte.setOnClickListener(v -> mostrarDialogSuporte());
// --- 6. TERMINAR SESSÃO --- // --- 6. TERMINAR SESSÃO ---
btnTerminarSessao.setOnClickListener(v -> terminarSessao()); btnTerminarSessao.setOnClickListener(v -> terminarSessao());
// --- 7. APAGAR CONTA --- // --- 7. APAGAR CONTA ---
btnEliminarConta.setOnClickListener(v -> mostrarAvisoEliminar()); btnApagarConta.setOnClickListener(v -> mostrarAvisoEliminar());
} }
private void mostrarAvisoEliminar() { private void mostrarAvisoEliminar() {
@@ -225,7 +228,7 @@ public class DefinicoesActivity extends AppCompatActivity {
enviarEmailProfissional(); enviarEmailProfissional();
}); });
// 📞 CONTACTOS DIRETOS: Abre o nosso Novo Design Premium! // 📞 CONTACTOS DIRETOS
dialog.findViewById(R.id.cardContactos).setOnClickListener(v -> { dialog.findViewById(R.id.cardContactos).setOnClickListener(v -> {
dialog.dismiss(); dialog.dismiss();
mostrarDialogContactosInfo(); mostrarDialogContactosInfo();
@@ -234,7 +237,6 @@ public class DefinicoesActivity extends AppCompatActivity {
dialog.show(); dialog.show();
} }
// 🏆 A NOVA FUNÇÃO QUE CHAMA O DESIGN PREMIUM
private void mostrarDialogContactosInfo() { private void mostrarDialogContactosInfo() {
Dialog dialog = new Dialog(this); Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.dialog_contactos); dialog.setContentView(R.layout.dialog_contactos);
@@ -244,7 +246,6 @@ public class DefinicoesActivity extends AppCompatActivity {
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
} }
// Quando clica em Voltar, fechamos este e abrimos o menu de Suporte outra vez!
dialog.findViewById(R.id.btnFecharContactos).setOnClickListener(v -> { dialog.findViewById(R.id.btnFecharContactos).setOnClickListener(v -> {
dialog.dismiss(); dialog.dismiss();
mostrarDialogSuporte(); mostrarDialogSuporte();

View File

@@ -9,11 +9,13 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -38,19 +40,20 @@ import okhttp3.Response;
public class DicasFragment extends Fragment { public class DicasFragment extends Fragment {
private TextView tvTaxaPoupanca, tvDicasReceitas, tvDicasDespesas; // IA
private ProgressBar progressPoupanca;
private TextView tvTituloDica1, tvDescDica1, tvTituloDica2, tvDescDica2, tvTituloDica3, tvDescDica3;
private LinearLayout layoutDistribuicao;
private View layoutConteudoDicas;
private View layoutEstadoVazioDicas;
private TextView tvRespostaAI;
private EditText editPerguntaAI; private EditText editPerguntaAI;
private ImageButton btnEnviarAI; private ImageView btnEnviarAI;
private ProgressBar pbCarregandoAI; private TextView tvRespostaAI; // 🚀 Adicionámos o jogador responsável por mostrar o texto da IA!
// Diagnóstico
private ProgressBar progressPoupanca;
private TextView tvTaxaPoupancaValor, tvReceitasResumo, tvDespesasResumo;
private TextView tvTituloDica1, tvDescDica1;
private TextView tvTituloDica2, tvDescDica2;
private TextView tvTituloDica3, tvDescDica3;
// Top Despesas
private LinearLayout layoutDistribuicao;
private int corFundoCartao; private int corFundoCartao;
private int corTextoDinamico; private int corTextoDinamico;
@@ -61,10 +64,19 @@ public class DicasFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_dicas, container, false); View view = inflater.inflate(R.layout.fragment_dicas, container, false);
tvTaxaPoupanca = view.findViewById(R.id.tvTaxaPoupanca); if (getContext() != null) {
tvDicasReceitas = view.findViewById(R.id.tvDicasReceitas); corFundoCartao = ContextCompat.getColor(getContext(), R.color.fundo_cartao);
tvDicasDespesas = view.findViewById(R.id.tvDicasDespesas); corTextoDinamico = ContextCompat.getColor(getContext(), R.color.texto_principal);
}
editPerguntaAI = view.findViewById(R.id.editPerguntaAI);
btnEnviarAI = view.findViewById(R.id.btnEnviarAI);
tvRespostaAI = view.findViewById(R.id.tvRespostaAI); // Ligar ao XML
progressPoupanca = view.findViewById(R.id.progressPoupanca); progressPoupanca = view.findViewById(R.id.progressPoupanca);
tvTaxaPoupancaValor = view.findViewById(R.id.tvTaxaPoupancaValor);
tvReceitasResumo = view.findViewById(R.id.tvReceitasResumo);
tvDespesasResumo = view.findViewById(R.id.tvDespesasResumo);
tvTituloDica1 = view.findViewById(R.id.tvTituloDica1); tvTituloDica1 = view.findViewById(R.id.tvTituloDica1);
tvDescDica1 = view.findViewById(R.id.tvDescDica1); tvDescDica1 = view.findViewById(R.id.tvDescDica1);
@@ -74,30 +86,29 @@ public class DicasFragment extends Fragment {
tvDescDica3 = view.findViewById(R.id.tvDescDica3); tvDescDica3 = view.findViewById(R.id.tvDescDica3);
layoutDistribuicao = view.findViewById(R.id.layoutDistribuicao); layoutDistribuicao = view.findViewById(R.id.layoutDistribuicao);
layoutConteudoDicas = view.findViewById(R.id.layoutConteudoDicas);
layoutEstadoVazioDicas = view.findViewById(R.id.layoutEstadoVazioDicas);
tvRespostaAI = view.findViewById(R.id.tvRespostaAI); if (btnEnviarAI != null) {
editPerguntaAI = view.findViewById(R.id.editPerguntaAI); btnEnviarAI.setOnClickListener(v -> perguntarAoNovoCoach());
btnEnviarAI = view.findViewById(R.id.btnEnviarAI);
pbCarregandoAI = view.findViewById(R.id.pbCarregandoAI);
if (getContext() != null) {
corFundoCartao = ContextCompat.getColor(getContext(), R.color.fundo_cartao);
corTextoDinamico = ContextCompat.getColor(getContext(), R.color.texto_principal);
} }
btnEnviarAI.setOnClickListener(v -> perguntarAoNovoCoach());
return view; return view;
} }
private void perguntarAoNovoCoach() { private void perguntarAoNovoCoach() {
if (editPerguntaAI == null || tvRespostaAI == null) return;
String pergunta = editPerguntaAI.getText().toString().trim(); String pergunta = editPerguntaAI.getText().toString().trim();
if (pergunta.isEmpty()) return; if (pergunta.isEmpty()) return;
pbCarregandoAI.setVisibility(View.VISIBLE); // Tática: Esconder o teclado para não tapar a resposta
tvRespostaAI.setText("A analisar os dados de forma inteligente..."); InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(editPerguntaAI.getWindowToken(), 0);
}
// Escrever logo no cartão que a máquina está a pensar!
tvRespostaAI.setText("A processar análise... 🧠");
tvRespostaAI.setTextColor(ContextCompat.getColor(getContext(), R.color.tech_accent_cyan));
editPerguntaAI.setText(""); editPerguntaAI.setText("");
OkHttpClient client = new OkHttpClient(); OkHttpClient client = new OkHttpClient();
@@ -138,8 +149,8 @@ public class DicasFragment extends Fragment {
public void onFailure(@NonNull Call call, @NonNull IOException e) { public void onFailure(@NonNull Call call, @NonNull IOException e) {
if (getActivity() != null) { if (getActivity() != null) {
getActivity().runOnUiThread(() -> { getActivity().runOnUiThread(() -> {
pbCarregandoAI.setVisibility(View.GONE); tvRespostaAI.setText("Falha na ligação. A minha antena está sem sinal, tenta outra vez! 📡");
tvRespostaAI.setText("Erro de ligação ao serviço de Inteligência Artificial."); tvRespostaAI.setTextColor(Color.parseColor("#F56565")); // Vermelho suave
}); });
} }
} }
@@ -147,25 +158,26 @@ public class DicasFragment extends Fragment {
@Override @Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
final String respBody = response.body() != null ? response.body().string() : ""; final String respBody = response.body() != null ? response.body().string() : "";
if (getActivity() != null) { if (getActivity() != null) {
getActivity().runOnUiThread(() -> { getActivity().runOnUiThread(() -> {
pbCarregandoAI.setVisibility(View.GONE);
if (response.isSuccessful()) { if (response.isSuccessful()) {
try { try {
JSONObject jsonObject = new JSONObject(respBody); JSONObject jsonObject = new JSONObject(respBody);
String respostaIA = jsonObject.getJSONArray("choices") String respostaIA = jsonObject.getJSONArray("choices")
.getJSONObject(0).getJSONObject("message").getString("content"); .getJSONObject(0).getJSONObject("message").getString("content");
String textoFormatado = respostaIA.replaceAll("\\*\\*(.*?)\\*\\*", "<b>$1</b>"); // Limpar asteriscos e colocar a resposta diretamente no cartão!
textoFormatado = textoFormatado.replace("\n", "<br>"); String textoLimpo = respostaIA.replaceAll("\\*\\*", "");
tvRespostaAI.setText(android.text.Html.fromHtml(textoFormatado, android.text.Html.FROM_HTML_MODE_LEGACY)); tvRespostaAI.setText(textoLimpo);
tvRespostaAI.setTextColor(ContextCompat.getColor(getContext(), R.color.text_secondary)); // Volta à cor normal
} catch (Exception e) { } catch (Exception e) {
tvRespostaAI.setText("Erro a ler os dados da análise: " + e.getMessage()); tvRespostaAI.setText("Erro ao processar a resposta dos servidores.");
tvRespostaAI.setTextColor(Color.parseColor("#F56565"));
} }
} else { } else {
tvRespostaAI.setText("O Assistente não está disponível neste momento."); tvRespostaAI.setText("Os servidores da IA estão ocupados neste momento. ⏱️");
tvRespostaAI.setTextColor(Color.parseColor("#ECC94B")); // Amarelo de aviso
} }
}); });
} }
@@ -216,9 +228,7 @@ public class DicasFragment extends Fragment {
mapaGastos.put(cat, mapaGastos.getOrDefault(cat, 0f) + v); mapaGastos.put(cat, mapaGastos.getOrDefault(cat, 0f) + v);
} }
} }
buscarOrcamentosECriarCerebro(userId, client, rec, desp, mapaGastos); buscarOrcamentosECriarCerebro(userId, client, rec, desp, mapaGastos);
} catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); }
} }
}); });
@@ -242,13 +252,11 @@ public class DicasFragment extends Fragment {
String body = response.body().string(); String body = response.body().string();
JSONArray arrayOrcamentos = new JSONArray(body); JSONArray arrayOrcamentos = new JSONArray(body);
// 🧠 RECONSTRUIR O CÉREBRO DA IA COM TODOS OS DETALHES!
StringBuilder cerebro = new StringBuilder(); StringBuilder cerebro = new StringBuilder();
cerebro.append("DADOS FINANCEIROS ATUAIS DO UTILIZADOR: "); cerebro.append("DADOS FINANCEIROS ATUAIS: ");
cerebro.append("Receitas Totais: ").append(rec).append("€. "); cerebro.append("Receitas: ").append(rec).append("€. ");
cerebro.append("Despesas Totais: ").append(desp).append("€. "); cerebro.append("Despesas: ").append(desp).append("€. ");
// Passar as categorias onde gastaste dinheiro
if (!mapaGastos.isEmpty()) { if (!mapaGastos.isEmpty()) {
cerebro.append("Gastos por categoria: "); cerebro.append("Gastos por categoria: ");
for (Map.Entry<String, Float> entry : mapaGastos.entrySet()) { for (Map.Entry<String, Float> entry : mapaGastos.entrySet()) {
@@ -257,19 +265,16 @@ public class DicasFragment extends Fragment {
} }
if (arrayOrcamentos.length() > 0) { if (arrayOrcamentos.length() > 0) {
cerebro.append(". ORÇAMENTOS DEFINIDOS: "); cerebro.append(". ORÇAMENTOS: ");
for (int i = 0; i < arrayOrcamentos.length(); i++) { for (int i = 0; i < arrayOrcamentos.length(); i++) {
JSONObject obj = arrayOrcamentos.getJSONObject(i); JSONObject obj = arrayOrcamentos.getJSONObject(i);
String cat = obj.getString("categoria"); String cat = obj.getString("categoria");
float limite = (float) obj.getDouble("valor_limite"); float limite = (float) obj.getDouble("valor_limite");
float gasto = mapaGastos.containsKey(cat) ? mapaGastos.get(cat) : 0f; float gasto = mapaGastos.containsKey(cat) ? mapaGastos.get(cat) : 0f;
cerebro.append("[").append(cat).append(": Limite definido ").append(limite).append("€, Gasto atual ").append(gasto).append("€] "); cerebro.append("[").append(cat).append(": Limite ").append(limite).append("€, Gasto ").append(gasto).append("€] ");
} }
} else {
cerebro.append(". O utilizador não tem orçamentos definidos de momento. ");
} }
// ⚠️ A JOGADA QUE FALTAVA: Guardar a memória na variável que a IA vai ler!
contextoFinanceiroParaAI = cerebro.toString(); contextoFinanceiroParaAI = cerebro.toString();
if (getActivity() != null) { if (getActivity() != null) {
@@ -282,24 +287,14 @@ public class DicasFragment extends Fragment {
private void aplicarLogicaDeDicas(float rec, float desp, HashMap<String, Float> mapa, JSONArray arrayOrcamentos) { private void aplicarLogicaDeDicas(float rec, float desp, HashMap<String, Float> mapa, JSONArray arrayOrcamentos) {
if (rec == 0 && desp == 0) {
layoutConteudoDicas.setVisibility(View.GONE);
layoutEstadoVazioDicas.setVisibility(View.VISIBLE);
return;
} else {
layoutConteudoDicas.setVisibility(View.VISIBLE);
layoutEstadoVazioDicas.setVisibility(View.GONE);
}
// --- TOPO: RESUMO ---
tvDicasReceitas.setText(String.format("€ %.2f", rec));
tvDicasDespesas.setText(String.format("€ %.2f", desp));
float taxa = (rec > 0) ? ((rec - desp) / rec) * 100 : 0; float taxa = (rec > 0) ? ((rec - desp) / rec) * 100 : 0;
if (taxa < 0) taxa = 0; if (taxa < 0) taxa = 0;
tvTaxaPoupanca.setText(String.format("%.1f%%", taxa));
progressPoupanca.setProgress((int) taxa);
// --- CARTÃO 1: REGRA 50/30/20 --- if (progressPoupanca != null) progressPoupanca.setProgress((int) taxa);
if (tvTaxaPoupancaValor != null) tvTaxaPoupancaValor.setText(String.format("%.1f%%", taxa));
if (tvReceitasResumo != null) tvReceitasResumo.setText(String.format("€ %.2f", rec));
if (tvDespesasResumo != null) tvDespesasResumo.setText(String.format("€ %.2f", desp));
float necessidades = 0; float desejos = 0; float necessidades = 0; float desejos = 0;
for (Map.Entry<String, Float> entry : mapa.entrySet()) { for (Map.Entry<String, Float> entry : mapa.entrySet()) {
String cat = entry.getKey().toLowerCase(); String cat = entry.getKey().toLowerCase();
@@ -316,25 +311,20 @@ public class DicasFragment extends Fragment {
float percDesejos = (desejos / rec) * 100; float percDesejos = (desejos / rec) * 100;
if (percNecessidades <= 50 && percDesejos <= 30) { if (percNecessidades <= 50 && percDesejos <= 30) {
tvTituloDica1.setText("Balanço Perfeito ⚖️"); if(tvTituloDica1 != null) { tvTituloDica1.setText("Balanço Perfeito ⚖️"); tvTituloDica1.setTextColor(Color.parseColor("#00E676")); }
tvTituloDica1.setTextColor(Color.parseColor("#00E676")); if(tvDescDica1 != null) tvDescDica1.setText("Estás a cumprir a Regra de Ouro (50/30/20). Os teus gastos essenciais e de lazer estão equilibrados face aos teus rendimentos.");
tvDescDica1.setText("Estás a cumprir a Regra de Ouro (50/30/20). Os teus gastos essenciais e de lazer estão equilibrados face aos teus rendimentos.");
} else if (percDesejos > 30) { } else if (percDesejos > 30) {
tvTituloDica1.setText("Atenção aos Gastos Supérfluos 🛍️"); if(tvTituloDica1 != null) { tvTituloDica1.setText("Atenção aos Gastos Supérfluos 🛍️"); tvTituloDica1.setTextColor(Color.parseColor("#ECC94B")); }
tvTituloDica1.setTextColor(Color.parseColor("#ECC94B")); if(tvDescDica1 != null) tvDescDica1.setText(String.format("A alocação em despesas não essenciais representa %.0f%% do teu orçamento. Recomenda-se reduzir para a margem dos 30%%.", percDesejos));
tvDescDica1.setText(String.format("A alocação em despesas não essenciais representa %.0f%% do teu orçamento. Recomenda-se reduzir para a margem dos 30%%.", percDesejos));
} else { } else {
tvTituloDica1.setText("Despesas Fixas Elevadas 🏠"); if(tvTituloDica1 != null) { tvTituloDica1.setText("Despesas Fixas Elevadas 🏠"); tvTituloDica1.setTextColor(Color.parseColor("#F56565")); }
tvTituloDica1.setTextColor(Color.parseColor("#F56565")); if(tvDescDica1 != null) tvDescDica1.setText(String.format("Os teus encargos fixos representam %.0f%% do salário. O indicador ideal para manter a estabilidade financeira é de 50%%.", percNecessidades));
tvDescDica1.setText(String.format("Os teus encargos fixos representam %.0f%% do salário. O indicador ideal para manter a estabilidade financeira é de 50%%.", percNecessidades));
} }
} else { } else {
tvTituloDica1.setText("Regra 50/30/20 ⚖️"); if(tvTituloDica1 != null) { tvTituloDica1.setText("Regra 50/30/20 ⚖️"); tvTituloDica1.setTextColor(corTextoDinamico); }
tvTituloDica1.setTextColor(corTextoDinamico); if(tvDescDica1 != null) tvDescDica1.setText("Regista receitas para que possamos calcular a distribuição ideal do teu património.");
tvDescDica1.setText("Regista receitas para que possamos calcular a distribuição ideal do teu património.");
} }
// --- CARTÃO 2: RADAR DE ORÇAMENTOS ---
String alertaOrcamento = "Todos os orçamentos definidos encontram-se dentro dos limites previstos."; String alertaOrcamento = "Todos os orçamentos definidos encontram-se dentro dos limites previstos.";
int corAlerta = Color.parseColor("#00E676"); int corAlerta = Color.parseColor("#00E676");
String tituloAlerta = "Orçamentos Controlados ✅"; String tituloAlerta = "Orçamentos Controlados ✅";
@@ -363,7 +353,7 @@ public class DicasFragment extends Fragment {
if (maiorRisco >= 1.0) { if (maiorRisco >= 1.0) {
tituloAlerta = "Orçamento Excedido 🚨"; tituloAlerta = "Orçamento Excedido 🚨";
corAlerta = Color.parseColor("#FF1744"); corAlerta = Color.parseColor("#FF1744");
alertaOrcamento = "O limite definido para a categoria '" + catRisco + "' foi ultrapassado. Sugere-se o reajuste das restantes categorias."; alertaOrcamento = "O limite definido para a categoria '" + catRisco + "' foi ultrapassado. Sugere-se o reajuste.";
} else if (maiorRisco >= 0.8) { } else if (maiorRisco >= 0.8) {
tituloAlerta = "Aviso de Limite Próximo ⚠️"; tituloAlerta = "Aviso de Limite Próximo ⚠️";
corAlerta = Color.parseColor("#ECC94B"); corAlerta = Color.parseColor("#ECC94B");
@@ -375,11 +365,9 @@ public class DicasFragment extends Fragment {
} }
} catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); }
tvTituloDica2.setText(tituloAlerta); if(tvTituloDica2 != null) { tvTituloDica2.setText(tituloAlerta); tvTituloDica2.setTextColor(corAlerta); }
tvTituloDica2.setTextColor(corAlerta); if(tvDescDica2 != null) tvDescDica2.setText(alertaOrcamento);
tvDescDica2.setText(alertaOrcamento);
// --- CARTÃO 3: PREVISÃO E TENDÊNCIA DIÁRIA ---
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance();
int diaAtual = cal.get(Calendar.DAY_OF_MONTH); int diaAtual = cal.get(Calendar.DAY_OF_MONTH);
int diasNoMes = cal.getActualMaximum(Calendar.DAY_OF_MONTH); int diasNoMes = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
@@ -389,67 +377,65 @@ public class DicasFragment extends Fragment {
float previsaoFimDoMes = mediaDiaria * diasNoMes; float previsaoFimDoMes = mediaDiaria * diasNoMes;
if (previsaoFimDoMes > rec && rec > 0) { if (previsaoFimDoMes > rec && rec > 0) {
tvTituloDica3.setText("Projeção Mensal Elevada 📈"); if(tvTituloDica3 != null) { tvTituloDica3.setText("Projeção Mensal Elevada 📈"); tvTituloDica3.setTextColor(Color.parseColor("#FF1744")); }
tvTituloDica3.setTextColor(Color.parseColor("#FF1744")); if(tvDescDica3 != null) tvDescDica3.setText(String.format("A média de custos diários situa-se em %.2f€. Mantendo esta tendência, o custo final estimado será de %.2f€ (acima dos rendimentos).", mediaDiaria, previsaoFimDoMes));
tvDescDica3.setText(String.format("A média de custos diários situa-se em %.2f€. Mantendo esta tendência, o custo final estimado será de %.2f€ (acima dos rendimentos).", mediaDiaria, previsaoFimDoMes));
} else { } else {
tvTituloDica3.setText("Projeção Mensal Controlada 📉"); if(tvTituloDica3 != null) { tvTituloDica3.setText("Projeção Mensal Controlada 📉"); tvTituloDica3.setTextColor(Color.parseColor("#00E676")); }
tvTituloDica3.setTextColor(Color.parseColor("#00E676")); if(tvDescDica3 != null) tvDescDica3.setText(String.format("A tua média de custos é de %.2f€ diários. A estimativa projetada para o final do mês é de %.2f€.", mediaDiaria, previsaoFimDoMes));
tvDescDica3.setText(String.format("A tua média de custos é de %.2f€ diários. A estimativa projetada para o final do mês é de %.2f€.", mediaDiaria, previsaoFimDoMes));
} }
} else { } else {
tvTituloDica3.setText("Projeção de Despesas 📊"); if(tvTituloDica3 != null) { tvTituloDica3.setText("Projeção de Despesas 📊"); tvTituloDica3.setTextColor(corTextoDinamico); }
tvTituloDica3.setTextColor(corTextoDinamico); if(tvDescDica3 != null) tvDescDica3.setText("Regista mais movimentos ao longo do mês para projetarmos a tua média diária.");
tvDescDica3.setText("Regista mais movimentos ao longo do mês para que o sistema possa projetar a tua média diária de despesas.");
} }
// --- LISTA DE TOP DESPESAS --- if (layoutDistribuicao != null) {
layoutDistribuicao.removeAllViews(); layoutDistribuicao.removeAllViews();
for (Map.Entry<String, Float> entry : mapa.entrySet()) { for (Map.Entry<String, Float> entry : mapa.entrySet()) {
String categoria = entry.getKey(); String categoria = entry.getKey();
float valor = entry.getValue(); float valor = entry.getValue();
LinearLayout row = new LinearLayout(getContext()); LinearLayout row = new LinearLayout(getContext());
row.setOrientation(LinearLayout.HORIZONTAL); row.setOrientation(LinearLayout.HORIZONTAL);
row.setPadding(40, 30, 40, 30); row.setPadding(40, 40, 40, 40);
row.setElevation(2f); row.setElevation(0f);
GradientDrawable shape = new GradientDrawable(); GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius(24f); shape.setCornerRadius(32f);
shape.setColor(corFundoCartao); shape.setColor(corFundoCartao);
row.setBackground(shape); row.setBackground(shape);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
params.setMargins(0, 0, 0, 20); params.setMargins(0, 0, 0, 24);
row.setLayoutParams(params); row.setLayoutParams(params);
String emoji = "💰"; String emoji = "💰";
String catLower = categoria.toLowerCase(); String catLower = categoria.toLowerCase();
if (catLower.contains("alimen") || catLower.contains("restaurante")) emoji = "🍔"; if (catLower.contains("alimen") || catLower.contains("restaurante")) emoji = "🍔";
else if (catLower.contains("transp") || catLower.contains("carro")) emoji = "🚗"; else if (catLower.contains("transp") || catLower.contains("carro")) emoji = "🚗";
else if (catLower.contains("lazer") || catLower.contains("divers")) emoji = "🎮"; else if (catLower.contains("lazer") || catLower.contains("divers")) emoji = "🎮";
else if (catLower.contains("saúd") || catLower.contains("farmácia")) emoji = "💊"; else if (catLower.contains("saúd") || catLower.contains("farmácia")) emoji = "💊";
else if (catLower.contains("educa")) emoji = "📚"; else if (catLower.contains("educa")) emoji = "📚";
else if (catLower.contains("casa") || catLower.contains("renda") || catLower.contains("conta")) emoji = "🏠"; else if (catLower.contains("casa") || catLower.contains("renda") || catLower.contains("conta")) emoji = "🏠";
else if (catLower.contains("compras") || catLower.contains("roupa")) emoji = "🛍️"; else if (catLower.contains("compras") || catLower.contains("roupa")) emoji = "🛍️";
TextView tvCat = new TextView(getContext()); TextView tvCat = new TextView(getContext());
tvCat.setText(emoji + " " + categoria); tvCat.setText(emoji + " " + categoria);
tvCat.setTextColor(corTextoDinamico); tvCat.setTextColor(corTextoDinamico);
tvCat.setTextSize(16f); tvCat.setTextSize(16f);
tvCat.setTypeface(null, Typeface.BOLD); tvCat.setTypeface(null, Typeface.BOLD);
tvCat.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)); tvCat.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
TextView tvVal = new TextView(getContext()); TextView tvVal = new TextView(getContext());
tvVal.setText(String.format("€ %.2f", valor)); tvVal.setText(String.format("€ %.2f", valor));
tvVal.setTextColor(Color.parseColor("#FF1744")); tvVal.setTextColor(Color.parseColor("#FF1744"));
tvVal.setTextSize(16f); tvVal.setTextSize(16f);
tvVal.setTypeface(null, Typeface.BOLD); tvVal.setTypeface(null, Typeface.BOLD);
row.addView(tvCat); row.addView(tvCat);
row.addView(tvVal); row.addView(tvVal);
layoutDistribuicao.addView(row); layoutDistribuicao.addView(row);
}
} }
} }
} }

View File

@@ -28,6 +28,7 @@ public class EditarPerfilActivity extends AppCompatActivity {
private EditText editNomePerfil; private EditText editNomePerfil;
private EditText editEmailPerfil; private EditText editEmailPerfil;
private EditText editTelemovelPerfil; // NOVO JOGADOR INSCRITO!
private ImageView imgFotoPerfil; private ImageView imgFotoPerfil;
private String caminhoFotoGuardada = null; private String caminhoFotoGuardada = null;
@@ -56,18 +57,23 @@ public class EditarPerfilActivity extends AppCompatActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_editar_perfil); setContentView(R.layout.activity_editar_perfil);
TextView btnVoltar = findViewById(R.id.btnVoltarEditarPerfil); // A CORREÇÃO DE MESTRE: Agora a seta de voltar é lida como ImageView (Imagem)
ImageView btnVoltar = findViewById(R.id.btnVoltarEditarPerfil);
editNomePerfil = findViewById(R.id.editNomePerfil); editNomePerfil = findViewById(R.id.editNomePerfil);
editEmailPerfil = findViewById(R.id.editEmailPerfil); editEmailPerfil = findViewById(R.id.editEmailPerfil);
editTelemovelPerfil = findViewById(R.id.editTelemovelPerfil); // Ligar ao XML
Button btnAlterarPassword = findViewById(R.id.btnAlterarPassword); // Ligar ao XML
Button btnGuardarPerfil = findViewById(R.id.btnGuardarPerfil); Button btnGuardarPerfil = findViewById(R.id.btnGuardarPerfil);
imgFotoPerfil = findViewById(R.id.imgFotoPerfil); imgFotoPerfil = findViewById(R.id.imgFotoPerfil);
btnVoltar.setOnClickListener(v -> finish()); btnVoltar.setOnClickListener(v -> finish());
imgFotoPerfil.setOnClickListener(v -> seletorImagens.launch("image/*")); imgFotoPerfil.setOnClickListener(v -> seletorImagens.launch("image/*"));
// Carregar os dados que já estavam guardados na app
SharedPreferences prefs = getSharedPreferences("DadosUtilizador", MODE_PRIVATE); SharedPreferences prefs = getSharedPreferences("DadosUtilizador", MODE_PRIVATE);
editNomePerfil.setText(prefs.getString("nome_usuario", "Investidor")); editNomePerfil.setText(prefs.getString("nome_usuario", "Investidor"));
editEmailPerfil.setText(prefs.getString("email_usuario", "")); editEmailPerfil.setText(prefs.getString("email_usuario", ""));
editTelemovelPerfil.setText(prefs.getString("telemovel_usuario", "")); // Carrega o telemóvel
caminhoFotoGuardada = prefs.getString("foto_usuario_path", null); caminhoFotoGuardada = prefs.getString("foto_usuario_path", null);
if (caminhoFotoGuardada != null) { if (caminhoFotoGuardada != null) {
@@ -85,9 +91,16 @@ public class EditarPerfilActivity extends AppCompatActivity {
} }
} }
// 🚀 PASSE DE RUTURA: Abrir o novo ecrã profissional de segurança
btnAlterarPassword.setOnClickListener(v -> {
startActivity(new Intent(EditarPerfilActivity.this, AlterarPasswordActivity.class));
});
// Quando o utilizador clica em Guardar
btnGuardarPerfil.setOnClickListener(v -> { btnGuardarPerfil.setOnClickListener(v -> {
String novoNome = editNomePerfil.getText().toString().trim(); String novoNome = editNomePerfil.getText().toString().trim();
String novoEmail = editEmailPerfil.getText().toString().trim(); String novoEmail = editEmailPerfil.getText().toString().trim();
String novoTelemovel = editTelemovelPerfil.getText().toString().trim(); // Lê o que foi escrito
if (novoNome.isEmpty()) { if (novoNome.isEmpty()) {
editNomePerfil.setError("O nome não pode estar vazio!"); editNomePerfil.setError("O nome não pode estar vazio!");
@@ -97,6 +110,7 @@ public class EditarPerfilActivity extends AppCompatActivity {
SharedPreferences.Editor editor = prefs.edit(); SharedPreferences.Editor editor = prefs.edit();
editor.putString("nome_usuario", novoNome); editor.putString("nome_usuario", novoNome);
editor.putString("email_usuario", novoEmail); editor.putString("email_usuario", novoEmail);
editor.putString("telemovel_usuario", novoTelemovel); // Guarda o telemóvel
if (caminhoFotoGuardada != null) { if (caminhoFotoGuardada != null) {
editor.putString("foto_usuario_path", caminhoFotoGuardada); editor.putString("foto_usuario_path", caminhoFotoGuardada);

View File

@@ -42,11 +42,11 @@ public class GraficosFragment extends Fragment {
private BarChart barChartOrcamento; private BarChart barChartOrcamento;
private BarChart barChartTendencia; private BarChart barChartTendencia;
// ⚠️ 1. As Vistas do Estado Vazio
private View scrollviewGraficos; private View scrollviewGraficos;
private View layoutEstadoVazio; private View layoutEstadoVazio;
private int corTextoDinamica; private int corTextoDinamica;
private int corGridSubtil;
@Nullable @Nullable
@Override @Override
@@ -57,14 +57,15 @@ public class GraficosFragment extends Fragment {
barChartOrcamento = view.findViewById(R.id.barChartOrcamento); barChartOrcamento = view.findViewById(R.id.barChartOrcamento);
barChartTendencia = view.findViewById(R.id.barChartTendencia); barChartTendencia = view.findViewById(R.id.barChartTendencia);
// ⚠️ 2. Ligar ao XML
scrollviewGraficos = view.findViewById(R.id.scrollviewGraficos); scrollviewGraficos = view.findViewById(R.id.scrollviewGraficos);
layoutEstadoVazio = view.findViewById(R.id.layoutEstadoVazioGraficos); layoutEstadoVazio = view.findViewById(R.id.layoutEstadoVazioGraficos);
if (getContext() != null) { if (getContext() != null) {
corTextoDinamica = ContextCompat.getColor(getContext(), R.color.texto_principal); corTextoDinamica = ContextCompat.getColor(getContext(), R.color.texto_principal);
corGridSubtil = Color.parseColor("#1A888888"); // Uma grelha muito subtil e quase invisível
} else { } else {
corTextoDinamica = Color.BLACK; corTextoDinamica = Color.BLACK;
corGridSubtil = Color.LTGRAY;
} }
return view; return view;
@@ -125,18 +126,14 @@ public class GraficosFragment extends Fragment {
final float totalDespesas = somaDespesas; final float totalDespesas = somaDespesas;
final Map<String, Float> mapaGastos = gastosPorCategoria; final Map<String, Float> mapaGastos = gastosPorCategoria;
// ⚠️ 3. A Lógica de Mostrar/Esconder
if (getActivity() != null) { if (getActivity() != null) {
getActivity().runOnUiThread(() -> { getActivity().runOnUiThread(() -> {
// Se as receitas E as despesas forem 0, é porque não há transações nenhumas!
if (totalReceitas == 0 && totalDespesas == 0) { if (totalReceitas == 0 && totalDespesas == 0) {
scrollviewGraficos.setVisibility(View.GONE); scrollviewGraficos.setVisibility(View.GONE);
layoutEstadoVazio.setVisibility(View.VISIBLE); layoutEstadoVazio.setVisibility(View.VISIBLE);
} else { } else {
scrollviewGraficos.setVisibility(View.VISIBLE); scrollviewGraficos.setVisibility(View.VISIBLE);
layoutEstadoVazio.setVisibility(View.GONE); layoutEstadoVazio.setVisibility(View.GONE);
// O utilizador tem dados! Vamos buscar os orçamentos para cruzar a informação
carregarOrcamentosEDesenhar(userId, mapaGastos, totalReceitas, totalDespesas); carregarOrcamentosEDesenhar(userId, mapaGastos, totalReceitas, totalDespesas);
} }
}); });
@@ -193,6 +190,7 @@ public class GraficosFragment extends Fragment {
pieChartDespesas.getLegend().setTextColor(corTextoDinamica); pieChartDespesas.getLegend().setTextColor(corTextoDinamica);
pieChartDespesas.getLegend().setTextSize(12f); pieChartDespesas.getLegend().setTextSize(12f);
pieChartDespesas.getLegend().setWordWrapEnabled(true); pieChartDespesas.getLegend().setWordWrapEnabled(true);
pieChartDespesas.getLegend().setForm(com.github.mikephil.charting.components.Legend.LegendForm.CIRCLE); // Fica mais tecnológico!
pieChartDespesas.setCenterText("Despesas"); pieChartDespesas.setCenterText("Despesas");
pieChartDespesas.setCenterTextColor(corTextoDinamica); pieChartDespesas.setCenterTextColor(corTextoDinamica);
@@ -208,14 +206,24 @@ public class GraficosFragment extends Fragment {
if (entradas.isEmpty()) { pieChartDespesas.clear(); return; } if (entradas.isEmpty()) { pieChartDespesas.clear(); return; }
PieDataSet dataSet = new PieDataSet(entradas, ""); PieDataSet dataSet = new PieDataSet(entradas, "");
dataSet.setColors(new int[]{Color.parseColor("#7C4DFF"), Color.parseColor("#00E5FF"), Color.parseColor("#FFD600"), Color.parseColor("#FF4081")});
dataSet.setSliceSpace(3f); // 🚀 PALETA CYBERPUNK PREMIUM: Tons Ciano, Azul Escuro, Roxo Neon, etc.
dataSet.setColors(new int[]{
Color.parseColor("#00E5FF"), // Cyan Tech
Color.parseColor("#2979FF"), // Blue Deep
Color.parseColor("#D500F9"), // Neon Purple
Color.parseColor("#00E676"), // Emerald
Color.parseColor("#FFEA00"), // Yellow Tech
Color.parseColor("#FF1744") // Danger Red
});
dataSet.setSliceSpace(4f); // Espaço entre as fatias dá o efeito premium
PieData data = new PieData(dataSet); PieData data = new PieData(dataSet);
data.setValueTextSize(14f); data.setValueTextSize(12f);
data.setValueTextColor(corTextoDinamica); data.setValueTextColor(Color.WHITE); // Branco destaca bem em cima destas cores fortes
pieChartDespesas.setData(data); pieChartDespesas.setData(data);
pieChartDespesas.animateY(1000); pieChartDespesas.animateY(1200);
} }
private void desenharBarChartOrcamento(Map<String, Float> orcamentos, Map<String, Float> gastos) { private void desenharBarChartOrcamento(Map<String, Float> orcamentos, Map<String, Float> gastos) {
@@ -239,17 +247,16 @@ public class GraficosFragment extends Fragment {
if (categorias.isEmpty()) { barChartOrcamento.clear(); return; } if (categorias.isEmpty()) { barChartOrcamento.clear(); return; }
BarDataSet setGastos = new BarDataSet(gastosEntries, "Gastos Reais"); BarDataSet setGastos = new BarDataSet(gastosEntries, "Gasto Real");
setGastos.setColor(Color.parseColor("#FF4081")); setGastos.setColor(Color.parseColor("#FF1744")); // Vermelho de Gasto
setGastos.setValueTextColor(corTextoDinamica); setGastos.setValueTextColor(corTextoDinamica);
BarDataSet setOrcamento = new BarDataSet(orcamentoEntries, "Orçamento"); BarDataSet setOrcamento = new BarDataSet(orcamentoEntries, "Limite (Orçamento)");
setOrcamento.setColor(Color.parseColor("#00E5FF")); setOrcamento.setColor(Color.parseColor("#00B8D4")); // Ciano Tech do Limite
setOrcamento.setValueTextColor(corTextoDinamica); setOrcamento.setValueTextColor(corTextoDinamica);
BarData data = new BarData(setGastos, setOrcamento); BarData data = new BarData(setGastos, setOrcamento);
// ⚠️ A MATEMÁTICA PERFEITA (tem de somar 1.00)
float barWidth = 0.35f; float barWidth = 0.35f;
float barSpace = 0.05f; float barSpace = 0.05f;
float groupSpace = 0.20f; float groupSpace = 0.20f;
@@ -257,21 +264,16 @@ public class GraficosFragment extends Fragment {
data.setBarWidth(barWidth); data.setBarWidth(barWidth);
barChartOrcamento.setData(data); barChartOrcamento.setData(data);
// ⚠️ COMEÇA NO 0 PARA ALINHAR AO CENTRO
barChartOrcamento.groupBars(0f, groupSpace, barSpace); barChartOrcamento.groupBars(0f, groupSpace, barSpace);
XAxis xAxis = barChartOrcamento.getXAxis(); XAxis xAxis = barChartOrcamento.getXAxis();
xAxis.setValueFormatter(new IndexAxisValueFormatter(categorias)); xAxis.setValueFormatter(new IndexAxisValueFormatter(categorias));
// ⚠️ LIMITES DINÂMICOS PARA ENCAIXAR OS GRUPOS TODOS
xAxis.setAxisMinimum(0f); xAxis.setAxisMinimum(0f);
xAxis.setAxisMaximum(barChartOrcamento.getBarData().getGroupWidth(groupSpace, barSpace) * categorias.size()); xAxis.setAxisMaximum(barChartOrcamento.getBarData().getGroupWidth(groupSpace, barSpace) * categorias.size());
// Para não ficar tudo esmagado se tiveres muitas categorias, mete limite visível a 4
barChartOrcamento.setVisibleXRangeMaximum(4); barChartOrcamento.setVisibleXRangeMaximum(4);
barChartOrcamento.animateY(1200);
barChartOrcamento.animateY(1000); barChartOrcamento.invalidate();
barChartOrcamento.invalidate(); // Refresca o gráfico
} }
private void desenharBarChartTendencia(float receitas, float despesas) { private void desenharBarChartTendencia(float receitas, float despesas) {
@@ -284,16 +286,15 @@ public class GraficosFragment extends Fragment {
receitaEntry.add(new BarEntry(0, receitas)); receitaEntry.add(new BarEntry(0, receitas));
BarDataSet setDespesas = new BarDataSet(despesaEntry, "Despesas"); BarDataSet setDespesas = new BarDataSet(despesaEntry, "Despesas");
setDespesas.setColor(Color.parseColor("#FF1744")); setDespesas.setColor(Color.parseColor("#FF1744")); // Red Tech
setDespesas.setValueTextColor(corTextoDinamica); setDespesas.setValueTextColor(corTextoDinamica);
BarDataSet setReceitas = new BarDataSet(receitaEntry, "Receitas"); BarDataSet setReceitas = new BarDataSet(receitaEntry, "Receitas");
setReceitas.setColor(Color.parseColor("#00E676")); setReceitas.setColor(Color.parseColor("#00E676")); // Green Emerald
setReceitas.setValueTextColor(corTextoDinamica); setReceitas.setValueTextColor(corTextoDinamica);
BarData data = new BarData(setDespesas, setReceitas); BarData data = new BarData(setDespesas, setReceitas);
// ⚠️ MATEMÁTICA PERFEITA PARA A TENDÊNCIA
float groupSpace = 0.3f; float groupSpace = 0.3f;
float barSpace = 0.05f; float barSpace = 0.05f;
float barWidth = 0.3f; float barWidth = 0.3f;
@@ -301,36 +302,39 @@ public class GraficosFragment extends Fragment {
data.setBarWidth(barWidth); data.setBarWidth(barWidth);
barChartTendencia.setData(data); barChartTendencia.setData(data);
// ⚠️ COMEÇA NO 0 TAMBÉM
barChartTendencia.groupBars(0f, groupSpace, barSpace); barChartTendencia.groupBars(0f, groupSpace, barSpace);
ArrayList<String> labelMes = new ArrayList<>(); ArrayList<String> labelMes = new ArrayList<>();
labelMes.add("Atual"); labelMes.add("Mês Atual");
XAxis xAxis = barChartTendencia.getXAxis(); XAxis xAxis = barChartTendencia.getXAxis();
xAxis.setValueFormatter(new IndexAxisValueFormatter(labelMes)); xAxis.setValueFormatter(new IndexAxisValueFormatter(labelMes));
// ⚠️ COMO É SÓ 1 GRUPO, O MÁXIMO É 1
xAxis.setAxisMinimum(0f); xAxis.setAxisMinimum(0f);
xAxis.setAxisMaximum(1f); xAxis.setAxisMaximum(1f);
barChartTendencia.animateY(1000); barChartTendencia.animateY(1200);
barChartTendencia.invalidate(); barChartTendencia.invalidate();
} }
private void configurarEstiloBarChart(BarChart chart) { private void configurarEstiloBarChart(BarChart chart) {
chart.getDescription().setEnabled(false); chart.getDescription().setEnabled(false);
chart.getLegend().setTextColor(corTextoDinamica); chart.getLegend().setTextColor(corTextoDinamica);
chart.getAxisRight().setEnabled(false); chart.getLegend().setForm(com.github.mikephil.charting.components.Legend.LegendForm.CIRCLE); // Ícones redondos na legenda
chart.getAxisRight().setEnabled(false); // Desliga eixo direito
chart.getAxisLeft().setTextColor(corTextoDinamica); chart.getAxisLeft().setTextColor(corTextoDinamica);
chart.getAxisLeft().setDrawGridLines(true); chart.getAxisLeft().setDrawGridLines(true);
chart.getAxisLeft().setGridColor(Color.LTGRAY); chart.getAxisLeft().setGridColor(corGridSubtil); // Grelha muito subtil e tecnológica
chart.getAxisLeft().setAxisLineColor(Color.TRANSPARENT); // Remove linha forte do eixo Y
XAxis xAxis = chart.getXAxis(); XAxis xAxis = chart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setTextColor(corTextoDinamica); xAxis.setTextColor(corTextoDinamica);
xAxis.setDrawGridLines(false); xAxis.setDrawGridLines(false); // Remove grelha feia vertical
xAxis.setAxisLineColor(corGridSubtil);
xAxis.setGranularity(1f); xAxis.setGranularity(1f);
xAxis.setCenterAxisLabels(true); xAxis.setCenterAxisLabels(true);
} }

View File

@@ -13,7 +13,6 @@ import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
@@ -52,7 +51,6 @@ public class MainActivity extends AppCompatActivity {
private ViewPager2 viewPager; private ViewPager2 viewPager;
private FloatingActionButton fabAdicionar; private FloatingActionButton fabAdicionar;
private TextView tvNomeUsuario; private TextView tvNomeUsuario;
private Button btnSair;
private TextView tvSaldoGeral, tvReceitasGeral, tvDespesasGeral; private TextView tvSaldoGeral, tvReceitasGeral, tvDespesasGeral;
private JSONArray listaTransacoesGlobal; private JSONArray listaTransacoesGlobal;
@@ -76,7 +74,6 @@ public class MainActivity extends AppCompatActivity {
viewPager = findViewById(R.id.viewPager); viewPager = findViewById(R.id.viewPager);
fabAdicionar = findViewById(R.id.fabAdicionar); fabAdicionar = findViewById(R.id.fabAdicionar);
tvNomeUsuario = findViewById(R.id.tvNomeUsuario); tvNomeUsuario = findViewById(R.id.tvNomeUsuario);
btnSair = findViewById(R.id.btnSair);
tvSaldoGeral = findViewById(R.id.tvSaldoGeral); tvSaldoGeral = findViewById(R.id.tvSaldoGeral);
tvReceitasGeral = findViewById(R.id.tvReceitasGeral); tvReceitasGeral = findViewById(R.id.tvReceitasGeral);
@@ -86,8 +83,6 @@ public class MainActivity extends AppCompatActivity {
String nome = prefs.getString("nome_usuario", "Investidor"); String nome = prefs.getString("nome_usuario", "Investidor");
tvNomeUsuario.setText("Olá, " + nome); tvNomeUsuario.setText("Olá, " + nome);
btnSair.setOnClickListener(v -> finishAffinity());
fabAdicionar.setOnClickListener(v -> startActivity(new Intent(this, AdicionarTransacaoActivity.class))); fabAdicionar.setOnClickListener(v -> startActivity(new Intent(this, AdicionarTransacaoActivity.class)));
ImageView btnAbrirDefinicoes = findViewById(R.id.btnAbrirDefinicoes); ImageView btnAbrirDefinicoes = findViewById(R.id.btnAbrirDefinicoes);

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#000000">
<path
android:fillColor="@android:color/white"
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zM18,16v-5c0,-3.07 -1.63,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.64,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#000000">
<path
android:fillColor="@android:color/white"
android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#000000">
<path
android:fillColor="@android:color/white"
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4zM9,9c-0.55,0 -1,0.45 -1,1v8c0,0.55 0.45,1 1,1s1,-0.45 1,-1v-8c0,-0.55 -0.45,-1 -1,-1zM15,9c-0.55,0 -1,0.45 -1,1v8c0,0.55 0.45,1 1,1s1,-0.45 1,-1v-8c0,-0.55 -0.45,-1 -1,-1z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#000000">
<path
android:fillColor="@android:color/white"
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#000000">
<path
android:fillColor="@android:color/white"
android:pathData="M17.81,4.47c-0.08,0 -0.16,-0.02 -0.23,-0.06C15.66,3.42 14,3 12.01,3c-1.98,0 -3.86,0.47 -5.57,1.41 -0.24,0.13 -0.54,0.04 -0.68,-0.2s-0.04,-0.55 0.2,-0.68C7.82,2.52 9.86,2 12.01,2c2.13,0 4.13,0.46 5.93,1.36 0.24,0.12 0.35,0.42 0.22,0.66 -0.09,0.16 -0.26,0.25 -0.35,0.25zM3.19,9.45c-0.2,0 -0.39,-0.12 -0.47,-0.32 -0.1,-0.26 0.03,-0.55 0.29,-0.65 1.63,-0.62 3.32,-0.98 5.03,-1.07 0.27,-0.02 0.51,0.19 0.53,0.46 0.02,0.27 -0.19,0.51 -0.46,0.53 -1.59,0.08 -3.16,0.42 -4.68,0.99 -0.08,0.03 -0.16,0.06 -0.24,0.06zM20.12,12.01c0,-0.27 0.22,-0.49 0.49,-0.49 1.13,0 2.11,-0.31 2.92,-0.91 0.22,-0.17 0.52,-0.13 0.69,0.09s0.13,0.52 -0.09,0.69c-1,0.75 -2.23,1.13 -3.52,1.13 -0.27,0.01 -0.49,-0.21 -0.49,-0.48zM2.51,15.11c0,-0.27 0.22,-0.49 0.49,-0.49 0.33,0 0.65,-0.03 0.96,-0.08 0.27,-0.04 0.52,0.14 0.56,0.41 0.04,0.27 -0.14,0.52 -0.41,0.56 -0.44,0.06 -0.89,0.1 -1.35,0.1 -0.28,0 -0.5,-0.22 -0.5,-0.5zM12,22c-0.27,0 -0.49,-0.22 -0.49,-0.49v-4.02c0,-0.27 0.22,-0.49 0.49,-0.49s0.49,0.22 0.49,0.49v4.02C12.49,21.78 12.27,22 12,22zM19.07,20.21c-0.12,0 -0.25,-0.05 -0.34,-0.14 -1.4,-1.4 -2.17,-3.26 -2.17,-5.23 0,-1.71 0.61,-3.2 1.77,-4.31 0.2,-0.19 0.51,-0.18 0.7,0.02s0.18,0.51 -0.02,0.7c-0.93,0.89 -1.41,2.08 -1.41,3.58 0,1.72 0.67,3.34 1.84,4.5 0.19,0.19 0.19,0.51 0,0.7 -0.1,0.1 -0.24,0.18 -0.37,0.18zM15,20.08c-0.12,0 -0.24,-0.04 -0.34,-0.13 -2.22,-2.11 -3.45,-5 -3.45,-8.11 0,-1.4 0.27,-2.72 0.81,-3.93 0.11,-0.25 0.41,-0.36 0.66,-0.25 0.25,0.11 0.36,0.41 0.25,0.66 -0.47,1.06 -0.7,2.2 -0.7,3.52 0,2.83 1.11,5.43 3.12,7.34 0.2,0.19 0.21,0.51 0.02,0.7 -0.1,0.11 -0.24,0.2 -0.37,0.2zM8.31,21.31c-0.19,0 -0.37,-0.11 -0.45,-0.29C6.39,17.9 6,15 6,12c0,-1.82 0.3,-3.57 0.91,-5.21 0.09,-0.26 0.38,-0.39 0.64,-0.3 0.26,0.09 0.39,0.38 0.3,0.64C7.3,8.62 7,10.27 7,12c0,2.83 0.36,5.55 1.77,8.62 0.12,0.25 0.01,0.55 -0.24,0.66 -0.07,0.02 -0.15,0.03 -0.22,0.03zM5,12c0,-3.2 0.94,-6.17 2.58,-8.66 0.15,-0.23 0.46,-0.29 0.69,-0.14 0.23,0.15 0.29,0.46 0.14,0.69C6.91,6.17 6,8.99 6,12c0,2.1 0.22,4.14 0.64,6.09 0.06,0.27 -0.11,0.53 -0.38,0.59 -0.26,0.07 -0.53,-0.11 -0.59,-0.38C5.24,16.2 5,14.12 5,12z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#000000">
<path
android:fillColor="@android:color/white"
android:pathData="M18,8h-1V6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2H6c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V10C20,8.9 19.1,8 18,8zM9,6c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v2H9V6zM18,20H6V10h12V20zM12,17c1.1,0 2,-0.9 2,-2c0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2C10,16.1 10.9,17 12,17z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#000000">
<path
android:fillColor="@android:color/white"
android:pathData="M17,7l-1.41,1.41L18.17,11H8v2h10.17l-2.58,2.58L17,17l5,-5L17,7zM4,5h8V3H4C2.9,3 2,3.9 2,5v14c0,1.1 0.9,2 2,2h8v-2H4V5z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#000000">
<path
android:fillColor="@android:color/white"
android:pathData="M12.3,13.25a3.75,3.75 0,0 1,3.45 -2.47c0.56,0 1.09,0.12 1.56,0.35a9.24,9.24 0,0 1,0.06 1.12c0,5.09 -4.13,9.25 -9.25,9.25 -2.1,0 -4.03,-0.69 -5.59,-1.86a9.27,9.27 0,0 1,-0.12 -1.13c0,-5.09 4.13,-9.25 9.25,-9.25 1.1,0 2.15,0.19 3.12,0.54a3.75,3.75 0,0 1,-0.17 0.96a3.75,3.75 0,0 1,-2.3 2.5z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#000000">
<path
android:fillColor="@android:color/white"
android:pathData="M19,2h-4.18C14.4,0.84 13.3,0 12,0S9.6,0.84 9.18,2H5C3.9,2 3,2.9 3,4v16c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V4C21,2.9 20.1,2 19,2zM12,2c0.55,0 1,0.45 1,1s-0.45,1 -1,1s-1,-0.45 -1,-1S11.45,2 12,2zM14,14h-4v-2h4V14zM16,10H8V8h8V10z"/>
</vector>

View File

@@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/fundo_app"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginBottom="32dp">
<ImageView
android:id="@+id/btnVoltarPassword"
android:layout_width="32dp"
android:layout_height="32dp"
android:src="@drawable/ic_arrow_back"
app:tint="@color/texto_principal"
android:layout_marginEnd="16dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Segurança"
android:textColor="@color/texto_principal"
android:textSize="28sp"
android:textStyle="bold"/>
</LinearLayout>
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_lock"
app:tint="@color/tech_accent_cyan"
android:layout_marginBottom="16dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Muda a tua palavra-passe regularmente para manteres a tua conta Finzora segura."
android:textAlignment="center"
android:textColor="@color/text_secondary"
android:textSize="14sp"
android:layout_marginBottom="32dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Palavra-passe Atual"
android:textColor="@color/text_secondary"
android:textSize="12sp"
android:textStyle="bold"
android:layout_marginBottom="8dp"/>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="12dp"
app:cardElevation="0dp"
android:layout_marginBottom="24dp">
<EditText
android:id="@+id/editPasswordAtual"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:textColor="@color/texto_principal"
android:padding="16dp"
android:hint="••••••••"
android:textColorHint="@color/text_secondary"
android:inputType="textPassword"/>
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nova Palavra-passe"
android:textColor="@color/text_secondary"
android:textSize="12sp"
android:textStyle="bold"
android:layout_marginBottom="8dp"/>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="12dp"
app:cardElevation="0dp"
android:layout_marginBottom="16dp">
<EditText
android:id="@+id/editPasswordNova"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:textColor="@color/texto_principal"
android:padding="16dp"
android:hint="Pelo menos 6 caracteres"
android:textColorHint="@color/text_secondary"
android:inputType="textPassword"/>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="12dp"
app:cardElevation="0dp"
android:layout_marginBottom="32dp">
<EditText
android:id="@+id/editPasswordConfirmar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:textColor="@color/texto_principal"
android:padding="16dp"
android:hint="Repetir nova palavra-passe"
android:textColorHint="@color/text_secondary"
android:inputType="textPassword"/>
</androidx.cardview.widget.CardView>
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginBottom="16dp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/btnGuardarPassword"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="Atualizar Palavra-passe"
android:textColor="@color/texto_dinamico"
android:textSize="16sp"
android:textStyle="bold"
app:cornerRadius="16dp"
app:backgroundTint="@color/tech_accent_cyan" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View File

@@ -1,117 +1,352 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:background="@color/fundo_app"
android:padding="24dp" tools:context=".DefinicoesActivity">
android:background="@color/fundo_app">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbarDefinicoes"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/fundo_app"
android:elevation="0dp"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="@drawable/ic_arrow_back"
app:title="Definições"
app:titleTextColor="@color/texto_principal" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:fillViewport="true"
app:layout_constraintBottom_toTopOf="@+id/buttonContainer"
app:layout_constraintTop_toBottomOf="@+id/toolbarDefinicoes">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:text="A Tua Conta"
android:textAllCaps="true"
android:textColor="@color/text_secondary"
android:textSize="12sp"
android:textStyle="bold" />
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="16dp"
app:cardElevation="1dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/itemEditarPerfil"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/ic_edit_profile"
app:tint="@color/texto_principal" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Editar Perfil"
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Alterar nome, email..."
android:textColor="@color/text_secondary"
android:textSize="12sp" />
</LinearLayout>
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_chevron_right"
app:tint="@color/text_secondary" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:text="Preferências e Segurança"
android:textAllCaps="true"
android:textColor="@color/text_secondary"
android:textSize="12sp"
android:textStyle="bold" />
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="16dp"
app:cardElevation="1dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/ic_moon"
app:tint="@color/texto_principal" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_weight="1"
android:text="Modo Escuro"
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switchModoEscuro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:thumbTint="@color/tech_accent_cyan"
app:trackTint="@color/tech_accent_cyan" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/linha_separadora" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/ic_fingerprint"
app:tint="@color/texto_principal" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_weight="1"
android:text="Bloqueio Biométrico"
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switchBiometria"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:thumbTint="@color/tech_accent_cyan"
app:trackTint="@color/tech_accent_cyan" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/linha_separadora" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/ic_bell"
app:tint="@color/texto_principal" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_weight="1"
android:text="Ativar Notificações"
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switchNotificacoes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:thumbTint="@color/tech_accent_cyan"
app:trackTint="@color/tech_accent_cyan" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:text="Ajuda"
android:textAllCaps="true"
android:textColor="@color/text_secondary"
android:textSize="12sp"
android:textStyle="bold" />
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="16dp"
app:cardElevation="1dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/itemCentroSuporte"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/ic_support"
app:tint="@color/texto_principal" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_weight="1"
android:text="Centro de Suporte"
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold" />
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_chevron_right"
app:tint="@color/text_secondary" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<LinearLayout <LinearLayout
android:id="@+id/buttonContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:background="@color/fundo_app"
android:gravity="center_vertical" android:orientation="vertical"
android:layout_marginBottom="32dp"> android:paddingHorizontal="20dp"
android:paddingTop="8dp"
android:paddingBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent">
<TextView <View
android:id="@+id/btnVoltarDefinicoes" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="1dp"
android:layout_height="wrap_content" android:layout_marginBottom="16dp"
android:text="←" android:background="@color/linha_separadora" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnTerminarSessao"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginBottom="12dp"
android:text="Terminar Sessão"
android:textAllCaps="false"
android:textColor="@color/texto_principal" android:textColor="@color/texto_principal"
android:textSize="32sp" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
android:paddingEnd="16dp" app:cornerRadius="16dp"
android:background="?attr/selectableItemBackgroundBorderless"/> app:icon="@drawable/ic_logout"
app:iconGravity="textStart"
app:iconTint="@color/texto_principal"
app:strokeColor="@color/linha_separadora"
app:strokeWidth="1dp" />
<TextView <com.google.android.material.button.MaterialButton
android:layout_width="wrap_content" android:id="@+id/btnApagarConta"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:text="Definições" android:layout_height="56dp"
android:textColor="@color/texto_principal" android:text="Apagar Conta e Dados"
android:textSize="28sp" android:textAllCaps="false"
android:textStyle="bold"/> android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
app:backgroundTint="@color/tech_accent_red"
app:cornerRadius="16dp"
app:icon="@drawable/ic_delete_forever"
app:iconGravity="textStart"
app:iconTint="@color/white"
app:rippleColor="@color/white" />
</LinearLayout> </LinearLayout>
<TextView </androidx.constraintlayout.widget.ConstraintLayout>
android:id="@+id/btnEditarPerfil"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Editar Perfil"
android:textColor="@color/texto_principal"
android:textSize="18sp"
android:paddingVertical="16dp"
android:background="?attr/selectableItemBackground"/>
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/linha_separadora" />
<Switch
android:id="@+id/switchModoEscuro"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Modo Escuro"
android:textColor="@color/texto_principal"
android:textSize="18sp"
android:paddingVertical="16dp" />
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/linha_separadora" />
<Switch
android:id="@+id/switchBiometria"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bloqueio por Biometria"
android:textColor="@color/texto_principal"
android:textSize="18sp"
android:paddingVertical="16dp" />
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/linha_separadora" />
<Switch
android:id="@+id/switchNotificacoes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Ativar Notificações"
android:textColor="@color/texto_principal"
android:textSize="18sp"
android:paddingVertical="16dp" />
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/linha_separadora" />
<TextView
android:id="@+id/btnSuporte"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Centro de Suporte"
android:textColor="@color/texto_principal"
android:textSize="18sp"
android:paddingVertical="16dp"
android:background="?attr/selectableItemBackground"/>
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/linha_separadora" android:layout_marginBottom="32dp" />
<Button
android:id="@+id/btnTerminarSessao"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Terminar Sessão"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:padding="16dp"
app:cornerRadius="8dp"
android:backgroundTint="#424242" />
<Button
android:id="@+id/btnEliminarConta"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Apagar Conta e Dados"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:padding="16dp"
android:layout_marginTop="12dp"
app:cornerRadius="8dp"
android:backgroundTint="#FF1744" />
</LinearLayout>

View File

@@ -1,96 +1,177 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:background="@color/fundo_app"
android:padding="24dp" android:fillViewport="true">
android:background="@color/bg_dinamico">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="vertical"
android:gravity="center_vertical" android:padding="24dp">
android:layout_marginBottom="40dp">
<TextView <LinearLayout
android:id="@+id/btnVoltarEditarPerfil" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginBottom="32dp">
<ImageView
android:id="@+id/btnVoltarEditarPerfil"
android:layout_width="32dp"
android:layout_height="32dp"
android:src="@drawable/ic_arrow_back"
app:tint="@color/texto_principal"
android:layout_marginEnd="16dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Editar Perfil"
android:textColor="@color/texto_principal"
android:textSize="28sp"
android:textStyle="bold"/>
</LinearLayout>
<FrameLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="←" android:layout_gravity="center_horizontal"
android:textColor="@color/texto_dinamico" android:layout_marginBottom="32dp">
android:textSize="32sp"
<ImageView
android:id="@+id/imgFotoPerfil"
android:layout_width="120dp"
android:layout_height="120dp"
android:background="@drawable/bg_circle_icon"
android:src="@android:drawable/ic_menu_camera"
android:scaleType="centerCrop" />
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_gravity="bottom|end"
android:background="@drawable/bg_circle_icon"
android:backgroundTint="@color/tech_accent_cyan"
android:src="@android:drawable/ic_menu_camera"
android:padding="8dp"
app:tint="@color/texto_dinamico"
android:elevation="4dp"/>
</FrameLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dados Pessoais"
android:textAllCaps="true"
android:textColor="@color/text_secondary"
android:textSize="12sp"
android:textStyle="bold" android:textStyle="bold"
android:paddingEnd="16dp" android:layout_marginBottom="12dp"/>
android:background="?attr/selectableItemBackgroundBorderless"/>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="12dp"
app:cardElevation="0dp"
android:layout_marginBottom="16dp">
<EditText
android:id="@+id/editNomePerfil"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:textColor="@color/texto_principal"
android:padding="16dp"
android:hint="O teu nome"
android:textColorHint="@color/text_secondary"/>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="12dp"
app:cardElevation="0dp"
android:layout_marginBottom="16dp">
<EditText
android:id="@+id/editEmailPerfil"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:textColor="@color/texto_principal"
android:padding="16dp"
android:hint="O teu email"
android:textColorHint="@color/text_secondary"
android:inputType="textEmailAddress"/>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="12dp"
app:cardElevation="0dp"
android:layout_marginBottom="32dp">
<EditText
android:id="@+id/editTelemovelPerfil"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:textColor="@color/texto_principal"
android:padding="16dp"
android:hint="Telemóvel (Opcional)"
android:textColorHint="@color/text_secondary"
android:inputType="phone"/>
</androidx.cardview.widget.CardView>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Editar Perfil" android:text="Segurança"
android:textAllCaps="true"
android:textColor="@color/text_secondary"
android:textSize="12sp"
android:textStyle="bold"
android:layout_marginBottom="12dp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/btnAlterarPassword"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginBottom="32dp"
android:text="Alterar Palavra-passe"
android:textAllCaps="false"
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold"
app:cornerRadius="12dp"
app:strokeColor="@color/linha_separadora"
app:strokeWidth="1dp" />
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginBottom="16dp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/btnGuardarPerfil"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="Guardar Alterações"
android:textColor="@color/texto_dinamico" android:textColor="@color/texto_dinamico"
android:textSize="28sp" android:textSize="16sp"
android:textStyle="bold"/> android:textStyle="bold"
app:cornerRadius="16dp"
app:backgroundTint="@color/tech_accent_cyan" />
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView>
<ImageView
android:id="@+id/imgFotoPerfil"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/bg_circle_icon"
android:src="@android:drawable/ic_menu_camera"
android:scaleType="centerCrop"
android:layout_marginBottom="32dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nome"
android:textColor="@color/texto_dinamico"
android:textSize="14sp"
android:layout_marginBottom="8dp"/>
<EditText
android:id="@+id/editNomePerfil"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#2D3748"
android:textColor="#FFFFFF"
android:padding="16dp"
android:hint="O teu nome"
android:textColorHint="#718096"
android:layout_marginBottom="24dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Email"
android:textColor="@color/texto_dinamico"
android:textSize="14sp"
android:layout_marginBottom="8dp"/>
<EditText
android:id="@+id/editEmailPerfil"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#2D3748"
android:textColor="#FFFFFF"
android:padding="16dp"
android:hint="O teu email"
android:textColorHint="#718096"
android:inputType="textEmailAddress"
android:layout_marginBottom="40dp"/>
<Button
android:id="@+id/btnGuardarPerfil"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Guardar Alterações"
android:textColor="#1A202C"
android:textStyle="bold"
android:padding="16dp"
app:cornerRadius="8dp"
android:backgroundTint="#00E676" />
</LinearLayout>

View File

@@ -11,38 +11,40 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<RelativeLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="20dp"> android:orientation="horizontal"
android:gravity="center_vertical"
android:paddingHorizontal="24dp"
android:paddingTop="32dp"
android:paddingBottom="24dp">
<ImageView <ImageView
android:id="@+id/imgLogo" android:id="@+id/imgLogo"
android:layout_width="45dp" android:layout_width="50dp"
android:layout_height="45dp" android:layout_height="50dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:background="@drawable/bg_circle_icon" android:background="@drawable/bg_circle_icon"
android:padding="8dp" android:backgroundTint="@color/tech_accent_cyan"
android:padding="12dp"
android:src="@android:drawable/ic_menu_gallery" android:src="@android:drawable/ic_menu_gallery"
app:tint="@color/white" app:tint="#1A202C" />
android:scaleType="centerCrop" />
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical" android:orientation="vertical"
android:layout_toEndOf="@id/imgLogo" android:layout_marginStart="16dp">
android:layout_centerVertical="true"
android:layout_marginStart="12dp">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="FINZORA" android:text="FINZORA"
android:textColor="@color/tech_accent_cyan" android:textColor="@color/tech_accent_cyan"
android:textSize="18sp" android:textSize="12sp"
android:textStyle="bold"/> android:textStyle="bold"
android:letterSpacing="0.1"/>
<TextView <TextView
android:id="@+id/tvNomeUsuario" android:id="@+id/tvNomeUsuario"
@@ -50,52 +52,40 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Olá, Investidor" android:text="Olá, Investidor"
android:textColor="@color/texto_principal" android:textColor="@color/texto_principal"
android:textSize="14sp"/> android:textSize="22sp"
android:textStyle="bold"/>
</LinearLayout> </LinearLayout>
<ImageView
android:id="@+id/btnAbrirDefinicoes"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_toStartOf="@id/btnExportarPDF"
android:layout_centerVertical="true"
android:layout_marginEnd="15dp"
android:src="@drawable/ic_settings_pap"
app:tint="@color/tech_accent_cyan"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="Definições" />
<ImageView <ImageView
android:id="@+id/btnExportarPDF" android:id="@+id/btnExportarPDF"
android:layout_width="35dp" android:layout_width="44dp"
android:layout_height="35dp" android:layout_height="44dp"
android:layout_toStartOf="@id/btnSair" android:padding="10dp"
android:layout_centerVertical="true" android:layout_marginEnd="8dp"
android:layout_marginEnd="15dp"
android:src="@android:drawable/ic_menu_save" android:src="@android:drawable/ic_menu_save"
app:tint="@color/tech_accent_cyan" app:tint="@color/texto_principal"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="Exportar Relatório" /> android:contentDescription="Exportar Relatório" />
<Button <ImageView
android:id="@+id/btnSair" android:id="@+id/btnAbrirDefinicoes"
android:layout_width="wrap_content" android:layout_width="44dp"
android:layout_height="wrap_content" android:layout_height="44dp"
android:layout_alignParentEnd="true" android:padding="10dp"
android:layout_centerVertical="true" android:src="@drawable/ic_settings_pap"
android:text="Sair" app:tint="@color/texto_principal"
android:textColor="#FFFFFF" android:background="?attr/selectableItemBackgroundBorderless"
android:backgroundTint="#FF1744" android:contentDescription="Definições" />
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
app:cornerRadius="8dp"/> </LinearLayout>
</RelativeLayout>
<HorizontalScrollView <HorizontalScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="20dp" android:paddingStart="24dp"
android:paddingEnd="20dp" android:paddingEnd="24dp"
android:clipToPadding="false"> android:clipToPadding="false"
android:scrollbars="none">
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -110,18 +100,21 @@
android:id="@+id/tabLayoutDashboard" android:id="@+id/tabLayoutDashboard"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="24dp"
android:layout_marginHorizontal="24dp"
android:background="@android:color/transparent" android:background="@android:color/transparent"
app:tabTextColor="@color/texto_principal" app:tabTextColor="@color/text_secondary"
app:tabSelectedTextColor="@color/tech_accent_cyan" app:tabSelectedTextColor="@color/tech_accent_cyan"
app:tabIndicatorColor="@color/tech_accent_cyan" app:tabIndicatorColor="@color/tech_accent_cyan"
app:tabMode="scrollable"/> app:tabIndicatorHeight="3dp"
app:tabIndicatorFullWidth="false"
<androidx.viewpager2.widget.ViewPager2 app:tabGravity="fill"
android:id="@+id/viewPager" app:tabMode="scrollable"/> <androidx.viewpager2.widget.ViewPager2
android:layout_width="match_parent" android:id="@+id/viewPager"
android:layout_height="0dp" android:layout_width="match_parent"
android:layout_weight="1"/> android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="8dp"/>
</LinearLayout> </LinearLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.FloatingActionButton
@@ -132,7 +125,9 @@
android:layout_margin="24dp" android:layout_margin="24dp"
android:src="@android:drawable/ic_input_add" android:src="@android:drawable/ic_input_add"
app:backgroundTint="@color/tech_accent_cyan" app:backgroundTint="@color/tech_accent_cyan"
app:tint="@color/black" app:tint="#1A202C"
app:elevation="6dp"/> app:elevation="4dp"
app:fabSize="normal"
android:contentDescription="Adicionar Transação"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -1,313 +1,324 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?android:attr/windowBackground"> android:background="@color/fundo_app"
android:fillViewport="true">
<LinearLayout <LinearLayout
android:id="@+id/layoutEstadoVazioDicas"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone"> android:padding="20dp">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="📊" android:text="Conselheiro Inteligente"
android:textSize="60sp" /> android:textAllCaps="true"
android:textColor="@color/text_secondary"
android:textSize="12sp"
android:textStyle="bold"
android:layout_marginBottom="12dp"/>
<TextView <com.google.android.material.card.MaterialCardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Sem dados para analisar"
android:textColor="?android:attr/textColorPrimary"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:paddingHorizontal="32dp"
android:text="Adiciona transações para receberes conselhos da nossa Inteligência Artificial."
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
<ScrollView
android:id="@+id/layoutConteudoDicas"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:padding="16dp"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="16dp"
<androidx.cardview.widget.CardView app:cardElevation="0dp"
android:layout_width="match_parent" app:strokeColor="@color/tech_accent_cyan"
android:layout_height="wrap_content" app:strokeWidth="1dp"
android:layout_marginBottom="16dp" android:layout_marginBottom="24dp">
app:cardBackgroundColor="?android:attr/colorBackgroundFloating"
app:cardCornerRadius="20dp"
app:cardElevation="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="🤖 Finzora AI Coach"
android:textColor="@color/tech_accent_cyan"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvRespostaAI"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Olá! Já analisei os teus dados. Pergunta-me qualquer coisa sobre como poupar ou investir."
android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/bg_search_bar"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="12dp"
android:paddingVertical="4dp">
<EditText
android:id="@+id/editPerguntaAI"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:hint="Pede uma dica tática..."
android:textColor="?android:attr/textColorPrimary"
android:textColorHint="?android:attr/textColorSecondary"
android:textSize="14sp" />
<ImageButton
android:id="@+id/btnEnviarAI"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@android:drawable/ic_menu_send"
app:tint="@color/tech_accent_cyan" />
</LinearLayout>
<ProgressBar
android:id="@+id/pbCarregandoAI"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="8dp"
android:visibility="gone" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:cardBackgroundColor="?android:attr/colorBackgroundFloating"
app:cardCornerRadius="16dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Taxa de Poupança"
android:textColor="?android:attr/textColorPrimary"
android:textStyle="bold" />
<TextView
android:id="@+id/tvTaxaPoupanca"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0%"
android:textColor="#00E676"
android:textStyle="bold" />
</LinearLayout>
<ProgressBar
android:id="@+id/progressPoupanca"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="8dp"
android:layout_marginTop="8dp"
android:max="100"
android:progress="0"
android:progressTint="#00E676" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tvDicasReceitas"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="€ 0.00"
android:textColor="#00E676"
android:textStyle="bold" />
<TextView
android:id="@+id/tvDicasDespesas"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="€ 0.00"
android:textColor="#FF1744"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
app:cardBackgroundColor="?android:attr/colorBackgroundFloating"
app:cardCornerRadius="16dp"
app:cardElevation="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvTituloDica1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A Regra 50/30/20 ⚖️"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvDescDica1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="A calcular a tua distribuição de riqueza..."
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
app:cardBackgroundColor="?android:attr/colorBackgroundFloating"
app:cardCornerRadius="16dp"
app:cardElevation="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvTituloDica2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Radar de Orçamentos 🎯"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvDescDica2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="A verificar limites..."
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:cardBackgroundColor="?android:attr/colorBackgroundFloating"
app:cardCornerRadius="16dp"
app:cardElevation="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvTituloDica3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Ritmo de Gastos 🏃‍♂️"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvDescDica3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="A calcular a tua velocidade de gastos..."
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="Top Despesas"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp"
android:textStyle="bold" />
<LinearLayout <LinearLayout
android:id="@+id/layoutDistribuicao"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" /> android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginBottom="12dp">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/ic_support"
app:tint="@color/tech_accent_cyan" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Finzora AI Coach"
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginStart="8dp"/>
<View android:layout_width="0dp" android:layout_height="0dp" android:layout_weight="1"/>
<ImageView
android:layout_width="10dp"
android:layout_height="10dp"
android:src="@drawable/bg_circle_icon"
app:tint="#00E676"/>
</LinearLayout>
<TextView
android:id="@+id/tvRespostaAI"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Olá! Já analisei os teus dados de hoje. Pergunta-me qualquer coisa sobre como otimizar o teu dinheiro."
android:textColor="@color/text_secondary"
android:textSize="14sp"
android:lineSpacingExtra="4dp"
android:layout_marginBottom="16dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:background="@drawable/bg_search_bar"
android:gravity="center_vertical"
android:paddingHorizontal="12dp">
<EditText
android:id="@+id/editPerguntaAI"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@android:color/transparent"
android:hint="Pede uma dica tática..."
android:textColorHint="@color/text_secondary"
android:textColor="@color/texto_principal"
android:textSize="14sp"/>
<ImageView
android:id="@+id/btnEnviarAI"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@android:drawable/ic_menu_send"
app:tint="@color/tech_accent_cyan"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Diagnóstico da Máquina"
android:textAllCaps="true"
android:textColor="@color/text_secondary"
android:textSize="12sp"
android:textStyle="bold"
android:layout_marginBottom="12dp"/>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="16dp"
app:cardElevation="0dp"
android:layout_marginBottom="12dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Taxa de Poupança"
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold"/>
<View android:layout_width="0dp" android:layout_height="0dp" android:layout_weight="1"/>
<TextView
android:id="@+id/tvTaxaPoupancaValor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0.0%"
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold"/>
</LinearLayout>
<ProgressBar
android:id="@+id/progressPoupanca"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="8dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="8dp"
android:max="100"
android:progress="0"
android:progressTint="#00E676"
android:progressBackgroundTint="@color/linha_separadora"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tvReceitasResumo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="€ 0.00"
android:textColor="#00E676"
android:textSize="12sp"
android:textStyle="bold"/>
<View android:layout_width="0dp" android:layout_height="0dp" android:layout_weight="1"/>
<TextView
android:id="@+id/tvDespesasResumo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="€ 0.00"
android:textColor="#FF1744"
android:textSize="12sp"
android:textStyle="bold"/>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="16dp"
app:cardElevation="0dp"
android:layout_marginBottom="12dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvTituloDica1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A calcular..."
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/tvDescDica1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Aguarde enquanto analisamos os teus movimentos."
android:textColor="@color/text_secondary"
android:textSize="14sp"
android:lineSpacingExtra="4dp"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="16dp"
app:cardElevation="0dp"
android:layout_marginBottom="12dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvTituloDica2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A calcular..."
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/tvDescDica2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="A analisar limites estabelecidos..."
android:textColor="@color/text_secondary"
android:textSize="14sp"
android:lineSpacingExtra="4dp"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="16dp"
app:cardElevation="0dp"
android:layout_marginBottom="24dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvTituloDica3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A calcular..."
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/tvDescDica3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="A prever gastos até ao fim do mês..."
android:textColor="@color/text_secondary"
android:textSize="14sp"
android:lineSpacingExtra="4dp"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Top Despesas"
android:textAllCaps="true"
android:textColor="@color/text_secondary"
android:textSize="12sp"
android:textStyle="bold"
android:layout_marginBottom="12dp"/>
<LinearLayout
android:id="@+id/layoutDistribuicao"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginBottom="20dp">
</LinearLayout> </LinearLayout>
</ScrollView>
</FrameLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView>

View File

@@ -3,111 +3,170 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/bg_dinamico"> android:background="@color/fundo_app">
<ScrollView <androidx.core.widget.NestedScrollView
android:id="@+id/scrollviewGraficos" android:id="@+id/scrollviewGraficos"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp"> android:padding="20dp">
<androidx.cardview.widget.CardView <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Terminal de Análise"
android:textAllCaps="true"
android:textColor="@color/text_secondary"
android:textSize="12sp"
android:textStyle="bold"
android:layout_marginBottom="16dp"/>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="24dp" android:layout_marginBottom="20dp"
app:cardBackgroundColor="@color/fundo_cartao" app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="16dp" app:cardCornerRadius="20dp"
app:cardElevation="2dp"> app:cardElevation="0dp"
app:strokeColor="@color/linha_separadora"
app:strokeWidth="1dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp"> android:padding="20dp">
<TextView <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Distribuição de Despesas" android:orientation="horizontal"
android:textColor="@color/texto_principal" android:gravity="center_vertical"
android:textSize="18sp" android:layout_marginBottom="24dp">
android:textStyle="bold"
android:layout_marginBottom="16dp"/> <ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@android:drawable/ic_menu_compass"
app:tint="@color/tech_accent_cyan" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="Distribuição de Despesas"
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<com.github.mikephil.charting.charts.PieChart <com.github.mikephil.charting.charts.PieChart
android:id="@+id/pieChartDespesas" android:id="@+id/pieChartDespesas"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="300dp"/> android:layout_height="300dp"/>
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </com.google.android.material.card.MaterialCardView>
<androidx.cardview.widget.CardView <com.google.android.material.card.MaterialCardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="24dp" android:layout_marginBottom="20dp"
app:cardBackgroundColor="@color/fundo_cartao" app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="16dp" app:cardCornerRadius="20dp"
app:cardElevation="2dp"> app:cardElevation="0dp"
app:strokeColor="@color/linha_separadora"
app:strokeWidth="1dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp"> android:padding="20dp">
<TextView <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Orçamento vs Gasto" android:orientation="horizontal"
android:textColor="@color/texto_principal" android:gravity="center_vertical"
android:textSize="18sp" android:layout_marginBottom="24dp">
android:textStyle="bold"
android:layout_marginBottom="16dp"/> <ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@android:drawable/ic_menu_sort_by_size"
app:tint="@color/tech_accent_cyan" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="Orçamento vs Gasto Real"
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<com.github.mikephil.charting.charts.BarChart <com.github.mikephil.charting.charts.BarChart
android:id="@+id/barChartOrcamento" android:id="@+id/barChartOrcamento"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="300dp"/> android:layout_height="280dp"/>
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </com.google.android.material.card.MaterialCardView>
<androidx.cardview.widget.CardView <com.google.android.material.card.MaterialCardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="24dp" android:layout_marginBottom="80dp"
app:cardBackgroundColor="@color/fundo_cartao" app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="16dp" app:cardCornerRadius="20dp"
app:cardElevation="2dp"> app:cardElevation="0dp"
app:strokeColor="@color/linha_separadora"
app:strokeWidth="1dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp"> android:padding="20dp">
<TextView <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Tendência de Gastos" android:orientation="horizontal"
android:textColor="@color/texto_principal" android:gravity="center_vertical"
android:textSize="18sp" android:layout_marginBottom="24dp">
android:textStyle="bold"
android:layout_marginBottom="16dp"/> <ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@android:drawable/ic_menu_month"
app:tint="@color/tech_accent_cyan" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="Balanço (Tendência)"
android:textColor="@color/texto_principal"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<com.github.mikephil.charting.charts.BarChart <com.github.mikephil.charting.charts.BarChart
android:id="@+id/barChartTendencia" android:id="@+id/barChartTendencia"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="300dp"/> android:layout_height="250dp"/>
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </com.google.android.material.card.MaterialCardView>
</LinearLayout> </LinearLayout>
</ScrollView> </androidx.core.widget.NestedScrollView>
<LinearLayout <LinearLayout
android:id="@+id/layoutEstadoVazioGraficos" android:id="@+id/layoutEstadoVazioGraficos"
@@ -116,32 +175,32 @@
android:orientation="vertical" android:orientation="vertical"
android:gravity="center" android:gravity="center"
android:visibility="gone" android:visibility="gone"
android:padding="32dp"> android:padding="40dp">
<com.airbnb.lottie.LottieAnimationView <ImageView
android:layout_width="250dp" android:layout_width="100dp"
android:layout_height="250dp" android:layout_height="100dp"
app:lottie_rawRes="@raw/anim_grafico_vazio" android:src="@android:drawable/ic_menu_sort_by_size"
app:lottie_autoPlay="true" app:tint="@color/text_secondary"
app:lottie_loop="true"/> android:alpha="0.3"
android:layout_marginBottom="24dp"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="À espera de dados! 📊" android:text="Terminal inativo"
android:textSize="20sp" android:textSize="20sp"
android:textStyle="bold" android:textStyle="bold"
android:textColor="@color/texto_principal" android:textColor="@color/texto_principal"
android:layout_marginTop="16dp"/> android:layout_marginBottom="8dp"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Regista as tuas primeiras transações para veres a magia dos gráficos acontecer." android:text="A aguardar a introdução de dados financeiros para gerar análises e projeções."
android:textSize="15sp" android:textSize="14sp"
android:textAlignment="center" android:textAlignment="center"
android:textColor="?android:attr/textColorSecondary" android:textColor="@color/text_secondary"/>
android:layout_marginTop="8dp"/>
</LinearLayout> </LinearLayout>
</FrameLayout> </FrameLayout>

View File

@@ -3,18 +3,17 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/bg_dinamico"> android:background="@color/fundo_app">
<!-- Lista onde vão aparecer os Cofres -->
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerObjetivos" android:id="@+id/recyclerObjetivos"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="16dp" android:paddingHorizontal="16dp"
android:paddingTop="16dp"
android:clipToPadding="false" android:clipToPadding="false"
android:paddingBottom="80dp"/> android:paddingBottom="100dp"/>
<!-- Mensagem quando não há objetivos -->
<LinearLayout <LinearLayout
android:id="@+id/layoutObjetivosVazios" android:id="@+id/layoutObjetivosVazios"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@@ -22,25 +21,35 @@
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:orientation="vertical" android:orientation="vertical"
android:gravity="center" android:gravity="center"
android:visibility="gone"> android:visibility="gone"
android:padding="32dp">
<ImageView <ImageView
android:layout_width="80dp" android:layout_width="80dp"
android:layout_height="80dp" android:layout_height="80dp"
android:src="@drawable/ic_lazer" android:src="@drawable/ic_lazer"
app:tint="#A0AEC0" app:tint="@color/text_secondary"
android:layout_marginBottom="16dp"/> android:layout_marginBottom="16dp"
android:alpha="0.4"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Sem objetivos definidos." android:text="Sem objetivos definidos"
android:textColor="#A0AEC0" android:textColor="@color/texto_principal"
android:textSize="16sp" android:textSize="18sp"
android:textStyle="bold"/> android:textStyle="bold"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cria o teu primeiro cofre financeiro e começa a poupar para os teus sonhos."
android:textColor="@color/text_secondary"
android:textSize="14sp"
android:textAlignment="center"
android:layout_marginTop="8dp"/>
</LinearLayout> </LinearLayout>
<!-- Botão de Adicionar Objetivo -->
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabAdicionarObjetivo" android:id="@+id/fabAdicionarObjetivo"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@@ -49,8 +58,8 @@
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_margin="24dp" android:layout_margin="24dp"
android:src="@android:drawable/ic_input_add" android:src="@android:drawable/ic_input_add"
app:tint="#FFFFFF" app:tint="#1A202C"
app:backgroundTint="#00B8D4" app:backgroundTint="@color/tech_accent_cyan"
app:elevation="6dp"/> app:elevation="4dp"/>
</RelativeLayout> </RelativeLayout>

View File

@@ -4,31 +4,34 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
android:background="?android:attr/windowBackground" android:background="@color/fundo_app"
android:padding="16dp"> android:padding="20dp">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Planeamento de Orçamento" android:text="Planeamento Estratégico"
android:textColor="?android:attr/textColorPrimary" android:textAllCaps="true"
android:textSize="18sp" android:textColor="@color/text_secondary"
android:textSize="12sp"
android:textStyle="bold" android:textStyle="bold"
android:layout_marginBottom="12dp"/> android:layout_marginBottom="12dp"/>
<androidx.cardview.widget.CardView <com.google.android.material.card.MaterialCardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:cardBackgroundColor="?android:attr/colorBackgroundFloating" app:cardBackgroundColor="@color/fundo_cartao"
app:cardCornerRadius="16dp" app:cardCornerRadius="20dp"
app:cardElevation="2dp" app:cardElevation="0dp"
android:layout_marginBottom="16dp"> app:strokeColor="@color/linha_separadora"
app:strokeWidth="1dp"
android:layout_marginBottom="24dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp"> android:padding="20dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -41,79 +44,86 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:orientation="vertical" android:orientation="vertical"
android:layout_marginEnd="8dp"> android:layout_marginEnd="12dp">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Categoria" android:text="Categoria"
android:textColor="?android:attr/textColorSecondary" android:textColor="@color/text_secondary"
android:textSize="12sp" android:textSize="12sp"
android:layout_marginBottom="4dp"/> android:layout_marginBottom="8dp"/>
<TextView <TextView
android:id="@+id/txtCategoriaOrcamento" android:id="@+id/txtCategoriaOrcamento"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="45dp" android:layout_height="50dp"
android:text="Selecionar..." android:text="Selecionar..."
android:textColor="?android:attr/textColorPrimary" android:textColor="@color/texto_principal"
android:textSize="14sp" android:textSize="14sp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:paddingStart="12dp" android:paddingHorizontal="16dp"
android:paddingEnd="12dp" android:background="@drawable/bg_search_bar" />
android:background="@drawable/bg_coach_input_rect" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:orientation="vertical" android:orientation="vertical">
android:layout_marginStart="8dp">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Limite (€)" android:text="Limite (€)"
android:textColor="?android:attr/textColorSecondary" android:textColor="@color/text_secondary"
android:textSize="12sp" android:textSize="12sp"
android:layout_marginBottom="4dp"/> android:layout_marginBottom="8dp"/>
<EditText <LinearLayout
android:id="@+id/editLimiteOrcamento"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="45dp" android:layout_height="50dp"
android:hint="0.00" android:background="@drawable/bg_search_bar"
android:textColor="?android:attr/textColorPrimary" android:gravity="center_vertical"
android:textColorHint="?android:attr/textColorSecondary" android:paddingHorizontal="12dp">
android:inputType="numberDecimal"
android:backgroundTint="@color/tech_accent_cyan" <EditText
android:paddingStart="4dp" android:id="@+id/editLimiteOrcamento"
android:textSize="16sp" /> android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="0.00"
android:background="@android:color/transparent"
android:textColor="@color/texto_principal"
android:textColorHint="@color/text_secondary"
android:inputType="numberDecimal"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<Button <com.google.android.material.button.MaterialButton
android:id="@+id/btnDefinirOrcamento" android:id="@+id/btnDefinirOrcamento"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="45dp" android:layout_height="56dp"
android:text="Definir Orçamento" android:text="Ativar Orçamento"
android:textColor="#1A202C" android:textColor="@color/texto_dinamico"
android:textSize="14sp"
android:textStyle="bold" android:textStyle="bold"
android:layout_marginTop="16dp" android:layout_marginTop="20dp"
app:cornerRadius="8dp" app:cornerRadius="16dp"
app:backgroundTint="@color/tech_accent_cyan" /> app:backgroundTint="@color/tech_accent_cyan" />
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </com.google.android.material.card.MaterialCardView>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Orçamentos Ativos" android:text="Orçamentos Ativos"
android:textColor="?android:attr/textColorPrimary" android:textAllCaps="true"
android:textSize="18sp" android:textColor="@color/text_secondary"
android:textSize="12sp"
android:textStyle="bold" android:textStyle="bold"
android:layout_marginBottom="8dp"/> android:layout_marginBottom="12dp"/>
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -123,7 +133,9 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerOrcamentos" android:id="@+id/recyclerOrcamentos"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="80dp"/>
<LinearLayout <LinearLayout
android:id="@+id/layoutEstadoVazioOrcamento" android:id="@+id/layoutEstadoVazioOrcamento"
@@ -132,33 +144,32 @@
android:orientation="vertical" android:orientation="vertical"
android:gravity="center" android:gravity="center"
android:visibility="gone" android:visibility="gone"
android:padding="16dp"> android:padding="32dp">
<com.airbnb.lottie.LottieAnimationView <ImageView
android:layout_width="150dp" android:layout_width="80dp"
android:layout_height="150dp" android:layout_height="80dp"
app:lottie_rawRes="@raw/anim_vazio" android:src="@drawable/ic_alimentacao"
app:lottie_autoPlay="true" app:tint="@color/text_secondary"
app:lottie_loop="true"/> android:alpha="0.3"
android:layout_marginBottom="16dp"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Sem limites definidos!" android:text="Sem limites definidos"
android:textSize="16sp" android:textSize="18sp"
android:textStyle="bold" android:textStyle="bold"
android:textColor="?android:attr/textColorPrimary" android:textColor="@color/texto_principal"
android:layout_marginTop="8dp"/> android:layout_marginBottom="8dp"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Usa o cartão acima para definir objetivos." android:text="Usa o painel acima para definir limites de gastos por categoria."
android:textSize="14sp" android:textSize="14sp"
android:textAlignment="center" android:textAlignment="center"
android:textColor="?android:attr/textColorSecondary" android:textColor="@color/text_secondary"/>
android:layout_marginTop="4dp"/>
</LinearLayout> </LinearLayout>
</FrameLayout> </FrameLayout>
</LinearLayout> </LinearLayout>

View File

@@ -4,38 +4,45 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
android:background="@color/bg_dinamico"> android:background="@color/fundo_app">
<LinearLayout <androidx.cardview.widget.CardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp" android:layout_marginHorizontal="20dp"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:background="@drawable/bg_search_bar" app:cardBackgroundColor="@color/fundo_cartao"
android:orientation="horizontal" app:cardCornerRadius="12dp"
android:padding="12dp" app:cardElevation="0dp">
android:gravity="center_vertical">
<ImageView <LinearLayout
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@android:drawable/ic_menu_search"
app:tint="#A0AEC0" />
<EditText
android:id="@+id/editPesquisar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="12dp" android:orientation="horizontal"
android:background="@android:color/transparent" android:padding="12dp"
android:hint="Pesquisar transação..." android:gravity="center_vertical">
android:textColorHint="#718096"
android:textColor="@color/texto_principal" <ImageView
android:textSize="14sp" android:layout_width="20dp"
android:inputType="text" android:layout_height="20dp"
android:maxLines="1"/> android:src="@android:drawable/ic_menu_search"
</LinearLayout> app:tint="@color/text_secondary" />
<EditText
android:id="@+id/editPesquisar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:background="@android:color/transparent"
android:hint="Pesquisar transação..."
android:textColorHint="@color/text_secondary"
android:textColor="@color/texto_principal"
android:textSize="14sp"
android:inputType="text"
android:maxLines="1"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -80,7 +87,7 @@
android:text="Clica no botão + para começares a registar os teus movimentos." android:text="Clica no botão + para começares a registar os teus movimentos."
android:textSize="14sp" android:textSize="14sp"
android:textAlignment="center" android:textAlignment="center"
android:textColor="?android:attr/textColorSecondary" android:textColor="@color/text_secondary"
android:layout_marginTop="8dp"/> android:layout_marginTop="8dp"/>
</LinearLayout> </LinearLayout>
</FrameLayout> </FrameLayout>

View File

@@ -1,15 +1,17 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardObjetivo" android:id="@+id/cardObjetivo"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp" android:layout_marginHorizontal="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="12dp"
app:cardCornerRadius="16dp" app:cardCornerRadius="20dp"
app:cardElevation="2dp" app:cardElevation="0dp"
app:cardBackgroundColor="?android:attr/colorBackgroundFloating"> app:strokeColor="@color/linha_separadora"
app:strokeWidth="1dp"
app:cardBackgroundColor="@color/fundo_cartao">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -17,74 +19,74 @@
android:orientation="vertical" android:orientation="vertical"
android:padding="20dp"> android:padding="20dp">
<RelativeLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView <ImageView
android:id="@+id/imgIconeObjetivo" android:id="@+id/imgIconeObjetivo"
android:layout_width="28dp" android:layout_width="40dp"
android:layout_height="28dp" android:layout_height="40dp"
android:layout_centerVertical="true" android:background="@drawable/bg_circle_icon"
android:src="@drawable/ic_lazer" android:src="@drawable/ic_lazer"
app:tint="#00B8D4" /> android:padding="8dp"
app:tint="@color/tech_accent_cyan" />
<TextView <TextView
android:id="@+id/tvNomeObjetivo" android:id="@+id/tvNomeObjetivo"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerVertical="true" android:layout_marginStart="16dp"
android:layout_marginStart="12dp"
android:layout_toEndOf="@id/imgIconeObjetivo"
android:layout_toStartOf="@id/layoutBotoesAcao"
android:text="Nome do Objetivo" android:text="Nome do Objetivo"
android:textColor="?android:attr/textColorPrimary" android:textColor="@color/texto_principal"
android:textSize="18sp" android:textSize="18sp"
android:textStyle="bold" /> android:textStyle="bold" />
<!-- Zona dos Botões de Ação -->
<LinearLayout <LinearLayout
android:id="@+id/layoutBotoesAcao" android:id="@+id/layoutBotoesAcao"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:orientation="horizontal"> android:orientation="horizontal">
<!-- ✏️ Novo Botão Editar -->
<ImageView <ImageView
android:id="@+id/btnEditarObjetivo" android:id="@+id/btnEditarObjetivo"
android:layout_width="24dp" android:layout_width="28dp"
android:layout_height="24dp" android:layout_height="28dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="12dp"
android:padding="4dp"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:src="@android:drawable/ic_menu_edit" android:src="@android:drawable/ic_menu_edit"
app:tint="#ECC94B" /> app:tint="@color/text_secondary" />
<!-- 🗑️ Botão Eliminar -->
<ImageView <ImageView
android:id="@+id/btnEliminarObjetivo" android:id="@+id/btnEliminarObjetivo"
android:layout_width="24dp" android:layout_width="28dp"
android:layout_height="24dp" android:layout_height="28dp"
android:padding="4dp"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:src="@android:drawable/ic_menu_delete" android:src="@android:drawable/ic_menu_delete"
app:tint="#F56565" /> app:tint="@color/text_secondary" />
</LinearLayout> </LinearLayout>
</RelativeLayout> </LinearLayout>
<TextView <TextView
android:id="@+id/tvValoresObjetivo" android:id="@+id/tvValoresObjetivo"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginTop="16dp"
android:text="Guardado: € 0.00 / Alvo: € 0.00" android:text="Guardado: € 0.00 / Alvo: € 0.00"
android:textColor="?android:attr/textColorSecondary" android:textColor="@color/text_secondary"
android:textSize="14sp" /> android:textSize="13sp"
android:fontFamily="sans-serif-medium"
android:letterSpacing="0.02"/>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginTop="8dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
@@ -92,20 +94,22 @@
android:id="@+id/progressObjetivo" android:id="@+id/progressObjetivo"
style="?android:attr/progressBarStyleHorizontal" style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="8dp" android:layout_height="6dp"
android:layout_weight="1" android:layout_weight="1"
android:max="100" android:max="100"
android:progress="0" android:progress="0"
android:progressTint="#00B8D4" /> android:progressTint="@color/tech_accent_cyan"
android:progressBackgroundTint="@color/linha_separadora" />
<TextView <TextView
android:id="@+id/tvPercentagemObjetivo" android:id="@+id/tvPercentagemObjetivo"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="12dp" android:layout_marginStart="16dp"
android:text="0%" android:text="0%"
android:textColor="#00B8D4" android:textColor="@color/tech_accent_cyan"
android:textSize="16sp"
android:textStyle="bold" /> android:textStyle="bold" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </com.google.android.material.card.MaterialCardView>

View File

@@ -1,19 +1,20 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp" android:layout_marginBottom="12dp"
android:layout_marginVertical="8dp" app:cardBackgroundColor="@color/fundo_cartao"
app:cardBackgroundColor="?android:attr/colorBackgroundFloating" app:cardCornerRadius="20dp"
app:cardCornerRadius="16dp" app:cardElevation="0dp"
app:cardElevation="4dp"> app:strokeColor="@color/linha_separadora"
app:strokeWidth="1dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp"> android:padding="20dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -25,6 +26,8 @@
android:id="@+id/imgIconeOrcamento" android:id="@+id/imgIconeOrcamento"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:background="@drawable/bg_circle_icon"
android:padding="8dp"
android:src="@drawable/ic_alimentacao" android:src="@drawable/ic_alimentacao"
app:tint="@color/tech_accent_cyan" /> app:tint="@color/tech_accent_cyan" />
@@ -33,20 +36,21 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:layout_marginStart="12dp" android:layout_marginStart="16dp"
android:text="Alimentação" android:text="Alimentação"
android:textColor="?android:attr/textColorPrimary" android:textColor="@color/texto_principal"
android:textSize="18sp" android:textSize="16sp"
android:textStyle="bold" /> android:textStyle="bold" />
<ImageView <ImageView
android:id="@+id/btnEliminarOrcamento" android:id="@+id/btnEliminarOrcamento"
android:layout_width="28dp" android:layout_width="28dp"
android:layout_height="28dp" android:layout_height="28dp"
android:layout_marginEnd="12dp" android:layout_marginEnd="16dp"
android:padding="4dp"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:src="@android:drawable/ic_menu_delete" android:src="@android:drawable/ic_menu_delete"
app:tint="#F56565" /> app:tint="@color/text_secondary" />
<TextView <TextView
android:id="@+id/tvPercentagemOrcamento" android:id="@+id/tvPercentagemOrcamento"
@@ -54,6 +58,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="75%" android:text="75%"
android:textColor="@color/tech_accent_cyan" android:textColor="@color/tech_accent_cyan"
android:textSize="16sp"
android:textStyle="bold" /> android:textStyle="bold" />
</LinearLayout> </LinearLayout>
@@ -61,19 +66,22 @@
android:id="@+id/progressOrcamento" android:id="@+id/progressOrcamento"
style="?android:attr/progressBarStyleHorizontal" style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="8dp" android:layout_height="6dp"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:progress="75" android:progress="75"
android:progressDrawable="@drawable/custom_progress_bar" /> android:progressTint="@color/tech_accent_cyan"
android:progressBackgroundTint="@color/linha_separadora" />
<TextView <TextView
android:id="@+id/tvValoresOrcamento" android:id="@+id/tvValoresOrcamento"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Gasto: € 150.00 / Limite: € 200.00" android:text="Gasto: € 150.00 / Limite: € 200.00"
android:textColor="?android:attr/textColorSecondary" android:textColor="@color/text_secondary"
android:textSize="12sp" android:textSize="12sp"
android:fontFamily="sans-serif-medium"
android:letterSpacing="0.02"
android:textAlignment="viewEnd" /> android:textAlignment="viewEnd" />
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </com.google.android.material.card.MaterialCardView>