diff --git a/app/Http/Controllers/PhotosController.php b/app/Http/Controllers/PhotosController.php index 11d9f6c1..2ff4687b 100644 --- a/app/Http/Controllers/PhotosController.php +++ b/app/Http/Controllers/PhotosController.php @@ -16,7 +16,7 @@ public function index() /** @var User $user */ $user = auth()->user(); - $photos = $user->photos()->latest()->paginate(); + $photos = $user->photos()->latest('id')->paginate(12); $photos->getCollection()->transform(function (Photo $photo) { $photo->append('full_path'); @@ -45,6 +45,7 @@ public function show(Photo $photo) 'photoId' => $photo->id, 'items' => Item::query()->orderBy('name')->get(), 'tags' => $tags, + 'nextPhotoUrl' => $this->getNextPhotoUrl($photo), ]); } @@ -61,4 +62,20 @@ public function show(Photo $photo) 'items' => $items, ]; } + + private function getNextPhotoUrl(Photo $photo): ?string + { + $nextPhoto = Photo::query() + ->where('user_id', $photo->user_id) + ->whereDoesntHave('items') + ->where('id', '<', $photo->id) + ->orderByDesc('id') + ->first(); + + if (! $nextPhoto) { + return null; + } + + return route('photos.show', $nextPhoto); + } } diff --git a/resources/js/Pages/Photo/Show.vue b/resources/js/Pages/Photo/Show.vue index 8032fd85..f950afa2 100644 --- a/resources/js/Pages/Photo/Show.vue +++ b/resources/js/Pages/Photo/Show.vue @@ -2,11 +2,14 @@ import AppLayout from '@/Layouts/AppLayout.vue'; import {onMounted, ref} from "vue"; import PhotoItem from "@/Pages/Photo/PhotoItem.vue"; +import {Link} from "@inertiajs/vue3"; +import PrimaryButton from "@/Components/PrimaryButton.vue"; const props = defineProps({ photoId: Number, items: Array, - tags: Array, + tags: Object, + nextPhotoUrl: String, }); const photo = ref(null); @@ -81,8 +84,16 @@ const toggleItemPickedUp = (photoItemId) => { +
+ + Next Photo + + + All Photos + +
diff --git a/routes/web.php b/routes/web.php index 5977ffd2..472115b8 100644 --- a/routes/web.php +++ b/routes/web.php @@ -46,7 +46,7 @@ })->name('docs'); Route::get('/my-photos', [PhotosController::class, 'index'])->name('my-photos'); - Route::get('/photos/{photo}', [PhotosController::class, 'show']); + Route::get('/photos/{photo}', [PhotosController::class, 'show'])->name('photos.show'); Route::post('/photos/{photo}/tags', [PhotoTagsController::class, 'store']); Route::delete('/photos/{photo}/tags/{tag}', [PhotoTagsController::class, 'destroy']); diff --git a/tests/Feature/Photos/ShowPhotoTest.php b/tests/Feature/Photos/ShowPhotoTest.php index 5bf93158..bb3dd804 100644 --- a/tests/Feature/Photos/ShowPhotoTest.php +++ b/tests/Feature/Photos/ShowPhotoTest.php @@ -25,7 +25,7 @@ ['name' => 'C material'], )->create(['tag_type_id' => $material->id]); - $response = $this->get("/photos/{$photo->id}"); + $response = $this->get(route('photos.show', $photo)); $response->assertOk(); @@ -40,6 +40,32 @@ ); }); +test('a user can see the next untagged photo link', function () { + $this->actingAs($user = User::factory()->create()); + $photo = Photo::factory()->for($user)->create(); + $untaggedPhoto = Photo::factory()->for($user)->create(); + + $response = $this->get(route('photos.show', $photo)); + + $response->assertOk(); + $response->assertInertia(fn (AssertableInertia $page) => $page + ->where('nextPhotoUrl', route('photos.show', $untaggedPhoto)) + ); +}); + +test('a user can not see the next untagged photo link if there are no more untagged photos', function () { + $this->actingAs($user = User::factory()->create()); + $photo = Photo::factory()->for($user)->create(); + $taggedPhoto = Photo::factory()->for($user)->create(); + $item = Item::factory()->create(); + $taggedPhoto->items()->sync($item); + + $response = $this->get(route('photos.show', $photo)); + + $response->assertOk(); + $response->assertInertia(fn (AssertableInertia $page) => $page->where('nextPhotoUrl', null)); +}); + test('a user can see a photo', function () { $this->actingAs($user = User::factory()->create()); $photo = Photo::factory()->for($user)->create(); @@ -51,7 +77,7 @@ 'tag_id' => $tag->id, ]); - $response = $this->getJson("/photos/{$photo->id}"); + $response = $this->getJson(route('photos.show', $photo)); $response->assertOk(); $response->assertJson(fn (AssertableJson $json) => $json