Files
money.sori.studio/components/TransactionListRow.vue

72 lines
2.2 KiB
Vue

<template>
<component
:is="rowComponent"
v-bind="rowAttrs"
class="grid grid-cols-[2.5rem_minmax(0,1fr)_auto] items-start gap-3 px-4 py-3 active:bg-paper md:px-5"
>
<div
class="mt-0.5 flex h-10 w-10 items-center justify-center rounded-md text-sm font-extrabold"
:style="categoryIconStyle"
aria-hidden="true"
>
{{ categoryIconGlyph }}
</div>
<div class="min-w-0">
<p class="truncate text-[15px] font-bold leading-5 text-ink">
{{ transaction.title }}
</p>
<p class="mt-1 truncate text-xs font-medium leading-5 text-muted">
{{ metaLine }}
</p>
<p v-if="memoPreview" class="mt-1 truncate text-xs font-medium leading-5 text-muted">
{{ memoPreview }}
</p>
</div>
<p
class="whitespace-nowrap pt-0.5 text-right text-[15px] font-bold leading-5"
:class="transaction.type === 'income' ? 'text-brand-700' : 'text-ink'"
>
{{ formatWon(transaction.amount) }}
</p>
</component>
</template>
<script setup lang="ts">
import type { Transaction } from '~/composables/useMoney'
import { categoryColor, categoryGlyph } from '~/utils/categoryPresentation'
const props = defineProps<{
transaction: Transaction
readonly?: boolean
}>()
const rowComponent = computed(() => props.readonly ? 'div' : resolveComponent('NuxtLink'))
const rowAttrs = computed(() => props.readonly ? {} : { to: `/transactions/${props.transaction.id}` })
const categoryLabel = computed(() => {
const category = props.transaction.category
return category.name
})
const presentationCategory = computed(() => {
const category = props.transaction.category
return category.icon || category.color ? category : category.parent || category
})
const categoryIconGlyph = computed(() => categoryGlyph(presentationCategory.value.icon))
const categoryIconStyle = computed(() => {
const color = categoryColor(presentationCategory.value.color)
return {
color,
backgroundColor: `${color}14`
}
})
const metaLine = computed(() => {
return [props.transaction.asset.name, categoryLabel.value].filter(Boolean).join(' · ')
})
const memoPreview = computed(() => props.transaction.memo?.trim().slice(0, 60) || '')
</script>