Created Turnpike, event attendee and volunteer management
Built after prototype, Traverse, an attendee and volunteer list maintainer.
This commit is contained in:
commit
d05b8dc7e0
59 changed files with 8663 additions and 0 deletions
46
frontend/src/components/SyncStatus.svelte
Normal file
46
frontend/src/components/SyncStatus.svelte
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<script>
|
||||
import { onMount, onDestroy } from 'svelte'
|
||||
import { getLastSync } from '../db.js'
|
||||
import { syncPull } from '../sync.js'
|
||||
|
||||
let online = $state(navigator.onLine)
|
||||
let syncing = $state(false)
|
||||
let lastSync = $state('')
|
||||
|
||||
async function refresh() {
|
||||
lastSync = await getLastSync()
|
||||
}
|
||||
|
||||
async function manualSync() {
|
||||
syncing = true
|
||||
await syncPull()
|
||||
await refresh()
|
||||
syncing = false
|
||||
}
|
||||
|
||||
function onOnline() { online = true; manualSync() }
|
||||
function onOffline() { online = false }
|
||||
|
||||
onMount(() => {
|
||||
refresh()
|
||||
window.addEventListener('online', onOnline)
|
||||
window.addEventListener('offline', onOffline)
|
||||
})
|
||||
onDestroy(() => {
|
||||
window.removeEventListener('online', onOnline)
|
||||
window.removeEventListener('offline', onOffline)
|
||||
})
|
||||
|
||||
const dotClass = $derived(syncing ? 'syncing' : online ? 'online' : 'offline')
|
||||
const label = $derived(syncing ? 'Syncing…' : online ? 'Online' : 'Offline')
|
||||
const lastSyncLabel = $derived(lastSync ? new Date(lastSync).toLocaleTimeString() : 'Never')
|
||||
</script>
|
||||
|
||||
<div class="sync-bar">
|
||||
<div class="sync-dot {dotClass}"></div>
|
||||
<span>{label}</span>
|
||||
<span class="text-muted" style="margin-left:auto;font-size:0.72rem">Last sync: {lastSyncLabel}</span>
|
||||
{#if online && !syncing}
|
||||
<button class="btn btn-ghost btn-sm" onclick={manualSync}>↻</button>
|
||||
{/if}
|
||||
</div>
|
||||
Loading…
Add table
Add a link
Reference in a new issue