"use client"; import { useState, useEffect, useMemo } from "react"; import { api } from "@/lib/api"; import { Spinner } from "@/components/ui/Spinner"; import type { Exercise } from "@/lib/types"; interface ExcludedExercisesStepProps { selectedIds: number[]; onChange: (ids: number[]) => void; } export function ExcludedExercisesStep({ selectedIds, onChange, }: ExcludedExercisesStepProps) { const [exercises, setExercises] = useState([]); const [loading, setLoading] = useState(true); const [search, setSearch] = useState(""); useEffect(() => { async function fetchExercises() { try { const data = await api.getExercises(); setExercises(data); } catch (err) { console.error("Failed to fetch exercises:", err); } finally { setLoading(false); } } fetchExercises(); }, []); const excludedExercises = useMemo( () => exercises.filter((e) => selectedIds.includes(e.id)), [exercises, selectedIds] ); const searchResults = useMemo(() => { if (search.length < 2) return []; const query = search.toLowerCase(); return exercises.filter((e) => e.name.toLowerCase().includes(query) ); }, [exercises, search]); const toggle = (id: number) => { if (selectedIds.includes(id)) { onChange(selectedIds.filter((i) => i !== id)); } else { onChange([...selectedIds, id]); } }; if (loading) { return (
); } return (

Exclude Exercises

Search for exercises you can't or won't do. They'll never appear in your generated workouts.

{/* Excluded chips */}
{excludedExercises.length === 0 ? (

No exercises excluded yet

) : (
{excludedExercises.map((ex) => ( ))}
)}
{/* Search input */} setSearch(e.target.value)} placeholder="Search exercises..." className="w-full px-4 py-3 rounded-xl bg-zinc-900 border border-zinc-700/50 text-zinc-100 placeholder-zinc-500 focus:outline-none focus:border-zinc-500 transition-colors mb-4" /> {/* Search results */} {search.length >= 2 && (
{searchResults.length === 0 ? (

No exercises match "{search}"

) : ( searchResults.map((ex) => { const isExcluded = selectedIds.includes(ex.id); return ( ); }) )}
)}
); }