Scrapboard.org client
at labels 85 lines 2.2 kB view raw
1import { create } from "zustand"; 2import { persist } from "zustand/middleware"; 3import * as z from "zod"; 4 5export const Board = z.looseObject({ 6 name: z.string(), 7 description: z.string(), 8}); 9 10export type Board = z.infer<typeof Board>; 11 12type BoardsState = { 13 boards: Record<string, Record<string, Board>>; 14 isLoading: boolean; 15 setLoading: (value: boolean) => void; 16 setBoard: (did: string, rkey: string, board: Board) => void; 17 removeBoard: (did: string, rkey: string) => void; 18 getBoards: (did: string) => Record<string, Board> | undefined; 19 getBoardsAsEntries: (did: string) => [string, Board][] | undefined; 20 getAllBoards: () => Record<string, Record<string, Board>>; 21 clearBoards: (did?: string) => void; 22}; 23 24export const useBoardsStore = create<BoardsState>()( 25 persist( 26 (set, get) => ({ 27 boards: {}, 28 isLoading: true, 29 30 setLoading: (value) => set(() => ({ isLoading: value })), 31 32 setBoard: (did, rkey, board) => 33 set((state) => ({ 34 boards: { 35 ...state.boards, 36 [did]: { 37 ...state.boards[did], 38 [rkey]: board, 39 }, 40 }, 41 })), 42 43 removeBoard: (did, rkey) => 44 set((state) => { 45 const userBoards = state.boards[did]; 46 if (!userBoards || !userBoards[rkey]) return state; 47 48 const { [rkey]: removed, ...rest } = userBoards; 49 return { 50 boards: { 51 ...state.boards, 52 [did]: rest, 53 }, 54 }; 55 }), 56 57 getBoards: (did) => get().boards[did], 58 59 getBoardsAsEntries: (did) => { 60 const boards = get().boards[did]; 61 return boards ? Object.entries(boards) : undefined; 62 }, 63 64 getAllBoards: () => get().boards, 65 66 clearBoards: (did) => 67 set((state) => { 68 if (did) { 69 const { [did]: removed, ...rest } = state.boards; 70 return { boards: rest }; 71 } else { 72 return { boards: {} }; 73 } 74 }), 75 }), 76 { 77 name: "boards", 78 partialize: (state) => ({ 79 boards: state.boards, 80 }), 81 version: 2, 82 // No need for custom storage anymore! 83 } 84 ) 85);