pinia+track
This commit is contained in:
53
package-lock.json
generated
53
package-lock.json
generated
@@ -13,6 +13,7 @@
|
|||||||
"@vueuse/core": "^10.2.1",
|
"@vueuse/core": "^10.2.1",
|
||||||
"@vueuse/integrations": "^10.2.1",
|
"@vueuse/integrations": "^10.2.1",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
|
"pinia": "^2.1.6",
|
||||||
"pocketbase": "^0.18.0",
|
"pocketbase": "^0.18.0",
|
||||||
"vue": "^3.3.4",
|
"vue": "^3.3.4",
|
||||||
"vue-router": "^4.2.4"
|
"vue-router": "^4.2.4"
|
||||||
@@ -1719,6 +1720,56 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pinia": {
|
||||||
|
"version": "2.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.6.tgz",
|
||||||
|
"integrity": "sha512-bIU6QuE5qZviMmct5XwCesXelb5VavdOWKWaB17ggk++NUwQWWbP5YnsONTk3b752QkW9sACiR81rorpeOMSvQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/devtools-api": "^6.5.0",
|
||||||
|
"vue-demi": ">=0.14.5"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/posva"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.4.0",
|
||||||
|
"typescript": ">=4.4.4",
|
||||||
|
"vue": "^2.6.14 || ^3.3.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pinia/node_modules/vue-demi": {
|
||||||
|
"version": "0.14.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
|
||||||
|
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"bin": {
|
||||||
|
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||||
|
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.0.0-rc.1",
|
||||||
|
"vue": "^3.0.0-0 || ^2.6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pirates": {
|
"node_modules/pirates": {
|
||||||
"version": "4.0.6",
|
"version": "4.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
|
||||||
@@ -2111,7 +2162,7 @@
|
|||||||
"version": "5.2.2",
|
"version": "5.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"@vueuse/core": "^10.2.1",
|
"@vueuse/core": "^10.2.1",
|
||||||
"@vueuse/integrations": "^10.2.1",
|
"@vueuse/integrations": "^10.2.1",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
|
"pinia": "^2.1.6",
|
||||||
"pocketbase": "^0.18.0",
|
"pocketbase": "^0.18.0",
|
||||||
"vue": "^3.3.4",
|
"vue": "^3.3.4",
|
||||||
"vue-router": "^4.2.4"
|
"vue-router": "^4.2.4"
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ useEventListener('keyup', e => {
|
|||||||
<div class="fixed inset-0" @click="isOpen = false">
|
<div class="fixed inset-0" @click="isOpen = false">
|
||||||
<div class="absolute bg-black opacity-80 inset-0 z-0" />
|
<div class="absolute bg-black opacity-80 inset-0 z-0" />
|
||||||
<div class="absolute grid inset-0">
|
<div class="absolute grid inset-0">
|
||||||
<div class="justify-self-center" @click.stop>
|
<div class="justify-self-center m-auto" @click.stop>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { providePocketBase } from '@/pocketbase';
|
import { providePocketBase } from '@/pocketbase';
|
||||||
|
import { createPinia } from 'pinia';
|
||||||
import { createApp } from 'vue';
|
import { createApp } from 'vue';
|
||||||
import { createRouter, createWebHistory } from 'vue-router';
|
import { createRouter, createWebHistory } from 'vue-router';
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
@@ -7,6 +8,7 @@ import './style.css';
|
|||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
const pb = providePocketBase(app);
|
const pb = providePocketBase(app);
|
||||||
|
const pinia = createPinia();
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
routes,
|
routes,
|
||||||
@@ -20,6 +22,7 @@ router.beforeEach(async to => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.use(pinia);
|
||||||
app.use(router);
|
app.use(router);
|
||||||
|
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
export * from './HistoryQuartils';
|
export * from './HistoryQuartils';
|
||||||
export * from './scan';
|
export * from './scan';
|
||||||
|
|
||||||
export { default as BuyModal } from './BuyModal.vue';
|
|
||||||
export { default as ScanResultTable } from './ScanResultTable.vue';
|
export { default as ScanResultTable } from './ScanResultTable.vue';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { MarketOrderHistory, MarketType } from "@/market";
|
import { MarketOrderHistory, MarketType } from "@/market";
|
||||||
|
import { usePocketBase, watchCollection } from "@/pocketbase";
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { RecordModel } from "pocketbase";
|
||||||
|
import { computed, onMounted, ref } from "vue";
|
||||||
|
|
||||||
export type ScanResult = {
|
export type ScanResult = {
|
||||||
type: MarketType;
|
type: MarketType;
|
||||||
@@ -7,3 +11,33 @@ export type ScanResult = {
|
|||||||
sell: number
|
sell: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MarketScan extends RecordModel {
|
||||||
|
owner: string;
|
||||||
|
types: number[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const marketScans = 'marketScans';
|
||||||
|
|
||||||
|
export const useMarkeyScanStore = defineStore(marketScans, () => {
|
||||||
|
const pb = usePocketBase();
|
||||||
|
const marketScan = ref<MarketScan>();
|
||||||
|
|
||||||
|
const types = computed(() => marketScan.value?.types ?? []);
|
||||||
|
const setTypes = async (types: number[]) => {
|
||||||
|
if (marketScan.value?.id) {
|
||||||
|
pb.collection(marketScans).update(marketScan.value.id, { owner: pb.authStore.model!.id, types });
|
||||||
|
} else {
|
||||||
|
pb.collection(marketScans).create({ owner: pb.authStore.model!.id, types });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watchCollection<MarketScan>(marketScans, '*', data => {
|
||||||
|
if (data.action === 'delete') {
|
||||||
|
marketScan.value = undefined;
|
||||||
|
} else if (!marketScan.value || data.record.id === marketScan.value.id) {
|
||||||
|
marketScan.value = data.record;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onMounted(async () => marketScan.value = await pb.collection(marketScans).getFirstListItem<MarketScan>('').catch(() => undefined));
|
||||||
|
return { types, setTypes };
|
||||||
|
});
|
||||||
@@ -2,16 +2,11 @@
|
|||||||
import Modal from '@/Modal.vue';
|
import Modal from '@/Modal.vue';
|
||||||
import { formatIsk } from '@/formaters';
|
import { formatIsk } from '@/formaters';
|
||||||
import { MarketType } from '@/market';
|
import { MarketType } from '@/market';
|
||||||
import { useTrackedItemsStorage } from '@/market/track';
|
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { useTrackedItemStore } from './track';
|
||||||
|
|
||||||
interface Emit {
|
|
||||||
(e: 'added'): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emit = defineEmits<Emit>();
|
const trackedItemStore = useTrackedItemStore();
|
||||||
|
|
||||||
const itemsStorage = useTrackedItemsStorage();
|
|
||||||
|
|
||||||
const modalOpen = ref<boolean>(false);
|
const modalOpen = ref<boolean>(false);
|
||||||
const type = ref<MarketType>();
|
const type = ref<MarketType>();
|
||||||
@@ -43,24 +38,7 @@ const add = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldItem = itemsStorage.value.find(i => i.typeID === id);
|
trackedItemStore.addTrackedItem(id, count.value, price.value);
|
||||||
|
|
||||||
if (oldItem) {
|
|
||||||
const item = {
|
|
||||||
typeID: id,
|
|
||||||
count: count.value + oldItem.count,
|
|
||||||
averagePrice: ((price.value * count.value) + (oldItem.averagePrice * oldItem.count)) / (count.value + oldItem.count)
|
|
||||||
};
|
|
||||||
itemsStorage.value = itemsStorage.value.map(i => i.typeID === id ? item : i);
|
|
||||||
} else {
|
|
||||||
const item = {
|
|
||||||
typeID: id,
|
|
||||||
count: count.value,
|
|
||||||
averagePrice: price.value
|
|
||||||
};
|
|
||||||
itemsStorage.value = [ ...itemsStorage.value, item ];
|
|
||||||
}
|
|
||||||
emit('added');
|
|
||||||
modalOpen.value = false;
|
modalOpen.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +47,7 @@ defineExpose({ open });
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Modal v-model:open="modalOpen">
|
<Modal v-model:open="modalOpen">
|
||||||
<div class="p-4 bg-slate-800 rounded mt-20 flex">
|
<div class="p-4 bg-slate-800 rounded flex">
|
||||||
<div class="flex me-2">
|
<div class="flex me-2">
|
||||||
<span>Price: </span>
|
<span>Price: </span>
|
||||||
<div class="ms-2">
|
<div class="ms-2">
|
||||||
@@ -1,16 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Modal from '@/Modal.vue';
|
import Modal from '@/Modal.vue';
|
||||||
import { MarketType } from '@/market';
|
import { MarketType } from '@/market';
|
||||||
import { useTrackedItemsStorage } from '@/market/track';
|
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { useTrackedItemStore } from './track';
|
||||||
|
|
||||||
interface Emit {
|
|
||||||
(e: 'removed'): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emit = defineEmits<Emit>();
|
const trackedItemStore = useTrackedItemStore();
|
||||||
|
|
||||||
const itemsStorage = useTrackedItemsStorage();
|
|
||||||
|
|
||||||
const modalOpen = ref<boolean>(false);
|
const modalOpen = ref<boolean>(false);
|
||||||
const type = ref<MarketType>();
|
const type = ref<MarketType>();
|
||||||
@@ -29,26 +24,7 @@ const remove = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldItem = itemsStorage.value.find(i => i.typeID === id);
|
trackedItemStore.removeTrackedItem(id, count.value);
|
||||||
|
|
||||||
if (!oldItem) {
|
|
||||||
modalOpen.value = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const c = oldItem.count - count.value;
|
|
||||||
|
|
||||||
if (c > 0) {
|
|
||||||
const item = {
|
|
||||||
typeID: id,
|
|
||||||
count: oldItem.count - count.value,
|
|
||||||
averagePrice: oldItem.averagePrice
|
|
||||||
};
|
|
||||||
itemsStorage.value = itemsStorage.value.map(i => i.typeID === id ? item : i);
|
|
||||||
} else {
|
|
||||||
itemsStorage.value = itemsStorage.value.filter(i => i.typeID !== id);
|
|
||||||
}
|
|
||||||
emit('removed');
|
|
||||||
modalOpen.value = false;
|
modalOpen.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +33,7 @@ defineExpose({ open });
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Modal v-model:open="modalOpen">
|
<Modal v-model:open="modalOpen">
|
||||||
<div class="p-4 bg-slate-800 rounded mt-20 flex">
|
<div class="p-4 bg-slate-800 rounded flex">
|
||||||
<div class="flex me-2 mb-auto">
|
<div class="flex me-2 mb-auto">
|
||||||
<span>Count: </span>
|
<span>Count: </span>
|
||||||
<input class="ms-2" type="number" min="0" step="1" v-model="count" />
|
<input class="ms-2" type="number" min="0" step="1" v-model="count" />
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export * from './TrackedItem';
|
export * from './TrackedItem';
|
||||||
export * from './storage';
|
export * from './track';
|
||||||
|
|
||||||
|
export { default as BuyModal } from './BuyModal.vue';
|
||||||
export { default as SellModal } from './SellModal.vue';
|
export { default as SellModal } from './SellModal.vue';
|
||||||
export { default as TrackResultTable } from './TrackResultTable.vue';
|
export { default as TrackResultTable } from './TrackResultTable.vue';
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
import { createSharedComposable, useLocalStorage } from '@vueuse/core';
|
|
||||||
|
|
||||||
export type TrackedMarketItemStorage = {
|
|
||||||
typeID: number;
|
|
||||||
count: number;
|
|
||||||
averagePrice: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useTrackedItemsStorage = createSharedComposable(() => useLocalStorage<TrackedMarketItemStorage[]>('market-track-items', []));
|
|
||||||
58
src/market/track/track.ts
Normal file
58
src/market/track/track.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { useCollection, usePocketBase } from "@/pocketbase";
|
||||||
|
import { createSharedComposable, useLocalStorage } from '@vueuse/core';
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { RecordModel } from "pocketbase";
|
||||||
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
export type TrackedMarketItemStorage = {
|
||||||
|
typeID: number;
|
||||||
|
count: number;
|
||||||
|
averagePrice: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TrackedMarketItem extends RecordModel {
|
||||||
|
owner: string;
|
||||||
|
typeID: number;
|
||||||
|
count: number;
|
||||||
|
averagePrice: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const marketTrackings = 'marketTrackings';
|
||||||
|
|
||||||
|
export const useTrackedItemsStorage = createSharedComposable(() => useLocalStorage<TrackedMarketItemStorage[]>('market-track-items', []));
|
||||||
|
|
||||||
|
export const useTrackedItemStore = defineStore(marketTrackings, () => {
|
||||||
|
const pb = usePocketBase();
|
||||||
|
const trackedItems = useCollection<TrackedMarketItem>(marketTrackings);
|
||||||
|
|
||||||
|
const items = computed(() => trackedItems);
|
||||||
|
const addTrackedItem = async (typeID: number, count: number, averagePrice: number) => {
|
||||||
|
const oldItem = trackedItems.value.find(i => i.typeID === typeID);
|
||||||
|
|
||||||
|
if (oldItem?.id) {
|
||||||
|
pb.collection(marketTrackings).update(oldItem.id, {
|
||||||
|
...oldItem,
|
||||||
|
count: count + oldItem.count,
|
||||||
|
averagePrice: ((averagePrice * count) + (oldItem.averagePrice * oldItem.count)) / (count + oldItem.count)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
pb.collection(marketTrackings).create({ owner: pb.authStore.model!.id, typeID, count, averagePrice});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const removeTrackedItem = async (typeID: number, count: number) => {
|
||||||
|
const oldItem = trackedItems.value.find(i => i.typeID === typeID);
|
||||||
|
|
||||||
|
if (!oldItem?.id) {
|
||||||
|
return;
|
||||||
|
} else if (oldItem.count > count) {
|
||||||
|
pb.collection(marketTrackings).update(oldItem.id, {
|
||||||
|
...oldItem,
|
||||||
|
count: oldItem.count - count
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
pb.collection(marketTrackings).delete(oldItem.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return { items, addTrackedItem, removeTrackedItem };
|
||||||
|
});
|
||||||
@@ -19,12 +19,12 @@ const login = async () => {
|
|||||||
<div class="p-4 mx-auto mt-10 grid justify-center gap-2 w-64">
|
<div class="p-4 mx-auto mt-10 grid justify-center gap-2 w-64">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
Login:
|
Login:
|
||||||
<input type="text" autocomplete="username" v-model="username" />
|
<input type="text" name="username" v-model="username" />
|
||||||
</div>
|
</div>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
Password:
|
Password:
|
||||||
<input type="password" autocomplete="password" v-model="password" />
|
<input type="password" name="password" v-model="password" />
|
||||||
</div>
|
</div>
|
||||||
<button class="justify-self-end" @click="login" >Login</button>
|
<button class="justify-self-end" name="login" @click="login">Login</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,21 +1,15 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { MarketType, MarketTypePrice, getHistory, getMarketType, getMarketTypes, getPrice, getPrices, jitaId } from "@/market";
|
import { MarketType, MarketTypePrice, getHistory, getMarketType, getMarketTypes, getPrice, getPrices, jitaId } from "@/market";
|
||||||
import { BuyModal, ScanResult, ScanResultTable } from '@/market/scan';
|
import { ScanResult, ScanResultTable, useMarkeyScanStore } from '@/market/scan';
|
||||||
import { usePocketBase } from "@/pocketbase";
|
import { BuyModal } from '@/market/track';
|
||||||
import { onMounted, ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
const pb = usePocketBase();
|
|
||||||
|
|
||||||
type MarketScan = {
|
|
||||||
id?: string;
|
|
||||||
owner: string;
|
|
||||||
types: number[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const buyModal = ref<typeof BuyModal>();
|
const buyModal = ref<typeof BuyModal>();
|
||||||
|
|
||||||
const item = ref("");
|
const item = ref("");
|
||||||
|
|
||||||
|
const markeyScanStore = useMarkeyScanStore();
|
||||||
const items = ref<ScanResult[]>([]);
|
const items = ref<ScanResult[]>([]);
|
||||||
const addOrRelaod = async (type: MarketType) => {
|
const addOrRelaod = async (type: MarketType) => {
|
||||||
const typeID = type.id;
|
const typeID = type.id;
|
||||||
@@ -43,35 +37,24 @@ const addItem = async () => {
|
|||||||
addOrRelaod(type);
|
addOrRelaod(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getMarketScan = () => pb.collection('marketScans').getFirstListItem<MarketScan>("").catch(() => null);
|
|
||||||
|
|
||||||
watch(items, async itms => {
|
watch(items, async itms => markeyScanStore.setTypes(itms.map(i => i.type.id)));
|
||||||
const types = itms.map(i => i.type.id);
|
watch(() => markeyScanStore.types, async t => {
|
||||||
const marketScan = await getMarketScan();
|
const typesToLoad = t.filter(t => !items.value.some(i => i.type.id === t));
|
||||||
|
|
||||||
if (marketScan?.id) {
|
if (typesToLoad.length === 0) {
|
||||||
pb.collection('marketScans').update(marketScan.id, { owner: pb.authStore.model!.id, types });
|
|
||||||
} else {
|
|
||||||
pb.collection('marketScans').create({ owner: pb.authStore.model!.id, types });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
onMounted(async () => {
|
|
||||||
const marketScan = await getMarketScan();
|
|
||||||
|
|
||||||
if (!marketScan || marketScan.types.length === 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const prices = await getPrices(await getMarketTypes(marketScan.types));
|
const prices = await getPrices(await getMarketTypes(typesToLoad));
|
||||||
|
|
||||||
items.value = await Promise.all(marketScan.types.map(async i => {
|
items.value = [...items.value, ...(await Promise.all(typesToLoad.map(async i => {
|
||||||
const price = prices.find(p => p.type.id === i) as MarketTypePrice;
|
const price = prices.find(p => p.type.id === i) as MarketTypePrice;
|
||||||
const history = await getHistory(jitaId, i);
|
const history = await getHistory(jitaId, i);
|
||||||
|
|
||||||
return { id: i, history, ...price };
|
return { id: i, history, ...price };
|
||||||
}));
|
})))];
|
||||||
});
|
}, { immediate: true });
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -1,31 +1,27 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { MarketTypePrice, getMarketTypes, getPrices } from "@/market";
|
import { MarketTypePrice, getMarketTypes, getPrices } from "@/market";
|
||||||
import { BuyModal } from '@/market/scan';
|
import { BuyModal, SellModal, TrackResultTable, TrackedItem, useTrackedItemStore } from '@/market/track';
|
||||||
import { SellModal, TrackResultTable, TrackedItem, useTrackedItemsStorage } from '@/market/track';
|
import { ref, watch } from 'vue';
|
||||||
import { onMounted, ref, watch } from 'vue';
|
|
||||||
|
|
||||||
const buyModal = ref<typeof BuyModal>();
|
const buyModal = ref<typeof BuyModal>();
|
||||||
const sellModal = ref<typeof SellModal>();
|
const sellModal = ref<typeof SellModal>();
|
||||||
|
|
||||||
const itemsStorage = useTrackedItemsStorage();
|
const trackedItemStore = useTrackedItemStore();
|
||||||
const items = ref<TrackedItem[]>([]);
|
const items = ref<TrackedItem[]>([]);
|
||||||
|
|
||||||
const relaod = async () => {
|
watch(() => trackedItemStore.items.value, async itms => {
|
||||||
if (itemsStorage.value.length === 0) {
|
if (itms.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const prices = await getPrices(await getMarketTypes(itemsStorage.value.map(i => i.typeID)));
|
const prices = await getPrices(await getMarketTypes(itms.map(i => i.typeID)));
|
||||||
|
|
||||||
items.value = itemsStorage.value.map(i => {
|
items.value = itms.map(i => {
|
||||||
const price = prices.find(p => p.type.id === i.typeID) as MarketTypePrice;
|
const price = prices.find(p => p.type.id === i.typeID) as MarketTypePrice;
|
||||||
|
|
||||||
return { ...i, ...price };
|
return { ...i, ...price };
|
||||||
});
|
});
|
||||||
};
|
})
|
||||||
|
|
||||||
watch(items, itms => itemsStorage.value = itms.map(i => ({ typeID: i.type.id, count: i.count, averagePrice: i.averagePrice })));
|
|
||||||
onMounted(relaod);
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -34,8 +30,8 @@ onMounted(relaod);
|
|||||||
<template v-if="items.length > 0">
|
<template v-if="items.length > 0">
|
||||||
<hr />
|
<hr />
|
||||||
<TrackResultTable :items="items" @buy="(type, price, buy, sell) => buyModal?.open(type, { 'Price': price, 'Buy': buy, 'Sell': sell })" @sell="type => sellModal?.open(type)" />
|
<TrackResultTable :items="items" @buy="(type, price, buy, sell) => buyModal?.open(type, { 'Price': price, 'Buy': buy, 'Sell': sell })" @sell="type => sellModal?.open(type)" />
|
||||||
<BuyModal ref="buyModal" @added="relaod" />
|
<BuyModal ref="buyModal" />
|
||||||
<SellModal ref="sellModal" @removed="relaod" />
|
<SellModal ref="sellModal" />
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
31
src/pocketbase/collection.ts
Normal file
31
src/pocketbase/collection.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
import { usePocketBase } from "@/pocketbase";
|
||||||
|
import { RecordModel, RecordSubscription, UnsubscribeFunc } from "pocketbase";
|
||||||
|
import { Ref, computed, onMounted, onUnmounted, ref } from "vue";
|
||||||
|
|
||||||
|
export const watchCollection = <T extends RecordModel = RecordModel>(collection: string, query: string, callback: (data: RecordSubscription<T>) => void) => {
|
||||||
|
const pb = usePocketBase();
|
||||||
|
let unsubscribe: UnsubscribeFunc = () => Promise.resolve();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
unsubscribe = await pb.collection(collection).subscribe<T>(query, callback);
|
||||||
|
});
|
||||||
|
onUnmounted(() => unsubscribe());
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCollection = <T extends RecordModel = RecordModel>(collection: string) => {
|
||||||
|
const pb = usePocketBase();
|
||||||
|
const list = ref<T[]>([]) as Ref<T[]>;
|
||||||
|
|
||||||
|
watchCollection<T>(collection, '*', data => {
|
||||||
|
if (data.action === 'delete') {
|
||||||
|
list.value = list.value.filter(i => i.id !== data.record.id);
|
||||||
|
} else if (data.action === 'update') {
|
||||||
|
list.value = list.value.map(i => i.id === data.record.id ? data.record : i);
|
||||||
|
} else if (data.action === 'create') {
|
||||||
|
list.value = [...list.value, data.record];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onMounted(async () => list.value = await pb.collection(collection).getFullList<T>().catch(() => [] as T[]));
|
||||||
|
return computed(() => list.value);
|
||||||
|
}
|
||||||
@@ -1 +1,2 @@
|
|||||||
|
export * from './collection';
|
||||||
export * from './pocketbase';
|
export * from './pocketbase';
|
||||||
|
|||||||
Reference in New Issue
Block a user