HomeSales.vue
3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<script setup lang="ts">
import { h, resolveComponent } from 'vue'
import type { TableColumn } from '@nuxt/ui'
import type { Period, Range, Sale } from '~/types'
const props = defineProps<{
period: Period
range: Range
}>()
const { locale, t } = useAppI18n()
const UBadge = resolveComponent('UBadge')
const sampleEmails = [
'james.anderson@example.com',
'mia.white@example.com',
'william.brown@example.com',
'emma.davis@example.com',
'ethan.harris@example.com'
]
const { data } = await useAsyncData('sales', async () => {
const sales: Sale[] = []
const currentDate = new Date()
for (let i = 0; i < 5; i++) {
const hoursAgo = randomInt(0, 48)
const date = new Date(currentDate.getTime() - hoursAgo * 3600000)
sales.push({
id: (4600 - i).toString(),
date: date.toISOString(),
status: randomFrom(['paid', 'failed', 'refunded']),
email: randomFrom(sampleEmails),
amount: randomInt(100, 1000)
})
}
return sales.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
}, {
watch: [() => props.period, () => props.range],
default: () => []
})
const dateFormatter = computed(() => {
return new Intl.DateTimeFormat(locale.value === 'zh-CN' ? 'zh-CN' : 'en-US', {
day: 'numeric',
month: 'short',
hour: '2-digit',
minute: '2-digit',
hour12: false
})
})
const currencyFormatter = computed(() => {
return new Intl.NumberFormat(locale.value === 'zh-CN' ? 'zh-CN' : 'en-US', {
style: 'currency',
currency: 'EUR'
})
})
const columns = computed<TableColumn<Sale>[]>(() => [
{
accessorKey: 'id',
header: t('home.sales.id'),
cell: ({ row }) => `#${row.getValue('id')}`
},
{
accessorKey: 'date',
header: t('home.sales.date'),
cell: ({ row }) => dateFormatter.value.format(new Date(row.getValue('date')))
},
{
accessorKey: 'status',
header: t('home.sales.status'),
cell: ({ row }) => {
const status = row.getValue('status') as Sale['status']
const color = {
paid: 'success' as const,
failed: 'error' as const,
refunded: 'neutral' as const
}[status]
return h(UBadge, { class: 'capitalize', variant: 'subtle', color }, () =>
t(`home.sales.statusMap.${status}`)
)
}
},
{
accessorKey: 'email',
header: t('home.sales.email')
},
{
accessorKey: 'amount',
header: () => h('div', { class: 'text-right' }, t('home.sales.amount')),
cell: ({ row }) => {
const amount = Number.parseFloat(row.getValue('amount'))
return h('div', { class: 'text-right font-medium' }, currencyFormatter.value.format(amount))
}
}
])
</script>
<template>
<UTable
:data="data"
:columns="columns"
class="shrink-0"
:ui="{
base: 'table-fixed border-separate border-spacing-0',
thead: '[&>tr]:bg-elevated/50 [&>tr]:after:content-none',
tbody: '[&>tr]:last:[&>td]:border-b-0',
th: 'first:rounded-l-lg last:rounded-r-lg border-y border-default first:border-l last:border-r',
td: 'border-b border-default'
}"
/>
</template>