74 lines
2.5 KiB
TypeScript
74 lines
2.5 KiB
TypeScript
|
|
'use client';
|
||
|
|
|
||
|
|
import { useState, useEffect } from 'react';
|
||
|
|
import { useTranslations } from 'next-intl';
|
||
|
|
import { Keyboard, Mic } from 'lucide-react';
|
||
|
|
import { cn } from '@/lib/utils';
|
||
|
|
|
||
|
|
// ─── Types ───────────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
interface ModeToggleProps {
|
||
|
|
mode: 'type' | 'talk';
|
||
|
|
onChange: (mode: 'type' | 'talk') => void;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ─── Component ───────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
export default function ModeToggle({ mode, onChange }: ModeToggleProps) {
|
||
|
|
const t = useTranslations('configurator');
|
||
|
|
const [voiceSupported, setVoiceSupported] = useState(false);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
async function check() {
|
||
|
|
if (typeof WebSocket === 'undefined') return;
|
||
|
|
if (!navigator.mediaDevices?.getUserMedia) return;
|
||
|
|
|
||
|
|
try {
|
||
|
|
const res = await fetch('/api/gemini-token', {
|
||
|
|
method: 'POST',
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: JSON.stringify({ locale: 'en' }),
|
||
|
|
});
|
||
|
|
const data = (await res.json()) as { success: boolean };
|
||
|
|
if (data.success) setVoiceSupported(true);
|
||
|
|
} catch {
|
||
|
|
// silent — toggle stays hidden
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void check();
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
if (!voiceSupported) return null;
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="flex items-center gap-1 rounded-xl bg-surface-low p-1 border border-outline-variant/30">
|
||
|
|
<button
|
||
|
|
type="button"
|
||
|
|
onClick={() => onChange('type')}
|
||
|
|
className={cn(
|
||
|
|
'flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-all duration-200',
|
||
|
|
mode === 'type'
|
||
|
|
? 'bg-white text-on-surface shadow-card'
|
||
|
|
: 'text-outline hover:text-on-surface',
|
||
|
|
)}
|
||
|
|
>
|
||
|
|
<Keyboard size={13} />
|
||
|
|
{t('mode.type')}
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
type="button"
|
||
|
|
onClick={() => onChange('talk')}
|
||
|
|
className={cn(
|
||
|
|
'flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-all duration-200',
|
||
|
|
mode === 'talk'
|
||
|
|
? 'bg-white text-on-surface shadow-card'
|
||
|
|
: 'text-outline hover:text-on-surface',
|
||
|
|
)}
|
||
|
|
>
|
||
|
|
<Mic size={13} />
|
||
|
|
{t('mode.talk')}
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|