in src/frontends/live_api_react/frontend/src/App.tsx [27:203]
function App() {
const videoRef = useRef<HTMLVideoElement>(null);
const [videoStream, setVideoStream] = useState<MediaStream | null>(null);
const [serverUrl, setServerUrl] = useState<string>(defaultUri);
const [runId] = useState<string>(crypto.randomUUID());
const [userId, setUserId] = useState<string>("user1");
// Feedback state
const [feedbackScore, setFeedbackScore] = useState<number>(10);
const [feedbackText, setFeedbackText] = useState<string>("");
const [sendFeedback, setShowFeedback] = useState(false);
const submitFeedback = async () => {
const feedbackUrl = new URL('feedback', serverUrl.replace('ws', 'http')).href;
try {
const response = await fetch(feedbackUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
score: feedbackScore,
text: feedbackText,
run_id: runId,
user_id: userId,
log_type: "feedback"
})
});
if (!response.ok) {
throw new Error(`Failed to submit feedback: Server returned status ${response.status} ${response.statusText}`);
}
// Clear feedback after successful submission
setFeedbackScore(10);
setFeedbackText("");
setShowFeedback(false);
alert("Feedback submitted successfully!");
} catch (error) {
console.error('Error submitting feedback:', error);
alert(`Failed to submit feedback: ${error}`);
}
};
return (
<div className="App">
<LiveAPIProvider url={serverUrl} userId={userId}>
<div className="streaming-console">
<SidePanel />
<main>
<div className="main-app-area">
<video
className={cn("stream", {
hidden: !videoRef.current || !videoStream,
})}
ref={videoRef}
autoPlay
playsInline
/>
</div>
<ControlTray
videoRef={videoRef}
supportsVideo={true}
onVideoStreamChange={setVideoStream}
>
</ControlTray>
<div className="url-setup" style={{position: 'absolute', top: 0, left: 0, right: 0, pointerEvents: 'auto', zIndex: 1000, padding: '2px', marginBottom: '2px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', background: 'rgba(255, 255, 255, 0.9)'}}>
<div>
<label htmlFor="server-url">Server URL:</label>
<input
id="server-url"
type="text"
value={serverUrl}
onChange={(e) => setServerUrl(e.target.value)}
placeholder="Enter server URL"
style={{
cursor: 'text',
padding: '4px',
margin: '0 4px',
borderRadius: '2px',
border: '1px solid #ccc',
fontSize: '14px',
fontFamily: 'system-ui, -apple-system, sans-serif',
width: '200px'
}}
/>
<label htmlFor="user-id">User ID:</label>
<input
id="user-id"
type="text"
value={userId}
onChange={(e) => setUserId(e.target.value)}
placeholder="Enter user ID"
style={{
cursor: 'text',
padding: '4px',
margin: '0 4px',
borderRadius: '2px',
border: '1px solid #ccc',
fontSize: '14px',
fontFamily: 'system-ui, -apple-system, sans-serif',
width: '100px'
}}
/>
</div>
{/* Feedback Button */}
<button
onClick={() => setShowFeedback(!sendFeedback)}
style={{
padding: '5px 10px',
margin: '10px',
cursor: 'pointer'
}}
>
{sendFeedback ? 'Hide Feedback' : 'Send Feedback'}
</button>
</div>
{/* Feedback Overlay Section */}
{sendFeedback && (
<div className="feedback-section" style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
padding: '20px',
background: 'rgba(255, 255, 255, 0.95)',
boxShadow: '0 0 10px rgba(0,0,0,0.2)',
borderRadius: '8px',
zIndex: 1001,
minWidth: '300px'
}}>
<h3>Provide Feedback</h3>
<div>
<label htmlFor="feedback-score">Score (0-10): </label>
<input
id="feedback-score"
type="number"
min="0"
max="10"
value={feedbackScore}
onChange={(e) => setFeedbackScore(Number(e.target.value))}
style={{margin: '0 10px'}}
/>
</div>
<div style={{marginTop: '10px'}}>
<label htmlFor="feedback-text">Comments: </label>
<textarea
id="feedback-text"
value={feedbackText}
onChange={(e) => setFeedbackText(e.target.value)}
style={{
width: '100%',
height: '60px',
margin: '5px 0'
}}
/>
</div>
<button
onClick={submitFeedback}
style={{
padding: '5px 10px',
marginTop: '5px',
cursor: 'pointer'
}}
>
Submit Feedback
</button>
</div>
)}
</main>
</div>
</LiveAPIProvider>
</div>
);
}