112 lines
7.0 KiB
JavaScript
112 lines
7.0 KiB
JavaScript
import React from 'react';
|
|
import { MoreVertical, ArrowDownRight, ArrowUpRight, ChevronLeft, ChevronRight } from 'lucide-react';
|
|
|
|
export default function AccountsTable({ data = [], pagination = null, onPageChange }) {
|
|
const formatCurrency = (val) => {
|
|
return new Intl.NumberFormat('en-AE', { style: 'currency', currency: 'AED' }).format(val);
|
|
};
|
|
|
|
return (
|
|
<div className="bg-white rounded-[2rem] p-8 border border-gray-100 shadow-sm overflow-hidden animate-in fade-in slide-in-from-bottom-4 duration-500">
|
|
<div className="flex items-center justify-between mb-8">
|
|
<div>
|
|
<h3 className="text-xl font-bold text-gray-900">Recent Transactions</h3>
|
|
<p className="text-xs text-gray-400 font-bold uppercase tracking-widest mt-1">Detailed breakdown of income and expenses.</p>
|
|
</div>
|
|
<button className="text-gray-400 hover:text-gray-900 transition-colors">
|
|
<MoreVertical size={20} />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="overflow-x-auto -mx-8">
|
|
<table className="w-full">
|
|
<thead>
|
|
<tr className="text-left border-b border-gray-50 bg-gray-50/30">
|
|
<th className="px-8 pb-4 text-[10px] uppercase font-bold text-gray-400 tracking-wider">Date</th>
|
|
<th className="px-4 pb-4 text-[10px] uppercase font-bold text-gray-400 tracking-wider">Type</th>
|
|
<th className="px-4 pb-4 text-[10px] uppercase font-bold text-gray-400 tracking-wider">Category / Description</th>
|
|
<th className="px-8 pb-4 text-right text-[10px] uppercase font-bold text-gray-400 tracking-wider">Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-gray-50">
|
|
{data.length === 0 && (
|
|
<tr>
|
|
<td colSpan="4" className="py-12 text-center text-sm font-medium text-gray-400 italic">No transactions found for the selected period.</td>
|
|
</tr>
|
|
)}
|
|
{data.map((row, index) => (
|
|
<tr key={index} className="group hover:bg-gray-50/50 transition-all">
|
|
<td className="px-8 py-5">
|
|
<div className="flex flex-col">
|
|
<span className="text-sm font-bold text-gray-900">{new Date(row.date).toLocaleDateString()}</span>
|
|
<span className="text-[10px] text-gray-400 font-medium uppercase">{new Date(row.date).toLocaleDateString(undefined, { weekday: 'short' })}</span>
|
|
</div>
|
|
</td>
|
|
<td className="px-4 py-5 font-medium">
|
|
<span className={`inline-flex items-center gap-1.5 px-3 py-1 rounded-lg text-[10px] font-black uppercase tracking-widest ${
|
|
row.type === 'Income'
|
|
? 'bg-emerald-50 text-emerald-600 border border-emerald-100'
|
|
: 'bg-rose-50 text-rose-600 border border-rose-100'
|
|
}`}>
|
|
{row.type === 'Income' ? <ArrowUpRight size={12} /> : <ArrowDownRight size={12} />}
|
|
{row.type}
|
|
</span>
|
|
</td>
|
|
<td className="px-4 py-5">
|
|
<div className="flex flex-col max-w-md">
|
|
<span className="text-sm font-bold text-gray-800 truncate">{row.category}</span>
|
|
<span className="text-xs text-gray-400 font-medium truncate">{row.description || 'No description provided'}</span>
|
|
</div>
|
|
</td>
|
|
<td className="px-8 py-5 text-right">
|
|
<span className={`text-sm font-black ${row.type === 'Income' ? 'text-emerald-600' : 'text-rose-600'}`}>
|
|
{row.type === 'Income' ? '+' : '-'}{formatCurrency(row.amount)}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{/* Pagination Controls */}
|
|
{pagination && pagination.last_page > 1 && (
|
|
<div className="flex items-center justify-between mt-8 pt-6 border-t border-gray-50">
|
|
<p className="text-[10px] font-black text-gray-400 uppercase tracking-widest">
|
|
Showing page {pagination.current_page} of {pagination.last_page} ({pagination.total} total)
|
|
</p>
|
|
<div className="flex items-center gap-2">
|
|
<button
|
|
disabled={pagination.current_page === 1}
|
|
onClick={() => onPageChange(pagination.current_page - 1)}
|
|
className="p-2 bg-gray-50 text-gray-400 rounded-lg hover:bg-red-50 hover:text-red-500 transition-all disabled:opacity-30 disabled:hover:bg-gray-50 disabled:hover:text-gray-400"
|
|
>
|
|
<ChevronLeft size={18} />
|
|
</button>
|
|
{[...Array(pagination.last_page)].map((_, i) => (
|
|
<button
|
|
key={i + 1}
|
|
onClick={() => onPageChange(i + 1)}
|
|
className={`w-9 h-9 flex items-center justify-center rounded-lg text-[10px] font-black transition-all ${
|
|
pagination.current_page === i + 1
|
|
? 'bg-red-500 text-white shadow-lg shadow-red-200'
|
|
: 'bg-gray-50 text-gray-400 hover:bg-gray-100 hover:text-gray-900'
|
|
}`}
|
|
>
|
|
{i + 1}
|
|
</button>
|
|
))}
|
|
<button
|
|
disabled={pagination.current_page === pagination.last_page}
|
|
onClick={() => onPageChange(pagination.current_page + 1)}
|
|
className="p-2 bg-gray-50 text-gray-400 rounded-lg hover:bg-red-50 hover:text-red-500 transition-all disabled:opacity-30 disabled:hover:bg-gray-50 disabled:hover:text-gray-400"
|
|
>
|
|
<ChevronRight size={18} />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|