Persist in localStorage

This commit is contained in:
Leo Vasanko 2025-08-22 20:16:39 -06:00
parent 407e87e0f9
commit d46aaa6106
5 changed files with 53 additions and 7 deletions

View File

@ -17,6 +17,7 @@
}, },
"dependencies": { "dependencies": {
"pinia": "^3.0.3", "pinia": "^3.0.3",
"pinia-plugin-persistedstate": "^4.5.0",
"vue": "^3.5.18" "vue": "^3.5.18"
}, },
"devDependencies": { "devDependencies": {

View File

@ -63,7 +63,8 @@ const totalVirtualWeeks = computed(() => {
}) })
const initialScrollTop = computed(() => { const initialScrollTop = computed(() => {
const targetWeekIndex = getWeekIndex(calendarStore.now) - 3 const nowDate = new Date(calendarStore.now)
const targetWeekIndex = getWeekIndex(nowDate) - 3
return (targetWeekIndex - minVirtualWeek.value) * rowHeight.value return (targetWeekIndex - minVirtualWeek.value) * rowHeight.value
}) })
@ -76,7 +77,8 @@ const selectedDateRange = computed(() => {
}) })
const todayString = computed(() => { const todayString = computed(() => {
const t = calendarStore.now const d = new Date(calendarStore.now)
const t = d
.toLocaleDateString(undefined, { weekday: 'long', month: 'long', day: 'numeric' }) .toLocaleDateString(undefined, { weekday: 'long', month: 'long', day: 'numeric' })
.replace(/,? /, '\n') .replace(/,? /, '\n')
return t.charAt(0).toUpperCase() + t.slice(1) return t.charAt(0).toUpperCase() + t.slice(1)

View File

@ -2,11 +2,14 @@ import './assets/calendar.css'
import { createApp } from 'vue' import { createApp } from 'vue'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import App from './App.vue' import App from './App.vue'
const app = createApp(App) const app = createApp(App)
app.use(createPinia()) const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
app.use(pinia)
app.mount('#app') app.mount('#app')

24
src/plugins/persist.js Normal file
View File

@ -0,0 +1,24 @@
// Simple Pinia persistence plugin supporting `persist: true` and Map serialization.
export function persistPlugin({ store }) {
if (!store.$options || !store.$options.persist) return
const key = `pinia-${store.$id}`
try {
const raw = localStorage.getItem(key)
if (raw) {
const state = JSON.parse(raw, (k, v) => {
if (v && v.__map === true && Array.isArray(v.data)) return new Map(v.data)
return v
})
store.$patch(state)
}
} catch {}
store.$subscribe((_mutation, state) => {
try {
const json = JSON.stringify(state, (_k, v) => {
if (v instanceof Map) return { __map: true, data: Array.from(v.entries()) }
return v
})
localStorage.setItem(key, json)
} catch {}
})
}

View File

@ -7,7 +7,7 @@ const MAX_YEAR = 2100
export const useCalendarStore = defineStore('calendar', { export const useCalendarStore = defineStore('calendar', {
state: () => ({ state: () => ({
today: toLocalString(new Date()), today: toLocalString(new Date()),
now: new Date(), now: new Date().toISOString(), // store as ISO string
events: new Map(), // Map of date strings to arrays of events events: new Map(), // Map of date strings to arrays of events
weekend: getLocaleWeekendDays(), weekend: getLocaleWeekendDays(),
config: { config: {
@ -26,8 +26,9 @@ export const useCalendarStore = defineStore('calendar', {
actions: { actions: {
updateCurrentDate() { updateCurrentDate() {
this.now = new Date() const d = new Date()
const today = toLocalString(this.now) this.now = d.toISOString()
const today = toLocalString(d)
if (this.today !== today) { if (this.today !== today) {
this.today = today this.today = today
} }
@ -468,4 +469,19 @@ export const useCalendarStore = defineStore('calendar', {
// NOTE: legacy dynamic getEventById for synthetic occurrences removed. // NOTE: legacy dynamic getEventById for synthetic occurrences removed.
}, },
persist: {
key: 'calendar-store',
storage: localStorage,
paths: ['today', 'events', 'config'],
serializer: {
serialize(value) {
return JSON.stringify(value, (_k, v) =>
v instanceof Map ? { __map: true, data: [...v] } : v,
)
},
deserialize(value) {
return JSON.parse(value, (_k, v) => (v && v.__map ? new Map(v.data) : v))
},
},
},
}) })