From 3b2be0f19d290a308ed8e010e7fe2281270a3cd1 Mon Sep 17 00:00:00 2001 From: poketonova Date: Mon, 27 Jul 2026 09:01:15 -0600 Subject: [PATCH 1/2] feat: add trade log state and actions to portfolio store --- src/stores/portfolio.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/stores/portfolio.js b/src/stores/portfolio.js index f556724..41a432b 100644 --- a/src/stores/portfolio.js +++ b/src/stores/portfolio.js @@ -27,6 +27,7 @@ export const usePortfolioStore = defineStore('portfolio', () => { const activePortfolioId = ref(null) const settings = ref({ currency: 'USD', defaultPortfolioId: null }) const snapshots = ref({}) + const tradeLog = ref([]) const initialized = ref(false) // ── Persistence ────────────────────────────────────────────────────── @@ -37,6 +38,7 @@ export const usePortfolioStore = defineStore('portfolio', () => { activePortfolioId: activePortfolioId.value, settings: settings.value, snapshots: snapshots.value, + tradeLog: tradeLog.value, })) } @@ -45,6 +47,7 @@ export const usePortfolioStore = defineStore('portfolio', () => { if (state.activePortfolioId) activePortfolioId.value = state.activePortfolioId if (state.settings) settings.value = { ...settings.value, ...state.settings } if (state.snapshots) snapshots.value = state.snapshots + if (state.tradeLog) tradeLog.value = state.tradeLog } // Debounced save to IDB @@ -245,6 +248,24 @@ export const usePortfolioStore = defineStore('portfolio', () => { }) } + // ── Trade Log ─────────────────────────────────────────────────────── + + function logTrade(trade) { + const entry = { + id: generateId(), + date: new Date().toISOString(), + ...trade + } + tradeLog.value.unshift(entry) + if (tradeLog.value.length > 100) tradeLog.value.pop() + persist() + } + + function deleteTrade(id) { + tradeLog.value = tradeLog.value.filter(t => t.id !== id) + persist() + } + // ── Helpers ────────────────────────────────────────────────────────── function isJPCard(item) { @@ -364,6 +385,7 @@ export const usePortfolioStore = defineStore('portfolio', () => { portfolios.value = [] activePortfolioId.value = null snapshots.value = {} + tradeLog.value = [] settings.value = { currency: 'USD', defaultPortfolioId: null } // Clear both IDB and any leftover localStorage await saveState(null) @@ -405,6 +427,7 @@ export const usePortfolioStore = defineStore('portfolio', () => { activePortfolio, settings, snapshots, + tradeLog, initialized, totalPortfolioValue, totalCostBasis, @@ -419,6 +442,8 @@ export const usePortfolioStore = defineStore('portfolio', () => { updateItem, removeItem, updateCardPrice, + logTrade, + deleteTrade, getPortfolioStats, recordSnapshot, getItemHistory, From 6ecba2b5d9d1e8ae195085b2ddc4804aabdeb297 Mon Sep 17 00:00:00 2001 From: poketonova Date: Mon, 27 Jul 2026 09:01:56 -0600 Subject: [PATCH 2/2] feat: implement Trade Log section in DashboardView --- src/views/DashboardView.vue | 156 +++++++++++++++++++++++++++--------- 1 file changed, 119 insertions(+), 37 deletions(-) diff --git a/src/views/DashboardView.vue b/src/views/DashboardView.vue index 12527a5..9f896c8 100644 --- a/src/views/DashboardView.vue +++ b/src/views/DashboardView.vue @@ -275,6 +275,41 @@ + +
+
+
+
Trade Log
+
History of your manual trades
+
+ +
+ +
+ No trades logged yet. Track your card swaps and deals here. +
+ +
+
+
{{ new Date(trade.date).toLocaleDateString() }}
+
+
+ Out: {{ trade.gave }} +
+
+ In: {{ trade.received }} +
+
+
+ + {{ trade.valueDifference >= 0 ? '+' : '' }}${{ trade.valueDifference.toFixed(2) }} + +
+ +
+
+
+
Portfolios
@@ -328,6 +363,29 @@
+ + + @@ -340,6 +398,9 @@ import PortfolioChart from '../components/PortfolioChart.vue' const store = usePortfolioStore() const featuresRef = ref(null) +const showTradeModal = ref(false) +const newTrade = ref({ gave: '', received: '', valueDifference: 0 }) + // New user = every portfolio has 0 items (store auto-creates one empty portfolio on init) const isNewUser = computed(() => { return store.portfolios.every(p => p.items.length === 0) @@ -349,6 +410,13 @@ function scrollToFeatures() { featuresRef.value?.scrollIntoView({ behavior: 'smooth' }) } +function saveTrade() { + if (!newTrade.value.gave || !newTrade.value.received) return + store.logTrade({ ...newTrade.value }) + newTrade.value = { gave: '', received: '', valueDifference: 0 } + showTradeModal.value = false +} + const totalGain = computed(() => store.totalPortfolioValue - store.totalCostBasis) const totalGainPct = computed(() => store.totalCostBasis > 0 ? (totalGain.value / store.totalCostBasis) * 100 : 0) const totalItems = computed(() => store.portfolios.reduce((s, p) => s + p.items.length, 0)) @@ -413,6 +481,39 @@ onMounted(async () => {