Compare commits

...

1 Commits

Author SHA1 Message Date
Adam Veldhousen d3361cb8f3
pagination and linking improvements 2023-05-26 01:41:44 -05:00
3 changed files with 59 additions and 13 deletions

View File

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { LayoutData } from './$types'; import type { LayoutData } from './$types';
import { goto, invalidateAll } from '$app/navigation'; import { goto } from '$app/navigation';
import SearchBox from '$lib/SearchBox.svelte'; import SearchBox from '$lib/SearchBox.svelte';
import '../app.css'; import '../app.css';
@ -40,7 +40,7 @@
<ul class="flex w-full py-3 items-center justify-between"> <ul class="flex w-full py-3 items-center justify-between">
<li class="flex grow justify-center"> <li class="flex grow justify-center">
<span class="flex grow" style="max-width: 75%;"> <span class="flex grow" style="max-width: 75%;">
<SearchBox on:search={onSubmit} page={data.page} /> <SearchBox on:search={onSubmit} query={data.query} page={data.page} />
</span> </span>
</li> </li>
<li class="px-6"> <li class="px-6">

View File

@ -5,10 +5,19 @@
export let data: PageData; export let data: PageData;
function buildQueryString({ query, page }: { query: string; page: number }): string {
const qs = [query === '' ? query : `query=${query}`, page <= 1 ? '' : `page=${page}`]
.filter((x) => x !== '')
.join('&');
return qs !== '' ? `?${qs}` : qs;
}
const { query, page } = data;
$: hasResults = (data.results || []).length > 0; $: hasResults = (data.results || []).length > 0;
$: currentPage = data.page + 1; $: currentPage = data.page + 1;
$: pageCount = Math.max(1, Math.floor(data.found / data.limit)); $: pageCount = Math.max(1, Math.ceil(data.found / data.limit));
$: console.log(data.found, ' / ', data.limit, ' = ', data.found / data.limit); $: console.log(`page: ${currentPage}, count: ${pageCount}, `);
</script> </script>
{#if hasResults} {#if hasResults}
@ -17,7 +26,7 @@
<ol class="flex justify-between w-full center" style="padding: 0 10%;"> <ol class="flex justify-between w-full center" style="padding: 0 10%;">
{#if currentPage > 1} {#if currentPage > 1}
<li in:fade> <li in:fade>
<a href="/?query={data.query}&page={data.page - 1}">&lt;Previous</a> <a href="/{buildQueryString({ query, page: currentPage - 1 })}">&lt;Previous</a>
</li> </li>
{:else} {:else}
<li /> <li />
@ -25,7 +34,7 @@
<li>Page {currentPage} of {pageCount}</li> <li>Page {currentPage} of {pageCount}</li>
{#if currentPage < pageCount} {#if currentPage < pageCount}
<li in:fade> <li in:fade>
<a href="/?query={data.query}&page={data.page + 1}">Next&gt;</a> <a href="/{buildQueryString({ query, page: currentPage + 1 })}">Next&gt;</a>
</li> </li>
{/if} {/if}
</ol> </ol>

View File

@ -14,20 +14,19 @@ interface SearchPageData {
} }
export const load = (async ({ fetch, url }): Promise<SearchPageData> => { export const load = (async ({ fetch, url }): Promise<SearchPageData> => {
// TODO: refactor to one source of truth for all query param value fetching const searchParams = new SearchParameters(url);
const searchTerm = url.searchParams.get('query') || ''; const limit = searchParams.getLimit();
const currentPage = Number(url.searchParams.get('page') || 0); const searchTerm = searchParams.getSearchTerm();
const currentLimit = Number(url.searchParams.get('limit') || 64);
try { try {
// TODO: refactor to one source of truth for all query string building // TODO: refactor to one source of truth for all query string building
const response = await fetch(API_HOST + `/upcoming?searchTerm=${searchTerm}&page=${currentPage}&limit=${currentLimit}`); const response = await fetch(API_HOST + `/upcoming${searchParams.toQueryString()}`);
const { page, total, found, results } = await response.json() || {}; const { page, total, found, results } = await response.json() || {};
// TODO: return found results so we can do upperbound on pagination // TODO: return found results so we can do upperbound on pagination
return { return {
page, page,
limit: currentLimit, limit,
query: searchTerm, query: searchTerm,
found, found,
total, total,
@ -37,7 +36,7 @@ export const load = (async ({ fetch, url }): Promise<SearchPageData> => {
console.log(e); console.log(e);
return { return {
page: 0, page: 0,
limit: currentLimit, limit,
query: searchTerm, query: searchTerm,
found: 0, found: 0,
total: 0, total: 0,
@ -46,3 +45,41 @@ export const load = (async ({ fetch, url }): Promise<SearchPageData> => {
} }
}) satisfies PageLoad; }) satisfies PageLoad;
class SearchParameters {
page: number
limit: number
searchTerm?: string
constructor(url: URL) {
this.searchTerm = url.searchParams.get('query') || undefined;
this.page = Number(url.searchParams.get('page') || 1) - 1;
if (this.page < 0 ) {
this.page = 0;
}
this.limit = Number(url.searchParams.get('limit') || 64);
if (this.limit > 128) {
this.limit = 128;
} else if (this.limit < 32) {
this.limit = 32;
}
}
getPage(): number {
return this.page || 0;
}
getSearchTerm(): string {
return this.searchTerm || '';
}
getLimit(): number {
return this.limit || 64;
}
toQueryString(): string {
const qs = Object.entries(this).filter(t => t.length > 0 && t[1]).map(t => `${t[0]}=${t[1]}`).join('&');
return qs === '' ? '' : `?${qs}`;
}
}