diff --git a/store/useInventoryStore.ts b/store/useInventoryStore.ts new file mode 100644 index 0000000..d27ae06 --- /dev/null +++ b/store/useInventoryStore.ts @@ -0,0 +1,135 @@ +import { create } from 'zustand'; +import { persist } from 'zustand/middleware'; + +export interface InventoryState { + unlockedCharacters: string[]; + unlockedCustomizations: string[]; + items: Record; + offerings: Record; + unlockAllDLCs: boolean; + + toggleItem: (id: string, category: 'characters' | 'customizations' | 'items' | 'offerings') => void; + setItemQuantity: (id: string, qty: number) => void; + setOfferingQuantity: (id: string, qty: number) => void; + setUnlockAllDLCs: (val: boolean) => void; + + unlockAllInCategory: (category: 'characters' | 'customizations' | 'items' | 'offerings', allIds: string[], qty?: number) => void; + clearCategory: (category: 'characters' | 'customizations' | 'items' | 'offerings') => void; + clearAll: () => void; + importProfile: (profile: any) => void; +} + +export const useInventoryStore = create()( + persist( + (set) => ({ + unlockedCharacters: [], + unlockedCustomizations: [], + items: {}, + offerings: {}, + unlockAllDLCs: false, + + toggleItem: (id, category) => set((state) => { + if (category === 'characters') { + const arr = state.unlockedCharacters; + return { + unlockedCharacters: arr.includes(id) ? arr.filter(i => i !== id) : [...arr, id] + }; + } else if (category === 'customizations') { + const arr = state.unlockedCustomizations; + return { + unlockedCustomizations: arr.includes(id) ? arr.filter(i => i !== id) : [...arr, id] + }; + } else if (category === 'items') { + const current = state.items[id] || 0; + const newItems = { ...state.items }; + if (current > 0) { + delete newItems[id]; + } else { + newItems[id] = 100; + } + return { items: newItems }; + } else { + const current = state.offerings[id] || 0; + const newOfferings = { ...state.offerings }; + if (current > 0) { + delete newOfferings[id]; + } else { + newOfferings[id] = 100; + } + return { offerings: newOfferings }; + } + }), + + setItemQuantity: (id, qty) => set((state) => { + const newItems = { ...state.items }; + if (qty <= 0) { + delete newItems[id]; + } else { + newItems[id] = Math.min(32767, Math.max(0, qty)); + } + return { items: newItems }; + }), + + setOfferingQuantity: (id, qty) => set((state) => { + const newOfferings = { ...state.offerings }; + if (qty <= 0) { + delete newOfferings[id]; + } else { + newOfferings[id] = Math.min(32767, Math.max(0, qty)); + } + return { offerings: newOfferings }; + }), + + setUnlockAllDLCs: (val) => set({ unlockAllDLCs: val }), + + unlockAllInCategory: (category, allIds, qty = 100) => set((state) => { + if (category === 'characters') { + return { unlockedCharacters: allIds }; + } else if (category === 'customizations') { + return { unlockedCustomizations: allIds }; + } else if (category === 'items') { + const newItems = { ...state.items }; + allIds.forEach(id => { + newItems[id] = qty; + }); + return { items: newItems }; + } else { + const newOfferings = { ...state.offerings }; + allIds.forEach(id => { + newOfferings[id] = qty; + }); + return { offerings: newOfferings }; + } + }), + + clearCategory: (category) => set((state) => { + if (category === 'characters') return { unlockedCharacters: [] }; + if (category === 'customizations') return { unlockedCustomizations: [] }; + if (category === 'items') return { items: {} }; + return { offerings: {} }; + }), + + clearAll: () => set({ + unlockedCharacters: [], + unlockedCustomizations: [], + items: {}, + offerings: {}, + unlockAllDLCs: false + }), + + importProfile: (profile) => set((state) => { + if (!profile) return {}; + return { + unlockedCharacters: Array.isArray(profile.unlockedCharacters) ? profile.unlockedCharacters : state.unlockedCharacters, + unlockedCustomizations: Array.isArray(profile.unlockedCustomizations) ? profile.unlockedCustomizations : state.unlockedCustomizations, + items: (profile.items && typeof profile.items === 'object') ? profile.items : state.items, + offerings: (profile.offerings && typeof profile.offerings === 'object') ? profile.offerings : state.offerings, + unlockAllDLCs: typeof profile.unlockAllDLCs === 'boolean' ? profile.unlockAllDLCs : state.unlockAllDLCs, + }; + }) + }), + { + name: 'hex-unlocked-inventory', + } + ) +); \ No newline at end of file