'use client' import { useCallback, useEffect, useRef, useState } from 'react' import { CloudOff, Loader2, Plus, RefreshCw } from 'lucide-react' import { toast } from 'sonner' import { Button } from '@/components/ui/button' import { abarbeiten, alle, anstellen, type Eintrag } from '@/lib/warteschlange' /** * Schnellerfassung fürs Handy. * * Ein Feld, ein Knopf, große Fläche. Was erfasst wird, geht sofort hinaus — * und wenn kein Netz da ist, wartet es im Gerät, bis wieder eines da ist. * * Der Unterschied zur Erfassung auf der Startseite ist nicht die Optik, * sondern die Verlässlichkeit: Hier darf nichts verloren gehen, auch nicht * im Funkloch. */ export function Erfassung() { const [titel, setTitel] = useState('') const [laeuft, setLaeuft] = useState(false) const [wartend, setWartend] = useState([]) // Vor der Hydratation weiss der Server nichts vom Netz des Geraets; // "null" heisst schlicht: noch nicht nachgesehen. const [online, setOnline] = useState(null) const feld = useRef(null) const nachsehen = useCallback(async () => { try { setWartend(await alle()) } catch { // Ohne IndexedDB gibt es keine Warteschlange; erfassen geht trotzdem. } }, []) const leeren = useCallback(async () => { const bericht = await abarbeiten() if (bericht.gesendet > 0) { toast.success( bericht.gesendet === 1 ? 'Eine gemerkte Aufgabe ist raus.' : `${bericht.gesendet} gemerkte Aufgaben sind raus.`, ) } await nachsehen() }, [nachsehen]) useEffect(() => { function wiederDa() { setOnline(true) void leeren() } function weg() { setOnline(false) } window.addEventListener('online', wiederDa) window.addEventListener('offline', weg) // Den Anfangszustand nicht im Rumpf setzen, sondern als Antwort auf das // Aussenwelt-Ereignis "die Seite ist jetzt da". const ersteRunde = window.setTimeout(() => { setOnline(navigator.onLine) void nachsehen() void leeren() }, 0) return () => { window.clearTimeout(ersteRunde) window.removeEventListener('online', wiederDa) window.removeEventListener('offline', weg) } }, [leeren, nachsehen]) // Der Dienstarbeiter hält die Seite selbst offline bereit. Ohne ihn wäre // die Warteschlange sinnlos: Man käme gar nicht erst auf die Seite. useEffect(() => { if ('serviceWorker' in navigator) { void navigator.serviceWorker.register('/sw.js').catch(() => undefined) } }, []) async function erfassen(ereignis: React.FormEvent) { ereignis.preventDefault() const text = titel.trim() if (text.length === 0) return setLaeuft(true) try { // Erst anstellen, dann senden. Andersherum ginge der Eintrag verloren, // wenn der Browser mitten im Senden geschlossen wird. const eintrag = await anstellen(text) setTitel('') feld.current?.focus() const bericht = await abarbeiten() await nachsehen() toast.success( bericht.gesendet > 0 ? 'Erfasst. Liegt in der Inbox.' : 'Gemerkt. Geht raus, sobald wieder Netz da ist.', ) // Der Eintrag selbst interessiert nur, wenn er liegen bleibt. void eintrag } catch { toast.error('Das hat nicht geklappt.') } finally { setLaeuft(false) } } return (
void erfassen(e)} className="flex flex-col gap-3">