82 lines
4.1 KiB
TypeScript
82 lines
4.1 KiB
TypeScript
import React from 'react';
|
|
import { mdiArrowTopRight, mdiArrowBottomLeft, mdiChevronRight } from '@mdi/js';
|
|
import BaseIcon from '../../BaseIcon';
|
|
import Link from 'next/link';
|
|
import { useAppSelector } from '../../../stores/hooks';
|
|
|
|
const RecentTransactions = () => {
|
|
const { stats, loading } = useAppSelector((state) => state.dashboard);
|
|
|
|
const transactions = stats?.recentTransactions || [];
|
|
|
|
return (
|
|
<div className="bg-white dark:bg-dark-900 border border-gray-100 dark:border-dark-700 rounded-[1.5rem] p-6 shadow-sm overflow-hidden flex flex-col h-full">
|
|
<div className="flex items-center justify-between mb-6">
|
|
<h2 className="text-xl font-bold text-slate-800 dark:text-white">Recent Transactions</h2>
|
|
<Link href="/transactions" className="text-sm font-bold text-indigo-600 hover:text-indigo-700 flex items-center transition-colors">
|
|
View All
|
|
<BaseIcon path={mdiChevronRight} size={20} className="ml-0.5" />
|
|
</Link>
|
|
</div>
|
|
|
|
<div className="overflow-x-auto flex-grow">
|
|
<table className="w-full text-left">
|
|
<thead>
|
|
<tr className="border-b border-gray-50 dark:border-dark-700">
|
|
<th className="pb-4 text-xs font-bold text-slate-400 uppercase tracking-wider">Date</th>
|
|
<th className="pb-4 text-xs font-bold text-slate-400 uppercase tracking-wider">Description</th>
|
|
<th className="pb-4 text-xs font-bold text-slate-400 uppercase tracking-wider">Type</th>
|
|
<th className="pb-4 text-xs font-bold text-slate-400 uppercase tracking-wider text-right">Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-gray-50 dark:divide-dark-700">
|
|
{loading ? (
|
|
Array.from({ length: 5 }).map((_, i) => (
|
|
<tr key={i} className="animate-pulse">
|
|
<td className="py-4 h-4 bg-gray-50 dark:bg-dark-800 rounded w-16 my-2"></td>
|
|
<td className="py-4 h-4 bg-gray-50 dark:bg-dark-800 rounded w-32 my-2"></td>
|
|
<td className="py-4 h-4 bg-gray-50 dark:bg-dark-800 rounded w-20 my-2"></td>
|
|
<td className="py-4 h-4 bg-gray-50 dark:bg-dark-800 rounded w-20 my-2"></td>
|
|
</tr>
|
|
))
|
|
) : transactions.length > 0 ? (
|
|
transactions.map((transaction, index) => (
|
|
<tr key={index} className="group hover:bg-gray-50 dark:hover:bg-dark-800 transition-colors">
|
|
<td className="py-4 text-sm font-medium text-slate-500 dark:text-gray-400 whitespace-nowrap">
|
|
{new Date(transaction.date).toLocaleDateString()}
|
|
</td>
|
|
<td className="py-4 text-sm font-bold text-slate-800 dark:text-white whitespace-nowrap">
|
|
{transaction.description}
|
|
</td>
|
|
<td className="py-4 whitespace-nowrap">
|
|
<div className={`inline-flex items-center px-2.5 py-1 rounded-full text-[10px] font-bold shadow-sm border border-opacity-20 ${
|
|
transaction.isIncome
|
|
? 'bg-emerald-50 text-emerald-600 border-emerald-500'
|
|
: 'bg-rose-50 text-rose-600 border-rose-500'
|
|
}`}>
|
|
<BaseIcon path={transaction.isIncome ? mdiArrowTopRight : mdiArrowBottomLeft} size={14} className="mr-1" />
|
|
{transaction.type}
|
|
</div>
|
|
</td>
|
|
<td className={`py-4 text-sm font-bold text-right whitespace-nowrap ${
|
|
transaction.isIncome ? 'text-emerald-600' : 'text-rose-600'
|
|
}`}>
|
|
{transaction.isIncome ? '+' : '-'}{Number(transaction.amount).toLocaleString()}
|
|
</td>
|
|
</tr>
|
|
))
|
|
) : (
|
|
<tr>
|
|
<td colSpan={4} className="py-8 text-center text-gray-400 italic">
|
|
No recent transactions
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default RecentTransactions; |