// App shell: header with angled tabs, role toggle, menu, settings, persistence. const { useState, useEffect } = React; const DEFAULT_CONFIG = { name: 'Shalom Bible Baptist Mission', logo: 'Shalom logo', welcomeBg: 'Plants.png', admins: 'Admin User 1, Admin User 2, Admin User 3', users: 'User 1, User 2, User 3, User 4, User 5, User 6', themeId: 'warm-stone', slidesName: 'The Salvation', deckName: 'The Salvation', ytUser: 'sample@gmail.com', ytPass: '12345678abc', emailjsKey: '', emailjsService: '', emailjsTemplate: '', slideImages: [], hymns: window.DEMO_HYMNS.map(h=>({ ...h })), prayer: JSON.parse(JSON.stringify(window.DEMO_PRAYER)), lastUpdate: 'Feb 1, 2026' }; function loadConfig(){ try{ const raw = localStorage.getItem('cwa-config'); if(raw){ return { ...DEFAULT_CONFIG, ...JSON.parse(raw) }; } }catch(e){} return JSON.parse(JSON.stringify(DEFAULT_CONFIG)); } const TABS = ['Slides','Bible','Hymns','Prayer']; function App(){ const themes = window.CHURCH_THEMES; const [config, setConfig] = useState(loadConfig); const [tab, setTab] = useState(()=> localStorage.getItem('cwa-tab') || 'Slides'); const [accounts, setAccounts] = useState(()=> window.loadAccounts()); const [currentUser, setCurrentUser] = useState(()=>{ const a = window.loadAccounts(); return a ? window.loadSession(a) : null; }); const [menu, setMenu] = useState(false); const [settings, setSettings] = useState(false); const [fs, setFs] = useState(false); const [fsPrompt, setFsPrompt] = useState(()=> !localStorage.getItem('cwa-fsdismiss')); // ----- Full-screen "focus" mode ----- function toggleFs(){ const d = document; if(!d.fullscreenElement){ const el = d.documentElement; const req = el.requestFullscreen || el.webkitRequestFullscreen || el.msRequestFullscreen; if(req) req.call(el).catch(()=>{}); }else{ (d.exitFullscreen || d.webkitExitFullscreen || d.msExitFullscreen).call(d); } } function dismissPrompt(){ setFsPrompt(false); localStorage.setItem('cwa-fsdismiss','1'); } useEffect(()=>{ const on = ()=> setFs(!!document.fullscreenElement); document.addEventListener('fullscreenchange', on); document.addEventListener('webkitfullscreenchange', on); // keyboard: F toggles, Esc exits (browser handles esc natively) const key = (e)=>{ if((e.key==='f'||e.key==='F') && !/input|textarea/i.test(e.target.tagName) && !e.target.isContentEditable){ toggleFs(); } }; window.addEventListener('keydown', key); return ()=>{ document.removeEventListener('fullscreenchange', on); document.removeEventListener('webkitfullscreenchange', on); window.removeEventListener('keydown', key); }; }, []); // apply theme whenever it changes useEffect(()=>{ const t = themes.find(x=>x.id===config.themeId) || themes[0]; window.applyTheme(t); }, [config.themeId]); useEffect(()=>{ try{ localStorage.setItem('cwa-config', JSON.stringify(config)); } catch(e){ // uploaded slide images can exceed the localStorage quota — persist everything else try{ const { slideImages, ...rest } = config; localStorage.setItem('cwa-config', JSON.stringify(rest)); }catch(e2){} } }, [config]); useEffect(()=>{ localStorage.setItem('cwa-tab', tab); }, [tab]); const today = ()=> new Date().toLocaleDateString('en-US',{ month:'short', day:'numeric', year:'numeric' }); const setPrayer = (updater)=> setConfig(c=>({ ...c, prayer: typeof updater==='function' ? updater(c.prayer) : updater })); const touchPrayer = ()=> setConfig(c=>({ ...c, lastUpdate: today() })); function saveSettings(draft){ setConfig(c=>({ ...c, ...draft })); setSettings(false); } function onAuth(a, user){ setAccounts(a); setCurrentUser(user); } function logout(){ window.setSession(null); setCurrentUser(null); setMenu(false); setSettings(false); } const role = currentUser ? currentUser.role : 'user'; const isAdmin = window.isAdminRole(role); // theme is applied above; show login until authenticated if(!currentUser){ return ; } return (
{TABS.map(t=>( ))}
{config.name}
{window.roleLabel(role)} {currentUser.email}
{menu && (
setMenu(false)}>
{currentUser.email} · {window.roleLabel(role)}
{isAdmin && ( )}
)}
{tab==='Slides' && } {tab==='Bible' && } {tab==='Hymns' && } {tab==='Prayer' && }
{settings && ( setSettings(false)} /> )} {fsPrompt && !fs && (
Enter full screen for a focused, distraction-free view.
)}
); } ReactDOM.createRoot(document.getElementById('root')).render();