mirror of
https://github.com/web3privacy/explorer-app.git
synced 2024-10-15 16:46:26 +02:00
commit
120744e9bb
14 changed files with 103 additions and 56 deletions
|
@ -3,6 +3,7 @@ import type { ProjectRating, ProjectShallow } from '~/types'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
project: ProjectShallow
|
project: ProjectShallow
|
||||||
|
hiddenColumns?: string[]
|
||||||
}>()
|
}>()
|
||||||
const { switcher, ecosystems, filter } = storeToRefs(useData())
|
const { switcher, ecosystems, filter } = storeToRefs(useData())
|
||||||
|
|
||||||
|
@ -11,6 +12,14 @@ const isLargeScreen = useMediaQuery('(min-width: 1024px)')
|
||||||
const ratings: { label: string, type: string, rating: ProjectRating }[] = (props.project.ratings || []).map(rating => ({ label: rating.name, type: 'rating', rating: rating }))
|
const ratings: { label: string, type: string, rating: ProjectRating }[] = (props.project.ratings || []).map(rating => ({ label: rating.name, type: 'rating', rating: rating }))
|
||||||
const ecosystem: { label: string[], type: string } = { label: ecosystems.value.filter(e => (props.project.ecosystem || []).includes(e.id)).map(e => e.icon!), type: 'ecosystem' }
|
const ecosystem: { label: string[], type: string } = { label: ecosystems.value.filter(e => (props.project.ecosystem || []).includes(e.id)).map(e => e.icon!), type: 'ecosystem' }
|
||||||
const projectItems: { label: string | string[], type: string, rating?: ProjectRating }[] = [{ label: props.project.usecases || [], type: 'array' }, ...ratings, ecosystem, { label: [props.project.website || '', props.project.github || '', props.project.twitter || ''], type: 'links' }]
|
const projectItems: { label: string | string[], type: string, rating?: ProjectRating }[] = [{ label: props.project.usecases || [], type: 'array' }, ...ratings, ecosystem, { label: [props.project.website || '', props.project.github || '', props.project.twitter || ''], type: 'links' }]
|
||||||
|
|
||||||
|
const { width } = useWindowSize()
|
||||||
|
const visibleColumnsCount = computed(() => {
|
||||||
|
if (width.value >= 1024)
|
||||||
|
return projectItems.filter(item => item.rating?.type ? !props.hiddenColumns?.includes(item.rating.type) : true).length + 4
|
||||||
|
else
|
||||||
|
return 2
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -25,7 +34,7 @@ const projectItems: { label: string | string[], type: string, rating?: ProjectRa
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
grid
|
grid
|
||||||
grid-cols="2 lg:10"
|
:style="`grid-template-columns: repeat(${visibleColumnsCount}, 1fr)`"
|
||||||
w-full
|
w-full
|
||||||
>
|
>
|
||||||
|
|
||||||
|
@ -89,7 +98,7 @@ const projectItems: { label: string | string[], type: string, rating?: ProjectRa
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-for="(projectItem, index) of projectItems"
|
v-for="(projectItem, index) of projectItems.filter((item) => item.rating?.type ? !hiddenColumns?.includes(item.rating.type): true)"
|
||||||
:key="projectItem.label.toString()"
|
:key="projectItem.label.toString()"
|
||||||
hidden
|
hidden
|
||||||
lg:flex
|
lg:flex
|
||||||
|
|
|
@ -28,7 +28,7 @@ function onOptionSelected(value: string | number) {
|
||||||
<div class="relative font-700 font-24px">
|
<div class="relative font-700 font-24px">
|
||||||
<HeadlessListboxButton
|
<HeadlessListboxButton
|
||||||
:id="`headless-listbox-button-${name}`"
|
:id="`headless-listbox-button-${name}`"
|
||||||
class="relative cursor-pointer py-6px px-14px text-left border-2px bg-app-white text-app-black text-xs sm:text-sm sm:leading-6"
|
class="w-full relative cursor-pointer py-6px px-14px text-left border-2px bg-app-white text-app-black text-xs sm:text-sm sm:leading-6"
|
||||||
hover="bg-app-black text-app-white"
|
hover="bg-app-black text-app-white"
|
||||||
transition="all"
|
transition="all"
|
||||||
duration-250
|
duration-250
|
||||||
|
@ -52,7 +52,7 @@ function onOptionSelected(value: string | number) {
|
||||||
leave-to-class="opacity-0"
|
leave-to-class="opacity-0"
|
||||||
>
|
>
|
||||||
<HeadlessListboxOptions
|
<HeadlessListboxOptions
|
||||||
class="absolute z-100 max-h-60 w-auto border-2px border-t-0 overflow-auto bg-app-black text-app-white focus:outline-none sm:text-sm"
|
class="absolute z-100 max-h-60 w-fit border-2px border-t-0 overflow-auto bg-app-black text-app-white focus:outline-none sm:text-sm"
|
||||||
>
|
>
|
||||||
<HeadlessListboxOption
|
<HeadlessListboxOption
|
||||||
v-for="option in props.options"
|
v-for="option in props.options"
|
||||||
|
|
|
@ -3,7 +3,7 @@ const isHovered = ref(false)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div app-container>
|
<div w-full>
|
||||||
<div mt-48px>
|
<div mt-48px>
|
||||||
<hr
|
<hr
|
||||||
border-t-2px
|
border-t-2px
|
||||||
|
@ -13,7 +13,8 @@ const isHovered = ref(false)
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
p-24px
|
app-container
|
||||||
|
pt-24px
|
||||||
pb-8px
|
pb-8px
|
||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
|
@ -121,8 +122,8 @@ const isHovered = ref(false)
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
app-container
|
||||||
text="14px sm:16px"
|
text="14px sm:16px"
|
||||||
px-24px
|
|
||||||
grid
|
grid
|
||||||
grid-cols-2
|
grid-cols-2
|
||||||
sm:grid-cols-3
|
sm:grid-cols-3
|
||||||
|
@ -196,7 +197,7 @@ const isHovered = ref(false)
|
||||||
w-full
|
w-full
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
px-24px
|
app-container
|
||||||
my-16px
|
my-16px
|
||||||
sm:mt-32px
|
sm:mt-32px
|
||||||
flex
|
flex
|
||||||
|
|
|
@ -19,6 +19,7 @@ const isProjectDetailRoute = computed(() => {
|
||||||
z-100
|
z-100
|
||||||
bg-black
|
bg-black
|
||||||
overflow-hidden
|
overflow-hidden
|
||||||
|
border="b-1px white/20"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
relative
|
relative
|
||||||
|
@ -28,7 +29,7 @@ const isProjectDetailRoute = computed(() => {
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
absolute
|
absolute
|
||||||
lg="left--30px"
|
lg="left-10px"
|
||||||
left--30px
|
left--30px
|
||||||
top--25px
|
top--25px
|
||||||
z-101
|
z-101
|
||||||
|
|
|
@ -15,6 +15,7 @@ const totalProjectsCount = props.projects.map(g => g.projects.length).reduce((a,
|
||||||
items-start
|
items-start
|
||||||
>
|
>
|
||||||
<ProjectGridGroup
|
<ProjectGridGroup
|
||||||
|
my-24px lg:my-32px
|
||||||
v-for="group in projects"
|
v-for="group in projects"
|
||||||
:key="group.title"
|
:key="group.title"
|
||||||
:group="group"
|
:group="group"
|
||||||
|
|
|
@ -46,7 +46,18 @@ const shownProjects = computed(() => props.group.projects.slice(0, shownProjects
|
||||||
@click="groupCollapsed = !groupCollapsed"
|
@click="groupCollapsed = !groupCollapsed"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ProjectGridGroupSort v-if="!groupCollapsed" />
|
<ClientOnly>
|
||||||
|
<ProjectGridGroupSort
|
||||||
|
v-if="!groupCollapsed"
|
||||||
|
:hidden-columns="group.title === 'Social & Communications' ? ['technology'] : []"
|
||||||
|
/>
|
||||||
|
<template #fallback>
|
||||||
|
<div
|
||||||
|
h-48px
|
||||||
|
w-full
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</ClientOnly>
|
||||||
<div
|
<div
|
||||||
v-if="!groupCollapsed"
|
v-if="!groupCollapsed"
|
||||||
grid
|
grid
|
||||||
|
@ -61,6 +72,7 @@ const shownProjects = computed(() => props.group.projects.slice(0, shownProjects
|
||||||
<Card
|
<Card
|
||||||
v-for="project in group.projects.slice(0, shownProjectsCount)"
|
v-for="project in group.projects.slice(0, shownProjectsCount)"
|
||||||
:key="project.id"
|
:key="project.id"
|
||||||
|
:hidden-columns="group.title === 'Social & Communications' ? ['technology'] : []"
|
||||||
:project="project"
|
:project="project"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -79,9 +91,11 @@ const shownProjects = computed(() => props.group.projects.slice(0, shownProjects
|
||||||
text="12px lg:14px"
|
text="12px lg:14px"
|
||||||
leading="24px lg:32px"
|
leading="24px lg:32px"
|
||||||
font-bold
|
font-bold
|
||||||
pt-16px
|
mt-24px
|
||||||
pb-24px
|
px-16px
|
||||||
|
py-4px
|
||||||
text-app-text-grey
|
text-app-text-grey
|
||||||
|
border="2px white/50"
|
||||||
@click="shownProjectsCount += 15"
|
@click="shownProjectsCount += 15"
|
||||||
>
|
>
|
||||||
LOAD MORE
|
LOAD MORE
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
const props = defineProps<{
|
||||||
|
hiddenColumns?: string[]
|
||||||
|
}>()
|
||||||
|
|
||||||
const { filter } = storeToRefs(useData())
|
const { filter } = storeToRefs(useData())
|
||||||
|
|
||||||
function onChangeSort(sortKey: string) {
|
function onChangeSort(sortKey: string) {
|
||||||
|
@ -15,6 +19,10 @@ function onChangeSort(sortKey: string) {
|
||||||
filter.value.sortDirection = sortKey === 'score' ? 'desc' : 'asc'
|
filter.value.sortDirection = sortKey === 'score' ? 'desc' : 'asc'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(filter, () => {
|
||||||
|
console.log(filter.value)
|
||||||
|
}, { deep: true })
|
||||||
|
|
||||||
const cardTitles = ref< { label: string, sortKey: string, togglable?: boolean }[]>([
|
const cardTitles = ref< { label: string, sortKey: string, togglable?: boolean }[]>([
|
||||||
{ label: 'Usecase', sortKey: 'usecase' },
|
{ label: 'Usecase', sortKey: 'usecase' },
|
||||||
{ label: 'Openess', sortKey: 'openess', togglable: true },
|
{ label: 'Openess', sortKey: 'openess', togglable: true },
|
||||||
|
@ -24,12 +32,21 @@ const cardTitles = ref< { label: string, sortKey: string, togglable?: boolean }[
|
||||||
{ label: 'Links', sortKey: 'links' },
|
{ label: 'Links', sortKey: 'links' },
|
||||||
{ label: 'W3PN Score', sortKey: 'score', togglable: true },
|
{ label: 'W3PN Score', sortKey: 'score', togglable: true },
|
||||||
])
|
])
|
||||||
|
|
||||||
|
const { width } = useWindowSize()
|
||||||
|
const visibleColumnsCount = computed(() => {
|
||||||
|
if (width.value >= 1024)
|
||||||
|
return cardTitles.value.filter(title => !props.hiddenColumns?.includes(title.sortKey)).length + 3
|
||||||
|
else {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
grid
|
grid
|
||||||
grid-cols="2 lg:10"
|
:style="`grid-template-columns: repeat(${visibleColumnsCount}, 1fr)`"
|
||||||
w-full
|
w-full
|
||||||
mb-16px
|
mb-16px
|
||||||
>
|
>
|
||||||
|
@ -76,7 +93,7 @@ const cardTitles = ref< { label: string, sortKey: string, togglable?: boolean }[
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-for="(title, index) in cardTitles"
|
v-for="(title, index) in cardTitles.filter((title) => !hiddenColumns?.includes(title.sortKey))"
|
||||||
:key="title.label"
|
:key="title.label"
|
||||||
lg:flex
|
lg:flex
|
||||||
items-center
|
items-center
|
||||||
|
@ -100,8 +117,8 @@ const cardTitles = ref< { label: string, sortKey: string, togglable?: boolean }[
|
||||||
<button
|
<button
|
||||||
v-if="title.togglable"
|
v-if="title.togglable"
|
||||||
type="button"
|
type="button"
|
||||||
:class="[title.sortKey === filter.sortby ? filter.sortDirection === 'desc' ? 'i-ic-baseline-arrow-drop-up'
|
:class="[title.sortKey === filter.sortby ? filter.sortDirection === 'desc' ? 'i-ic-baseline-arrow-drop-down'
|
||||||
: 'i-ic-baseline-arrow-drop-down'
|
: 'i-ic-baseline-arrow-drop-up'
|
||||||
: 'i-ic-baseline-arrow-drop-down']"
|
: 'i-ic-baseline-arrow-drop-down']"
|
||||||
text-24px
|
text-24px
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -114,10 +114,9 @@ const logo = props.project?.logos?.at(0)?.url
|
||||||
flex
|
flex
|
||||||
justify-center
|
justify-center
|
||||||
lg:grid
|
lg:grid
|
||||||
grid-cols-10
|
grid-cols-8
|
||||||
w-full
|
w-full
|
||||||
items-center
|
items-center
|
||||||
mt-4px
|
|
||||||
>
|
>
|
||||||
<h2
|
<h2
|
||||||
hidden
|
hidden
|
||||||
|
@ -126,10 +125,10 @@ const logo = props.project?.logos?.at(0)?.url
|
||||||
Usecases:
|
Usecases:
|
||||||
</h2>
|
</h2>
|
||||||
<p
|
<p
|
||||||
mt-8px
|
mb-8px
|
||||||
mb-16px
|
lg="mb-0 mt-0"
|
||||||
text-app-white
|
text-app-white
|
||||||
col-span-9
|
col-span-7
|
||||||
>
|
>
|
||||||
{{ projectUsecases }}
|
{{ projectUsecases }}
|
||||||
</p>
|
</p>
|
||||||
|
@ -143,15 +142,13 @@ const logo = props.project?.logos?.at(0)?.url
|
||||||
order-3
|
order-3
|
||||||
lg:order-2
|
lg:order-2
|
||||||
w-full
|
w-full
|
||||||
md:ml-0px
|
|
||||||
ml-18px
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
flex
|
flex
|
||||||
flex-col
|
flex-col
|
||||||
gap-4px
|
gap-4px
|
||||||
lg:grid
|
lg:grid
|
||||||
lg:grid-cols-10
|
lg:grid-cols-8
|
||||||
lg:items-center
|
lg:items-center
|
||||||
w-full
|
w-full
|
||||||
>
|
>
|
||||||
|
@ -160,7 +157,7 @@ const logo = props.project?.logos?.at(0)?.url
|
||||||
</h2>
|
</h2>
|
||||||
<p
|
<p
|
||||||
text-app-white
|
text-app-white
|
||||||
col-span-9
|
col-span-7
|
||||||
>
|
>
|
||||||
{{ projectCategories }}
|
{{ projectCategories }}
|
||||||
</p>
|
</p>
|
||||||
|
@ -170,7 +167,7 @@ const logo = props.project?.logos?.at(0)?.url
|
||||||
flex-col
|
flex-col
|
||||||
gap-4px
|
gap-4px
|
||||||
lg:grid
|
lg:grid
|
||||||
lg:grid-cols-10
|
lg:grid-cols-8
|
||||||
lg:items-center
|
lg:items-center
|
||||||
w-full
|
w-full
|
||||||
>
|
>
|
||||||
|
@ -179,7 +176,7 @@ const logo = props.project?.logos?.at(0)?.url
|
||||||
</h2>
|
</h2>
|
||||||
<p
|
<p
|
||||||
text-app-white
|
text-app-white
|
||||||
col-span-9
|
col-span-7
|
||||||
>
|
>
|
||||||
{{ projectEcosystems }}
|
{{ projectEcosystems }}
|
||||||
</p>
|
</p>
|
||||||
|
@ -192,6 +189,8 @@ const logo = props.project?.logos?.at(0)?.url
|
||||||
items-center
|
items-center
|
||||||
order-2
|
order-2
|
||||||
lg:order-3
|
lg:order-3
|
||||||
|
lg:ml-0
|
||||||
|
ml--12px
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
flex
|
flex
|
||||||
|
|
|
@ -30,19 +30,13 @@ const props = defineProps<{
|
||||||
v-for="member in members"
|
v-for="member in members"
|
||||||
:key="member.name"
|
:key="member.name"
|
||||||
>
|
>
|
||||||
<div
|
<NuxtLink
|
||||||
|
:to="member.link"
|
||||||
|
target="_blank"
|
||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
gap-12px
|
gap-12px
|
||||||
>
|
>
|
||||||
<!-- <template v-if="member.link">
|
|
||||||
<NuxtImg
|
|
||||||
:src="member.link"
|
|
||||||
width="48"
|
|
||||||
height="48"
|
|
||||||
:alt="member.name"
|
|
||||||
/>
|
|
||||||
</template> -->
|
|
||||||
<div
|
<div
|
||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
|
@ -67,7 +61,7 @@ const props = defineProps<{
|
||||||
font-700
|
font-700
|
||||||
>{{ member.name }}</span>
|
>{{ member.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</NuxtLink>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
|
|
@ -14,7 +14,7 @@ const props = defineProps<{
|
||||||
const emits = defineEmits(['selected'])
|
const emits = defineEmits(['selected'])
|
||||||
|
|
||||||
const colors = [
|
const colors = [
|
||||||
'#EA171D', // 0-10%
|
'#EA171D', // 1-10%
|
||||||
'#FB2D00', // 11-20%
|
'#FB2D00', // 11-20%
|
||||||
'#FD6515', // 21-30%
|
'#FD6515', // 21-30%
|
||||||
'#FD941A', // 31-40%
|
'#FD941A', // 31-40%
|
||||||
|
@ -29,6 +29,8 @@ const colors = [
|
||||||
const backgroundColorByScore = computed(() => {
|
const backgroundColorByScore = computed(() => {
|
||||||
if (props.percentage === 100)
|
if (props.percentage === 100)
|
||||||
return '#42FF00'
|
return '#42FF00'
|
||||||
|
if (props.percentage === 0)
|
||||||
|
return '#494949'
|
||||||
const normalizedPercentage = Math.min(Math.max(props.percentage, 0), 100)
|
const normalizedPercentage = Math.min(Math.max(props.percentage, 0), 100)
|
||||||
const colorIndex = Math.floor(normalizedPercentage / 10)
|
const colorIndex = Math.floor(normalizedPercentage / 10)
|
||||||
return colors[colorIndex]
|
return colors[colorIndex]
|
||||||
|
|
|
@ -61,10 +61,16 @@ export const useData = defineStore('data', () => {
|
||||||
ranks: Rank[]
|
ranks: Rank[]
|
||||||
}>('/api/data')
|
}>('/api/data')
|
||||||
data.projects.forEach(project => project.ratings = generateProjectRating(project))
|
data.projects.forEach(project => project.ratings = generateProjectRating(project))
|
||||||
projects.value = data.projects.map(project => ({
|
projects.value = data.projects.map((project) => {
|
||||||
...project,
|
const totalPoints = project.ratings?.reduce((a, b) => a + b.percentagePoints, 0) || 0
|
||||||
percentage: Math.round((project.ratings?.reduce((a, b) => a + b.points, 0) || 0) / 1.5),
|
const numberOfRatings = project.ratings?.length || 1 // Avoid division by zero
|
||||||
})).filter(p => p.name)
|
const averagePercentage = totalPoints / numberOfRatings
|
||||||
|
return {
|
||||||
|
...project,
|
||||||
|
percentage: Math.min(Math.max(Math.round(averagePercentage), 0), 100), // Ensure within 0-100%
|
||||||
|
}
|
||||||
|
}).filter(p => p.name)
|
||||||
|
console.log(projects.value.filter(p => p.name === 'ETHBerlin'))
|
||||||
const projectCategories = projects.value.map(p => p.categories).flat()
|
const projectCategories = projects.value.map(p => p.categories).flat()
|
||||||
categories.value = data.categories.filter(c => projectCategories.includes(c.id))
|
categories.value = data.categories.filter(c => projectCategories.includes(c.id))
|
||||||
usecases.value = data.usecases
|
usecases.value = data.usecases
|
||||||
|
@ -72,7 +78,6 @@ export const useData = defineStore('data', () => {
|
||||||
assets.value = data.assets
|
assets.value = data.assets
|
||||||
features.value = data.features
|
features.value = data.features
|
||||||
ranks.value = data.ranks
|
ranks.value = data.ranks
|
||||||
|
|
||||||
projectPhase.value = data.phases?.map(p => ({ id: p.id.toLowerCase(), name: p.name }))
|
projectPhase.value = data.phases?.map(p => ({ id: p.id.toLowerCase(), name: p.name }))
|
||||||
assetCustody.value = data.custodys.map(a => ({ id: a.id.toLowerCase(), name: a.name }))
|
assetCustody.value = data.custodys.map(a => ({ id: a.id.toLowerCase(), name: a.name }))
|
||||||
signInRequirments.value = data.requirements.map(s => ({ id: s.id.toLowerCase(), name: s.name }))
|
signInRequirments.value = data.requirements.map(s => ({ id: s.id.toLowerCase(), name: s.name }))
|
||||||
|
@ -173,9 +178,6 @@ export const useData = defineStore('data', () => {
|
||||||
case 'live-on-mainnet':
|
case 'live-on-mainnet':
|
||||||
return project.project_phase === 'mainnet'
|
return project.project_phase === 'mainnet'
|
||||||
}
|
}
|
||||||
// const features = project.technology?.features?.map(f => f.toLowerCase()) || []
|
|
||||||
// if (!features.includes(selectedFeature))
|
|
||||||
// return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -191,7 +193,7 @@ export const useData = defineStore('data', () => {
|
||||||
if (!projects.value) return []
|
if (!projects.value) return []
|
||||||
|
|
||||||
const query = filter.query.toLowerCase()
|
const query = filter.query.toLowerCase()
|
||||||
const sortDirection = filter.sortDirection === 'asc' ? 1 : -1
|
const sortDirection = filter.sortDirection === 'desc' ? 1 : -1
|
||||||
const sortBy = filter.sortby
|
const sortBy = filter.sortby
|
||||||
|
|
||||||
const filteredShallowProjects = getProjectsByFilters({ shallow: true })
|
const filteredShallowProjects = getProjectsByFilters({ shallow: true })
|
||||||
|
@ -200,10 +202,11 @@ export const useData = defineStore('data', () => {
|
||||||
})
|
})
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
if (sortBy === 'score') {
|
if (sortBy === 'score') {
|
||||||
return sortDirection * (a.percentage - b.percentage)
|
return sortDirection * (b.percentage - a.percentage)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sortBy === 'title') {
|
if (sortBy === 'title') {
|
||||||
|
// sortDirection is reversed because the default sort is descending
|
||||||
return sortDirection * a.title1.toLowerCase().localeCompare(b.title1.toLowerCase())
|
return sortDirection * a.title1.toLowerCase().localeCompare(b.title1.toLowerCase())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,11 +251,17 @@ export const useData = defineStore('data', () => {
|
||||||
const projectRatings: ProjectRating[] = ranks.value?.map((rank) => {
|
const projectRatings: ProjectRating[] = ranks.value?.map((rank) => {
|
||||||
let rankPoints = 0
|
let rankPoints = 0
|
||||||
let maxPoints = 0
|
let maxPoints = 0
|
||||||
|
const ratingStats: ProjectRatingItem[] = []
|
||||||
|
|
||||||
const ratingStats: ProjectRatingItem[] = rank.references?.map((ref) => {
|
rank.references?.forEach((ref) => {
|
||||||
let isValid = false
|
let isValid = false
|
||||||
const field = ref.field.includes('.') ? getNestedField(project, ref.field) : project[ref.field]
|
const field = ref.field.includes('.') ? getNestedField(project, ref.field) : project[ref.field]
|
||||||
|
|
||||||
|
// adds only one valid social link
|
||||||
|
if (ref.label.positive === 'Link' && ref.label.name !== 'Documentation')
|
||||||
|
if (ratingStats.some(r => r.positive === 'Link' && r.label !== 'Documentation' && r.value) || !field)
|
||||||
|
return
|
||||||
|
|
||||||
let value
|
let value
|
||||||
let positive
|
let positive
|
||||||
let negative
|
let negative
|
||||||
|
@ -285,14 +294,15 @@ export const useData = defineStore('data', () => {
|
||||||
rankPoints += isValid ? ref.points : 0
|
rankPoints += isValid ? ref.points : 0
|
||||||
maxPoints += ref.points
|
maxPoints += ref.points
|
||||||
|
|
||||||
return {
|
ratingStats.push({
|
||||||
isValid,
|
isValid,
|
||||||
label: ref.label.name,
|
label: ref.label.name,
|
||||||
positive: positive ? positive : ref.label.positive,
|
positive: positive ? positive : ref.label.positive,
|
||||||
negative: negative ? negative : ref.label.negative,
|
negative: negative ? negative : ref.label.negative,
|
||||||
value,
|
value,
|
||||||
} as ProjectRatingItem
|
} as ProjectRatingItem)
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: rank.id,
|
type: rank.id,
|
||||||
name: rank.name,
|
name: rank.name,
|
||||||
|
|
|
@ -81,10 +81,10 @@ watch([scrollY, top, y], (newValues, oldValues) => {
|
||||||
md:justify-between
|
md:justify-between
|
||||||
md:items-center
|
md:items-center
|
||||||
gap-16px
|
gap-16px
|
||||||
mb="16px md:32px"
|
|
||||||
>
|
>
|
||||||
<SearchBox
|
<SearchBox
|
||||||
flex-1
|
flex-1
|
||||||
|
class="w-full lg:max-w-1/3"
|
||||||
placeholder:text-app-text-grey
|
placeholder:text-app-text-grey
|
||||||
:placeholder="`Search in ${filteredProjectsCount} Projects`"
|
:placeholder="`Search in ${filteredProjectsCount} Projects`"
|
||||||
/>
|
/>
|
||||||
|
@ -98,7 +98,7 @@ watch([scrollY, top, y], (newValues, oldValues) => {
|
||||||
pb-274px
|
pb-274px
|
||||||
mb--250px
|
mb--250px
|
||||||
md="overflow-x-visible pb-0 mb-0"
|
md="overflow-x-visible pb-0 mb-0"
|
||||||
class="no-scrollbar"
|
class="no-scrollbar lg:w-full lg:max-w-2/3"
|
||||||
>
|
>
|
||||||
<CategorySelectBox
|
<CategorySelectBox
|
||||||
v-model="selectedCategoryId"
|
v-model="selectedCategoryId"
|
||||||
|
|
|
@ -34,13 +34,12 @@ useSeoMeta({
|
||||||
<div v-if="project">
|
<div v-if="project">
|
||||||
<div
|
<div
|
||||||
app-container
|
app-container
|
||||||
px-16px
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
flex
|
flex
|
||||||
flex-col
|
flex-col
|
||||||
gap-48px
|
gap-48px
|
||||||
mt-54px
|
mt-32px
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { collections } from './unocss.config.collections'
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
shortcuts: [
|
shortcuts: [
|
||||||
{
|
{
|
||||||
'app-container': 'px-12px sm:px-1.5rem max-w-1140px 2xl:max-w-1400px m-auto w-full',
|
'app-container': 'px-24px sm:px-1.5rem max-w-1140px 2xl:max-w-1400px m-auto w-full',
|
||||||
'custom-link': 'text-app-text-grey hover:underline underline-offset-4px text-18px font-400 leading-32px cursor-pointer',
|
'custom-link': 'text-app-text-grey hover:underline underline-offset-4px text-18px font-400 leading-32px cursor-pointer',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue