feat(expenses): add import functionality for expenses and total pending calculation
This commit is contained in:
@@ -7,7 +7,7 @@ import {
|
||||
} from "@tanstack/react-table";
|
||||
import type { Expense } from "@/lib/api";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { CircleDollarSign } from "lucide-react";
|
||||
import { CircleDollarSign, ChevronsLeftIcon, ChevronsRightIcon, SkipBackIcon, SkipForwardIcon } from "lucide-react";
|
||||
import {
|
||||
Pagination,
|
||||
PaginationContent,
|
||||
@@ -114,6 +114,10 @@ export function ExpensesTable({ data, onPay, page, total, pageSize, onPageChange
|
||||
});
|
||||
|
||||
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
||||
const GROUP_SIZE = 3;
|
||||
const currentGroup = Math.floor((page - 1) / GROUP_SIZE);
|
||||
const startPage = currentGroup * GROUP_SIZE + 1;
|
||||
const endPage = Math.min(startPage + GROUP_SIZE - 1, totalPages);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
@@ -157,6 +161,16 @@ export function ExpensesTable({ data, onPay, page, total, pageSize, onPageChange
|
||||
{totalPages > 1 && (
|
||||
<Pagination>
|
||||
<PaginationContent>
|
||||
<PaginationItem>
|
||||
<PaginationLink
|
||||
onClick={(e) => { e.preventDefault(); onPageChange(1); }}
|
||||
href="#"
|
||||
aria-label="Ir a la primera página"
|
||||
className={page <= 1 ? "pointer-events-none opacity-50" : ""}
|
||||
>
|
||||
<SkipBackIcon className="size-4" />
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<PaginationPrevious
|
||||
onClick={(e) => { e.preventDefault(); if (page > 1) onPageChange(page - 1); }}
|
||||
@@ -164,7 +178,18 @@ export function ExpensesTable({ data, onPay, page, total, pageSize, onPageChange
|
||||
className={page <= 1 ? "pointer-events-none opacity-50" : ""}
|
||||
/>
|
||||
</PaginationItem>
|
||||
{Array.from({ length: totalPages }, (_, i) => i + 1).map((p) => (
|
||||
{currentGroup > 0 && (
|
||||
<PaginationItem>
|
||||
<PaginationLink
|
||||
onClick={(e) => { e.preventDefault(); onPageChange(startPage - 1); }}
|
||||
href="#"
|
||||
aria-label="Ir al grupo anterior"
|
||||
>
|
||||
<ChevronsLeftIcon className="size-4" />
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
)}
|
||||
{Array.from({ length: endPage - startPage + 1 }, (_, i) => startPage + i).map((p) => (
|
||||
<PaginationItem key={p}>
|
||||
<PaginationLink
|
||||
isActive={p === page}
|
||||
@@ -175,6 +200,17 @@ export function ExpensesTable({ data, onPay, page, total, pageSize, onPageChange
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
))}
|
||||
{(currentGroup + 1) * GROUP_SIZE < totalPages && (
|
||||
<PaginationItem>
|
||||
<PaginationLink
|
||||
onClick={(e) => { e.preventDefault(); onPageChange(endPage + 1); }}
|
||||
href="#"
|
||||
aria-label="Ir al siguiente grupo"
|
||||
>
|
||||
<ChevronsRightIcon className="size-4" />
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
)}
|
||||
<PaginationItem>
|
||||
<PaginationNext
|
||||
onClick={(e) => { e.preventDefault(); if (page < totalPages) onPageChange(page + 1); }}
|
||||
@@ -182,6 +218,16 @@ export function ExpensesTable({ data, onPay, page, total, pageSize, onPageChange
|
||||
className={page >= totalPages ? "pointer-events-none opacity-50" : ""}
|
||||
/>
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<PaginationLink
|
||||
onClick={(e) => { e.preventDefault(); onPageChange(totalPages); }}
|
||||
href="#"
|
||||
aria-label="Ir a la última página"
|
||||
className={page >= totalPages ? "pointer-events-none opacity-50" : ""}
|
||||
>
|
||||
<SkipForwardIcon className="size-4" />
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
</PaginationContent>
|
||||
</Pagination>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user