From 2f2bac9d3a1ff9396f4131ba46b7582d8565ab37 Mon Sep 17 00:00:00 2001 From: Leon Morival Date: Tue, 11 Aug 2026 16:06:58 +0200 Subject: [PATCH] feat: paginate public profile meals --- .../PublicUserProfileController.php | 14 ++++-- .../PublicUserProfilePaginationTest.php | 46 +++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 tests/Feature/PublicUserProfilePaginationTest.php diff --git a/app/Http/Controllers/PublicUserProfileController.php b/app/Http/Controllers/PublicUserProfileController.php index 9a0064b..ff862ec 100644 --- a/app/Http/Controllers/PublicUserProfileController.php +++ b/app/Http/Controllers/PublicUserProfileController.php @@ -17,13 +17,15 @@ class PublicUserProfileController extends Controller abort_if($user->isSuspended(), 404); abort_if($request->user()?->hasBlockingRelationshipWith($user), 404); + $perPage = max(1, min($request->integer('per_page', 18), 60)); $meals = $user->mealPosts() ->where('visibility', MealPostVisibility::Public->value) ->whereNull('hidden_at') ->with('user:id,name,avatar_url,account_verified_at') ->latest('eaten_at') - ->limit(18) - ->get(); + ->latest('id') + ->paginate($perPage) + ->withQueryString(); return response()->json([ 'data' => [ @@ -54,7 +56,13 @@ class PublicUserProfileController extends Controller ->whereIn('status', [FollowStatus::Accepted, FollowStatus::Pending]) ->exists() : false, - 'meals' => MealPostsResource::collection($meals)->resolve($request), + 'meals' => MealPostsResource::collection($meals->getCollection())->resolve($request), + 'mealsPagination' => [ + 'currentPage' => $meals->currentPage(), + 'lastPage' => $meals->lastPage(), + 'perPage' => $meals->perPage(), + 'total' => $meals->total(), + ], ], ]); } diff --git a/tests/Feature/PublicUserProfilePaginationTest.php b/tests/Feature/PublicUserProfilePaginationTest.php new file mode 100644 index 0000000..80e8235 --- /dev/null +++ b/tests/Feature/PublicUserProfilePaginationTest.php @@ -0,0 +1,46 @@ +create(); + $profileUser = User::factory()->create(); + $oldestMeal = MealPosts::factory()->for($profileUser, 'user')->create([ + 'eaten_at' => '2026-08-08 12:00:00', + 'visibility' => MealPostVisibility::Public, + ]); + $middleMeal = MealPosts::factory()->for($profileUser, 'user')->create([ + 'eaten_at' => '2026-08-09 12:00:00', + 'visibility' => MealPostVisibility::Public, + ]); + $latestMeal = MealPosts::factory()->for($profileUser, 'user')->create([ + 'eaten_at' => '2026-08-10 12:00:00', + 'visibility' => MealPostVisibility::Public, + ]); + MealPosts::factory()->for($profileUser, 'user')->create([ + 'visibility' => MealPostVisibility::Private, + ]); + + Sanctum::actingAs($viewer); + + $this->getJson("/api/users/{$profileUser->id}?per_page=2&page=1") + ->assertOk() + ->assertJsonCount(2, 'data.meals') + ->assertJsonPath('data.meals.0.id', $latestMeal->id) + ->assertJsonPath('data.meals.1.id', $middleMeal->id) + ->assertJsonPath('data.mealsPagination.currentPage', 1) + ->assertJsonPath('data.mealsPagination.lastPage', 2) + ->assertJsonPath('data.mealsPagination.total', 3); + + $this->getJson("/api/users/{$profileUser->id}?per_page=2&page=2") + ->assertOk() + ->assertJsonCount(1, 'data.meals') + ->assertJsonPath('data.meals.0.id', $oldestMeal->id) + ->assertJsonPath('data.mealsPagination.currentPage', 2); +});