faturas
This commit is contained in:
@@ -48,6 +48,7 @@ dependencies {
|
||||
implementation(libs.credentials.play.services.auth)
|
||||
implementation(libs.googleid)
|
||||
implementation(libs.firebase.database)
|
||||
implementation("com.google.firebase:firebase-storage:21.0.0")
|
||||
implementation(libs.recyclerview)
|
||||
implementation(libs.cardview)
|
||||
implementation(libs.lifecycle.runtime.ktx)
|
||||
@@ -58,8 +59,8 @@ dependencies {
|
||||
implementation(libs.ui.tooling.preview)
|
||||
implementation(libs.material3)
|
||||
implementation(libs.material3.adaptive.navigation.suite)
|
||||
implementation("com.google.ai.client.generativeai:generativeai:0.7.0")
|
||||
implementation("com.google.guava:guava:31.1-android")
|
||||
implementation("com.google.ai.client.generativeai:generativeai:0.9.0")
|
||||
implementation("com.google.guava:guava:33.0.0-android")
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.ext.junit)
|
||||
androidTestImplementation(libs.espresso.core)
|
||||
|
||||
@@ -4,19 +4,40 @@ import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.example.lifegrid.adapters.DocumentoAdapter;
|
||||
import com.example.lifegrid.models.Documento;
|
||||
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.List;
|
||||
|
||||
public class DocumentosActivity extends AppCompatActivity {
|
||||
|
||||
private ImageView btnBack;
|
||||
private LinearLayout llDocumentsList;
|
||||
private RecyclerView rvDocumentos;
|
||||
private DocumentoAdapter adapter;
|
||||
private List<Documento> documentoList;
|
||||
private TextView tvEmptyState1, tvEmptyState2;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -30,62 +51,55 @@ public class DocumentosActivity extends AppCompatActivity {
|
||||
});
|
||||
|
||||
btnBack = findViewById(R.id.btnBack);
|
||||
llDocumentsList = findViewById(R.id.llDocumentsList);
|
||||
|
||||
btnBack.setOnClickListener(v -> finish());
|
||||
|
||||
loadDocuments();
|
||||
rvDocumentos = findViewById(R.id.rvDocumentos);
|
||||
tvEmptyState1 = findViewById(R.id.tvEmptyState1);
|
||||
tvEmptyState2 = findViewById(R.id.tvEmptyState2);
|
||||
|
||||
rvDocumentos.setLayoutManager(new LinearLayoutManager(this));
|
||||
documentoList = new ArrayList<>();
|
||||
adapter = new DocumentoAdapter(documentoList, this);
|
||||
rvDocumentos.setAdapter(adapter);
|
||||
|
||||
carregarDocumentos();
|
||||
}
|
||||
|
||||
private void loadDocuments() {
|
||||
SharedPreferences prefs = getSharedPreferences("LifeGridDocs", Context.MODE_PRIVATE);
|
||||
int count = prefs.getInt("doc_count", 0);
|
||||
private void carregarDocumentos() {
|
||||
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||
if (user == null) return;
|
||||
|
||||
if (count == 0) {
|
||||
TextView emptyText = new TextView(this);
|
||||
emptyText.setText("Nenhum documento guardado.");
|
||||
emptyText.setPadding(32, 32, 32, 32);
|
||||
llDocumentsList.addView(emptyText);
|
||||
return;
|
||||
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("users")
|
||||
.child(user.getUid()).child("documentos");
|
||||
|
||||
ref.addValueEventListener(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
documentoList.clear();
|
||||
for (DataSnapshot ds : snapshot.getChildren()) {
|
||||
Documento doc = ds.getValue(Documento.class);
|
||||
if (doc != null) {
|
||||
doc.setId(ds.getKey());
|
||||
documentoList.add(doc);
|
||||
}
|
||||
}
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
if (documentoList.isEmpty()) {
|
||||
tvEmptyState1.setVisibility(View.VISIBLE);
|
||||
tvEmptyState2.setVisibility(View.VISIBLE);
|
||||
rvDocumentos.setVisibility(View.GONE);
|
||||
} else {
|
||||
tvEmptyState1.setVisibility(View.GONE);
|
||||
tvEmptyState2.setVisibility(View.GONE);
|
||||
rvDocumentos.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
String uriString = prefs.getString("doc_uri_" + i, "");
|
||||
String desc = prefs.getString("doc_desc_" + i, "Sem descrição");
|
||||
String data = prefs.getString("doc_data_" + i, "Sem data");
|
||||
|
||||
LinearLayout itemLayout = new LinearLayout(this);
|
||||
itemLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||
itemLayout.setPadding(16, 16, 16, 16);
|
||||
|
||||
ImageView ivDoc = new ImageView(this);
|
||||
ivDoc.setLayoutParams(new LinearLayout.LayoutParams(200, 200));
|
||||
ivDoc.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
try {
|
||||
ivDoc.setImageURI(Uri.parse(uriString));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
LinearLayout textLayout = new LinearLayout(this);
|
||||
textLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
textLayout.setPadding(16, 0, 0, 0);
|
||||
|
||||
TextView tvDesc = new TextView(this);
|
||||
tvDesc.setText(desc);
|
||||
tvDesc.setTextSize(16);
|
||||
tvDesc.setTypeface(null, android.graphics.Typeface.BOLD);
|
||||
|
||||
TextView tvData = new TextView(this);
|
||||
tvData.setText(data);
|
||||
|
||||
textLayout.addView(tvDesc);
|
||||
textLayout.addView(tvData);
|
||||
|
||||
itemLayout.addView(ivDoc);
|
||||
itemLayout.addView(textLayout);
|
||||
|
||||
llDocumentsList.addView(itemLayout);
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
Toast.makeText(DocumentosActivity.this, "Erro ao carregar documentos.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public class InvoiceScannerHelper {
|
||||
}
|
||||
|
||||
public static void scanInvoice(Context context, Uri imageUri, ScanCallback callback) {
|
||||
if (API_KEY == null || API_KEY.isEmpty() || API_KEY.contains("AIzaSyCoUZSXfEk43LfPtkCCjsnQ_ZMWX7NG1xQ")) {
|
||||
if (API_KEY == null || API_KEY.isEmpty() || API_KEY.contains("CHAVE_API_KEY")) {
|
||||
callback.onError("Chave API do Gemini não configurada.");
|
||||
return;
|
||||
}
|
||||
@@ -47,7 +47,7 @@ public class InvoiceScannerHelper {
|
||||
}
|
||||
|
||||
GenerativeModel gm = new GenerativeModel(
|
||||
"gemini-1.5-flash",
|
||||
"gemini-2.5-flash",
|
||||
API_KEY
|
||||
);
|
||||
GenerativeModelFutures model = GenerativeModelFutures.from(gm);
|
||||
|
||||
@@ -16,13 +16,10 @@ import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.example.lifegrid.menu.AtivosFragment;
|
||||
import com.example.lifegrid.menu.DefinicoesFragment;
|
||||
import com.example.lifegrid.menu.DocumentosFragment;
|
||||
import com.example.lifegrid.menu.GraficosFragment;
|
||||
import com.example.lifegrid.menu.HomeFragment;
|
||||
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;
|
||||
@@ -30,17 +27,12 @@ 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.
|
||||
@@ -182,8 +174,8 @@ public class TelaInicialActivity extends AppCompatActivity {
|
||||
}
|
||||
transFragment.showNovaTransacaoDialog(valor, descricao, categoria, data);
|
||||
|
||||
// Save document to shared preferences or database
|
||||
saveDocument(imageUri.toString(), descricao, data);
|
||||
// Save document to Firebase
|
||||
uploadDocumentoToFirebase(imageUri, descricao, data);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -194,15 +186,37 @@ public class TelaInicialActivity extends AppCompatActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private void saveDocument(String uriString, String descricao, String data) {
|
||||
SharedPreferences prefs = getSharedPreferences("LifeGridDocs", Context.MODE_PRIVATE);
|
||||
int count = prefs.getInt("doc_count", 0);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putString("doc_uri_" + count, uriString);
|
||||
editor.putString("doc_desc_" + count, descricao);
|
||||
editor.putString("doc_data_" + count, data);
|
||||
editor.putInt("doc_count", count + 1);
|
||||
editor.apply();
|
||||
private void uploadDocumentoToFirebase(android.net.Uri imageUri, String descricao, String data) {
|
||||
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||
if (user == null) {
|
||||
Toast.makeText(this, "Utilizador não autenticado.", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
Toast.makeText(this, "A guardar documento na Cloud...", Toast.LENGTH_SHORT).show();
|
||||
|
||||
String fileName = "invoice_" + System.currentTimeMillis() + ".jpg";
|
||||
com.google.firebase.storage.StorageReference storageRef = com.google.firebase.storage.FirebaseStorage.getInstance().getReference()
|
||||
.child("users/" + user.getUid() + "/documentos/" + fileName);
|
||||
|
||||
storageRef.putFile(imageUri).addOnSuccessListener(taskSnapshot -> {
|
||||
storageRef.getDownloadUrl().addOnSuccessListener(uri -> {
|
||||
String downloadUrl = uri.toString();
|
||||
DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference("users")
|
||||
.child(user.getUid()).child("documentos").push();
|
||||
|
||||
com.example.lifegrid.models.Documento doc = new com.example.lifegrid.models.Documento(descricao, data, downloadUrl);
|
||||
dbRef.setValue(doc).addOnCompleteListener(task -> {
|
||||
if (task.isSuccessful()) {
|
||||
Toast.makeText(TelaInicialActivity.this, "Documento guardado com sucesso!", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(TelaInicialActivity.this, "Erro ao guardar dados na Cloud.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
});
|
||||
}).addOnFailureListener(e -> {
|
||||
Toast.makeText(this, "Erro ao enviar imagem para a Cloud.", Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -276,11 +290,14 @@ public class TelaInicialActivity extends AppCompatActivity {
|
||||
|
||||
public void atualizarDadosHome() {
|
||||
Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
|
||||
if (currentFragment instanceof HomeFragment) {
|
||||
int mesSelecionado = spinnerMes.getSelectedItemPosition() + 1; // 1 to 12
|
||||
String anoSelecionado = spinnerAno.getSelectedItem().toString();
|
||||
|
||||
if (currentFragment instanceof HomeFragment) {
|
||||
String mesNome = meses[spinnerMes.getSelectedItemPosition()];
|
||||
((HomeFragment) currentFragment).carregarDados(mesSelecionado, anoSelecionado, mesNome);
|
||||
} else if (currentFragment instanceof TransacoesFragment) {
|
||||
((TransacoesFragment) currentFragment).setFiltro(mesSelecionado, anoSelecionado);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.example.lifegrid.adapters;
|
||||
|
||||
import android.app.DownloadManager;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
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.Documento;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DocumentoAdapter extends RecyclerView.Adapter<DocumentoAdapter.DocumentoViewHolder> {
|
||||
|
||||
private List<Documento> documentos;
|
||||
private Context context;
|
||||
|
||||
public DocumentoAdapter(List<Documento> documentos, Context context) {
|
||||
this.documentos = documentos;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public DocumentoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_documento, parent, false);
|
||||
return new DocumentoViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull DocumentoViewHolder holder, int position) {
|
||||
Documento documento = documentos.get(position);
|
||||
holder.tvDescricao.setText(documento.getDescricao() != null && !documento.getDescricao().isEmpty() ? documento.getDescricao() : "Fatura");
|
||||
holder.tvData.setText(documento.getData());
|
||||
|
||||
holder.btnDownload.setOnClickListener(v -> {
|
||||
String url = documento.getUrlImagem();
|
||||
if (url != null && !url.isEmpty()) {
|
||||
downloadFile(url, holder.tvDescricao.getText().toString());
|
||||
} else {
|
||||
Toast.makeText(context, "URL inválido para o documento.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return documentos != null ? documentos.size() : 0;
|
||||
}
|
||||
|
||||
private void downloadFile(String url, String descricao) {
|
||||
try {
|
||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
|
||||
String fileName = "Fatura_" + System.currentTimeMillis() + ".jpg";
|
||||
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
|
||||
request.setTitle("Descarregar Fatura");
|
||||
request.setDescription("A transferir " + descricao);
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
|
||||
|
||||
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
if (manager != null) {
|
||||
manager.enqueue(request);
|
||||
Toast.makeText(context, "Transferência iniciada. Verifique as notificações.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(context, "Erro ao iniciar transferência.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
public static class DocumentoViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView tvDescricao, tvData;
|
||||
ImageButton btnDownload;
|
||||
|
||||
public DocumentoViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
tvDescricao = itemView.findViewById(R.id.tvDescricao);
|
||||
tvData = itemView.findViewById(R.id.tvData);
|
||||
btnDownload = itemView.findViewById(R.id.btnDownload);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.example.lifegrid.menu;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.example.lifegrid.R;
|
||||
|
||||
/**
|
||||
* DocumentosFragment é a área orientada ao scan, compilação de faturas e arquivo seguro.
|
||||
* Foca-se unicamente nas componentes não contabéis mas sim em anotações em anexo faturado.
|
||||
*/
|
||||
public class DocumentosFragment extends Fragment {
|
||||
|
||||
public DocumentosFragment() {
|
||||
// Construtor público vazio obrigatório
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflaciona o layout para este fragmento
|
||||
View root = inflater.inflate(R.layout.fragment_documentos, container, false);
|
||||
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
@@ -50,9 +50,12 @@ public class TransacoesFragment extends Fragment {
|
||||
private RecyclerView rvTransacoes;
|
||||
private TransacaoAdapter transacaoAdapter;
|
||||
private List<Transacao> transacoesList;
|
||||
private List<Transacao> allTransacoesList;
|
||||
private TextView tvEmptyState;
|
||||
private DatabaseReference databaseReference;
|
||||
private String userId;
|
||||
private int currentMes = -1;
|
||||
private String currentAno = "";
|
||||
|
||||
public TransacoesFragment() {
|
||||
// Construtor público vazio obrigatório
|
||||
@@ -65,6 +68,14 @@ public class TransacoesFragment extends Fragment {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (getActivity() instanceof com.example.lifegrid.TelaInicialActivity) {
|
||||
((com.example.lifegrid.TelaInicialActivity) getActivity()).atualizarDadosHome();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
@@ -88,6 +99,7 @@ public class TransacoesFragment extends Fragment {
|
||||
|
||||
rvTransacoes.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
transacoesList = new ArrayList<>();
|
||||
allTransacoesList = new ArrayList<>();
|
||||
|
||||
transacaoAdapter = new TransacaoAdapter(transacoesList, transacao -> {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
@@ -119,14 +131,62 @@ public class TransacoesFragment extends Fragment {
|
||||
databaseReference.child("users").child(userId).child("transacoes").addValueEventListener(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
transacoesList.clear();
|
||||
allTransacoesList.clear();
|
||||
for (DataSnapshot ds : snapshot.getChildren()) {
|
||||
Transacao t = ds.getValue(Transacao.class);
|
||||
if (t != null) {
|
||||
t.setId(ds.getKey());
|
||||
allTransacoesList.add(t);
|
||||
}
|
||||
}
|
||||
aplicarFiltro();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
Toast.makeText(requireContext(), "Erro ao carregar transações.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void aplicarFiltro() {
|
||||
transacoesList.clear();
|
||||
for (Transacao t : allTransacoesList) {
|
||||
if (currentMes != -1 && !currentAno.isEmpty() && t.getData() != null) {
|
||||
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)) {
|
||||
transacoesList.add(t);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
transacoesList.add(t);
|
||||
}
|
||||
}
|
||||
|
||||
java.util.Collections.sort(transacoesList, new java.util.Comparator<Transacao>() {
|
||||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd/MM/yyyy", java.util.Locale.getDefault());
|
||||
@Override
|
||||
public int compare(Transacao t1, Transacao t2) {
|
||||
try {
|
||||
java.util.Date d1 = sdf.parse(t1.getData());
|
||||
java.util.Date d2 = sdf.parse(t2.getData());
|
||||
if (d1 != null && d2 != null) {
|
||||
return d2.compareTo(d1); // Ordem decrescente (mais recentes no topo)
|
||||
}
|
||||
} catch (java.text.ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
transacaoAdapter.notifyDataSetChanged();
|
||||
|
||||
if (transacoesList.isEmpty()) {
|
||||
@@ -138,11 +198,10 @@ public class TransacoesFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
Toast.makeText(requireContext(), "Erro ao carregar transações.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
public void setFiltro(int mesSelecionado, String anoSelecionado) {
|
||||
this.currentMes = mesSelecionado;
|
||||
this.currentAno = anoSelecionado;
|
||||
aplicarFiltro();
|
||||
}
|
||||
|
||||
public void showNovaTransacaoDialog() {
|
||||
|
||||
53
app/src/main/java/com/example/lifegrid/models/Documento.java
Normal file
53
app/src/main/java/com/example/lifegrid/models/Documento.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package com.example.lifegrid.models;
|
||||
|
||||
import com.google.firebase.database.Exclude;
|
||||
|
||||
public class Documento {
|
||||
private String id;
|
||||
private String descricao;
|
||||
private String data;
|
||||
private String urlImagem;
|
||||
|
||||
public Documento() {
|
||||
}
|
||||
|
||||
public Documento(String descricao, String data, String urlImagem) {
|
||||
this.descricao = descricao;
|
||||
this.data = data;
|
||||
this.urlImagem = urlImagem;
|
||||
}
|
||||
|
||||
@Exclude
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Exclude
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDescricao() {
|
||||
return descricao;
|
||||
}
|
||||
|
||||
public void setDescricao(String descricao) {
|
||||
this.descricao = descricao;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public String getUrlImagem() {
|
||||
return urlImagem;
|
||||
}
|
||||
|
||||
public void setUrlImagem(String urlImagem) {
|
||||
this.urlImagem = urlImagem;
|
||||
}
|
||||
}
|
||||
@@ -41,18 +41,44 @@
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<ScrollView
|
||||
<TextView
|
||||
android:id="@+id/tvEmptyState1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Nenhum documento encontrado"
|
||||
android:textAlignment="center"
|
||||
android:textColor="#898585"
|
||||
android:textSize="18sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/tvEmptyState2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/headerLayout"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvEmptyState2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Adicione documentos das suas transações"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/cinzaescuro"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvEmptyState1" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvDocumentos"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/headerLayout">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llDocumentsList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp" />
|
||||
</ScrollView>
|
||||
app:layout_constraintTop_toBottomOf="@id/headerLayout" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".menu.DocumentosFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/transacoes2CardView"
|
||||
android:layout_width="379dp"
|
||||
android:layout_height="544dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/cardview_background"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView12"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="28dp"
|
||||
android:text="Documentos"
|
||||
android:textSize="17sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.111"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView13"
|
||||
android:layout_width="302dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginTop="216dp"
|
||||
android:text="Nenhum documento encontrado"
|
||||
android:textAlignment="center"
|
||||
android:textColor="#898585"
|
||||
android:textSize="18sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.493"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView12" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView23"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Adicione documentos das suas transações"
|
||||
android:textColor="@color/cinzaescuro"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.493"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView13" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:layout_width="348dp"
|
||||
android:layout_height="382dp"
|
||||
android:layout_marginTop="40dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.516"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView12" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
||||
69
app/src/main/res/layout/item_documento.xml
Normal file
69
app/src/main/res/layout/item_documento.xml
Normal file
@@ -0,0 +1,69 @@
|
||||
<?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_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="8dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/branco"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivIcon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/documento"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/btnDownload"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivIcon"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDescricao"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Fatura de Exemplo"
|
||||
android:textColor="@color/preto"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvData"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="12/04/2026"
|
||||
android:textColor="#898585"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnDownload"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_arrow_down"
|
||||
app:tint="@color/preto"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
Reference in New Issue
Block a user