feat(#10): Add per-ledger acquisitions view + ledger column

This commit is contained in:
Sirttas
2026-07-05 00:55:13 +02:00
parent 8d73fe3ed1
commit 698156cf00
13 changed files with 156 additions and 104 deletions
@@ -7,6 +7,7 @@ import {computed, ref} from 'vue';
import {AcquiredType} from './AcquiredType';
import AcquisitionQuartilesTooltip from './AcquisitionQuartilesTooltip.vue';
import {formatEveDate, formatIsk, percentFormater} from "@/formaters.ts";
import {Ledger, LedgerLabel, useLedgersStore} from "@/ledger";
type Result = {
id: string;
@@ -20,6 +21,8 @@ type Result = {
precentProfit: number;
iskProfit: number;
date: Date;
ledger?: Ledger;
ledgerName: string;
acquisitions: AcquiredType[];
}
@@ -46,15 +49,22 @@ const props = withDefaults(defineProps<Props>(), {
defineEmits<Emits>();
const columnsToIgnore = computed(() => {
const ic = typeof props.ignoredColums === 'string' ? [props.ignoredColums] : props.ignoredColums;
const ignoredColums = typeof props.ignoredColums === 'string' ? [props.ignoredColums] : [...props.ignoredColums];
if (props.infoOnly && !ic.includes('buttons')) {
return [...ic, 'buttons'];
if (props.infoOnly && !ignoredColums.includes('buttons')) {
ignoredColums.push('buttons');
}
return ic;
if (!props.showAll && !ignoredColums.includes('ledger')) {
ignoredColums.push('ledger');
}
if (ignoredColums.includes('ledger')) {
ignoredColums.push('ledgerName');
}
return ignoredColums;
});
const marketTaxStore = useMarketTaxStore();
const ledgersStore = useLedgersStore();
const threshold = useStorage('market-acquisition-threshold', 10);
const filter = ref("");
@@ -77,6 +87,8 @@ const { sortedArray, headerProps, showColumn } = useSort<Result>(computed(() =>
precentProfit,
iskProfit: r.price * precentProfit * r.remaining,
date: r.date,
ledger: ledgersStore.findById(r.ledgerId),
ledgerName: ledgersStore.findById(r.ledgerId)?.name ?? '',
acquisitions: [r]
};
});
@@ -109,6 +121,7 @@ const { sortedArray, headerProps, showColumn } = useSort<Result>(computed(() =>
precentProfit,
iskProfit: price * precentProfit * totalRemaining,
date: first.date,
ledgerName: '',
acquisitions: group
});
});
@@ -176,6 +189,7 @@ const total = computed(() => {
<SortableHeader v-bind="headerProps" sortKey="name">Item</SortableHeader>
<SortableHeader v-bind="headerProps" sortKey="buy">Buy</SortableHeader>
<SortableHeader v-bind="headerProps" sortKey="sell">Sell</SortableHeader>
<SortableHeader v-bind="headerProps" sortKey="ledgerName">Ledger</SortableHeader>
<SortableHeader v-bind="headerProps" sortKey="date">Bought at</SortableHeader>
<SortableHeader v-bind="headerProps" sortKey="price">Bought Price</SortableHeader>
<SortableHeader v-bind="headerProps" sortKey="remaining">Remaining Amount</SortableHeader>
@@ -194,6 +208,9 @@ const total = computed(() => {
</td>
<td v-if="showColumn('buy')" class="text-right">{{ formatIsk(r.data.buy) }}</td>
<td v-if="showColumn('sell')" class="text-right">{{ formatIsk(r.data.sell) }}</td>
<td v-if="showColumn('ledger')">
<LedgerLabel v-if="r.data.ledger" :ledger="r.data.ledger" link />
</td>
<td v-if="showColumn('date')" class="text-right">{{ formatEveDate(r.data.date) }}</td>
<td v-if="showColumn('price')" class="text-right">{{ formatIsk(r.data.price) }}</td>
<td v-if="showColumn('remaining')" class="text-right">{{ r.data.remaining }}/{{ r.data.quantity }}</td>
@@ -214,9 +231,12 @@ const total = computed(() => {
<td v-if="showColumn('sell')">
<template v-if="!showColumn('name') && !showColumn('buy')">Total</template>
</td>
<td v-if="showColumn('date')">
<td v-if="showColumn('ledger')">
<template v-if="!showColumn('name') && !showColumn('buy') && !showColumn('sell')">Total</template>
</td>
<td v-if="showColumn('date')">
<template v-if="!showColumn('name') && !showColumn('buy') && !showColumn('sell') && !showColumn('ledger')">Total</template>
</td>
<td v-if="showColumn('price')" class="text-right">
<template v-if="total.sameItem">
{{ formatIsk(total.price) }}
@@ -0,0 +1,51 @@
<script setup lang="ts">
import {getMarketTypes, MarketTypePrice, useApraisalStore} from "@/market";
import {ref, watch} from 'vue';
import {AcquiredType} from './AcquiredType';
import {RawAcquiredType} from './acquisition';
import AcquisitionResultTable from './AcquisitionResultTable.vue';
import BuyModal from './BuyModal.vue';
import SellModal from './SellModal.vue';
interface Props {
items: RawAcquiredType[];
ignoredColums?: string[] | string;
}
const props = defineProps<Props>();
const buyModal = ref<typeof BuyModal>();
const sellModal = ref<typeof SellModal>();
const apraisalStore = useApraisalStore();
const enriched = ref<AcquiredType[]>([]);
watch(() => props.items, async itms => {
if (itms.length === 0) {
enriched.value = [];
return;
}
const types = await getMarketTypes([...new Set(itms.map(i => i.type))]);
const prices = await apraisalStore.getPrices(types);
enriched.value = itms.map(i => {
const price = prices.find(p => p.type.id === i.type) as MarketTypePrice;
return {
...i,
type: price.type,
buy: price.buy,
sell: price.sell
};
});
}, {immediate: true});
</script>
<template>
<template v-if="enriched.length > 0">
<AcquisitionResultTable :items="enriched" :ignoredColums="ignoredColums" @buy="(types, price, buy, sell) => buyModal?.open(types[0].type, { 'Price': price, 'Buy': buy, 'Sell': sell })" @sell="types => sellModal?.open(types)" />
<BuyModal ref="buyModal" />
<SellModal ref="sellModal" />
</template>
</template>
+3 -1
View File
@@ -7,6 +7,7 @@ export type AcquiredTypeSource = 'bo' | 'so' | 'prod' | 'misc';
export type RawAcquiredType = {
id: string;
ledgerId: string;
type: number;
quantity: number;
remaining: number;
@@ -15,8 +16,9 @@ export type RawAcquiredType = {
source: ActivitySourceResponse;
}
const toAcquiredType = (a: AcquisitionResponse): RawAcquiredType => ({
export const toAcquiredType = (a: AcquisitionResponse): RawAcquiredType => ({
id: a.acquisitionId,
ledgerId: a.ledgerId,
type: a.marketTypeId,
quantity: a.quantity,
remaining: a.remaining,
+1
View File
@@ -2,6 +2,7 @@ export * from './AcquiredType';
export * from './acquisition';
export { default as AcquisitionResultTable } from './AcquisitionResultTable.vue';
export { default as AcquisitionsPanel } from './AcquisitionsPanel.vue';
export { default as BuyModal } from './BuyModal.vue';
export { default as SellModal } from './SellModal.vue';