113 lines
2.5 KiB
Vue
113 lines
2.5 KiB
Vue
<script setup>
|
|
import { Maximize } from 'lucide-vue-next'
|
|
|
|
const props = defineProps({
|
|
type: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
name: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
})
|
|
|
|
const id = inject('id')
|
|
const startAt = inject('startAt')
|
|
const endAt = inject('endAt')
|
|
|
|
const total = ref(0)
|
|
const metrics = ref([])
|
|
const top6 = ref([])
|
|
|
|
async function getLinkMetrics() {
|
|
total.value = 0
|
|
metrics.value = []
|
|
top6.value = []
|
|
const { data } = await useAPI('/api/stats/metrics', {
|
|
query: {
|
|
type: props.type,
|
|
id: id.value,
|
|
startAt: startAt.value,
|
|
endAt: endAt.value,
|
|
},
|
|
})
|
|
if (Array.isArray(data)) {
|
|
const colors = colorGradation(data.length)
|
|
total.value = data.reduce((acc, cur) => acc + Number(cur.count), 0)
|
|
metrics.value = data.map((item, i) => {
|
|
item.color = colors[i]
|
|
item.percent = Math.floor(item.count / total.value * 100) || (item.count ? 1 : 0)
|
|
return item
|
|
})
|
|
top6.value = metrics.value.slice(0, 6)
|
|
}
|
|
}
|
|
|
|
const stopWatchTime = watch([startAt, endAt], getLinkMetrics)
|
|
|
|
onMounted(() => {
|
|
getLinkMetrics()
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
stopWatchTime()
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<Card class="flex flex-col">
|
|
<template v-if="metrics.length">
|
|
<DashboardMetricsList
|
|
class="flex-1"
|
|
:metrics="top6"
|
|
:type="type"
|
|
/>
|
|
<CardFooter class="py-2">
|
|
<Dialog>
|
|
<DialogTrigger
|
|
as-child
|
|
class="w-full"
|
|
>
|
|
<Button
|
|
variant="link"
|
|
>
|
|
<Maximize
|
|
class="w-4 h-4 mr-2"
|
|
/> DETAILS
|
|
</Button>
|
|
</DialogTrigger>
|
|
<DialogContent class="max-w-[95svw] max-h-[95svh] md:max-w-screen-md grid-rows-[auto_minmax(0,1fr)_auto]">
|
|
<DialogHeader>
|
|
<DialogTitle>{{ name }}</DialogTitle>
|
|
</DialogHeader>
|
|
<DashboardMetricsList
|
|
class="overflow-y-auto"
|
|
:metrics="metrics"
|
|
:type="type"
|
|
/>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</CardFooter>
|
|
</template>
|
|
<template v-else>
|
|
<div class="flex items-center justify-between h-12 px-4">
|
|
<Skeleton
|
|
class="w-32 h-4 rounded-full"
|
|
/>
|
|
<Skeleton
|
|
class="w-20 h-4 rounded-full"
|
|
/>
|
|
</div>
|
|
<div
|
|
v-for="i in 3"
|
|
:key="i"
|
|
class="px-4 py-4"
|
|
>
|
|
<Skeleton
|
|
class="w-full h-4 rounded-full"
|
|
/>
|
|
</div>
|
|
</template>
|
|
</Card>
|
|
</template>
|