import { defineStore } from "pinia" import { GET, POST } from "../api"; import { useSessionStore } from "./session"; interface State { Accounts: Map, CurrentAccountID: string | null, Categories: Map, Months: Map>>, Transactions: any[], Assignments: [] } export interface Transaction { ID: string, Date: string, TransferAccount: string, CategoryGroup: string, Category: string, Memo: string, Status: string, GroupID: string, Payee: string, Amount: number, } export interface Account { ID: string Name: string OnBudget: boolean Balance: number } export interface Category { ID: string Group: string Name: string AvailableLastMonth: number Assigned: number Activity: number Available: number } export const useAccountStore = defineStore("budget/account", { state: (): State => ({ Accounts: new Map(), CurrentAccountID: null, Months: new Map>>(), Categories: new Map(), Transactions: [], Assignments: [] }), getters: { AccountsList(state) { return [...state.Accounts.values()]; }, AllCategoriesForMonth: (state) => (year: number, month: number) => { const yearMap = state.Months.get(year); const monthMap = yearMap?.get(month); return [...monthMap?.values() || []]; }, CategoryGroupsForMonth(state) { return (year: number, month: number) => { const categories = this.AllCategoriesForMonth(year, month); const categoryGroups = []; let prev = undefined; for (const category of categories) { if(category.Group != prev) categoryGroups.push(category.Group); prev = category.Group; } return categoryGroups; } }, CategoriesForMonthAndGroup(state) { return (year: number, month: number, group : string) => { const categories = this.AllCategoriesForMonth(year, month); return categories.filter(x => x.Group == group); } }, CurrentAccount(state): Account | undefined { if (state.CurrentAccountID == null) return undefined; return state.Accounts.get(state.CurrentAccountID); }, OnBudgetAccounts(state) { return [...state.Accounts.values()].filter(x => x.OnBudget); }, OnBudgetAccountsBalance(state): number { return this.OnBudgetAccounts.reduce((prev, curr) => prev + Number(curr.Balance), 0); }, OffBudgetAccounts(state) { return [...state.Accounts.values()].filter(x => !x.OnBudget); }, OffBudgetAccountsBalance(state): number { return this.OffBudgetAccounts.reduce((prev, curr) => prev + Number(curr.Balance), 0); }, TransactionsList(state) { return (state.Transactions || []); } }, actions: { async SetCurrentAccount(budgetid: string, accountid: string) { if (budgetid == null) return this.CurrentAccountID = accountid; if (this.CurrentAccount == undefined) return useSessionStore().setTitle(this.CurrentAccount.Name); await this.FetchAccount(accountid); }, async FetchAccount(accountid: string) { const result = await GET("/account/" + accountid + "/transactions"); const response = await result.json(); this.Transactions = response.Transactions; }, async FetchMonthBudget(budgetid: string, year: number, month: number) { const result = await GET("/budget/" + budgetid + "/" + year + "/" + month); const response = await result.json(); if(response.Categories == undefined || response.Categories.length <= 0) return; this.addCategoriesForMonth(year, month, response.Categories); }, addCategoriesForMonth(year: number, month: number, categories: Category[]): void { this.$patch((state) => { const yearMap = state.Months.get(year) || new Map>(); const monthMap = yearMap.get(month) || new Map(); for (const category of categories) { monthMap.set(category.ID, category); } yearMap.set(month, monthMap); state.Months.set(year, yearMap); }); }, logout() { this.$reset() }, async saveTransaction(payload: string) { const result = await POST("/transaction/new", payload); const response = await result.json(); this.Transactions.unshift(response); } } })