builder / components /chat-panel /interview-picker.tsx
Leon4gr45's picture
Upload folder using huggingface_hub
eeb9404 verified
Raw
History Blame Contribute Delete
3.85 kB
import { useState, useMemo } from 'react';
import { Search, ClipboardList, ArrowRight, Plus, Settings2 } from 'lucide-react';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { filterInterviewTemplates } from '@/lib/interview/templates';
import type { InterviewTemplate } from '@/lib/interview/types';
interface InterviewPickerProps {
templates: InterviewTemplate[];
onStart: (template: InterviewTemplate) => void;
disabled?: boolean;
onNew?: () => void;
onManage?: () => void;
}
export function InterviewPicker({ templates, onStart, disabled, onNew, onManage }: InterviewPickerProps) {
const [query, setQuery] = useState('');
const [selectedId, setSelectedId] = useState<string | null>(null);
const filtered = useMemo(() => filterInterviewTemplates(templates, query), [templates, query]);
const selected = selectedId ? filtered.find(t => t.id === selectedId) ?? null : null;
return (
<div className="flex flex-col gap-3 p-3">
<div className="flex items-center gap-2 text-xs font-medium text-blue-500">
<ClipboardList className="h-4 w-4" />
<span>Start an interview</span>
<div className="ml-auto flex items-center gap-1">
{onManage && (
<Button
variant="ghost"
size="sm"
className="h-6 px-1.5 text-xs text-muted-foreground gap-1"
onClick={onManage}
>
<Settings2 className="h-3.5 w-3.5" />
Manage
</Button>
)}
{onNew && (
<Button
variant="ghost"
size="sm"
className="h-6 px-1.5 text-xs text-muted-foreground gap-1"
onClick={onNew}
>
<Plus className="h-3.5 w-3.5" />
New
</Button>
)}
</div>
</div>
<div className="relative">
<Search className="absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground pointer-events-none" />
<Input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search templates…"
className="h-8 pl-8 text-xs"
/>
</div>
<div className="flex flex-col gap-1.5 max-h-56 overflow-y-auto">
{filtered.length === 0 ? (
<div className="text-xs text-muted-foreground text-center py-4">No templates match “{query}”.</div>
) : (
filtered.map((t) => {
const isSelected = t.id === selectedId;
return (
<button
key={t.id}
type="button"
onClick={() => setSelectedId(t.id)}
onDoubleClick={() => !disabled && onStart(t)}
className={`text-left rounded-lg border px-3 py-2 transition-colors ${
isSelected
? 'border-blue-500 bg-blue-500/10 ring-1 ring-blue-500'
: 'border-border bg-card hover:bg-muted/50'
}`}
>
<div className="text-xs font-medium text-foreground">{t.title}</div>
<div className="text-[11px] text-muted-foreground mt-0.5 line-clamp-2">{t.description}</div>
{t.artifacts[0] && (
<div className="text-[11px] text-blue-500/80 mt-1 font-mono truncate">→ {t.artifacts[0].path}</div>
)}
</button>
);
})
)}
</div>
<Button
size="sm"
disabled={!selected || disabled}
onClick={() => selected && onStart(selected)}
className="bg-blue-500 hover:bg-blue-600 text-white gap-1.5"
>
<ArrowRight className="h-3.5 w-3.5" />
Start interview
</Button>
</div>
);
}