transaction list display
This commit is contained in:
@@ -6,7 +6,7 @@ import {ref} from 'vue';
|
||||
|
||||
interface Props {
|
||||
inline?: boolean;
|
||||
autoClose: boolean;
|
||||
autoClose?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
import {isCombined, Ledger} from "@/ledger/ledger.ts";
|
||||
import {FolderOpenIcon} from '@heroicons/vue/24/outline';
|
||||
import {RouterLink} from "vue-router";
|
||||
import {routeNames} from "@/routes.ts";
|
||||
|
||||
interface Props {
|
||||
ledger: Ledger;
|
||||
link?: boolean;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
@@ -14,6 +17,7 @@ const props = defineProps<Props>();
|
||||
<div class="flex">
|
||||
<FolderOpenIcon v-if="isCombined(ledger)" class="w-4 me-1" />
|
||||
<div v-else class="w-4 me-1"/>
|
||||
<span>{{ ledger.name }}</span>
|
||||
<RouterLink v-if="link" :to="{name: routeNames.listLedgerTransactions, params: {ledgerId: ledger.ledgerId}}">{{ ledger.name }}</RouterLink>
|
||||
<span v-else>{{ ledger.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -6,12 +6,14 @@ import {
|
||||
LedgerResponseTypeEnum,
|
||||
MainLedgerResponse,
|
||||
MainLedgerResponseTypeEnum,
|
||||
TransactionResponse,
|
||||
TransferResponseTypeEnum,
|
||||
UpdateCombinedLedgerRequest,
|
||||
UpdateMainLedgerRequest
|
||||
} from "@/generated/mammon";
|
||||
import {defineStore} from "pinia";
|
||||
import {ref, triggerRef} from "vue";
|
||||
import {ledgerApi} from "@/mammon";
|
||||
import {ledgerApi, transactionApi} from "@/mammon";
|
||||
|
||||
export const LedgerTypes = LedgerResponseTypeEnum;
|
||||
|
||||
@@ -20,6 +22,7 @@ export type MainLedger = MainLedgerResponse & {type: MainLedgerResponseTypeEnum}
|
||||
export type CombinedLedger = CombinedLedgerResponse & {type: CombinedLedgerResponseTypeEnum}
|
||||
export type Ledger = MainLedger | CombinedLedger;
|
||||
|
||||
export const TransferTypes = TransferResponseTypeEnum;
|
||||
|
||||
export const systemLedgerRef = 'system';
|
||||
export const systemLedger = {
|
||||
@@ -71,3 +74,5 @@ export const useLedgersStore = defineStore('ledgers', () => {
|
||||
return {ledgers, findById, findAllById, createMain, createCombined, updateMain, updateCombined, refresh};
|
||||
})
|
||||
|
||||
export const findAllTransactionInLeger = (ledger: Ledger | string): Promise<TransactionResponse[]> => transactionApi.finAllTransactionsInLedger(typeof ledger == 'string' ? ledger : ledger.ledgerId).then(response => response.data)
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
CharacterRuleBookApi,
|
||||
LedgerApi,
|
||||
ProcessingApi,
|
||||
RuleBookApi
|
||||
RuleBookApi,
|
||||
TransactionApi
|
||||
} from "@/generated/mammon";
|
||||
|
||||
export const mammonUrl = import.meta.env.VITE_MAMMON_URL;
|
||||
@@ -22,6 +23,7 @@ const mammonAxiosInstance = axios.create({
|
||||
logResource(mammonAxiosInstance)
|
||||
|
||||
export const ledgerApi = new LedgerApi(undefined, mammonUrl, mammonAxiosInstance);
|
||||
export const transactionApi = new TransactionApi(undefined, mammonUrl, mammonAxiosInstance);
|
||||
export const characterApi = new CharacterApi(undefined, mammonUrl, mammonAxiosInstance);
|
||||
export const ruleBookApi = new RuleBookApi(undefined, mammonUrl, mammonAxiosInstance);
|
||||
export const characterRuleBookApi = new CharacterRuleBookApi(undefined, mammonUrl, mammonAxiosInstance);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import {formatIsk} from "@/formaters";
|
||||
|
||||
interface Props {
|
||||
amount: number;
|
||||
}
|
||||
|
||||
const { amount } = defineProps<Props>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span :class="amount >= 0 ? 'text-emerald-400' : 'text-amber-700'">{{ formatIsk(amount) }}</span>
|
||||
</template>
|
||||
@@ -6,3 +6,5 @@ export * from './type';
|
||||
export * from './appraisal';
|
||||
export * from './market';
|
||||
|
||||
export { default as IskLabel } from './IskLabel.vue';
|
||||
|
||||
|
||||
@@ -1,27 +1,40 @@
|
||||
import {esiAxiosInstance} from '@/service';
|
||||
|
||||
export type MarketType = {
|
||||
id: number;
|
||||
type_id: number;
|
||||
group_id: number;
|
||||
marketgroup_id: number;
|
||||
market_group_id: number;
|
||||
name: string;
|
||||
published: boolean;
|
||||
description: string;
|
||||
basePrice: number;
|
||||
base_price: number;
|
||||
icon_id: number;
|
||||
volume: number;
|
||||
portionSize: number;
|
||||
portion_size: number;
|
||||
}
|
||||
|
||||
const cache = new Map<number, MarketType>(); // TODO move to pinia store
|
||||
|
||||
const fetchType = (id: number): Promise<MarketType> => {
|
||||
if (cache.has(id)) {
|
||||
return Promise.resolve(cache.get(id)!);
|
||||
}
|
||||
return esiAxiosInstance.get<MarketType>(`/universe/types/${id}/`).then(r => {
|
||||
cache.set(id, r.data);
|
||||
return r.data;
|
||||
});
|
||||
};
|
||||
|
||||
export const getMarketType = async (type: string | number): Promise<MarketType> => (await getMarketTypes([type]))[0];
|
||||
export const getMarketTypes = async (types: (string | number)[]): Promise<MarketType[]> => {
|
||||
if (types.length === 0) {
|
||||
return [];
|
||||
} else if (types.length === 1 && typeof types[0] === "number") {
|
||||
return [];
|
||||
}
|
||||
return []
|
||||
const ids = types.filter((t): t is number => typeof t === 'number');
|
||||
return Promise.all(ids.map(fetchType));
|
||||
}
|
||||
|
||||
const blueprintMarketGrous = [ // TODO add all groups
|
||||
const blueprintMarketGroups = [ // TODO add all groups
|
||||
2,
|
||||
2157,
|
||||
2159,
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {ref, watch} from "vue";
|
||||
import {useRoute} from "vue-router";
|
||||
import log from "loglevel";
|
||||
import {findAllTransactionInLeger, Ledger, TransferTypes, useLedgersStore} from "@/ledger";
|
||||
import {computedAsync} from "@vueuse/core";
|
||||
import {TransactionResponse} from "@/generated/mammon";
|
||||
import {formatEveDate} from "@/formaters.ts";
|
||||
import {IskLabel} from "@/market";
|
||||
|
||||
const {findById, refresh} = useLedgersStore();
|
||||
|
||||
const ledger = ref<Ledger>();
|
||||
|
||||
const transactions = computedAsync<TransactionResponse[]>(async () => {
|
||||
if (ledger.value) {
|
||||
return await findAllTransactionInLeger(ledger.value.ledgerId);
|
||||
}
|
||||
return [];
|
||||
}, []);
|
||||
|
||||
const getIskBalance = (transaction: TransactionResponse) => {
|
||||
const ledgerId = ledger.value?.ledgerId;
|
||||
|
||||
if (!ledgerId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let balance = 0;
|
||||
|
||||
for (const transfer of transaction.transfers) {
|
||||
if (transfer.type === TransferTypes.Isk) {
|
||||
if (transfer.toLedgerId === ledgerId) {
|
||||
balance += transfer.amount;
|
||||
} else if (transfer.fromLedgerId === ledgerId) {
|
||||
balance -= transfer.amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
return balance;
|
||||
}
|
||||
|
||||
watch(useRoute(), async route => {
|
||||
if (route.params.ledgerId) {
|
||||
const id = typeof route.params.ledgerId === 'string' ? route.params.ledgerId : route.params.ledgerId[0];
|
||||
|
||||
await refresh() // FIXME
|
||||
|
||||
ledger.value = findById(id)
|
||||
log.info('Loaded ledger:', ledger.value);
|
||||
} else {
|
||||
ledger.value = undefined;
|
||||
log.info('No ledger to load');
|
||||
}
|
||||
}, { immediate: true })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mt-4">
|
||||
<div class="flex items-end gap-2 mt-2" v-for="transaction in transactions" :key="transaction.transactionId">
|
||||
<span>{{formatEveDate(new Date(transaction.datetime))}}</span>
|
||||
<IskLabel :amount="getIskBalance(transaction)" />
|
||||
<span>{{transaction.description}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -4,7 +4,7 @@ import {EditLedgerModal, LedgerLabel, useLedgersStore} from "@/ledger";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {nextTick, ref} from "vue";
|
||||
import {PencilSquareIcon} from "@heroicons/vue/24/outline";
|
||||
import {formatIsk} from "@/formaters.ts";
|
||||
import {IskLabel} from "@/market";
|
||||
|
||||
const {ledgers} = storeToRefs(useLedgersStore());
|
||||
|
||||
@@ -22,9 +22,9 @@ const openEdit = async (ledgerId: string) => {
|
||||
<template>
|
||||
<div class="mt-4">
|
||||
<div v-for="ledger in ledgers" :key="ledger.ledgerId" class="flex items-center mb-2">
|
||||
<LedgerLabel :ledger="ledger" />
|
||||
<LedgerLabel :ledger="ledger" :link="true" />
|
||||
<div class="flex grow">
|
||||
<span class="ms-2">{{ formatIsk(ledger.balance) }}</span>
|
||||
<IskLabel class="ms-2" :amount="ledger.balance" />
|
||||
</div>
|
||||
<button class="btn-icon ms-2" @click="openEdit(ledger.ledgerId)"><PencilSquareIcon /></button>
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@ const {characters} = storeToRefs(useCharactersStore());
|
||||
<div class="grid mb-2 mt-4">
|
||||
<div v-for="character in characters" :key="character.characterId" class="flex items-center mb-2">
|
||||
<CharacterLabel class="flex grow" :character="character" />
|
||||
<RouterLink class="btn-icon ms-2" :to="{ name: routeNames.characterRulebook, params: { characterId: character.characterId } }"><PencilSquareIcon /></RouterLink>
|
||||
<RouterLink class="btn-icon ms-2" :to="{ name: routeNames.editCharacterRulebook, params: { characterId: character.characterId } }"><PencilSquareIcon /></RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
+4
-2
@@ -3,10 +3,11 @@ import {RouteRecordRaw} from 'vue-router';
|
||||
export const routeNames = {
|
||||
home: 'home',
|
||||
callback: 'callback',
|
||||
listLedgerTransactions: 'list-ledger-tTransactions',
|
||||
listRuleBooks: 'list-rule-books',
|
||||
newRuleBook: 'new-rule-book',
|
||||
editRuleBook: 'edit-rule-book',
|
||||
characterRulebook: 'character-rulebook',
|
||||
editCharacterRulebook: 'edit-character-rule-book',
|
||||
marketTypes: 'market-types',
|
||||
about: 'about',
|
||||
} as const;
|
||||
@@ -17,6 +18,7 @@ export const routes: RouteRecordRaw[] = [
|
||||
|
||||
{path: '/ledgers', component: () => import('@/pages/Ledgers.vue'), children: [
|
||||
{path: '', component: () => import('@/pages/ledger/ListLedgers.vue')},
|
||||
{path: ':ledgerId/transactions', name: routeNames.listLedgerTransactions, component: () => import('@/pages/ledger/ListLedgerTransactions.vue')},
|
||||
]},
|
||||
|
||||
{path: '/rules', component: () => import('@/pages/Rules.vue'), children: [
|
||||
@@ -28,7 +30,7 @@ export const routes: RouteRecordRaw[] = [
|
||||
]},
|
||||
{path: '/characters/rules', children: [
|
||||
{path: '', component: () => import('@/pages/rules/ListCharacterRuleBooks.vue')},
|
||||
{path: '/characters/:characterId/rules', name: routeNames.characterRulebook, component: () => import('@/pages/rules/EditCharacterRuleBook.vue')},
|
||||
{path: '/characters/:characterId/rules', name: routeNames.editCharacterRulebook, component: () => import('@/pages/rules/EditCharacterRuleBook.vue')},
|
||||
]}
|
||||
]},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user