Allow to edit accounts

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2024-01-22 21:37:15 +01:00
parent 7886365acc
commit ed3f281092
Signed by: luzifer
SSH key fingerprint: SHA256:/xtE5lCgiRDQr8SLxHMS92ZBlACmATUmF1crK16Ks4E
3 changed files with 211 additions and 5 deletions

View file

@ -0,0 +1,153 @@
<template>
<div
id="editAccountModal"
ref="editAccountModal"
class="modal fade"
tabindex="-1"
aria-labelledby="editAccountModalLabel"
aria-hidden="true"
>
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h1
id="editAccountModalLabel"
class="modal-title fs-5"
>
Edit Account
</h1>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
/>
</div>
<div class="modal-body">
<div class="mb-3">
<label
for="editAccountModalName"
class="form-label"
>Name</label>
<input
id="editAccountModalName"
v-model="form.name"
class="form-control"
type="text"
@keypress.enter="updateAccount"
>
</div>
<div class="mb-3">
<div class="form-check">
<input
id="editAccountModalHidden"
v-model="form.hidden"
class="form-check-input"
type="checkbox"
:disabled="form.balance !== 0"
>
<label
for="editAccountModalHidden"
class="form-check-label"
>Hide account</label>
</div>
<div class="form-text">
Note: You cannot un-hide the account using UI, you need to unhide it via API.
</div>
</div>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-primary"
@click="updateAccount"
>
<i class="fas fa-fw fa-pencil mr-1" />
Update
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import { Modal } from 'bootstrap'
import { responseToJSON } from '../helpers'
export default {
data() {
return {
form: {
balance: 0,
hidden: false,
name: '',
},
}
},
emits: ['editClosed', 'editComplete'],
methods: {
updateAccount() {
if (!this.account) {
return
}
const update = new URLSearchParams()
if (this.form.name !== this.account.name) {
update.set('name', this.form.name)
}
if (this.form.hidden !== this.account.hidden) {
update.set('hidden', String(this.form.hidden))
}
if (update.toString().length === 0) {
// No updates, why are we here?
return
}
return fetch(`/api/accounts/${this.account.id}?${update.toString()}`, {
method: 'PATCH',
})
.then(responseToJSON)
.then(() => this.$emit('editComplete'))
},
},
mounted() {
this.$refs.editAccountModal
.addEventListener('hidden.bs.modal', () => this.$emit('editClosed'))
},
name: 'AccountingAppAccountEditor',
props: {
account: {
default: () => ({}),
required: false,
type: Object,
},
},
watch: {
account(to) {
if (!to) {
Modal.getOrCreateInstance(this.$refs.editAccountModal).hide()
return
}
this.form = {
balance: to.balance,
hidden: to.hidden,
name: to.name,
}
Modal.getOrCreateInstance(this.$refs.editAccountModal).show()
},
},
}
</script>

View file

@ -2,8 +2,17 @@
<div>
<div class="container-fluid">
<div class="row">
<div class="col d-flex fs-3 align-items-center text-semibold">
{{ accountIdToName[accountId] }}
<div
class="col d-flex fs-3 align-items-center text-semibold"
>
<a
class="text-white text-decoration-none"
href="#"
title="Click to Edit"
@click.prevent="editedAccId = accountId"
>
{{ accountIdToName[accountId] }}
</a>
</div>
<div class="col d-flex align-items-center justify-content-end">
<range-selector
@ -306,6 +315,12 @@
</div>
</div>
</div>
<account-editor
:account="editedAcc"
@editClosed="editedAccId = null"
@editComplete="$emit('update-accounts'); editedAccId = null"
/>
</div>
</template>
@ -313,12 +328,13 @@
/* eslint-disable sort-imports */
import { Modal } from 'bootstrap'
import accountEditor from './accountEditor.vue'
import { formatNumber } from '../helpers'
import rangeSelector from './rangeSelector.vue'
import txEditor from './txEditor.vue'
export default {
components: { rangeSelector, txEditor },
components: { accountEditor, rangeSelector, txEditor },
computed: {
account() {
@ -345,6 +361,13 @@ export default {
return cats
},
editedAcc() {
if (!this.editedAccId) {
return null
}
return this.accounts.filter(acc => acc.id === this.editedAccId)[0] || null
},
selectedTx() {
return Object.entries(this.selectedTxRaw)
.filter(e => e[1])
@ -392,6 +415,7 @@ export default {
data() {
return {
editedAccId: null,
editedTxId: null,
modals: {
@ -410,6 +434,8 @@ export default {
}
},
emits: ['update-accounts'],
methods: {
deleteSelected() {
const actions = []

View file

@ -49,7 +49,16 @@
v-for="cat in categories"
:key="cat.id"
>
<td>{{ cat.name }}</td>
<td>
<a
class="text-white text-decoration-none"
href="#"
title="Click to Edit"
@click.prevent="editedAccId = cat.id"
>
{{ cat.name }}
</a>
</td>
<td :class="{'text-end': true, 'text-danger': (allocatedByCategory[cat.id] || 0) < 0}">
{{ formatNumber(allocatedByCategory[cat.id] || 0) }}
</td>
@ -170,6 +179,12 @@
</div>
</div>
</div>
<account-editor
:account="editedAcc"
@editClosed="editedAccId = null"
@editComplete="$emit('update-accounts'); editedAccId = null"
/>
</div>
</template>
@ -177,12 +192,13 @@
/* eslint-disable sort-imports */
import { Modal } from 'bootstrap'
import accountEditor from './accountEditor.vue'
import { formatNumber } from '../helpers'
import rangeSelector from './rangeSelector.vue'
import { unallocatedMoneyAcc } from '../constants'
export default {
components: { rangeSelector },
components: { accountEditor, rangeSelector },
computed: {
activityByCategory() {
@ -211,6 +227,13 @@ export default {
return accounts
},
editedAcc() {
if (!this.editedAccId) {
return null
}
return this.accounts.filter(acc => acc.id === this.editedAccId)[0] || null
},
transferModalValid() {
if (!this.modals.createTransfer.from || !this.modals.createTransfer.to) {
return false
@ -254,6 +277,8 @@ export default {
data() {
return {
editedAccId: null,
modals: {
createTransfer: {
amount: 0,
@ -267,6 +292,8 @@ export default {
}
},
emits: ['update-accounts'],
methods: {
fetchTransactions() {
const since = this.timeRange.start.toISOString()