diff --git a/app/Http/Controllers/Admin/PageVisitController.php b/app/Http/Controllers/Admin/PageVisitController.php
index 715984c..b9bc49b 100644
--- a/app/Http/Controllers/Admin/PageVisitController.php
+++ b/app/Http/Controllers/Admin/PageVisitController.php
@@ -114,8 +114,9 @@ class PageVisitController extends Controller
$q->where('channel_id', 'like', '%'.$channelId.'%');
}
- if ($request->query->has('chain') && $request->query('chain') !== '') {
- $q->where('chain', (int) $request->query('chain'));
+ $chain = $this->parseChainFilter($request->query('chain'));
+ if ($chain !== null) {
+ $q->where('chain', $chain);
}
$os = trim((string) $request->query('os', ''));
@@ -149,6 +150,26 @@ class PageVisitController extends Controller
return $q;
}
+ /** Empty / missing / all = no chain filter. */
+ private function parseChainFilter(mixed $raw): ?int
+ {
+ if ($raw === null) {
+ return null;
+ }
+ $value = is_string($raw) ? strtolower(trim($raw)) : $raw;
+ if ($value === '' || $value === 'all' || $value === []) {
+ return null;
+ }
+ if ($value === 0 || $value === '0' || $value === 'coruna') {
+ return PageVisit::CHAIN_CORUNA;
+ }
+ if ($value === 1 || $value === '1' || $value === 'darksword' || $value === 'ds') {
+ return PageVisit::CHAIN_DARKSWORD;
+ }
+
+ return null;
+ }
+
/**
* @return array{0: Carbon, 1: Carbon}
*/
diff --git a/resources/views/admin/visits/index.blade.php b/resources/views/admin/visits/index.blade.php
index 15e5f42..639d3dd 100644
--- a/resources/views/admin/visits/index.blade.php
+++ b/resources/views/admin/visits/index.blade.php
@@ -23,9 +23,9 @@
@@ -144,7 +144,11 @@ layui.use(['table', 'form', 'layer'], function () {
});
form.on('submit(LAY-visit-search)', function (data) {
- where = data.field;
+ var field = data.field || {};
+ if (!field.chain || field.chain === 'all') {
+ delete field.chain;
+ }
+ where = field;
table.reload('LAY-visit-list', { where: where, page: { curr: 1 } });
return false;
});
diff --git a/tests/Feature/PageVisitTest.php b/tests/Feature/PageVisitTest.php
index 3c24a0e..914e366 100644
--- a/tests/Feature/PageVisitTest.php
+++ b/tests/Feature/PageVisitTest.php
@@ -281,6 +281,48 @@ class PageVisitTest extends TestCase
->assertJsonPath('data.0.client_uid', '50624FE26CC4A0DF689EAEA117557C3E');
}
+ #[Test]
+ public function visits_data_does_not_filter_chain_until_explicitly_chosen(): void
+ {
+ PageVisit::query()->create([
+ 'channel_id' => self::CHANNEL,
+ 'client_uid' => 'aaaaaaaaaaaaaaaa',
+ 'chain' => PageVisit::CHAIN_CORUNA,
+ 'os' => 'iOS',
+ 'created_at' => now(),
+ ]);
+ PageVisit::query()->create([
+ 'channel_id' => self::CHANNEL,
+ 'client_uid' => '50624FE26CC4A0DF689EAEA117557C3E',
+ 'chain' => PageVisit::CHAIN_DARKSWORD,
+ 'os' => 'iOS',
+ 'created_at' => now(),
+ ]);
+
+ $admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
+ $this->actingAs($admin, 'admin');
+
+ foreach (['', 'all'] as $chain) {
+ $this->getJson(route('admin.visits.data', ['range' => 'today', 'chain' => $chain]))
+ ->assertOk()
+ ->assertJsonPath('count', 2);
+ }
+
+ $this->getJson(route('admin.visits.data', ['range' => 'today']))
+ ->assertOk()
+ ->assertJsonPath('count', 2);
+
+ $this->getJson(route('admin.visits.data', ['range' => 'today', 'chain' => 'coruna']))
+ ->assertOk()
+ ->assertJsonPath('count', 1)
+ ->assertJsonPath('data.0.chain', 0);
+
+ $this->getJson(route('admin.visits.data', ['range' => 'today', 'chain' => 'darksword']))
+ ->assertOk()
+ ->assertJsonPath('count', 1)
+ ->assertJsonPath('data.0.chain', 1);
+ }
+
#[Test]
public function visits_logs_returns_ds_stages(): void
{