package com.example.lifegrid.menu; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; import com.example.lifegrid.utils.CustomToast; import com.example.lifegrid.R; import com.example.lifegrid.models.Transacao; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; import com.github.mikephil.charting.formatter.IndexAxisValueFormatter; import com.github.mikephil.charting.utils.ColorTemplate; 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 java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.graphics.Color; import com.example.lifegrid.TelaInicialActivity; /** * GraficosFragment tem como único propósito compilar a informação da aplicação sob uma * componente puramente matemática exibida de forma ilustrativa. Trata da visão de Dashboard de estatística. */ public class GraficosFragment extends Fragment { private PieChart pieChartMensal; private BarChart barChartAnual; private TextView tvTituloMensal; private TextView tvTituloAnual; private List allTransacoesList = new ArrayList<>(); private int currentMes = -1; private String currentAno = ""; private String currentMesNome = ""; public GraficosFragment() { // Construtor público vazio obrigatório } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public void onResume() { super.onResume(); if (getActivity() instanceof TelaInicialActivity) { ((TelaInicialActivity) getActivity()).atualizarDadosHome(); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflaciona o layout para este fragmento View root = inflater.inflate(R.layout.fragment_graficos, container, false); pieChartMensal = root.findViewById(R.id.pieChartMensal); barChartAnual = root.findViewById(R.id.barChartAnual); tvTituloMensal = root.findViewById(R.id.tvTituloMensal); tvTituloAnual = root.findViewById(R.id.tvTituloAnual); configurarGraficos(); carregarTransacoes(); return root; } private void configurarGraficos() { // Config PieChart pieChartMensal.getDescription().setEnabled(false); pieChartMensal.setUsePercentValues(true); pieChartMensal.setEntryLabelColor(Color.BLACK); pieChartMensal.setEntryLabelTextSize(12f); pieChartMensal.setCenterText("Despesas"); pieChartMensal.setCenterTextSize(18f); // Config BarChart barChartAnual.getDescription().setEnabled(false); barChartAnual.setDrawGridBackground(false); barChartAnual.getAxisRight().setEnabled(false); XAxis xAxis = barChartAnual.getXAxis(); xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); xAxis.setGranularity(1f); xAxis.setCenterAxisLabels(true); String[] mesesLabel = new String[]{"Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"}; xAxis.setValueFormatter(new IndexAxisValueFormatter(mesesLabel)); } private void carregarTransacoes() { FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser(); if (currentUser == null) return; String userId = currentUser.getUid(); DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference(); databaseReference.child("users").child(userId).child("transacoes").addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { allTransacoesList.clear(); for (DataSnapshot ds : snapshot.getChildren()) { Transacao t = ds.getValue(Transacao.class); if (t != null) { t.setId(ds.getKey()); allTransacoesList.add(t); } } atualizarGraficos(); } @Override public void onCancelled(@NonNull DatabaseError error) { CustomToast.error(requireContext(), "Erro ao carregar transações."); } }); } public void setFiltro(int mesSelecionado, String anoSelecionado, String mesNome) { this.currentMes = mesSelecionado; this.currentAno = anoSelecionado; this.currentMesNome = mesNome; if (tvTituloMensal != null) { tvTituloMensal.setText("Resumo de " + mesNome + " " + anoSelecionado); } if (tvTituloAnual != null) { tvTituloAnual.setText("Balanço Anual - " + anoSelecionado); } atualizarGraficos(); } private void atualizarGraficos() { if (currentMes == -1 || currentAno.isEmpty()) return; atualizarPieChart(); atualizarBarChart(); } private void atualizarPieChart() { Map categoriasMap = new HashMap<>(); for (Transacao t : allTransacoesList) { if (t.getData() != null && t.getTipo() != null && t.getTipo().equalsIgnoreCase("Despesa")) { String[] parts = t.getData().split("/"); if (parts.length == 3) { try { int mesTransacao = Integer.parseInt(parts[1]); String anoTransacao = parts[2]; if (mesTransacao == currentMes && anoTransacao.equals(currentAno)) { float valor = Float.parseFloat(t.getValor()); String cat = t.getCategoria(); categoriasMap.put(cat, categoriasMap.getOrDefault(cat, 0f) + valor); } } catch (NumberFormatException e) { e.printStackTrace(); } } } } List entries = new ArrayList<>(); for (Map.Entry entry : categoriasMap.entrySet()) { if (entry.getValue() > 0) { entries.add(new PieEntry(entry.getValue(), entry.getKey())); } } PieDataSet dataSet = new PieDataSet(entries, ""); dataSet.setColors(ColorTemplate.MATERIAL_COLORS); dataSet.setSliceSpace(3f); dataSet.setValueTextSize(14f); dataSet.setValueTextColor(Color.WHITE); PieData data = new PieData(dataSet); pieChartMensal.setData(data); pieChartMensal.invalidate(); // refresh } private void atualizarBarChart() { float[] receitasPorMes = new float[12]; float[] despesasPorMes = new float[12]; for (Transacao t : allTransacoesList) { if (t.getData() != null) { String[] parts = t.getData().split("/"); if (parts.length == 3) { try { int mesTransacao = Integer.parseInt(parts[1]) - 1; // 0 a 11 String anoTransacao = parts[2]; if (anoTransacao.equals(currentAno) && mesTransacao >= 0 && mesTransacao < 12) { float valor = Float.parseFloat(t.getValor()); if (t.getTipo() != null && t.getTipo().equalsIgnoreCase("Receita")) { receitasPorMes[mesTransacao] += valor; } else { despesasPorMes[mesTransacao] += valor; } } } catch (NumberFormatException e) { e.printStackTrace(); } } } } List entriesReceitas = new ArrayList<>(); List entriesDespesas = new ArrayList<>(); for (int i = 0; i < 12; i++) { entriesReceitas.add(new BarEntry(i, receitasPorMes[i])); entriesDespesas.add(new BarEntry(i, despesasPorMes[i])); } BarDataSet setReceitas = new BarDataSet(entriesReceitas, "Receitas"); setReceitas.setColor(Color.parseColor("#2ECC71")); setReceitas.setValueTextSize(10f); BarDataSet setDespesas = new BarDataSet(entriesDespesas, "Despesas"); setDespesas.setColor(Color.parseColor("#E74C3C")); setDespesas.setValueTextSize(10f); BarData data = new BarData(setReceitas, setDespesas); // agrupar barras float groupSpace = 0.4f; float barSpace = 0.05f; float barWidth = 0.25f; data.setBarWidth(barWidth); barChartAnual.setData(data); barChartAnual.groupBars(0f, groupSpace, barSpace); barChartAnual.getXAxis().setAxisMinimum(0f); barChartAnual.getXAxis().setAxisMaximum(0f + barChartAnual.getBarData().getGroupWidth(groupSpace, barSpace) * 12); barChartAnual.invalidate(); // refresh } }