Files
goal-planner/frontend/components/GoalInputForm.tsx
T
2026-11-02 17:15:39 +08:00

89 lines
5.4 KiB
TypeScript

import React, { useState } from 'react';
import { useLanguage } from '../i18n/LanguageContext';
interface GoalInputFormProps {
onGeneratePlan: (goal: string, additionalInfo?: string) => void;
}
const GoalInputForm: React.FC<GoalInputFormProps> = ({ onGeneratePlan }) => {
const { t } = useLanguage();
const [goal, setGoal] = useState('');
const [additionalInfo, setAdditionalInfo] = useState('');
const [showAdditional, setShowAdditional] = useState(false);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (goal.trim()) {
onGeneratePlan(goal.trim(), additionalInfo.trim() || undefined);
}
};
const handleExampleClick = (exampleGoal: string) => {
setGoal(exampleGoal);
onGeneratePlan(exampleGoal);
};
return (
<div className="bg-white dark:bg-slate-800 p-6 sm:p-10 rounded-3xl shadow-sm border border-slate-200/80 dark:border-slate-700 text-center">
<h2 className="text-2xl sm:text-3xl font-bold text-slate-800 dark:text-slate-100 mb-2">{t('nextGoalTitle')}</h2>
<p className="text-slate-600 dark:text-slate-400 mb-7">{t('nextGoalSub')}</p>
<form onSubmit={handleSubmit}>
<textarea
value={goal}
onChange={(e) => setGoal(e.target.value)}
placeholder={t('goalPlaceholder')}
className="w-full p-4 bg-slate-50 dark:bg-slate-700 text-slate-900 dark:text-slate-100 border border-slate-200 dark:border-slate-600 rounded-2xl mb-3 focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 focus:bg-white dark:focus:bg-slate-700 transition-shadow text-lg placeholder:text-slate-400 dark:placeholder:text-slate-500"
rows={3}
/>
{/* Toggle additional info */}
<button
type="button"
onClick={() => setShowAdditional(!showAdditional)}
className="flex items-center gap-1.5 text-sm text-slate-500 dark:text-slate-400 hover:text-green-600 dark:hover:text-green-400 transition-colors mb-2 mx-auto"
>
<svg xmlns="http://www.w3.org/2000/svg" className={`h-4 w-4 transition-transform duration-200 ${showAdditional ? 'rotate-90' : ''}`} fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
</svg>
{showAdditional ? t('collapseExtra') : t('importPlan')}
</button>
{showAdditional && (
<div className="mb-4 animate-in fade-in duration-200">
<textarea
value={additionalInfo}
onChange={(e) => setAdditionalInfo(e.target.value)}
placeholder={t('importPlaceholder')}
className="w-full p-4 bg-slate-50 dark:bg-slate-700/50 text-slate-900 dark:text-slate-100 border border-slate-200 dark:border-slate-500 rounded-2xl focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 transition-shadow text-sm placeholder:text-slate-400 dark:placeholder:text-slate-500 font-mono"
rows={8}
/>
{additionalInfo.trim() && (
<p className="text-xs text-green-600 dark:text-green-400 mt-1">
✅ {t('importReady')}
</p>
)}
</div>
)}
<button
type="submit"
disabled={!goal.trim()}
className="w-full bg-emerald-600 text-white font-semibold px-6 py-3.5 rounded-xl hover:bg-emerald-700 transition-colors disabled:bg-slate-300 dark:disabled:bg-slate-600 disabled:cursor-not-allowed shadow-sm shadow-emerald-200 dark:shadow-none"
>
{t('generatePlan')}
</button>
</form>
<div className="mt-6">
<p className="text-sm text-slate-500 dark:text-slate-400">{t('orTryExample')}</p>
<div className="flex flex-wrap justify-center gap-2 mt-2">
<button onClick={() => handleExampleClick(t('exampleTripGoal'))} className="text-xs bg-slate-100 dark:bg-slate-700 text-slate-700 dark:text-slate-300 px-3.5 py-1.5 rounded-full hover:bg-emerald-50 hover:text-emerald-700 dark:hover:bg-emerald-900/30 dark:hover:text-emerald-300 transition-colors">{t('exampleTrip')}</button>
<button onClick={() => handleExampleClick(t('exampleSkillGoal'))} className="text-xs bg-slate-100 dark:bg-slate-700 text-slate-700 dark:text-slate-300 px-3.5 py-1.5 rounded-full hover:bg-emerald-50 hover:text-emerald-700 dark:hover:bg-emerald-900/30 dark:hover:text-emerald-300 transition-colors">{t('exampleSkill')}</button>
<button onClick={() => handleExampleClick(t('exampleProductGoal'))} className="text-xs bg-slate-100 dark:bg-slate-700 text-slate-700 dark:text-slate-300 px-3.5 py-1.5 rounded-full hover:bg-emerald-50 hover:text-emerald-700 dark:hover:bg-emerald-900/30 dark:hover:text-emerald-300 transition-colors">{t('exampleProduct')}</button>
</div>
</div>
</div>
);
};
export default GoalInputForm;