Read-it-later social network

add debounced search of publications

+19 -7
bun.lockb

This is a binary file and will not be displayed.

+1
package.json
··· 36 36 "drizzle-orm": "^0.44.5", 37 37 "postgres": "^3.4.7", 38 38 "quickslice-client-js": "^0.3.0", 39 + "runed": "^0.37.1", 39 40 "valibot": "^1.1.0" 40 41 } 41 42 }
+1 -3
src/routes/+layout.svelte
··· 42 42 <div class="flex gap-4 items-center flex-wrap"> 43 43 <nav class="flex gap-4 flex-wrap items-center px-3 py-1.5"> 44 44 <a href="/" class="hover:text-shadow-sm" title="explore" aria-label="explore">🛰️ explore</a> 45 - <a href="https://tangled.sh/@zeu.dev/potatonet-app" class="hover:text-shadow-sm" title="source code" aria-label="source code">🧶 source code</a> 46 45 {#if user} 47 - <a href={`/${user.handle}/bookmarks`} class="hover:text-shadow-sm" aria-label="logged in user's bookmarks">🔖 your bookmarks</a> 48 46 <p>{user.handle}</p> 49 47 {/if} 50 48 </nav> 51 49 {#if user} 52 - <button onclick={logout} class="hover:text-shadow-lg hover:cursor-pointer"> 50 + <button onclick={logout} class="bg-amber-400 text-black hover:cursor-pointer hover:bg-amber-500 hover:text-white px-4 py-2"> 53 51 Logout 54 52 </button> 55 53 {:else}
+17 -4
src/routes/+page.svelte
··· 1 1 <script lang="ts"> 2 + import { Debounced } from "runed"; 2 3 import type { PublicationNode } from '$lib/utils'; 3 4 import { createInfiniteQuery } from '@tanstack/svelte-query'; 4 5 import PublicationCard from '$lib/components/PublicationCard.svelte'; ··· 7 8 let { atclient, user } = data; 8 9 9 10 let page = $state(0); 11 + let searchTerm = $state(""); 12 + const debouncedSearchTerm = new Debounced(() => searchTerm, 500); 10 13 11 - const publicationsQuery = createInfiniteQuery(() => ({ 12 - queryKey: ["publications"], 14 + const publicationsQuery =$derived( createInfiniteQuery(() => ({ 15 + queryKey: ["publications", debouncedSearchTerm.current], 13 16 queryFn: async ({ pageParam }) => { 14 17 const query = ` 15 18 query GetPublications { 16 - siteStandardPublication(first: 20, after: "${pageParam}") { 19 + siteStandardPublication(first: 20, after: "${pageParam}", where: { 20 + or: [{ 21 + name: { contains: "${debouncedSearchTerm.current}" } 22 + }, { 23 + actorHandle: { contains: "${debouncedSearchTerm.current}" } 24 + }] 25 + }) { 17 26 edges {} 18 27 pageInfo { 19 28 hasNextPage ··· 41 50 const nodes = items.map((i) => i.node); 42 51 return nodes; 43 52 } 44 - })); 53 + }))); 45 54 46 55 let currentPage = $derived(publicationsQuery.data?.slice(page*20, (page*20) + 20)); 47 56 </script> 48 57 49 58 <menu> 59 + <label> 60 + Search: 61 + <input bind:value={searchTerm} class="border" /> 62 + </label> 50 63 <button 51 64 onclick={() => { 52 65 if (page > 0) {