Skip to content

Commit

Permalink
[Update] User Achievements
Browse files Browse the repository at this point in the history
- Added dedicated route for user/achievements
- Updated Profile/Badges/Index to be a proper page
  • Loading branch information
kiritokatklian committed Sep 7, 2024
1 parent ff7dd0a commit 3f91be7
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 74 deletions.
62 changes: 28 additions & 34 deletions app/Livewire/Profile/Badges/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

namespace App\Livewire\Profile\Badges;

use App\Models\Badge;
use App\Models\User;
use App\Models\UserBadge;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Pagination\CursorPaginator;
use Illuminate\Support\Collection;
use Livewire\Component;
use Livewire\WithPagination;

Expand All @@ -23,27 +25,11 @@ class Index extends Component
public User $user;

/**
* The current page query parameter's alias.
* Whether the component is ready to load.
*
* @var string $bgc
* @var bool $readyToLoad
*/
public string $bgc = '';

/**
* The current page query parameter.
*
* @var string $cursor
*/
public string $cursor = '';

/**
* The query strings of the component.
*
* @var string[] $queryString
*/
protected $queryString = [
'cursor' => ['as' => 'bgc']
];
public bool $readyToLoad = false;

/**
* Prepare the component.
Expand All @@ -58,23 +44,31 @@ public function mount(User $user): void
}

/**
* The user's badge list.
* Sets the property to load the page.
*
* @return CursorPaginator
* @return void
*/
public function loadPage(): void
{
$this->readyToLoad = true;
}

/**
* The user's achievement list.
*
* @return LengthAwarePaginator|Collection
*/
public function getBadgesProperty(): CursorPaginator
public function getAchievementsProperty(): LengthAwarePaginator|Collection
{
// We're aliasing `cursorName` as `bgc`, and setting
// query rule to never show `cursor` param when it's
// empty. Since `cursor` is also aliased as `bgc` in
// query rules, and we always keep it empty, as far
// as Livewire is concerned, `bgc` is also empty. So,
// `bgc` doesn't show up in the query params in the
// browser.
return $this->user->badges()
->with(['media'])
->orderBy(UserBadge::TABLE_NAME . '.created_at', 'desc')
->cursorPaginate(25, ['*'], 'bgc');
if (!$this->readyToLoad) {
return collect();
}

return Badge::achievedUserBadges($this->user)
->with('media')
->orderBy('is_achieved', 'desc')
->orderBy(UserBadge::TABLE_NAME . '.created_at')
->paginate(25);
}

/**
Expand Down
1 change: 0 additions & 1 deletion app/Livewire/Profile/Details.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ class Details extends Component
*/
private array $popupTypes = [
'edit',
'achievements',
];

/**
Expand Down
97 changes: 68 additions & 29 deletions resources/views/livewire/profile/badges/index.blade.php
Original file line number Diff line number Diff line change
@@ -1,33 +1,72 @@
<div>
<style>
ul#badgesList > li:nth-child(even) {
flex-direction: row-reverse;
}
</style>

<ul id="badgesList" class="m-0 space-y-4">
@foreach($this->badges as $badge)
@php
$borderColor = strtolower($badge->text_color) == '#ffffffff' ? '#ffffff80' : $badge->text_color;
@endphp
<li class="relative flex space-x-2 pt-4 pr-4 pb-4 pl-4 rounded-lg" style="background-color: {{ $badge->background_color }};">
<picture class="relative w-16 h-16 aspect-square rounded-full overflow-hidden">
<img class="w-full" src="{{ $badge->getFirstMediaFullUrl(\App\Enums\MediaCollection::Symbol()) }}" alt="{{ $badge->name }} Badge Image" width="{{ $badge->getFirstMedia(\App\Enums\MediaCollection::Symbol)?->custom_properties['width'] ?? 96 }}" height="{{ $badge->getFirstMedia(\App\Enums\MediaCollection::Symbol)?->custom_properties['height'] ?? 96 }}">

<div class="absolute top-0 left-0 h-full w-full border-2 rounded-full" style="border-color: {{ $borderColor }};"></div>
</picture>

<div class="flex-1" style="color: {{ $badge->text_color }};">
<p class="font-semibold">{{ $badge->name }}</p>
<p class="text-sm">{{ $badge->description }}</p>
<main>
<x-slot:title>
{{ __(':x’s Followers', ['x' => $user->username]) }}
</x-slot:title>

<x-slot:description>
{{ __('Browse :x’s achievements on Kurozora. Join the Kurozora community and create your anime, manga and game list. Discover songs, episodes and read reviews and news!', ['x' => $user->username]) }}
</x-slot:description>

<x-slot:meta>
<meta property="og:title" content="{{ __(':x’s Followers', ['x' => $user->username]) }}{{ config('app.name') }}" />
<meta property="og:description" content="{{ __('Browse :x’s achievements on Kurozora. Join the Kurozora community and create your anime, manga and game list. Discover songs, episodes and read reviews and news!', ['x' => $user->username]) }}" />
<meta property="og:image" content="{{ $user->getFirstMediaFullUrl(\App\Enums\MediaCollection::Profile()) }}" />
<meta property="og:type" content="website" />
<link rel="canonical" href="{{ route('profile.achievements', $user) }}">
</x-slot:meta>

<x-slot:appArgument>
users/{{ $user->id }}/achievements
</x-slot:appArgument>

<div class="max-w-7xl mx-auto pl-4 pr-4 py-6 sm:px-6" wire:init="loadPage">
<section class="mb-4">
<div>
<div class="flex gap-1">
<div class="flex flex-wrap items-center w-full">
<h1 class="text-2xl font-bold">{{ __(':x’s Achievements', ['x' => $user->username]) }}</h1>
</div>

<div class="flex flex-wrap flex-1 justify-end items-center w-full">
</div>
</div>
</div>
</section>

@if ($this->achievements->count())
<section class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
@foreach($this->achievements as $achievement)
<x-lockups.achievement-lockup :achievement="$achievement" />
@endforeach
</section>

<div class="mt-4">
{{ $this->achievements->links() }}
</div>
@elseif (!$readyToLoad)
<section class="mt-4">
<div class="flex gap-4 justify-between flex-wrap">
@foreach(range(1,25) as $range)
<div class="bg-gray-200 w-64 md:w-80 flex-grow" style="height: 168px;"></div>
@endforeach
<div class="w-64 md:w-80 flex-grow"></div>
<div class="w-64 md:w-80 flex-grow"></div>
</div>
</section>
@else
<section class="flex flex-col items-center mt-4 text-center">
<x-picture>
<img class="w-full max-w-sm" src="{{ asset('images/static/placeholders/empty_anime_library.webp') }}" alt="No reviews" title="No achievements">
</x-picture>

<div class="absolute top-0 right-0 w-full h-full border-2 rounded-lg" style="border-color: {{ $borderColor }};"></div>
</li>
@endforeach
</ul>
<p class="font-bold">{{ __('No Achievements') }}</p>

<div class="mt-4">
{{ $this->badges->links() }}
@if ($user->id == auth()->user()?->id)
<p class="text-sm text-gray-500">{{ __('Your unlocked achievements will show up here!') }}</p>
@else
<p class="text-sm text-gray-500">{{ __(':x has no achievements unlocked yet.', ['x' => $user->username]) }}</p>
@endif
</section>
@endif
</div>
</div>
</main>
11 changes: 1 addition & 10 deletions resources/views/livewire/profile/details.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
<div class="mt-2 pt-2 pb-2 px-3">{!! $user->biography_html !!}</div>

<div class="flex justify-between">
<x-profile-information-badge wire:click="togglePopupFor('achievements')">
<x-profile-information-badge href="{{ route('profile.achievements', $user) }}" wire:navigate>
<x-slot:title>{{ __('Achievements') }}</x-slot:title>
<x-slot:description>{{ number_shorten($counts['achievements_count'], 0, true) }}</x-slot:description>
</x-profile-information-badge>
Expand Down Expand Up @@ -106,14 +106,5 @@
</x-modal-form-section>
@endauth
@break
@case ('achievements')
<x-page-modal maxWidth="sm" model="showPopup">
<x-slot:title>
{{ __('Achievements') }}
</x-slot:title>

<livewire:profile.badges :user="$user" />
</x-page-modal>
@break
@endswitch
</main>
4 changes: 4 additions & 0 deletions routes/Web/Profile.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Http\Controllers\Web\Profile\GameLibraryController;
use App\Http\Controllers\Web\Profile\MangaLibraryController;
use App\Http\Controllers\Web\UserProfileController;
use App\Livewire\Profile\Badges\Index as AchievementsIndex;
use App\Livewire\Profile\Details;
use App\Livewire\Profile\Followers\Index as FollowersIndex;
use App\Livewire\Profile\Following\Index as FollowingIndex;
Expand Down Expand Up @@ -72,6 +73,9 @@
// ->name('.reminders');
});

Route::get('/achievements', AchievementsIndex::class)
->name('.achievements');

Route::get('/followers', FollowersIndex::class)
->name('.followers');

Expand Down

0 comments on commit 3f91be7

Please sign in to comment.