feat: Aufnahmeseite und Liste der Sprachnotizen (T7 L5 Task 19)
/voice/new: großer Aufnahmeknopf mit Zeit, Hinweis bei 150 s, Stopp bei 180 s; eine automatisch beendete Aufnahme liegt sofort in der Warteschlange des Geräts (Ruling 13); Abbrechen und Neu aufnehmen fragen nach; Hilfe bei gesperrtem Mikrofon; Fokus bleibt bei jedem Zustandswechsel an einem Bedienelement; Volk und Datum während der Aufnahme gesperrt, ?date= auf die letzten 7 Tage begrenzt. /voice: wartende Notizen des Geräts zuerst, dann die des Servers mit Status, „Prüfen“ nur bei fertigen, Verwerfen mit Rückfrage. Einstiege über Schnellanlage, Menü (nur mit voice-captures:use und inspections:create), Volksseite und Durchsicht. Bei ausgeschalteter Aufnahme verschwinden die Einstiege; jeder HTTP-Fehler der Konfiguration zählt als aus, nur fehlendes Netz als unbekannt. Fehlertexte gleich mit dem Backend (Test). Gates: Frontend lint, typecheck, 2979 Tests, build. Refs #27 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
462ac46d1e
commit
e0be687b7c
33 files changed
+3460
-19
No files matched your search
@@ -0,0 +1,42 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { Mic } from "lucide-react";
|
||||
import { useAuth } from "@/lib/auth/auth-context";
|
||||
import { offersRecording, useVoiceRecordingSwitch } from "@/lib/voice/use-voice-recording-switch";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
interface VoiceEntryLinkProps {
|
||||
colonyId: string;
|
||||
/** The stand round the note belongs to; keeps the round going afterwards. */
|
||||
roundApiaryId?: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* „Sprachnotiz aufnehmen“ next to „Durchsicht erfassen“. Not there without the
|
||||
* rights or while the operator has recording switched off - no dead button.
|
||||
*/
|
||||
export function VoiceEntryLink({ colonyId, roundApiaryId }: VoiceEntryLinkProps) {
|
||||
const { hasPermission } = useAuth();
|
||||
const allowed = hasPermission("voice-captures:use") && hasPermission("inspections:create");
|
||||
const recordingSwitch = useVoiceRecordingSwitch(allowed);
|
||||
if (!allowed || !offersRecording(recordingSwitch)) {
|
||||
return null;
|
||||
}
|
||||
const params = new URLSearchParams({ colonyId });
|
||||
if (roundApiaryId) {
|
||||
params.set("round", roundApiaryId);
|
||||
}
|
||||
return (
|
||||
<Button
|
||||
size="touch"
|
||||
variant="outline"
|
||||
className="min-h-14"
|
||||
nativeButton={false}
|
||||
render={<Link href={`/voice/new?${params.toString()}`} />}
|
||||
>
|
||||
<Mic aria-hidden />
|
||||
Sprachnotiz aufnehmen
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user