diff --git a/src/components/credito/DespesasList.tsx b/src/components/credito/DespesasList.tsx
index 56c20d1..e755abd 100644
--- a/src/components/credito/DespesasList.tsx
+++ b/src/components/credito/DespesasList.tsx
@@ -12,6 +12,15 @@ import {
} from "@/components/ui/table";
import { formatDistanceToNow } from 'date-fns';
import { ptBR } from 'date-fns/locale';
+import {
+ Pagination,
+ PaginationContent,
+ PaginationEllipsis,
+ PaginationItem,
+ PaginationLink,
+ PaginationNext,
+ PaginationPrevious,
+} from "@/components/ui/pagination";
interface DespesasListProps {
despesas: DespesaCartao[];
@@ -20,7 +29,9 @@ interface DespesasListProps {
export function DespesasList({ despesas, isLoading }: DespesasListProps) {
const { toast } = useToast();
-
+ const [currentPage, setCurrentPage] = useState(1);
+ const itemsPerPage = 5; // Number of expenses to display per page
+
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('pt-BR', {
style: 'currency',
@@ -52,30 +63,118 @@ export function DespesasList({ despesas, isLoading }: DespesasListProps) {
;
}
+ // Calculate pagination values
+ const totalPages = Math.ceil(despesas.length / itemsPerPage);
+ const indexOfLastItem = currentPage * itemsPerPage;
+ const indexOfFirstItem = indexOfLastItem - itemsPerPage;
+ const currentItems = despesas.slice(indexOfFirstItem, indexOfLastItem);
+
+ // Generate page numbers for pagination
+ const pageNumbers = [];
+ for (let i = 1; i <= totalPages; i++) {
+ pageNumbers.push(i);
+ }
+
+ // Go to a specific page
+ const paginate = (pageNumber: number) => setCurrentPage(pageNumber);
+
+ // Go to previous page
+ const goToPreviousPage = () => {
+ if (currentPage > 1) {
+ setCurrentPage(currentPage - 1);
+ }
+ };
+
+ // Go to next page
+ const goToNextPage = () => {
+ if (currentPage < totalPages) {
+ setCurrentPage(currentPage + 1);
+ }
+ };
+
+ // Determine which page numbers to show
+ const getPageNumbers = () => {
+ const maxPagesToShow = 5;
+ let startPage = Math.max(1, currentPage - 2);
+ let endPage = Math.min(totalPages, startPage + maxPagesToShow - 1);
+
+ // Adjust if at the end of the range
+ if (endPage - startPage + 1 < maxPagesToShow && startPage > 1) {
+ startPage = Math.max(1, endPage - maxPagesToShow + 1);
+ }
+
+ return Array.from({ length: endPage - startPage + 1 }, (_, i) => startPage + i);
+ };
+
return (
-
-
-
-
- Data
- Descrição
- Valor
-
-
-
- {despesas.map((despesa) => (
-
-
- {formatDate(despesa.data_despesa)}
-
- {despesa.descricao}
-
- {formatCurrency(despesa.valor)}
-
+
+
+
+
+
+ Data
+ Descrição
+ Valor
- ))}
-
-
+
+
+ {currentItems.map((despesa) => (
+
+
+ {formatDate(despesa.data_despesa)}
+
+ {despesa.descricao}
+
+ {formatCurrency(despesa.valor)}
+
+
+ ))}
+
+
+
+
+ {totalPages > 1 && (
+
+
+
+
+
+
+ {getPageNumbers().map((number) => (
+
+ {
+ e.preventDefault();
+ paginate(number);
+ }}
+ >
+ {number}
+
+
+ ))}
+
+ {totalPages > 5 && currentPage < totalPages - 2 && (
+
+
+
+ )}
+
+
+
+
+
+
+ )}
);
}
diff --git a/src/services/cartao/cartoesService.ts b/src/services/cartao/cartoesService.ts
index 05fd95c..7ba0479 100644
--- a/src/services/cartao/cartoesService.ts
+++ b/src/services/cartao/cartoesService.ts
@@ -1,3 +1,4 @@
+
import { supabase } from "@/integrations/supabase/client";
import { CartaoCredito } from "@/types/cartaoTypes";
import { gerarCartaoCodigo } from "./cartaoCodigoUtils";
@@ -23,34 +24,27 @@ export async function getCartoes(): Promise {
const { data, error } = await supabase
.from('cartoes_credito')
.select('*')
- .eq('login', normalizedEmail);
+ .eq('login', normalizedEmail)
+ .order('nome', { ascending: true });
if (error) {
console.error('Erro ao buscar cartões:', error);
throw new Error('Não foi possível carregar os cartões de crédito');
}
- // Garantir que todos os dados têm os campos necessários da interface CartaoCredito
- const cartoesCompletos = data.map(cartao => {
- const cartaoCompleto = {
+ // Para cada cartão, obter o total de despesas
+ const cartoesComDespesas = await Promise.all(data.map(async (cartao) => {
+ const totalDespesas = await getTotalDespesasCartao(cartao.cartao_codigo || '');
+ return {
...cartao,
- bandeira: cartao.bandeira || 'Não especificada',
- banco: cartao.banco || 'Não especificado',
- cartao_codigo: cartao.cartao_codigo || `cartao_${cartao.id.substring(0, 8)}`
+ bandeira: cartao.bandeira || '',
+ banco: cartao.banco || '',
+ cartao_codigo: cartao.cartao_codigo || '',
+ total_despesas: totalDespesas
} as CartaoCredito;
-
- return cartaoCompleto;
- });
+ }));
- // Buscar o total de despesas para cada cartão - Promise.all já tipa corretamente o retorno
- const cartoesComTotal = await Promise.all(
- cartoesCompletos.map(async (cartao) => {
- const total = await getTotalDespesasCartao(cartao.cartao_codigo);
- return { ...cartao, total_despesas: total };
- })
- );
-
- return cartoesComTotal;
+ return cartoesComDespesas;
} catch (error) {
console.error('Erro ao buscar cartões:', error);
return [];
@@ -58,51 +52,59 @@ export async function getCartoes(): Promise {
}
/**
- * Checks if a card with the same name and bank already exists for the user
- * @param nome Card name
- * @param banco Bank name
- * @returns Boolean indicating if the card exists
+ * Gets a specific credit card by ID
+ * @param cartaoId Card ID
+ * @returns Card details or null if not found
*/
-export async function verificarCartaoExistente(nome: string, banco: string): Promise {
+export async function getCartao(cartaoId: string): Promise {
// Obter o email do usuário do localStorage
const userEmail = localStorage.getItem('userEmail');
if (!userEmail) {
console.error('Email do usuário não encontrado no localStorage');
- return false;
+ return null;
}
- // Normalizar o email (minúsculo e sem espaços)
- const normalizedEmail = userEmail.trim().toLowerCase();
-
try {
- const { data, error, count } = await supabase
+ const { data, error } = await supabase
.from('cartoes_credito')
- .select('*', { count: 'exact' })
- .eq('login', normalizedEmail)
- .eq('nome', nome)
- .eq('banco', banco);
+ .select('*')
+ .eq('id', cartaoId)
+ .single();
if (error) {
- console.error('Erro ao verificar cartão existente:', error);
- return false;
+ console.error('Erro ao obter cartão:', error);
+ return null;
}
- return count ? count > 0 : false;
+ // Obter o total de despesas para esse cartão
+ const totalDespesas = await getTotalDespesasCartao(data.cartao_codigo || '');
+
+ return {
+ ...data,
+ bandeira: data.bandeira || '',
+ banco: data.banco || '',
+ cartao_codigo: data.cartao_codigo || '',
+ total_despesas: totalDespesas
+ } as CartaoCredito;
} catch (error) {
- console.error('Erro ao verificar cartão existente:', error);
- return false;
+ console.error('Erro ao obter cartão:', error);
+ return null;
}
}
/**
- * Creates a new credit card
+ * Creates a new credit card for the user
* @param nome Card name
- * @param bandeira Card brand
* @param banco Bank name
- * @returns Created credit card or null if failed
+ * @param bandeira Card brand
+ * @returns Created card or null if failed
*/
-export async function criarCartao(nome: string, bandeira: string, banco: string): Promise {
+export async function criarCartao(
+ nome: string,
+ banco: string,
+ bandeira: string
+): Promise {
// Obter o email do usuário do localStorage
const userEmail = localStorage.getItem('userEmail');
// Obter o ID do usuário do localStorage (mantido por compatibilidade)
@@ -116,25 +118,19 @@ export async function criarCartao(nome: string, bandeira: string, banco: string)
// Normalizar o email (minúsculo e sem espaços)
const normalizedEmail = userEmail.trim().toLowerCase();
- // Verificar se já existe um cartão com o mesmo nome e banco
- const cartaoExistente = await verificarCartaoExistente(nome, banco);
- if (cartaoExistente) {
- throw new Error(`Você já possui um cartão ${nome} do banco ${banco}.`);
- }
-
- // Gerar um código único para o cartão
- const cartao_codigo = gerarCartaoCodigo(nome, banco);
-
try {
+ // Gerar um código único para o cartão
+ const cartao_codigo = gerarCartaoCodigo(nome, bandeira);
+
const { data, error } = await supabase
.from('cartoes_credito')
.insert([{
nome: nome,
- bandeira: bandeira,
banco: banco,
+ bandeira: bandeira,
cartao_codigo: cartao_codigo,
- user_id: userId,
- login: normalizedEmail
+ login: normalizedEmail,
+ user_id: userId
}])
.select();
@@ -143,42 +139,13 @@ export async function criarCartao(nome: string, bandeira: string, banco: string)
throw new Error('Não foi possível criar o cartão de crédito');
}
- return data[0] as CartaoCredito;
+ // Retornar o cartão criado
+ return {
+ ...data[0],
+ total_despesas: 0
+ } as CartaoCredito;
} catch (error) {
console.error('Erro ao criar cartão:', error);
- throw error;
- }
-}
-
-/**
- * Fetches details of a specific credit card
- * @param cartaoId Card ID
- * @returns Credit card or null if not found
- */
-export async function getCartao(cartaoId: string): Promise {
- try {
- const { data, error } = await supabase
- .from('cartoes_credito')
- .select('*')
- .eq('id', cartaoId)
- .single();
-
- if (error) {
- console.error('Erro ao buscar cartão:', error);
- throw new Error('Não foi possível carregar os detalhes do cartão');
- }
-
- // Garantir que o objeto retornado tem todos os campos necessários
- const cartaoCompleto = { ...data } as CartaoCredito;
-
- // Garantir que cartao_codigo existe
- if (!cartaoCompleto.cartao_codigo) {
- cartaoCompleto.cartao_codigo = `cartao_${cartaoCompleto.id.substring(0, 8)}`;
- }
-
- return cartaoCompleto;
- } catch (error) {
- console.error('Erro ao buscar cartão:', error);
return null;
}
}
diff --git a/src/services/cartao/despesasService.ts b/src/services/cartao/despesasService.ts
index 3132b8e..9f3b72e 100644
--- a/src/services/cartao/despesasService.ts
+++ b/src/services/cartao/despesasService.ts
@@ -1,3 +1,4 @@
+
import { supabase } from "@/integrations/supabase/client";
import { DespesaCartao } from "@/types/cartaoTypes";
import { getCartao } from "./cartoesService";