83 lines
4.5 KiB
JavaScript
83 lines
4.5 KiB
JavaScript
import { useState } from 'react';
|
|
import { Link } from 'react-router-dom';
|
|
import { useStore } from '../hooks/useStore.jsx';
|
|
import { SPORTS } from '../data/seedData.js';
|
|
import Avatar from '../components/Avatar.jsx';
|
|
import SportBadge from '../components/SportBadge.jsx';
|
|
import { fmtName } from '../utils/formatName.js';
|
|
|
|
export default function Athletes() {
|
|
const { users } = useStore();
|
|
const [search, setSearch] = useState('');
|
|
const [sport, setSport] = useState('all');
|
|
|
|
const filtered = users.filter(u => {
|
|
const matchSearch = !search || u.name?.toLowerCase().includes(search.toLowerCase()) || u.city?.toLowerCase().includes(search.toLowerCase());
|
|
const matchSport = sport === 'all' || u.sports?.includes(sport);
|
|
return matchSearch && matchSport;
|
|
});
|
|
|
|
return (
|
|
<div className="page">
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 4 }}>
|
|
<h1 className="section-title">Athletes</h1>
|
|
<Link to="/register" className="btn btn-primary" style={{ fontSize: 13, padding: '8px 16px' }}>+ Add</Link>
|
|
</div>
|
|
<p className="section-sub">All registered athletes</p>
|
|
|
|
<div style={{ display: 'flex', gap: 12, marginBottom: 20, flexWrap: 'wrap' }}>
|
|
<div style={{ flex: 1, minWidth: 200 }}>
|
|
<input value={search} onChange={e => setSearch(e.target.value)} placeholder="Search name or city..." />
|
|
</div>
|
|
<select value={sport} onChange={e => setSport(e.target.value)} style={{ width: 'auto', minWidth: 160 }}>
|
|
<option value="all">All Sports</option>
|
|
{Object.values(SPORTS).map(s => <option key={s.id} value={s.id}>{s.emoji} {s.name}</option>)}
|
|
</select>
|
|
</div>
|
|
|
|
<div style={{ color: 'var(--text-muted)', fontSize: 13, marginBottom: 12 }}>
|
|
{filtered.length} athlete{filtered.length !== 1 ? 's' : ''}
|
|
</div>
|
|
|
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px,1fr))', gap: 12 }}>
|
|
{filtered.map(u => (
|
|
<Link key={u.id} to={`/athletes/${u.id}`}>
|
|
<div className="card" style={{ cursor: 'pointer', transition: 'border-color 0.15s, transform 0.15s' }}
|
|
onMouseEnter={e => { e.currentTarget.style.borderColor = 'var(--accent)'; e.currentTarget.style.transform = 'translateY(-2px)'; }}
|
|
onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border)'; e.currentTarget.style.transform = ''; }}
|
|
>
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 12 }}>
|
|
<Avatar user={u} size={48} />
|
|
<div>
|
|
<div style={{ fontWeight: 700, fontSize: 16 }}>{fmtName(u)}</div>
|
|
<div style={{ color: 'var(--text-muted)', fontSize: 12 }}>{u.city}, {u.country}</div>
|
|
</div>
|
|
</div>
|
|
<div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 10 }}>
|
|
{u.sports?.map(s => <SportBadge key={s} sport={s} />)}
|
|
</div>
|
|
<div style={{ display: 'flex', gap: 16 }}>
|
|
<div>
|
|
<div style={{ fontSize: 11, color: 'var(--text-muted)', fontFamily: 'var(--font-display)', letterSpacing: '0.06em', textTransform: 'uppercase' }}>Age</div>
|
|
<div style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 18, color: 'var(--accent)' }}>{u.biometrics?.age}</div>
|
|
</div>
|
|
<div>
|
|
<div style={{ fontSize: 11, color: 'var(--text-muted)', fontFamily: 'var(--font-display)', letterSpacing: '0.06em', textTransform: 'uppercase' }}>Height</div>
|
|
<div style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 18, color: 'var(--accent)' }}>{u.biometrics?.height_cm}<span style={{ fontSize: 11 }}>cm</span></div>
|
|
</div>
|
|
<div>
|
|
<div style={{ fontSize: 11, color: 'var(--text-muted)', fontFamily: 'var(--font-display)', letterSpacing: '0.06em', textTransform: 'uppercase' }}>Years Pro</div>
|
|
<div style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 18, color: 'var(--accent)' }}>{u.biometrics?.years_pro}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
))}
|
|
{filtered.length === 0 && (
|
|
<div style={{ textAlign: 'center', color: 'var(--text-muted)', padding: 48, gridColumn: '1/-1' }}>No athletes found</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|