add: livewire top users

More cleanly modularized using livewire computed attributes. Abuses the fact that only one of the tabs is selected and most users won't access the other tabs. This significantly reduces the time spent loading the home page when the cache is cleared.
This commit is contained in:
Roardom
2024-06-01 15:43:35 +00:00
parent 2c949efaad
commit 80b9aa32bf
6 changed files with 666 additions and 577 deletions
+6 -136
View File
@@ -18,21 +18,15 @@ namespace App\Http\Controllers;
use App\Models\Article;
use App\Models\Bookmark;
use App\Models\Comment;
use App\Models\FeaturedTorrent;
use App\Models\FreeleechToken;
use App\Models\Group;
use App\Models\History;
use App\Models\Peer;
use App\Models\Poll;
use App\Models\Post;
use App\Models\Thank;
use App\Models\Topic;
use App\Models\Torrent;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Exception;
/**
@@ -75,7 +69,7 @@ class HomeController extends Controller
->where('last_action', '>', now()->subMinutes(60))
->orderByRaw('(select position from `groups` where `groups`.id = users.group_id), group_id, username')
->get()
->sortBy(fn ($user) => $user->privacy?->hidden || !$user->isVisible($user, 'other', 'show_online'))
->sortBy(fn ($user) => $user->privacy?->hidden || ! $user->isVisible($user, 'other', 'show_online')),
),
'groups' => cache()->remember(
'user-groups',
@@ -85,7 +79,7 @@ class HomeController extends Controller
'name',
'color',
'effect',
'icon'
'icon',
])
->oldest('position')
->get()
@@ -111,141 +105,17 @@ class HomeController extends Controller
->authorized(canReadTopic: true)
->latest()
->take(5)
->get()
->get(),
),
'featured' => cache()->remember(
'latest_featured',
$expiresAt,
fn () => FeaturedTorrent::with([
'torrent' => ['resolution', 'type', 'category'],
'user.group'
])->get()
),
'poll' => cache()->remember('latest_poll', $expiresAt, fn () => Poll::latest()->first()),
'uploaders' => cache()->remember(
'top-users:uploaders',
3_600,
fn () => Torrent::with(['user' , 'user.group'])
->select(DB::raw('user_id, COUNT(user_id) as value'))
->where('user_id', '!=', User::SYSTEM_USER_ID)
->where('anon', '=', false)
->groupBy('user_id')
->orderByDesc('value')
->take(8)
->get()
),
'downloaders' => cache()->remember(
'top-users:downloaders',
3_600,
fn () => History::with(['user' , 'user.group'])
->select(DB::raw('user_id, count(distinct torrent_id) as value'))
->whereNotNull('completed_at')
->where('user_id', '!=', User::SYSTEM_USER_ID)
->groupBy('user_id')
->orderByDesc('value')
->take(8)
->get()
),
'uploaded' => cache()->remember(
'top-users:uploaded',
3_600,
fn () => User::select(['id', 'group_id', 'username', 'uploaded', 'image'])
->where('id', '!=', User::SYSTEM_USER_ID)
->whereNotIn('group_id', Group::select('id')->whereIn('slug', ['banned', 'validating', 'disabled', 'pruned']))
->orderByDesc('uploaded')
->take(8)
->get(),
),
'downloaded' => cache()->remember(
'top-users:downloaded',
3_600,
fn () => User::select(['id', 'group_id', 'username', 'downloaded', 'image'])
->where('id', '!=', User::SYSTEM_USER_ID)
->whereNotIn('group_id', Group::select('id')->whereIn('slug', ['banned', 'validating', 'disabled', 'pruned']))
->orderByDesc('downloaded')
->take(8)
->get(),
),
'seeders' => cache()->remember(
'top-users:seeders',
3_600,
fn () => Peer::with(['user' , 'user.group'])
->select(DB::raw('user_id, count(distinct torrent_id) as value'))
->where('user_id', '!=', User::SYSTEM_USER_ID)
->where('seeder', '=', 1)
->where('active', '=', 1)
->groupBy('user_id')
->orderByDesc('value')
->take(8)
->get(),
),
'seedtimes' => cache()->remember(
'top-users:seedtimes',
3_600,
fn () => User::withSum('history as seedtime', 'seedtime')
->where('id', '!=', User::SYSTEM_USER_ID)
->whereNotIn('group_id', Group::select('id')->whereIn('slug', ['banned', 'validating', 'disabled', 'pruned']))
->orderByDesc('seedtime')
->take(8)
->get(),
),
'served' => cache()->remember(
'top-users:served',
3_600,
fn () => User::withCount('uploadSnatches')
->where('id', '!=', User::SYSTEM_USER_ID)
->whereNotIn('group_id', Group::select('id')->whereIn('slug', ['banned', 'validating', 'disabled', 'pruned']))
->orderByDesc('upload_snatches_count')
->take(8)
->get(),
),
'commenters' => cache()->remember(
'top-users:commenters',
3_600,
fn () => Comment::with(['user' , 'user.group'])
->select(DB::raw('user_id, COUNT(user_id) as value'))
->where('user_id', '!=', User::SYSTEM_USER_ID)
->where('anon', '=', false)
->groupBy('user_id')
->orderByRaw('COALESCE(value, 0) DESC')
->take(8)
->get()
),
'posters' => cache()->remember(
'top-users:posters',
3_600,
fn () => Post::with(['user' , 'user.group'])
->select(DB::raw('user_id, COUNT(user_id) as value'))
->where('user_id', '!=', User::SYSTEM_USER_ID)
->groupBy('user_id')
->orderByRaw('COALESCE(value, 0) DESC')
->take(8)
->get()
),
'thankers' => cache()->remember(
'top-users:thankers',
3_600,
fn () => Thank::with(['user' , 'user.group'])
->select(DB::raw('user_id, COUNT(user_id) as value'))
->where('user_id', '!=', User::SYSTEM_USER_ID)
->groupBy('user_id')
->orderByRaw('COALESCE(value, 0) DESC')
->take(8)
->get()
),
'personals' => cache()->remember(
'top-users:personals',
3_600,
fn () => Torrent::with(['user' , 'user.group'])
->select(DB::raw('user_id, COUNT(user_id) as value'))
->where('user_id', '!=', User::SYSTEM_USER_ID)
->where('anon', '=', false)
->where('personal_release', '=', 1)
->groupBy('user_id')
->orderByDesc('value')
->take(8)
->get()
'user.group',
])->get(),
),
'poll' => cache()->remember('latest_poll', $expiresAt, fn () => Poll::latest()->first()),
'freeleech_tokens' => FreeleechToken::where('user_id', $user->id)->get(),
'bookmarks' => Bookmark::where('user_id', $user->id)->get(),
]);
+199
View File
@@ -0,0 +1,199 @@
<?php
declare(strict_types=1);
namespace App\Http\Livewire;
use App\Models\Comment;
use App\Models\Group;
use App\Models\History;
use App\Models\Peer;
use App\Models\Post;
use App\Models\Thank;
use App\Models\Torrent;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Livewire\Attributes\Computed;
use Livewire\Component;
class TopUsers extends Component
{
public string $tab = 'uploaders';
/**
* @return \Illuminate\Support\Collection<int, Torrent>
*/
#[Computed(cache: true)]
final public function uploaders(): \Illuminate\Support\Collection
{
return Torrent::with(['user.group'])
->select(DB::raw('user_id, COUNT(user_id) as value'))
->where('user_id', '!=', User::SYSTEM_USER_ID)
->where('anon', '=', false)
->groupBy('user_id')
->orderByDesc('value')
->take(8)
->get();
}
/**
* @return \Illuminate\Support\Collection<int, History>
*/
#[Computed(cache: true)]
final public function downloaders(): \Illuminate\Support\Collection
{
return History::with(['user.group'])
->select(DB::raw('user_id, count(distinct torrent_id) as value'))
->whereNotNull('completed_at')
->where('user_id', '!=', User::SYSTEM_USER_ID)
->groupBy('user_id')
->orderByDesc('value')
->take(8)
->get();
}
/**
* @return \Illuminate\Support\Collection<int, User>
*/
#[Computed(cache: true)]
final public function uploaded(): \Illuminate\Support\Collection
{
return User::select(['id', 'group_id', 'username', 'uploaded', 'image'])
->with('group')
->where('id', '!=', User::SYSTEM_USER_ID)
->whereNotIn('group_id', Group::select('id')->whereIn('slug', ['banned', 'validating', 'disabled', 'pruned']))
->orderByDesc('uploaded')
->take(8)
->get();
}
/**
* @return \Illuminate\Support\Collection<int, User>
*/
#[Computed(cache: true)]
final public function downloaded(): \Illuminate\Support\Collection
{
return User::select(['id', 'group_id', 'username', 'downloaded', 'image'])
->with('group')
->where('id', '!=', User::SYSTEM_USER_ID)
->whereNotIn('group_id', Group::select('id')->whereIn('slug', ['banned', 'validating', 'disabled', 'pruned']))
->orderByDesc('downloaded')
->take(8)
->get();
}
/**
* @return \Illuminate\Support\Collection<int, Peer>
*/
#[Computed(cache: true)]
final public function seeders(): \Illuminate\Support\Collection
{
return Peer::with(['user.group'])
->select(DB::raw('user_id, count(distinct torrent_id) as value'))
->where('user_id', '!=', User::SYSTEM_USER_ID)
->where('seeder', '=', 1)
->where('active', '=', 1)
->groupBy('user_id')
->orderByDesc('value')
->take(8)
->get();
}
/**
* @return \Illuminate\Support\Collection<int, User>
*/
#[Computed(cache: true)]
final public function seedtimes(): \Illuminate\Support\Collection
{
return User::withSum('history as seedtime', 'seedtime')
->with('group')
->where('id', '!=', User::SYSTEM_USER_ID)
->whereNotIn('group_id', Group::select('id')->whereIn('slug', ['banned', 'validating', 'disabled', 'pruned']))
->orderByDesc('seedtime')
->take(8)
->get();
}
/**
* @return \Illuminate\Support\Collection<int, User>
*/
#[Computed(cache: true)]
final public function served(): \Illuminate\Support\Collection
{
return User::withCount('uploadSnatches')
->with('group')
->where('id', '!=', User::SYSTEM_USER_ID)
->whereNotIn('group_id', Group::select('id')->whereIn('slug', ['banned', 'validating', 'disabled', 'pruned']))
->orderByDesc('upload_snatches_count')
->take(8)
->get();
}
/**
* @return \Illuminate\Support\Collection<int, Comment>
*/
#[Computed(cache: true)]
final public function commenters(): \Illuminate\Support\Collection
{
return Comment::with(['user.group'])
->select(DB::raw('user_id, COUNT(user_id) as value'))
->where('user_id', '!=', User::SYSTEM_USER_ID)
->where('anon', '=', false)
->groupBy('user_id')
->orderByRaw('COALESCE(value, 0) DESC')
->take(8)
->get();
}
/**
* @return \Illuminate\Support\Collection<int, Post>
*/
#[Computed(cache: true)]
final public function posters(): \Illuminate\Support\Collection
{
return Post::with(['user.group'])
->select(DB::raw('user_id, COUNT(user_id) as value'))
->where('user_id', '!=', User::SYSTEM_USER_ID)
->groupBy('user_id')
->orderByRaw('COALESCE(value, 0) DESC')
->take(8)
->get();
}
/**
* @return \Illuminate\Support\Collection<int, Thank>
*/
#[Computed(cache: true)]
final public function thankers(): \Illuminate\Support\Collection
{
return Thank::with(['user.group'])
->select(DB::raw('user_id, COUNT(user_id) as value'))
->where('user_id', '!=', User::SYSTEM_USER_ID)
->groupBy('user_id')
->orderByRaw('COALESCE(value, 0) DESC')
->take(8)
->get();
}
/**
* @return \Illuminate\Support\Collection<int, Torrent>
*/
#[Computed(cache: true)]
final public function personals(): \Illuminate\Support\Collection
{
return Torrent::with(['user.group'])
->select(DB::raw('user_id, COUNT(user_id) as value'))
->where('user_id', '!=', User::SYSTEM_USER_ID)
->where('anon', '=', false)
->where('personal_release', '=', 1)
->groupBy('user_id')
->orderByDesc('value')
->take(8)
->get();
}
public function render(): \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Contracts\Foundation\Application
{
return view('livewire.top-users');
}
}
-429
View File
@@ -1,429 +0,0 @@
<section class="panelV2 blocks__uploaders" x-data="{ tab: 'uploaders' }">
<h2 class="panel__heading">Top Users</h2>
<menu class="panel__tabs">
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'uploaders' && 'panel__tab--active'"
x-on:click="tab = 'uploaders'"
>
Uploaders
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'downloaders' && 'panel__tab--active'"
x-on:click="tab = 'downloaders'"
>
Downloaders
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'uploaded' && 'panel__tab--active'"
x-on:click="tab = 'uploaded'"
>
Uploaded
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'downloaded' && 'panel__tab--active'"
x-on:click="tab = 'downloaded'"
>
Downloaded
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'seeders' && 'panel__tab--active'"
x-on:click="tab = 'seeders'"
>
Seeders
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'seedtime' && 'panel__tab--active'"
x-on:click="tab = 'seedtime'"
>
Seedtime
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'served' && 'panel__tab--active'"
x-on:click="tab = 'served'"
>
Users Served
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'commenters' && 'panel__tab--active'"
x-on:click="tab = 'commenters'"
>
Commenters
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'posters' && 'panel__tab--active'"
x-on:click="tab = 'posters'"
>
Posters
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'thankers' && 'panel__tab--active'"
x-on:click="tab = 'thankers'"
>
Thankers
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'personals' && 'panel__tab--active'"
x-on:click="tab = 'personals'"
>
Personal Releases
</li>
</menu>
<div class="panel__body">
<div class="user-stat-card-container" x-show="tab === 'uploaders'">
@foreach ($uploaders as $uploader)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$uploader->user"
:anon="$uploader->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">{{ $uploader->value }} Uploads</h4>
@if ($uploader->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($uploader->user->image === null ? 'img/profile.png' : 'files/img/' . $uploader->user->image) }}"
/>
@endif
</article>
@endforeach
</div>
<div class="user-stat-card-container" x-clock x-show="tab === 'downloaders'">
@foreach ($downloaders as $downloader)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$downloader->user"
:anon="$downloader->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">{{ $downloader->value }} Downloads</h4>
@if ($downloader->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($downloader->user->image === null ? 'img/profile.png' : 'files/img/' . $downloader->user->image) }}"
/>
@endif
</article>
@endforeach
</div>
<div class="user-stat-card-container" x-clock x-show="tab === 'uploaded'">
@foreach ($uploaded as $upload)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag :user="$upload" :anon="$upload->privacy?->private_profile" />
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">
{{ App\Helpers\StringHelper::formatBytes($upload->uploaded, 2) }} Uploaded
</h4>
@if ($upload->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($upload->image === null ? 'img/profile.png' : 'files/img/' . $upload->image) }}"
/>
@endif
</article>
@endforeach
</div>
<div class="user-stat-card-container" x-clock x-show="tab === 'downloaded'">
@foreach ($downloaded as $download)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$download"
:anon="$download->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">
{{ App\Helpers\StringHelper::formatBytes($download->downloaded, 2) }}
Downloaded
</h4>
@if ($download->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($download->image === null ? 'img/profile.png' : 'files/img/' . $download->image) }}"
/>
@endif
</article>
@endforeach
</div>
<div class="user-stat-card-container" x-show="tab === 'seeders'">
@foreach ($seeders as $seeder)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$seeder->user"
:anon="$seeder->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">{{ $seeder->value }} Seeds</h4>
@if ($seeder->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($seeder->user->image === null ? 'img/profile.png' : 'files/img/' . $seeder->user->image) }}"
/>
@endif
</article>
@endforeach
</div>
<div class="user-stat-card-container" x-show="tab === 'seedtime'">
@foreach ($seedtimes as $seedtime)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$seedtime"
:anon="$seedtime->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">
{{ App\Helpers\StringHelper::timeElapsed($seedtime->seedtime ?? 0) }}
Seedtime Average
</h4>
@if ($seedtime->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($seedtime->image === null ? 'img/profile.png' : 'files/img/' . $seedtime->image) }}"
/>
@endif
</article>
@endforeach
</div>
<div class="user-stat-card-container" x-show="tab === 'served'">
@foreach ($served as $serve)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag :user="$serve" :anon="$serve->privacy?->private_profile" />
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">
{{ $serve->upload_snatches_count }} Users Served
</h4>
@if ($serve->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($serve->image === null ? 'img/profile.png' : 'files/img/' . $serve->image) }}"
/>
@endif
</article>
@endforeach
</div>
<div class="user-stat-card-container" x-show="tab === 'commenters'">
@foreach ($commenters as $commenter)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$commenter->user"
:anon="$commenter->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">{{ $commenter->value }} Comments Made</h4>
@if ($commenter->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($commenter->user->image === null ? 'img/profile.png' : 'files/img/' . $commenter->user->image) }}"
/>
@endif
</article>
@endforeach
</div>
<div class="user-stat-card-container" x-show="tab === 'posters'">
@foreach ($posters as $poster)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$poster->user"
:anon="$poster->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">{{ $poster->value }} Posts Made</h4>
@if ($poster->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($poster->user->image === null ? 'img/profile.png' : 'files/img/' . $poster->user->image) }}"
/>
@endif
</article>
@endforeach
</div>
<div class="user-stat-card-container" x-show="tab === 'thankers'">
@foreach ($thankers as $thanker)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$thanker->user"
:anon="$thanker->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">{{ $thanker->value }} Thanks Given</h4>
@if ($thanker->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($thanker->user->image === null ? 'img/profile.png' : 'files/img/' . $thanker->user->image) }}"
/>
@endif
</article>
@endforeach
</div>
<div class="user-stat-card-container" x-show="tab === 'personals'">
@foreach ($personals as $personal)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$personal->user"
:anon="$personal->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">{{ $personal->value }} Personal Releases</h4>
@if ($personal->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($personal->user->image === null ? 'img/profile.png' : 'files/img/' . $personal->user->image) }}"
/>
@endif
</article>
@endforeach
</div>
</div>
</section>
+1 -1
View File
@@ -15,7 +15,7 @@
@livewire('random-media')
@include('blocks.poll')
@livewire('top-torrents')
@include('blocks.top_users')
@livewire('top-users')
@include('blocks.latest_topics')
@include('blocks.latest_posts')
@include('blocks.online')
@@ -0,0 +1,460 @@
<section class="panelV2 blocks__uploaders" x-data="{ tab: @entangle('tab').live }">
<h2 class="panel__heading">Top Users</h2>
<menu class="panel__tabs">
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'uploaders' && 'panel__tab--active'"
x-on:click="tab = 'uploaders'"
>
Uploaders
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'downloaders' && 'panel__tab--active'"
x-on:click="tab = 'downloaders'"
>
Downloaders
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'uploaded' && 'panel__tab--active'"
x-on:click="tab = 'uploaded'"
>
Uploaded
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'downloaded' && 'panel__tab--active'"
x-on:click="tab = 'downloaded'"
>
Downloaded
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'seeders' && 'panel__tab--active'"
x-on:click="tab = 'seeders'"
>
Seeders
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'seedtime' && 'panel__tab--active'"
x-on:click="tab = 'seedtime'"
>
Seedtime
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'served' && 'panel__tab--active'"
x-on:click="tab = 'served'"
>
Users Served
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'commenters' && 'panel__tab--active'"
x-on:click="tab = 'commenters'"
>
Commenters
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'posters' && 'panel__tab--active'"
x-on:click="tab = 'posters'"
>
Posters
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'thankers' && 'panel__tab--active'"
x-on:click="tab = 'thankers'"
>
Thankers
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'personals' && 'panel__tab--active'"
x-on:click="tab = 'personals'"
>
Personal Releases
</li>
</menu>
<div class="panel__body" wire:loading.block>Loading...</div>
<div class="panel__body" wire:loading.remove>
<div class="user-stat-card-container">
@switch($this->tab)
@case('uploaders')
@foreach ($this->uploaders as $uploader)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$uploader->user"
:anon="$uploader->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">{{ $uploader->value }} Uploads</h4>
@if ($uploader->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($uploader->user->image === null ? 'img/profile.png' : 'files/img/' . $uploader->user->image) }}"
/>
@endif
</article>
@endforeach
@break
@case('downloaders')
@foreach ($this->downloaders as $downloader)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$downloader->user"
:anon="$downloader->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">
{{ $downloader->value }} Downloads
</h4>
@if ($downloader->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($downloader->user->image === null ? 'img/profile.png' : 'files/img/' . $downloader->user->image) }}"
/>
@endif
</article>
@endforeach
@break
@case('uploaded')
@foreach ($this->uploaded as $upload)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$upload"
:anon="$upload->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">
{{ App\Helpers\StringHelper::formatBytes($upload->uploaded, 2) }}
Uploaded
</h4>
@if ($upload->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($upload->image === null ? 'img/profile.png' : 'files/img/' . $upload->image) }}"
/>
@endif
</article>
@endforeach
@break
@case('downloaded')
@foreach ($this->downloaded as $download)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$download"
:anon="$download->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">
{{ App\Helpers\StringHelper::formatBytes($download->downloaded, 2) }}
Downloaded
</h4>
@if ($download->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($download->image === null ? 'img/profile.png' : 'files/img/' . $download->image) }}"
/>
@endif
</article>
@endforeach
@break
@case('seeders')
@foreach ($this->seeders as $seeder)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$seeder->user"
:anon="$seeder->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">{{ $seeder->value }} Seeds</h4>
@if ($seeder->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($seeder->user->image === null ? 'img/profile.png' : 'files/img/' . $seeder->user->image) }}"
/>
@endif
</article>
@endforeach
@break
@case('seedtime')
@foreach ($this->seedtimes as $seedtime)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$seedtime"
:anon="$seedtime->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">
{{ App\Helpers\StringHelper::timeElapsed($seedtime->seedtime ?? 0) }}
Seedtime Average
</h4>
@if ($seedtime->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($seedtime->image === null ? 'img/profile.png' : 'files/img/' . $seedtime->image) }}"
/>
@endif
</article>
@endforeach
@break
@case('served')
@foreach ($this->served as $serve)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$serve"
:anon="$serve->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">
{{ $serve->upload_snatches_count }} Users Served
</h4>
@if ($serve->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($serve->image === null ? 'img/profile.png' : 'files/img/' . $serve->image) }}"
/>
@endif
</article>
@endforeach
@break
@case('commenters')
@foreach ($this->commenters as $commenter)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$commenter->user"
:anon="$commenter->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">
{{ $commenter->value }} Comments Made
</h4>
@if ($commenter->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($commenter->user->image === null ? 'img/profile.png' : 'files/img/' . $commenter->user->image) }}"
/>
@endif
</article>
@endforeach
@break
@case('posters')
@foreach ($this->posters as $poster)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$poster->user"
:anon="$poster->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">{{ $poster->value }} Posts Made</h4>
@if ($poster->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($poster->user->image === null ? 'img/profile.png' : 'files/img/' . $poster->user->image) }}"
/>
@endif
</article>
@endforeach
@break
@case('thankers')
@foreach ($this->thankers as $thanker)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$thanker->user"
:anon="$thanker->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">
{{ $thanker->value }} Thanks Given
</h4>
@if ($thanker->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($thanker->user->image === null ? 'img/profile.png' : 'files/img/' . $thanker->user->image) }}"
/>
@endif
</article>
@endforeach
@break
@case('personals')
@foreach ($this->personals as $personal)
<article class="user-stat-card">
<h3 class="user-stat-card__username">
<x-user_tag
:user="$personal->user"
:anon="$personal->user->privacy?->private_profile"
/>
<div title="Place" class="top-users__place">
{{ Number::ordinal($loop->iteration) }}
</div>
</h3>
<h4 class="user-stat-card__stat">
{{ $personal->value }} Personal Releases
</h4>
@if ($personal->user->privacy?->private_profile)
<img
class="user-stat-card__avatar"
alt=""
src="{{ url('img/profile.png') }}"
/>
@else
<img
class="user-stat-card__avatar"
alt=""
src="{{ url($personal->user->image === null ? 'img/profile.png' : 'files/img/' . $personal->user->image) }}"
/>
@endif
</article>
@endforeach
@break
@endswitch
</div>
</div>
</section>
@@ -31,17 +31,6 @@ test('index returns an ok response', function (): void {
$response->assertViewHas('posts');
$response->assertViewHas('featured');
$response->assertViewHas('poll');
$response->assertViewHas('uploaders');
$response->assertViewHas('downloaders');
$response->assertViewHas('uploaded');
$response->assertViewHas('downloaded');
$response->assertViewHas('seeders');
$response->assertViewHas('seedtimes');
$response->assertViewHas('served');
$response->assertViewHas('commenters');
$response->assertViewHas('posters');
$response->assertViewHas('thankers');
$response->assertViewHas('personals');
$response->assertViewHas('freeleech_tokens');
$response->assertViewHas('bookmarks');
});