diff --git a/app/Http/Controllers/WorkoutController.php b/app/Http/Controllers/WorkoutController.php
index 5af75ee..9718847 100644
--- a/app/Http/Controllers/WorkoutController.php
+++ b/app/Http/Controllers/WorkoutController.php
@@ -42,10 +42,26 @@ class WorkoutController extends Controller
{
$this->authorizeWorkout($workout);
$workout->load(['items.exercise']);
- $exercises = Exercise::orderBy('name')->limit(50)->get(['id','name','slug']);
+ $exercises = Exercise::orderBy('name')->limit(20)->get(['id','name','slug']);
return view('workouts.show', compact('workout', 'exercises'));
}
+ public function searchExercises(Request $request, Workout $workout)
+ {
+ $this->authorizeWorkout($workout);
+ $q = trim((string) $request->query('q', ''));
+
+ $exercises = Exercise::query()
+ ->with(['aliases' => fn ($rel) => $rel->where('user_id', Auth::id())])
+ ->when($q !== '', fn ($qb) => $qb->where('name', 'like', "%{$q}%"))
+ ->orderBy('name')
+ ->limit(20)
+ ->get(['id', 'name'])
+ ->map(fn ($e) => ['id' => $e->id, 'name' => $e->display_name]);
+
+ return response()->json($exercises);
+ }
+
// Legacy builder route -> redirect to create
public function builder()
{
diff --git a/resources/views/workouts/show.blade.php b/resources/views/workouts/show.blade.php
index b0da7c5..325221a 100644
--- a/resources/views/workouts/show.blade.php
+++ b/resources/views/workouts/show.blade.php
@@ -113,15 +113,27 @@
+
+ @push('scripts')
+
+ @endpush
diff --git a/routes/web.php b/routes/web.php
index c9c6736..f85a0fa 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -46,6 +46,7 @@ Route::middleware('auth')->prefix('/workouts')->group(function () {
Route::delete('/{workout}', [\App\Http\Controllers\WorkoutController::class, 'destroy'])->name('workouts.destroy');
// Manage exercises within a workout
+ Route::get('/{workout}/exercises/search', [\App\Http\Controllers\WorkoutController::class, 'searchExercises'])->name('workouts.exercises.search');
Route::post('/{workout}/exercises', [\App\Http\Controllers\WorkoutController::class, 'addExercise'])->name('workouts.exercises.add');
Route::patch('/{workout}/exercises/{item}', [\App\Http\Controllers\WorkoutController::class, 'updateExercise'])->name('workouts.exercises.update');
Route::delete('/{workout}/exercises/{item}', [\App\Http\Controllers\WorkoutController::class, 'removeExercise'])->name('workouts.exercises.remove');
diff --git a/tests/Feature/WorkoutTest.php b/tests/Feature/WorkoutTest.php
index 771b473..5a05401 100644
--- a/tests/Feature/WorkoutTest.php
+++ b/tests/Feature/WorkoutTest.php
@@ -146,4 +146,41 @@ class WorkoutTest extends TestCase
$response->assertForbidden();
$this->assertDatabaseHas('workouts', ['id' => $workout->id]);
}
+
+ public function test_owner_can_search_exercises_for_the_picker(): void
+ {
+ $user = User::factory()->create();
+ $workout = Workout::factory()->create(['user_id' => $user->id]);
+ Exercise::factory()->create(['name' => 'Barbell Bench Press']);
+ Exercise::factory()->create(['name' => 'Dumbbell Curl']);
+
+ $response = $this->actingAs($user)->getJson(route('workouts.exercises.search', $workout) . '?q=Bench');
+
+ $response->assertOk();
+ $response->assertJsonCount(1);
+ $response->assertJsonFragment(['name' => 'Barbell Bench Press']);
+ }
+
+ public function test_search_caps_results_at_twenty(): void
+ {
+ $user = User::factory()->create();
+ $workout = Workout::factory()->create(['user_id' => $user->id]);
+ Exercise::factory()->count(25)->create();
+
+ $response = $this->actingAs($user)->getJson(route('workouts.exercises.search', $workout));
+
+ $response->assertOk();
+ $this->assertCount(20, $response->json());
+ }
+
+ public function test_other_user_cannot_search_exercises_for_someone_elses_workout(): void
+ {
+ $owner = User::factory()->create();
+ $other = User::factory()->create();
+ $workout = Workout::factory()->create(['user_id' => $owner->id]);
+
+ $response = $this->actingAs($other)->getJson(route('workouts.exercises.search', $workout));
+
+ $response->assertForbidden();
+ }
}