First step from vuex to pinia
This commit is contained in:
parent
2137460187
commit
2d0737a10c
@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"@mdi/font": "5.9.55",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"pinia": "^2.0.11",
|
||||
"postcss": "^8.4.6",
|
||||
"tailwindcss": "^3.0.18",
|
||||
"vue": "^3.2.25",
|
||||
|
@ -21,7 +21,22 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
beforeCreate () {
|
||||
this.$store.commit("initializeStore");
|
||||
const store = localStorage.getItem("store");
|
||||
if (!store)
|
||||
return;
|
||||
|
||||
const restoredState = JSON.parse(store);
|
||||
if (!restoredState)
|
||||
return;
|
||||
|
||||
state.Session = restoredState.Session;
|
||||
state.CurrentBudgetID = restoredState.CurrentBudgetID;
|
||||
state.ShowMenu = restoredState.ShowMenu;
|
||||
state.ExpandMenu = restoredState.ExpandMenu;
|
||||
|
||||
for (const budget of restoredState.Budgets || []) {
|
||||
state.Budgets.set(budget[0], budget[1]);
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
@ -2,12 +2,12 @@ import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import './index.css'
|
||||
import router from './router'
|
||||
import { store, key } from './store'
|
||||
import { createPinia } from 'pinia'
|
||||
import { SET_CURRENT_ACCOUNT, SET_CURRENT_BUDGET } from './store/action-types'
|
||||
|
||||
const app = createApp(App)
|
||||
app.use(router)
|
||||
app.use(store, key)
|
||||
app.use(createPinia())
|
||||
app.mount('#app')
|
||||
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
|
@ -3,98 +3,21 @@ import { createStore, Store, createLogger } from 'vuex'
|
||||
import { LOGIN_SUCCESS, LOGOUT, TITLE } from './mutation-types'
|
||||
import { FETCH_ACCOUNT, FETCH_BUDGET, GET, REGISTER, IMPORT_YNAB, LOGIN, NEW_BUDGET, POST, SET_CURRENT_ACCOUNT, SET_CURRENT_BUDGET } from './action-types'
|
||||
import { budgetStore } from './budget'
|
||||
|
||||
export interface State {
|
||||
Session: {
|
||||
Token?: string
|
||||
User?: string
|
||||
},
|
||||
ShowMenu?: boolean,
|
||||
ExpandMenu?: boolean,
|
||||
Budgets: Map<string, Budget>,
|
||||
CurrentBudgetID?: string,
|
||||
}
|
||||
|
||||
export interface Budget {
|
||||
ID: string
|
||||
Name: string
|
||||
AvailableBalance: number
|
||||
}
|
||||
import { Budget, useSessionStore } from '../stores/session'
|
||||
|
||||
export const key: InjectionKey<Store<State>> = Symbol()
|
||||
|
||||
export const store = createStore<State>({
|
||||
state: {
|
||||
Session: {
|
||||
Token: undefined,
|
||||
User: undefined
|
||||
},
|
||||
ShowMenu: undefined,
|
||||
Budgets: new Map<string, Budget>(),
|
||||
CurrentBudgetID: undefined,
|
||||
},
|
||||
mutations: {
|
||||
deleteBudget(state: State, budgetid: string) {
|
||||
state.Budgets.delete(budgetid)
|
||||
},
|
||||
toggleMenu(state) {
|
||||
state.ShowMenu = !state.ShowMenu;
|
||||
},
|
||||
toggleMenuSize(state) {
|
||||
state.ExpandMenu = !state.ExpandMenu;
|
||||
},
|
||||
initializeStore(state) {
|
||||
const store = localStorage.getItem("store");
|
||||
if (!store)
|
||||
return;
|
||||
|
||||
const restoredState = JSON.parse(store);
|
||||
if (!restoredState)
|
||||
return;
|
||||
|
||||
state.Session = restoredState.Session;
|
||||
state.CurrentBudgetID = restoredState.CurrentBudgetID;
|
||||
state.ShowMenu = restoredState.ShowMenu;
|
||||
state.ExpandMenu = restoredState.ExpandMenu;
|
||||
|
||||
for (const budget of restoredState.Budgets || []) {
|
||||
state.Budgets.set(budget[0], budget[1]);
|
||||
}
|
||||
},
|
||||
[TITLE](state, title) {
|
||||
document.title = "Budgeteer - " + title;
|
||||
},
|
||||
[LOGIN_SUCCESS](state, result) {
|
||||
state.Session = {
|
||||
User: result.User,
|
||||
Token: result.Token
|
||||
};
|
||||
for (const budget of result.Budgets) {
|
||||
state.Budgets.set(budget.ID, budget)
|
||||
}
|
||||
},
|
||||
addBudget(state, budget) {
|
||||
state.Budgets.set(budget.ID, budget);
|
||||
},
|
||||
[LOGOUT](state) {
|
||||
state.Session = { Token: undefined, User: undefined };
|
||||
state.Budgets.clear();
|
||||
},
|
||||
setCurrentBudgetID(state, budgetid) {
|
||||
state.CurrentBudgetID = budgetid;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
[LOGIN]({ state, commit }, login) {
|
||||
return fetch("/api/v1/user/login", { method: "POST", body: JSON.stringify(login) })
|
||||
.then(x => x.json())
|
||||
.then(x => commit(LOGIN_SUCCESS, x))
|
||||
},
|
||||
[REGISTER]({ state, commit }, login) {
|
||||
return fetch("/api/v1/user/register", { method: "POST", body: JSON.stringify(login) })
|
||||
.then(x => x.json())
|
||||
.then(x => commit(LOGIN_SUCCESS, x))
|
||||
},
|
||||
[IMPORT_YNAB]({ getters, dispatch }, formData) {
|
||||
return dispatch("POST", { path: "/budget/" + getters.CurrentBudget.ID + "/import/ynab", body: formData });
|
||||
},
|
||||
@ -137,9 +60,6 @@ export const store = createStore<State>({
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
Budgets(state) {
|
||||
return state.Budgets.values();
|
||||
},
|
||||
AuthHeaders(state) {
|
||||
return {
|
||||
'Authorization': 'Bearer ' + state.Session.Token
|
||||
@ -171,9 +91,10 @@ export const store = createStore<State>({
|
||||
})
|
||||
|
||||
store.subscribe((mutation, state) => {
|
||||
|
||||
const sessionStore = useSessionStore();
|
||||
let persistedState = {
|
||||
Session: state.Session,
|
||||
Budgets: [...state.Budgets],
|
||||
Session: sessionStore,
|
||||
// Accounts: [...state.Accounts],
|
||||
CurrentBudgetID: state.CurrentBudgetID,
|
||||
//CurrentAccountID: state.CurrentAccountID,
|
||||
|
16
web/src/stores/budgets.ts
Normal file
16
web/src/stores/budgets.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
interface State {
|
||||
CurrentBudgetID: string | null,
|
||||
}
|
||||
|
||||
export const useBudgetsStore = defineStore('budget', {
|
||||
state: (): State => ({
|
||||
CurrentBudgetID: null
|
||||
}),
|
||||
actions: {
|
||||
setCurrentBudgetID(budgetid : string) {
|
||||
this.CurrentBudgetID = budgetid;
|
||||
},
|
||||
}
|
||||
})
|
69
web/src/stores/session.ts
Normal file
69
web/src/stores/session.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
interface State {
|
||||
Token: string | null
|
||||
User: string | null
|
||||
Budgets: Map<string, Budget>,
|
||||
}
|
||||
|
||||
export interface Budget {
|
||||
ID: string
|
||||
Name: string
|
||||
AvailableBalance: number
|
||||
}
|
||||
|
||||
export const useSessionStore = defineStore('session', {
|
||||
// convert to a function
|
||||
state: (): State => ({
|
||||
Token: null,
|
||||
User: null,
|
||||
Budgets: new Map<string, Budget>(),
|
||||
}),
|
||||
getters: {
|
||||
Budgets(): IterableIterator<Budget> {
|
||||
return this.Budgets.values();
|
||||
},
|
||||
/*// must define return type because of using `this`
|
||||
fullUserDetails (state): FullUserDetails {
|
||||
// import from other stores
|
||||
const authPreferencesStore = useAuthPreferencesStore()
|
||||
const authEmailStore = useAuthEmailStore()
|
||||
return {
|
||||
...state,
|
||||
// other getters now on `this`
|
||||
fullName: this.fullName,
|
||||
...authPreferencesStore.$state,
|
||||
...authEmailStore.details
|
||||
}
|
||||
|
||||
// alternative if other modules are still in Vuex
|
||||
// return {
|
||||
// ...state,
|
||||
// fullName: this.fullName,
|
||||
// ...vuexStore.state.auth.preferences,
|
||||
// ...vuexStore.getters['auth/email'].details
|
||||
// }
|
||||
}*/
|
||||
},
|
||||
actions: {
|
||||
loginSuccess(x : any) {
|
||||
this.User = x.User;
|
||||
this.Token = x.Token;
|
||||
this.Budgets = x.Budgets;
|
||||
},
|
||||
login(login: any) {
|
||||
return fetch("/api/v1/user/login", { method: "POST", body: JSON.stringify(login) })
|
||||
.then(x => x.json())
|
||||
.then(x => this.loginSuccess(x));
|
||||
},
|
||||
register(login : any) {
|
||||
return fetch("/api/v1/user/register", { method: "POST", body: JSON.stringify(login) })
|
||||
.then(x => x.json())
|
||||
.then(x => this.loginSuccess(x))
|
||||
},
|
||||
// easily reset state using `$reset`
|
||||
logout() {
|
||||
this.$reset()
|
||||
}
|
||||
}
|
||||
})
|
21
web/src/stores/settings.ts
Normal file
21
web/src/stores/settings.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
interface State {
|
||||
ShowMenu?: boolean,
|
||||
ExpandMenu?: boolean,
|
||||
}
|
||||
|
||||
export const useSettingsStore = defineStore('settings', {
|
||||
state: (): State => ({
|
||||
ShowMenu: undefined,
|
||||
ExpandMenu: false,
|
||||
}),
|
||||
actions: {
|
||||
toggleMenu() {
|
||||
this.ShowMenu = !this.ShowMenu;
|
||||
},
|
||||
toggleMenuSize() {
|
||||
this.ExpandMenu = !this.ExpandMenu;
|
||||
},
|
||||
}
|
||||
});
|
@ -1588,6 +1588,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.0.0-beta.21.1.tgz#f1410f53c42aa67fa3b01ca7bdba891f69d7bc97"
|
||||
integrity sha512-FqC4s3pm35qGVeXRGOjTsRzlkJjrBLriDS9YXbflHLsfA9FrcKzIyWnLXoNm+/7930E8rRakXuAc2QkC50swAw==
|
||||
|
||||
"@vue/devtools-api@^6.0.0-beta.21":
|
||||
version "6.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.0.5.tgz#7e35cfee4f44ada65cde0d19341fbaeb0ae353f4"
|
||||
integrity sha512-2nM84dzo3B63pKgxwoArlT1d/yqSL0y2lG2GiyyGhwpyPTwkfIuJHlCNbputCoSCNnT6MMfenK1g7nv7Mea19A==
|
||||
|
||||
"@vue/reactivity-transform@3.2.29":
|
||||
version "3.2.29"
|
||||
resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.29.tgz#a08d606e10016b7cf588d1a43dae4db2953f9354"
|
||||
@ -6260,6 +6265,14 @@ pify@^4.0.1:
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
|
||||
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
|
||||
|
||||
pinia@^2.0.11:
|
||||
version "2.0.11"
|
||||
resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.0.11.tgz#ff03c714f5e5f16207280a4fc2eab01f3701ee2b"
|
||||
integrity sha512-JzcmnMqu28PNWOjDgEDK6fTrIzX8eQZKPPKvu/fpHdpXARUj1xeVdFi3YFIMOWswqaBd589cpmAMdSSTryI9iw==
|
||||
dependencies:
|
||||
"@vue/devtools-api" "^6.0.0-beta.21"
|
||||
vue-demi "*"
|
||||
|
||||
pkg-dir@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
|
||||
@ -8167,6 +8180,11 @@ vue-cli-plugin-vuetify@~2.4.5:
|
||||
semver "^7.1.2"
|
||||
shelljs "^0.8.3"
|
||||
|
||||
vue-demi@*:
|
||||
version "0.12.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.12.1.tgz#f7e18efbecffd11ab069d1472d7a06e319b4174c"
|
||||
integrity sha512-QL3ny+wX8c6Xm1/EZylbgzdoDolye+VpCXRhI2hug9dJTP3OUJ3lmiKN3CsVV3mOJKwFi0nsstbgob0vG7aoIw==
|
||||
|
||||
vue-hot-reload-api@^2.3.0:
|
||||
version "2.3.4"
|
||||
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"
|
||||
|
Loading…
x
Reference in New Issue
Block a user