feat: BreakPilot PWA - Full codebase (clean push without large binaries)
Some checks failed
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
ci/woodpecker/manual/build-ci-image Pipeline was successful
ci/woodpecker/manual/main Pipeline failed
Some checks failed
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
ci/woodpecker/manual/build-ci-image Pipeline was successful
ci/woodpecker/manual/main Pipeline failed
All services: admin-v2, studio-v2, website, ai-compliance-sdk, consent-service, klausur-service, voice-service, and infrastructure. Large PDFs and compiled binaries excluded via .gitignore.
This commit is contained in:
235
studio-v2/app/voice-test/page.tsx
Normal file
235
studio-v2/app/voice-test/page.tsx
Normal file
@@ -0,0 +1,235 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { VoiceCapture, VoiceCommandBar } from '@/components/voice'
|
||||
import { VoiceTask } from '@/lib/voice/voice-api'
|
||||
|
||||
/**
|
||||
* Voice Test Page
|
||||
* For testing and demonstrating voice interface
|
||||
*/
|
||||
export default function VoiceTestPage() {
|
||||
const [activeTab, setActiveTab] = useState<'simple' | 'full'>('full')
|
||||
const [transcripts, setTranscripts] = useState<string[]>([])
|
||||
const [intents, setIntents] = useState<{ intent: string; params: Record<string, unknown> }[]>([])
|
||||
const [tasks, setTasks] = useState<VoiceTask[]>([])
|
||||
|
||||
const handleTranscript = (text: string, isFinal: boolean) => {
|
||||
if (isFinal) {
|
||||
setTranscripts((prev) => [...prev.slice(-9), text])
|
||||
}
|
||||
}
|
||||
|
||||
const handleIntent = (intent: string, params: Record<string, unknown>) => {
|
||||
setIntents((prev) => [...prev.slice(-9), { intent, params }])
|
||||
}
|
||||
|
||||
const handleTaskCreated = (task: VoiceTask) => {
|
||||
setTasks((prev) => [...prev.slice(-9), task])
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-gray-100 to-gray-200 p-8">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
{/* Header */}
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl font-bold text-gray-800 mb-2">
|
||||
Breakpilot Voice Test
|
||||
</h1>
|
||||
<p className="text-gray-600">
|
||||
Testen Sie die Sprachsteuerung fuer Breakpilot. Sprechen Sie Befehle wie:
|
||||
</p>
|
||||
<ul className="mt-2 text-sm text-gray-500 list-disc list-inside">
|
||||
<li>"Notiz zu Max: heute wiederholt gestoert"</li>
|
||||
<li>"Erinner mich morgen an Hausaufgabenkontrolle"</li>
|
||||
<li>"Erstelle Arbeitsblatt mit 3 Lueckentexten"</li>
|
||||
<li>"Elternbrief wegen wiederholter Stoerungen"</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Tab switcher */}
|
||||
<div className="flex gap-2 mb-6">
|
||||
<button
|
||||
onClick={() => setActiveTab('full')}
|
||||
className={`px-4 py-2 rounded-lg transition-colors ${
|
||||
activeTab === 'full'
|
||||
? 'bg-blue-500 text-white'
|
||||
: 'bg-white text-gray-700 hover:bg-gray-50'
|
||||
}`}
|
||||
>
|
||||
Volle Ansicht
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('simple')}
|
||||
className={`px-4 py-2 rounded-lg transition-colors ${
|
||||
activeTab === 'simple'
|
||||
? 'bg-blue-500 text-white'
|
||||
: 'bg-white text-gray-700 hover:bg-gray-50'
|
||||
}`}
|
||||
>
|
||||
Einfacher Modus
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
{/* Voice Component */}
|
||||
<div>
|
||||
{activeTab === 'full' ? (
|
||||
<VoiceCommandBar
|
||||
onTaskCreated={handleTaskCreated}
|
||||
className="h-[500px]"
|
||||
/>
|
||||
) : (
|
||||
<div className="bg-white rounded-xl shadow-lg p-6">
|
||||
<h2 className="text-lg font-semibold mb-4">Sprachaufnahme</h2>
|
||||
<VoiceCapture
|
||||
onTranscript={handleTranscript}
|
||||
onIntent={handleIntent}
|
||||
onTaskCreated={handleTaskCreated}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Debug panel */}
|
||||
<div className="space-y-6">
|
||||
{/* Transcripts */}
|
||||
<div className="bg-white rounded-xl shadow-lg p-6">
|
||||
<h2 className="text-lg font-semibold mb-4">Erkannte Texte</h2>
|
||||
<div className="space-y-2 max-h-[150px] overflow-y-auto">
|
||||
{transcripts.length === 0 ? (
|
||||
<p className="text-gray-400 text-sm">
|
||||
Noch keine Transkripte...
|
||||
</p>
|
||||
) : (
|
||||
transcripts.map((t, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="bg-gray-50 rounded px-3 py-2 text-sm"
|
||||
>
|
||||
{t}
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Intents */}
|
||||
<div className="bg-white rounded-xl shadow-lg p-6">
|
||||
<h2 className="text-lg font-semibold mb-4">Erkannte Absichten</h2>
|
||||
<div className="space-y-2 max-h-[150px] overflow-y-auto">
|
||||
{intents.length === 0 ? (
|
||||
<p className="text-gray-400 text-sm">Noch keine Intents...</p>
|
||||
) : (
|
||||
intents.map((intent, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="bg-blue-50 rounded px-3 py-2 text-sm"
|
||||
>
|
||||
<span className="font-medium text-blue-700">
|
||||
{intent.intent}
|
||||
</span>
|
||||
{Object.keys(intent.params).length > 0 && (
|
||||
<pre className="mt-1 text-xs text-gray-500">
|
||||
{JSON.stringify(intent.params, null, 2)}
|
||||
</pre>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tasks */}
|
||||
<div className="bg-white rounded-xl shadow-lg p-6">
|
||||
<h2 className="text-lg font-semibold mb-4">Erstellte Aufgaben</h2>
|
||||
<div className="space-y-2 max-h-[150px] overflow-y-auto">
|
||||
{tasks.length === 0 ? (
|
||||
<p className="text-gray-400 text-sm">
|
||||
Noch keine Aufgaben...
|
||||
</p>
|
||||
) : (
|
||||
tasks.map((task, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="bg-green-50 rounded px-3 py-2 text-sm"
|
||||
>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="font-medium text-green-700">
|
||||
{task.type}
|
||||
</span>
|
||||
<span
|
||||
className={`px-2 py-0.5 rounded text-xs ${
|
||||
task.state === 'completed'
|
||||
? 'bg-green-200 text-green-800'
|
||||
: task.state === 'ready'
|
||||
? 'bg-yellow-200 text-yellow-800'
|
||||
: 'bg-gray-200 text-gray-800'
|
||||
}`}
|
||||
>
|
||||
{task.state}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
ID: {task.id.slice(0, 8)}...
|
||||
</p>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Instructions */}
|
||||
<div className="mt-8 bg-white rounded-xl shadow-lg p-6">
|
||||
<h2 className="text-lg font-semibold mb-4">Anleitung</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 text-sm">
|
||||
<div>
|
||||
<h3 className="font-medium text-gray-700 mb-2">
|
||||
1. Notizen & Beobachtungen
|
||||
</h3>
|
||||
<ul className="text-gray-500 space-y-1">
|
||||
<li>• "Notiz zu [Name]: [Beobachtung]"</li>
|
||||
<li>• "[Name] braucht extra Uebung"</li>
|
||||
<li>• "Hausaufgabe kontrollieren"</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-medium text-gray-700 mb-2">
|
||||
2. Materialerstellung
|
||||
</h3>
|
||||
<ul className="text-gray-500 space-y-1">
|
||||
<li>• "Arbeitsblatt erstellen"</li>
|
||||
<li>• "Quiz mit 10 Fragen"</li>
|
||||
<li>• "Elternbrief wegen..."</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-medium text-gray-700 mb-2">
|
||||
3. Organisation
|
||||
</h3>
|
||||
<ul className="text-gray-500 space-y-1">
|
||||
<li>• "Erinner mich morgen..."</li>
|
||||
<li>• "Nachricht an Klasse 8a"</li>
|
||||
<li>• "Offene Aufgaben zeigen"</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Privacy note */}
|
||||
<div className="mt-6 text-center text-sm text-gray-400">
|
||||
<p>
|
||||
DSGVO-konform: Audio wird nur im Arbeitsspeicher verarbeitet und
|
||||
nie gespeichert.
|
||||
</p>
|
||||
<p>
|
||||
Alle personenbezogenen Daten werden verschluesselt gespeichert -
|
||||
der Schluessel bleibt auf Ihrem Geraet.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user