diff --git a/package-lock.json b/package-lock.json index 8dc5edb..ec451a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "colorthief": "^2.4.0", + "pinia": "^3.0.4", "tinycolor2": "^1.6.0", "vue": "^3.3.4", "vue-router": "^5.0.2" @@ -2797,6 +2798,66 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pinia": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", + "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^7.7.7" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.5.0", + "vue": "^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia/node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, + "node_modules/pinia/node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/pinia/node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/pinia/node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" + }, "node_modules/pkg-types": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", diff --git a/package.json b/package.json index b404777..cf27518 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "colorthief": "^2.4.0", + "pinia": "^3.0.4", "tinycolor2": "^1.6.0", "vue": "^3.3.4", "vue-router": "^5.0.2" diff --git a/src/composables/usePokedexNavigation.js b/src/composables/usePokedexNavigation.js index 65523d2..bfa6cbf 100644 --- a/src/composables/usePokedexNavigation.js +++ b/src/composables/usePokedexNavigation.js @@ -1,6 +1,7 @@ import { ref } from 'vue' import { useRouter, useRoute } from 'vue-router' import { appState } from '../store' +import { usePokemonListStore } from '../stores/pokemonListStore' import { MAX_SEARCH_LENGTH } from '../constants/ui' const searchQuery = ref('') @@ -16,6 +17,7 @@ export const homeMenuState = ref({ export function usePokedexNavigation() { const router = useRouter() const route = useRoute() + const pokemonListStore = usePokemonListStore() function handleKeypad(num) { if (searchQuery.value.length < MAX_SEARCH_LENGTH) { @@ -73,10 +75,10 @@ export function usePokedexNavigation() { function handleMainButton() { if (route.path === '/' && homeMenuState.value.onSelect) { homeMenuState.value.onSelect() + } else if (route.path === '/pokemon' && pokemonListStore.onSelect) { + pokemonListStore.onSelect() } else if (searchQuery.value) { executeSearch() - } else { - goHome() } } @@ -89,6 +91,8 @@ export function usePokedexNavigation() { function handleNext() { if (route.path === '/' && homeMenuState.value.onMoveDown) { homeMenuState.value.onMoveDown() + } else if (route.path === '/pokemon' && pokemonListStore.onMoveDown) { + pokemonListStore.onMoveDown() } else if (appState.currentPokemon) { let nextId = appState.currentPokemon.id + 1 router.push(`/pokemon/${nextId}`) @@ -98,6 +102,8 @@ export function usePokedexNavigation() { function handlePrev() { if (route.path === '/' && homeMenuState.value.onMoveUp) { homeMenuState.value.onMoveUp() + } else if (route.path === '/pokemon' && pokemonListStore.onMoveUp) { + pokemonListStore.onMoveUp() } else if (appState.currentPokemon && appState.currentPokemon.id > 1) { let prevId = appState.currentPokemon.id - 1 router.push(`/pokemon/${prevId}`) diff --git a/src/main.js b/src/main.js index 81f2ec3..bb7778b 100644 --- a/src/main.js +++ b/src/main.js @@ -1,10 +1,13 @@ import { createApp } from "vue"; +import { createPinia } from "pinia"; import "./style.css"; import App from "./App.vue"; import router from "./router"; const app = createApp(App); +const pinia = createPinia(); +app.use(pinia); app.use(router); router.isReady().then(() => { diff --git a/src/pages/Pokedex.vue b/src/pages/Pokedex.vue index 479bd0b..afb47a5 100644 --- a/src/pages/Pokedex.vue +++ b/src/pages/Pokedex.vue @@ -8,9 +8,11 @@ import PageLayout from '../components/layout/PageLayout.vue' import ColorThief from 'colorthief' import { generateThemeColors } from '../utils/theme' import { appState } from '../store' +import { usePokemonListStore } from '../stores/pokemonListStore' import { useScreenActions } from '../composables/useScreenActions' const { setButtonActions } = useScreenActions() +const pokemonListStore = usePokemonListStore() const route = useRoute(); const router = useRouter(); @@ -53,6 +55,7 @@ function getPokemonData() { pokemon.value = json pokemonImage.value = pokemon.value.sprites.other['official-artwork'].front_default appState.setCurrentPokemon(json) + pokemonListStore.setLastSelectedPokemon(currentId) getPokemonColors(pokemonImage.value) }) diff --git a/src/pages/Pokemon.vue b/src/pages/Pokemon.vue index 0204ba0..a8cb5e1 100644 --- a/src/pages/Pokemon.vue +++ b/src/pages/Pokemon.vue @@ -1,24 +1,306 @@ diff --git a/src/stores/pokemonListStore.js b/src/stores/pokemonListStore.js new file mode 100644 index 0000000..0f788c7 --- /dev/null +++ b/src/stores/pokemonListStore.js @@ -0,0 +1,42 @@ +import { defineStore } from 'pinia' + +export const usePokemonListStore = defineStore('pokemonList', { + state: () => ({ + lastSelectedPokemonId: parseInt(localStorage.getItem('lastSelectedPokemonId')) || null, + selectedIndex: 0, + onSelect: null, + onMoveUp: null, + onMoveDown: null + }), + + actions: { + setLastSelectedPokemon(id) { + this.lastSelectedPokemonId = id + if (id) { + localStorage.setItem('lastSelectedPokemonId', id.toString()) + } else { + localStorage.removeItem('lastSelectedPokemonId') + } + }, + + setNavigationHandlers(handlers) { + this.selectedIndex = handlers.selectedIndex || 0 + this.onSelect = handlers.onSelect || null + this.onMoveUp = handlers.onMoveUp || null + this.onMoveDown = handlers.onMoveDown || null + }, + + clearNavigationHandlers() { + this.selectedIndex = 0 + this.onSelect = null + this.onMoveUp = null + this.onMoveDown = null + } + }, + + getters: { + hasNavigationHandlers: (state) => { + return state.onSelect !== null || state.onMoveUp !== null || state.onMoveDown !== null + } + } +})