File size: 3,353 Bytes
fa9dbcb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import { Edit2, Trash2 } from 'lucide-react';

export default function TransactionList({
  transactions,
  type,
  onEdit,
  onDelete,
  emptyMessage,
}) {
  const formatCurrency = (amount) => {
    return new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency: 'USD',
      minimumFractionDigits: 2,
    }).format(amount);
  };

  const formatDate = (dateStr) => {
    const date = new Date(dateStr);
    return new Intl.DateTimeFormat('en-US', {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    }).format(date);
  };

  const filtered = transactions.filter((t) => t.type === type);

  if (filtered.length === 0) {
    return (
      <div className="text-center py-12">
        <p className="text-neutral-400">{emptyMessage}</p>
      </div>
    );
  }

  return (
    <div className="overflow-hidden">
      <ul className="divide-y divide-neutral-100">
        {filtered.map((transaction) => (
          <li
            key={transaction.id}
            className="px-4 py-4 hover:bg-neutral-50 transition-colors duration-150 group"
          >
            <div className="flex items-center justify-between">
              <div className="flex-1 min-w-0">
                <div className="flex items-center gap-2">
                  <span className="font-medium text-neutral-800 truncate">
                    {transaction.category}
                  </span>
                  <span className={`text-xs px-2 py-0.5 rounded-full ${
                    type === 'income'
                      ? 'bg-income-light text-income-dark'
                      : 'bg-expense-light text-expense-dark'
                  }`}>
                    {transaction.category}
                  </span>
                </div>
                {transaction.description && (
                  <p className="text-sm text-neutral-500 mt-1 truncate">
                    {transaction.description}
                  </p>
                )}
                <p className="text-xs text-neutral-400 mt-1">
                  {formatDate(transaction.date)}
                </p>
              </div>
              <div className="flex items-center gap-3">
                <span className={`font-semibold ${
                  type === 'income' ? 'text-income-dark' : 'text-expense-dark'
                }`}>
                  {type === 'income' ? '+' : '-'}{formatCurrency(transaction.amount)}
                </span>
                <div className="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
                  <button
                    onClick={() => onEdit(transaction)}
                    className="p-2 text-neutral-400 hover:text-primary-600 rounded-lg hover:bg-primary-50 transition-colors"
                    aria-label="Edit"
                  >
                    <Edit2 className="w-4 h-4" />
                  </button>
                  <button
                    onClick={() => onDelete(transaction.id)}
                    className="p-2 text-neutral-400 hover:text-expense-DEFAULT rounded-lg hover:bg-expense-light transition-colors"
                    aria-label="Delete"
                  >
                    <Trash2 className="w-4 h-4" />
                  </button>
                </div>
              </div>
            </div>
          </li>
        ))}
      </ul>
    </div>
  );
}