Exersice name field focus opens keyboard. Typing filters the options.
This commit is contained in:
@@ -30,6 +30,8 @@ const Tracker: React.FC<TrackerProps> = ({ userId, userWeight, activeSession, ac
|
||||
const [plans, setPlans] = useState<WorkoutPlan[]>([]);
|
||||
const [selectedExercise, setSelectedExercise] = useState<ExerciseDef | null>(null);
|
||||
const [lastSet, setLastSet] = useState<WorkoutSet | undefined>(undefined);
|
||||
const [searchQuery, setSearchQuery] = useState<string>('');
|
||||
const [showSuggestions, setShowSuggestions] = useState(false);
|
||||
|
||||
// Timer State
|
||||
const [elapsedTime, setElapsedTime] = useState<string>('00:00:00');
|
||||
@@ -174,11 +176,19 @@ const Tracker: React.FC<TrackerProps> = ({ userId, userWeight, activeSession, ac
|
||||
if (selectedExercise.type !== ExerciseType.HIGH_JUMP) {
|
||||
setHeight('');
|
||||
}
|
||||
} else {
|
||||
setSearchQuery(''); // Clear search query if no exercise is selected
|
||||
}
|
||||
};
|
||||
updateSelection();
|
||||
}, [selectedExercise, userId]);
|
||||
|
||||
const filteredExercises = searchQuery === ''
|
||||
? exercises
|
||||
: exercises.filter(ex =>
|
||||
ex.name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
const handleStart = (plan?: WorkoutPlan) => {
|
||||
if (plan && plan.description) {
|
||||
setShowPlanPrep(plan);
|
||||
@@ -486,25 +496,46 @@ const Tracker: React.FC<TrackerProps> = ({ userId, userWeight, activeSession, ac
|
||||
<div className="flex-1 overflow-y-auto p-4 pb-32 space-y-6">
|
||||
|
||||
<div className="relative">
|
||||
<select
|
||||
className="w-full p-4 pr-12 bg-transparent border border-outline rounded-lg text-on-surface appearance-none focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary text-lg font-normal"
|
||||
value={selectedExercise?.id || ''}
|
||||
onChange={(e) => setSelectedExercise(exercises.find(ex => ex.id === e.target.value) || null)}
|
||||
>
|
||||
<option value="" disabled>{t('select_exercise', lang)}</option>
|
||||
{exercises
|
||||
.map(ex => (
|
||||
<option key={ex.id} value={ex.id} className="bg-surface-container text-on-surface">{ex.name}</option>
|
||||
))}
|
||||
</select>
|
||||
<ChevronDown className="absolute right-4 top-1/2 -translate-y-1/2 text-on-surface-variant pointer-events-none" size={24} />
|
||||
|
||||
<FilledInput
|
||||
label={t('select_exercise', lang)}
|
||||
value={searchQuery}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchQuery(e.target.value);
|
||||
setShowSuggestions(true);
|
||||
}}
|
||||
onFocus={() => setShowSuggestions(true)}
|
||||
onBlur={() => setTimeout(() => setShowSuggestions(false), 100)} // Delay hiding to allow click
|
||||
icon={<Dumbbell size={10} />}
|
||||
autoComplete="off"
|
||||
type="text"
|
||||
/>
|
||||
<button
|
||||
onClick={() => setIsCreating(true)}
|
||||
className="absolute right-12 top-1/2 -translate-y-1/2 p-2 text-primary hover:bg-primary-container/20 rounded-full"
|
||||
className="absolute right-2 top-1/2 -translate-y-1/2 p-2 text-primary hover:bg-primary-container/20 rounded-full z-10"
|
||||
>
|
||||
<Plus size={24} />
|
||||
</button>
|
||||
{showSuggestions && (
|
||||
<div className="absolute top-full left-0 w-full bg-surface-container rounded-xl shadow-elevation-3 overflow-hidden z-20 mt-1 max-h-60 overflow-y-auto animate-in fade-in slide-in-from-top-2">
|
||||
{filteredExercises.length > 0 ? (
|
||||
filteredExercises.map(ex => (
|
||||
<button
|
||||
key={ex.id}
|
||||
onClick={() => {
|
||||
setSelectedExercise(ex);
|
||||
setSearchQuery(ex.name);
|
||||
setShowSuggestions(false);
|
||||
}}
|
||||
className="w-full text-left px-4 py-3 text-on-surface hover:bg-surface-container-high transition-colors text-lg"
|
||||
>
|
||||
{ex.name}
|
||||
</button>
|
||||
))
|
||||
) : (
|
||||
<div className="px-4 py-3 text-on-surface-variant text-lg">{t('no_exercises_found', lang)}</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{selectedExercise && (
|
||||
|
||||
Reference in New Issue
Block a user