Merge pull request #52 from web3privacy/dw/bug-fixes

Polishing v2
This commit is contained in:
MufCZ 2024-10-03 16:47:50 +02:00 committed by GitHub
commit 120744e9bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 103 additions and 56 deletions

View file

@ -3,6 +3,7 @@ import type { ProjectRating, ProjectShallow } from '~/types'
const props = defineProps<{
project: ProjectShallow
hiddenColumns?: string[]
}>()
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 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 { 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>
<template>
@ -25,7 +34,7 @@ const projectItems: { label: string | string[], type: string, rating?: ProjectRa
>
<div
grid
grid-cols="2 lg:10"
:style="`grid-template-columns: repeat(${visibleColumnsCount}, 1fr)`"
w-full
>
@ -89,7 +98,7 @@ const projectItems: { label: string | string[], type: string, rating?: ProjectRa
</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()"
hidden
lg:flex

View file

@ -28,7 +28,7 @@ function onOptionSelected(value: string | number) {
<div class="relative font-700 font-24px">
<HeadlessListboxButton
: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"
transition="all"
duration-250
@ -52,7 +52,7 @@ function onOptionSelected(value: string | number) {
leave-to-class="opacity-0"
>
<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
v-for="option in props.options"

View file

@ -3,7 +3,7 @@ const isHovered = ref(false)
</script>
<template>
<div app-container>
<div w-full>
<div mt-48px>
<hr
border-t-2px
@ -13,7 +13,8 @@ const isHovered = ref(false)
>
</div>
<div
p-24px
app-container
pt-24px
pb-8px
flex
items-center
@ -121,8 +122,8 @@ const isHovered = ref(false)
</div>
</div>
<div
app-container
text="14px sm:16px"
px-24px
grid
grid-cols-2
sm:grid-cols-3
@ -196,7 +197,7 @@ const isHovered = ref(false)
w-full
>
<div
px-24px
app-container
my-16px
sm:mt-32px
flex

View file

@ -19,6 +19,7 @@ const isProjectDetailRoute = computed(() => {
z-100
bg-black
overflow-hidden
border="b-1px white/20"
>
<div
relative
@ -28,7 +29,7 @@ const isProjectDetailRoute = computed(() => {
>
<img
absolute
lg="left--30px"
lg="left-10px"
left--30px
top--25px
z-101

View file

@ -15,6 +15,7 @@ const totalProjectsCount = props.projects.map(g => g.projects.length).reduce((a,
items-start
>
<ProjectGridGroup
my-24px lg:my-32px
v-for="group in projects"
:key="group.title"
:group="group"

View file

@ -46,7 +46,18 @@ const shownProjects = computed(() => props.group.projects.slice(0, shownProjects
@click="groupCollapsed = !groupCollapsed"
/>
</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
v-if="!groupCollapsed"
grid
@ -61,6 +72,7 @@ const shownProjects = computed(() => props.group.projects.slice(0, shownProjects
<Card
v-for="project in group.projects.slice(0, shownProjectsCount)"
:key="project.id"
:hidden-columns="group.title === 'Social & Communications' ? ['technology'] : []"
:project="project"
/>
@ -79,9 +91,11 @@ const shownProjects = computed(() => props.group.projects.slice(0, shownProjects
text="12px lg:14px"
leading="24px lg:32px"
font-bold
pt-16px
pb-24px
mt-24px
px-16px
py-4px
text-app-text-grey
border="2px white/50"
@click="shownProjectsCount += 15"
>
LOAD MORE

View file

@ -1,4 +1,8 @@
<script lang="ts" setup>
const props = defineProps<{
hiddenColumns?: string[]
}>()
const { filter } = storeToRefs(useData())
function onChangeSort(sortKey: string) {
@ -15,6 +19,10 @@ function onChangeSort(sortKey: string) {
filter.value.sortDirection = sortKey === 'score' ? 'desc' : 'asc'
}
watch(filter, () => {
console.log(filter.value)
}, { deep: true })
const cardTitles = ref< { label: string, sortKey: string, togglable?: boolean }[]>([
{ label: 'Usecase', sortKey: 'usecase' },
{ label: 'Openess', sortKey: 'openess', togglable: true },
@ -24,12 +32,21 @@ const cardTitles = ref< { label: string, sortKey: string, togglable?: boolean }[
{ label: 'Links', sortKey: 'links' },
{ 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>
<template>
<div
grid
grid-cols="2 lg:10"
:style="`grid-template-columns: repeat(${visibleColumnsCount}, 1fr)`"
w-full
mb-16px
>
@ -76,7 +93,7 @@ const cardTitles = ref< { label: string, sortKey: string, togglable?: boolean }[
/>
</div>
<div
v-for="(title, index) in cardTitles"
v-for="(title, index) in cardTitles.filter((title) => !hiddenColumns?.includes(title.sortKey))"
:key="title.label"
lg:flex
items-center
@ -100,8 +117,8 @@ const cardTitles = ref< { label: string, sortKey: string, togglable?: boolean }[
<button
v-if="title.togglable"
type="button"
:class="[title.sortKey === filter.sortby ? filter.sortDirection === 'desc' ? 'i-ic-baseline-arrow-drop-up'
: 'i-ic-baseline-arrow-drop-down'
:class="[title.sortKey === filter.sortby ? filter.sortDirection === 'desc' ? 'i-ic-baseline-arrow-drop-down'
: 'i-ic-baseline-arrow-drop-up'
: 'i-ic-baseline-arrow-drop-down']"
text-24px
/>

View file

@ -114,10 +114,9 @@ const logo = props.project?.logos?.at(0)?.url
flex
justify-center
lg:grid
grid-cols-10
grid-cols-8
w-full
items-center
mt-4px
>
<h2
hidden
@ -126,10 +125,10 @@ const logo = props.project?.logos?.at(0)?.url
Usecases:
</h2>
<p
mt-8px
mb-16px
mb-8px
lg="mb-0 mt-0"
text-app-white
col-span-9
col-span-7
>
{{ projectUsecases }}
</p>
@ -143,15 +142,13 @@ const logo = props.project?.logos?.at(0)?.url
order-3
lg:order-2
w-full
md:ml-0px
ml-18px
>
<div
flex
flex-col
gap-4px
lg:grid
lg:grid-cols-10
lg:grid-cols-8
lg:items-center
w-full
>
@ -160,7 +157,7 @@ const logo = props.project?.logos?.at(0)?.url
</h2>
<p
text-app-white
col-span-9
col-span-7
>
{{ projectCategories }}
</p>
@ -170,7 +167,7 @@ const logo = props.project?.logos?.at(0)?.url
flex-col
gap-4px
lg:grid
lg:grid-cols-10
lg:grid-cols-8
lg:items-center
w-full
>
@ -179,7 +176,7 @@ const logo = props.project?.logos?.at(0)?.url
</h2>
<p
text-app-white
col-span-9
col-span-7
>
{{ projectEcosystems }}
</p>
@ -192,6 +189,8 @@ const logo = props.project?.logos?.at(0)?.url
items-center
order-2
lg:order-3
lg:ml-0
ml--12px
>
<div
flex

View file

@ -30,19 +30,13 @@ const props = defineProps<{
v-for="member in members"
:key="member.name"
>
<div
<NuxtLink
:to="member.link"
target="_blank"
flex
items-center
gap-12px
>
<!-- <template v-if="member.link">
<NuxtImg
:src="member.link"
width="48"
height="48"
:alt="member.name"
/>
</template> -->
<div
flex
items-center
@ -67,7 +61,7 @@ const props = defineProps<{
font-700
>{{ member.name }}</span>
</div>
</div>
</NuxtLink>
</template>
</template>
<template v-else>

View file

@ -14,7 +14,7 @@ const props = defineProps<{
const emits = defineEmits(['selected'])
const colors = [
'#EA171D', // 0-10%
'#EA171D', // 1-10%
'#FB2D00', // 11-20%
'#FD6515', // 21-30%
'#FD941A', // 31-40%
@ -29,6 +29,8 @@ const colors = [
const backgroundColorByScore = computed(() => {
if (props.percentage === 100)
return '#42FF00'
if (props.percentage === 0)
return '#494949'
const normalizedPercentage = Math.min(Math.max(props.percentage, 0), 100)
const colorIndex = Math.floor(normalizedPercentage / 10)
return colors[colorIndex]

View file

@ -61,10 +61,16 @@ export const useData = defineStore('data', () => {
ranks: Rank[]
}>('/api/data')
data.projects.forEach(project => project.ratings = generateProjectRating(project))
projects.value = data.projects.map(project => ({
projects.value = data.projects.map((project) => {
const totalPoints = project.ratings?.reduce((a, b) => a + b.percentagePoints, 0) || 0
const numberOfRatings = project.ratings?.length || 1 // Avoid division by zero
const averagePercentage = totalPoints / numberOfRatings
return {
...project,
percentage: Math.round((project.ratings?.reduce((a, b) => a + b.points, 0) || 0) / 1.5),
})).filter(p => p.name)
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()
categories.value = data.categories.filter(c => projectCategories.includes(c.id))
usecases.value = data.usecases
@ -72,7 +78,6 @@ export const useData = defineStore('data', () => {
assets.value = data.assets
features.value = data.features
ranks.value = data.ranks
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 }))
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':
return project.project_phase === 'mainnet'
}
// const features = project.technology?.features?.map(f => f.toLowerCase()) || []
// if (!features.includes(selectedFeature))
// return false
}
return true
@ -191,7 +193,7 @@ export const useData = defineStore('data', () => {
if (!projects.value) return []
const query = filter.query.toLowerCase()
const sortDirection = filter.sortDirection === 'asc' ? 1 : -1
const sortDirection = filter.sortDirection === 'desc' ? 1 : -1
const sortBy = filter.sortby
const filteredShallowProjects = getProjectsByFilters({ shallow: true })
@ -200,10 +202,11 @@ export const useData = defineStore('data', () => {
})
.sort((a, b) => {
if (sortBy === 'score') {
return sortDirection * (a.percentage - b.percentage)
return sortDirection * (b.percentage - a.percentage)
}
if (sortBy === 'title') {
// sortDirection is reversed because the default sort is descending
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) => {
let rankPoints = 0
let maxPoints = 0
const ratingStats: ProjectRatingItem[] = []
const ratingStats: ProjectRatingItem[] = rank.references?.map((ref) => {
rank.references?.forEach((ref) => {
let isValid = false
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 positive
let negative
@ -285,14 +294,15 @@ export const useData = defineStore('data', () => {
rankPoints += isValid ? ref.points : 0
maxPoints += ref.points
return {
ratingStats.push({
isValid,
label: ref.label.name,
positive: positive ? positive : ref.label.positive,
negative: negative ? negative : ref.label.negative,
value,
} as ProjectRatingItem
} as ProjectRatingItem)
})
return {
type: rank.id,
name: rank.name,

View file

@ -81,10 +81,10 @@ watch([scrollY, top, y], (newValues, oldValues) => {
md:justify-between
md:items-center
gap-16px
mb="16px md:32px"
>
<SearchBox
flex-1
class="w-full lg:max-w-1/3"
placeholder:text-app-text-grey
:placeholder="`Search in ${filteredProjectsCount} Projects`"
/>
@ -98,7 +98,7 @@ watch([scrollY, top, y], (newValues, oldValues) => {
pb-274px
mb--250px
md="overflow-x-visible pb-0 mb-0"
class="no-scrollbar"
class="no-scrollbar lg:w-full lg:max-w-2/3"
>
<CategorySelectBox
v-model="selectedCategoryId"

View file

@ -34,13 +34,12 @@ useSeoMeta({
<div v-if="project">
<div
app-container
px-16px
>
<div
flex
flex-col
gap-48px
mt-54px
mt-32px
>
<div>
<div>

View file

@ -10,7 +10,7 @@ import { collections } from './unocss.config.collections'
export default defineConfig({
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',
},
{