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:
parent
b483674ebe
commit
58cf5cb762
1 changed files with 26 additions and 50 deletions
|
|
@ -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"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue