From 9b0a052cbeefeba94ce0eb66c6412b68ff1a7caf Mon Sep 17 00:00:00 2001
From: Philipp Lang <privat@zoomyboy.de>
Date: Tue, 14 Feb 2023 14:27:11 +0100
Subject: [PATCH] Add index for activity

---
 app/Activity/Actions/IndexAction.php        | 28 +++++++++++++++++++++
 app/Activity/Resources/ActivityResource.php | 27 ++++++++++++++++++++
 app/Nami/HasNamiField.php                   | 12 +++++++++
 routes/web.php                              |  2 ++
 tests/Feature/Activity/IndexTest.php        | 24 ++++++++++++++++++
 5 files changed, 93 insertions(+)
 create mode 100644 app/Activity/Actions/IndexAction.php
 create mode 100644 app/Activity/Resources/ActivityResource.php
 create mode 100644 tests/Feature/Activity/IndexTest.php

diff --git a/app/Activity/Actions/IndexAction.php b/app/Activity/Actions/IndexAction.php
new file mode 100644
index 00000000..d5cdfc84
--- /dev/null
+++ b/app/Activity/Actions/IndexAction.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Activity\Actions;
+
+use App\Activity;
+use App\Activity\Resources\ActivityResource;
+use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
+use Inertia\Inertia;
+use Inertia\Response;
+use Lorisleiva\Actions\ActionRequest;
+use Lorisleiva\Actions\Concerns\AsAction;
+
+class IndexAction
+{
+    use AsAction;
+
+    public function handle(): AnonymousResourceCollection
+    {
+        return ActivityResource::collection(Activity::local()->paginate(20));
+    }
+
+    public function asController(ActionRequest $request): Response
+    {
+        return Inertia::render('activity/Index', [
+            'data' => $this->handle(),
+        ]);
+    }
+}
diff --git a/app/Activity/Resources/ActivityResource.php b/app/Activity/Resources/ActivityResource.php
new file mode 100644
index 00000000..1b341161
--- /dev/null
+++ b/app/Activity/Resources/ActivityResource.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Activity\Resources;
+
+use App\Activity;
+use Illuminate\Http\Resources\Json\JsonResource;
+
+/**
+ * @mixin Activity
+ */
+class ActivityResource extends JsonResource
+{
+    /**
+     * Transform the resource into an array.
+     *
+     * @param \Illuminate\Http\Request $request
+     *
+     * @return array{id: int, name: string}
+     */
+    public function toArray($request)
+    {
+        return [
+            'name' => $this->name,
+            'id' => $this->id,
+        ];
+    }
+}
diff --git a/app/Nami/HasNamiField.php b/app/Nami/HasNamiField.php
index 28300ecb..95509371 100644
--- a/app/Nami/HasNamiField.php
+++ b/app/Nami/HasNamiField.php
@@ -2,6 +2,8 @@
 
 namespace App\Nami;
 
+use Illuminate\Database\Eloquent\Builder;
+
 trait HasNamiField
 {
     public static function nami(int $id): ?self
@@ -13,4 +15,14 @@ trait HasNamiField
     {
         return null !== $this->nami_id;
     }
+
+    /**
+     * @param Builder<self> $query
+     *
+     * @return Builder<self>
+     */
+    public static function scopeLocal(Builder $query): Builder
+    {
+        return $query->whereNull('nami_id');
+    }
 }
diff --git a/routes/web.php b/routes/web.php
index c8d31e79..f0f37682 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -1,5 +1,6 @@
 <?php
 
+use App\Activity\Actions\IndexAction as ActivityIndexAction;
 use App\Contribution\Actions\FormAction as ContributionFormAction;
 use App\Contribution\ContributionController;
 use App\Course\Controllers\CourseController;
@@ -46,4 +47,5 @@ Route::group(['middleware' => 'auth:web'], function (): void {
     Route::get('/member/{member}/resync', MemberResyncAction::class)->name('member.resync');
     Route::get('/contribution', ContributionFormAction::class)->name('contribution.form');
     Route::get('/contribution/generate', [ContributionController::class, 'generate'])->name('contribution.generate');
+    Route::get('/activity', ActivityIndexAction::class)->name('activity.index');
 });
diff --git a/tests/Feature/Activity/IndexTest.php b/tests/Feature/Activity/IndexTest.php
new file mode 100644
index 00000000..0943771b
--- /dev/null
+++ b/tests/Feature/Activity/IndexTest.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Tests\Feature\Activity;
+
+use App\Activity;
+use Illuminate\Foundation\Testing\DatabaseTransactions;
+use Tests\TestCase;
+
+class IndexTest extends TestCase
+{
+    use DatabaseTransactions;
+
+    public function testItDisplaysLocalActivities(): void
+    {
+        $this->login()->withoutExceptionHandling();
+        $local = Activity::factory()->name('Local')->create();
+        $remote = Activity::factory()->name('Remote')->inNami(123)->create();
+
+        $response = $this->get('/activity');
+
+        $this->assertInertiaHas('Local', $response, 'data.data.0.name');
+        $this->assertCount(1, $this->inertia($response, 'data.data'));
+    }
+}