add zustand stores for ephemeral ui state (search queries survive tab switches)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-02 14:13:52 +01:00
parent c96c24a250
commit 765543920c
6 changed files with 30 additions and 5 deletions

View File

@@ -16,7 +16,7 @@
"react-dom": "^19.1.0", "react-dom": "^19.1.0",
"tailwind-merge": "^3.5.0", "tailwind-merge": "^3.5.0",
"zod": "^3.24.3", "zod": "^3.24.3",
"zustand": "^5.0.5", "zustand": "^5.0.11",
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "^1.9.4", "@biomejs/biome": "^1.9.4",

View File

@@ -24,7 +24,7 @@
"react-dom": "^19.1.0", "react-dom": "^19.1.0",
"tailwind-merge": "^3.5.0", "tailwind-merge": "^3.5.0",
"zod": "^3.24.3", "zod": "^3.24.3",
"zustand": "^5.0.5" "zustand": "^5.0.11"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "^1.9.4", "@biomejs/biome": "^1.9.4",

View File

@@ -6,6 +6,7 @@ import { Block, Button, Card, List, ListItem, Navbar, Searchbar } from "konsta/r
import { useEffect, useMemo, useState } from "react" import { useEffect, useMemo, useState } from "react"
import { type GeoResult, loadCachedResult } from "../../location/lib/geo" import { type GeoResult, loadCachedResult } from "../../location/lib/geo"
import { getPartyMeta } from "../../location/lib/parties" import { getPartyMeta } from "../../location/lib/parties"
import { usePoliticiansUI } from "../store"
interface PartyGroup { interface PartyGroup {
partyLabel: string partyLabel: string
@@ -55,7 +56,8 @@ function mandateFunction(m: MandateWithPolitician): string | null {
export function PoliticianSearch() { export function PoliticianSearch() {
const db = useDb() const db = useDb()
const [result, setResult] = useState<GeoResult | null>(null) const [result, setResult] = useState<GeoResult | null>(null)
const [search, setSearch] = useState("") const search = usePoliticiansUI((s) => s.searchQuery)
const setSearch = usePoliticiansUI((s) => s.setSearchQuery)
const { isFollowing, follow, unfollow } = useFollows() const { isFollowing, follow, unfollow } = useFollows()
useEffect(() => { useEffect(() => {

View File

@@ -0,0 +1,11 @@
import { create } from "zustand"
interface PoliticiansUIState {
searchQuery: string
setSearchQuery: (query: string) => void
}
export const usePoliticiansUI = create<PoliticiansUIState>((set) => ({
searchQuery: "",
setSearchQuery: (query) => set({ searchQuery: query }),
}))

View File

@@ -1,12 +1,13 @@
import { useFollows } from "@/shared/hooks/use-follows" import { useFollows } from "@/shared/hooks/use-follows"
import { Button, List, ListItem, Navbar, Preloader, Searchbar } from "konsta/react" import { Button, List, ListItem, Navbar, Preloader, Searchbar } from "konsta/react"
import { useState } from "react"
import { useTopics } from "../hooks/use-topics" import { useTopics } from "../hooks/use-topics"
import { useTopicsUI } from "../store"
export function TopicList() { export function TopicList() {
const { topics, loading, error } = useTopics() const { topics, loading, error } = useTopics()
const { isFollowing, follow, unfollow } = useFollows() const { isFollowing, follow, unfollow } = useFollows()
const [search, setSearch] = useState("") const search = useTopicsUI((s) => s.searchQuery)
const setSearch = useTopicsUI((s) => s.setSearchQuery)
const filtered = topics.filter((t) => t.label.toLowerCase().includes(search.toLowerCase())) const filtered = topics.filter((t) => t.label.toLowerCase().includes(search.toLowerCase()))

View File

@@ -0,0 +1,11 @@
import { create } from "zustand"
interface TopicsUIState {
searchQuery: string
setSearchQuery: (query: string) => void
}
export const useTopicsUI = create<TopicsUIState>((set) => ({
searchQuery: "",
setSearchQuery: (query) => set({ searchQuery: query }),
}))