tudo a andar rapido vamossss
This commit is contained in:
@@ -17,6 +17,25 @@ import com.example.lifegrid.menu.DocumentosFragment;
|
||||
import com.example.lifegrid.menu.GraficosFragment;
|
||||
import com.example.lifegrid.menu.MetasFragment;
|
||||
import com.example.lifegrid.menu.TransacoesFragment;
|
||||
import com.example.lifegrid.models.Transacao;
|
||||
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Toast;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.auth.FirebaseUser;
|
||||
import com.google.firebase.database.DataSnapshot;
|
||||
import com.google.firebase.database.DatabaseError;
|
||||
import com.google.firebase.database.DatabaseReference;
|
||||
import com.google.firebase.database.FirebaseDatabase;
|
||||
import com.google.firebase.database.ValueEventListener;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* TelaInicialActivity funciona como a janela mestre (Container) de navegação da aplicação.
|
||||
@@ -33,6 +52,13 @@ public class TelaInicialActivity extends AppCompatActivity {
|
||||
private TextView tvTransacoes3;
|
||||
private TextView tvValor4;
|
||||
private TextView tvTransacoes4;
|
||||
private TextView tvTitulo;
|
||||
private TextView tvTitulo2;
|
||||
|
||||
private Spinner spinnerMes;
|
||||
private Spinner spinnerAno;
|
||||
|
||||
private String[] meses = {"Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -45,6 +71,22 @@ public class TelaInicialActivity extends AppCompatActivity {
|
||||
return insets;
|
||||
});
|
||||
|
||||
tvValor = findViewById(R.id.tvValor);
|
||||
tvTransacoes = findViewById(R.id.tvTransacoes);
|
||||
tvValor2 = findViewById(R.id.tvValor2);
|
||||
tvTransacoes2 = findViewById(R.id.tvTransacoes2);
|
||||
tvValor3 = findViewById(R.id.tvValor3);
|
||||
tvTransacoes3 = findViewById(R.id.tvTransacoes3);
|
||||
tvValor4 = findViewById(R.id.tvValor4);
|
||||
tvTransacoes4 = findViewById(R.id.tvTransacoes4);
|
||||
tvTitulo = findViewById(R.id.tvTitulo);
|
||||
tvTitulo2 = findViewById(R.id.tvTitulo2);
|
||||
|
||||
spinnerMes = findViewById(R.id.spinnerMes);
|
||||
spinnerAno = findViewById(R.id.spinnerAno);
|
||||
|
||||
setupSpinners();
|
||||
|
||||
Fragment transacoesFragment2 = new TransacoesFragment();
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.fragmentContainerView, transacoesFragment2)
|
||||
@@ -93,4 +135,108 @@ public class TelaInicialActivity extends AppCompatActivity {
|
||||
.commit();
|
||||
});
|
||||
}
|
||||
|
||||
private void setupSpinners() {
|
||||
ArrayAdapter<String> mesAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, meses);
|
||||
mesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinnerMes.setAdapter(mesAdapter);
|
||||
|
||||
int currentYear = Calendar.getInstance().get(Calendar.YEAR);
|
||||
List<String> anos = new ArrayList<>();
|
||||
for (int i = currentYear - 5; i <= currentYear + 5; i++) {
|
||||
anos.add(String.valueOf(i));
|
||||
}
|
||||
ArrayAdapter<String> anoAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, anos);
|
||||
anoAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinnerAno.setAdapter(anoAdapter);
|
||||
|
||||
// Set current month and year
|
||||
spinnerMes.setSelection(Calendar.getInstance().get(Calendar.MONTH));
|
||||
spinnerAno.setSelection(anos.indexOf(String.valueOf(currentYear)));
|
||||
|
||||
AdapterView.OnItemSelectedListener listener = new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, android.view.View view, int position, long id) {
|
||||
carregarDados();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {}
|
||||
};
|
||||
|
||||
spinnerMes.setOnItemSelectedListener(listener);
|
||||
spinnerAno.setOnItemSelectedListener(listener);
|
||||
}
|
||||
|
||||
private void carregarDados() {
|
||||
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||
if (user == null) return;
|
||||
|
||||
int mesSelecionado = spinnerMes.getSelectedItemPosition() + 1; // 1 to 12
|
||||
String anoSelecionado = spinnerAno.getSelectedItem().toString();
|
||||
|
||||
String mesNome = meses[spinnerMes.getSelectedItemPosition()];
|
||||
tvTitulo.setText("Receitas (" + mesNome + " " + anoSelecionado + ")");
|
||||
tvTitulo2.setText("Despesas (" + mesNome + " " + anoSelecionado + ")");
|
||||
|
||||
DatabaseReference transacoesRef = FirebaseDatabase.getInstance().getReference()
|
||||
.child("users").child(user.getUid()).child("transacoes");
|
||||
|
||||
transacoesRef.addValueEventListener(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
double totalReceitas = 0;
|
||||
double totalDespesas = 0;
|
||||
int countReceitas = 0;
|
||||
int countDespesas = 0;
|
||||
|
||||
for (DataSnapshot ds : snapshot.getChildren()) {
|
||||
Transacao transacao = ds.getValue(Transacao.class);
|
||||
if (transacao != null && transacao.getData() != null) {
|
||||
String[] parts = transacao.getData().split("/");
|
||||
if (parts.length == 3) {
|
||||
try {
|
||||
int mesTransacao = Integer.parseInt(parts[1]);
|
||||
String anoTransacao = parts[2];
|
||||
|
||||
if (mesTransacao == mesSelecionado && anoTransacao.equals(anoSelecionado)) {
|
||||
double valor = Double.parseDouble(transacao.getValor().replace(",", "."));
|
||||
if ("Receita".equals(transacao.getTipo())) {
|
||||
totalReceitas += valor;
|
||||
countReceitas++;
|
||||
} else if ("Despesa".equals(transacao.getTipo())) {
|
||||
totalDespesas += valor;
|
||||
countDespesas++;
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tvValor.setText(String.format(Locale.getDefault(), "%.2f€", totalReceitas));
|
||||
tvTransacoes.setText(countReceitas + " transações");
|
||||
|
||||
tvValor2.setText(String.format(Locale.getDefault(), "%.2f€", totalDespesas));
|
||||
tvTransacoes2.setText(countDespesas + " transações");
|
||||
|
||||
double saldo = totalReceitas - totalDespesas;
|
||||
tvValor3.setText(String.format(Locale.getDefault(), "%.2f€", saldo));
|
||||
if (saldo >= 0) {
|
||||
tvTransacoes3.setText("Poupança positiva");
|
||||
tvTransacoes3.setTextColor(android.graphics.Color.parseColor("#8E8E8E"));
|
||||
} else {
|
||||
tvTransacoes3.setText("Poupança negativa");
|
||||
tvTransacoes3.setTextColor(android.graphics.Color.parseColor("#FF0000"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
Toast.makeText(TelaInicialActivity.this, "Erro ao carregar dados", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
144
app/src/main/java/com/example/lifegrid/adapters/MetaAdapter.java
Normal file
144
app/src/main/java/com/example/lifegrid/adapters/MetaAdapter.java
Normal file
@@ -0,0 +1,144 @@
|
||||
package com.example.lifegrid.adapters;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.example.lifegrid.R;
|
||||
import com.example.lifegrid.models.Meta;
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class MetaAdapter extends RecyclerView.Adapter<MetaAdapter.MetaViewHolder> {
|
||||
|
||||
private List<Meta> metasList;
|
||||
private OnItemClickListener listener;
|
||||
|
||||
public interface OnItemClickListener {
|
||||
void onDeleteClick(Meta meta);
|
||||
void onAddValueClick(Meta meta, double valorAdicional, EditText editText);
|
||||
}
|
||||
|
||||
public MetaAdapter(List<Meta> metasList, OnItemClickListener listener) {
|
||||
this.metasList = metasList;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MetaViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_meta, parent, false);
|
||||
return new MetaViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull MetaViewHolder holder, int position) {
|
||||
Meta meta = metasList.get(position);
|
||||
|
||||
holder.tvNome.setText(meta.getNome());
|
||||
holder.tvCategoria.setText(meta.getCategoria());
|
||||
|
||||
double valorObjetivo = 0;
|
||||
double valorGuardado = 0;
|
||||
|
||||
try {
|
||||
valorObjetivo = Double.parseDouble(meta.getValor().replace(",", "."));
|
||||
if (meta.getValorGuardado() != null && !meta.getValorGuardado().isEmpty()) {
|
||||
valorGuardado = Double.parseDouble(meta.getValorGuardado().replace(",", "."));
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
holder.tvValorStatus.setText(String.format(Locale.getDefault(), "%.2f€ / %.2f€", valorGuardado, valorObjetivo));
|
||||
|
||||
int progress = 0;
|
||||
if (valorObjetivo > 0) {
|
||||
progress = (int) ((valorGuardado / valorObjetivo) * 100);
|
||||
if (progress > 100) progress = 100;
|
||||
}
|
||||
holder.pbProgresso.setProgress(progress);
|
||||
holder.tvPercentagem.setText(progress + ".0%");
|
||||
|
||||
// Calculate days remaining
|
||||
long daysRemaining = 0;
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault());
|
||||
try {
|
||||
Date goalDate = sdf.parse(meta.getData());
|
||||
if (goalDate != null) {
|
||||
long diff = goalDate.getTime() - new Date().getTime();
|
||||
daysRemaining = diff / (1000 * 60 * 60 * 24);
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (daysRemaining >= 0) {
|
||||
holder.tvDiasRestantes.setText("Faltam " + daysRemaining + " dias");
|
||||
} else {
|
||||
holder.tvDiasRestantes.setText("Atrasado " + Math.abs(daysRemaining) + " dias");
|
||||
}
|
||||
|
||||
holder.ivDelete.setOnClickListener(v -> {
|
||||
if (listener != null) {
|
||||
listener.onDeleteClick(meta);
|
||||
}
|
||||
});
|
||||
|
||||
holder.btnAddValor.setOnClickListener(v -> {
|
||||
if (listener != null) {
|
||||
String input = holder.etAdicionarValor.getText().toString().trim();
|
||||
if (!input.isEmpty()) {
|
||||
try {
|
||||
double valorAdicional = Double.parseDouble(input);
|
||||
listener.onAddValueClick(meta, valorAdicional, holder.etAdicionarValor);
|
||||
} catch (NumberFormatException e) {
|
||||
Toast.makeText(v.getContext(), "Valor inválido", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return metasList.size();
|
||||
}
|
||||
|
||||
public static class MetaViewHolder extends RecyclerView.ViewHolder {
|
||||
ImageView ivIcon, ivDelete, ivCalendar;
|
||||
TextView tvNome, tvCategoria, tvLabelProgresso, tvValorStatus, tvDiasRestantes, tvPercentagem;
|
||||
ProgressBar pbProgresso;
|
||||
EditText etAdicionarValor;
|
||||
MaterialButton btnAddValor;
|
||||
|
||||
public MetaViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ivIcon = itemView.findViewById(R.id.ivIcon);
|
||||
ivDelete = itemView.findViewById(R.id.ivDelete);
|
||||
ivCalendar = itemView.findViewById(R.id.ivCalendar);
|
||||
tvNome = itemView.findViewById(R.id.tvNome);
|
||||
tvCategoria = itemView.findViewById(R.id.tvCategoria);
|
||||
tvLabelProgresso = itemView.findViewById(R.id.tvLabelProgresso);
|
||||
tvValorStatus = itemView.findViewById(R.id.tvValorStatus);
|
||||
tvDiasRestantes = itemView.findViewById(R.id.tvDiasRestantes);
|
||||
tvPercentagem = itemView.findViewById(R.id.tvPercentagem);
|
||||
pbProgresso = itemView.findViewById(R.id.pbProgresso);
|
||||
etAdicionarValor = itemView.findViewById(R.id.etAdicionarValor);
|
||||
btnAddValor = itemView.findViewById(R.id.btnAddValor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.example.lifegrid.adapters;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.example.lifegrid.R;
|
||||
import com.example.lifegrid.models.Transacao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TransacaoAdapter extends RecyclerView.Adapter<TransacaoAdapter.TransacaoViewHolder> {
|
||||
|
||||
private List<Transacao> transacoesList;
|
||||
private OnItemClickListener listener;
|
||||
|
||||
public interface OnItemClickListener {
|
||||
void onDeleteClick(Transacao transacao);
|
||||
}
|
||||
|
||||
public TransacaoAdapter(List<Transacao> transacoesList, OnItemClickListener listener) {
|
||||
this.transacoesList = transacoesList;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public TransacaoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_transacao, parent, false);
|
||||
return new TransacaoViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull TransacaoViewHolder holder, int position) {
|
||||
Transacao transacao = transacoesList.get(position);
|
||||
holder.tvDescricao.setText(transacao.getDescricao());
|
||||
holder.tvCategoria.setText(transacao.getCategoria());
|
||||
holder.tvData.setText(transacao.getData());
|
||||
|
||||
if ("Receita".equals(transacao.getTipo())) {
|
||||
holder.ivIconBackground.setBackgroundResource(R.drawable.bg_circle_green);
|
||||
holder.ivIcon.setImageResource(R.drawable.diagonalarrowrightup_110941);
|
||||
holder.ivIcon.setColorFilter(Color.parseColor("#2ECC71"));
|
||||
holder.tvValor.setText("+" + transacao.getValor() + "€");
|
||||
holder.tvValor.setTextColor(Color.parseColor("#2ECC71"));
|
||||
} else {
|
||||
holder.ivIconBackground.setBackgroundResource(R.drawable.bg_circle_red);
|
||||
holder.ivIcon.setImageResource(R.drawable.diagonalarrowleftdownoutline_110924);
|
||||
holder.ivIcon.setColorFilter(Color.parseColor("#E74C3C"));
|
||||
holder.tvValor.setText("-" + transacao.getValor() + "€");
|
||||
holder.tvValor.setTextColor(Color.parseColor("#E74C3C"));
|
||||
}
|
||||
|
||||
holder.ivDelete.setOnClickListener(v -> {
|
||||
if (listener != null) {
|
||||
listener.onDeleteClick(transacao);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return transacoesList.size();
|
||||
}
|
||||
|
||||
public static class TransacaoViewHolder extends RecyclerView.ViewHolder {
|
||||
ImageView ivIconBackground, ivIcon, ivDelete;
|
||||
TextView tvDescricao, tvCategoria, tvData, tvValor;
|
||||
|
||||
public TransacaoViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ivIconBackground = itemView.findViewById(R.id.ivIconBackground);
|
||||
ivIcon = itemView.findViewById(R.id.ivIcon);
|
||||
ivDelete = itemView.findViewById(R.id.ivDelete);
|
||||
tvDescricao = itemView.findViewById(R.id.tvDescricao);
|
||||
tvCategoria = itemView.findViewById(R.id.tvCategoria);
|
||||
tvData = itemView.findViewById(R.id.tvData);
|
||||
tvValor = itemView.findViewById(R.id.tvValor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,16 +14,32 @@ import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.example.lifegrid.R;
|
||||
import com.example.lifegrid.adapters.MetaAdapter;
|
||||
import com.example.lifegrid.models.Meta;
|
||||
import com.example.lifegrid.models.Transacao;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.auth.FirebaseUser;
|
||||
import com.google.firebase.database.DataSnapshot;
|
||||
import com.google.firebase.database.DatabaseError;
|
||||
import com.google.firebase.database.DatabaseReference;
|
||||
import com.google.firebase.database.FirebaseDatabase;
|
||||
import com.google.firebase.database.ValueEventListener;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MetasFragment projeta objetivos futuros onde o utilizador fixa montantes e datas a alcançar
|
||||
@@ -31,6 +47,13 @@ import com.google.firebase.database.FirebaseDatabase;
|
||||
*/
|
||||
public class MetasFragment extends Fragment {
|
||||
|
||||
private RecyclerView rvMetas;
|
||||
private MetaAdapter metaAdapter;
|
||||
private List<Meta> metasList;
|
||||
private TextView tvEmptyState;
|
||||
private DatabaseReference databaseReference;
|
||||
private String userId;
|
||||
|
||||
public MetasFragment() {
|
||||
// Construtor público vazio obrigatório
|
||||
}
|
||||
@@ -49,9 +72,100 @@ public class MetasFragment extends Fragment {
|
||||
Button novaTransacaoButton = root.findViewById(R.id.novaTransacaoButton);
|
||||
novaTransacaoButton.setOnClickListener(v -> showNovaMetaDialog());
|
||||
|
||||
rvMetas = root.findViewById(R.id.rvMetas);
|
||||
tvEmptyState = root.findViewById(R.id.textView13);
|
||||
|
||||
rvMetas.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
metasList = new ArrayList<>();
|
||||
|
||||
metaAdapter = new MetaAdapter(metasList, new MetaAdapter.OnItemClickListener() {
|
||||
@Override
|
||||
public void onDeleteClick(Meta meta) {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle("Excluir Meta")
|
||||
.setMessage("Tem a certeza que deseja excluir esta meta?")
|
||||
.setPositiveButton("Sim", (dialog, which) -> {
|
||||
if (databaseReference != null && userId != null && meta.getId() != null) {
|
||||
databaseReference.child("users").child(userId).child("metas").child(meta.getId()).removeValue();
|
||||
Toast.makeText(requireContext(), "Meta excluída.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
})
|
||||
.setNegativeButton("Não", null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAddValueClick(Meta meta, double valorAdicional, EditText editText) {
|
||||
if (databaseReference != null && userId != null && meta.getId() != null) {
|
||||
double valorAtual = 0;
|
||||
if (meta.getValorGuardado() != null && !meta.getValorGuardado().isEmpty()) {
|
||||
valorAtual = Double.parseDouble(meta.getValorGuardado().replace(",", "."));
|
||||
}
|
||||
|
||||
double novoValor = valorAtual + valorAdicional;
|
||||
|
||||
// Update Meta
|
||||
databaseReference.child("users").child(userId).child("metas").child(meta.getId())
|
||||
.child("valorGuardado").setValue(String.format(Locale.US, "%.2f", novoValor));
|
||||
|
||||
// Create a Despesa Transaction to adjust the global balance (Receitas - Despesas)
|
||||
String todayDate = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).format(new Date());
|
||||
Transacao transacao = new Transacao("Despesa", String.format(Locale.US, "%.2f", valorAdicional), "Investimento/Meta", "Adicionado à meta: " + meta.getNome(), todayDate);
|
||||
|
||||
String key = databaseReference.child("users").child(userId).child("transacoes").push().getKey();
|
||||
if (key != null) {
|
||||
databaseReference.child("users").child(userId).child("transacoes").child(key).setValue(transacao);
|
||||
}
|
||||
|
||||
editText.setText("");
|
||||
Toast.makeText(requireContext(), "Valor adicionado e despesa registada!", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
rvMetas.setAdapter(metaAdapter);
|
||||
|
||||
carregarMetas();
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void carregarMetas() {
|
||||
FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
|
||||
if (currentUser == null) return;
|
||||
|
||||
userId = currentUser.getUid();
|
||||
databaseReference = FirebaseDatabase.getInstance().getReference();
|
||||
|
||||
databaseReference.child("users").child(userId).child("metas").addValueEventListener(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
metasList.clear();
|
||||
for (DataSnapshot ds : snapshot.getChildren()) {
|
||||
Meta m = ds.getValue(Meta.class);
|
||||
if (m != null) {
|
||||
m.setId(ds.getKey());
|
||||
metasList.add(m);
|
||||
}
|
||||
}
|
||||
metaAdapter.notifyDataSetChanged();
|
||||
|
||||
if (metasList.isEmpty()) {
|
||||
tvEmptyState.setVisibility(View.VISIBLE);
|
||||
rvMetas.setVisibility(View.GONE);
|
||||
} else {
|
||||
tvEmptyState.setVisibility(View.GONE);
|
||||
rvMetas.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
Toast.makeText(requireContext(), "Erro ao carregar metas.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showNovaMetaDialog() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
|
||||
View dialogView = getLayoutInflater().inflate(R.layout.dialog_nova_meta, null);
|
||||
|
||||
@@ -25,12 +25,21 @@ import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.example.lifegrid.R;
|
||||
import com.example.lifegrid.adapters.TransacaoAdapter;
|
||||
import com.example.lifegrid.models.Transacao;
|
||||
import com.google.firebase.Firebase;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.auth.FirebaseUser;
|
||||
import com.google.firebase.database.DataSnapshot;
|
||||
import com.google.firebase.database.DatabaseError;
|
||||
import com.google.firebase.database.DatabaseReference;
|
||||
import com.google.firebase.database.FirebaseDatabase;
|
||||
import com.google.firebase.database.ValueEventListener;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TransacoesFragment controla a aba pertencente às listagens e histórico de carteira e gestão de dados base.
|
||||
@@ -38,7 +47,12 @@ import com.google.firebase.database.FirebaseDatabase;
|
||||
*/
|
||||
public class TransacoesFragment extends Fragment {
|
||||
|
||||
|
||||
private RecyclerView rvTransacoes;
|
||||
private TransacaoAdapter transacaoAdapter;
|
||||
private List<Transacao> transacoesList;
|
||||
private TextView tvEmptyState;
|
||||
private DatabaseReference databaseReference;
|
||||
private String userId;
|
||||
|
||||
public TransacoesFragment() {
|
||||
// Construtor público vazio obrigatório
|
||||
@@ -60,9 +74,68 @@ public class TransacoesFragment extends Fragment {
|
||||
Button novaTransacaoButton = root.findViewById(R.id.novaTransacaoButton);
|
||||
novaTransacaoButton.setOnClickListener(v -> showNovaTransacaoDialog());
|
||||
|
||||
rvTransacoes = root.findViewById(R.id.rvTransacoes);
|
||||
tvEmptyState = root.findViewById(R.id.textView13);
|
||||
|
||||
rvTransacoes.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
transacoesList = new ArrayList<>();
|
||||
|
||||
transacaoAdapter = new TransacaoAdapter(transacoesList, transacao -> {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle("Excluir Transação")
|
||||
.setMessage("Tem a certeza que deseja excluir esta transação?")
|
||||
.setPositiveButton("Sim", (dialog, which) -> {
|
||||
if (databaseReference != null && userId != null && transacao.getId() != null) {
|
||||
databaseReference.child("users").child(userId).child("transacoes").child(transacao.getId()).removeValue();
|
||||
Toast.makeText(requireContext(), "Transação excluída.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
})
|
||||
.setNegativeButton("Não", null)
|
||||
.show();
|
||||
});
|
||||
rvTransacoes.setAdapter(transacaoAdapter);
|
||||
|
||||
carregarTransacoes();
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void carregarTransacoes() {
|
||||
FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
|
||||
if (currentUser == null) return;
|
||||
|
||||
userId = currentUser.getUid();
|
||||
databaseReference = FirebaseDatabase.getInstance().getReference();
|
||||
|
||||
databaseReference.child("users").child(userId).child("transacoes").addValueEventListener(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
transacoesList.clear();
|
||||
for (DataSnapshot ds : snapshot.getChildren()) {
|
||||
Transacao t = ds.getValue(Transacao.class);
|
||||
if (t != null) {
|
||||
t.setId(ds.getKey());
|
||||
transacoesList.add(t);
|
||||
}
|
||||
}
|
||||
transacaoAdapter.notifyDataSetChanged();
|
||||
|
||||
if (transacoesList.isEmpty()) {
|
||||
tvEmptyState.setVisibility(View.VISIBLE);
|
||||
rvTransacoes.setVisibility(View.GONE);
|
||||
} else {
|
||||
tvEmptyState.setVisibility(View.GONE);
|
||||
rvTransacoes.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
Toast.makeText(requireContext(), "Erro ao carregar transações.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Cria e monta manualmente uma janela Modal (Pop-up) a fim do utilizador preencher
|
||||
* os detalhes referentes a uma recém aquisição de receita ou encargo para alimentar a base de dados.
|
||||
|
||||
@@ -5,6 +5,8 @@ public class Meta {
|
||||
private String categoria;
|
||||
private String valor;
|
||||
private String data;
|
||||
private String valorGuardado = "0.00";
|
||||
private String id;
|
||||
|
||||
public Meta(){
|
||||
}
|
||||
@@ -47,4 +49,22 @@ public class Meta {
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public String getValorGuardado() {
|
||||
return valorGuardado;
|
||||
}
|
||||
|
||||
public void setValorGuardado(String valorGuardado) {
|
||||
this.valorGuardado = valorGuardado;
|
||||
}
|
||||
|
||||
@com.google.firebase.database.Exclude
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@com.google.firebase.database.Exclude
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ public class Transacao {
|
||||
private String categoria;
|
||||
private String descricao;
|
||||
private String data;
|
||||
private String id;
|
||||
|
||||
public Transacao() {
|
||||
}
|
||||
@@ -58,4 +59,14 @@ public class Transacao {
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@com.google.firebase.database.Exclude
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@com.google.firebase.database.Exclude
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
6
app/src/main/res/drawable/bg_badge_category.xml
Normal file
6
app/src/main/res/drawable/bg_badge_category.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#E8ECEF" />
|
||||
<corners android:radius="12dp" />
|
||||
</shape>
|
||||
5
app/src/main/res/drawable/bg_circle_green.xml
Normal file
5
app/src/main/res/drawable/bg_circle_green.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="#E8F8F0" />
|
||||
</shape>
|
||||
5
app/src/main/res/drawable/bg_circle_red.xml
Normal file
5
app/src/main/res/drawable/bg_circle_red.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="#FCE8E8" />
|
||||
</shape>
|
||||
17
app/src/main/res/drawable/custom_progressbar.xml
Normal file
17
app/src/main/res/drawable/custom_progressbar.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@android:id/background">
|
||||
<shape>
|
||||
<corners android:radius="4dp" />
|
||||
<solid android:color="#E5E7EB" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:id="@android:id/progress">
|
||||
<clip>
|
||||
<shape>
|
||||
<corners android:radius="4dp" />
|
||||
<solid android:color="#2563EB" />
|
||||
</shape>
|
||||
</clip>
|
||||
</item>
|
||||
</layer-list>
|
||||
9
app/src/main/res/drawable/ic_arrow_down.xml
Normal file
9
app/src/main/res/drawable/ic_arrow_down.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#1F2937"
|
||||
android:pathData="M7,10l5,5l5,-5z" />
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_calendar.xml
Normal file
10
app/src/main/res/drawable/ic_calendar.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0"
|
||||
android:tint="#8E8E8E">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M19,3h-1V1h-2v2H8V1H6v2H5C3.9,3 3,3.9 3,5v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5C21,3.9 20.1,3 19,3zM19,19H5V8h14V19z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_delete.xml
Normal file
10
app/src/main/res/drawable/ic_delete.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0"
|
||||
android:tint="#FF0000">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
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,1H5v2h14V4z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_goal.xml
Normal file
10
app/src/main/res/drawable/ic_goal.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0"
|
||||
android:tint="#1D4ED8">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM12,6c-3.31,0 -6,2.69 -6,6s2.69,6 6,6 6,-2.69 6,-6 -2.69,-6 -6,-6zM12,16c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_trend_up.xml
Normal file
10
app/src/main/res/drawable/ic_trend_up.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0"
|
||||
android:tint="#FFFFFF">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M16,6l2.29,2.29 -4.88,4.88 -4,-4L2,16.59 3.41,18l6,-6 4,4 6.3,-6.29L22,12V6z"/>
|
||||
</vector>
|
||||
11
app/src/main/res/drawable/spinner_border_bg.xml
Normal file
11
app/src/main/res/drawable/spinner_border_bg.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#FFFFFF" />
|
||||
<corners android:radius="12dp" />
|
||||
<stroke android:width="1dp" android:color="#E0E0E0" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:gravity="end|center_vertical" android:right="12dp" android:drawable="@drawable/ic_arrow_down" />
|
||||
</layer-list>
|
||||
@@ -32,7 +32,7 @@
|
||||
android:padding="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView11">
|
||||
app:layout_constraintTop_toBottomOf="@+id/llFiltros">
|
||||
|
||||
<!-- TRANSAÇÕES -->
|
||||
|
||||
@@ -119,6 +119,40 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView10" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llFiltros"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView11">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerMes"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/spinner_border_bg"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="36dp"
|
||||
android:spinnerMode="dropdown" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerAno"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:background="@drawable/spinner_border_bg"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="36dp"
|
||||
android:spinnerMode="dropdown" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/despesasCardView"
|
||||
android:layout_width="379dp"
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView12" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvMetas"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="211dp"
|
||||
android:layout_marginStart="16dp"
|
||||
|
||||
157
app/src/main/res/layout/item_meta.xml
Normal file
157
app/src/main/res/layout/item_meta.xml
Normal file
@@ -0,0 +1,157 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView 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="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="0dp"
|
||||
app:cardBackgroundColor="#FFFFFF">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:background="@drawable/spinner_border_bg">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivIcon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/ic_goal"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvNome"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="Férias"
|
||||
android:textColor="#000000"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/ivIcon"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivIcon"
|
||||
app:layout_constraintTop_toTopOf="@+id/ivIcon" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivDelete"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/ic_delete"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/ivIcon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/ivIcon" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvCategoria"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="Viagem"
|
||||
android:textColor="#4B5563"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintStart_toStartOf="@+id/tvNome"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvNome" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLabelProgresso"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Progresso"
|
||||
android:textColor="#374151"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintStart_toStartOf="@+id/tvCategoria"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvCategoria" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvValorStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="0.00€ / 1500.00€"
|
||||
android:textColor="#000000"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/tvLabelProgresso"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/tvLabelProgresso" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pbProgresso"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:progressDrawable="@drawable/custom_progressbar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/tvLabelProgresso"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvLabelProgresso" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivCalendar"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:src="@drawable/ic_calendar"
|
||||
app:layout_constraintStart_toStartOf="@+id/pbProgresso"
|
||||
app:layout_constraintTop_toBottomOf="@+id/pbProgresso" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDiasRestantes"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:text="Faltam 0 dias"
|
||||
android:textColor="#4B5563"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/ivCalendar"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivCalendar"
|
||||
app:layout_constraintTop_toTopOf="@+id/ivCalendar" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPercentagem"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="0.0%"
|
||||
android:textColor="#2563EB"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/tvDiasRestantes"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/tvDiasRestantes" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etAdicionarValor"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="45dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/spinner_border_bg"
|
||||
android:hint="Adicionar valor..."
|
||||
android:inputType="numberDecimal"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/btnAddValor"
|
||||
app:layout_constraintStart_toStartOf="@+id/tvDiasRestantes"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvDiasRestantes" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnAddValor"
|
||||
android:layout_width="45dp"
|
||||
android:layout_height="45dp"
|
||||
app:icon="@drawable/ic_trend_up"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="0dp"
|
||||
app:iconTint="#FFFFFF"
|
||||
android:insetTop="0dp"
|
||||
android:insetBottom="0dp"
|
||||
app:backgroundTint="#0B0F19"
|
||||
app:cornerRadius="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/etAdicionarValor"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/etAdicionarValor" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
107
app/src/main/res/layout/item_transacao.xml
Normal file
107
app/src/main/res/layout/item_transacao.xml
Normal file
@@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView 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="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="0dp"
|
||||
app:cardBackgroundColor="#FFFFFF">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:background="@drawable/spinner_border_bg">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivIconBackground"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/bg_circle_green"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@drawable/diagonalarrowrightup_110941"
|
||||
app:tint="#2ECC71"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/ivIconBackground"
|
||||
app:layout_constraintEnd_toEndOf="@+id/ivIconBackground"
|
||||
app:layout_constraintStart_toStartOf="@+id/ivIconBackground"
|
||||
app:layout_constraintTop_toTopOf="@+id/ivIconBackground" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDescricao"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="dinheiro"
|
||||
android:textColor="#000000"
|
||||
android:textSize="18sp"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivIconBackground"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvCategoria"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:background="@drawable/bg_badge_category"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:paddingVertical="4dp"
|
||||
android:text="Outros"
|
||||
android:textColor="#000000"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/tvDescricao"
|
||||
app:layout_constraintStart_toEndOf="@+id/tvDescricao"
|
||||
app:layout_constraintTop_toTopOf="@+id/tvDescricao" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivCalendar"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:src="@drawable/ic_calendar"
|
||||
app:layout_constraintStart_toStartOf="@+id/tvDescricao"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvDescricao" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvData"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:text="23/04/2026"
|
||||
android:textColor="#6B7280"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/ivCalendar"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivCalendar"
|
||||
app:layout_constraintTop_toTopOf="@+id/ivCalendar" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivDelete"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/ic_delete"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvValor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="+25.00€"
|
||||
android:textColor="#2ECC71"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/ivDelete"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
Reference in New Issue
Block a user