first commit

This commit is contained in:
root
2025-11-30 19:49:01 +08:00
commit 8dcb2a5898
46 changed files with 14428 additions and 0 deletions

View 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>