feature: main page - ranking list

This commit is contained in:
antv
2026-07-06 16:44:03 +07:00
parent 618dcef37f
commit e163d2f349
3 changed files with 142 additions and 7 deletions
+24 -6
View File
@@ -115,8 +115,13 @@ class UserService implements UserServiceInterface
->whereColumn('msnv', 'user.msnv') ->whereColumn('msnv', 'user.msnv')
->whereBetween('date', [$startOfMonth, $endOfMonth]) ->whereBetween('date', [$startOfMonth, $endOfMonth])
]) ])
->orderByDesc('score') ->get()
->get(); ->filter(fn($u) => $u->score > 0)
->sortBy([
['score', 'desc'],
['msnv', 'asc']
])
->values();
$currentRank = 0; $currentRank = 0;
$prevScore = null; $prevScore = null;
@@ -157,8 +162,13 @@ class UserService implements UserServiceInterface
->whereColumn('msnv', 'user.msnv') ->whereColumn('msnv', 'user.msnv')
->whereBetween('date', [$startOfMonth, $endOfMonth]) ->whereBetween('date', [$startOfMonth, $endOfMonth])
]) ])
->orderByDesc('score') ->get()
->get(); ->filter(fn($u) => $u->score > 0)
->sortBy([
['score', 'desc'],
['msnv', 'asc']
])
->values();
$prevScore = null; $prevScore = null;
$rank = 1; $rank = 1;
@@ -181,15 +191,23 @@ class UserService implements UserServiceInterface
$currentUserRankItem = $userItem; $currentUserRankItem = $userItem;
} }
if ($index < 5) { if ($index < 4) {
$rankers[] = $userItem; $rankers[] = $userItem;
} }
$rank++; $rank++;
} }
$showCurrentUserAtBottom = false;
if ($currentUserRankItem) {
$currentUserIndex = $users->search(fn($u) => $u->msnv == $currentUser->msnv);
if ($currentUserIndex !== false && $currentUserIndex >= 4) {
$showCurrentUserAtBottom = true;
}
}
return [ return [
'rankers' => $rankers, 'rankers' => $rankers,
'currentUserRankItem' => $currentUserRankItem 'currentUserRankItem' => $showCurrentUserAtBottom ? $currentUserRankItem : null
]; ];
} }
} }
@@ -18,7 +18,7 @@
/> />
@endforeach @endforeach
@if($currentUserRankItem && $currentUserRankItem->rank > 5) @if($currentUserRankItem)
<div class="my-3 border-t border-dashed border-gray-100 mx-2"></div> <div class="my-3 border-t border-dashed border-gray-100 mx-2"></div>
<x-ranking-item <x-ranking-item
rank="{{ $currentUserRankItem->rank }}" rank="{{ $currentUserRankItem->rank }}"
+117
View File
@@ -92,4 +92,121 @@ class UserDashboardLayoutTest extends TestCase
$response->assertSee('User A', false); $response->assertSee('User A', false);
$response->assertSee('User B', false); $response->assertSee('User B', false);
} }
public function test_dashboard_ranking_empty_state_when_no_data(): void
{
$user = \App\Models\User::create([
'msnv' => 5001,
'name' => 'User A',
'mail' => 'usera@runsystem.net',
'pass' => md5('password'),
'departments' => 1,
'role' => \App\Models\User::ROLE_MEMBER,
'status' => \App\Models\User::STATUS_ACTIVE,
'card' => 10,
'flag_send' => \App\Models\User::FLAG_SEND_ENABLED,
'first_login' => \App\Models\User::FIRST_LOGIN_FALSE,
]);
$this->actingAs($user);
$response = $this->get('/my-page');
$response->assertOk();
$response->assertSee('Chưa có xếp hạng cho tháng này', false);
}
public function test_dashboard_ranking_dense_rank_and_deterministic_order(): void
{
$users = [];
for ($i = 1; $i <= 5; $i++) {
$char = chr(64 + $i);
$users[$i] = \App\Models\User::create([
'msnv' => 5000 + $i,
'name' => "User {$char}",
'mail' => "user{$char}@runsystem.net",
'pass' => md5('password'),
'departments' => 1,
'role' => \App\Models\User::ROLE_MEMBER,
'status' => \App\Models\User::STATUS_ACTIVE,
'card' => 10,
'flag_send' => \App\Models\User::FLAG_SEND_ENABLED,
'first_login' => \App\Models\User::FIRST_LOGIN_FALSE,
]);
\App\Models\Administration::create([
'msnv' => 5000 + $i,
'received' => 9,
'sender' => 9999,
'sent' => 0,
'receiver' => null,
'date' => \Carbon\Carbon::now()->format('Y-m-d')
]);
}
$this->actingAs($users[5]);
$response = $this->get('/my-page');
$response->assertOk();
$response->assertSee('User A', false);
$response->assertSee('User B', false);
$response->assertSee('User C', false);
$response->assertSee('User D', false);
$response->assertSee('User E', false);
}
public function test_dashboard_ranking_inactive_users_excluded(): void
{
$activeUser = \App\Models\User::create([
'msnv' => 5001,
'name' => 'Active User',
'mail' => 'active@runsystem.net',
'pass' => md5('password'),
'departments' => 1,
'role' => \App\Models\User::ROLE_MEMBER,
'status' => \App\Models\User::STATUS_ACTIVE,
'card' => 10,
'flag_send' => \App\Models\User::FLAG_SEND_ENABLED,
'first_login' => \App\Models\User::FIRST_LOGIN_FALSE,
]);
$inactiveUser = \App\Models\User::create([
'msnv' => 5002,
'name' => 'Inactive User',
'mail' => 'inactive@runsystem.net',
'pass' => md5('password'),
'departments' => 1,
'role' => \App\Models\User::ROLE_MEMBER,
'status' => \App\Models\User::STATUS_INACTIVE,
'card' => 10,
'flag_send' => \App\Models\User::FLAG_SEND_ENABLED,
'first_login' => \App\Models\User::FIRST_LOGIN_FALSE,
]);
\App\Models\Administration::create([
'msnv' => 5001,
'received' => 10,
'sender' => 9999,
'sent' => 0,
'receiver' => null,
'date' => \Carbon\Carbon::now()->format('Y-m-d')
]);
\App\Models\Administration::create([
'msnv' => 5002,
'received' => 20,
'sender' => 9999,
'sent' => 0,
'receiver' => null,
'date' => \Carbon\Carbon::now()->format('Y-m-d')
]);
$this->actingAs($activeUser);
$response = $this->get('/my-page');
$response->assertOk();
$response->assertSee('Active User', false);
$response->assertDontSee('Inactive User', false);
}
} }