Sink/components/dashboard/metrics/Locations.vue
ccbikai 2a6b875bdb feat: consolidate time filtering and add advanced filters
Refactors time-based filtering by combining startAt/endAt into a single time object
Adds support for additional filter types in stats API queries
Implements deep watching for both time and filter changes

Improves code organization and maintainability while enabling more flexible data filtering
2025-03-02 13:40:43 +08:00

91 lines
2.1 KiB
Vue

<script setup>
import { ChartTooltip } from '@/components/ui/chart'
import { VisSingleContainer, VisTopoJSONMap, VisTopoJSONMapSelectors } from '@unovis/vue'
const id = inject('id')
const time = inject('time')
const filters = inject('filters')
const worldMapTopoJSON = ref({})
const areaData = ref([])
async function getWorldMapJSON() {
const data = await $fetch('/world.json')
worldMapTopoJSON.value = data
}
async function getMapData() {
areaData.value = []
const { data } = await useAPI('/api/stats/metrics', {
query: {
type: 'country',
id: id.value,
startAt: time.value.startAt,
endAt: time.value.endAt,
...filters.value,
},
})
if (Array.isArray(data)) {
areaData.value = data.map((country) => {
country.id = country.name
return country
})
}
}
const stopWatchQueryChange = watch([time, filters], getMapData, {
deep: true,
})
onMounted(() => {
getWorldMapJSON()
getMapData()
})
onBeforeUnmount(() => {
stopWatchQueryChange()
})
const valueFormatter = v => v
const Tooltip = {
props: ['title', 'data'],
setup(props) {
const title = props.data[1]?.value?.name
const data = [{
name: props.title,
value: props.data[3]?.value?.count,
color: 'black',
}]
return () => h(ChartTooltip, { title, data })
},
}
</script>
<template>
<Card class="flex flex-col md:h-[500px]">
<CardHeader>
<CardTitle>Locations</CardTitle>
</CardHeader>
<CardContent class="flex-1 flex [&_[data-radix-aspect-ratio-wrapper]]:flex-1">
<AspectRatio :ratio="65 / 30">
<VisSingleContainer
v-if="worldMapTopoJSON.type"
:data="{ areas: areaData }"
class="h-full"
>
<VisTopoJSONMap
:topojson="worldMapTopoJSON"
map-feature-name="countries"
/>
<ChartSingleTooltip
index="id"
:selector="VisTopoJSONMapSelectors.feature"
:items="areaData"
:value-formatter="valueFormatter"
:custom-tooltip="Tooltip"
/>
</VisSingleContainer>
</AspectRatio>
</CardContent>
</Card>
</template>