Created Turnpike, event attendee and volunteer management
Built after prototype, Traverse, an attendee and volunteer list maintainer.
This commit is contained in:
commit
5d56ba8112
59 changed files with 8663 additions and 0 deletions
102
frontend/src/App.svelte
Normal file
102
frontend/src/App.svelte
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import { getSession, clearSession } from './db.js'
|
||||
import { syncPull, startSSE, startSyncLoop } from './sync.js'
|
||||
import Login from './pages/Login.svelte'
|
||||
import Dashboard from './pages/Dashboard.svelte'
|
||||
import Attendees from './pages/Attendees.svelte'
|
||||
import Volunteers from './pages/Volunteers.svelte'
|
||||
import Departments from './pages/Departments.svelte'
|
||||
import Shifts from './pages/Shifts.svelte'
|
||||
import Users from './pages/Users.svelte'
|
||||
import Import from './pages/Import.svelte'
|
||||
import Kiosk from './pages/Kiosk.svelte'
|
||||
import GateUI from './pages/GateUI.svelte'
|
||||
import ScheduleBoard from './pages/ScheduleBoard.svelte'
|
||||
import Settings from './pages/Settings.svelte'
|
||||
import Nav from './components/Nav.svelte'
|
||||
import SyncStatus from './components/SyncStatus.svelte'
|
||||
|
||||
let session = $state(null)
|
||||
let loading = $state(true)
|
||||
let route = $state(window.location.hash || '#/')
|
||||
|
||||
// Check if this is a kiosk token URL before doing anything else
|
||||
const kioskToken = $derived(window.location.hash.match(/^#\/v\/([A-Z0-9]+)/i)?.[1] ?? '')
|
||||
|
||||
onMount(async () => {
|
||||
// Kiosk pages don't need auth
|
||||
if (kioskToken) {
|
||||
loading = false
|
||||
return
|
||||
}
|
||||
session = await getSession()
|
||||
loading = false
|
||||
if (session) {
|
||||
await syncPull()
|
||||
startSSE()
|
||||
startSyncLoop()
|
||||
}
|
||||
window.addEventListener('hashchange', () => {
|
||||
route = window.location.hash || '#/'
|
||||
})
|
||||
})
|
||||
|
||||
function onLogin(s) {
|
||||
session = s
|
||||
window.location.hash = '#/'
|
||||
syncPull().then(() => { startSSE(); startSyncLoop() })
|
||||
}
|
||||
|
||||
async function onLogout() {
|
||||
await clearSession()
|
||||
session = null
|
||||
window.location.hash = '#/login'
|
||||
}
|
||||
|
||||
const path = $derived(route.replace(/^#/, '') || '/')
|
||||
const role = $derived(session?.user?.role ?? '')
|
||||
</script>
|
||||
|
||||
{#if loading}
|
||||
<!-- checking session -->
|
||||
{:else if kioskToken}
|
||||
<Kiosk />
|
||||
{:else if !session}
|
||||
<Login onlogin={onLogin} />
|
||||
{:else if role === 'gate'}
|
||||
<!-- Gate users get the full-screen GateUI instead of the standard layout -->
|
||||
<GateUI {session} {onLogout} />
|
||||
{:else}
|
||||
<div class="layout">
|
||||
<Nav {session} {onLogout} active={path} />
|
||||
<div class="main">
|
||||
{#if path === '/' || path === ''}
|
||||
{#if role === 'volunteer_lead'}
|
||||
<ScheduleBoard {session} />
|
||||
{:else}
|
||||
<Dashboard {session} />
|
||||
{/if}
|
||||
{:else if path.startsWith('/attendees')}
|
||||
<Attendees {session} />
|
||||
{:else if path.startsWith('/volunteers')}
|
||||
<Volunteers {session} />
|
||||
{:else if path.startsWith('/departments')}
|
||||
<Departments {session} />
|
||||
{:else if path.startsWith('/shifts')}
|
||||
<Shifts {session} />
|
||||
{:else if path.startsWith('/schedule')}
|
||||
<ScheduleBoard {session} />
|
||||
{:else if path.startsWith('/users')}
|
||||
<Users {session} />
|
||||
{:else if path.startsWith('/import')}
|
||||
<Import {session} />
|
||||
{:else if path.startsWith('/settings')}
|
||||
<Settings {session} />
|
||||
{:else}
|
||||
<div class="page"><p class="text-muted">Page not found.</p></div>
|
||||
{/if}
|
||||
<SyncStatus />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
Loading…
Add table
Add a link
Reference in a new issue