Skip to main content
Glama
zustand-store.md4.39 kB
```typescript import { create } from "zustand"; import { persist, createJSONStorage, devtools } from "zustand/middleware"; // ============================================ // Types // ============================================ interface User { id: string; name: string; email: string; avatar?: string; } interface AuthState { user: User | null; token: string | null; isAuthenticated: boolean; login: (user: User, token: string) => void; logout: () => void; updateProfile: (data: Partial<User>) => void; } interface ThemeState { mode: "light" | "dark" | "system"; setMode: (mode: "light" | "dark" | "system") => void; toggleMode: () => void; } interface CartItem { id: string; name: string; price: number; quantity: number; } interface CartState { items: CartItem[]; addToCart: (item: CartItem) => void; removeFromCart: (id: string) => void; updateQuantity: (id: string, quantity: number) => void; clearCart: () => void; total: () => number; } // ============================================ // Auth Store (Persisted) // ============================================ export const useAuthStore = create<AuthState>()( devtools( persist( (set) => ({ user: null, token: null, isAuthenticated: false, login: (user, token) => set( { user, token, isAuthenticated: true, }, false, "auth/login", ), // Action name for devtools logout: () => set( { user: null, token: null, isAuthenticated: false, }, false, "auth/logout", ), updateProfile: (data) => set( (state) => ({ user: state.user ? { ...state.user, ...data } : null, }), false, "auth/updateProfile", ), }), { name: "auth-storage", storage: createJSONStorage(() => localStorage), partialize: (state) => ({ token: state.token, user: state.user }), // Only persist token and user }, ), ), ); // ============================================ // Theme Store // ============================================ export const useThemeStore = create<ThemeState>()( persist( (set, get) => ({ mode: "system", setMode: (mode) => set({ mode }), toggleMode: () => { const current = get().mode; set({ mode: current === "light" ? "dark" : "light" }); }, }), { name: "theme-storage" }, ), ); // ============================================ // Cart Store (Computed Values) // ============================================ export const useCartStore = create<CartState>((set, get) => ({ items: [], addToCart: (newItem) => set((state) => { const existing = state.items.find((i) => i.id === newItem.id); if (existing) { return { items: state.items.map((i) => i.id === newItem.id ? { ...i, quantity: i.quantity + 1 } : i, ), }; } return { items: [...state.items, { ...newItem, quantity: 1 }] }; }), removeFromCart: (id) => set((state) => ({ items: state.items.filter((i) => i.id !== id), })), updateQuantity: (id, quantity) => set((state) => ({ items: quantity <= 0 ? state.items.filter((i) => i.id !== id) : state.items.map((i) => (i.id === id ? { ...i, quantity } : i)), })), clearCart: () => set({ items: [] }), total: () => { return get().items.reduce( (sum, item) => sum + item.price * item.quantity, 0, ); }, })); // ============================================ // Selectors (Optimization) // ============================================ // Use these to prevent unnecessary re-renders export const useUser = () => useAuthStore((state) => state.user); export const useIsAuthenticated = () => useAuthStore((state) => state.isAuthenticated); export const useAuthActions = () => useAuthStore((state) => ({ login: state.login, logout: state.logout })); export const useCartTotal = () => useCartStore((state) => state.total()); export const useCartItemsCount = () => useCartStore((state) => state.items.reduce((acc, item) => acc + item.quantity, 0), ); ```

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/millsydotdev/Code-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server