laravel-nuxt/nuxt/app/components/account/AccountDeviceTable.vue

110 lines
2.3 KiB
Vue

<script setup lang="ts">
import type { TableColumn } from '#ui/components/Table.vue'
import type { Device, IDevicesResponse } from '~/types/device'
const UButton = resolveComponent('UButton')
const UBadge = resolveComponent('UBadge')
const UDropdownMenu = resolveComponent('UDropdownMenu')
const dayjs = useDayjs()
const auth = useAuthStore()
const loading = ref(false)
const devices = ref<Device[]>([])
async function fetchData() {
loading.value = true
const response = await $fetch<IDevicesResponse>('devices')
if (response.ok) {
devices.value = response.devices
}
loading.value = false
}
const columns: TableColumn<Device>[] = [
{
accessorKey: 'name',
header: 'Device',
cell: ({ row }) => {
return h('div', { class: 'font-semibold' }, [
row.original.name,
row.original.is_current && h(UBadge, {
label: 'active',
color: 'primary',
variant: 'soft',
size: 'sm',
class: 'ms-1',
}),
h('div', { class: 'font-medium text-sm' }, `IP: ${row.original.ip}`),
])
},
},
{
accessorKey: 'last_used_at',
header: 'Last used at',
cell: ({ row }) => {
return dayjs(row.original.last_used_at).fromNow()
},
},
{
accessorKey: 'actions',
header: 'Actions',
cell: ({ row }) => {
return h('div', { class: 'flex justify-end' },
h(UDropdownMenu, {
items: items(row.original),
}, () => h(UButton, {
icon: 'i-heroicons-ellipsis-vertical-20-solid',
variant: 'ghost',
color: 'neutral',
})),
)
},
},
]
const items = (row: Device) => [
[
{
label: 'Delete',
icon: 'i-heroicons-trash-20-solid',
onSelect: async () => {
await $fetch<never>('devices/disconnect', {
method: 'POST',
body: {
hash: row.hash,
},
async onResponse({ response }) {
if (response._data?.ok) {
await fetchData()
await auth.fetchUser()
}
},
})
},
},
],
]
if (import.meta.client) {
fetchData()
}
</script>
<template>
<ClientOnly>
<UTable
:data="devices"
:columns="columns"
size="lg"
:loading="loading"
/>
</ClientOnly>
</template>
<style scoped>
</style>