From dd71d10564b738a57ab36a30bcad930200888c4d Mon Sep 17 00:00:00 2001 From: Padreug Date: Sat, 6 Jun 2026 22:51:43 +0200 Subject: [PATCH] feat(libra): hide voided by default + add Pending badge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Voided transactions are noise in the day-to-day view (the user already saw and rejected them), so default to hiding them. A Switch in the filter row toggles 'Show voided'. When voided are present but hidden, the results-count line shows '(N voided hidden)' so the toggle has a discoverable hook. Pending entries gain a yellow Pending badge symmetric with the red Voided badge — both signal 'needs attention' states in the badge row, while cleared entries stay unmarked (the default, quiet state). Status / type encoding (icon = status, signed/colored amount = type) is unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../expenses/views/TransactionsPage.vue | 52 ++++++++++++++++--- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/src/modules/expenses/views/TransactionsPage.vue b/src/modules/expenses/views/TransactionsPage.vue index 6803aa0..7a34476 100644 --- a/src/modules/expenses/views/TransactionsPage.vue +++ b/src/modules/expenses/views/TransactionsPage.vue @@ -11,6 +11,8 @@ import FuzzySearch from '@/components/ui/fuzzy-search/FuzzySearch.vue' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' import { Input } from '@/components/ui/input' +import { Switch } from '@/components/ui/switch' +import { Label } from '@/components/ui/label' import { CheckCircle2, Clock, @@ -31,6 +33,7 @@ const dateRangeType = ref(15) // 15, 30, 60, or 'custom' const customStartDate = ref('') const customEndDate = ref('') const typeFilter = ref<'all' | 'income' | 'expense'>('all') +const showVoided = ref(false) const typeFilterOptions = [ { label: 'All', value: 'all' as const }, @@ -50,6 +53,10 @@ function isVoided(t: Transaction): boolean { return t.tags?.includes('voided') ?? false } +function isPending(t: Transaction): boolean { + return t.flag === '!' && !isVoided(t) +} + const walletKey = computed(() => user.value?.wallets?.[0]?.inkey) // Fuzzy search state and configuration @@ -75,14 +82,25 @@ const searchOptions: FuzzySearchOptions = { matchAllWhenSearchEmpty: true } -// Transactions to display (search results or all transactions), filtered by type +// Transactions to display: search results (or all), with voided hidden by +// default and the type filter applied last. const transactionsToDisplay = computed(() => { - const base = searchResults.value.length > 0 ? searchResults.value : transactions.value + let base = searchResults.value.length > 0 ? searchResults.value : transactions.value + if (!showVoided.value) base = base.filter(t => !isVoided(t)) if (typeFilter.value === 'income') return base.filter(isIncome) if (typeFilter.value === 'expense') return base.filter(isExpense) return base }) +// Count of voided entries that are being hidden right now — surfaced in +// the results-count line so the user knows the toggle has something to +// reveal. +const voidedHiddenCount = computed(() => { + if (showVoided.value) return 0 + const base = searchResults.value.length > 0 ? searchResults.value : transactions.value + return base.filter(isVoided).length +}) + // Handle search results function handleSearchResults(results: Transaction[]) { searchResults.value = results @@ -255,7 +273,7 @@ onMounted(() => { - +
+
+ + +
@@ -322,7 +350,10 @@ onMounted(() => { Found {{ transactionsToDisplay.length }} matching transaction{{ transactionsToDisplay.length === 1 ? '' : 's' }} - {{ transactions.length }} transaction{{ transactions.length === 1 ? '' : 's' }} + {{ transactionsToDisplay.length }} transaction{{ transactionsToDisplay.length === 1 ? '' : 's' }} + + + ({{ voidedHiddenCount }} voided hidden) @@ -405,11 +436,11 @@ onMounted(() => { Ref: {{ transaction.reference }} -
{ > Voided + + Pending +