Reworked Follow Livewire Components

Fixes PHPStan errors and makes it a little more performant. Still not good enough. Making way to many queries for what it's doing.
This commit is contained in:
Refringe 2024-09-30 22:56:06 -04:00
parent df8e7f958d
commit 39a7640e92
Signed by: Refringe
SSH Key Fingerprint: SHA256:t865XsQpfTeqPRBMN2G6+N8wlDjkgUCZF3WGW6O9N/k
2 changed files with 52 additions and 31 deletions

View File

@ -3,7 +3,6 @@
namespace App\Livewire\User; namespace App\Livewire\User;
use App\Models\User; use App\Models\User;
use Illuminate\Support\Collection;
use Illuminate\View\View; use Illuminate\View\View;
use Livewire\Attributes\Locked; use Livewire\Attributes\Locked;
use Livewire\Attributes\On; use Livewire\Attributes\On;
@ -40,12 +39,16 @@ class FollowCard extends Component
public string $dialogTitle; public string $dialogTitle;
/** /**
* The users to display in the card. * The user data to display in the card.
*
* @var Collection<User>
*/ */
#[Locked] #[Locked]
public Collection $followUsers; public array $display = [];
/**
* The limited user data to display in the card.
*/
#[Locked]
public array $displayLimit = [];
/** /**
* The maximum number of users to display on the card. * The maximum number of users to display on the card.
@ -64,6 +67,12 @@ class FollowCard extends Component
#[Locked] #[Locked]
public User $profileUser; public User $profileUser;
/**
* The number of users being displayed.
*/
#[Locked]
public int $followUsersCount;
/** /**
* Called when the component is initialized. * Called when the component is initialized.
*/ */
@ -130,18 +139,31 @@ class FollowCard extends Component
public function populateFollowUsers(): void public function populateFollowUsers(): void
{ {
// Fetch IDs of all users the authenticated user is following. // Fetch IDs of all users the authenticated user is following.
$followingIds = auth()->user()->following()->pluck('following_id'); $followingIds = collect();
$authUser = auth()->user();
if ($authUser) {
$followingIds = $authUser->following()->pluck('following_id');
}
// Load the profile user's followers (or following) and map the follow status. // Load the profile user's followers (or following).
$this->followUsers = $this->profileUser->{$this->relationship} $users = $this->profileUser->{$this->relationship}()->with([])->get();
// Count the number of users.
$this->followUsersCount = $users->count();
// Load the users to display and whether the authenticated user is following each user.
$this->display = $users
->map(function (User $user) use ($followingIds) { ->map(function (User $user) use ($followingIds) {
// Add the follow status based on the preloaded IDs. return [
$user->follows = $followingIds->contains($user->id); 'user' => $user,
'isFollowing' => $followingIds->contains($user->id),
];
})->toArray();
// TODO: The above follows property doesn't exist on the User model. What was I smoking? // Store limited users for the main view.
$this->displayLimit = collect($this->display)
return $user; ->take($this->limit)
}); ->toArray();
} }
/** /**

View File

@ -4,37 +4,37 @@
<h2 class="text-2xl">{{ $title }}</h2> <h2 class="text-2xl">{{ $title }}</h2>
</div> </div>
@if (! $followUsers->count()) @if ($followUsersCount === 0)
<div class="flex justify-center text-sm pt-2"> <div class="flex justify-center text-sm pt-2">
{{ $emptyMessage }} {{ $emptyMessage }}
</div> </div>
@else @else
<div class="flex ml-6 py-2 justify-center items-center"> <div class="flex ml-6 py-2 justify-center items-center">
@foreach ($followUsers->slice(0, $limit) as $user) @foreach ($displayLimit as $data)
{{-- User Badge --}} {{-- User Badge --}}
<div class="relative group"> <div class="relative group">
<a href="{{ $user->profileUrl() }}" class="rounded-full -ml-6 z-20 bg-[#ebf4ff] h-16 w-16 flex justify-center items-center border"> <a href="{{ $data['user']->profileUrl() }}" class="rounded-full -ml-6 z-20 bg-[#ebf4ff] h-16 w-16 flex justify-center items-center border">
<img src="{{ $user->profile_photo_url }}" alt="{{ $user->name }}" class="h-full w-full rounded-full" /> <img src="{{ $data['user']->profile_photo_url }}" alt="{{ $data['user']->name }}" class="h-full w-full rounded-full" />
</a> </a>
<div class="absolute bottom-full -ml-3 left-1/2 transform -translate-x-1/2 mb-2 w-max px-2 py-1 text-sm text-white bg-gray-700 rounded shadow-lg opacity-0 group-hover:opacity-100"> <div class="absolute bottom-full -ml-3 left-1/2 transform -translate-x-1/2 mb-2 w-max px-2 py-1 text-sm text-white bg-gray-700 rounded shadow-lg opacity-0 group-hover:opacity-100">
{{ $user->name }} {{ $data['user']->name }}
</div> </div>
</div> </div>
@endforeach @endforeach
@if ($followUsers->count() > $limit) @if ($followUsersCount > $limit)
{{-- Count Badge --}} {{-- Count Badge --}}
<div class="relative group"> <div class="relative group">
<button wire:click="toggleFollowDialog" class="rounded-full -ml-6 z-20 bg-cyan-500 dark:bg-cyan-700 h-16 w-16 flex justify-center items-center border text-white">+{{ $followUsers->count() - $limit }}</button> <button wire:click="toggleFollowDialog" class="rounded-full -ml-6 z-20 bg-cyan-500 dark:bg-cyan-700 h-16 w-16 flex justify-center items-center border text-white">+{{ $followUsersCount - $limit }}</button>
<div class="absolute bottom-full -ml-3 left-1/2 transform -translate-x-1/2 mb-2 w-max px-2 py-1 text-sm text-white bg-gray-700 rounded shadow-lg opacity-0 group-hover:opacity-100"> <div class="absolute bottom-full -ml-3 left-1/2 transform -translate-x-1/2 mb-2 w-max px-2 py-1 text-sm text-white bg-gray-700 rounded shadow-lg opacity-0 group-hover:opacity-100">
{{ $followUsers->count() }} total {{ $followUsersCount }} total
</div> </div>
</div> </div>
@endif @endif
</div> </div>
@endif @endif
@if ($followUsers->count() > $limit) @if ($followUsersCount > $limit)
{{-- View All Button --}} {{-- View All Button --}}
<div class="flex justify-center items-center"> <div class="flex justify-center items-center">
<button wire:click="toggleFollowDialog" class="hover:underline active:underline">View All</button> <button wire:click="toggleFollowDialog" class="hover:underline active:underline">View All</button>
@ -49,28 +49,27 @@
</x-slot> </x-slot>
<x-slot name="content"> <x-slot name="content">
<div class="h-96 overflow-y-auto"> <div class="h-96 overflow-y-auto">
@foreach ($followUsers as $user) @foreach ($display as $data)
<div class="flex group/item dark:hover:bg-gray-950 items-center p-2 pr-3 rounded-md"> <div class="flex group/item dark:hover:bg-gray-950 items-center p-2 pr-3 rounded-md">
<a href="{{ $user->profileUrl() }}" class="flex-shrink-0 w-16 h-16 items-center"> <a href="{{ $data['user']->profileUrl() }}" class="flex-shrink-0 w-16 h-16 items-center">
<img src="{{ $user->profile_photo_url }}" alt="{{ $user->name }}" class="block w-full h-full rounded-full" /> <img src="{{ $data['user']->profile_photo_url }}" alt="{{ $data['user']->name }}" class="block w-full h-full rounded-full" />
</a> </a>
<div class="flex flex-col w-full pl-3"> <div class="flex flex-col w-full pl-3">
<a href="{{ $user->profileUrl() }}" class="text-2xl group-hover/item:underline group-hover/item:text-white">{{ $user->name }}</a> <a href="{{ $data['user']->profileUrl() }}" class="text-2xl group-hover/item:underline group-hover/item:text-white">{{ $data['user']->name }}</a>
<span> <span>
{{ __("Member Since") }} {{ __("Member Since") }}
<x-time :datetime="$user->created_at" /> <x-time :datetime="$data['user']->created_at" />
</span> </span>
</div> </div>
@if (auth()->check() && auth()->user()->id !== $user->id) @if (auth()->check() && auth()->user()->id !== $data['user']->id)
<livewire:user.follow-buttons :profile-user-id="$user->id" :is-following="$user->follows" /> <livewire:user.follow-buttons :profile-user-id="$data['user']->id" :is-following="$data['isFollowing']" />
@endif @endif
</div> </div>
@endforeach @endforeach
</div> </div>
</x-slot> </x-slot>
<x-slot name="footer"> <x-slot name="footer">
<x-button x-on:click="show = false"> <x-button x-on:click="show = false">
{{ __('Close') }} {{ __('Close') }}