2026-03-04 11:13:15 -08:00
|
|
|
import { createStore } from 'zustand/vanilla'
|
2026-03-04 18:35:20 -08:00
|
|
|
import { persist, createJSONStorage } from 'zustand/middleware'
|
|
|
|
|
import { get, set, del } from 'idb-keyval'
|
2026-03-04 12:23:40 -08:00
|
|
|
|
2026-03-04 18:55:48 -08:00
|
|
|
// Create IndexedDB storage adapter with error handling
|
2026-03-04 18:35:20 -08:00
|
|
|
const storage = createJSONStorage(() => ({
|
|
|
|
|
getItem: async (name) => {
|
2026-03-04 18:55:48 -08:00
|
|
|
try {
|
|
|
|
|
const value = await get(name)
|
|
|
|
|
return value ?? null
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('IndexedDB getItem error:', error)
|
|
|
|
|
return null // Fallback to null if IndexedDB fails
|
|
|
|
|
}
|
2026-03-04 18:35:20 -08:00
|
|
|
},
|
|
|
|
|
setItem: async (name, value) => {
|
2026-03-04 18:55:48 -08:00
|
|
|
try {
|
|
|
|
|
await set(name, value)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('IndexedDB setItem error:', error)
|
|
|
|
|
// Silently fail - app continues to work without persistence
|
|
|
|
|
}
|
2026-03-04 18:35:20 -08:00
|
|
|
},
|
|
|
|
|
removeItem: async (name) => {
|
2026-03-04 18:55:48 -08:00
|
|
|
try {
|
|
|
|
|
await del(name)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('IndexedDB removeItem error:', error)
|
|
|
|
|
// Silently fail
|
|
|
|
|
}
|
2026-03-04 18:35:20 -08:00
|
|
|
},
|
2026-03-04 12:23:40 -08:00
|
|
|
}))
|
2026-03-04 18:35:20 -08:00
|
|
|
|
|
|
|
|
export const store = createStore(
|
|
|
|
|
persist(
|
|
|
|
|
(set, get) => ({
|
|
|
|
|
_hydrated: true, // Start as true - persistence happens in background
|
|
|
|
|
user: null,
|
|
|
|
|
items: [],
|
|
|
|
|
route: 'home',
|
2026-03-04 18:55:48 -08:00
|
|
|
error: null, // For error notifications
|
2026-03-04 18:35:20 -08:00
|
|
|
|
|
|
|
|
// Actions
|
|
|
|
|
setUser: (user) => set({ user }),
|
2026-03-04 18:55:48 -08:00
|
|
|
|
|
|
|
|
addItem: (item) => {
|
|
|
|
|
try {
|
|
|
|
|
if (!item || !item.name || !item.name.trim()) {
|
|
|
|
|
throw new Error('Item name is required')
|
|
|
|
|
}
|
|
|
|
|
set(s => ({ items: [...s.items, item], error: null }))
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('addItem error:', error)
|
|
|
|
|
set({ error: error.message })
|
|
|
|
|
setTimeout(() => set({ error: null }), 3000) // Clear after 3s
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
removeItem: (id) => {
|
|
|
|
|
try {
|
|
|
|
|
if (!id) {
|
|
|
|
|
throw new Error('Item ID is required')
|
|
|
|
|
}
|
|
|
|
|
set(s => ({ items: s.items.filter(i => i.id !== id), error: null }))
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('removeItem error:', error)
|
|
|
|
|
set({ error: error.message })
|
|
|
|
|
setTimeout(() => set({ error: null }), 3000)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2026-03-04 18:35:20 -08:00
|
|
|
navigate: (route) => set({ route }),
|
2026-03-04 18:55:48 -08:00
|
|
|
|
|
|
|
|
clearError: () => set({ error: null }),
|
2026-03-04 18:35:20 -08:00
|
|
|
}),
|
|
|
|
|
{
|
|
|
|
|
name: 'app-store',
|
|
|
|
|
storage,
|
|
|
|
|
partialize: (state) => ({
|
|
|
|
|
user: state.user,
|
|
|
|
|
items: state.items,
|
|
|
|
|
route: state.route,
|
|
|
|
|
}),
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
)
|