/* ============================================================================ Super Sunday — Frontend API client (ESM) ============================================================================ */ const BASE = '/api'; const TOKEN_KEY = 'ss_token'; function getToken() { return localStorage.getItem(TOKEN_KEY) || ''; } function setToken(t) { if (t) localStorage.setItem(TOKEN_KEY, t); else localStorage.removeItem(TOKEN_KEY); } async function fetchJSON(url, opts = {}) { const res = await fetch(url, opts); const ct = res.headers.get('content-type') || ''; const isJSON = ct.includes('application/json'); const data = isJSON ? await res.json().catch(() => ({})) : await res.text(); if (!res.ok) { const err = new Error((data && data.error) || res.statusText || 'HTTP Error'); err.status = res.status; err.payload = data; throw err; } return data; } async function authFetch(path, options = {}) { const token = getToken(); const headers = new Headers(options.headers || {}); headers.set('Content-Type','application/json'); if(token) headers.set('Authorization',`Bearer ${token}`); return fetchJSON(`${BASE}${path}`,{...options,headers}); } /* Public endpoints */ export async function listTournaments(){ return fetchJSON(`${BASE}/tournaments`); } export async function getTournament(id){ return fetchJSON(`${BASE}/tournaments/${id}`); } export async function listParticipants(id){ return fetchJSON(`${BASE}/tournaments/${id}/participants`); } export async function listMatches(id){ return fetchJSON(`${BASE}/tournaments/${id}/matches`); } /* Admin endpoints */ export async function login(email,password){ const data = await fetchJSON(`${BASE}/auth/login`,{ method:'POST',headers:{'Content-Type':'application/json'}, body: JSON.stringify({email,password}) }); if(data && data.token) setToken(data.token); return data; } export function logout(){ setToken(''); } export function isAuthenticated(){ return !!getToken(); } export async function createTournament(payload){ return authFetch(`/tournaments`,{method:'POST',body:JSON.stringify(payload)}); } export async function addParticipant(tid,payload){ return authFetch(`/tournaments/${tid}/participants`,{method:'POST',body:JSON.stringify(payload)}); } export async function generateAmericano(tid,payload){ return authFetch(`/tournaments/${tid}/generate-americano`,{method:'POST',body:JSON.stringify(payload)}); } export async function scoreMatch(mid,payload){ return authFetch(`/matches/${mid}/score`,{method:'POST',body:JSON.stringify(payload)}); } /* Helpers */ export function bindLoginForm({formSel='#loginSection',statusSel='#loginStatus'}={}){ const form=document.querySelector(formSel); const status=document.querySelector(statusSel); if(!form) return; const email=form.querySelector('#email'); const password=form.querySelector('#password'); const btn=form.querySelector('#loginBtn'); btn?.addEventListener('click',async ()=>{ status.textContent='Connexion…'; try{ await login(email.value.trim(),password.value); status.textContent='Connecté ✔'; const admin=document.querySelector('#adminSection'); if(admin) admin.style.display='grid'; form.style.display='none'; }catch(e){ status.textContent=`Erreur: ${e.payload?.error||e.message}`; } }); }