refactor(libra): drop status icons, add Income/Expense badges

Per the iteration: the title-row status icons (green check / yellow
clock / red X) were doing the same job as the new status badges and
amount color, so each row had three signals fighting for the same
meaning. Drop the icons and lean on badges instead.

Badge row order (left-to-right): Voided > Income/Expense > Pending >
user tags. Type badge sits between the high-attention Voided marker
and the secondary Pending marker, so the type chip is easy to spot
on every row.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-06-06 23:05:55 +02:00
commit 58cf5cb762

View file

@ -12,10 +12,6 @@ import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge' import { Badge } from '@/components/ui/badge'
import { Input } from '@/components/ui/input' import { Input } from '@/components/ui/input'
import { import {
CheckCircle2,
Clock,
Flag,
XCircle,
RefreshCw, RefreshCw,
Calendar, Calendar,
Filter Filter
@ -137,25 +133,6 @@ function formatAmount(amount: number): string {
return new Intl.NumberFormat('en-US').format(amount) return new Intl.NumberFormat('en-US').format(amount)
} }
// Get status icon and color. Voided entries (per libra convention) keep
// flag='!' and carry a 'voided' tag surface that as the icon regardless
// of the underlying flag.
function getStatusInfo(transaction: Transaction) {
if (isVoided(transaction)) {
return { icon: XCircle, color: 'text-muted-foreground', label: 'Voided' }
}
switch (transaction.flag) {
case '*':
return { icon: CheckCircle2, color: 'text-green-600', label: 'Cleared' }
case '!':
return { icon: Clock, color: 'text-yellow-500', label: 'Pending' }
case '#':
return { icon: Flag, color: 'text-red-600', label: 'Flagged' }
default:
return null
}
}
// Income gets a leading '+', expense a leading '-'. // Income gets a leading '+', expense a leading '-'.
function getAmountSign(t: Transaction): string { function getAmountSign(t: Transaction): string {
if (isIncome(t)) return '+' if (isIncome(t)) return '+'
@ -380,25 +357,14 @@ onMounted(() => {
<!-- Transaction Header --> <!-- Transaction Header -->
<div class="flex items-start justify-between gap-3 mb-2"> <div class="flex items-start justify-between gap-3 mb-2">
<div class="flex-1 min-w-0"> <div class="flex-1 min-w-0">
<div class="flex items-center gap-2 mb-1">
<!-- Status Icon -->
<component
v-if="getStatusInfo(transaction)"
:is="getStatusInfo(transaction)!.icon"
:class="[
'h-4 w-4 flex-shrink-0',
getStatusInfo(transaction)!.color
]"
/>
<h3 <h3
:class="[ :class="[
'font-medium text-sm sm:text-base truncate', 'font-medium text-sm sm:text-base truncate mb-1',
isVoided(transaction) && 'line-through text-muted-foreground' isVoided(transaction) && 'line-through text-muted-foreground'
]" ]"
> >
{{ transaction.description }} {{ transaction.description }}
</h3> </h3>
</div>
<p class="text-xs sm:text-sm text-muted-foreground"> <p class="text-xs sm:text-sm text-muted-foreground">
{{ formatDate(transaction.date) }} {{ formatDate(transaction.date) }}
</p> </p>
@ -433,13 +399,9 @@ onMounted(() => {
<span class="font-medium">Ref:</span> {{ transaction.reference }} <span class="font-medium">Ref:</span> {{ transaction.reference }}
</div> </div>
<!-- Tags: status badge (Voided / Pending) + any user-added tags. <!-- Badges: Voided (leftmost, high-signal) + type (Income /
Type tags (income-entry / expense-entry) are intentionally Expense) + Pending (after type) + any user-added tags. -->
suppressed they're encoded by the signed amount. --> <div class="flex flex-wrap gap-1 mt-2">
<div
v-if="isVoided(transaction) || isPending(transaction) || getDisplayTags(transaction).length > 0"
class="flex flex-wrap gap-1 mt-2"
>
<Badge <Badge
v-if="isVoided(transaction)" v-if="isVoided(transaction)"
variant="secondary" variant="secondary"
@ -448,7 +410,21 @@ onMounted(() => {
Voided Voided
</Badge> </Badge>
<Badge <Badge
v-else-if="isPending(transaction)" v-if="isIncome(transaction)"
variant="secondary"
class="text-xs bg-green-100 dark:bg-green-900/20 text-green-700 dark:text-green-300"
>
Income
</Badge>
<Badge
v-else-if="isExpense(transaction)"
variant="secondary"
class="text-xs bg-red-100 dark:bg-red-900/20 text-red-700 dark:text-red-300"
>
Expense
</Badge>
<Badge
v-if="isPending(transaction)"
variant="secondary" variant="secondary"
class="text-xs bg-yellow-100 dark:bg-yellow-900/20 text-yellow-700 dark:text-yellow-300" class="text-xs bg-yellow-100 dark:bg-yellow-900/20 text-yellow-700 dark:text-yellow-300"
> >