CoolFace
Apppublic

spdniloy/anycoder-380d34cb

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
TransactionList.js97 linesDownload Raw Back to components
1import { Edit2, Trash2 } from 'lucide-react';2 3export default function TransactionList({4  transactions,5  type,6  onEdit,7  onDelete,8  emptyMessage,9}) {10  const formatCurrency = (amount) => {11    return new Intl.NumberFormat('en-US', {12      style: 'currency',13      currency: 'USD',14      minimumFractionDigits: 2,15    }).format(amount);16  };17 18  const formatDate = (dateStr) => {19    const date = new Date(dateStr);20    return new Intl.DateTimeFormat('en-US', {21      month: 'short',22      day: 'numeric',23      year: 'numeric',24    }).format(date);25  };26 27  const filtered = transactions.filter((t) => t.type === type);28 29  if (filtered.length === 0) {30    return (31      <div className="text-center py-12">32        <p className="text-neutral-400">{emptyMessage}</p>33      </div>34    );35  }36 37  return (38    <div className="overflow-hidden">39      <ul className="divide-y divide-neutral-100">40        {filtered.map((transaction) => (41          <li42            key={transaction.id}43            className="px-4 py-4 hover:bg-neutral-50 transition-colors duration-150 group"44          >45            <div className="flex items-center justify-between">46              <div className="flex-1 min-w-0">47                <div className="flex items-center gap-2">48                  <span className="font-medium text-neutral-800 truncate">49                    {transaction.category}50                  </span>51                  <span className={`text-xs px-2 py-0.5 rounded-full ${52                    type === 'income'53                      ? 'bg-income-light text-income-dark'54                      : 'bg-expense-light text-expense-dark'55                  }`}>56                    {transaction.category}57                  </span>58                </div>59                {transaction.description && (60                  <p className="text-sm text-neutral-500 mt-1 truncate">61                    {transaction.description}62                  </p>63                )}64                <p className="text-xs text-neutral-400 mt-1">65                  {formatDate(transaction.date)}66                </p>67              </div>68              <div className="flex items-center gap-3">69                <span className={`font-semibold ${70                  type === 'income' ? 'text-income-dark' : 'text-expense-dark'71                }`}>72                  {type === 'income' ? '+' : '-'}{formatCurrency(transaction.amount)}73                </span>74                <div className="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">75                  <button76                    onClick={() => onEdit(transaction)}77                    className="p-2 text-neutral-400 hover:text-primary-600 rounded-lg hover:bg-primary-50 transition-colors"78                    aria-label="Edit"79                  >80                    <Edit2 className="w-4 h-4" />81                  </button>82                  <button83                    onClick={() => onDelete(transaction.id)}84                    className="p-2 text-neutral-400 hover:text-expense-DEFAULT rounded-lg hover:bg-expense-light transition-colors"85                    aria-label="Delete"86                  >87                    <Trash2 className="w-4 h-4" />88                  </button>89                </div>90              </div>91            </div>92          </li>93        ))}94      </ul>95    </div>96  );97}