Use vue's Composition API #10

Merged
jacob1123 merged 4 commits from vue-composition into master 2022-02-14 23:44:01 +01:00
15 changed files with 302 additions and 356 deletions

26
web/src/api.ts Normal file
View File

@ -0,0 +1,26 @@
import { useSessionStore } from "./stores/session";
export const BASE_URL = "/api/v1"
export function GET(path: string) {
const sessionStore = useSessionStore();
return fetch(BASE_URL + path, {
headers: sessionStore.AuthHeaders,
})
};
export function POST(path: string, body: FormData | string | null) {
const sessionStore = useSessionStore();
return fetch(BASE_URL + path, {
method: "POST",
headers: sessionStore.AuthHeaders,
body: body,
})
}
export function DELETE(path: string) {
const sessionStore = useSessionStore();
return fetch(BASE_URL + path, {
method: "DELETE",
headers: sessionStore.AuthHeaders,
})
}

View File

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from "vue" import { defineComponent, PropType } from "vue"
import { useAPI } from "../stores/api"; import { GET } from "../api";
import { useBudgetsStore } from "../stores/budget"; import { useBudgetsStore } from "../stores/budget";
export interface Suggestion { export interface Suggestion {
@ -42,9 +42,8 @@ export default defineComponent({
return; return;
} }
const api = useAPI();
const budgetStore = useBudgetsStore(); const budgetStore = useBudgetsStore();
api.GET("/budget/" + budgetStore.CurrentBudgetID + "/autocomplete/" + this.type + "?s=" + text) GET("/budget/" + budgetStore.CurrentBudgetID + "/autocomplete/" + this.type + "?s=" + text)
.then(x=>x.json()) .then(x=>x.json())
.then(x => { .then(x => {
let suggestions = x || []; let suggestions = x || [];

View File

@ -1,46 +1,40 @@
<script lang="ts"> <script lang="ts" setup>
import { mapState } from "pinia"; import { computed, ref } from "vue"
import { defineComponent } from "vue"
import Autocomplete, { Suggestion } from '../components/Autocomplete.vue' import Autocomplete, { Suggestion } from '../components/Autocomplete.vue'
import Currency from "../components/Currency.vue"; import Currency from "../components/Currency.vue";
import TransactionRow from "../components/TransactionRow.vue"; import TransactionRow from "../components/TransactionRow.vue";
import { useAPI } from "../stores/api"; import { POST } from "../api";
import { useAccountStore } from "../stores/budget-account"; import { useAccountStore } from "../stores/budget-account";
import { useSessionStore } from "../stores/session";
export default defineComponent({ const props = defineProps<{
data() { budgetid: string
return { accountid: string
TransactionDate: new Date().toISOString().substring(0, 10), }>()
Payee: undefined as Suggestion | undefined,
Category: undefined as Suggestion | undefined, const TransactionDate = ref(new Date().toISOString().substring(0, 10));
Memo: "", const Payee = ref<Suggestion | undefined>(undefined);
Amount: 0 const Category = ref<Suggestion | undefined>(undefined);
} const Memo = ref("");
}, const Amount = ref(0);
components: { Autocomplete, Currency, TransactionRow },
props: ["budgetid", "accountid"], function saveTransaction(e: MouseEvent) {
computed: {
...mapState(useAccountStore, ["CurrentAccount", "TransactionsList"]),
},
methods: {
saveTransaction(e : MouseEvent) {
e.preventDefault(); e.preventDefault();
const api = useAPI(); POST("/transaction/new", JSON.stringify({
api.POST("/transaction/new", JSON.stringify({ budget_id: props.budgetid,
budget_id: this.budgetid, account_id: props.accountid,
account_id: this.accountid, date: TransactionDate.value,
date: this.$data.TransactionDate, payee: Payee.value,
payee: this.$data.Payee, category: Category.value,
category: this.$data.Category, memo: Memo.value,
memo: this.$data.Memo, amount: Amount,
amount: this.$data.Amount,
state: "Uncleared" state: "Uncleared"
})) }))
.then(x => x.json()); .then(x => x.json());
}, }
}
}) const accountStore = useAccountStore();
const CurrentAccount = accountStore.CurrentAccount;
const TransactionsList = accountStore.TransactionsList;
</script> </script>
<template> <template>
@ -73,16 +67,22 @@ export default defineComponent({
<input class="block w-full border-b-2 border-black" type="text" v-model="Memo" /> <input class="block w-full border-b-2 border-black" type="text" v-model="Memo" />
</td> </td>
<td style="width: 80px;" class="text-right"> <td style="width: 80px;" class="text-right">
<input class="text-right block w-full border-b-2 border-black" type="currency" v-model="Amount" /> <input
class="text-right block w-full border-b-2 border-black"
type="currency"
v-model="Amount"
/>
</td> </td>
<td style="width: 20px;"> <td style="width: 20px;">
<input type="submit" @click="saveTransaction" value="Save" /> <input type="submit" @click="saveTransaction" value="Save" />
</td> </td>
<td style="width: 20px;"></td> <td style="width: 20px;"></td>
</tr> </tr>
<TransactionRow v-for="(transaction, index) in TransactionsList" <TransactionRow
v-for="(transaction, index) in TransactionsList"
:transaction="transaction" :transaction="transaction"
:index="index" /> :index="index"
/>
</table> </table>
</template> </template>

View File

@ -1,10 +1,8 @@
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from "vue"; import { onMounted } from 'vue';
export default defineComponent({ onMounted(() => {
mounted() {
document.title = "Budgeteer - Admin"; document.title = "Budgeteer - Admin";
},
}) })
</script> </script>

View File

@ -1,20 +1,25 @@
<script lang="ts"> <script lang="ts" setup>
import { mapState } from "pinia"
import { defineComponent } from "vue"
import Currency from "../components/Currency.vue" import Currency from "../components/Currency.vue"
import { useBudgetsStore } from "../stores/budget" import { useBudgetsStore } from "../stores/budget"
import { useAccountStore } from "../stores/budget-account" import { useAccountStore } from "../stores/budget-account"
import { useSettingsStore } from "../stores/settings" import { useSettingsStore } from "../stores/settings"
export default defineComponent({ const props = defineProps<{
props: ["budgetid", "accountid"], budgetid: string,
components: { Currency }, accountid: string,
computed: { }>();
...mapState(useSettingsStore, ["ExpandMenu"]),
...mapState(useBudgetsStore, ["CurrentBudgetName", "CurrentBudgetID"]), const ExpandMenu = useSettingsStore().Menu.Expand;
...mapState(useAccountStore, ["OnBudgetAccounts", "OnBudgetAccountsBalance", "OffBudgetAccounts", "OffBudgetAccountsBalance"])
} const budgetStore = useBudgetsStore();
}) const CurrentBudgetName = budgetStore.CurrentBudgetName;
const CurrentBudgetID = budgetStore.CurrentBudgetID;
const accountStore = useAccountStore();
const OnBudgetAccounts = accountStore.OnBudgetAccounts;
const OffBudgetAccounts = accountStore.OffBudgetAccounts;
const OnBudgetAccountsBalance = accountStore.OnBudgetAccountsBalance;
const OffBudgetAccountsBalance = accountStore.OffBudgetAccountsBalance;
</script> </script>
<template> <template>

View File

@ -1,68 +1,48 @@
<script lang="ts"> <script lang="ts" setup>
import { mapState } from "pinia"; import { computed, defineProps, onMounted, PropType, watch, watchEffect } from "vue";
import { defineComponent, PropType } from "vue";
import Currency from "../components/Currency.vue"; import Currency from "../components/Currency.vue";
import { useBudgetsStore } from "../stores/budget"; import { useBudgetsStore } from "../stores/budget";
import { Category, useAccountStore } from "../stores/budget-account"; import { useAccountStore } from "../stores/budget-account";
interface Date { interface Date {
Year: number, Year: number,
Month: number, Month: number,
} }
export default defineComponent({ const props = defineProps<{
props: { budgetid: string,
budgetid: {} as PropType<string>, year: string,
year: {} as PropType<number>, month: string,
month: {} as PropType<number>, }>()
},
computed: { const budgetsStore = useBudgetsStore();
...mapState(useBudgetsStore, ["CurrentBudgetID"]), const CurrentBudgetID = computed(() => budgetsStore.CurrentBudgetID);
Categories() : Category[] {
const accountStore = useAccountStore(); const categoriesForMonth = useAccountStore().CategoriesForMonth;
return [...accountStore.CategoriesForMonth(this.selected.Year, this.selected.Month)]; const Categories = computed(() => {
}, return [...categoriesForMonth(selected.value.Year, selected.value.Month)];
previous() : Date { });
return { const previous = computed(() => ({
Year: new Date(this.selected.Year, this.selected.Month - 1, 1).getFullYear(), Year: new Date(selected.value.Year, selected.value.Month - 1, 1).getFullYear(),
Month: new Date(this.selected.Year, this.selected.Month - 1, 1).getMonth(), Month: new Date(selected.value.Year, selected.value.Month - 1, 1).getMonth(),
}; }));
}, const current = computed(() => ({
current() : Date {
return {
Year: new Date().getFullYear(), Year: new Date().getFullYear(),
Month: new Date().getMonth(), Month: new Date().getMonth(),
}; }));
}, const selected = computed(() => ({
selected() : Date { Year: Number(props.year) ?? current.value.Year,
return { Month: Number(props.month ?? current.value.Month)
Year: this.year ?? this.current.Year, }));
Month: Number(this.month ?? this.current.Month) + 1 const next = computed(() => ({
} Year: new Date(selected.value.Year, Number(props.month) + 1, 1).getFullYear(),
}, Month: new Date(selected.value.Year, Number(props.month) + 1, 1).getMonth(),
next() : Date { }));
return {
Year: new Date(this.selected.Year, Number(this.month) + 1, 1).getFullYear(), watchEffect(() => {
Month: new Date(this.selected.Year, Number(this.month) + 1, 1).getMonth(), if (props.year != undefined && props.month != undefined)
}; return useAccountStore().FetchMonthBudget(props.budgetid ?? "", Number(props.year), Number(props.month));
} });
},
mounted() : Promise<void> {
document.title = "Budgeteer - Budget for " + this.selected.Month + "/" + this.selected.Year;
return useAccountStore().FetchMonthBudget(this.budgetid ?? "", this.selected.Year, this.selected.Month);
},
watch: {
year() {
if (this.year != undefined && this.month != undefined)
return useAccountStore().FetchMonthBudget(this.budgetid ?? "", this.year, this.month);
},
month() {
if (this.year != undefined && this.month != undefined)
return useAccountStore().FetchMonthBudget(this.budgetid ?? "", this.year, this.month);
},
},
components: { Currency }
})
/*{{define "title"}} /*{{define "title"}}
{{printf "Budget for %s %d" .Date.Month .Date.Year}} {{printf "Budget for %s %d" .Date.Month .Date.Year}}
@ -70,7 +50,7 @@ export default defineComponent({
</script> </script>
<template> <template>
<h1>Budget for {{ selected.Month }}/{{ selected.Year }}</h1> <h1>Budget for {{ selected.Month + 1 }}/{{ selected.Year }}</h1>
<div> <div>
<router-link <router-link
:to="'/budget/' + CurrentBudgetID + '/budgeting/' + previous.Year + '/' + previous.Month" :to="'/budget/' + CurrentBudgetID + '/budgeting/' + previous.Year + '/' + previous.Month"

View File

@ -1,17 +1,13 @@
<script lang="ts"> <script lang="ts" setup>
import NewBudget from '../dialogs/NewBudget.vue'; import NewBudget from '../dialogs/NewBudget.vue';
import Card from '../components/Card.vue'; import Card from '../components/Card.vue';
import { defineComponent } from 'vue';
import { mapState } from 'pinia';
import { useSessionStore } from '../stores/session'; import { useSessionStore } from '../stores/session';
export default defineComponent({ const props = defineProps<{
props: ["budgetid"], budgetid: string,
components: { NewBudget, Card }, }>();
computed: {
...mapState(useSessionStore, ["BudgetsList"]), const BudgetsList = useSessionStore().BudgetsList;
}
})
</script> </script>
<template> <template>

View File

@ -1,9 +1,4 @@
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue';
export default defineComponent({
})
</script> </script>
<template> <template>

View File

@ -1,46 +1,48 @@
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from "vue"; import { onMounted, ref } from "vue";
import { useRouter } from "vue-router";
import { useSessionStore } from "../stores/session"; import { useSessionStore } from "../stores/session";
export default defineComponent({ const error = ref("");
data() { const login = ref({ user: "", password: "" });
return {
error: "", onMounted(() => {
login: {
user: "",
password: ""
},
showPassword: false
}
},
mounted() {
document.title = "Budgeteer - Login"; document.title = "Budgeteer - Login";
}, });
methods: {
formSubmit(e : MouseEvent) { function formSubmit(e: MouseEvent) {
e.preventDefault(); e.preventDefault();
useSessionStore().login(this.$data.login) useSessionStore().login(login)
.then(x => { .then(x => {
this.$data.error = ""; error.value = "";
this.$router.replace("/dashboard"); useRouter().replace("/dashboard");
}) })
.catch(x => this.$data.error = "The entered credentials are invalid!"); .catch(x => error.value = "The entered credentials are invalid!");
// TODO display invalidCredentials // TODO display invalidCredentials
// TODO redirect to dashboard on success // TODO redirect to dashboard on success
} }
}
})
</script> </script>
<template> <template>
<div> <div>
<input type="text" v-model="login.user" placeholder="Username" class="border-2 border-black rounded-lg block px-2 my-2 w-48" /> <input
<input type="password" v-model="login.password" placeholder="Password" class="border-2 border-black rounded-lg block px-2 my-2 w-48" /> type="text"
v-model="login.user"
placeholder="Username"
class="border-2 border-black rounded-lg block px-2 my-2 w-48"
/>
<input
type="password"
v-model="login.password"
placeholder="Password"
class="border-2 border-black rounded-lg block px-2 my-2 w-48"
/>
</div> </div>
<div>{{ error }}</div> <div>{{ error }}</div>
<button type="submit" @click="formSubmit" class="bg-blue-300 rounded-lg p-2 w-48">Login</button> <button type="submit" @click="formSubmit" class="bg-blue-300 rounded-lg p-2 w-48">Login</button>
<p> <p>
New user? <router-link to="/register">Register</router-link> instead! New user?
<router-link to="/register">Register</router-link>instead!
</p> </p>
</template> </template>

View File

@ -1,31 +1,20 @@
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { ref } from 'vue';
import { useSessionStore } from '../stores/session'; import { useSessionStore } from '../stores/session';
export default defineComponent({ const error = ref("");
data() { const login = ref({ email: "", password: "", name: "" });
return { const showPassword = ref(false);
showPassword: false,
error: "", function formSubmit(e: FormDataEvent) {
login: {
email: "",
password: "",
name: "",
}
}
},
methods: {
formSubmit (e : FormDataEvent) {
e.preventDefault(); e.preventDefault();
useSessionStore().register(this.$data.login) useSessionStore().register(login)
.then(() => this.$data.error = "") .then(() => error.value = "")
.catch(() => this.$data.error = "Something went wrong!"); .catch(() => error.value = "Something went wrong!");
// TODO display invalidCredentials // TODO display invalidCredentials
// TODO redirect to dashboard on success // TODO redirect to dashboard on success
} }
}
})
</script> </script>
<template> <template>
@ -38,30 +27,35 @@ export default defineComponent({
<v-text-field v-model="login.name" type="text" label="Name" /> <v-text-field v-model="login.name" type="text" label="Name" />
</v-col> </v-col>
<v-col cols="6"> <v-col cols="6">
<v-text-field v-model="login.password" label="Password" <v-text-field
v-model="login.password"
label="Password"
:append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'" :append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
:type="showPassword ? 'text' : 'password'" :type="showPassword ? 'text' : 'password'"
@click:append="showPassword = showPassword" @click:append="showPassword = showPassword"
:error-message="error" :error-message="error"
error-count="2" error-count="2"
error /> error
/>
</v-col> </v-col>
<v-col cols="6"> <v-col cols="6">
<v-text-field v-model="login.password" label="Repeat password" <v-text-field
v-model="login.password"
label="Repeat password"
:append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'" :append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
:type="showPassword ? 'text' : 'password'" :type="showPassword ? 'text' : 'password'"
@click:append="showPassword = showPassword" @click:append="showPassword = showPassword"
:error-message="error" :error-message="error"
error-count="2" error-count="2"
error /> error
/>
</v-col> </v-col>
</v-row> </v-row>
<div class="form-group"> <div class="form-group">{{ error }}</div>
{{ error }}
</div>
<v-btn type="submit" @click="formSubmit">Register</v-btn> <v-btn type="submit" @click="formSubmit">Register</v-btn>
<p> <p>
Existing user? <router-link to="/login">Login</router-link> instead! Existing user?
<router-link to="/login">Login</router-link>instead!
</p> </p>
</v-container> </v-container>
</template> </template>

View File

@ -1,67 +1,56 @@
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from "vue" import { computed, defineComponent, onMounted, ref } from "vue"
import { useAPI } from "../stores/api"; import { useRouter } from "vue-router";
import { DELETE, POST } from "../api";
import { useBudgetsStore } from "../stores/budget"; import { useBudgetsStore } from "../stores/budget";
import { useSessionStore } from "../stores/session"; import { useSessionStore } from "../stores/session";
export default defineComponent({ const transactionsFile = ref<File | undefined>(undefined);
data() { const assignmentsFile = ref<File | undefined>(undefined);
return {
transactionsFile: undefined as File | undefined, const filesIncomplete = computed(() => transactionsFile.value == undefined || assignmentsFile.value == undefined);
assignmentsFile: undefined as File | undefined onMounted(() => {
}
},
computed: {
filesIncomplete() : boolean {
return this.$data.transactionsFile == undefined || this.$data.assignmentsFile == undefined;
}
},
mounted() {
document.title = "Budgeteer - Settings"; document.title = "Budgeteer - Settings";
}, });
methods: {
gotAssignments(e : Event) { function gotAssignments(e: Event) {
const input = (<HTMLInputElement>e.target); const input = (<HTMLInputElement>e.target);
if(input.files != null) if (input.files != null)
this.$data.assignmentsFile = input.files[0]; assignmentsFile.value = input.files[0];
}, }
gotTransactions(e : Event) { function gotTransactions(e: Event) {
const input = (<HTMLInputElement>e.target); const input = (<HTMLInputElement>e.target);
if(input.files != null) if (input.files != null)
this.$data.transactionsFile = input.files[0]; transactionsFile.value = input.files[0];
}, };
deleteBudget() { function deleteBudget() {
const currentBudgetID = useBudgetsStore().CurrentBudgetID; const currentBudgetID = useBudgetsStore().CurrentBudgetID;
if (currentBudgetID == null) if (currentBudgetID == null)
return; return;
const api = useAPI(); DELETE("/budget/" + currentBudgetID);
api.DELETE("/budget/" + currentBudgetID);
const budgetStore = useSessionStore(); const budgetStore = useSessionStore();
budgetStore.Budgets.delete(currentBudgetID); budgetStore.Budgets.delete(currentBudgetID);
this.$router.push("/") useRouter().push("/")
}, };
clearBudget() { function clearBudget() {
const currentBudgetID = useBudgetsStore().CurrentBudgetID; const currentBudgetID = useBudgetsStore().CurrentBudgetID;
const api = useAPI(); POST("/budget/" + currentBudgetID + "/settings/clear", null)
api.POST("/budget/" + currentBudgetID + "/settings/clear", null) };
}, function cleanNegative() {
cleanNegative() {
// <a href="/budget/{{.Budget.ID}}/settings/clean-negative">Fix all historic negative category-balances</a> // <a href="/budget/{{.Budget.ID}}/settings/clean-negative">Fix all historic negative category-balances</a>
}, };
ynabImport() { function ynabImport() {
if (this.$data.transactionsFile == undefined || this.$data.assignmentsFile == undefined) if (transactionsFile.value == undefined || assignmentsFile.value == undefined)
return return
let formData = new FormData(); let formData = new FormData();
formData.append("transactions", this.$data.transactionsFile); formData.append("transactions", transactionsFile.value);
formData.append("assignments", this.$data.assignmentsFile); formData.append("assignments", assignmentsFile.value);
const budgetStore = useBudgetsStore(); const budgetStore = useBudgetsStore();
budgetStore.ImportYNAB(formData); budgetStore.ImportYNAB(formData);
} };
}
})
</script> </script>
<template> <template>
@ -126,10 +115,7 @@ export default defineComponent({
</label> </label>
<v-card-actions class="justify-center"> <v-card-actions class="justify-center">
<v-btn <v-btn :disabled="filesIncomplete" @click="ynabImport">Importieren</v-btn>
:disabled="filesIncomplete"
@click="ynabImport"
>Importieren</v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</v-col> </v-col>

View File

@ -1,28 +0,0 @@
import { defineStore } from "pinia";
import { useSessionStore } from "./session";
export const useAPI = defineStore("api", {
actions: {
GET(path : string) {
const sessionStore = useSessionStore();
return fetch("/api/v1" + path, {
headers: sessionStore.AuthHeaders,
})
},
POST(path : string, body : FormData | string | null) {
const sessionStore = useSessionStore();
return fetch("/api/v1" + path, {
method: "POST",
headers: sessionStore.AuthHeaders,
body: body,
})
},
DELETE(path : string) {
const sessionStore = useSessionStore();
return fetch("/api/v1" + path, {
method: "DELETE",
headers: sessionStore.AuthHeaders,
})
},
}
});

View File

@ -1,5 +1,5 @@
import { defineStore } from "pinia" import { defineStore } from "pinia"
import { useAPI } from "./api"; import { GET } from "../api";
import { useSessionStore } from "./session"; import { useSessionStore } from "./session";
interface State { interface State {
@ -81,14 +81,12 @@ export const useAccountStore = defineStore("budget/account", {
await this.FetchAccount(accountid); await this.FetchAccount(accountid);
}, },
async FetchAccount(accountid : string) { async FetchAccount(accountid : string) {
const api = useAPI(); const result = await GET("/account/" + accountid + "/transactions");
const result = await api.GET("/account/" + accountid + "/transactions");
const response = await result.json(); const response = await result.json();
this.Transactions = response.Transactions; this.Transactions = response.Transactions;
}, },
async FetchMonthBudget(budgetid : string, year : number, month : number) { async FetchMonthBudget(budgetid : string, year : number, month : number) {
const api = useAPI(); const result = await GET("/budget/" + budgetid + "/" + year + "/" + month);
const result = await api.GET("/budget/" + budgetid + "/" + year + "/" + month);
const response = await result.json(); const response = await result.json();
this.addCategoriesForMonth(year, month, response.Categories); this.addCategoriesForMonth(year, month, response.Categories);
}, },

View File

@ -1,5 +1,5 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { useAPI } from "./api"; import { GET, POST } from "../api";
import { useAccountStore } from "./budget-account"; import { useAccountStore } from "./budget-account";
import { Budget, useSessionStore } from "./session"; import { Budget, useSessionStore } from "./session";
@ -25,15 +25,13 @@ export const useBudgetsStore = defineStore('budget', {
}, },
actions: { actions: {
ImportYNAB(formData: FormData) { ImportYNAB(formData: FormData) {
const api = useAPI(); return POST(
return api.POST(
"/budget/" + this.CurrentBudgetID + "/import/ynab", "/budget/" + this.CurrentBudgetID + "/import/ynab",
formData, formData,
); );
}, },
async NewBudget(budgetName: string): Promise<void> { async NewBudget(budgetName: string): Promise<void> {
const api = useAPI(); const result = await POST(
const result = await api.POST(
"/budget/new", "/budget/new",
JSON.stringify({ name: budgetName }) JSON.stringify({ name: budgetName })
); );
@ -51,8 +49,7 @@ export const useBudgetsStore = defineStore('budget', {
await this.FetchBudget(budgetid); await this.FetchBudget(budgetid);
}, },
async FetchBudget(budgetid: string) { async FetchBudget(budgetid: string) {
const api = useAPI(); const result = await GET("/budget/" + budgetid);
const result = await api.GET("/budget/" + budgetid);
const response = await result.json(); const response = await result.json();
for (const account of response.Accounts || []) { for (const account of response.Accounts || []) {
useAccountStore().Accounts.set(account.ID, account); useAccountStore().Accounts.set(account.ID, account);

View File

@ -1,6 +1,6 @@
import { StorageSerializers, useStorage } from '@vueuse/core'; import { StorageSerializers, useStorage } from '@vueuse/core';
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { useAPI } from './api'; import { POST } from '../api';
interface State { interface State {
Session: Session | null Session: Session | null
@ -40,14 +40,12 @@ export const useSessionStore = defineStore('session', {
this.Budgets = x.Budgets; this.Budgets = x.Budgets;
}, },
async login(login: any) { async login(login: any) {
const api = useAPI(); const response = await POST("/user/login", JSON.stringify(login));
const response = await api.POST("/user/login", JSON.stringify(login));
const result = await response.json(); const result = await response.json();
return this.loginSuccess(result); return this.loginSuccess(result);
}, },
async register(login : any) { async register(login : any) {
const api = useAPI(); const response = await POST("/user/register", JSON.stringify(login));
const response = await api.POST("/user/register", JSON.stringify(login));
const result = await response.json(); const result = await response.json();
return this.loginSuccess(result); return this.loginSuccess(result);
}, },