Mod Filter Page - Per Page Option - Validate Value

This change validates the input of the per page option so that it has to be one of the provided options. If an option does not match a provided option, it's set to the closest available option. For example, manually setting it to 100000 in the URL param will have it automatically set to the largest option, 50, while manually setting it to 1 will change it to 6, the smallest option.

Also made some small language adjustments to get everything to fit a little nicer in the mobile views.
This commit is contained in:
Refringe 2024-10-07 09:53:30 -06:00
parent 53e3fd36da
commit 75b8be1e1e
Signed by: Refringe
SSH Key Fingerprint: SHA256:t865XsQpfTeqPRBMN2G6+N8wlDjkgUCZF3WGW6O9N/k
2 changed files with 40 additions and 10 deletions

View File

@ -9,6 +9,7 @@ use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Livewire\Attributes\Computed; use Livewire\Attributes\Computed;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Session; use Livewire\Attributes\Session;
use Livewire\Attributes\Url; use Livewire\Attributes\Url;
use Livewire\Component; use Livewire\Component;
@ -32,8 +33,18 @@ class Listing extends Component
#[Url] #[Url]
public string $order = 'created'; public string $order = 'created';
/**
* The number of results to show on a single page.
*/
#[Session]
#[Url] #[Url]
public int $resultsPerPage = 12; public int $perPage = 12;
/**
* The options that are available for the per page setting.
*/
#[Locked]
public array $perPageOptions = [6, 12, 24, 50];
/** /**
* The SPT versions filter value. * The SPT versions filter value.
@ -83,6 +94,8 @@ class Listing extends Component
*/ */
public function render(): View public function render(): View
{ {
$this->validatePerPage();
// Fetch the mods using the filters saved to the component properties. // Fetch the mods using the filters saved to the component properties.
$filters = [ $filters = [
'query' => $this->query, 'query' => $this->query,
@ -90,13 +103,32 @@ class Listing extends Component
'order' => $this->order, 'order' => $this->order,
'sptVersions' => $this->sptVersions, 'sptVersions' => $this->sptVersions,
]; ];
$mods = (new ModFilter($filters))->apply()->paginate($this->resultsPerPage);
$mods = (new ModFilter($filters))->apply()->paginate($this->perPage);
$this->redirectOutOfBoundsPage($mods); $this->redirectOutOfBoundsPage($mods);
return view('livewire.mod.listing', compact('mods')); return view('livewire.mod.listing', compact('mods'));
} }
/**
* Validate that the option selected is an option that is available by setting it to the closest available version.
*/
public function validatePerPage(): void
{
$this->perPage = collect($this->perPageOptions)->pipe(function ($data) {
$closest = null;
foreach ($data as $item) {
if ($closest === null || abs($this->perPage - $closest) > abs($item - $this->perPage)) {
$closest = $item;
}
}
return $closest;
});
}
/** /**
* Check if the current page is greater than the last page. Redirect if it is. * Check if the current page is greater than the last page. Redirect if it is.
*/ */

View File

@ -105,14 +105,14 @@
<div class="flex"> <div class="flex">
{{-- Large display can show full text --}} {{-- Large display can show full text --}}
<button type="button" @click="isResultsPerPageOpen = !isResultsPerPageOpen" class="hidden lg:flex group inline-flex justify-center text-sm font-medium text-gray-700 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100" id="menu-button" :aria-expanded="isResultsPerPageOpen.toString()" aria-haspopup="true"> <button type="button" @click="isResultsPerPageOpen = !isResultsPerPageOpen" class="hidden lg:flex group inline-flex justify-center text-sm font-medium text-gray-700 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100" id="menu-button" :aria-expanded="isResultsPerPageOpen.toString()" aria-haspopup="true">
{{ __('Results Per Page') }} {{ __('Per Page') }}
<svg class="-mr-1 ml-1 h-5 w-5 flex-shrink-0 text-gray-400 group-hover:text-gray-500" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> <svg class="-mr-1 ml-1 h-5 w-5 flex-shrink-0 text-gray-400 group-hover:text-gray-500" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd" /> <path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd" />
</svg> </svg>
</button> </button>
{{-- Only show selected number on smaller screens --}} {{-- Only show selected number on smaller screens --}}
<button type="button" @click="isResultsPerPageOpen = !isResultsPerPageOpen" class="lg:hidden group inline-flex justify-center text-sm font-medium text-gray-700 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100" id="menu-button" :aria-expanded="isResultsPerPageOpen.toString()" aria-haspopup="true"> <button type="button" @click="isResultsPerPageOpen = !isResultsPerPageOpen" class="lg:hidden group inline-flex justify-center text-sm font-medium text-gray-700 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100" id="menu-button" :aria-expanded="isResultsPerPageOpen.toString()" aria-haspopup="true" title="{{ __(':perPage results per page', ['perPage' => $perPage]) }}">
{{ $resultsPerPage }} {{ __(':perPage/p', ['perPage' => $perPage]) }}
<svg class="-mr-1 ml-1 h-5 w-5 flex-shrink-0 text-gray-400 group-hover:text-gray-500" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> <svg class="-mr-1 ml-1 h-5 w-5 flex-shrink-0 text-gray-400 group-hover:text-gray-500" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd" /> <path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd" />
</svg> </svg>
@ -129,11 +129,9 @@
class="absolute top-7 right-0 z-10 flex w-full min-w-[12rem] flex-col divide-y divide-slate-300 overflow-hidden rounded-xl border border-gray-300 bg-gray-100 dark:divide-gray-700 dark:border-gray-700 dark:bg-gray-800" class="absolute top-7 right-0 z-10 flex w-full min-w-[12rem] flex-col divide-y divide-slate-300 overflow-hidden rounded-xl border border-gray-300 bg-gray-100 dark:divide-gray-700 dark:border-gray-700 dark:bg-gray-800"
role="menu" aria-orientation="vertical" aria-labelledby="menu-button" tabindex="-1"> role="menu" aria-orientation="vertical" aria-labelledby="menu-button" tabindex="-1">
<div class="flex flex-col py-1.5"> <div class="flex flex-col py-1.5">
<x-filter-menu-item filterName="resultsPerPage" filter="6" :currentFilter="$resultsPerPage">6</x-filter-menu-item> @foreach($perPageOptions as $option)
<x-filter-menu-item filterName="resultsPerPage" filter="12" :currentFilter="$resultsPerPage">12</x-filter-menu-item> <x-filter-menu-item filterName="perPage" :filter="$option" :currentFilter="$perPage">{{ $option }}</x-filter-menu-item>
<x-filter-menu-item filterName="resultsPerPage" filter="24" :currentFilter="$resultsPerPage">24</x-filter-menu-item> @endforeach
<x-filter-menu-item filterName="resultsPerPage" filter="50" :currentFilter="$resultsPerPage">50</x-filter-menu-item>
<x-filter-menu-item filterName="resultsPerPage" filter="100" :currentFilter="$resultsPerPage">100</x-filter-menu-item>
</div> </div>
</div> </div>
</div> </div>