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));