Files
planer/src/components/aufgaben/schnellerfassung.tsx
T
Florian WildeandClaude Opus 5 a4a889fcb8 feat(aufgaben): Inbox, Aufgabenliste, Ideen und Projekte
Die Schnellerfassung braucht ein Feld und einen Knopf; wer beim Erfassen
erst ein Formular ausfüllen muss, erfasst nichts. Der Fokus bleibt danach
im Feld, damit mehrere Sachen hintereinander hineingehen.

Die Filter der Aufgabenliste stehen in der Adresse, nicht im Zustand der
Komponente — so lässt sich eine gefilterte Liste als Lesezeichen ablegen,
und der Zurück-Knopf tut, was er soll.

Die Startseite zeigt jetzt, was überfällig, heute oder morgen fällig ist,
statt nur die Bereiche aufzuzählen.

Für die Auswahlfelder bewusst das native <select>: es bedient sich auf
dem Handy mit dem Systemdialog und ist ohne Zusatzcode tastaturbedienbar.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 16:17:44 +02:00

73 lines
2.1 KiB
TypeScript

'use client'
import { useRef, useState, useTransition } from 'react'
import { useRouter } from 'next/navigation'
import { Lightbulb, Loader2, Plus } from 'lucide-react'
import { toast } from 'sonner'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { schnellErfassen } from '@/server/aktionen/aufgaben'
/**
* Ein Feld, ein Knopf, fertig.
*
* Alles Weitere — Bereich, Termin, Aufwand — kommt später beim Einsortieren.
* Wer beim Erfassen erst ein Formular ausfüllen muss, erfasst nichts.
*/
export function Schnellerfassung({ typ = 'AUFGABE' }: { typ?: 'AUFGABE' | 'IDEE' }) {
const router = useRouter()
const [titel, setTitel] = useState('')
const [laeuft, starte] = useTransition()
const feld = useRef<HTMLInputElement>(null)
function absenden(ereignis: React.FormEvent) {
ereignis.preventDefault()
const wert = titel.trim()
if (wert.length < 2) {
toast.error('Bitte mindestens zwei Zeichen eingeben.')
return
}
const daten = new FormData()
daten.set('titel', wert)
daten.set('typ', typ)
starte(async () => {
const antwort = await schnellErfassen(daten)
if (antwort.ok) {
setTitel('')
toast.success(antwort.meldung)
router.refresh()
// Gleich weiter erfassen können, ohne noch einmal zu klicken.
feld.current?.focus()
} else {
toast.error(antwort.fehler)
}
})
}
return (
<form onSubmit={absenden} className="flex gap-2">
<Input
ref={feld}
value={titel}
onChange={(e) => setTitel(e.target.value)}
placeholder={typ === 'IDEE' ? 'Idee notieren …' : 'Was ist zu tun?'}
maxLength={200}
disabled={laeuft}
aria-label={typ === 'IDEE' ? 'Neue Idee' : 'Neue Aufgabe'}
/>
<Button type="submit" disabled={laeuft} className="shrink-0">
{laeuft ? (
<Loader2 className="animate-spin" aria-hidden />
) : typ === 'IDEE' ? (
<Lightbulb aria-hidden />
) : (
<Plus aria-hidden />
)}
Erfassen
</Button>
</form>
)
}