qwen-hackthon / frontend /src /components /QuestionPanel.tsx
Yousef
Add all project files
f97e4ec
Raw
History Blame Contribute Delete
4.16 kB
import { useState, useCallback } from 'react';
interface Props {
question: string;
options: string[];
number: number;
total: number;
onAnswer: (answer: string) => void;
}
export default function QuestionPanel({ question, options, number, total, onAnswer }: Props) {
const [selected, setSelected] = useState<string | null>(null);
const [custom, setCustom] = useState('');
const handleConfirm = useCallback(() => {
const answer = selected === '__custom__' ? custom.trim() : (selected || custom.trim());
if (!answer) return;
onAnswer(answer);
setSelected(null);
setCustom('');
}, [selected, custom, onAnswer]);
return (
<div className="w-full max-w-lg mx-auto my-4 animate-fade-in">
{/* Pink/white panel */}
<div className="rounded-xl shadow-md border border-pink-200 overflow-hidden bg-white">
{/* Header */}
<div className="bg-gradient-to-r from-pink-500 to-purple-500 px-4 py-3">
<div className="flex items-center justify-between">
<span className="text-[10px] font-bold text-white/80 uppercase tracking-wider">
Question {number} of {total}
</span>
<span className="text-[10px] font-bold text-white/60">
{Math.round((number / total) * 100)}%
</span>
</div>
{/* Progress bar */}
<div className="mt-2 h-1 bg-white/20 rounded-full overflow-hidden">
<div
className="h-full bg-white rounded-full transition-all duration-500"
style={{ width: `${(number / total) * 100}%` }}
/>
</div>
</div>
{/* Question */}
<div className="px-4 pt-4 pb-2">
<p className="text-sm text-slate-800 font-medium leading-relaxed">{question}</p>
</div>
{/* Options */}
<div className="px-4 pb-3 space-y-2">
{options.map((opt, i) => (
<button
key={i}
onClick={() => { setSelected(opt); setCustom(''); }}
className={`w-full text-left px-4 py-2.5 rounded-lg text-sm transition-all border ${
selected === opt
? 'bg-pink-50 border-pink-400 text-pink-700 font-medium shadow-sm'
: 'bg-white border-slate-200 text-slate-600 hover:border-pink-300 hover:bg-pink-50/50'
}`}
>
{opt}
</button>
))}
{/* Custom answer */}
<div className={`rounded-lg border transition-all ${
selected === '__custom__' ? 'border-pink-400 bg-pink-50' : 'border-slate-200'
}`}>
<button
onClick={() => setSelected('__custom__')}
className="w-full text-left px-4 py-2 text-xs text-slate-400 hover:text-pink-500 transition-colors"
>
{selected === '__custom__' ? 'Custom answer' : '✏️ Or type your own answer...'}
</button>
{selected === '__custom__' && (
<div className="px-3 pb-3">
<input
autoFocus
value={custom}
onChange={e => setCustom(e.target.value)}
placeholder="Type your answer..."
className="w-full bg-white border border-slate-200 rounded-lg px-3 py-2 text-sm text-slate-700 placeholder-slate-400 outline-none focus:border-pink-300 focus:ring-2 focus:ring-pink-100"
/>
</div>
)}
</div>
</div>
{/* Confirm button */}
<div className="px-4 pb-4">
<button
onClick={handleConfirm}
disabled={!selected && !custom.trim()}
className="w-full py-2.5 bg-gradient-to-r from-pink-500 to-purple-500 hover:from-pink-600 hover:to-purple-600 disabled:from-slate-200 disabled:to-slate-200 text-white text-sm font-semibold rounded-lg transition-all shadow-sm disabled:shadow-none disabled:text-slate-400"
>
{number < total ? 'Confirm & Continue →' : 'Confirm & Finish'}
</button>
</div>
</div>
</div>
);
}