110 lines
2.3 KiB
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>
|