Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [LAR-150] add forum leaderboard page #289

Merged
merged 4 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace App\Livewire;
namespace App\Livewire\Components;

use App\Contracts\ReactableInterface;
use App\Models\Reaction;
Expand Down Expand Up @@ -40,6 +40,6 @@ public function userReacted(string $reaction): void

public function render(): View
{
return view('livewire.reactions');
return view('livewire.components.reactions');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace App\Livewire;
namespace App\Livewire\Components;

use App\Actions\ReportSpamAction;
use App\Contracts\SpamReportableContract;
Expand Down
4 changes: 2 additions & 2 deletions app/Livewire/Pages/Forum/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ final class Index extends Component
use WithoutUrlPagination;
use WithPagination;

#[Url(as: 'channel')]
#[Url]
public ?string $channel = null;

#[Url(as: 'solved')]
#[Url]
public ?string $solved = null;

#[Url(as: 'me')]
Expand Down
49 changes: 49 additions & 0 deletions app/Livewire/Pages/Forum/Leaderboard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace App\Livewire\Pages\Forum;

use App\Models\User;
use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Cache;
use Livewire\Attributes\Layout;
use Livewire\Component;

#[Layout('layouts.forum')]
final class Leaderboard extends Component
{
public function render(): View
{
$startPosition = 1;
$leaders = collect();

/** @var Collection $leaderboard */
$leaderboard = User::mostSolutionsInLastDays(365)
->take(30)
->get()
->reject(fn ($leaderboard) => $leaderboard->solutions_count === 0); // @phpstan-ignore-line

if ($leaderboard->count() > 3) {
$leaders = $leaderboard->slice(0, 3);
$startPosition = 4;
}

return view('livewire.pages.forum.leaderboard', [
'members' => Cache::remember(
key: 'members',
ttl: now()->addWeek(),
callback: fn () => $leaderboard->reject(
fn (User $user) => in_array($user->id, $leaders->pluck('id')->toArray()) // @phpstan-ignore-line
)
),
'leaders' => Cache::remember(
key: 'leaders',
ttl: now()->addWeek(),
callback: fn () => $leaders
),
'startPosition' => $startPosition,
]);
}
}
2 changes: 1 addition & 1 deletion app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ public function countThreads(): int
public function scopeMostSolutions(Builder $query, ?int $inLastDays = null): Builder
{
return $query->withCount(['replyAble as solutions_count' => function ($query) use ($inLastDays) {
$query->where('replyable_type', 'threads')
$query->where('replyable_type', 'thread')
->join('threads', 'threads.solution_reply_id', '=', 'replies.id');

if ($inLastDays) {
Expand Down
24 changes: 0 additions & 24 deletions app/View/Composers/TopMembersComposer.php

This file was deleted.

8 changes: 8 additions & 0 deletions lang/en/global.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,13 @@
'language' => 'Language',
'french' => 'French',
'english' => 'English',
'experience' => 'Experience',
'last_active' => 'Last active',
'first_place' => '1st place',
'second_place' => '2nd place',
'third_place' => '3rd place',
'ranking_updated' => 'The rankings are updated weekly.',
'place' => 'Place',
'user' => 'User',

];
1 change: 1 addition & 0 deletions lang/en/pages/forum.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,6 @@
'prevent_text_one' => 'Make sure you\'ve read our',
'rules' => 'rules of conduct',
'prevent_text_two' => 'before replying to this thread.',
'leaderboard_empty' => 'No ranking available',

];
9 changes: 9 additions & 0 deletions lang/fr/global.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,13 @@
'language' => 'Langue',
'french' => 'Français',
'english' => 'Anglais',
'experience' => 'Expérience',
'last_active' => 'Dernière activité',
'first_place' => '1ere place',
'second_place' => '2e place',
'third_place' => '3e place',
'ranking_updated' => 'Ce classement est mis à jour toutes les semaines.',
'place' => 'Position',
'user' => 'Utilisateur',

];
1 change: 1 addition & 0 deletions lang/fr/pages/forum.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,6 @@
'prevent_text_one' => 'Assurez-vous d\'avoir lu nos',
'rules' => 'règles de conduite',
'prevent_text_two' => 'avant de répondre à ce thread.',
'leaderboard_empty' => 'Aucun classement disponible',

];
8 changes: 7 additions & 1 deletion resources/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@
@import 'tag.css';
@import 'forms.css';
@import 'torchlight.css';
@import 'toc.css';
@import 'forum.css';
@import 'header.css';

@property --border-angle {
inherits: false;
initial-value: 0deg;
syntax: '<angle>';
}

:root {
--laravel: #F56857;
--livewire: #fb70a9;
Expand Down
69 changes: 0 additions & 69 deletions resources/css/file-upload.css

This file was deleted.

22 changes: 22 additions & 0 deletions resources/css/forum.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#leaderboard {
*, *::before, *::after {
box-sizing: border-box;
transform-style: preserve-3d;
}

.leaderboard {
place-items: center;
transform: perspective(400px);
transform-style: preserve-3d;
}

.leaderboard > .stage {
@apply relative w-full rounded-t-lg;
transform: rotateX(70deg);
}

.leaderboard > .stage > .stage-front {
@apply absolute w-full rounded-b-lg origin-top top-full;
transform: rotateX(-80deg);
}
}
18 changes: 0 additions & 18 deletions resources/css/toc.css

This file was deleted.

79 changes: 79 additions & 0 deletions resources/views/components/forum/leader.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
@props([
'user',
'position',
])

@php
$icon = match ($position) {
1 => 'icon.trophies.first',
2 => 'icon.trophies.second',
3 => 'icon.trophies.third',
default => 'phosphor-trophy-duotone',
};

$ranking = match ($position) {
1 => __('global.first_place'),
2 => __('global.second_place'),
3 => __('global.third_place'),
default => 'N/A',
};

$color = match ($position) {
1 => 'success',
2 => 'warning',
3 => 'danger',
default => 'gray',
};
@endphp

<div class="bg-white divide-y divide-gray-200 rounded-lg ring-1 ring-gray-200 dark:bg-gray-800 dark:ring-white/10 dark:divide-white/10">
<div class="flex gap-4 p-4">
<div class="relative flex-1 flex items-center gap-2">
<x-filament::badge :color="$color" class="absolute -top-7 !rounded-full">
{{ $ranking }}
</x-filament::badge>
<x-user.avatar :user="$user" class="size-7" />
<div class="text-sm truncate">
<h5 class="font-medium text-gray-900 truncate dark:text-white">
{{ $user->name }}
</h5>
<span class="text-gray-500 dark:text-gray-400">
{{ '@' . $user->username }}
</span>
</div>
</div>
<div>
<x-dynamic-component :component="$icon" class="size-10" aria-hidden="true" />
</div>
</div>
<div class="flex divide-x divide-gray-200 dark:divide-white/10">
<div class="flex flex-col px-4 py-2.5">
<span class="text-xs/4 text-gray-400 capitalize dark:text-gray-500">
{{ __('global.experience') }}
</span>
<span class="font-medium text-sm text-gray-700 dark:text-gray-300">
{{ $user->getPoints() }}
</span>
</div>
<div class="flex flex-col px-4 py-2.5">
<span class="text-xs/4 text-gray-400 capitalize dark:text-gray-500">
{{ __('global.answers') }}
</span>
<span class="font-medium text-sm text-gray-700 dark:text-gray-300">
{{ $user->solutions_count }}
</span>
</div>
<div @class([
'flex flex-col px-4 py-2.5',
'lg:hidden' => $position !== 1,
])>
<span class="text-xs/4 text-gray-400 capitalize dark:text-gray-500">
{{ __('global.last_active') }}
</span>

<span class="font-medium text-sm text-gray-700 dark:text-gray-300">
{{ $user->last_active_at?->diffForHumans() }}
</span>
</div>
</div>
</div>
2 changes: 1 addition & 1 deletion resources/views/components/forum/thread.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class="inline-flex items-center rounded-xl gap-1 px-2 py-0.5 font-medium bg-prim
</span>
</x-link>
<span class="flex items-center text-xs text-gray-500 flex-wrap gap-1 dark:text-gray-400">
<span>{{ __('global.ask') }}</span>
<span class="hidden lg:inline">{{ __('global.ask') }}</span>
<time datetime="{{ $thread->created_at }}">
{{ $thread->created_at->diffForHumans() }}
</time>
Expand Down
Loading
Loading