feat: Add character names to scenarios and UI

Introduces `characterName` to the `Scenario` type, enabling AI personas to be explicitly named. This change also updates the `ScenarioCard` component to display the character name and adds foundational support for potential future scenario deletion functionality. The README has been updated with a new AI Studio link.
This commit is contained in:
John Remillard committed 2026-03-04 11:43:39 -05:00
1 parent e92c489db5
commit a4946ed04d
18 files changed
+3585 -320

No files matched your search

@@ -0,0 +1,16 @@
import React from 'react';
import { BrainCircuit } from 'lucide-react';
const AnalyzingState: React.FC = () => (
<div className="flex flex-col items-center justify-center h-full text-slate-800">
<div className="bg-white p-12 rounded-full shadow-lg border border-teal-100 mb-8 relative">
<BrainCircuit size={64} className="text-teal-600 animate-pulse" />
<div className="absolute inset-0 border-4 border-teal-500 border-t-transparent rounded-full animate-spin"></div>
</div>
<h2 className="text-2xl font-bold mb-2">Generating Report</h2>
<p className="text-slate-500 text-center max-w-sm">Synthesizing vocal patterns and cognitive restructuring evidence...</p>
</div>
);
export default React.memo(AnalyzingState);
@@ -0,0 +1,12 @@
import React from 'react';
import { Loader2 } from 'lucide-react';
const ConnectionState: React.FC = () => (
<div className="flex flex-col items-center justify-center h-full text-slate-800 animate-pulse">
<Loader2 size={48} className="animate-spin text-teal-600 mb-4" />
<p className="font-bold uppercase tracking-widest text-xs">Opening Neural Bridge...</p>
</div>
);
export default React.memo(ConnectionState);
+34
View File
@@ -0,0 +1,34 @@
import React from 'react';
import { Mic, MicOff, MessageSquare } from 'lucide-react';
interface VoiceControlsProps {
isMuted: boolean;
onToggleMute: () => void;
showTranscript: boolean;
onToggleTranscript: () => void;
}
const VoiceControls: React.FC<VoiceControlsProps> = ({
isMuted,
onToggleMute,
showTranscript,
onToggleTranscript
}) => (
<div className="p-8 flex justify-center gap-6 relative z-10 bg-black/20 backdrop-blur-md">
<button
onClick={onToggleMute}
className={`p-5 rounded-full transition-all ${isMuted ? 'bg-rose-600 text-white' : 'bg-white/10 text-white hover:bg-white/20'}`}
>
{isMuted ? <MicOff size={24} /> : <Mic size={24} />}
</button>
<button
onClick={onToggleTranscript}
className={`p-5 rounded-full transition-all ${showTranscript ? 'bg-teal-600 text-white' : 'bg-white/10 text-white hover:bg-white/20'}`}
>
<MessageSquare size={24} />
</button>
</div>
);
export default React.memo(VoiceControls);
+28
View File
@@ -0,0 +1,28 @@
import React from 'react';
import { PhoneOff, Flag } from 'lucide-react';
interface VoiceHeaderProps {
title: string;
onExit: () => void;
onFinish: () => void;
}
const VoiceHeader: React.FC<VoiceHeaderProps> = ({ title, onExit, onFinish }) => (
<div className="p-8 flex justify-between items-center relative z-10">
<div className="flex items-center gap-4">
<button onClick={onExit} className="p-3 bg-white/5 hover:bg-white/10 rounded-2xl text-white/50 hover:text-white transition-all">
<PhoneOff size={20} />
</button>
<div>
<h2 className="text-white font-bold text-lg">{title}</h2>
<p className="text-teal-400 text-[10px] font-black uppercase tracking-widest">Active Roleplay Session</p>
</div>
</div>
<button onClick={onFinish} className="bg-teal-600 hover:bg-teal-700 text-white px-6 py-2.5 rounded-xl text-[10px] font-black uppercase tracking-widest transition-all shadow-lg shadow-teal-900/40 flex items-center gap-2">
<Flag size={14} /> Finish
</button>
</div>
);
export default React.memo(VoiceHeader);