this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 115 lines 3.4 kB view raw
1import { createFileRoute } from "@tanstack/react-router"; 2import { useSuspenseQuery } from "@tanstack/react-query"; 3import { useLiveSuspenseQuery, eq, toArray } from "@tanstack/react-db"; 4import * as v from "valibot"; 5import { ChapterSplitColumn } from "~/chapters/chapter-split"; 6import { DemoCard } from "~/demos/components/demo-card"; 7import { 8 PokedexPagination, 9 PokedexTableResults, 10 PokedexTableSection, 11} from "~/demos/components/pokedex-table-section"; 12import { getArticleQueryOptions } from "~/articles/querys"; 13import { 14 pokemonCollection, 15 typesCollection, 16 pokemonTypesCollection, 17} from "~/demos/live-query/collections"; 18import { 19 getPokemonListingQueryLimit, 20 toPokemonListing, 21} from "~/demos/pokemon-listing/pokemon-listing"; 22 23const searchParamsSchema = v.object({ 24 offset: v.optional(v.number(), 0), 25}); 26 27export const Route = createFileRoute("/_chapters/live-query")({ 28 staticData: { 29 routeTitle: "07_live-query", 30 routeSubtitle: "// Electric SQL synced collection", 31 }, 32 ssr: false, 33 validateSearch: searchParamsSchema, 34 context: () => { 35 const liveQueryArticleQueryOptions = getArticleQueryOptions({ 36 slug: "live-query", 37 }); 38 return { liveQueryArticleQueryOptions }; 39 }, 40 loader: async ({ context: { queryClient, liveQueryArticleQueryOptions } }) => { 41 await queryClient.ensureQueryData(liveQueryArticleQueryOptions); 42 }, 43 component: RouteComponent, 44}); 45 46function RouteComponent() { 47 const { offset: currentOffset } = Route.useSearch(); 48 const { liveQueryArticleQueryOptions } = Route.useRouteContext(); 49 50 const { 51 data: { Article }, 52 } = useSuspenseQuery(liveQueryArticleQueryOptions); 53 54 return ( 55 <ChapterSplitColumn 56 blog={Article} 57 table={ 58 <DemoCard className="mb-6"> 59 <PokedexTableSection 60 currentOffset={currentOffset} 61 fallbackPagination={ 62 <PokedexPagination prevOffset={null} nextOffset={null} to="/live-query" /> 63 } 64 > 65 <PokemonTableContent currentOffset={currentOffset} /> 66 </PokedexTableSection> 67 </DemoCard> 68 } 69 /> 70 ); 71} 72 73function PokemonTableContent({ currentOffset }: { currentOffset: number }) { 74 const { data } = useLiveSuspenseQuery( 75 (q) => 76 q 77 .from({ pokemon: pokemonCollection }) 78 .orderBy(({ pokemon }) => pokemon.dexId) 79 .offset(currentOffset) 80 .limit(getPokemonListingQueryLimit()) 81 .select(({ pokemon }) => ({ 82 id: pokemon.id, 83 name: pokemon.name, 84 dexId: pokemon.dexId, 85 types: toArray( 86 q 87 .from({ pokemonType: pokemonTypesCollection }) 88 .join( 89 { type: typesCollection }, 90 ({ pokemonType, type }) => eq(pokemonType.typeId, type.id), 91 "inner", 92 ) 93 .where(({ pokemonType }) => eq(pokemonType.pokemonId, pokemon.id)) 94 .orderBy(({ pokemonType }) => pokemonType.id) 95 .select(({ type }) => ({ name: type.name })), 96 ), 97 })), 98 [currentOffset], 99 ); 100 101 const listing = toPokemonListing(data, { offset: currentOffset }); 102 103 return ( 104 <PokedexTableResults 105 pokemon={listing.pokemon} 106 pagination={ 107 <PokedexPagination 108 prevOffset={listing.prevOffset} 109 nextOffset={listing.nextOffset} 110 to="/live-query" 111 /> 112 } 113 /> 114 ); 115}