first commit
This commit is contained in:
112
app/components/home/HomeSales.vue
Normal file
112
app/components/home/HomeSales.vue
Normal file
@@ -0,0 +1,112 @@
|
||||
<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 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 columns: TableColumn<Sale>[] = [
|
||||
{
|
||||
accessorKey: 'id',
|
||||
header: 'ID',
|
||||
cell: ({ row }) => `#${row.getValue('id')}`
|
||||
},
|
||||
{
|
||||
accessorKey: 'date',
|
||||
header: 'Date',
|
||||
cell: ({ row }) => {
|
||||
return new Date(row.getValue('date')).toLocaleString('en-US', {
|
||||
day: 'numeric',
|
||||
month: 'short',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: false
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
accessorKey: 'status',
|
||||
header: 'Status',
|
||||
cell: ({ row }) => {
|
||||
const color = {
|
||||
paid: 'success' as const,
|
||||
failed: 'error' as const,
|
||||
refunded: 'neutral' as const
|
||||
}[row.getValue('status') as string]
|
||||
|
||||
return h(UBadge, { class: 'capitalize', variant: 'subtle', color }, () =>
|
||||
row.getValue('status')
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
accessorKey: 'email',
|
||||
header: 'Email'
|
||||
},
|
||||
{
|
||||
accessorKey: 'amount',
|
||||
header: () => h('div', { class: 'text-right' }, 'Amount'),
|
||||
cell: ({ row }) => {
|
||||
const amount = Number.parseFloat(row.getValue('amount'))
|
||||
|
||||
const formatted = new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: 'EUR'
|
||||
}).format(amount)
|
||||
|
||||
return h('div', { class: 'text-right font-medium' }, formatted)
|
||||
}
|
||||
}
|
||||
]
|
||||
</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>
|
||||
Reference in New Issue
Block a user