89 lines
2.3 KiB
TypeScript
89 lines
2.3 KiB
TypeScript
import { useLocalStorage } from "@vueuse/core";
|
|
|
|
const STORAGE_ID = "nds-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 },
|
|
{ id: "contact_linkedin_visit", secret: false },
|
|
// settings
|
|
{ id: "settings_color_change", secret: false },
|
|
{ id: "settings_visit_all", secret: false },
|
|
// snake
|
|
{ id: "snake_score_25", secret: false },
|
|
// 2048
|
|
{ id: "2048_score_512", secret: false },
|
|
// taptap
|
|
{ id: "taptap_score_20", secret: false },
|
|
// meta
|
|
{ id: "all_achievements", secret: false },
|
|
] as const;
|
|
|
|
export type Achievement = (typeof ACHIEVEMENTS)[number]["id"];
|
|
|
|
export const useAchievementsStore = defineStore("achievements", () => {
|
|
const storage = useLocalStorage(
|
|
STORAGE_ID,
|
|
{
|
|
unlocked: [] as Achievement[],
|
|
advancement: {
|
|
visitedSettings: [] as string[],
|
|
},
|
|
},
|
|
{ mergeDefaults: true },
|
|
);
|
|
|
|
const unlock = (name: Achievement) => {
|
|
if (storage.value.unlocked.includes(name)) {
|
|
return false;
|
|
}
|
|
|
|
storage.value.unlocked.push(name);
|
|
|
|
if (name !== "all_achievements") {
|
|
const othersCount = ACHIEVEMENTS.length - 1;
|
|
const unlockedOthers = storage.value.unlocked.filter(
|
|
(id) => id !== "all_achievements" && validIds.has(id as Achievement),
|
|
).length;
|
|
if (unlockedOthers === othersCount) {
|
|
unlock("all_achievements");
|
|
}
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
const reset = () => {
|
|
storage.value = {
|
|
unlocked: [],
|
|
advancement: {
|
|
visitedSettings: [],
|
|
},
|
|
};
|
|
};
|
|
|
|
const validIds = new Set(ACHIEVEMENTS.map((a) => a.id));
|
|
const unlocked = computed(() =>
|
|
storage.value.unlocked.filter((id) => validIds.has(id as Achievement)),
|
|
);
|
|
|
|
return {
|
|
unlocked,
|
|
advancement: computed(() => storage.value.advancement),
|
|
allObtained: computed(() => unlocked.value.length === ACHIEVEMENTS.length),
|
|
unlock,
|
|
reset,
|
|
isUnlocked: computed(
|
|
() => (name: Achievement) => storage.value.unlocked.includes(name),
|
|
),
|
|
};
|
|
});
|