/* Parent → School Calendar & Events: month strip, upcoming events, RSVP. */ function CalendarScreen({ onNav, onBack }) { const TYPES = { event: { tint:'var(--gold-100)', ic:'var(--gold-600)', icon:'party-popper' }, academic: { tint:'var(--blue-100)', ic:'var(--blue-500)', icon:'graduation-cap' }, holiday: { tint:'var(--success-100)', ic:'var(--success-500)', icon:'palmtree' }, off: { tint:'var(--success-100)', ic:'var(--success-500)', icon:'palmtree' }, sport: { tint:'var(--info-100)', ic:'var(--info-500)', icon:'volleyball' }, early: { tint:'var(--danger-100)', ic:'var(--danger-500)', icon:'clock' }, test: { tint:'var(--danger-100)', ic:'var(--danger-500)', icon:'file-pen' }, due: { tint:'var(--blue-100)', ic:'var(--blue-500)', icon:'clipboard-list' }, }; const SHARED_EVENTS = [ { id:'e-due', type:'due', title:'Ecosystem Lab Report due', when:'Fri, Jun 6 · 11:59 PM', where:'Science' }, { id:'e-test', type:'test', title:'Math Quiz — Fractions', when:'Tue, Jun 9 · 9:00 AM', where:'Rm 118' }, { id:'e-fair', type:'event', title:'Spring Science Fair', when:'Thu, Jun 12 · 6:00 PM', where:'Main Gymnasium' }, { id:'e-erd', type:'early', title:'Early Release Day', when:'Fri, Jun 13 · 1:00 PM', where:'Storm schedule' }, { id:'e-soc', type:'sport', title:'6th Grade vs. Cinco Ranch', when:'Sat, Jun 14 · 10:00 AM', where:'Soccer Field 2' }, { id:'e-rc', type:'academic', title:'End-of-Year Report Cards', when:'Mon, Jun 16', where:'Posted in app' }, { id:'e-sum', type:'off', title:'Summer Break Begins', when:'Fri, Jun 20', where:'No school' }, ]; const RSVP_TYPES = { event:true, sport:true }; const [events, setEvents] = React.useState(SHARED_EVENTS); React.useEffect(() => { const read = () => { try { let a = JSON.parse(localStorage.getItem('jl_events') || 'null'); if (!a) { a = SHARED_EVENTS; localStorage.setItem('jl_events', JSON.stringify(a)); } setEvents(a); } catch(e){} }; read(); const onStore = (e) => { if (e.key === 'jl_events') read(); }; window.addEventListener('storage', onStore); const iv = setInterval(read, 1500); return () => { window.removeEventListener('storage', onStore); clearInterval(iv); }; }, []); const [rsvp, setRsvp] = React.useState({}); const week = [ { d:'8', day:'MON', dot:null }, { d:'9', day:'TUE', dot:'var(--danger-500)' }, { d:'10', day:'WED', dot:null }, { d:'11', day:'THU', dot:'var(--gold-500)', today:true }, { d:'12', day:'FRI', dot:'var(--gold-500)' }, { d:'13', day:'SAT', dot:'var(--info-500)' }, { d:'14', day:'SUN', dot:null }, ]; const toggle = (id) => { setRsvp(r => { const n = { ...r, [id]: !r[id] }; jlToast(n[id] ? 'RSVP confirmed — see you there' : 'RSVP cancelled', { icon: n[id]?'calendar-check':'calendar-x' }); return n; }); }; return (
{/* month strip */}
June 2026
{week.map(w => (
{w.day} {w.d}
))}
{/* upcoming */} jlToast('Synced to your phone calendar', { icon:'calendar-plus' })} style={{ display:'inline-flex', alignItems:'center', gap:5, fontSize:12, fontWeight:700, color:'var(--blue-500)', cursor:'pointer' }}>{jlT('a_sync')}}>{jlT('l_upcoming')}
{events.map(e => { const t = TYPES[e.type] || TYPES.event; const on = !!rsvp[e.id]; const canRsvp = !!RSVP_TYPES[e.type]; return (
{e.title}
{e.when}
{e.where}
{canRsvp && ( )}
); })}
); } const calNav = { width:32, height:32, borderRadius:9, border:'1px solid var(--gray-200)', background:'#fff', display:'flex', alignItems:'center', justifyContent:'center', cursor:'pointer' }; Object.assign(window, { CalendarScreen });