function Seizoenen({baan,toon}){
  const [lijst,setLijst]=useState([]); const [dagen,setDagen]=useState({}); const [open,setOpen]=useState(null);
  const [laden,setLaden]=useState(true); const [nieuw,setNieuw]=useState(false);
  const [naam,setNaam]=useState(""); const [van,setVan]=useState(iso(new Date()));
  const [tot,setTot]=useState(iso(new Date(Date.now()+90*864e5))); const [f,setF]=useState(null);
  const [weg,setWeg]=useState(null);   // seizoen waarvoor het bevestigingspaneel openstaat
  const laad=useCallback(async()=>{ if(!baan) return; setLaden(true);
    const s=await db.from("seizoenen").select("*").eq("baan_id",baan).order("geldig_van");
    const d=await db.from("seizoen_dagen").select("*");
    if(s.error) setF(fout(s.error)); setLijst(s.data||[]);
    const k={}; (d.data||[]).forEach(r=>{ if(!k[r.seizoen_id])k[r.seizoen_id]={}; k[r.seizoen_id][r.dag]=r; }); setDagen(k); setLaden(false); },[baan]);
  useEffect(()=>{ laad(); },[laad]);
  async function maak(){ setF(null);
    const r=await db.from("seizoenen").insert({baan_id:baan,naam:naam.trim(),geldig_van:van,geldig_tot:tot}).select().single();
    if(r.error){ setF(fout(r.error)); return; }
    await db.from("seizoen_dagen").insert([1,2,3,4,5,6,7].map(d=>({seizoen_id:r.data.id,dag:d,gesloten:false,begintijd:"09:00",eindtijd:"17:00",interval_minuten:10,max_spelers:4})));
    setNieuw(false); setNaam(""); toon("Seizoen aangemaakt"); setOpen(r.data.id); laad(); }
  function wzDag(sid,dag,veld,val){ setDagen(v=>{ const k=Object.assign({},v); const ps=Object.assign({},k[sid]||{});
    const r=Object.assign({},ps[dag]||{seizoen_id:sid,dag:dag}); r[veld]=val; ps[dag]=r; k[sid]=ps; return k; }); }
  async function bewaar(sid){ setF(null); const rijen=[];
    for(let d=1;d<=7;d++){ const r=(dagen[sid]||{})[d]||{dag:d,gesloten:true};
      rijen.push({seizoen_id:sid,dag:d,gesloten:!!r.gesloten, begintijd:r.gesloten?null:(r.begintijd||"09:00"), eindtijd:r.gesloten?null:(r.eindtijd||"17:00"),
        interval_minuten:Number(r.interval_minuten||10), max_spelers:Number(r.max_spelers||4)}); }
    const w=await db.from("seizoen_dagen").delete().eq("seizoen_id",sid);
    if(w.error){ setF(fout(w.error)); return; }
    const i=await db.from("seizoen_dagen").insert(rijen);
    if(i.error){ setF(fout(i.error)); return; } toon("Openingstijden opgeslagen"); laad(); }
  async function uitrol(sid){ const r=await db.rpc("rol_seizoen_uit",{p_seizoen_id:sid});
    if(r.error){ setF(fout(r.error)); return; } toon(r.data.starttijden+" starttijden, "+r.data.speeldagen+" speeldagen"); }
  // Geen `window.confirm` meer. Die dialoog komt van de browser, draagt "127.0.0.1:8901 zegt:" boven de
  // vraag en bevriest de hele pagina tot er geklikt is. Zie de toelichting bij `Bevestig` in
  // schermen-dag.jsx; hier hangt hetzelfde paneel eronder.
  async function verwijderNu(s){ setWeg(null);
    const r=await db.from("seizoenen").delete().eq("id",s.id); if(r.error){ setF(fout(r.error)); return; } toon("Verwijderd"); laad(); }
  if(laden) return <div className="laden">Laden…</div>;
  return (<div>
    <div className="kop"><h3>Seizoenen</h3><div className="acties"><button className="mini doe" onClick={()=>setNieuw(!nieuw)}>{nieuw?"Annuleren":"+ Seizoen"}</button></div></div>
    <p className="bij" style={{marginTop:-4}}>Periode met openingstijden per weekdag. Uitrollen maakt de starttijden aan en slaat sluitingsdagen over.</p>
    {nieuw && <div className="kaart">
      <div className="rij"><div><label>Naam</label><input value={naam} onChange={e=>setNaam(e.target.value)} placeholder="Zomer 2026"/></div></div>
      <div className="rij"><div><label>Van</label><input type="date" value={van} onChange={e=>setVan(e.target.value)}/></div>
        <div><label>Tot en met</label><input type="date" value={tot} onChange={e=>setTot(e.target.value)}/></div></div>
      <button className="primair" onClick={maak} disabled={!naam.trim()}>Seizoen aanmaken</button></div>}
    {lijst.length===0 && !nieuw && <div className="kaart"><p className="bij" style={{margin:0}}>Nog geen seizoenen.</p></div>}
    {lijst.map(s=>(<div className="kaart" key={s.id}>
      <div className="kop"><h3>{s.naam}</h3><span className="pil">{kortDat(s.geldig_van)} tot {kortDat(s.geldig_tot)}</span>
        <div className="acties"><button className="mini" onClick={()=>setOpen(open===s.id?null:s.id)}>{open===s.id?"Inklappen":"Tijden"}</button>
          <button className="mini doe" onClick={()=>uitrol(s.id)}>Uitrollen</button><button className="mini gevaar" onClick={()=>setWeg(s)}>Verwijder</button></div></div>
      {open===s.id && <div>
        {[1,2,3,4,5,6,7].map(d=>{ const r=(dagen[s.id]||{})[d]||{gesloten:true}; return (
          <div className={"weekrij"+(r.gesloten?" dicht":"")} key={d}><div className="dg">{DAG[d]}</div>
            <label className="sw" style={{margin:0}}><input type="checkbox" checked={!r.gesloten} onChange={e=>wzDag(s.id,d,"gesloten",!e.target.checked)}/>open</label>
            <div className="paar"><input type="time" value={r.begintijd||""} disabled={r.gesloten} onChange={e=>wzDag(s.id,d,"begintijd",e.target.value)}/>
              <input type="time" value={r.eindtijd||""} disabled={r.gesloten} onChange={e=>wzDag(s.id,d,"eindtijd",e.target.value)}/></div>
          </div>);})}
        <button className="primair" onClick={()=>bewaar(s.id)}>Openingstijden opslaan</button></div>}
    </div>))}
    {weg && <Bevestig vraag={"Seizoen \""+weg.naam+"\" verwijderen?"}
      toelichting="De starttijden die dit seizoen al heeft aangemaakt blijven gewoon staan. Alleen de regel met de openingstijden verdwijnt."
      knop="Ja, verwijderen" onJa={()=>verwijderNu(weg)} onSluit={()=>setWeg(null)}/>}
    {f && <div className="fout">{f}</div>}
  </div>);
}

function Sluiting({baan,toon}){
  const [lijst,setLijst]=useState([]); const [datum,setDatum]=useState(iso(new Date()));
  const [reden,setReden]=useState(""); const [f,setF]=useState(null); const [laden,setLaden]=useState(true);
  const [waarschuwing,setWaarschuwing]=useState(null);  // melding van de database als er boekingen staan
  const laad=useCallback(async()=>{ if(!baan) return; setLaden(true);
    const r=await db.from("sluitingsdagen").select("*").eq("baan_id",baan).order("datum"); setLijst(r.data||[]); setLaden(false); },[baan]);
  useEffect(()=>{ laad(); },[laad]);
  // De database weigert een dag te sluiten waar nog boekingen op staan, en zegt erbij hoeveel het er
  // zijn. Dat is een belangrijke waarschuwing: forceren betekent dat die mensen nog steeds komen en
  // dat iemand ze zelf moet bellen. Dat hoort in een eigen paneel te staan en niet in een
  // browserdialoog die de pagina bevriest.
  async function sluit(forceer){ setF(null); setWaarschuwing(null);
    const r=await db.rpc("sluit_dag",{p_baan_id:baan,p_datum:datum,p_reden:reden.trim()||"Gesloten",p_forceer:!!forceer});
    if(r.error){ const m=fout(r.error); if(m.indexOf("Er staan nog")>=0){ setWaarschuwing(m); return; } setF(m); return; }
    toon(r.data.geblokkeerd+" starttijden geblokkeerd"); setReden(""); laad(); }
  async function openen(d){ const r=await db.rpc("open_dag",{p_baan_id:baan,p_datum:d}); if(r.error){ setF(fout(r.error)); return; } toon(r.data.vrijgegeven+" vrijgegeven"); laad(); }
  return (<div>
    <div className="kop"><h3>Sluitingsdagen</h3></div>
    <p className="bij" style={{marginTop:-4}}>Blokkeert alle starttijden van die dag in één keer.</p>
    <div className="kaart">
      <div className="rij"><div><label>Datum</label><input type="date" value={datum} onChange={e=>setDatum(e.target.value)}/></div>
        <div><label>Reden</label><input value={reden} onChange={e=>setReden(e.target.value)} placeholder="Onderhoud"/></div></div>
      <button className="primair" onClick={()=>sluit(false)}>Dag sluiten</button>{f && <div className="fout">{f}</div>}</div>
    <div className="kaart">
      {laden && <p className="bij" style={{margin:0}}>Laden…</p>}
      {!laden && lijst.length===0 && <p className="bij" style={{margin:0}}>Geen sluitingsdagen.</p>}
      {!laden && lijst.length>0 && <table className="tabel"><thead><tr><th>Datum</th><th>Reden</th><th></th></tr></thead>
        <tbody>{lijst.map(s=>(<tr key={s.id}><td style={{whiteSpace:"nowrap"}}>{kortDat(s.datum)}</td><td>{s.reden}</td>
          <td style={{textAlign:"right"}}><button className="mini" onClick={()=>openen(s.datum)}>Open</button></td></tr>))}</tbody></table>}</div>
    {waarschuwing && <Bevestig vraag="Er staan nog boekingen op deze dag"
      toelichting={waarschuwing+". Sluit je de dag toch, dan blijven die boekingen gewoon staan en komen die mensen nog steeds. Jij moet ze dan zelf bellen."}
      knop="Toch sluiten" onJa={()=>{ setWaarschuwing(null); sluit(true); }} onSluit={()=>setWaarschuwing(null)}/>}
  </div>);
}

function Tarieven({baan,toon}){
  const [regels,setRegels]=useState([]); const [types,setTypes]=useState([]); const [prod,setProd]=useState([]);
  const [laden,setLaden]=useState(true); const [f,setF]=useState(null); const [weg,setWeg]=useState(null);
  const laad=useCallback(async()=>{ if(!baan) return; setLaden(true);
    const r=await db.from("prijsregels").select("*").eq("baan_id",baan).order("prioriteit",{ascending:false});
    const t=await db.from("spelerstypes").select("*").order("code"); const p=await db.from("producten").select("*").order("code");
    if(r.error) setF(fout(r.error)); setRegels(r.data||[]); setTypes(t.data||[]); setProd(p.data||[]); setLaden(false); },[baan]);
  useEffect(()=>{ laad(); },[laad]);
  function wz(id,veld,val){ setRegels(regels.map(r=>r.id===id?Object.assign({},r,{[veld]:val}):r)); }
  function wisselDag(id,dag){ const r=regels.filter(x=>x.id===id)[0]; const h=r.dagen||[];
    const n=h.indexOf(dag)>=0?h.filter(d=>d!==dag):h.concat([dag]).sort(); wz(id,"dagen",n.length?n:null); }
  async function bewaar(r){ setF(null);
    const u=await db.from("prijsregels").update({omschrijving:r.omschrijving, dagen:r.dagen&&r.dagen.length?r.dagen:null, tijd_van:r.tijd_van||null, tijd_tot:r.tijd_tot||null,
      prijs_cent:Math.round(Number(String(r.prijs_euro!==undefined?r.prijs_euro:r.prijs_cent/100).replace(",","."))*100), prioriteit:Number(r.prioriteit), actief:r.actief}).eq("id",r.id);
    if(u.error){ setF(fout(u.error)); return; } toon("Tarief opgeslagen"); laad(); }
  async function voeg(){ if(!types.length||!prod.length) return;
    const r=await db.from("prijsregels").insert({product_id:prod[0].id,baan_id:baan,spelerstype_id:types[0].id,omschrijving:"Nieuw tarief",prijs_cent:0,prioriteit:0});
    if(r.error){ setF(fout(r.error)); return; } toon("Toegevoegd"); laad(); }
  async function verwijderNu(r){ setWeg(null);
    const d=await db.from("prijsregels").delete().eq("id",r.id); if(d.error){ setF(fout(d.error)); return; } toon("Verwijderd"); laad(); }
  const tn=id=>(types.filter(t=>t.id===id)[0]||{}).naam||"?";
  if(laden) return <div className="laden">Laden…</div>;
  return (<div>
    <div className="kop"><h3>Tarieven</h3><div className="acties"><button className="mini doe" onClick={voeg}>+ Tarief</button></div></div>
    <p className="bij" style={{marginTop:-4}}>Hoogste prioriteit die past wint. Geen dagen of tijden = altijd.</p>
    {regels.map(r=>(<div className="kaart" key={r.id}>
      <div className="kop"><h3>{tn(r.spelerstype_id)}</h3><span className={"pil"+(r.actief?" aan":"")}>{r.actief?"actief":"uit"}</span>
        <div className="acties"><button className="mini doe" onClick={()=>bewaar(r)}>Opslaan</button><button className="mini gevaar" onClick={()=>setWeg(r)}>Verwijder</button></div></div>
      <div className="rij"><div style={{flex:2}}><label>Omschrijving</label><input value={r.omschrijving||""} onChange={e=>wz(r.id,"omschrijving",e.target.value)}/></div>
        <div><label>Prijs €</label><input value={r.prijs_euro!==undefined?r.prijs_euro:(r.prijs_cent/100).toFixed(2)} onChange={e=>wz(r.id,"prijs_euro",e.target.value)}/></div>
        <div><label>Prio</label><input type="number" value={r.prioriteit} onChange={e=>wz(r.id,"prioriteit",e.target.value)}/></div></div>
      <label>Geldt op</label>
      <div className="dagkeuze">{[1,2,3,4,5,6,7].map(d=>(<button key={d} className={"dagknop"+((r.dagen||[]).indexOf(d)>=0?" aan":"")} onClick={()=>wisselDag(r.id,d)}>{DAG[d]}</button>))}
        {(r.dagen||[]).length===0 && <span className="bij" style={{margin:"6px 0 0 8px"}}>alle dagen</span>}</div>
      <div className="rij" style={{marginTop:10}}><div><label>Vanaf</label><input type="time" value={r.tijd_van||""} onChange={e=>wz(r.id,"tijd_van",e.target.value)}/></div>
        <div><label>Tot</label><input type="time" value={r.tijd_tot||""} onChange={e=>wz(r.id,"tijd_tot",e.target.value)}/></div>
        <div><label>Actief</label><select value={r.actief?"1":"0"} onChange={e=>wz(r.id,"actief",e.target.value==="1")}><option value="1">Ja</option><option value="0">Nee</option></select></div></div>
    </div>))}
    {weg && <Bevestig vraag="Tarief verwijderen?"
      toelichting={"\""+(weg.omschrijving||"zonder omschrijving")+"\" voor "+tn(weg.spelerstype_id)+", "+euro(weg.prijs_cent)+". Verwijderen is echt weg. Wil je hem alleen even uitzetten, kies dan Actief: Nee en sla op."}
      knop="Ja, verwijderen" onJa={()=>verwijderNu(weg)} onSluit={()=>setWeg(null)}/>}
    {f && <div className="fout">{f}</div>}
  </div>);
}

function Kaarthouders({toon}){
  const [lijst,setLijst]=useState([]); const [zoek,setZoek]=useState(""); const [laden,setLaden]=useState(true);
  const [f,setF]=useState(null); const [nieuw,setNieuw]=useState(false);
  const [n,setN]=useState({naam:"",email:"",telefoon:"",ngf:""});
  const [verkoop,setVerkoop]=useState(null); const [historie,setHistorie]=useState(null); const [verleng,setVerleng]=useState(null);
  const [opCode,setOpCode]=useState(false);
  const laad=useCallback(async()=>{ setLaden(true);
    const r=await db.from("leden").select("*").order("naam");
    const sk=await db.from("seizoenskaarten").select("*").eq("actief",true);
    // Het saldo stond eerder alleen achter de knop Historie. Deze derde uitvraag haalt de strippen
    // erbij zodat de balie het aantal ritten meteen in de lijst ziet. De tabel strippenkaarten is
    // voor een ingelogde medewerker al leesbaar via de policy kaarten_balie, dus dit vraagt niets
    // nieuws aan de database.
    const st=await db.from("strippenkaarten").select("lid_id,saldo,geldig_tot,actief").eq("actief",true);
    if(r.error) setF(fout(r.error));
    const kaartPer={}; (sk.data||[]).forEach(k=>{ if(!kaartPer[k.houder_id]) kaartPer[k.houder_id]=k; });
    const vandaagIso=iso(new Date());
    const strippenPer={};
    (st.data||[]).forEach(k=>{
      if(k.geldig_tot && k.geldig_tot < vandaagIso) return;   // verlopen kaarten tellen niet mee
      strippenPer[k.lid_id]=(strippenPer[k.lid_id]||0)+(k.saldo||0);
    });
    setLijst((r.data||[]).map(l=>Object.assign({},l,{seizoen:kaartPer[l.id]||null,strippen:strippenPer[l.id]||0})));
    setLaden(false); },[]);
  useEffect(()=>{ laad(); },[laad]);
  async function voeg(){ setF(null);
    const r=await db.from("leden").insert({naam:n.naam.trim(),email:n.email.trim(),telefoon:n.telefoon.trim()||null,ngf_nummer:n.ngf.trim()||null});
    if(r.error){ setF(fout(r.error)); return; } setNieuw(false); setN({naam:"",email:"",telefoon:"",ngf:""}); toon("Kaarthouder toegevoegd"); laad(); }
  const g=lijst.filter(l=>!zoek||(l.naam+" "+l.email).toLowerCase().indexOf(zoek.toLowerCase())>=0);
  const vandaag=iso(new Date());
  return (<div>
    <div className="kop"><h3>Kaarthouders</h3><div className="acties">
      <button className="mini" onClick={()=>setOpCode(true)}>Zoek op code</button>{" "}
      <button className="mini doe" onClick={()=>setNieuw(!nieuw)}>{nieuw?"Annuleren":"+ Persoon"}</button></div></div>
    <p className="bij" style={{marginTop:-4}}>Mensen met een seizoens- of strippenkaart. Voeg iemand toe, verkoop dan een kaart.</p>
    <p className="bij" style={{marginTop:-4}}>Kaarten die via de website in Recras gekocht zijn, zoek je op met Kaart op code of met Code kwijt? in het boekpaneel.</p>
    {nieuw && <div className="kaart">
      <div className="rij"><div><label>Naam</label><input value={n.naam} onChange={e=>setN(Object.assign({},n,{naam:e.target.value}))}/></div>
        <div><label>E-mail</label><input type="email" value={n.email} onChange={e=>setN(Object.assign({},n,{email:e.target.value}))}/></div></div>
      <div className="rij"><div><label>Telefoon</label><input value={n.telefoon} onChange={e=>setN(Object.assign({},n,{telefoon:e.target.value}))}/></div>
        <div><label>NGF</label><input value={n.ngf} onChange={e=>setN(Object.assign({},n,{ngf:e.target.value}))}/></div></div>
      <button className="primair" onClick={voeg} disabled={!n.naam.trim()||!n.email.trim()}>Toevoegen</button>
      <p className="bij" style={{margin:"10px 0 0"}}>Tip: gebruik het e-mailadres waarmee de persoon straks online inlogt, dan koppelt de seizoenskaart automatisch.</p></div>}
    <div className="kaart">
      <input value={zoek} onChange={e=>setZoek(e.target.value)} placeholder="Zoek op naam of e-mail" style={{marginBottom:12}}/>
      {laden && <p className="bij" style={{margin:0}}>Laden…</p>}
      {!laden && g.length===0 && <p className="bij" style={{margin:0}}>{lijst.length===0?"Nog niemand.":"Niemand gevonden."}</p>}
      {!laden && g.length>0 && <div className="tabelwrap"><table className="tabel">
        <thead><tr><th>Naam</th><th>Seizoenskaart</th><th>Strippen</th><th></th></tr></thead>
        <tbody>{g.map(l=>{ const geldig=l.seizoen&&l.seizoen.geldig_van<=vandaag&&l.seizoen.geldig_tot>=vandaag;
          return (<tr key={l.id}>
            <td style={{fontWeight:500}}>{l.naam}<div className="bij" style={{margin:0}}>{l.email}</div></td>
            <td>{geldig?<span className="pil aan">tot {kortDat(l.seizoen.geldig_tot)}</span>:l.seizoen?<span className="pil rood">verlopen</span>:<span className="pil">geen</span>}</td>
            <td>{l.strippen>0?<span className="pil aan">{l.strippen} over</span>:<span className="pil">0</span>}</td>
            <td style={{textAlign:"right",whiteSpace:"nowrap"}}>
              <button className="mini" onClick={()=>setHistorie(l)}>Historie</button>{" "}
              {l.seizoen && <button className="mini" onClick={()=>setVerleng(l)}>Verleng</button>}{" "}
              <button className="mini doe" onClick={()=>setVerkoop(l)}>Verkoop</button></td>
          </tr>);})}</tbody></table></div>}
      {f && <div className="fout">{f}</div>}
    </div>
    {verkoop && <VerkoopPaneel houder={verkoop} onSluit={()=>setVerkoop(null)} onKlaar={m=>{setVerkoop(null); toon(m); laad();}}/>}
    {verleng && <VerlengPaneel houder={verleng} onSluit={()=>setVerleng(null)} onKlaar={m=>{setVerleng(null); toon(m); laad();}}/>}
    {historie && <HistoriePaneel houder={historie} toon={toon} onSluit={()=>{setHistorie(null); laad();}}/>}
    {opCode && <CodePaneel onSluit={()=>setOpCode(false)} toon={toon} naLading={laad}/>}
  </div>);
}

// Blokkeren, weer vrijgeven en een nieuwe code uitgeven. Staat apart omdat het op twee plekken
// hangt: onder het zoekresultaat van een code, en per kaart in de historie van een houder. Alle
// drie de aanroepen gaan naar functies die al in de database staan; hier komt niets nieuws bij.
function CodeActies({code,status,kaartType,kaartId,onKlaar,toon}){
  const [bezig,setBezig]=useState(false); const [f,setF]=useState(null);
  const [nieuweCode,setNieuweCode]=useState(null); const [reden,setReden]=useState("");
  const [stuurVraag,setStuurVraag]=useState(false); const [stuurBezig,setStuurBezig]=useState(false);
  async function doe(functie,melding){
    setBezig(true); setF(null);
    const r=await db.rpc(functie,{p_code:code,p_reden:reden.trim()||null});
    setBezig(false);
    if(r.error){ setF(fout(r.error)); return; }
    if(functie==="heruitgeef_kaartcode" && r.data && r.data.nieuwe_code) setNieuweCode(r.data.nieuwe_code);
    if(toon) toon(melding);
    if(onKlaar) onKlaar();
  }
  // Stuurt de code opnieuw naar het bekende e-mailadres van de houder, via de edge function
  // stuur-bevestiging (staat al op staging, Enterprise gebouwd). db.functions.invoke stuurt vanuit
  // deze al ingelogde balieclient automatisch het token van de ingelogde medewerker mee. Het
  // e-mailadres zelf tonen we hier nergens: de functie geeft het niet terug.
  async function stuurOpnieuw(){
    setStuurVraag(false); setStuurBezig(true); setF(null);
    const r=await db.functions.invoke("stuur-bevestiging",{body:{kaart_type:kaartType,kaart_id:kaartId}});
    setStuurBezig(false);
    if(r.error){
      // functions.invoke gooit bij een niet-2xx-status een FunctionsHttpError. De statuscode zit
      // niet op r.error zelf, maar op r.error.context (de fetch Response) als .status.
      const status=r.error.context&&r.error.context.status;
      if(status===502){ setF("Mailen lukt nu niet (mailserver), de code is niet verstuurd"); return; }
      if(status===403){ setF("Geen toegang, log opnieuw in"); return; }
      if(status===404){ setF("Geen actieve code voor deze kaart, geef eerst een nieuwe code uit"); return; }
      if(status===400){ setF("Kaarttype onbekend, meld dit door"); return; }
      if(status===500){ setF("Er ging intern iets mis, probeer het nog eens"); return; }
      setF("Versturen is niet gelukt, probeer het nog eens"); return;
    }
    if(toon) toon("Verstuurd");
    if(onKlaar) onKlaar();
  }
  return (<div style={{marginTop:10}}>
    <label>Reden, mag leeg</label>
    <input value={reden} onChange={e=>setReden(e.target.value)} placeholder="Bijvoorbeeld: pasje kwijt"/>
    <div className="acties" style={{marginTop:8,display:"flex",gap:8,flexWrap:"wrap"}}>
      {status!=="geblokkeerd"
        ? <button className="mini" disabled={bezig} onClick={()=>doe("blokkeer_kaartcode","Code geblokkeerd")}>Blokkeren</button>
        : <button className="mini doe" disabled={bezig} onClick={()=>doe("deblokkeer_kaartcode","Code weer vrijgegeven")}>Weer vrijgeven</button>}
      <button className="mini" disabled={bezig} onClick={()=>doe("heruitgeef_kaartcode","Nieuwe code uitgegeven")}>Nieuwe code</button>
      {kaartType && kaartId && <button className="mini" disabled={stuurBezig} onClick={()=>setStuurVraag(true)}>{stuurBezig?"Bezig…":"Code opnieuw sturen"}</button>}
    </div>
    <p className="bij" style={{margin:"6px 0 0"}}>Blokkeren zet de code stil, de kaart en het saldo blijven staan. Nieuwe code trekt deze code in en maakt er een verse voor dezelfde kaart.</p>
    {nieuweCode && <div className="ok" style={{marginTop:8}}>Nieuwe code: <strong style={{letterSpacing:1}}>{nieuweCode}</strong>. Schrijf hem over voor de kaarthouder, hij gaat niet vanzelf per mail.</div>}
    {f && <div className="fout">{f}</div>}
    {stuurVraag && <Bevestig vraag="Stuur de code naar het bekende e-mailadres van de houder?"
      knop="Ja, versturen" onJa={stuurOpnieuw} onSluit={()=>setStuurVraag(false)}/>}
  </div>);
}

function CodePaneel({onSluit,toon,naLading}){
  const [code,setCode]=useState(""); const [data,setData]=useState(null);
  const [f,setF]=useState(null); const [bezig,setBezig]=useState(false);
  const [recras,setRecras]=useState(null); // ronde 2: Recras-kaart uit recras-balie zoek_code
  async function zoek(){
    setBezig(true); setF(null); setData(null); setRecras(null);
    // Ronde 2 (bouwspec 4.4 punt 1): 15 tekens is een Recras-kaart. Blokkeren en nieuwe code blijven
    // alleen voor ons eigen kaartsysteem.
    if(baliecodeSoort(code)==="recras"){
      const u=await recrasBalie({actie:"zoek_code", code:code.trim()});
      setBezig(false);
      if(u.http!==200||!u.d){ setF(recrasBalieFout(u)); return; }
      if(!u.d.gevonden){ setF(RECRAS_BALIE_TEKST.onbekend); return; }
      setRecras(u.d.kaarten[0]); return;
    }
    const r=await db.rpc("zoek_kaart_op_code",{p_code:code.trim()});
    setBezig(false);
    if(r.error){ setF(fout(r.error)); return; }
    setData(r.data);
  }
  return (<div className="scrim" onClick={e=>e.target===e.currentTarget&&onSluit()}>
    <div className="paneel"><div className="greep"/><h2>Kaart op code</h2>
      <p className="sub">Typ de code over van het pasje of uit de mail van de kaarthouder.</p>
      <label>Code</label>
      <input value={code} onChange={e=>setCode(e.target.value)} placeholder="ABCD-12345 of ABCDE-FGHIJ-KLMNO"
        style={{letterSpacing:1,textTransform:"uppercase"}}
        onKeyDown={e=>{ if(e.key==="Enter"&&code.trim()) zoek(); }}/>
      <button className="primair" onClick={zoek} disabled={bezig||!code.trim()}>{bezig?"Zoeken…":"Zoeken"}</button>
      {f && <div className="fout">{f}</div>}
      {data && <div className="kaart" style={{marginTop:14}}>
        <div className="kop" style={{marginBottom:6}}>
          <h3 style={{fontSize:15}}>{data.houder}</h3>
          <span className={"pil"+(data.code_status==="actief"?" aan":" rood")}>{data.code_status==="actief"?"actief":"geblokkeerd"}</span>
        </div>
        <table className="tabel"><tbody>
          <tr><td>Soort</td><td style={{textAlign:"right"}}>{data.kaart_type==="strippenkaart"?"Strippenkaart":"Seizoenskaart"}</td></tr>
          <tr><td>Naam kaart</td><td style={{textAlign:"right"}}>{data.kaarttype||data.naam||"geen"}</td></tr>
          {data.kaart_type==="strippenkaart"
            ? <tr><td>Saldo</td><td style={{textAlign:"right",fontWeight:700}}>{data.saldo} ritten</td></tr>
            : <tr><td>Geldig van</td><td style={{textAlign:"right"}}>{data.geldig_van?kortDat(data.geldig_van):"onbekend"}</td></tr>}
          <tr><td>Geldig tot</td><td style={{textAlign:"right"}}>{data.geldig_tot?kortDat(data.geldig_tot):"geen einddatum"}</td></tr>
          <tr><td>Code</td><td style={{textAlign:"right",letterSpacing:1,fontWeight:700}}>{data.code}</td></tr>
        </tbody></table>
        <CodeActies code={data.code} status={data.code_status} kaartType={data.kaart_type} kaartId={data.kaart_id} toon={toon}
          onKlaar={()=>{ zoek(); if(naLading) naLading(); }}/>
      </div>}
      {recras && <div className="kaart" style={{marginTop:14}}>
        <div className="kop" style={{marginBottom:6}}>
          <h3 style={{fontSize:15}}>{recras.houder||"Onbekende houder"}</h3>
          <span className={"pil"+(recras.staat==="bruikbaar"?" aan":" rood")}>{recras.staat}</span>
        </div>
        <table className="tabel"><tbody>
          <tr><td>Soort</td><td style={{textAlign:"right"}}>{recras.soort==="abonnement"?"Abonnement (Recras)":"Strippenkaart (Recras)"}</td></tr>
          <tr><td>Naam kaart</td><td style={{textAlign:"right"}}>{recras.kaartnaam}</td></tr>
          <tr><td>E-mail houder</td><td style={{textAlign:"right"}}>{recras.houder_email||"onbekend"}</td></tr>
          {recras.soort==="strippenkaart"
            ? <tr><td>Strippen</td><td style={{textAlign:"right",fontWeight:700}}>{recras.strippen_over} van {recras.strippen_totaal}</td></tr>
            : null}
          <tr><td>Geldig tot</td><td style={{textAlign:"right"}}>{recras.geldig_tot?kortDat(recras.geldig_tot):"geen einddatum"}</td></tr>
          <tr><td>Aantal keer gebruikt</td><td style={{textAlign:"right"}}>{recras.aantal_keer_gebruikt}</td></tr>
          <tr><td>Code</td><td style={{textAlign:"right",letterSpacing:1,fontWeight:700}}>{recras.code}</td></tr>
        </tbody></table>
        <p className="bij" style={{margin:"10px 0 0"}}>Deze kaart staat in Recras. Blokkeren of een nieuwe code maken doe je in Recras, bij Tegoedbonnen.</p>
      </div>}
      <button className="sluit" onClick={onSluit}>Sluiten</button>
    </div></div>);
}

function VerkoopPaneel({houder,onSluit,onKlaar}){
  const [soort,setSoort]=useState("seizoen"); const [naam,setNaam]=useState("Seizoenskaart");
  const [van,setVan]=useState(iso(new Date())); const [tot,setTot]=useState(iso(new Date(Date.now()+90*864e5)));
  const [prijs,setPrijs]=useState("250,00"); const [kaarttypes,setKaarttypes]=useState([]); const [kt,setKt]=useState("");
  const [f,setF]=useState(null); const [bezig,setBezig]=useState(false);
  useEffect(()=>{ db.from("kaarttypes").select("*").eq("actief",true).order("beurten").then(r=>{ setKaarttypes(r.data||[]); if(r.data&&r.data.length) setKt(r.data[0].id); }); },[]);
  async function verkoop(){ setBezig(true); setF(null);
    if(soort==="seizoen"){
      const r=await db.rpc("verkoop_seizoenskaart",{p_houder_id:houder.id,p_naam:naam.trim(),p_van:van,p_tot:tot,p_prijs_cent:Math.round(Number(prijs.replace(",","."))*100)});
      if(r.error){ setF(fout(r.error)); setBezig(false); return; } onKlaar("Seizoenskaart verkocht aan "+houder.naam);
    } else { const r=await db.rpc("verkoop_strippenkaart",{p_lid_id:houder.id,p_kaarttype_id:kt});
      if(r.error){ setF(fout(r.error)); setBezig(false); return; } onKlaar("Strippenkaart verkocht aan "+houder.naam); } }
  return (<div className="scrim" onClick={e=>e.target===e.currentTarget&&onSluit()}>
    <div className="paneel"><div className="greep"/><h2>Kaart verkopen</h2><p className="sub">Aan {houder.naam}</p>
      <div className="dagkeuze" style={{marginBottom:6}}>
        <button className={"dagknop"+(soort==="seizoen"?" aan":"")} style={{minWidth:110}} onClick={()=>setSoort("seizoen")}>Seizoenskaart</button>
        <button className={"dagknop"+(soort==="strip"?" aan":"")} style={{minWidth:110}} onClick={()=>setSoort("strip")}>Strippenkaart</button></div>
      {soort==="seizoen"?<div>
        <label>Omschrijving</label><input value={naam} onChange={e=>setNaam(e.target.value)} placeholder="Zomerseizoen 2026"/>
        <div className="rij"><div><label>Van</label><input type="date" value={van} onChange={e=>setVan(e.target.value)}/></div>
          <div><label>Tot en met</label><input type="date" value={tot} onChange={e=>setTot(e.target.value)}/></div></div>
        <label>Prijs €</label><input value={prijs} onChange={e=>setPrijs(e.target.value)}/>
        <div className="ok">Binnen deze periode speelt {houder.naam.split(" ")[0]} onbeperkt gratis, alleen voor zichzelf.</div></div>
      :<div><label>Type strippenkaart</label>
        <select value={kt} onChange={e=>setKt(e.target.value)}>{kaarttypes.map(t=><option key={t.id} value={t.id}>{t.naam}, {t.beurten} beurten, {euro(t.prijs_cent)}</option>)}</select>
        <div className="ok">Strepen zijn ook voor medespelers te gebruiken.</div></div>}
      {f && <div className="fout">{f}</div>}
      <button className="primair" onClick={verkoop} disabled={bezig||(soort==="strip"&&!kt)}>{bezig?"Bezig…":"Verkoop vastleggen"}</button>
      <button className="sluit" onClick={onSluit}>Annuleren</button>
    </div></div>);
}

function VerlengPaneel({houder,onSluit,onKlaar}){
  const [van,setVan]=useState(iso(new Date())); const [tot,setTot]=useState(iso(new Date(Date.now()+90*864e5)));
  const [prijs,setPrijs]=useState("250,00"); const [f,setF]=useState(null); const [bezig,setBezig]=useState(false);
  async function go(){ setBezig(true); setF(null);
    const r=await db.rpc("verleng_seizoenskaart",{p_houder_id:houder.id,p_van:van,p_tot:tot,p_prijs_cent:Math.round(Number(prijs.replace(",","."))*100)});
    if(r.error){ setF(fout(r.error)); setBezig(false); return; } onKlaar("Seizoenskaart verlengd voor "+houder.naam); }
  return (<div className="scrim" onClick={e=>e.target===e.currentTarget&&onSluit()}>
    <div className="paneel"><div className="greep"/><h2>Seizoenskaart verlengen</h2><p className="sub">Voor {houder.naam}, nieuwe periode</p>
      <div className="rij"><div><label>Van</label><input type="date" value={van} onChange={e=>setVan(e.target.value)}/></div>
        <div><label>Tot en met</label><input type="date" value={tot} onChange={e=>setTot(e.target.value)}/></div></div>
      <label>Prijs €</label><input value={prijs} onChange={e=>setPrijs(e.target.value)}/>
      {f && <div className="fout">{f}</div>}
      <button className="primair" onClick={go} disabled={bezig}>{bezig?"Bezig…":"Verlenging vastleggen"}</button>
      <button className="sluit" onClick={onSluit}>Annuleren</button>
    </div></div>);
}

function HistoriePaneel({houder,onSluit,toon}){
  const [data,setData]=useState(null); const [f,setF]=useState(null);
  // kaart_historie geeft de codes zelf niet terug. Ze staan wel in kaartcodes, en die tabel is voor
  // een ingelogde medewerker leesbaar via de policy kaartcodes_balie. Dit is de route voor iemand
  // die zijn code KWIJT is: de balie zoekt hem op naam op en ziet hier welke code erbij hoort.
  const [codes,setCodes]=useState({});
  const [openCode,setOpenCode]=useState(null);
  const laadCodes=useCallback(async(d)=>{
    const stripIds=(d.strippenkaarten||[]).map(k=>k.id);
    const seizIds=(d.seizoenskaarten||[]).map(k=>k.id);
    if(stripIds.length===0 && seizIds.length===0){ setCodes({}); return; }
    const r=await db.from("kaartcodes").select("code,status,kaart_type,strippenkaart_id,seizoenskaart_id").neq("status","ingetrokken");
    const per={};
    (r.data||[]).forEach(c=>{
      const sleutel=c.kaart_type==="strippenkaart"?c.strippenkaart_id:c.seizoenskaart_id;
      if(!sleutel) return;
      if(stripIds.indexOf(sleutel)<0 && seizIds.indexOf(sleutel)<0) return;
      per[sleutel]=c;
    });
    setCodes(per);
  },[]);
  const laadAlles=useCallback(async()=>{
    const r=await db.rpc("kaart_historie",{p_lid_id:houder.id});
    if(r.error){ setF(fout(r.error)); return; }
    setData(r.data); laadCodes(r.data);
  },[houder,laadCodes]);
  useEffect(()=>{ laadAlles(); },[laadAlles]);
  function CodeRegel({kaartId}){
    const c=codes[kaartId];
    if(!c) return <p className="bij" style={{margin:"6px 0 0"}}>Geen code bij deze kaart.</p>;
    return (<div style={{marginTop:8}}>
      <div style={{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap"}}>
        <span style={{letterSpacing:1,fontWeight:700}}>{c.code}</span>
        <span className={"pil"+(c.status==="actief"?" aan":" rood")}>{c.status==="actief"?"actief":"geblokkeerd"}</span>
        <button className="mini" onClick={()=>setOpenCode(openCode===c.code?null:c.code)}>
          {openCode===c.code?"Sluiten":"Code beheren"}</button>
      </div>
      {openCode===c.code && <CodeActies code={c.code} status={c.status} kaartType={c.kaart_type} kaartId={kaartId} toon={toon} onKlaar={laadAlles}/>}
    </div>);
  }
  return (<div className="scrim" onClick={e=>e.target===e.currentTarget&&onSluit()}>
    <div className="paneel"><div className="greep"/><h2>{houder.naam}</h2><p className="sub">Kaarten en verloop</p>
      {f && <div className="fout">{f}</div>}
      {!data && !f && <div className="laden">Laden…</div>}
      {data && <div>
        {data.seizoenskaarten.length===0 && data.strippenkaarten.length===0 && <p className="bij">Nog geen kaarten verkocht.</p>}
        {data.seizoenskaarten.length>0 && <div><label>Seizoenskaarten</label>
          {data.seizoenskaarten.map((s,i)=>(<div className="kaart" key={i} style={{padding:12}}>
            <div className="kop" style={{marginBottom:2}}><h3 style={{fontSize:14}}>{s.naam}</h3>
              <span className={"pil"+(s.actief&&s.geldig_tot>=iso(new Date())?" aan":"")}>{kortDat(s.geldig_van)} tot {kortDat(s.geldig_tot)}</span></div>
            <p className="bij" style={{margin:0}}>{euro(s.prijs_cent)}</p>
            <CodeRegel kaartId={s.id}/></div>))}</div>}
        {data.strippenkaarten.length>0 && <div><label>Strippenkaarten</label>
          {data.strippenkaarten.map((k,i)=>(<div className="kaart" key={i} style={{padding:12}}>
            <div className="kop" style={{marginBottom:6}}><h3 style={{fontSize:14}}>{k.naam}</h3>
              <span className="pil aan">{k.saldo} over</span>{k.geldig_tot && <span className="pil">tot {kortDat(k.geldig_tot)}</span>}</div>
            {k.mutaties.length>0 && <div className="tabelwrap"><table className="tabel"><tbody>
              {k.mutaties.slice(0,8).map((m,j)=>(<tr key={j}><td>{m.aantal>0?"+"+m.aantal:m.aantal}</td><td>{m.reden}</td>
                <td style={{textAlign:"right",color:"var(--muted)",whiteSpace:"nowrap"}}>{momentTekst(m.moment)}</td></tr>))}
            </tbody></table></div>}
            <CodeRegel kaartId={k.id}/></div>))}</div>}
      </div>}
      <button className="sluit" onClick={onSluit}>Sluiten</button>
    </div></div>);
}

function Types({toon}){
  const [lijst,setLijst]=useState([]); const [laden,setLaden]=useState(true); const [f,setF]=useState(null);
  const laad=useCallback(async()=>{ setLaden(true); const r=await db.from("spelerstypes").select("*").order("code"); setLijst(r.data||[]); setLaden(false); },[]);
  useEffect(()=>{ laad(); },[laad]);
  function wz(id,veld,val){ setLijst(lijst.map(r=>r.id===id?Object.assign({},r,{[veld]:val}):r)); }
  async function bewaar(r){ setF(null);
    const u=await db.from("spelerstypes").update({naam:r.naam,boekingsvenster_dagen:Number(r.boekingsvenster_dagen),max_open_boekingen:Number(r.max_open_boekingen),actief:r.actief}).eq("id",r.id);
    if(u.error){ setF(fout(u.error)); return; } toon("Opgeslagen"); laad(); }
  if(laden) return <div className="laden">Laden…</div>;
  return (<div>
    <div className="kop"><h3>Spelerstypes</h3></div>
    <p className="bij" style={{marginTop:-4}}>Boekingsvenster = dagen vooruit online. Balie kent die grens niet.</p>
    {lijst.map(r=>(<div className="kaart" key={r.id}>
      <div className="kop"><h3>{r.code}</h3>{r.is_lid && <span className="pil aan">kaarthouder</span>}
        <div className="acties"><button className="mini doe" onClick={()=>bewaar(r)}>Opslaan</button></div></div>
      <div className="rij"><div style={{flex:2}}><label>Naam</label><input value={r.naam} onChange={e=>wz(r.id,"naam",e.target.value)}/></div>
        <div><label>Dagen</label><input type="number" min="0" value={r.boekingsvenster_dagen} onChange={e=>wz(r.id,"boekingsvenster_dagen",e.target.value)}/></div>
        <div><label>Max open</label><input type="number" min="1" value={r.max_open_boekingen} onChange={e=>wz(r.id,"max_open_boekingen",e.target.value)}/></div></div>
    </div>))}
    {f && <div className="fout">{f}</div>}
  </div>);
}

function Rapportage({ baan, toon }){
  const [van,setVan]=useState(iso(new Date(Date.now()-29*864e5)));
  const [tot,setTot]=useState(iso(new Date()));
  const [data,setData]=useState(null);
  const [laden,setLaden]=useState(false);
  const [foutmsg,setFoutmsg]=useState(null);

  async function draai(v,t){
    if(!baan) return;
    setLaden(true); setFoutmsg(null);
    const r=await db.rpc("rapportage",{p_baan_id:baan,p_van:v,p_tot:t});
    if(r.error){ setFoutmsg(fout(r.error)); setLaden(false); return; }
    setData(r.data); setLaden(false);
  }

  useEffect(()=>{ if(baan) draai(van,tot); },[baan]);

  function snel(dagen){
    const t=iso(new Date());
    const v=iso(new Date(Date.now()-(dagen-1)*864e5));
    setVan(v); setTot(t); draai(v,t);
  }

  const k = data && data.kaarten;

  // Verplaatsingen-teller: het veld bestaat vandaag (22 augustus 2026) nog niet in de databasefunctie
  // `rapportage`, zie klanten/up-events/kennis/BOUWOPDRACHT-ENTERPRISE-verplaatsen-en-teller-20260822.md.
  // Zolang `totaal_verplaatsingen` ontbreekt (undefined of null) toont dit scherm "nog niet beschikbaar"
  // in plaats van nul: nul en onbekend zijn twee verschillende dingen, en dat verschil moet zichtbaar
  // blijven. Zodra Enterprise het veld gaat teruggeven, verschijnt de teller vanzelf, zonder dat dit
  // bestand opnieuw aangepast hoeft te worden.
  const verplaatsingenBeschikbaar = data && data.totaal_verplaatsingen !== undefined && data.totaal_verplaatsingen !== null;
  const verplaatsingenWaarde = verplaatsingenBeschikbaar ? data.totaal_verplaatsingen : "nog niet beschikbaar";
  const gastBalieBekend = verplaatsingenBeschikbaar
    && data.verplaatsingen_gast !== undefined && data.verplaatsingen_gast !== null
    && data.verplaatsingen_balie !== undefined && data.verplaatsingen_balie !== null;

  return (
    <div>
      <div className="kop"><h3>Rapportage</h3></div>
      <p className="bij" style={{marginTop:-6}}>
        Omzet, spelers en kaartverkoop over een periode. Kies zelf een bereik of gebruik een snelknop.
        Dit scherm zit achter het wachtwoord, want de omzet hoeft niet de hele dag op een baliescherm
        te staan. De omzet van vandaag staat onder Vandaag, en per dag in de tabel onderaan.
      </p>

      <div className="kaart">
        <div className="rij">
          <div><label>Van</label><input type="date" value={van} onChange={e=>setVan(e.target.value)}/></div>
          <div><label>Tot en met</label><input type="date" value={tot} onChange={e=>setTot(e.target.value)}/></div>
        </div>
        <div style={{display:"flex",gap:6,flexWrap:"wrap",marginTop:4}}>
          <button className="mini doe" onClick={()=>draai(van,tot)}>Toon</button>
          {/* Vandaag als eerste snelknop. De dagomzet stond eerst boven de tee sheet; die is daar weg
              en dit is de plek waar je hem nu in één klik terugvindt. */}
          <button className="mini" onClick={()=>snel(1)}>Vandaag</button>
          <button className="mini" onClick={()=>snel(7)}>Laatste 7 dagen</button>
          <button className="mini" onClick={()=>snel(30)}>Laatste 30 dagen</button>
          <button className="mini" onClick={()=>snel(90)}>Laatste 90 dagen</button>
        </div>
        {foutmsg && <div className="fout">{foutmsg}</div>}
      </div>

      {laden && <div className="laden">Rapport samenstellen…</div>}

      {!laden && data &&
        <div>
          <div className="stats">
            <div className="stat"><div className="k">Spelers</div><div className="v">{data.totaal_spelers}</div></div>
            <div className="stat"><div className="k">Boekingen</div><div className="v">{data.totaal_boekingen}</div></div>
            <div className="stat omzet"><div className="k">Omzet boekingen</div><div className="v">{euro(data.totaal_omzet_cent)}</div></div>
            <div className="stat">
              <div className="k">Verplaatsingen</div>
              <div className="v" style={!verplaatsingenBeschikbaar ? {fontSize:14,fontWeight:400,color:"var(--up-tekst-sub)"} : undefined}>
                {verplaatsingenWaarde}
              </div>
              {gastBalieBekend &&
                <div className="bij" style={{marginTop:2}}>
                  gast {data.verplaatsingen_gast}, balie {data.verplaatsingen_balie}
                </div>}
            </div>
          </div>

          <div className="kaart">
            <div className="kop"><h3>Kaartverkoop in deze periode</h3></div>
            <table className="tabel">
              <thead><tr><th>Soort</th><th>Aantal</th><th style={{textAlign:"right"}}>Omzet</th></tr></thead>
              <tbody>
                <tr><td>Seizoenskaarten</td><td>{k.seizoenskaarten}</td>
                  <td style={{textAlign:"right"}}>{euro(k.seizoenskaart_omzet_cent)}</td></tr>
                <tr><td>Strippenkaarten</td><td>{k.strippenkaarten}</td>
                  <td style={{textAlign:"right"}}>{euro(k.strippenkaart_omzet_cent)}</td></tr>
                <tr style={{fontWeight:700}}><td>Totaal kaarten</td>
                  <td>{k.seizoenskaarten+k.strippenkaarten}</td>
                  <td style={{textAlign:"right"}}>{euro(k.seizoenskaart_omzet_cent+k.strippenkaart_omzet_cent)}</td></tr>
              </tbody>
            </table>
          </div>

          <div className="kaart">
            <div className="kop"><h3>Per dag</h3></div>
            {(!data.per_dag||data.per_dag.length===0)
              ? <p className="bij" style={{margin:0}}>Geen boekingen in deze periode.</p>
              : <div className="tabelwrap"><table className="tabel">
                  <thead><tr><th>Datum</th><th>Spelers</th><th>Boekingen</th><th style={{textAlign:"right"}}>Omzet</th></tr></thead>
                  <tbody>
                    {data.per_dag.map(d=>(
                      <tr key={d.datum}>
                        <td style={{whiteSpace:"nowrap"}}>{kortDat(d.datum)}</td>
                        <td>{d.spelers}</td><td>{d.boekingen}</td>
                        <td style={{textAlign:"right"}}>{euro(d.omzet_cent)}</td>
                      </tr>))}
                  </tbody>
                </table></div>}
          </div>
        </div>}
    </div>
  );
}

