update links page to use <a> tags to update search params

pull/3/head
TZGyn 2 years ago
parent 1675b9e12e
commit ab7c632e0e
Signed by: TZGyn
GPG Key ID: 122EAF77AE81FD4A

@ -19,7 +19,7 @@ export const load = (async (event) => {
let sortBy = event.url.searchParams.get('sortBy') let sortBy = event.url.searchParams.get('sortBy')
let page = parseInt(event.url.searchParams.get('page') ?? '1') let page = parseInt(event.url.searchParams.get('page') ?? '1')
let perPage = parseInt( let perPage = parseInt(
event.url.searchParams.get('perPage') ?? '10', event.url.searchParams.get('perPage') ?? '12',
) )
if (isNaN(page)) { if (isNaN(page)) {
@ -83,6 +83,21 @@ export const load = (async (event) => {
.offset(perPage * (page - 1)) .offset(perPage * (page - 1))
.limit(perPage) .limit(perPage)
const pagination = db
.select({
total: sql<number>`count(*)`.as('total'),
})
.from(shortener)
.where(
and(
eq(shortener.userId, user.id),
project_id ? eq(shortener.projectId, project_id) : undefined,
search
? ilike(shortener.link, `%${decodeURI(search)}%`)
: undefined,
),
)
if (sortBy === 'latest') { if (sortBy === 'latest') {
shorteners.orderBy(desc(shortener.createdAt)) shorteners.orderBy(desc(shortener.createdAt))
} else if (sortBy === 'oldest') { } else if (sortBy === 'oldest') {
@ -108,5 +123,6 @@ export const load = (async (event) => {
perPage, perPage,
search, search,
sortBy, sortBy,
pagination,
} }
}) satisfies PageServerLoad }) satisfies PageServerLoad

@ -80,36 +80,25 @@
qrDialogOpen = true qrDialogOpen = true
} }
let page: number = data.page
let perPage: any = { label: data.perPage, value: data.perPage }
let selectedProjectUUID: string | null
$: selectedProjectUUID = data.selected_project.value
let search: string | null = data.search let search: string | null = data.search
let searchUpdateTimeout: any let searchUpdateTimeout: any
let sortBy: any = { label: data.sortBy, value: data.sortBy }
$: browser && $: browser &&
updateUrl(selectedProjectUUID, page, perPage, search, sortBy) goto(updateSearchParam([{ name: 'search', value: search }]))
const updateUrl = ( const updateSearchParam = (
selectedProjectUUID: string | null, params: { name: string; value: any }[],
page: number,
perPage: any,
search: string | null,
sortBy: any,
) => { ) => {
let query = [`page=${page}`, `perPage=${perPage.value}`] const urlParams = new URLSearchParams(window.location.search)
if (selectedProjectUUID) { params.map(({ name, value }) => {
query.push(`project=${selectedProjectUUID}`) if (value) {
} urlParams.set(name, value)
if (search) { } else {
query.push(`search=${encodeURI(search)}`) urlParams.delete(name)
}
if (sortBy) {
query.push(`sortBy=${sortBy.value}`)
} }
})
goto(`/links?${query.join('&')}`) const searchParams = urlParams.toString()
return '/links?' + searchParams
} }
</script> </script>
@ -135,10 +124,19 @@
<Command.Input placeholder="Search project..." /> <Command.Input placeholder="Search project..." />
<Command.Empty>No project found.</Command.Empty> <Command.Empty>No project found.</Command.Empty>
<Command.Group> <Command.Group>
<a
href={updateSearchParam([
{
name: 'project',
value: undefined,
},
{
name: 'page',
value: 1,
},
])}>
<Command.Item <Command.Item
onSelect={() => { onSelect={() => {
selectedProjectUUID = null
page = 1
open = false open = false
}}> }}>
<Check <Check
@ -149,11 +147,21 @@
)} /> )} />
All All
</Command.Item> </Command.Item>
</a>
{#each data.projects as project} {#each data.projects as project}
<a
href={updateSearchParam([
{
name: 'project',
value: project.uuid,
},
{
name: 'page',
value: 1,
},
])}>
<Command.Item <Command.Item
onSelect={() => { onSelect={() => {
selectedProjectUUID = project.uuid
page = 1
open = false open = false
}}> }}>
<Check <Check
@ -164,12 +172,13 @@
)} /> )} />
{project.name} {project.name}
</Command.Item> </Command.Item>
</a>
{/each} {/each}
</Command.Group> </Command.Group>
</Command.Root> </Command.Root>
</Popover.Content> </Popover.Content>
</Popover.Root> </Popover.Root>
<Select.Root bind:selected={sortBy}> <Select.Root selected={{ label: data.sortBy, value: data.sortBy }}>
<Select.Trigger class="w-[180px]" customIcon={SortDescIcon}> <Select.Trigger class="w-[180px]" customIcon={SortDescIcon}>
<Select.Value placeholder="Sort By" /> <Select.Value placeholder="Sort By" />
</Select.Trigger> </Select.Trigger>
@ -177,8 +186,15 @@
<Select.Group> <Select.Group>
<Select.Label>Sort By</Select.Label> <Select.Label>Sort By</Select.Label>
{#each ['latest', 'oldest', 'most_visited'] as sortBy} {#each ['latest', 'oldest', 'most_visited'] as sortBy}
<Select.Item value={sortBy} label={sortBy} <a
>{sortBy}</Select.Item> href={updateSearchParam([
{ name: 'sortBy', value: sortBy },
{ name: 'page', value: 1 },
])}>
<Select.Item value={sortBy} label={sortBy}>
{sortBy}
</Select.Item>
</a>
{/each} {/each}
</Select.Group> </Select.Group>
</Select.Content> </Select.Content>
@ -304,18 +320,48 @@
{/each} {/each}
</div> </div>
</ScrollArea> </ScrollArea>
{:else}
<div class="flex w-full flex-grow items-center justify-center">
<div class="flex flex-col items-center gap-12">
<div class="flex flex-col items-center gap-4">
<div class="text-4xl font-bold">No Shortener Found</div>
</div>
<Button
on:click={() => {
dialogOpen = true
}}
class="w-fit">Add Shortener</Button>
</div>
</div>
{/if}
{/await}
{#await data.pagination then pagination}
<div class="flex items-center justify-between border-t p-4"> <div class="flex items-center justify-between border-t p-4">
<Select.Root bind:selected={perPage}> <Select.Root
selected={{ label: data.perPage, value: data.perPage }}>
<Select.Trigger class="w-[180px]"> <Select.Trigger class="w-[180px]">
<Select.Value placeholder="Page Size" /> <Select.Value placeholder="Page Size" />
</Select.Trigger> </Select.Trigger>
<Select.Content> <Select.Content>
<Select.Group> <Select.Group>
<Select.Label>Page Size</Select.Label> <Select.Label>Page Size</Select.Label>
{#each [10, 20, 50, 100] as pageSize} {#each [12, 24, 48, 96] as pageSize}
<a
href={updateSearchParam([
{
name: 'perPage',
value: pageSize,
},
{
name: 'page',
value: 1,
},
])}>
<Select.Item <Select.Item
value={pageSize} value={pageSize}
label={pageSize.toString()}>{pageSize}</Select.Item> label={pageSize.toString()}>{pageSize}</Select.Item>
</a>
{/each} {/each}
</Select.Group> </Select.Group>
</Select.Content> </Select.Content>
@ -323,21 +369,42 @@
</Select.Root> </Select.Root>
<Pagination.Root <Pagination.Root
class="items-end " class="items-end "
count={shorteners[0].fullcount} count={pagination[0].total}
bind:page page={data.page}
perPage={perPage.value} perPage={data.perPage}
let:pages let:pages
let:currentPage> let:currentPage>
<Pagination.Content> <Pagination.Content>
{#if data.page <= 1}
<Pagination.Item>
<Pagination.PrevButton />
</Pagination.Item>
{:else}
<a
href={updateSearchParam([
{
name: 'page',
value: data.page - 1,
},
])}>
<Pagination.Item> <Pagination.Item>
<Pagination.PrevButton /> <Pagination.PrevButton />
</Pagination.Item> </Pagination.Item>
</a>
{/if}
{#each pages as page (page.key)} {#each pages as page (page.key)}
{#if page.type === 'ellipsis'} {#if page.type === 'ellipsis'}
<Pagination.Item> <Pagination.Item>
<Pagination.Ellipsis /> <Pagination.Ellipsis />
</Pagination.Item> </Pagination.Item>
{:else} {:else}
<a
href={updateSearchParam([
{
name: 'page',
value: page.value,
},
])}>
<Pagination.Item isVisible={currentPage == page.value}> <Pagination.Item isVisible={currentPage == page.value}>
<Pagination.Link <Pagination.Link
{page} {page}
@ -345,28 +412,29 @@
{page.value} {page.value}
</Pagination.Link> </Pagination.Link>
</Pagination.Item> </Pagination.Item>
</a>
{/if} {/if}
{/each} {/each}
{#if data.page >= pagination[0].total / data.perPage}
<Pagination.Item> <Pagination.Item>
<Pagination.NextButton /> <Pagination.NextButton />
</Pagination.Item> </Pagination.Item>
{:else}
<a
href={updateSearchParam([
{
name: 'page',
value: data.page + 1,
},
])}>
<Pagination.Item>
<Pagination.NextButton />
</Pagination.Item>
</a>
{/if}
</Pagination.Content> </Pagination.Content>
</Pagination.Root> </Pagination.Root>
</div> </div>
{:else}
<div class="flex h-full w-full items-center justify-center">
<div class="flex flex-col items-center gap-12">
<div class="flex flex-col items-center gap-4">
<div class="text-4xl font-bold">No Shortener Found</div>
</div>
<Button
on:click={() => {
dialogOpen = true
}}
class="w-fit">Add Shortener</Button>
</div>
</div>
{/if}
{/await} {/await}
<EditShortenerDialog <EditShortenerDialog

Loading…
Cancel
Save