Skip to content

Commit

Permalink
feat: added functional pagination
Browse files Browse the repository at this point in the history
Co-authored-by: fero <[email protected]>
  • Loading branch information
Wamy-Dev and ferothefox committed Aug 15, 2023
1 parent 24ba9e3 commit e916b26
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 25 deletions.
2 changes: 1 addition & 1 deletion apps/web/src/lib/components/ModListItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

<a href={`/mod/${slug}`}>
<div
class="beatforge-discover-list-item flex flex-row gap-2 md:gap-4 w-full bg-primary-850 hover:bg-primary-900 border-b-[1px] border-primary-850 items-center p-2 md:p-4 min-w-0 transition hover:duration-[0ms] duration-[120ms] my-2 md:my-0">
class="beatforge-discover-list-item flex flex-row gap-2 md:gap-4 w-full bg-primary-800 hover:bg-primary-850 border-b-[1px] border-primary-850 items-center p-2 md:p-4 min-w-0 transition hover:duration-[0ms] duration-[120ms] my-2 md:my-0 rounded-lg md:rounded-none">
<div
class="beatforge-discover-list-item-image h-12 w-12 md:h-24 md:w-24 bg-primary-600 flex flex-shrink-0 overflow-hidden rounded-md mr-2"
>
Expand Down
234 changes: 213 additions & 21 deletions apps/web/src/routes/discover/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
// import Search from '$lib/components/icons/search.svelte';
import { SearchIcon, ChevronDownIcon } from 'ui/icons';
import { SearchIcon, ChevronDownIcon, ArrowSmallLeftIcon, ArrowSmallRightIcon, FilterIcon } from 'ui/icons';
import { Button } from 'ui/button';
import VirtualList from 'svelte-tiny-virtual-list';
Expand All @@ -14,9 +14,28 @@
LeastPopular = "stats.downloads:asc"
}
function getSortLabel(sortValue: string): string {
switch (sortValue) {
case Sort.Newest:
return "Newest";
case Sort.Oldest:
return "Oldest";
case Sort.MostPopular:
return "Most Popular";
case Sort.LeastPopular:
return "Least Popular";
default:
return sortValue;
}
}
let listHeight;
let data: any[] = [];
let sort = Sort.Newest;
let totalPages = 1;
let totalHits = 0;
let currentPage = 1;
let searchValue: string = ""
const search = async (q: String) => {
const res = await (
Expand All @@ -30,19 +49,27 @@
},
body: JSON.stringify({
q: q,
sort: [sort.toString()]
sort: [sort.toString()],
page: currentPage,
hitsPerPage: 5,
})
})
).json();
data = res.hits;
data = data;
totalHits = res.totalHits;
totalPages = res.totalPages;
};
const searchOnInput = async (e: any) => {
await search(<String>(<HTMLInputElement>e.target).value);
searchValue = e.target.value;
currentPage = 1;
};
const onSortChange = async () => {
await search('');
currentPage = 1;
}
onMount(async () => {
await search('');
Expand All @@ -67,11 +94,18 @@
</div>

<div
class="relative flex w-2/5 flex-row items-center overflow-hidden rounded-md bg-primary-800"
class="relative flex w-14 md:w-2/5 flex-row items-center overflow-hidden rounded-md bg-primary-800"
>
<ChevronDownIcon
customClasses="w-4 h-4 absolute right-4 z-10 select-none pointer-events-none"
/>
<div class="absolute right-4 top-1/2 -translate-y-1/2 hidden md:block select-none pointer-events-none">
<ChevronDownIcon
customClasses="w-4 h-4 z-10 select-none pointer-events-none"
/>
</div>
<div class="absolute right-4 top-1/2 -translate-y-1/2 block md:hidden select-none pointer-events-none">
<FilterIcon
customClasses="w-4 h-4 z-10 select-none pointer-events-none"
/>
</div>
<select class="flex w-full flex-row items-center gap-2 py-3 pl-4 pr-12" bind:value={sort} on:change={onSortChange}>
<option value={Sort.Newest}>Newest</option>
<option value={Sort.Oldest}>Oldest</option>
Expand All @@ -81,6 +115,176 @@
</div>
</div>

<div class="pagination bg-primary-800 mt-4 rounded-md flex justify-center p-2">
<div class="flex overflow-hidden rounded-full">
<Button
variant="unset"
on:click={() => {
currentPage--;
search(searchValue);
}}
disabled={currentPage === 1}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
<ArrowSmallLeftIcon customClasses="w-4 h-4" />
</Button>

{#if totalPages <= 5}
{#each Array(totalPages) as _, i}
<Button
variant="unset"
on:click={() => {
currentPage = i + 1;
search(searchValue);
}}
disabled={currentPage === i + 1}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
{i + 1}
</Button>
{/each}
{:else}
{#if currentPage <= 2}
{#each Array(4) as _, i}
<Button
variant="unset"
on:click={() => {
currentPage = i + 1;
search(searchValue);
}}
disabled={currentPage === i + 1}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
{i + 1}
</Button>
{/each}
<Button
variant="unset"
on:click={() => {
currentPage = currentPage - 1;
search(searchValue);
}}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
...
</Button>
<Button
variant="unset"
on:click={() => {
currentPage = totalPages;
search(searchValue);
}}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
{totalPages}
</Button>
{:else if currentPage >= totalPages - 2}
<Button
variant="unset"
on:click={() => {
currentPage = 1;
search(searchValue);
}}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
1
</Button>
<Button
variant="unset"
on:click={() => {
currentPage = currentPage - 1;
search(searchValue);
}}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
...
</Button>
{#each Array(4) as _, i}
<Button
variant="unset"
on:click={() => {
currentPage = totalPages - 3 + i;
search(searchValue);
}}
disabled={currentPage === totalPages - 3 + i}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
{totalPages - 3 + i}
</Button>
{/each}
{:else}
<Button
variant="unset"
on:click={() => {
currentPage = 1;
search(searchValue);
}}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
1
</Button>
<Button
variant="unset"
on:click={() => {
currentPage = currentPage - 1;
search(searchValue);
}}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
...
</Button>
{#each Array(2) as _, i}
<Button
variant="unset"
on:click={() => {
currentPage = currentPage - 1 + i;
search(searchValue);
}}
disabled={currentPage === currentPage - 1 + i}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
{currentPage - 1 + i}
</Button>
{/each}
<Button
variant="unset"
on:click={() => {
currentPage = currentPage - 1;
search(searchValue);
}}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
...
</Button>
<Button
variant="unset"
on:click={() => {
currentPage = totalPages;
search(searchValue);
}}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
{totalPages}
</Button>
{/if}
{/if}

<Button
variant="unset"
on:click={() => {
currentPage++;
search(searchValue);
}}
disabled={currentPage === totalPages}
customClasses="px-3 py-1 rounded-none bg-primary-850 hover:bg-primary-900 text-md font-bold"
>
<ArrowSmallRightIcon customClasses="w-4 h-4" />
</Button>
</div>
</div>
<!-- end pagination -->

<div class="flex md:hidden mt-4 text-xs font-bold">Sorting by<span class="text-[#875CEF] ml-1">{getSortLabel(sort)}</span></div>
<div class="beatforge-discover-list-items-wrapper mt-4 overflow-hidden rounded-md">
{#if data && data.length}
{#each data as mod}
Expand All @@ -98,20 +302,8 @@
{:else}
<p class="text-center text-primary-300">No mods found</p>
{/if}
<!-- <VirtualList width="100%" itemCount={data.length} itemSize={129} height="100%">
<div slot="item" let:index let:style {style}>
<p>{data[index].name}</p>
<DiscoverListItem
name={data.mods[index].name}
slug={data.mods[index].slug}
author={data.mods[index].author.username}
description={data.mods[index].description}
category={data.mods[index].category.name}
downloads={data.mods[index].stats.downloads}
updatedAt={data.mods[index].updatedAt}
icon={data.mods[index].icon}
/>
</div>
</VirtualList> -->
</div>
<div class="mt-4 font-black text-xs text-primary-300">
<p>Total Mods: {totalHits}</p>
</div>
</div>
4 changes: 2 additions & 2 deletions packages/ui/button/Button.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
const variantClasses = {
unset: '',
primary: 'px-4 py-2 bg-primary-50 hover:bg-primary-100 text-black-950',
primary: 'px-4 py-2 bg-primary-50 hover:bg-primary-100 text-primary-950',
secondary: 'px-4 py-2 bg-primary-800 hover:bg-primary-900 text-white',
gradient:
'will-change-transform px-4 py-2 bg-gradient-to-r from-[#47334f] to-[#2d2c4f] text-white duration-[200ms] ease-[cubic-bezier(0.22,0.61,0.36,1)]',
Expand All @@ -18,7 +18,7 @@
};
let buttonClasses = `
${variant === "unset" ? '' : 'outline-none focus:shadow-none focus-visible:ring-4 focus-visible:ring-[#00a8fc] disabled:opacity-50 flex flex-row items-center justify-center transition-all duration-[80ms] rounded-full gap-2 font-bold text-sm'}
${variant === "unset" ? '' : 'select-none outline-none focus:shadow-none focus-visible:ring-4 focus-visible:ring-[#00a8fc] disabled:opacity-50 flex flex-row items-center justify-center transition-all duration-[80ms] rounded-full gap-2 font-bold text-sm'}
${variantClasses[variant]}
${customClasses}
`;
Expand Down
10 changes: 10 additions & 0 deletions packages/ui/icons/ArrowSmallLeft.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script lang="ts">
// @ts-nocheck
export let customClasses = '';
</script>

<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class={customClasses}>
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 12h-15m0 0l6.75 6.75M4.5 12l6.75-6.75" />
</svg>


10 changes: 10 additions & 0 deletions packages/ui/icons/ArrowSmallRight.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script lang="ts">
// @ts-nocheck
export let customClasses = '';
</script>

<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class={customClasses}>
<path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12h15m0 0l-6.75-6.75M19.5 12l-6.75 6.75" />
</svg>


10 changes: 10 additions & 0 deletions packages/ui/icons/Filter.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script lang="ts">
// @ts-nocheck
export let customClasses = '';
</script>

<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class={customClasses}>
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75" />
</svg>


5 changes: 4 additions & 1 deletion packages/ui/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ export { default as VerifiedIcon } from './Verified.svelte';
export { default as AtSymbolIcon } from './AtSymbol.svelte';
export { default as BarsThree } from './BarsThree.svelte';
export { default as CubeIcon } from './Cube.svelte';
export { default as CogIcon } from './Cog.svelte'
export { default as CogIcon } from './Cog.svelte'
export { default as ArrowSmallLeftIcon } from './ArrowSmallLeft.svelte'
export { default as ArrowSmallRightIcon } from './ArrowSmallRight.svelte'
export { default as FilterIcon } from './Filter.svelte'

0 comments on commit e916b26

Please sign in to comment.