1
0
Fork 1
mirror of https://github.com/0x2E/fusion.git synced 2025-06-08 05:27:15 +09:00

feat: add search page (#110)

This commit is contained in:
Yuan 2025-03-24 18:37:04 +08:00 committed by GitHub
parent 5e9d2d8d07
commit 78e4666be3
Signed by: github
GPG key ID: B5690EEEBB952194
3 changed files with 80 additions and 49 deletions

View file

@ -1,60 +1,18 @@
<script lang="ts">
import { listItems } from '$lib/api/item';
import type { Item } from '$lib/api/model';
import { debounce } from '$lib/utils';
import { Search } from 'lucide-svelte';
import ItemList from './ItemList.svelte';
import { goto } from '$app/navigation';
import { t } from '$lib/i18n';
let modal = $state<HTMLDialogElement>();
let keyword = $state('');
let result = $state<{ total: number; items: Item[] } | null>();
// let isMac = navigator.platform.indexOf('Mac') === 0 || navigator.platform === 'iPhone';
const handleSearch = debounce(async () => {
const resp = await listItems(); // TODO filter
result = resp;
}, 500);
import { Search } from 'lucide-svelte';
</script>
<label class="input input-sm lg:w-80">
<Search class="size-4 opacity-50" />
<input
type="search"
class="input"
placeholder={t('item.search.placeholder')}
onclick={() => modal?.showModal()}
onclick={async () => {
await goto('/search');
}}
readonly
class="cursor-pointer"
/>
<!-- <kbd class="kbd kbd-sm">{isMac ? '⌘' : '^'}</kbd>
<kbd class="kbd kbd-sm">K</kbd> -->
</label>
<dialog id="search" bind:this={modal} class="modal modal-bottom sm:modal-middle">
<div class="modal-box min-h-80 w-full overflow-x-hidden sm:max-w-4xl">
<form method="dialog">
<button class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"></button>
</form>
<h3 class="text-lg font-bold">{t('common.search')}</h3>
<div class="py-4">
<label class="input w-full">
<Search class="size-4 opacity-50" />
<input
type="search"
required
placeholder={t('item.search.placeholder')}
bind:value={keyword}
oninput={handleSearch}
class="w-full"
/>
</label>
{#if result?.total}
<div class="mt-6">
<ItemList items={result.items} total={result.total} />
</div>
{/if}
</div>
</div>
<form method="dialog" class="modal-backdrop">
<button>close</button>
</form>
</dialog>

View file

@ -0,0 +1,58 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { page } from '$app/state';
import { applyFilterToURL, parseURLtoFilter } from '$lib/api/item';
import ItemList from '$lib/components/ItemList.svelte';
import ItemListPlaceholder from '$lib/components/ItemListPlaceholder.svelte';
import PageNavHeader from '$lib/components/PageNavHeader.svelte';
import { t } from '$lib/i18n';
import { Search } from 'lucide-svelte';
let { data } = $props();
let filterForm = $state(Object.assign({}, parseURLtoFilter(page.url.searchParams)));
async function handleSearch(e: Event) {
e.preventDefault();
const url = page.url;
applyFilterToURL(url, filterForm);
console.log(url.toString());
goto(url, {
invalidate: ['page:search']
});
}
</script>
<svelte:head>
<title>{t('common.search')}: {filterForm.keyword}</title>
</svelte:head>
<div class="flex flex-col">
<PageNavHeader title={t('common.search')}></PageNavHeader>
<div class="px-4 lg:px-8">
<div class="py-6">
<h1 class="text-3xl font-bold">{t('common.search')}: {filterForm.keyword}</h1>
</div>
<form onsubmit={handleSearch} class="w-full max-w-lg pb-4">
<div class="join w-full">
<div class="w-full">
<label class="input join-item w-full">
<Search class="size-4 opacity-50" />
<input
type="search"
placeholder={t('item.search.placeholder')}
bind:value={filterForm.keyword}
required
/>
</label>
</div>
<button type="submit" class="btn btn-primary join-item">{t('common.search')}</button>
</div>
</form>
{#await data.items}
<ItemListPlaceholder />
{:then items}
<ItemList items={items.items} total={items.total} highlightUnread={true} />
{/await}
</div>
</div>

View file

@ -0,0 +1,15 @@
import { listItems, parseURLtoFilter } from '$lib/api/item';
import { fullItemFilter } from '$lib/state.svelte';
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ url, depends }) => {
depends('page:search');
const filter = parseURLtoFilter(url.searchParams);
Object.assign(fullItemFilter, filter);
return {
filter,
items: listItems(filter)
};
};