import { useLocalStorage } from "@vueuse/core"; const STORAGE_ID = "achievements"; export const ACHIEVEMENTS = [ { id: "boot", secret: false }, // projects { id: "projects_visit", secret: false }, { id: "projects_view_5", secret: false }, { id: "projects_open_link", secret: false }, // gallery { id: "gallery_visit", secret: false }, // contact { id: "contact_visit", secret: false }, { id: "contact_git_visit", secret: false }, // settings { id: "settings_color_change", secret: false }, // snake { id: "snake_score_25", secret: false }, // 2048 { id: "2048_score_512", secret: false }, // taptap { id: "taptap_score_20", secret: false }, // secrets { id: "settings_color_try_all", secret: true }, { id: "settings_language_try_all", secret: true }, { id: "settings_visit_all", secret: true }, { id: "contact_36_notifications", secret: true }, ] as const; export type Achievement = (typeof ACHIEVEMENTS)[number]["id"]; export const useAchievementsStore = defineStore("achievements", () => { const app = useAppStore(); const { locale } = useI18n(); const storage = useLocalStorage( STORAGE_ID, { unlocked: [] as Achievement[], advancement: { colors: [app.color.hex], languages: [locale.value], visitedSettings: [] as string[], }, }, { mergeDefaults: true }, ); if (!storage.value.advancement.colors.includes(app.color.hex)) { storage.value.advancement.colors.push(app.color.hex); } if (!storage.value.advancement.languages.includes(locale.value)) { storage.value.advancement.languages.push(locale.value); } const confetti = useConfetti(); const unlock = (name: Achievement) => { if (storage.value.unlocked.includes(name)) { return false; } storage.value.unlocked.push(name); if (storage.value.unlocked.length === ACHIEVEMENTS.length) { confetti.spawn(); } else { confetti.spawn(50, 175); } return true; }; const reset = () => { storage.value = { unlocked: [], advancement: { colors: [app.color.hex], languages: [locale.value], visitedSettings: [], }, }; }; return { unlocked: computed(() => storage.value.unlocked), advancement: computed(() => storage.value.advancement), allObtained: computed( () => storage.value.unlocked.length === ACHIEVEMENTS.length, ), unlock, reset, isUnlocked: computed( () => (name: Achievement) => storage.value.unlocked.includes(name), ), }; });