Enhancements
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Member, Payment } from '../types'
|
||||
|
||||
interface PaymentsTableProps {
|
||||
members: Member[]
|
||||
payments: Payment[]
|
||||
loading: boolean
|
||||
}
|
||||
|
||||
export const PaymentsTable: React.FC<PaymentsTableProps> = ({ members, payments, loading }) => {
|
||||
const [filter, setFilter] = useState('')
|
||||
|
||||
const getMemberName = (memberId: number) => {
|
||||
const member = members.find((m) => m.id === memberId)
|
||||
return member ? `${member.member_firstname} ${member.member_surname}` : 'Unknown'
|
||||
}
|
||||
|
||||
const filteredPayments = payments.filter((p) => {
|
||||
const memberName = getMemberName(p.member_id).toLowerCase()
|
||||
return memberName.includes(filter.toLowerCase())
|
||||
})
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="text-center py-5">
|
||||
<div className="spinner-border" role="status">
|
||||
<span className="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-4">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
placeholder="🔍 Search by member name..."
|
||||
value={filter}
|
||||
onChange={(e) => setFilter(e.target.value)}
|
||||
style={{ fontSize: '0.95rem' }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{filteredPayments.length > 0 ? (
|
||||
<>
|
||||
<div className="table-responsive">
|
||||
<table className="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Payment ID</th>
|
||||
<th>Member Name</th>
|
||||
<th>Member ID</th>
|
||||
<th>Payment Date</th>
|
||||
<th>Year</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{filteredPayments.map((payment) => (
|
||||
<tr key={payment.id}>
|
||||
<td style={{ fontWeight: 600, color: '#27ae60' }}>{payment.id}</td>
|
||||
<td>{getMemberName(payment.member_id)}</td>
|
||||
<td>{payment.member_id}</td>
|
||||
<td style={{ fontSize: '0.9rem' }}>
|
||||
{new Date(payment.payment_date).toLocaleDateString()}
|
||||
</td>
|
||||
<td>{payment.payment_year}</td>
|
||||
<td style={{ fontWeight: 600, color: '#3498db' }}>
|
||||
€{payment.payment_amount ? payment.payment_amount.toFixed(2) : '0.00'}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="mt-3 text-muted">
|
||||
Showing <strong>{filteredPayments.length}</strong> of <strong>{payments.length}</strong> payments
|
||||
{filteredPayments.length > 0 && (
|
||||
<span className="ms-3">
|
||||
• Total: <strong>€{filteredPayments.reduce((sum, p) => sum + (p.payment_amount || 0), 0).toFixed(2)}</strong>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="text-center py-5 text-muted">
|
||||
<p>No payments found matching your search</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user