113 lines
3.1 KiB
Vue
113 lines
3.1 KiB
Vue
<script setup lang="ts">
|
|
import { ApiError } from '@/api/base';
|
|
import { formatMoney } from '@/api/data';
|
|
import { TransactionApiClient, type TransactionDetail } from '@/api/transaction';
|
|
import AppPage from '@/components/AppPage.vue';
|
|
import PropertiesTable from '@/components/PropertiesTable.vue';
|
|
import { useProfileStore } from '@/stores/profile-store';
|
|
import { showAlert } from '@/util/alert';
|
|
import { onMounted, ref, type Ref } from 'vue';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
const profileStore = useProfileStore()
|
|
|
|
const transaction: Ref<TransactionDetail | undefined> = ref()
|
|
|
|
onMounted(async () => {
|
|
if (!profileStore.state) {
|
|
await router.replace('/')
|
|
return
|
|
}
|
|
|
|
const transactionId = parseInt(route.params.id as string)
|
|
try {
|
|
const api = new TransactionApiClient(profileStore.state)
|
|
transaction.value = await api.getTransaction(transactionId)
|
|
} catch (err) {
|
|
console.error(err)
|
|
await router.replace('/')
|
|
if (err instanceof ApiError) {
|
|
await showAlert('Failed to fetch transaction: ' + err.message)
|
|
}
|
|
}
|
|
})
|
|
</script>
|
|
<template>
|
|
<AppPage :title="'Transaction ' + transaction.id" v-if="transaction">
|
|
<PropertiesTable>
|
|
<tr>
|
|
<th>Timestamp</th>
|
|
<td>{{ new Date(transaction.timestamp).toLocaleString() }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Added at</th>
|
|
<td>{{ new Date(transaction.addedAt).toLocaleString() }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Amount</th>
|
|
<td>{{ formatMoney(transaction.amount, transaction.currency) }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Description</th>
|
|
<td>{{ transaction.description }}</td>
|
|
</tr>
|
|
<tr v-if="transaction.vendor">
|
|
<th>Vendor</th>
|
|
<td>
|
|
{{ transaction.vendor.name }}
|
|
</td>
|
|
</tr>
|
|
<tr v-if="transaction.category">
|
|
<th>Category</th>
|
|
<td>
|
|
{{ transaction.category.name }}
|
|
</td>
|
|
</tr>
|
|
<tr v-if="transaction.creditedAccount">
|
|
<th>Credited Account</th>
|
|
<td>
|
|
{{ transaction.creditedAccount.name }}
|
|
</td>
|
|
</tr>
|
|
<tr v-if="transaction.debitedAccount">
|
|
<th>Debited Account</th>
|
|
<td>
|
|
{{ transaction.debitedAccount.name }}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Tags</th>
|
|
<td>
|
|
<span v-for="tag in transaction.tags" :key="tag">{{ tag }},</span>
|
|
</td>
|
|
</tr>
|
|
</PropertiesTable>
|
|
|
|
<div v-if="transaction.lineItems.length > 0">
|
|
<h3>Line Items</h3>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>#</th>
|
|
<th>Amount per Item</th>
|
|
<th>Quantity</th>
|
|
<th>Description</th>
|
|
<th>Category</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="i in transaction.lineItems" :key="i.idx">
|
|
<td>{{ i.idx + 1 }}</td>
|
|
<td>{{ formatMoney(i.valuePerItem, transaction.currency) }}</td>
|
|
<td>{{ i.quantity }}</td>
|
|
<td>{{ i.description }}</td>
|
|
<td>{{ i.category?.name }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</AppPage>
|
|
</template>
|