/* global React, NA_DATA, NASite, naSupabase */ const { useState } = React; function AcademyPage({ setPage }) { const { Photo } = NASite; const { ACADEMY_SERVICES } = NA_DATA; return (
Athletic Academy CIC / Schools

For schools.

Athletic Academy CIC is the community arm of Nottingham Athletic. We partner with primary and secondary schools across Nottingham — coaching, mentoring, and structured enrichment, all delivered by qualified, club-trained staff.

{ACADEMY_SERVICES.map((s, i) => (
0{i + 1}

{s.t}

{s.d}

))}
For school trusts & heads

Inter-school leagues — properly run.

We design, schedule, and officiate inter-school basketball competitions on behalf of trusts — drawing on the American student-athlete model. Your pupils compete for their school AND have a route into the club.

{[ { l: 'Schools partnered', v: '12+', s: 'across Nottingham' }, { l: 'Pupils reached', v: '1,400', s: 'in school year 25/26' }, { l: 'Y6 transition cohort', v: '85', s: 'across 6 schools' }, { l: 'Founded', v: '2024', s: 'CIC since launch' }, ].map((b, i) => (
{b.l}
{b.v}
{b.s}
))}
); } function TravelTeamsPage({ setPage }) { const { TRAVEL_COMPETITIONS, TRAVEL_TIMELINE } = NA_DATA; const [status, setStatus] = useState('idle'); // 'idle' | 'sending' | 'sent' | 'error' const [errMsg, setErrMsg] = useState(''); const initial = { // Player full_name: '', dob: '', position: '', height_cm: '', nationality: '', // Contact email: '', phone: '', parent_name: '', parent_email: '', parent_phone: '', emergency_name: '', emergency_phone: '', // Playing age_group: 'Senior / open age', competition_id: 'any', existing_club: '', playing_history: '', // Notes medical: '', notes: '', // Consent consent: false, }; const [form, setForm] = useState(initial); const [hp, setHp] = useState(''); // honeypot — must stay empty const startedAt = React.useRef(Date.now()); const set = (k, v) => setForm(f => ({ ...f, [k]: v })); // Compute under-18 status from DOB. Used to mark parent / emergency fields required. const isUnder18 = (() => { if (!form.dob) return false; const dob = new Date(form.dob); if (isNaN(dob)) return false; const today = new Date(); let age = today.getFullYear() - dob.getFullYear(); const m = today.getMonth() - dob.getMonth(); if (m < 0 || (m === 0 && today.getDate() < dob.getDate())) age--; return age < 18; })(); // Surface only competitions still open for applications in the selector. const openCompetitions = TRAVEL_COMPETITIONS.filter(c => c.status === 'open'); const submit = async (e) => { e.preventDefault(); setStatus('sending'); setErrMsg(''); // Spam guard — silently succeed without writing if it trips. if (naSupabase.looksLikeSpam({ honeypot: hp, startedAt: startedAt.current })) { setStatus('sent'); return; } const parts = form.full_name.trim().split(/\s+/); const first_name = parts[0] || ''; const last_name = parts.length > 1 ? parts.slice(1).join(' ') : ''; const ageMap = { 'Senior / open age': 'senior', 'U23': 'u23', 'U18': 'u18', 'U16': 'u16', 'U14': 'u14' }; // Pack the extended fields into the `message` column so they're preserved // in the coach app without needing a DB schema change. Coaches see this as // a structured block they can copy out. const messageLines = [ '--- Travel teams application ---', `Date of birth: ${form.dob || '—'} ${isUnder18 ? '(Under 18)' : ''}`.trim(), form.position ? `Position: ${form.position}` : null, form.height_cm ? `Height: ${form.height_cm} cm` : null, form.nationality ? `Nationality / passport country: ${form.nationality}` : null, form.phone ? `Player phone: ${form.phone}` : null, isUnder18 && form.parent_name ? `Parent / guardian: ${form.parent_name}` : null, isUnder18 && form.parent_email ? `Parent / guardian email: ${form.parent_email}` : null, isUnder18 && form.parent_phone ? `Parent / guardian phone: ${form.parent_phone}` : null, form.emergency_name ? `Emergency contact: ${form.emergency_name}` : null, form.emergency_phone ? `Emergency phone: ${form.emergency_phone}` : null, form.playing_history ? `\nPlaying history / level:\n${form.playing_history.trim()}` : null, form.medical ? `\nMedical / dietary:\n${form.medical.trim()}` : null, form.notes ? `\nAnything else:\n${form.notes.trim()}` : null, ].filter(Boolean).join('\n'); try { await naSupabase.submitEnquiry({ source: 'travel_team', // 'any' = open to any tour; otherwise pin to a specific competition. competition_id: form.competition_id === 'any' ? null : form.competition_id, first_name, last_name, email: form.email.trim(), phone: form.phone.trim(), age_group: ageMap[form.age_group] || form.age_group, existing_club: form.existing_club.trim(), message: messageLines, }); setStatus('sent'); } catch (err) { console.warn('submitEnquiry failed:', err); setErrMsg(err.message || 'Could not send. Try again or email admin@nottinghamathletic.com.'); setStatus('error'); } }; const sent = status === 'sent'; const sending = status === 'sending'; const reset = () => { setStatus('idle'); setForm(initial); }; // Which competition was picked (for the success message). const picked = form.competition_id === 'any' ? null : TRAVEL_COMPETITIONS.find(c => c.id === form.competition_id); return (
Programme / Travel teams

Travel teams.

Nottingham Athletic aims to be a mainstay programme in the EYBL — the European Youth Basketball League — for all age groups. Alongside our domestic squads, we enter travel teams into European competition. Register interest below and a coach will be in touch about selection.

{/* Competitions list — cards for each upcoming tour */}
What we're entering

Our European programme

Register interest →
{TRAVEL_COMPETITIONS.map((c, i) => (
Tour 0{i + 1} · {c.when}
{c.status === 'open' ? ( Open for applications ) : c.status === 'planned' ? ( Planned · {c.when} ) : ( Roster locked )}

{c.name}

{c.blurb}

Dates
{c.dates.replace(/ \d{4}$/, '')}
Location
{c.location}
Eligible
{c.eligibility}
))}
{/* Travel teams WhatsApp community — always visible on the page */}
International announcements · WhatsApp community
Join the travel teams community.

Be the first to know about upcoming trips abroad — sign-up forms, letters, and exclusive early-bird rates, straight to your phone.

{/* Register-interest form */}
Register interest

Apply for travel teams.

One application covers every open tour. Submissions land with the coaches in the Nottingham Athletic coach app — selection details follow by email. Junior applicants: parent / guardian details are required.

{sent ? (
Thanks. You're on the list.

{picked ? <>We'll be in touch about {picked.short} and any other tours that fit your age group. : <>We'll be in touch about whichever tours fit your age group.}

{/* Travel teams WhatsApp community — surfaced right after applying */}
Next step · WhatsApp group
Join the travel teams community.

Be the first to get sign-up forms, letters, and exclusive early-bird rates for upcoming trips abroad.

) : (
{/* Honeypot — hidden from humans, bots fill it. Leave empty. */} {/* PLAYER */}
Player
set('full_name', e.target.value)} disabled={sending} />
set('dob', e.target.value)} disabled={sending} />
set('nationality', e.target.value)} disabled={sending} />
set('height_cm', e.target.value)} disabled={sending} />
{/* CONTACT */}
Contact
set('email', e.target.value)} disabled={sending} />
set('phone', e.target.value)} disabled={sending} />
{isUnder18 && (
Parent / guardian — required for under 18s
set('parent_name', e.target.value)} disabled={sending} />
set('parent_email', e.target.value)} disabled={sending} />
set('parent_phone', e.target.value)} disabled={sending} />
)}
set('emergency_name', e.target.value)} disabled={sending} />
set('emergency_phone', e.target.value)} disabled={sending} />
{/* PLAYING */}
Playing
set('existing_club', e.target.value)} disabled={sending} />