89 lines
4.7 KiB
TypeScript
89 lines
4.7 KiB
TypeScript
import React, { useState } from 'react';
|
||
import type { KICopilotProps } from '../types/ui.types';
|
||
|
||
const defaultSuggestions = [
|
||
{ id: 's1', icon: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>, label: '5 Reihen à 22 Stühle anlegen' },
|
||
{ id: 's2', icon: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>, label: 'Optimale Bestuhlung vorschlagen' },
|
||
{ id: 's3', icon: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>, label: 'Überlappende Stühle finden' },
|
||
];
|
||
|
||
const defaultMessages = [
|
||
{ id: 'm1', role: 'user' as const, content: 'Lege 5 Reihen mit je 22 Stühlen parallel zur Bühne an, Abstand 1m.' },
|
||
{ id: 'm2', role: 'assistant' as const, content: <span>Ich erstelle <strong>110 Stühle</strong> in 5 Reihen (Y=2,5m/3,5m/4,5m/5,5m/6,5m; X-Start=2,5m; 22 Stühle × 0,5m + 0,1m Abstand). Los geht's! <em style={{ color: 'var(--color-ki)' }}>● function_call: placeSeating(rows=5, cols=22, gap=1.0)</em></span> },
|
||
];
|
||
|
||
const KICopilot: React.FC<KICopilotProps> = ({ messages, suggestions, onSend, onSuggestionClick, loading }) => {
|
||
const [input, setInput] = useState('');
|
||
const allMessages = messages.length > 0 ? messages : defaultMessages;
|
||
const allSuggestions = suggestions.length > 0 ? suggestions : defaultSuggestions;
|
||
|
||
const handleSend = () => {
|
||
if (input.trim()) {
|
||
onSend(input.trim());
|
||
setInput('');
|
||
}
|
||
};
|
||
|
||
return (
|
||
<>
|
||
<div className="ki-header">
|
||
<div className="ki-avatar">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v2"/><path d="M9 13v2"/></svg>
|
||
</div>
|
||
<div>
|
||
<div className="ki-title">KI Copilot</div>
|
||
<div style={{ fontSize: '11px', color: 'var(--color-text-muted)' }}>Powered by Claude</div>
|
||
</div>
|
||
<span className="ki-status">Online</span>
|
||
</div>
|
||
|
||
<div className="ki-suggestions">
|
||
<div className="ki-suggestion-title">Schnell-Aktionen</div>
|
||
{allSuggestions.map((s) => (
|
||
<button key={s.id} className="ki-chip" onClick={() => onSuggestionClick(s)}>
|
||
{s.icon}
|
||
{s.label}
|
||
</button>
|
||
))}
|
||
</div>
|
||
|
||
<div className="ki-chat">
|
||
{allMessages.map((msg) => (
|
||
<div key={msg.id} className={`ki-msg ${msg.role}`}>
|
||
<div className="ki-msg-bubble">{msg.content}</div>
|
||
</div>
|
||
))}
|
||
{loading && (
|
||
<div className="ki-msg assistant">
|
||
<div className="ki-msg-bubble" style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
|
||
<span className="ki-typing-dot" />
|
||
<span className="ki-typing-dot" />
|
||
<span className="ki-typing-dot" />
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<div className="ki-input-wrap">
|
||
<input
|
||
className="ki-input"
|
||
type="text"
|
||
placeholder="Frage den KI Copilot..."
|
||
aria-label="KI Eingabe"
|
||
value={input}
|
||
onChange={(e) => setInput(e.target.value)}
|
||
onKeyDown={(e) => { if (e.key === 'Enter') handleSend(); }}
|
||
/>
|
||
<button className="ki-voice-btn" title="Spracheingabe" aria-label="Spracheingabe starten">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/></svg>
|
||
</button>
|
||
<button className="ki-send-btn" title="Senden" aria-label="Senden" onClick={handleSend} disabled={loading}>
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
|
||
</button>
|
||
</div>
|
||
</>
|
||
);
|
||
};
|
||
|
||
export default KICopilot;
|