mirror of
https://github.com/web3privacy/explorer-app.git
synced 2024-10-15 16:46:26 +02:00
131 lines
3.5 KiB
Vue
131 lines
3.5 KiB
Vue
<script lang="ts" setup>
|
|
import type { ProjectRating } from '~/types'
|
|
|
|
// Define props for score
|
|
const props = defineProps<{
|
|
rating: ProjectRating
|
|
percentage: number
|
|
compact?: boolean
|
|
}>()
|
|
|
|
const colors = [
|
|
'#ff0000', // 0-10%
|
|
'#ff4500', // 11-20%
|
|
'#ff8c00', // 21-30%
|
|
'#ffd700', // 31-40%
|
|
'#adff2f', // 41-50%
|
|
'#7fff00', // 51-60%
|
|
'#00ff00', // 61-70%
|
|
'#32cd32', // 71-80%
|
|
'#00fa9a', // 81-90%
|
|
'#00ffff', // 91-100%
|
|
]
|
|
|
|
const backgroundColorByScore = computed(() => {
|
|
const normalizedPercentage = Math.min(Math.max(props.percentage, 0), 100)
|
|
const colorIndex = Math.floor(normalizedPercentage / 10)
|
|
return colors[colorIndex]
|
|
})
|
|
|
|
const isPopoverVisible = ref(false)
|
|
|
|
let hideTimeout: ReturnType<typeof setTimeout> | null = null
|
|
const showPopover = () => {
|
|
if (hideTimeout) {
|
|
clearTimeout(hideTimeout)
|
|
hideTimeout = null
|
|
}
|
|
isPopoverVisible.value = true
|
|
}
|
|
|
|
const hidePopover = () => {
|
|
hideTimeout = setTimeout(() => {
|
|
isPopoverVisible.value = false
|
|
}, 100) // Delay of 200ms before hiding
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="relative">
|
|
<!-- Main div that shows rating and triggers the popover on hover -->
|
|
<div
|
|
flex
|
|
items-center
|
|
p-12px
|
|
gap-4px
|
|
hover:bg-app-bg-rating-hover
|
|
hover:rounded-8px
|
|
@mouseenter="showPopover"
|
|
@mouseleave="hidePopover"
|
|
>
|
|
<div
|
|
v-for="point of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"
|
|
:key="point"
|
|
:style="`background-color: ${percentage >= point * 10 ? backgroundColorByScore : '#494949'}`"
|
|
:class="[compact ? 'h-8px lg:h-10px w-4px lg:w-5px' : 'w-5px lg:w-6px h-10px lg:h-12px', point % 2 === 0 ? 'rounded-l-2px' : 'rounded-r-2px ml--4px', 'bg-app-bg-rating-default']"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Popover panel that appears on hover -->
|
|
<transition
|
|
enter-active-class="transition duration-300 ease-out"
|
|
enter-from-class="transform scale-95 opacity-0"
|
|
enter-to-class="transform scale-100 opacity-100"
|
|
leave-active-class="transition duration-200 ease-in"
|
|
leave-from-class="transform scale-100 opacity-100"
|
|
leave-to-class="transform scale-95 opacity-0"
|
|
>
|
|
<div
|
|
v-if="isPopoverVisible"
|
|
class="absolute mt-2 p-2 bg-app-bg-rating-hover w-240px shadow-lg rounded"
|
|
z-100
|
|
style="left: 50%; transform: translateX(-50%);"
|
|
flex
|
|
flex-col
|
|
gap-14px
|
|
px-16px
|
|
py-10px
|
|
@mouseenter="showPopover"
|
|
@mouseleave="hidePopover"
|
|
>
|
|
<div
|
|
v-for="item in rating.items"
|
|
:key="item.label"
|
|
flex
|
|
justify-between
|
|
items-center
|
|
text-12px
|
|
font-700
|
|
leading-20px
|
|
:class="[item.isValid ? 'text-app-white': 'text-app-text-rating-negative']"
|
|
>
|
|
<div
|
|
flex
|
|
items-center
|
|
gap-6px
|
|
>
|
|
<div
|
|
:class="[item.isValid ? 'i-ic-sharp-thumb-up' : 'i-ic-sharp-thumb-down']"
|
|
text-20px
|
|
mt--4px
|
|
/>
|
|
{{ item.label }}
|
|
</div>
|
|
<NuxtLink
|
|
v-if="item.isValid && item.positive === 'Link'"
|
|
:to="item.value"
|
|
target="_blank"
|
|
external
|
|
underline
|
|
@click.stop
|
|
>
|
|
{{ item.positive }}
|
|
</NuxtLink>
|
|
<div v-else>
|
|
{{ item.isValid ? item.positive : item.negative }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</transition>
|
|
</div>
|
|
</template>
|