/* global React, NA_DATA, NASite, naSupabase */ const { useState, useEffect } = React; /* ============================================================ CAMPS PAGE ============================================================ Lists published camps from Supabase (`public_camps` view). Each card has an "Apply" button that opens an application form; submitting writes to `enquiries` with source='camp_application'. ============================================================ */ function CampsPage({ setPage }) { const [camps, setCamps] = useState([]); const [loadState, setLoadState] = useState('loading'); // 'loading' | 'ok' | 'empty' | 'error' const [errMsg, setErrMsg] = useState(''); const [applyTo, setApplyTo] = useState(null); // a camp object, or null // Fetch published camps on mount. useEffect(() => { let cancelled = false; (async () => { try { const rows = await naSupabase.fetchCamps(); if (cancelled) return; setCamps(rows); setLoadState(rows.length === 0 ? 'empty' : 'ok'); } catch (e) { if (cancelled) return; console.warn('Supabase fetchCamps failed:', e); setErrMsg(e.message || 'Could not reach Supabase'); setLoadState('error'); } })(); return () => { cancelled = true; }; }, []); return (
Programme / Camps

Camps.

Multi-day skills camps — open to club members and outside players. Run during school holidays at our partner venues across Nottingham. Coaches publish each camp here as soon as dates are confirmed.

{loadState === 'loading' && (
Loading camps…
)} {loadState === 'error' && (
Could not load camps.

{errMsg}

)} {loadState === 'empty' && (
No camps published right now.

We run camps in the school holidays — Christmas, February half-term, Easter, and across summer. When dates are confirmed they appear here. Drop us a line and we'll let you know.

)} {loadState === 'ok' && (
{camps.map((c, i) => ( setApplyTo(c)} /> ))}
)}
{applyTo && ( setApplyTo(null)} /> )}
); } /* ---- One camp card ---- */ function CampCard({ camp, index, onApply }) { const dateLabel = formatCampDates(camp.starts_on, camp.ends_on); const priceLabel = !camp.price_pence ? 'Free' : '£' + (camp.price_pence / 100).toFixed(camp.price_pence % 100 === 0 ? 0 : 2); return (
Camp 0{index + 1} · {dateLabel.month}
{camp.is_open_for_applications ? ( Open for applications ) : ( Full )}

{camp.title}

{camp.blurb &&

{camp.blurb}

}
Dates
{dateLabel.range}
{(camp.start_time || camp.end_time) && (
{camp.start_time}{camp.end_time ? ' – ' + camp.end_time : ''}
)}
Venue
{camp.venue || 'TBA'}
{camp.eligibility && (
Eligible
{camp.eligibility}
)}
Price
{priceLabel}
); } /* ---- Camp application modal ---- */ function CampApplicationModal({ camp, onClose }) { const [status, setStatus] = useState('idle'); // 'idle' | 'sending' | 'sent' | 'error' const [errMsg, setErrMsg] = useState(''); const [form, setForm] = useState({ first_name: '', last_name: '', email: '', phone: '', player_info: '', message: '' }); const set = (k, v) => setForm(f => ({ ...f, [k]: v })); const submit = async (e) => { e.preventDefault(); setStatus('sending'); setErrMsg(''); try { await naSupabase.submitEnquiry({ source: 'camp_application', camp_id: camp.id, first_name: form.first_name.trim(), last_name: form.last_name.trim(), email: form.email.trim(), phone: form.phone.trim(), player_info: form.player_info.trim(), message: form.message.trim(), }); 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'; return (
e.stopPropagation()}> {sent ? (

You're in the queue.

We'll confirm a place at {camp.title} by email — including payment details and what to bring.

) : ( <>
Apply · {camp.title}

Sign up for this camp.

We'll confirm a place by email within a couple of days.

set('first_name', e.target.value)} disabled={sending} />
set('last_name', e.target.value)} disabled={sending} />
set('email', e.target.value)} disabled={sending} />
set('phone', e.target.value)} disabled={sending} />
set('player_info', e.target.value)} disabled={sending} />