From e912270d1eee546ddfcde2d28c512133e6535fc8 Mon Sep 17 00:00:00 2001 From: Pihkaal Date: Sun, 28 Dec 2025 23:56:23 +0100 Subject: [PATCH] feat(app): store settings in the local storage --- app/stores/app.ts | 47 ++++++++++++++++++++++++++++++++++++++++++----- package.json | 6 +++--- pnpm-lock.yaml | 22 +++++++++++----------- 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/app/stores/app.ts b/app/stores/app.ts index d223abe..a203fe1 100644 --- a/app/stores/app.ts +++ b/app/stores/app.ts @@ -1,20 +1,57 @@ +import { z } from "zod/mini"; + +const STORAGE_ID = "app_settings"; + +const settingsSchema = z.object({ + color: z.object({ + col: z.number(), + row: z.number(), + }), +}); + +type Settings = z.infer; + +const defaultSettings = (): Settings => ({ + color: { col: 0, row: 0 }, +}); + +const loadSettings = (): Settings => { + const stored = localStorage.getItem(STORAGE_ID); + try { + const result = settingsSchema.safeParse(JSON.parse(stored ?? "")); + if (result.success) { + return result.data; + } + } catch { + // JSON.parse failed + } + + const settings = defaultSettings(); + saveSettings(settings); + return settings; +}; + +const saveSettings = (settings: Settings) => { + localStorage.setItem(STORAGE_ID, JSON.stringify(settings)); +}; + export const useAppStore = defineStore("app", { state: () => ({ booted: false, - _color: { col: 0, row: 0 }, + settings: loadSettings(), }), actions: { setColor(col: number, row: number) { - this._color = { col, row }; + this.settings.color = { col, row }; }, }, getters: { color: (state) => ({ - col: state._color.col, - row: state._color.row, - hex: APP_COLORS[state._color.row]![state._color.col]!, + col: state.settings.color.col, + row: state.settings.color.row, + hex: APP_COLORS[state.settings.color.row]![state.settings.color.col]!, }), }, }); diff --git a/package.json b/package.json index d258d51..55698ca 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "pinia": "3.0.4", "three": "^0.182.0", "vue": "3.5.25", - "vue-router": "4.6.3" + "vue-router": "4.6.3", + "zod": "^4.2.1" }, "devDependencies": { "@nuxt/content": "3.8.2", @@ -34,7 +35,6 @@ "eslint": "9.39.1", "nuxt": "4.2.1", "prettier": "3.6.2", - "typescript": "5.9.3", - "zod": "4.1.12" + "typescript": "5.9.3" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e398e3f..8fead3f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,7 +15,7 @@ importers: version: 5.2.0(three@0.182.0)(vue@3.5.25(typescript@5.9.3)) "@tresjs/nuxt": specifier: ^5.1.2 - version: 5.1.2(@babel/parser@7.28.5)(@nuxt/content@3.8.2(better-sqlite3@12.4.1)(magicast@0.5.1))(@rollup/pluginutils@5.3.0(rollup@4.53.3))(change-case@5.4.4)(db0@0.3.4(better-sqlite3@12.4.1))(embla-carousel@8.6.0)(esbuild@0.27.1)(ioredis@5.8.2)(magicast@0.5.1)(three@0.182.0)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vue-router@4.6.3(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))(zod@4.1.12) + version: 5.1.2(@babel/parser@7.28.5)(@nuxt/content@3.8.2(better-sqlite3@12.4.1)(magicast@0.5.1))(@rollup/pluginutils@5.3.0(rollup@4.53.3))(change-case@5.4.4)(db0@0.3.4(better-sqlite3@12.4.1))(embla-carousel@8.6.0)(esbuild@0.27.1)(ioredis@5.8.2)(magicast@0.5.1)(three@0.182.0)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vue-router@4.6.3(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))(zod@4.2.1) gsap: specifier: 3.13.0 version: 3.13.0 @@ -31,6 +31,9 @@ importers: vue-router: specifier: 4.6.3 version: 4.6.3(vue@3.5.25(typescript@5.9.3)) + zod: + specifier: ^4.2.1 + version: 4.2.1 devDependencies: "@nuxt/content": specifier: 3.8.2 @@ -71,9 +74,6 @@ importers: typescript: specifier: 5.9.3 version: 5.9.3 - zod: - specifier: 4.1.12 - version: 4.1.12 packages: "@alloc/quick-lru@5.2.0": @@ -9623,10 +9623,10 @@ packages: integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==, } - zod@4.1.12: + zod@4.2.1: resolution: { - integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==, + integrity: sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==, } zwitch@2.0.4: @@ -10815,7 +10815,7 @@ snapshots: transitivePeerDependencies: - magicast - "@nuxt/ui@4.2.1(@babel/parser@7.28.5)(@nuxt/content@3.8.2(better-sqlite3@12.4.1)(magicast@0.5.1))(change-case@5.4.4)(db0@0.3.4(better-sqlite3@12.4.1))(embla-carousel@8.6.0)(ioredis@5.8.2)(magicast@0.5.1)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vue-router@4.6.3(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))(zod@4.1.12)": + "@nuxt/ui@4.2.1(@babel/parser@7.28.5)(@nuxt/content@3.8.2(better-sqlite3@12.4.1)(magicast@0.5.1))(change-case@5.4.4)(db0@0.3.4(better-sqlite3@12.4.1))(embla-carousel@8.6.0)(ioredis@5.8.2)(magicast@0.5.1)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vue-router@4.6.3(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))(zod@4.2.1)": dependencies: "@iconify/vue": 5.0.0(vue@3.5.25(typescript@5.9.3)) "@internationalized/date": 3.10.0 @@ -10866,7 +10866,7 @@ snapshots: optionalDependencies: "@nuxt/content": 3.8.2(better-sqlite3@12.4.1)(magicast@0.5.1) vue-router: 4.6.3(vue@3.5.25(typescript@5.9.3)) - zod: 4.1.12 + zod: 4.2.1 transitivePeerDependencies: - "@azure/app-configuration" - "@azure/cosmos" @@ -11737,10 +11737,10 @@ snapshots: three: 0.182.0 vue: 3.5.25(typescript@5.9.3) - "@tresjs/nuxt@5.1.2(@babel/parser@7.28.5)(@nuxt/content@3.8.2(better-sqlite3@12.4.1)(magicast@0.5.1))(@rollup/pluginutils@5.3.0(rollup@4.53.3))(change-case@5.4.4)(db0@0.3.4(better-sqlite3@12.4.1))(embla-carousel@8.6.0)(esbuild@0.27.1)(ioredis@5.8.2)(magicast@0.5.1)(three@0.182.0)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vue-router@4.6.3(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))(zod@4.1.12)": + "@tresjs/nuxt@5.1.2(@babel/parser@7.28.5)(@nuxt/content@3.8.2(better-sqlite3@12.4.1)(magicast@0.5.1))(@rollup/pluginutils@5.3.0(rollup@4.53.3))(change-case@5.4.4)(db0@0.3.4(better-sqlite3@12.4.1))(embla-carousel@8.6.0)(esbuild@0.27.1)(ioredis@5.8.2)(magicast@0.5.1)(three@0.182.0)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vue-router@4.6.3(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))(zod@4.2.1)": dependencies: "@nuxt/kit": 4.1.2(magicast@0.5.1) - "@nuxt/ui": 4.2.1(@babel/parser@7.28.5)(@nuxt/content@3.8.2(better-sqlite3@12.4.1)(magicast@0.5.1))(change-case@5.4.4)(db0@0.3.4(better-sqlite3@12.4.1))(embla-carousel@8.6.0)(ioredis@5.8.2)(magicast@0.5.1)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vue-router@4.6.3(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))(zod@4.1.12) + "@nuxt/ui": 4.2.1(@babel/parser@7.28.5)(@nuxt/content@3.8.2(better-sqlite3@12.4.1)(magicast@0.5.1))(change-case@5.4.4)(db0@0.3.4(better-sqlite3@12.4.1))(embla-carousel@8.6.0)(ioredis@5.8.2)(magicast@0.5.1)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vue-router@4.6.3(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))(zod@4.2.1) "@tresjs/core": 5.2.0(three@0.182.0)(vue@3.5.25(typescript@5.9.3)) defu: 6.1.4 mlly: 1.8.0 @@ -16378,6 +16378,6 @@ snapshots: zod@3.25.76: {} - zod@4.1.12: {} + zod@4.2.1: {} zwitch@2.0.4: {}