mirror of
https://github.com/web3privacy/explorer-app.git
synced 2024-10-15 16:46:26 +02:00
Merge remote-tracking branch 'origin/v3' into dw/form
This commit is contained in:
commit
0f9c57a6bc
45 changed files with 1980 additions and 1364 deletions
91
.github/workflows/ci.yml
vendored
91
.github/workflows/ci.yml
vendored
|
@ -1,77 +1,38 @@
|
||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches: [main, v3]
|
||||||
- main
|
|
||||||
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches: [main, v3]
|
||||||
- main
|
|
||||||
- dev
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
codechecks:
|
codechecks:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- name: Checkout the repository
|
||||||
- uses: pnpm/action-setup@v2
|
uses: actions/checkout@v4
|
||||||
- uses: actions/cache@v2
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.pnpm-store
|
run_install: false
|
||||||
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
- name: Install Node.js 20
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20.x
|
||||||
|
cache: pnpm
|
||||||
|
- name: Enable Corepack
|
||||||
|
run: corepack enable
|
||||||
|
- name: Get pnpm store directory
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||||
|
- name: Cache the pnpm lock file
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ${{ env.STORE_PATH }}
|
||||||
|
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-pnpm-
|
${{ runner.os }}-pnpm-store-
|
||||||
- name: Install Dependencies
|
- name: Install package dependencies
|
||||||
run: pnpm install
|
run: pnpm install
|
||||||
- name: Typecheck
|
- name: Lint the code
|
||||||
run: pnpm run typecheck
|
|
||||||
- name: Lint
|
|
||||||
run: pnpm run lint
|
run: pnpm run lint
|
||||||
|
|
||||||
# build:
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
# steps:
|
|
||||||
# - uses: actions/checkout@v3
|
|
||||||
# - uses: pnpm/action-setup@v2
|
|
||||||
# - uses: actions/setup-node@v3
|
|
||||||
# with:
|
|
||||||
# node-version: 16.x
|
|
||||||
# cache: pnpm
|
|
||||||
|
|
||||||
# - name: Install
|
|
||||||
# run: pnpm install
|
|
||||||
|
|
||||||
# - name: Build
|
|
||||||
# run: pnpm run build
|
|
||||||
|
|
||||||
# test-e2e:
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
# steps:
|
|
||||||
# - uses: actions/checkout@v3
|
|
||||||
# - uses: actions/cache@v3
|
|
||||||
# with:
|
|
||||||
# path: |
|
|
||||||
# ~/.cache
|
|
||||||
# key: cypress-cache-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
|
||||||
|
|
||||||
# - uses: pnpm/action-setup@v2
|
|
||||||
|
|
||||||
# - uses: pnpm/action-setup@v2
|
|
||||||
# - uses: actions/setup-node@v3
|
|
||||||
# with:
|
|
||||||
# node-version: 16.x
|
|
||||||
# cache: pnpm
|
|
||||||
|
|
||||||
# - name: Install
|
|
||||||
# run: pnpm install
|
|
||||||
|
|
||||||
# - name: Cypress PNPM Patch
|
|
||||||
# run: cp pnpm-lock.yaml package-lock.json
|
|
||||||
|
|
||||||
# - name: Cypress [Hub]
|
|
||||||
# uses: cypress-io/github-action@v4
|
|
||||||
# with:
|
|
||||||
# install-command: echo
|
|
||||||
# build: pnpm hub:generate
|
|
||||||
# start: pnpm hub:preview
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export default defineAppConfig({
|
export default defineAppConfig({
|
||||||
github: {
|
github: {
|
||||||
appId: null,
|
appId: 0,
|
||||||
privateKey: '',
|
privateKey: '',
|
||||||
installationId: null,
|
installationId: 0,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { ProjectShallow } from '~/types'
|
import type { ProjectRating, ProjectShallow } from '~/types'
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
project: ProjectShallow
|
project: ProjectShallow
|
||||||
}>()
|
}>()
|
||||||
const { switcher } = storeToRefs(useData())
|
const { switcher, ecosystems } = storeToRefs(useData())
|
||||||
|
|
||||||
|
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' }]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -18,230 +22,179 @@ const { switcher } = storeToRefs(useData())
|
||||||
transition-all
|
transition-all
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
relative
|
grid
|
||||||
max-w="96px lg:200px"
|
grid-cols="2 lg:10"
|
||||||
w-full
|
w-full
|
||||||
h="96px lg:200px"
|
|
||||||
:class="switcher ? '' : 'lg:max-w-full! lg:w-full '"
|
|
||||||
>
|
>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
col-span="1 lg:2"
|
||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
justify-center
|
gap="12px lg:16px"
|
||||||
|
relative
|
||||||
w-full
|
w-full
|
||||||
my-auto
|
|
||||||
h-full
|
h-full
|
||||||
|
h="48px lg:64px"
|
||||||
|
:class="switcher ? '' : 'lg:max-w-full! lg:w-full '"
|
||||||
>
|
>
|
||||||
<NuxtImg
|
<NuxtImg
|
||||||
:src="project?.image || '/no-image-1-1.svg'"
|
:src="project?.image || '/no-image-1-1.svg'"
|
||||||
class="w-full h-auto"
|
class="w-full h-auto"
|
||||||
max-h="md:196px 96px"
|
max-h="md:64px 48px"
|
||||||
|
max-w="md:64px 48px"
|
||||||
self-center
|
self-center
|
||||||
z-10
|
z-10
|
||||||
object-fit
|
object-fit
|
||||||
bg="#121212"
|
bg="#121212"
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-y-4px
|
||||||
|
lg:flex-row
|
||||||
|
justify-center
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
w-fit
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
gap-8px
|
||||||
|
@click.prevent="navigateTo(project.website, { external: true, open: { target: '_blank' } })"
|
||||||
|
>
|
||||||
|
<h1
|
||||||
|
text="14px app-white"
|
||||||
|
font-700
|
||||||
|
line-clamp-1
|
||||||
|
hover:underline
|
||||||
|
underline-offset-3
|
||||||
|
leading="20px lg:32px"
|
||||||
|
>
|
||||||
|
{{ project.title1 }}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<p
|
||||||
|
text-12px
|
||||||
|
leading-16px
|
||||||
|
lg:hidden
|
||||||
|
>
|
||||||
|
{{ project.usecases?.join(', ') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<Badge
|
|
||||||
v-if="project.percentage"
|
|
||||||
absolute
|
|
||||||
bottom-0.5
|
|
||||||
lg:bottom-0
|
|
||||||
right-0.5
|
|
||||||
lg:right-0
|
|
||||||
mr-2px
|
|
||||||
mb-2px
|
|
||||||
:text="`${project.percentage}%`"
|
|
||||||
class="leading-12px! text-12px! lg:text-18px! border-0!"
|
|
||||||
px="4px! lg:16px!"
|
|
||||||
py="4px! lg:8px!"
|
|
||||||
/>
|
|
||||||
</ClientOnly>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
h="96px lg:200px"
|
|
||||||
lg:py-24px
|
|
||||||
lg:pr-24px
|
|
||||||
flex
|
|
||||||
flex-col
|
|
||||||
justify-center
|
|
||||||
lg:justify-between
|
|
||||||
lg:gap-24px
|
|
||||||
w-full
|
|
||||||
text-white
|
|
||||||
:class="switcher ? '' : 'lg:p-16px! lg:py-16px!'"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
w-full
|
|
||||||
h-fit
|
|
||||||
flex
|
|
||||||
flex-col
|
|
||||||
gap-8px
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
w-fit
|
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
gap-8px
|
|
||||||
@click.prevent="navigateTo(project.website, { external: true, open: { target: '_blank' } })"
|
|
||||||
>
|
|
||||||
<h1
|
|
||||||
text="18px lg:24px app-white"
|
|
||||||
font-700
|
|
||||||
line-clamp-1
|
|
||||||
hover:underline
|
|
||||||
underline-offset-3
|
|
||||||
>
|
|
||||||
{{ project.title1 }}
|
|
||||||
</h1>
|
|
||||||
<UnoIcon
|
|
||||||
i-web-open
|
|
||||||
text-16px
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<h2
|
|
||||||
text="14px app-text-grey"
|
|
||||||
overflow-hidden
|
|
||||||
text-ellipsis
|
|
||||||
line-clamp-2
|
|
||||||
lg:line-clamp-2
|
|
||||||
>
|
|
||||||
{{ project.description }}
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
w-full
|
|
||||||
flex
|
|
||||||
justify-between
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
w-full
|
|
||||||
max-w-692px
|
|
||||||
grid
|
|
||||||
whitespace-nowrap
|
|
||||||
:class="switcher ? 'grid-cols-5' : 'grid-cols-3'"
|
|
||||||
gap-24px
|
|
||||||
lg:grid
|
|
||||||
hidden
|
|
||||||
>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project?.github"
|
|
||||||
:link="project?.github"
|
|
||||||
title="Github"
|
|
||||||
bold
|
|
||||||
text-size="18px"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
gap-8px
|
|
||||||
>
|
|
||||||
<UnoIcon
|
|
||||||
i-web-github
|
|
||||||
text-16px
|
|
||||||
/>
|
|
||||||
<span>{{ project?.github ? 'YES' : 'NO' }}</span>
|
|
||||||
</div>
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.readyness"
|
|
||||||
title="Readyness"
|
|
||||||
text-size="18px"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
gap-12px
|
|
||||||
>
|
|
||||||
<UnoIcon
|
|
||||||
i-web-live
|
|
||||||
text-10px
|
|
||||||
:class="(project.readyness === 'Mainnet') ? 'color-#18FF2F' : (project.readyness === 'Testnet') ? 'color-#FFA800' : (project.readyness === 'Alpha') ? 'color-#FF0000' : ''"
|
|
||||||
/>
|
|
||||||
<span :class="(project.readyness === 'Alpha') ? 'color-#FFA800' : 'color-white'">{{ project.readyness }}</span>
|
|
||||||
</div>
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="true"
|
|
||||||
title="Team"
|
|
||||||
text-size="18px"
|
|
||||||
>
|
|
||||||
<span v-if="project.team?.length">{{ `${project.team?.length} members` }}</span>
|
|
||||||
<span
|
|
||||||
v-else
|
|
||||||
color="#FF0000"
|
|
||||||
>{{ 'Anonymous' }}</span>
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project?.docs"
|
|
||||||
:link="project?.docs"
|
|
||||||
:color="project?.docs ? '#18FF2F' : '#FF0000'"
|
|
||||||
title="Docs"
|
|
||||||
bold
|
|
||||||
text-size="18px"
|
|
||||||
>
|
|
||||||
{{ project?.docs ? 'YES' : 'NO' }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.audits"
|
|
||||||
:link="project?.audits?.[0]?.link ?? undefined"
|
|
||||||
:color="project?.audits ? '#18FF2F' : '#FF0000'"
|
|
||||||
title="Audit"
|
|
||||||
bold
|
|
||||||
text-size="18px"
|
|
||||||
>
|
|
||||||
{{ project.audits ? 'YES' : 'NO' }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
|
v-for="(projectItem, index) of projectItems"
|
||||||
|
:key="projectItem.label.toString()"
|
||||||
hidden
|
hidden
|
||||||
lg:flex
|
lg:flex
|
||||||
items-center
|
items-center
|
||||||
|
text-14px
|
||||||
|
leading-24px
|
||||||
|
:class="{ 'col-span-1 lg:col-span-2': index === 0 }"
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
v-if="projectItem.type === 'array'"
|
||||||
|
text-app-text-grey
|
||||||
|
>
|
||||||
|
{{ (projectItem.label as string[] || []).join(', ') }}
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
v-if="projectItem.type === 'links'"
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
justify-start
|
||||||
|
gap-16px
|
||||||
|
>
|
||||||
|
<NuxtLink
|
||||||
|
v-if="projectItem.label[1]"
|
||||||
|
:to="projectItem.label[1]"
|
||||||
|
external
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<UnoIcon
|
||||||
|
i-ic-baseline-language
|
||||||
|
text="24px app-text-grey"
|
||||||
|
/>
|
||||||
|
</NuxtLink>
|
||||||
|
<NuxtLink
|
||||||
|
v-if="projectItem.label[2]"
|
||||||
|
:to="projectItem.label[2]"
|
||||||
|
external
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<UnoIcon
|
||||||
|
i-mdi-github
|
||||||
|
text="24px app-text-grey"
|
||||||
|
text-27px
|
||||||
|
/>
|
||||||
|
</NuxtLink>
|
||||||
|
<NuxtLink
|
||||||
|
v-if="projectItem.label[0]"
|
||||||
|
:to="projectItem.label[0]"
|
||||||
|
external
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<UnoIcon
|
||||||
|
i-bi-twitter-x
|
||||||
|
text="24px app-text-grey"
|
||||||
|
/>
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="projectItem.type === 'ecosystem'"
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
justify-start
|
||||||
|
gap-2px
|
||||||
|
>
|
||||||
|
<NuxtImg
|
||||||
|
v-for="ecosystem of projectItem.label"
|
||||||
|
:key="ecosystem"
|
||||||
|
:src="ecosystem"
|
||||||
|
w-24px
|
||||||
|
h-24px
|
||||||
|
rounded-full
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ProjectRating
|
||||||
|
v-if="projectItem.type! === 'rating' && projectItem.rating"
|
||||||
|
:percentage="projectItem.rating.points"
|
||||||
|
:rating="projectItem.rating"
|
||||||
|
:type="projectItem.rating.type"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
justify-end
|
||||||
|
w-full
|
||||||
gap-16px
|
gap-16px
|
||||||
>
|
>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
v-if="project.forum"
|
block
|
||||||
i-web-forum
|
lg:hidden
|
||||||
text-28px
|
i-iconoir-internet
|
||||||
opacity-50
|
text="24px"
|
||||||
hover:opacity-100
|
|
||||||
@click.prevent="navigateTo(project.forum, { external: true, open: { target: '_blank' } })"
|
|
||||||
/>
|
|
||||||
<UnoIcon
|
|
||||||
v-if="project.explorer"
|
|
||||||
i-web-explorer
|
|
||||||
text-32px
|
|
||||||
opacity-50
|
|
||||||
hover:opacity-100
|
|
||||||
@click.prevent="navigateTo(project.explorer, { external: true, open: { target: '_blank' } })"
|
|
||||||
/>
|
|
||||||
<UnoIcon
|
|
||||||
v-if="project.twitter"
|
|
||||||
i-web-twitter_x
|
|
||||||
text-22px
|
|
||||||
opacity-50
|
|
||||||
hover:opacity-100
|
|
||||||
@click.prevent="navigateTo(project.twitter, { external: true, open: { target: '_blank' } })"
|
|
||||||
/>
|
|
||||||
<UnoIcon
|
|
||||||
v-if="project.coingecko"
|
|
||||||
i-web-coingecko
|
|
||||||
text-24px
|
|
||||||
opacity-50
|
|
||||||
hover:opacity-100
|
|
||||||
@click.prevent="navigateTo(project.coingecko, { external: true, open: { target: '_blank' } })"
|
|
||||||
/>
|
|
||||||
<UnoIcon
|
|
||||||
v-if="project.newsletter"
|
|
||||||
i-web-news
|
|
||||||
text-28px
|
|
||||||
opacity-50
|
|
||||||
hover:opacity-100
|
|
||||||
@click.prevent="navigateTo(project.newsletter, { external: true, open: { target: '_blank' } })"
|
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
justify-center
|
||||||
|
border="2px app-white"
|
||||||
|
text="14px md:18px"
|
||||||
|
leading="24px md:32px"
|
||||||
|
max-h-="28px md:32px"
|
||||||
|
max-w="48px md:56px"
|
||||||
|
w-full
|
||||||
|
font-700
|
||||||
|
whitespace-nowrap
|
||||||
|
>
|
||||||
|
{{ project.percentage }} %
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -3,8 +3,9 @@ import type { InputOption } from '~/types'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
options: InputOption[]
|
options: InputOption[]
|
||||||
modelValue: string
|
modelValue: string | number
|
||||||
count?: number
|
count?: number
|
||||||
|
titleShowCount?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emits = defineEmits(['update:modelValue', 'selected'])
|
const emits = defineEmits(['update:modelValue', 'selected'])
|
||||||
|
@ -13,7 +14,7 @@ const selectedValue = useVModel(props, 'modelValue', emits)
|
||||||
const isOptionSelected = computed(() => {
|
const isOptionSelected = computed(() => {
|
||||||
return props.options.find(option => option.value === selectedValue.value)
|
return props.options.find(option => option.value === selectedValue.value)
|
||||||
})
|
})
|
||||||
function onOptionSelected(value: string) {
|
function onOptionSelected(value: string | number) {
|
||||||
emits('selected', value)
|
emits('selected', value)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -23,15 +24,18 @@ function onOptionSelected(value: string) {
|
||||||
v-model="selectedValue"
|
v-model="selectedValue"
|
||||||
as="div"
|
as="div"
|
||||||
>
|
>
|
||||||
<div class="relative mt-2 font-700 font-24px">
|
<div class="relative font-700 font-24px">
|
||||||
<HeadlessListboxButton
|
<HeadlessListboxButton
|
||||||
class="relative w-full cursor-pointer py-8px p-16px text-left border-2px text-app-white sm:text-sm sm:leading-6"
|
class="relative cursor-pointer py-6px px-14px text-left border-2px bg-app-white text-app-black sm:text-sm sm:leading-6"
|
||||||
>
|
>
|
||||||
<span class="block truncate mr-8px">{{ isOptionSelected?.label }} <span v-if="isOptionSelected?.count" opacity-50>({{ isOptionSelected?.count }})</span></span>
|
<span class="block truncate mr-8px font">{{ isOptionSelected?.label }} <span
|
||||||
|
v-if="titleShowCount"
|
||||||
|
opacity-50
|
||||||
|
>({{ isOptionSelected?.count }})</span></span>
|
||||||
<span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
|
<span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-heroicons-solid-chevron-down
|
i-ic-baseline-arrow-drop-down
|
||||||
text-app-white
|
text-app-black
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</HeadlessListboxButton>
|
</HeadlessListboxButton>
|
||||||
|
@ -42,7 +46,7 @@ function onOptionSelected(value: string) {
|
||||||
leave-to-class="opacity-0"
|
leave-to-class="opacity-0"
|
||||||
>
|
>
|
||||||
<HeadlessListboxOptions
|
<HeadlessListboxOptions
|
||||||
class="absolute z-100 max-h-60 w-full divide-y-2px 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-auto 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"
|
||||||
|
@ -53,15 +57,18 @@ function onOptionSelected(value: string) {
|
||||||
@click="onOptionSelected(option.value)"
|
@click="onOptionSelected(option.value)"
|
||||||
>
|
>
|
||||||
<li
|
<li
|
||||||
class="w-full relative cursor-pointer select-none py-8px p-16px"
|
class="w-full relative cursor-pointer select-none py-8px p-16px bg-app-black text-app-white"
|
||||||
:class="[active ? 'bg-#ffffff1a' : 'text-white']"
|
:class="[active ? 'text-app-white' : 'text-app-white']"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="block truncate"
|
class="block truncate"
|
||||||
:class="[selected ? 'font-semibold' : 'font-normal']"
|
:class="[selected ? 'font-semibold' : 'font-normal']"
|
||||||
>
|
>
|
||||||
{{ option.label }}
|
{{ option.label }}
|
||||||
<span v-if="option.count" opacity-50>({{ option.count }})</span>
|
<span
|
||||||
|
v-if="titleShowCount"
|
||||||
|
opacity-50
|
||||||
|
>({{ option.count }})</span>
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
</HeadlessListboxOption>
|
</HeadlessListboxOption>
|
||||||
|
|
|
@ -13,6 +13,7 @@ defineProps<{
|
||||||
>
|
>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-heroicons-solid-pencil
|
i-heroicons-solid-pencil
|
||||||
|
text-app-text-grey
|
||||||
text-24px
|
text-24px
|
||||||
/>
|
/>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
|
@ -44,7 +44,7 @@ function useTokens(project?: Partial<Project>) {
|
||||||
const { tokens, newToken, addToken, removeToken } = useTokens(props.project)
|
const { tokens, newToken, addToken, removeToken } = useTokens(props.project)
|
||||||
const assetsUsed = ref<string[]>(Array.isArray(props.project?.assets_used) ? props.project?.assets_used.map(a => a.toLowerCase()) : [])
|
const assetsUsed = ref<string[]>(Array.isArray(props.project?.assets_used) ? props.project?.assets_used.map(a => a.toLowerCase()) : [])
|
||||||
|
|
||||||
const { assetsData } = useData()
|
const { assets: assetsData } = useData()
|
||||||
const { saveProject } = useProject()
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
|
|
|
@ -6,7 +6,7 @@ const props = defineProps<{
|
||||||
project?: Partial<Project>
|
project?: Partial<Project>
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { categoriesData, usecasesData, ecosystemsData } = useData()
|
const { categories: categoriesData, usecases: usecasesData, ecosystems: ecosystemsData } = useData()
|
||||||
const { saveProject } = useProject()
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
const validationSchema = yup.object().shape({
|
const validationSchema = yup.object().shape({
|
||||||
|
|
|
@ -13,7 +13,7 @@ const signRequirements = ref(Array.isArray(props.project?.tracebility?.sign_in_t
|
||||||
const trackedData = ref(props.project?.tracebility?.tracked_data || '')
|
const trackedData = ref(props.project?.tracebility?.tracked_data || '')
|
||||||
const dataUsage = ref(props.project?.privacy_policy?.data_usage || '')
|
const dataUsage = ref(props.project?.privacy_policy?.data_usage || '')
|
||||||
|
|
||||||
const { signInRequirmentsData } = useData()
|
const { signInRequirments: signInRequirmentsData } = useData()
|
||||||
const { saveProject } = useProject()
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
|
|
|
@ -13,7 +13,7 @@ const encryption = ref(props.project?.blockchain_features?.encryption || '')
|
||||||
const peerToPeer = ref(props.project?.blockchain_features?.p2p)
|
const peerToPeer = ref(props.project?.blockchain_features?.p2p)
|
||||||
const decentralizedStorage = ref(props.project?.storage?.decentralized)
|
const decentralizedStorage = ref(props.project?.storage?.decentralized)
|
||||||
|
|
||||||
const { projectPhaseData, assetCustodyData } = useData()
|
const { projectPhase: projectPhaseData, assetCustody: assetCustodyData } = useData()
|
||||||
const { saveProject } = useProject()
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
|
|
|
@ -23,11 +23,12 @@ defineProps<{
|
||||||
>
|
>
|
||||||
<div mt-32px>
|
<div mt-32px>
|
||||||
<ProjectActivityLaunch
|
<ProjectActivityLaunch
|
||||||
v-if="project.history"
|
v-for="launch in project.history"
|
||||||
:network="project.history?.title"
|
:key="launch.title"
|
||||||
:date="project.history?.time"
|
:network="launch.title"
|
||||||
:launch-type="project.history?.description"
|
:date="launch.time"
|
||||||
:to="project.history?.link"
|
:launch-type="launch.description"
|
||||||
|
:to="launch.link"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -20,9 +20,6 @@ defineProps<{
|
||||||
gap-8px
|
gap-8px
|
||||||
text-16px
|
text-16px
|
||||||
font-700
|
font-700
|
||||||
lg:max-w-320px
|
|
||||||
lg:w-full
|
|
||||||
lg:justify-end
|
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
<div
|
<div
|
||||||
hidden
|
hidden
|
||||||
w-full
|
w-full
|
||||||
max-w-320px
|
|
||||||
lg:block
|
|
||||||
/>
|
/>
|
||||||
<div w-full>
|
<div w-full>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
|
@ -2,15 +2,35 @@
|
||||||
import type { ProjectShallow } from '~/types'
|
import type { ProjectShallow } from '~/types'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
projects: ProjectShallow[]
|
projects: { title: string, projects: ProjectShallow[] }[]
|
||||||
}>()
|
}>()
|
||||||
const { switcher } = storeToRefs(useData())
|
const { switcher, filter } = storeToRefs(useData())
|
||||||
|
|
||||||
const displayCount = ref(100)
|
const totalProjectsCount = props.projects.map(g => g.projects.length).reduce((a, b) => a + b, 0)
|
||||||
const displayedProjects = computed(() => props.projects.slice(0, displayCount.value))
|
|
||||||
function showMoreProjects() {
|
function onChangeSort(sortKey: string) {
|
||||||
displayCount.value += 50
|
if (filter.value.sortby === sortKey) {
|
||||||
|
if (filter.value.sortDirection === 'desc' && filter.value.sortby !== 'score') {
|
||||||
|
filter.value.sortby = 'score'
|
||||||
|
filter.value.sortDirection = 'desc'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
filter.value.sortDirection = filter.value.sortDirection === 'asc' ? 'desc' : 'asc'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
filter.value.sortby = sortKey
|
||||||
|
filter.value.sortDirection = sortKey === 'score' ? 'desc' : 'asc'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cardTitles = ref< { label: string, sortKey: string, togglable?: boolean }[]>([
|
||||||
|
{ label: 'Usecase', sortKey: 'usecase' },
|
||||||
|
{ label: 'Openess', sortKey: 'openess', togglable: true },
|
||||||
|
{ label: 'Technology', sortKey: 'technology', togglable: true },
|
||||||
|
{ label: 'Privacy', sortKey: 'privacy', togglable: true },
|
||||||
|
{ label: 'Ecosystem', sortKey: 'ecosystem' },
|
||||||
|
{ label: 'Links', sortKey: 'links' },
|
||||||
|
{ label: 'W3PN Score', sortKey: 'score', togglable: true },
|
||||||
|
])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -19,36 +39,138 @@ function showMoreProjects() {
|
||||||
flex-col
|
flex-col
|
||||||
items-start
|
items-start
|
||||||
>
|
>
|
||||||
<div
|
<template
|
||||||
v-if="displayedProjects.length"
|
v-for="group in projects"
|
||||||
grid
|
:key="group.title"
|
||||||
:class="switcher ? 'grid-cols-1 lg:grid-cols-1' : 'xl:grid-cols-3 lg:grid-cols-3 sm:grid-cols-2 grid-cols-1'"
|
|
||||||
gap-16px
|
|
||||||
text-white
|
|
||||||
w-full
|
|
||||||
>
|
>
|
||||||
<Card
|
<div
|
||||||
v-for="project in displayedProjects"
|
|
||||||
:key="project.id"
|
flex
|
||||||
:project="project"
|
items-center
|
||||||
/>
|
gap-x-12px
|
||||||
</div>
|
w-full
|
||||||
<div v-else>
|
mb="8px lg:16px"
|
||||||
|
mt-22px
|
||||||
|
>
|
||||||
|
<h2
|
||||||
|
text="app-white 16px lg:24px"
|
||||||
|
font-700
|
||||||
|
leading="24px lg:32px"
|
||||||
|
whitespace-nowrap
|
||||||
|
>
|
||||||
|
{{ group.projects.length }} {{ group.title }}
|
||||||
|
</h2>
|
||||||
|
<div
|
||||||
|
h-2px
|
||||||
|
w-full
|
||||||
|
bg-app-text-grey
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
i-ic-baseline-arrow-drop-down
|
||||||
|
text="app-text-grey 24px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
grid
|
||||||
|
grid-cols="2 lg:10"
|
||||||
|
w-full
|
||||||
|
mb-16px
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
gap-4px
|
||||||
|
col-span="1 lg:2"
|
||||||
|
:class="['title' === filter.sortby ? 'text-app-white' : 'text-app-text-grey', 'cursor-pointer']"
|
||||||
|
@click="onChangeSort('title')"
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
text="12px lg:14px"
|
||||||
|
leading="16px lg:24px"
|
||||||
|
whitespace-nowrap
|
||||||
|
>
|
||||||
|
Project name
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
:class="['title' === filter.sortby ? filter.sortDirection === 'desc' ? 'i-ic-baseline-arrow-drop-up'
|
||||||
|
: 'i-ic-baseline-arrow-drop-down'
|
||||||
|
: 'i-ic-baseline-arrow-drop-down']"
|
||||||
|
text="20px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
justify-end
|
||||||
|
gap-4px
|
||||||
|
lg:hidden
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
text="12px lg:14px app-text-grey"
|
||||||
|
leading="16px lg:24px"
|
||||||
|
>
|
||||||
|
Sort by:
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
text="12px lg:14px"
|
||||||
|
leading="16px lg:24px"
|
||||||
|
font-700
|
||||||
|
>
|
||||||
|
Score
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
i-ic-baseline-arrow-drop-down
|
||||||
|
text="app-text-grey 20px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="(title, index) in cardTitles"
|
||||||
|
:key="title.label"
|
||||||
|
lg:flex
|
||||||
|
items-center
|
||||||
|
justify-start
|
||||||
|
last:justify-end
|
||||||
|
gap-4px
|
||||||
|
hidden
|
||||||
|
:class="[title.sortKey === filter.sortby ? 'text-app-white' : 'text-app-text-grey', { 'cursor-pointer': title.togglable, 'col-span-1 lg:col-span-2': index === 0 }]"
|
||||||
|
@click="onChangeSort(title.sortKey)"
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
text="12px lg:14px "
|
||||||
|
leading="16px lg:24px"
|
||||||
|
whitespace-nowrap
|
||||||
|
>
|
||||||
|
{{ title.label }}
|
||||||
|
</p>
|
||||||
|
<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'
|
||||||
|
: 'i-ic-baseline-arrow-drop-down']"
|
||||||
|
text=" 20px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
grid
|
||||||
|
:class="switcher ? 'grid-cols-1 lg:grid-cols-1' : 'xl:grid-cols-3 lg:grid-cols-3 sm:grid-cols-2 grid-cols-1'"
|
||||||
|
gap-16px
|
||||||
|
text-white
|
||||||
|
w-full
|
||||||
|
>
|
||||||
|
<Card
|
||||||
|
v-for="project in group.projects"
|
||||||
|
:key="project.id"
|
||||||
|
:project="project"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div v-if="totalProjectsCount === 0">
|
||||||
<h3>No Projects found...</h3>
|
<h3>No Projects found...</h3>
|
||||||
</div>
|
</div>
|
||||||
<button
|
|
||||||
v-if="displayedProjects.length < projects.length"
|
|
||||||
mt-29px
|
|
||||||
text="14px"
|
|
||||||
leading-24px
|
|
||||||
font-700
|
|
||||||
px-12px
|
|
||||||
py-4px
|
|
||||||
border-2px
|
|
||||||
border-app-white
|
|
||||||
@click="showMoreProjects"
|
|
||||||
>
|
|
||||||
Load more projects
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { Project, ProjectIndexable } from '~/types'
|
import type { Project } from '~/types'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
project: Project
|
project: Project
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const availableSupport = computed(() => {
|
// const availableSupport = computed(() => {
|
||||||
const filteredKeys = ['forum', 'discord', 'twitter', 'lens', 'farcaster', 'telegram']
|
// const filteredKeys = ['forum', 'discord', 'twitter', 'lens', 'farcaster', 'telegram']
|
||||||
if (typeof props.project.links === 'object' && (props.project.links !== null || props.project.links !== undefined))
|
// if (typeof props.project.links === 'object' && (props.project.links !== null || props.project.links !== undefined))
|
||||||
return Object.keys(props.project.links).filter(key => filteredKeys.includes(key)).length
|
// return Object.keys(props.project.links).filter(key => filteredKeys.includes(key)).length
|
||||||
|
|
||||||
return 0
|
// return 0
|
||||||
})
|
// })
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* From data points
|
* From data points
|
||||||
|
@ -21,78 +21,42 @@ const availableSupport = computed(() => {
|
||||||
- team: anon / public
|
- team: anon / public
|
||||||
- audit: yes / no
|
- audit: yes / no
|
||||||
*/
|
*/
|
||||||
const calculateScore = computed(() => {
|
|
||||||
const criterias: { value: keyof ProjectIndexable, key: keyof ProjectIndexable | '' }[] = [
|
|
||||||
{ value: 'product_readiness', key: '' },
|
|
||||||
{ value: 'github', key: 'links' },
|
|
||||||
{ value: 'docs', key: 'links' },
|
|
||||||
{ value: 'team', key: '' },
|
|
||||||
{ value: 'audits', key: '' },
|
|
||||||
]
|
|
||||||
|
|
||||||
let matched = 0
|
|
||||||
for (let i = 0; i < criterias.length; i++) {
|
|
||||||
let value
|
|
||||||
// value = ((criterias[i].key ?? props.project[criterias[i].value as keyof typeof props.project]) ?? null === null) ? null : (props.project as ProjectIndexable)[criterias[i].key][criterias[i].value]
|
|
||||||
|
|
||||||
const indexableProject = props.project as ProjectIndexable
|
|
||||||
if (criterias[i].key !== '')
|
|
||||||
value = (indexableProject[criterias[i].key] as any)?.[criterias[i].value]
|
|
||||||
else
|
|
||||||
value = indexableProject?.[criterias[i].value]
|
|
||||||
|
|
||||||
if (value === null || value === undefined)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if (fulfilled(value))
|
|
||||||
matched++
|
|
||||||
}
|
|
||||||
|
|
||||||
return 100 / criterias.length * matched
|
|
||||||
})
|
|
||||||
|
|
||||||
function fulfilled(value: any): boolean {
|
|
||||||
const type = typeof value
|
|
||||||
switch (type) {
|
|
||||||
case 'string':
|
|
||||||
if (value !== '')
|
|
||||||
return true
|
|
||||||
break
|
|
||||||
case 'object':
|
|
||||||
if (Object.keys(value!).length > 0)
|
|
||||||
return true
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const logo = props.project?.logos?.at(0)?.url
|
const logo = props.project?.logos?.at(0)?.url
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
lg:flex
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-y-16px
|
||||||
|
lg:flex-row
|
||||||
|
items-center
|
||||||
lg:gap-32px
|
lg:gap-32px
|
||||||
>
|
>
|
||||||
<NuxtImg
|
<NuxtImg
|
||||||
lg:max-w-320px
|
max-w-200px
|
||||||
lg:max-h-320px
|
max-h-200px
|
||||||
shrink
|
shrink
|
||||||
|
border="1px app-text-grey"
|
||||||
:src="logo ?? '/no-image-1-1.svg'"
|
:src="logo ?? '/no-image-1-1.svg'"
|
||||||
class="bg-app-bg-grey object-cover max-w-full h-full vertical-align[middle] block border-0 w-full h-[300px]"
|
class="bg-app-bg-grey object-cover h-full vertical-align[middle] block w-full h-[300px] "
|
||||||
/>
|
/>
|
||||||
<div grow>
|
<div
|
||||||
|
grow
|
||||||
|
w-full
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
flex
|
flex
|
||||||
flex-col
|
flex-col
|
||||||
|
items-center
|
||||||
|
lg:items-start
|
||||||
justify-between
|
justify-between
|
||||||
gap-32px
|
gap-y="lg:12px 24px"
|
||||||
lg:flex-row
|
text-app-text-grey
|
||||||
lg:items-center
|
w-full
|
||||||
>
|
>
|
||||||
<div mt-24px>
|
<div mt-4px>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
:to="project.links?.web"
|
:to="project.links?.web"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
@ -110,139 +74,154 @@ const logo = props.project?.logos?.at(0)?.url
|
||||||
{{ project.name }}
|
{{ project.name }}
|
||||||
</h1>
|
</h1>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-openinnew
|
i-ic-twotone-open-in-new
|
||||||
text-16px
|
text="22px app-white"
|
||||||
/>
|
/>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<h2
|
|
||||||
text="16px app-text-grey"
|
|
||||||
leading-24px
|
|
||||||
mt-8px
|
|
||||||
>
|
|
||||||
{{ project.project_type ?? '---' }}
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
border-2px
|
|
||||||
class="border-app-black bg-app-white text-app-black"
|
|
||||||
flex
|
flex
|
||||||
items-center
|
|
||||||
justify-center
|
justify-center
|
||||||
px-32px
|
lg:grid
|
||||||
py-16px
|
grid-cols-10
|
||||||
text-32px
|
w-full
|
||||||
font-700
|
items-center
|
||||||
leading-40px
|
mt-4px
|
||||||
cursor-pointer
|
|
||||||
>
|
>
|
||||||
{{ `${calculateScore}%` }}
|
<h2
|
||||||
|
hidden
|
||||||
|
lg:block
|
||||||
|
>
|
||||||
|
Usecases:
|
||||||
|
</h2>
|
||||||
|
<p
|
||||||
|
text-app-white
|
||||||
|
col-span-9
|
||||||
|
>
|
||||||
|
Swap, Mixer
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div
|
||||||
<div
|
grid
|
||||||
grid
|
grid-cols-2
|
||||||
grid-cols-2
|
gap-y-12px
|
||||||
gap-16px
|
lg:flex
|
||||||
my-32px
|
lg:flex-col
|
||||||
lg:grid-cols-4
|
order-3
|
||||||
>
|
lg:order-2
|
||||||
<ProjectInfoItem
|
w-full
|
||||||
:check-undefined="project.links?.github"
|
|
||||||
title="Github"
|
|
||||||
bold
|
|
||||||
text-size="18px"
|
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<div
|
||||||
<UnoIcon i-web-code />
|
flex
|
||||||
</template>
|
flex-col
|
||||||
{{ project.links?.github ? 'YES' : 'NO' }}
|
gap-4px
|
||||||
</ProjectInfoItem>
|
lg:grid
|
||||||
<ProjectInfoItem
|
lg:grid-cols-10
|
||||||
:check-undefined="project.project_status?.version"
|
lg:items-center
|
||||||
title="Product readyness"
|
w-full
|
||||||
bold
|
>
|
||||||
text-size="18px"
|
<h2>
|
||||||
|
Categories:
|
||||||
|
</h2>
|
||||||
|
<p
|
||||||
|
text-app-white
|
||||||
|
col-span-9
|
||||||
|
>
|
||||||
|
Dapp, Network
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-4px
|
||||||
|
lg:grid
|
||||||
|
lg:grid-cols-10
|
||||||
|
lg:items-center
|
||||||
|
w-full
|
||||||
|
>
|
||||||
|
<h2>
|
||||||
|
Ecosystems:
|
||||||
|
</h2>
|
||||||
|
<p
|
||||||
|
text-app-white
|
||||||
|
col-span-9
|
||||||
|
>
|
||||||
|
Ethereum, Secret Network
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
grid
|
||||||
|
grid-cols-4
|
||||||
|
w-full
|
||||||
|
items-center
|
||||||
|
order-2
|
||||||
|
lg:order-3
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<div
|
||||||
<UnoIcon i-web-cube />
|
flex
|
||||||
</template>
|
items-center
|
||||||
{{ project.project_status?.version }}
|
justify-between
|
||||||
</ProjectInfoItem>
|
lg:justify-start
|
||||||
<ProjectInfoItem
|
lg:gap-24px
|
||||||
:check-undefined="project.team?.length"
|
col-span-3
|
||||||
title="Team"
|
>
|
||||||
bold
|
<div
|
||||||
text-size="18px"
|
v-for="rating of project.ratings"
|
||||||
>
|
:key="rating.name"
|
||||||
<template #prefix>
|
flex
|
||||||
<UnoIcon i-web-team />
|
flex-col
|
||||||
</template>
|
lg:flex-row
|
||||||
{{ `${project.team?.length} members` }}
|
items-center
|
||||||
</ProjectInfoItem>
|
>
|
||||||
<ProjectInfoItem
|
<p
|
||||||
:check-undefined="project.links?.docs"
|
text="12px lg:16px"
|
||||||
title="Docs"
|
leading="16px lg:24px"
|
||||||
bold
|
>
|
||||||
text-size="18px"
|
{{ rating.name }}:
|
||||||
>
|
</p>
|
||||||
<template #prefix>
|
<ProjectRating
|
||||||
<UnoIcon
|
:rating="rating"
|
||||||
i-web-docs
|
:percentage="rating.points"
|
||||||
text-28px
|
compact
|
||||||
/>
|
/>
|
||||||
</template>
|
</div>
|
||||||
{{ project.links?.docs ? 'YES' : 'NO' }}
|
</div>
|
||||||
</ProjectInfoItem>
|
<div
|
||||||
<ProjectInfoItem
|
flex
|
||||||
:check-undefined="project.audits"
|
items-center
|
||||||
title="Audit"
|
justify-end
|
||||||
bold
|
w-full
|
||||||
text-size="18px"
|
gap-16px
|
||||||
>
|
mt--8px
|
||||||
<template #prefix>
|
lg:mt-0
|
||||||
<UnoIcon
|
>
|
||||||
i-web-audit
|
<h2
|
||||||
text-28px
|
hidden
|
||||||
/>
|
lg:block
|
||||||
</template>
|
>
|
||||||
{{ project.audits ? 'YES' : 'NO' }}
|
Total Score:
|
||||||
</ProjectInfoItem>
|
</h2>
|
||||||
<ProjectInfoItem
|
<div
|
||||||
:check-undefined="project.links"
|
flex
|
||||||
title="Available support"
|
items-center
|
||||||
bold
|
justify-center
|
||||||
text-size="18px"
|
border="2px app-white"
|
||||||
>
|
text="16px lg:24px app-white"
|
||||||
<template #prefix>
|
leading="24px md:32px"
|
||||||
<UnoIcon
|
max-h-="32px md:40px"
|
||||||
i-web-support
|
max-w="84px"
|
||||||
text-28px
|
w-full
|
||||||
/>
|
h-full
|
||||||
</template>
|
font-700
|
||||||
{{ `${availableSupport} channels` }}
|
whitespace-nowrap
|
||||||
</ProjectInfoItem>
|
py="2px lg:8px"
|
||||||
</div>
|
lg:py-4px
|
||||||
<div
|
>
|
||||||
grid
|
{{ calculateScore(project) }} %
|
||||||
grid-cols-2
|
</div>
|
||||||
gap-16px
|
</div>
|
||||||
my-32px
|
</div>
|
||||||
lg:grid-cols-4
|
|
||||||
>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.blockchain_features?.network"
|
|
||||||
tooltip-link="/"
|
|
||||||
title="Ecosystem"
|
|
||||||
bold
|
|
||||||
>
|
|
||||||
{{ project.blockchain_features?.network }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
invisible
|
|
||||||
title="Last update"
|
|
||||||
bold
|
|
||||||
>
|
|
||||||
17/11/2023 – 23:22
|
|
||||||
</ProjectInfoItem>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
36
components/Project/ProjectHistory.vue
Normal file
36
components/Project/ProjectHistory.vue
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { Project } from '~/types'
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
project: Project
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ProjectDetailCategoryDivider
|
||||||
|
title="HISTORY"
|
||||||
|
badge-text="3/10"
|
||||||
|
>
|
||||||
|
<UnoIcon
|
||||||
|
i-material-symbols-calendar-month
|
||||||
|
text-24px
|
||||||
|
/>
|
||||||
|
</ProjectDetailCategoryDivider>
|
||||||
|
<ProjectDetailContainer>
|
||||||
|
<div
|
||||||
|
grid
|
||||||
|
grid-cols-2
|
||||||
|
items-start
|
||||||
|
mt-32px
|
||||||
|
gap-y-16px
|
||||||
|
lg:grid-cols-4
|
||||||
|
>
|
||||||
|
<!-- <ProjectInfoItem
|
||||||
|
:check-undefined="project.history?.time"
|
||||||
|
title="Date of creation"
|
||||||
|
>
|
||||||
|
{{ formatDate(project.history!.time!) }}
|
||||||
|
</ProjectInfoItem> -->
|
||||||
|
</div>
|
||||||
|
</ProjectDetailContainer>
|
||||||
|
</template>
|
|
@ -32,13 +32,6 @@ const route = useRoute()
|
||||||
md:block
|
md:block
|
||||||
>{{ 'BACK TO LIST' }}</span>
|
>{{ 'BACK TO LIST' }}</span>
|
||||||
</NavigationButton>
|
</NavigationButton>
|
||||||
<hr
|
|
||||||
hidden
|
|
||||||
md:block
|
|
||||||
border-t-2px
|
|
||||||
border-white
|
|
||||||
w-full
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
flex
|
flex
|
||||||
gap-16px
|
gap-16px
|
||||||
|
|
|
@ -12,7 +12,7 @@ defineProps<{
|
||||||
badge-text="3/10"
|
badge-text="3/10"
|
||||||
>
|
>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-code_v2
|
i-bi-code-square
|
||||||
text-24px
|
text-24px
|
||||||
/>
|
/>
|
||||||
</ProjectDetailCategoryDivider>
|
</ProjectDetailCategoryDivider>
|
||||||
|
@ -23,25 +23,98 @@ defineProps<{
|
||||||
leading-24px
|
leading-24px
|
||||||
font-400
|
font-400
|
||||||
>
|
>
|
||||||
<h3 text-app-text-grey>
|
<h3
|
||||||
{{ 'Project Description' }}
|
text-app-text-grey
|
||||||
|
mb-8px
|
||||||
|
>
|
||||||
|
Project Description
|
||||||
</h3>
|
</h3>
|
||||||
<span
|
<p
|
||||||
text="14px sm:16px"
|
text="14px sm:16px"
|
||||||
leading-20px
|
leading-20px
|
||||||
>{{ project.description ?? '---' }}</span>
|
>
|
||||||
|
{{ project.description ?? '---' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
grid
|
||||||
|
grid-cols="2 lg:4"
|
||||||
|
mt="24px lg:32px"
|
||||||
|
text="14px lg:16px"
|
||||||
|
gap-y-16px
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<h3
|
||||||
|
text-app-text-grey
|
||||||
|
leading-20px
|
||||||
|
mb="4px lg:8px"
|
||||||
|
>
|
||||||
|
Project Phase
|
||||||
|
</h3>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
gap-8px
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
h-10px
|
||||||
|
w-10px
|
||||||
|
rounded-full
|
||||||
|
bg-green
|
||||||
|
/><p leading="20px lg:24px">
|
||||||
|
Mainnet
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3
|
||||||
|
text-app-text-grey
|
||||||
|
leading-20px
|
||||||
|
mb="4px lg:8px"
|
||||||
|
>
|
||||||
|
Assets used
|
||||||
|
</h3>
|
||||||
|
<p leading="20px lg:24px">
|
||||||
|
ETH, DAI, USDC, FRAX
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3
|
||||||
|
text-app-text-grey
|
||||||
|
leading-20px
|
||||||
|
mb="4px lg:8px"
|
||||||
|
>
|
||||||
|
Native token
|
||||||
|
</h3>
|
||||||
|
<p leading="20px lg:24px">
|
||||||
|
SCRT
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3
|
||||||
|
text-app-text-grey
|
||||||
|
leading-20px
|
||||||
|
mb="4px lg:8px"
|
||||||
|
>
|
||||||
|
Project launch day
|
||||||
|
</h3>
|
||||||
|
<p leading="20px lg:24px">
|
||||||
|
06/2017
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div mt-24px>
|
<div mt-24px>
|
||||||
<h3
|
<h3
|
||||||
text="14px sm:16px app-text-grey"
|
text="14px sm:16px app-text-grey"
|
||||||
leading-20px
|
leading-20px
|
||||||
>
|
>
|
||||||
{{ 'Infrastructure links' }}
|
Infrastructure links:
|
||||||
</h3>
|
</h3>
|
||||||
<div
|
<div
|
||||||
grid
|
grid
|
||||||
grid-cols-2
|
grid-cols-2
|
||||||
gap-16px
|
gap-x-16px
|
||||||
|
gap-y-12px
|
||||||
mt-8px
|
mt-8px
|
||||||
lg:grid-cols-4
|
lg:grid-cols-4
|
||||||
>
|
>
|
||||||
|
@ -50,18 +123,12 @@ defineProps<{
|
||||||
:to="project.links?.web"
|
:to="project.links?.web"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<UnoIcon i-web-website />
|
<UnoIcon
|
||||||
|
i-ic-baseline-language
|
||||||
|
text="24px app-text-grey"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
{{ 'Website' }}
|
Website
|
||||||
</ProjectOpenessLink>
|
|
||||||
<ProjectOpenessLink
|
|
||||||
v-if="project.links?.blog"
|
|
||||||
:to="project.links.blog"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<UnoIcon i-web-website />
|
|
||||||
</template>
|
|
||||||
{{ 'Blog' }}
|
|
||||||
</ProjectOpenessLink>
|
</ProjectOpenessLink>
|
||||||
<ProjectOpenessLink
|
<ProjectOpenessLink
|
||||||
v-if="project.links?.github"
|
v-if="project.links?.github"
|
||||||
|
@ -69,12 +136,25 @@ defineProps<{
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-github
|
i-mdi-github
|
||||||
opacity-30
|
text="24px app-text-grey"
|
||||||
text-27px
|
text-27px
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
{{ 'Github' }}
|
Github
|
||||||
|
</ProjectOpenessLink>
|
||||||
|
<ProjectOpenessLink
|
||||||
|
v-if="project.links?.whitepaper"
|
||||||
|
:to="project.links?.whitepaper"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<UnoIcon
|
||||||
|
i-material-symbols-description
|
||||||
|
text="24px app-text-grey"
|
||||||
|
text-27px
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
Whitepaper
|
||||||
</ProjectOpenessLink>
|
</ProjectOpenessLink>
|
||||||
<ProjectOpenessLink
|
<ProjectOpenessLink
|
||||||
v-if="project.links?.docs"
|
v-if="project.links?.docs"
|
||||||
|
@ -82,11 +162,38 @@ defineProps<{
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-documents
|
i-material-symbols-contract
|
||||||
text-24px
|
text="24px app-text-grey"
|
||||||
|
text-27px
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
{{ 'Docs' }}
|
Docs
|
||||||
|
</ProjectOpenessLink>
|
||||||
|
<ProjectOpenessLink
|
||||||
|
v-if="project.links?.blog"
|
||||||
|
:to="project.links.blog"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<UnoIcon
|
||||||
|
i-material-symbols-newsmode
|
||||||
|
text="24px app-text-grey"
|
||||||
|
text-27px
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
Blog
|
||||||
|
</ProjectOpenessLink>
|
||||||
|
<ProjectOpenessLink
|
||||||
|
v-if="project.links?.forum"
|
||||||
|
:to="project.links.forum"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<UnoIcon
|
||||||
|
i-material-symbols-forum-outline
|
||||||
|
text="24px app-text-grey"
|
||||||
|
text-27px
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
Forum
|
||||||
</ProjectOpenessLink>
|
</ProjectOpenessLink>
|
||||||
<ProjectOpenessLink
|
<ProjectOpenessLink
|
||||||
v-if="project.links?.block_explorer"
|
v-if="project.links?.block_explorer"
|
||||||
|
@ -94,48 +201,25 @@ defineProps<{
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-explorer
|
i-material-symbols-explore-outline
|
||||||
opacity-30
|
text="24px app-text-grey"
|
||||||
|
text-27px
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
{{ 'Explorer' }}
|
Explorer
|
||||||
</ProjectOpenessLink>
|
</ProjectOpenessLink>
|
||||||
<ProjectOpenessLink
|
<ProjectOpenessLink
|
||||||
v-if="project.links?.snapshot"
|
v-if="project.links?.governance"
|
||||||
:to="project.links.snapshot"
|
:to="project.links.governance"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-snapshot
|
i-material-symbols-how-to-vote-outline
|
||||||
text-32px
|
text="24px app-text-grey"
|
||||||
|
text-27px
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
{{ 'Snapshot' }}
|
Governance
|
||||||
</ProjectOpenessLink>
|
|
||||||
<ProjectOpenessLink
|
|
||||||
v-if="project.links?.token"
|
|
||||||
:to="project.links.token"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<UnoIcon
|
|
||||||
i-web-token
|
|
||||||
text-28px
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
{{ 'Token' }}
|
|
||||||
</ProjectOpenessLink>
|
|
||||||
<ProjectOpenessLink
|
|
||||||
v-if="project.links?.coingecko"
|
|
||||||
:to="project.links.coingecko"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<UnoIcon
|
|
||||||
i-web-coingecko
|
|
||||||
opacity-30
|
|
||||||
text-24px
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
{{ 'Coingecko' }}
|
|
||||||
</ProjectOpenessLink>
|
</ProjectOpenessLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -149,22 +233,22 @@ defineProps<{
|
||||||
<div
|
<div
|
||||||
grid
|
grid
|
||||||
grid-cols-2
|
grid-cols-2
|
||||||
gap-16px
|
gap-x-16px
|
||||||
|
gap-y-12px
|
||||||
mt-8px
|
mt-8px
|
||||||
lg:grid-cols-4
|
lg:grid-cols-4
|
||||||
>
|
>
|
||||||
<ProjectOpenessLink
|
<ProjectOpenessLink
|
||||||
v-if="project.links?.forum"
|
v-if="project.links?.twitter"
|
||||||
:to="project.links.forum"
|
:to="project.links.twitter"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-forum
|
i-bi-twitter-x
|
||||||
opacity-30
|
text="24px app-text-grey"
|
||||||
text-28px
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
{{ 'Forum' }}
|
Twitter
|
||||||
</ProjectOpenessLink>
|
</ProjectOpenessLink>
|
||||||
<ProjectOpenessLink
|
<ProjectOpenessLink
|
||||||
v-if="project.links?.discord"
|
v-if="project.links?.discord"
|
||||||
|
@ -172,24 +256,23 @@ defineProps<{
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-discord
|
i-ic-baseline-discord
|
||||||
text-27px
|
text="24px app-text-grey"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
{{ 'Discord' }}
|
Discord
|
||||||
</ProjectOpenessLink>
|
</ProjectOpenessLink>
|
||||||
<ProjectOpenessLink
|
<ProjectOpenessLink
|
||||||
v-if="project.links?.twitter"
|
v-if="project.links?.telegram"
|
||||||
:to="project.links.twitter"
|
:to="project.links.telegram"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-twitter_x
|
i-mdi-telegram
|
||||||
opacity-30
|
text="24px app-text-grey"
|
||||||
text-22px
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
{{ 'Twitter' }}
|
Telegram
|
||||||
</ProjectOpenessLink>
|
</ProjectOpenessLink>
|
||||||
<ProjectOpenessLink
|
<ProjectOpenessLink
|
||||||
v-if="project.links?.lens"
|
v-if="project.links?.lens"
|
||||||
|
@ -198,10 +281,10 @@ defineProps<{
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-lens
|
i-web-lens
|
||||||
text-32px
|
text="24px app-text-grey"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
{{ 'Lens' }}
|
Lens
|
||||||
</ProjectOpenessLink>
|
</ProjectOpenessLink>
|
||||||
<ProjectOpenessLink
|
<ProjectOpenessLink
|
||||||
v-if="project.links?.farcaster"
|
v-if="project.links?.farcaster"
|
||||||
|
@ -210,89 +293,63 @@ defineProps<{
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-farcaster
|
i-web-farcaster
|
||||||
text-26px
|
text="24px app-text-grey"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
{{ 'Farcaster' }}
|
Farcaster
|
||||||
</ProjectOpenessLink>
|
|
||||||
<ProjectOpenessLink
|
|
||||||
v-if="project.links?.telegram"
|
|
||||||
:to="project.links.telegram"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<UnoIcon
|
|
||||||
i-web-telegram
|
|
||||||
opacity-30
|
|
||||||
text-22px
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
{{ 'Telegram' }}
|
|
||||||
</ProjectOpenessLink>
|
</ProjectOpenessLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div mt-24px>
|
<ProjectOpenessTeamMembers
|
||||||
<ProjectOpenessTeamMembers :members="project.team" />
|
v-if="project?.team?.teammembers"
|
||||||
</div>
|
:members="project.team?.teammembers"
|
||||||
<div
|
mt-24px
|
||||||
grid
|
/>
|
||||||
grid-cols-2
|
<div mt-32px>
|
||||||
items-start
|
<h3
|
||||||
mt-32px
|
text="app-text-grey 14px lg:16px"
|
||||||
gap-y-26px
|
leading-24px
|
||||||
lg:grid-cols-4
|
|
||||||
>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.product_launch_day"
|
|
||||||
title="Product launch day"
|
|
||||||
>
|
>
|
||||||
{{ project.product_launch_day }}
|
Funding
|
||||||
</ProjectInfoItem>
|
</h3>
|
||||||
<ProjectInfoItem
|
<div
|
||||||
title="Opensource"
|
v-for="funding of project.funding"
|
||||||
bold
|
:key="funding.name"
|
||||||
:check-undefined="project.blockchain_features?.opensource"
|
flex
|
||||||
:color=" project.blockchain_features?.opensource ? '#A8FF18' : '#FF0000'"
|
items-center
|
||||||
>
|
justify-between
|
||||||
{{ project.blockchain_features?.opensource ? 'Yes' : 'No' }}
|
rounded-full
|
||||||
</ProjectInfoItem>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
mt-32px
|
|
||||||
w-full
|
|
||||||
>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.funding"
|
|
||||||
title="Funding"
|
|
||||||
bold
|
|
||||||
w-full
|
w-full
|
||||||
|
bg-app-bg-funding-card
|
||||||
|
px-24px
|
||||||
|
py-12px
|
||||||
|
mt-12px
|
||||||
>
|
>
|
||||||
<template
|
<h3
|
||||||
v-for="fund in project.funding"
|
text="14px lg:16px"
|
||||||
:key="fund.name"
|
leading="20px lg:24px"
|
||||||
|
font-700
|
||||||
>
|
>
|
||||||
<div
|
{{ funding.name }}
|
||||||
mt-16px
|
</h3>
|
||||||
grid
|
<NuxtLink
|
||||||
grid-cols-2
|
:to="funding.link"
|
||||||
sm:grid-cols-4
|
external
|
||||||
>
|
target="_blank"
|
||||||
<span v-if="fund.name">{{ fund.name }}</span>
|
>
|
||||||
<span
|
<UnoIcon
|
||||||
v-if="fund.time"
|
i-ic-twotone-open-in-new
|
||||||
font-400
|
text="22px app-text-grey"
|
||||||
>{{ fund.time }}</span>
|
/>
|
||||||
<span
|
</NuxtLink>
|
||||||
v-if="fund.time"
|
</div>
|
||||||
font-400
|
<h3
|
||||||
text-app-text-grey
|
v-if="!project.funding?.length"
|
||||||
>{{ fund.type }}</span>
|
text="app-text-grey 14px lg:16px"
|
||||||
<span
|
leading-24px
|
||||||
v-if="fund.time"
|
>
|
||||||
font-400
|
N/A
|
||||||
>{{ fund.value }}</span>
|
</h3>
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</ProjectInfoItem>
|
|
||||||
</div>
|
</div>
|
||||||
</ProjectDetailContainer>
|
</ProjectDetailContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
members: {
|
members: {
|
||||||
name: string
|
name?: string
|
||||||
role?: string
|
role?: string
|
||||||
link?: string
|
link?: string
|
||||||
}[] | undefined
|
}[] | undefined
|
||||||
|
@ -32,58 +32,32 @@ const props = defineProps<{
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
flex
|
flex
|
||||||
|
items-center
|
||||||
gap-12px
|
gap-12px
|
||||||
>
|
>
|
||||||
<template v-if="member.link">
|
<!-- <template v-if="member.link">
|
||||||
<NuxtImg
|
<NuxtImg
|
||||||
:src="member.link"
|
:src="member.link"
|
||||||
width="48"
|
width="48"
|
||||||
height="48"
|
height="48"
|
||||||
:alt="member.name"
|
:alt="member.name"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template> -->
|
||||||
<template v-else>
|
<div
|
||||||
<svg
|
flex
|
||||||
width="48"
|
items-center
|
||||||
height="48"
|
justify-center
|
||||||
viewBox="0 0 48 48"
|
text-black
|
||||||
fill="none"
|
w="40px lg:48px"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
h="40px lg:48px"
|
||||||
>
|
rounded-full
|
||||||
<circle
|
bg-app-bg-team-grey
|
||||||
opacity="0.2"
|
>
|
||||||
cx="24"
|
<div
|
||||||
cy="24"
|
i-heroicons-solid-user
|
||||||
r="23.5"
|
text-24px
|
||||||
stroke="white"
|
/>
|
||||||
/>
|
</div>
|
||||||
<g opacity="0.2">
|
|
||||||
<mask
|
|
||||||
id="mask0_2200_7716"
|
|
||||||
style="mask-type:alpha"
|
|
||||||
maskUnits="userSpaceOnUse"
|
|
||||||
x="12"
|
|
||||||
y="12"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
>
|
|
||||||
<rect
|
|
||||||
x="12"
|
|
||||||
y="12"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
fill="#D9D9D9"
|
|
||||||
/>
|
|
||||||
</mask>
|
|
||||||
<g mask="url(#mask0_2200_7716)">
|
|
||||||
<path
|
|
||||||
d="M24 24C22.9 24 21.9583 23.6083 21.175 22.825C20.3917 22.0417 20 21.1 20 20C20 18.9 20.3917 17.9583 21.175 17.175C21.9583 16.3917 22.9 16 24 16C25.1 16 26.0417 16.3917 26.825 17.175C27.6083 17.9583 28 18.9 28 20C28 21.1 27.6083 22.0417 26.825 22.825C26.0417 23.6083 25.1 24 24 24ZM16 32V29.2C16 28.6333 16.1458 28.1125 16.4375 27.6375C16.7292 27.1625 17.1167 26.8 17.6 26.55C18.6333 26.0333 19.6833 25.6458 20.75 25.3875C21.8167 25.1292 22.9 25 24 25C25.1 25 26.1833 25.1292 27.25 25.3875C28.3167 25.6458 29.3667 26.0333 30.4 26.55C30.8833 26.8 31.2708 27.1625 31.5625 27.6375C31.8542 28.1125 32 28.6333 32 29.2V32H16Z"
|
|
||||||
fill="white"
|
|
||||||
/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
||||||
<div
|
<div
|
||||||
flex
|
flex
|
||||||
flex-col
|
flex-col
|
||||||
|
@ -92,10 +66,6 @@ const props = defineProps<{
|
||||||
text="14px sm:16px"
|
text="14px sm:16px"
|
||||||
font-700
|
font-700
|
||||||
>{{ member.name }}</span>
|
>{{ member.name }}</span>
|
||||||
<span
|
|
||||||
text="14px sm:16px app-text-grey"
|
|
||||||
font-400
|
|
||||||
>{{ member.role ?? 'N/A' }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -12,7 +12,7 @@ defineProps<{
|
||||||
badge-text="3/10"
|
badge-text="3/10"
|
||||||
>
|
>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-code_v2
|
i-heroicons-solid-eye
|
||||||
text-24px
|
text-24px
|
||||||
/>
|
/>
|
||||||
</ProjectDetailCategoryDivider>
|
</ProjectDetailCategoryDivider>
|
||||||
|
@ -26,11 +26,11 @@ defineProps<{
|
||||||
lg:grid-cols-4
|
lg:grid-cols-4
|
||||||
>
|
>
|
||||||
<ProjectInfoItem
|
<ProjectInfoItem
|
||||||
:check-undefined="project.blockchain_features?.p2p"
|
:check-undefined="project.default_privacy"
|
||||||
bold
|
title="Default privacy"
|
||||||
title="Peer to Peer (P2P)"
|
:color="project.default_privacy ? '#18FF2F' : '#FF0000'"
|
||||||
>
|
>
|
||||||
{{ project.blockchain_features?.p2p ? 'YES' : 'NO' }}
|
{{ project.default_privacy ? 'YES' : 'NO' }}
|
||||||
</ProjectInfoItem>
|
</ProjectInfoItem>
|
||||||
<ProjectInfoItem
|
<ProjectInfoItem
|
||||||
:check-undefined="project.tracebility?.kyc"
|
:check-undefined="project.tracebility?.kyc"
|
||||||
|
@ -40,109 +40,6 @@ defineProps<{
|
||||||
>
|
>
|
||||||
{{ project.tracebility?.kyc ? 'YES' : 'NO' }}
|
{{ project.tracebility?.kyc ? 'YES' : 'NO' }}
|
||||||
</ProjectInfoItem>
|
</ProjectInfoItem>
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.storage"
|
|
||||||
bold
|
|
||||||
title="Decentralized storage"
|
|
||||||
:color="project.storage?.decentralized ? '#18FF2F' : '#FF0000'"
|
|
||||||
>
|
|
||||||
{{ project.storage?.decentralized ? 'YES' : 'NO' }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.default_privacy"
|
|
||||||
title="Default privacy"
|
|
||||||
:color="project.default_privacy ? '#18FF2F' : '#FF0000'"
|
|
||||||
>
|
|
||||||
{{ project.default_privacy ? 'YES' : 'NO' }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
grid
|
|
||||||
grid-cols-2
|
|
||||||
items-start
|
|
||||||
mt-32px
|
|
||||||
gap-y-16px
|
|
||||||
lg:grid-cols-4
|
|
||||||
>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.blockchain_features?.revealed_recipient"
|
|
||||||
:color="project.blockchain_features?.revealed_recipient ? '#FF0000' : '#18FF2F'"
|
|
||||||
bold
|
|
||||||
title="Revealed recipient"
|
|
||||||
>
|
|
||||||
{{ project.blockchain_features?.revealed_recipient ? 'YES' : 'NO' }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.blockchain_features?.revealed_sender"
|
|
||||||
:color="project.blockchain_features?.revealed_sender ? '#FF0000' : '#18FF2F'"
|
|
||||||
bold
|
|
||||||
title="Revealed sender"
|
|
||||||
>
|
|
||||||
{{ project.blockchain_features?.revealed_sender ? 'YES' : 'NO' }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.blockchain_features?.revealed_ammount"
|
|
||||||
:color="project.blockchain_features?.revealed_ammount ? '#FF0000' : '#18FF2F'"
|
|
||||||
bold
|
|
||||||
title="Revealed amount"
|
|
||||||
>
|
|
||||||
{{ project.blockchain_features?.revealed_ammount ? 'YES' : 'NO' }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.blockchain_features?.reversability_condition"
|
|
||||||
bold
|
|
||||||
title="Reversability"
|
|
||||||
>
|
|
||||||
{{ project.blockchain_features?.reversability_condition }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
grid
|
|
||||||
grid-cols-2
|
|
||||||
items-start
|
|
||||||
mt-32px
|
|
||||||
gap-y-16px
|
|
||||||
lg:grid-cols-4
|
|
||||||
>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.blockchain_features?.connected_tx"
|
|
||||||
:color="project.blockchain_features?.connected_tx ? '#FF0000' : '#18FF2F'"
|
|
||||||
bold
|
|
||||||
title="Connected Txs"
|
|
||||||
>
|
|
||||||
{{ project.blockchain_features?.connected_tx ? 'YES' : 'NO' }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.blockchain_features?.data_masking"
|
|
||||||
bold
|
|
||||||
title="Data masking"
|
|
||||||
>
|
|
||||||
{{ project.blockchain_features?.data_masking }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.blockchain_features?.tx_history"
|
|
||||||
bold
|
|
||||||
title="Tx history"
|
|
||||||
>
|
|
||||||
{{ project.blockchain_features?.tx_history ? 'YES' : 'NO' }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
</div>
|
|
||||||
<div my-24px>
|
|
||||||
<hr
|
|
||||||
border-t-2px
|
|
||||||
border-white
|
|
||||||
opacity-20
|
|
||||||
w-80px
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
grid
|
|
||||||
grid-cols-2
|
|
||||||
items-start
|
|
||||||
mt-32px
|
|
||||||
gap-y-16px
|
|
||||||
lg:grid-cols-4
|
|
||||||
>
|
|
||||||
<ProjectInfoItem
|
<ProjectInfoItem
|
||||||
:check-undefined="project.privacy_policy"
|
:check-undefined="project.privacy_policy"
|
||||||
:color="project.privacy_policy?.defined ? '#18FF2F' : '#FF0000'"
|
:color="project.privacy_policy?.defined ? '#18FF2F' : '#FF0000'"
|
||||||
|
@ -150,6 +47,31 @@ defineProps<{
|
||||||
title="Privacy Policy"
|
title="Privacy Policy"
|
||||||
>
|
>
|
||||||
{{ project.privacy_policy?.defined ? 'YES' : 'NO' }}
|
{{ project.privacy_policy?.defined ? 'YES' : 'NO' }}
|
||||||
|
<NuxtLink
|
||||||
|
:to="project.privacy_policy?.link"
|
||||||
|
external
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<UnoIcon
|
||||||
|
i-ic-twotone-open-in-new
|
||||||
|
text="22px app-text-grey"
|
||||||
|
/>
|
||||||
|
</NuxtLink>
|
||||||
|
</ProjectInfoItem>
|
||||||
|
<ProjectInfoItem
|
||||||
|
:check-undefined="project.compliance"
|
||||||
|
color="#FFB800"
|
||||||
|
bold
|
||||||
|
title="Compliance with"
|
||||||
|
>
|
||||||
|
{{ project.compliance ? 'YES' : 'NO' }}
|
||||||
|
</ProjectInfoItem>
|
||||||
|
<ProjectInfoItem
|
||||||
|
:check-undefined="project.tracebility?.sign_in_type_requirments"
|
||||||
|
bold
|
||||||
|
title="Sign-in requirements"
|
||||||
|
>
|
||||||
|
{{ project.tracebility?.sign_in_type_requirments }}
|
||||||
</ProjectInfoItem>
|
</ProjectInfoItem>
|
||||||
<ProjectInfoItem
|
<ProjectInfoItem
|
||||||
:check-undefined="project.tracebility?.tracked_data"
|
:check-undefined="project.tracebility?.tracked_data"
|
||||||
|
@ -163,58 +85,6 @@ defineProps<{
|
||||||
>
|
>
|
||||||
{{ project.privacy_policy?.data_usage }}
|
{{ project.privacy_policy?.data_usage }}
|
||||||
</ProjectInfoItem>
|
</ProjectInfoItem>
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.blockchain_features?.frontend_anonymity"
|
|
||||||
bold
|
|
||||||
title="Frontend anonymity"
|
|
||||||
>
|
|
||||||
{{ project.blockchain_features?.frontend_anonymity }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
</div>
|
|
||||||
<div my-24px>
|
|
||||||
<hr
|
|
||||||
border-t-2px
|
|
||||||
border-white
|
|
||||||
opacity-20
|
|
||||||
w-80px
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
grid
|
|
||||||
grid-cols-2
|
|
||||||
items-start
|
|
||||||
mt-32px
|
|
||||||
gap-y-16px
|
|
||||||
>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.compliance"
|
|
||||||
:color="project.compliance ? '#FF0000' : '#18FF2F'"
|
|
||||||
bold
|
|
||||||
title="Compliance"
|
|
||||||
>
|
|
||||||
{{ project.compliance ? 'YES' : 'NO' }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
grid
|
|
||||||
grid-cols-2
|
|
||||||
items-start
|
|
||||||
mt-32px
|
|
||||||
gap-y-16px
|
|
||||||
>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.tracebility?.sign_in_type_requirments"
|
|
||||||
bold
|
|
||||||
title="Sign-in requirements"
|
|
||||||
>
|
|
||||||
{{ project.tracebility?.sign_in_type_requirments }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.blockchain_features?.identity_integration"
|
|
||||||
title="Identity integrations"
|
|
||||||
>
|
|
||||||
{{ project.blockchain_features?.identity_integration }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
</div>
|
</div>
|
||||||
</ProjectDetailContainer>
|
</ProjectDetailContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
131
components/Project/ProjectRating.vue
Normal file
131
components/Project/ProjectRating.vue
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
<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>
|
|
@ -12,11 +12,36 @@ defineProps<{
|
||||||
badge-text="3/10"
|
badge-text="3/10"
|
||||||
>
|
>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-code_v2
|
i-material-symbols-lock-outline
|
||||||
text-24px
|
text-24px
|
||||||
/>
|
/>
|
||||||
</ProjectDetailCategoryDivider>
|
</ProjectDetailCategoryDivider>
|
||||||
<ProjectDetailContainer>
|
<ProjectDetailContainer>
|
||||||
|
<div v-if="project.audits">
|
||||||
|
<h2
|
||||||
|
text-18px
|
||||||
|
text-app-text-grey
|
||||||
|
my-24px
|
||||||
|
>
|
||||||
|
Audits
|
||||||
|
</h2>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap="12px lg:16px"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
v-for="audit in project.audits"
|
||||||
|
:key="audit.name"
|
||||||
|
>
|
||||||
|
<ProjectSecurityAudit
|
||||||
|
:audit-name="audit.name"
|
||||||
|
:audit-url="audit.link"
|
||||||
|
:date="audit.time"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
grid
|
grid
|
||||||
grid-cols-2
|
grid-cols-2
|
||||||
|
@ -26,20 +51,11 @@ defineProps<{
|
||||||
lg:grid-cols-4
|
lg:grid-cols-4
|
||||||
>
|
>
|
||||||
<ProjectInfoItem
|
<ProjectInfoItem
|
||||||
:check-undefined="project.blockchain_features?.asset_custody_type"
|
:check-undefined="project.technical_spof"
|
||||||
bold
|
:color="project.technical_spof ? '#FF0000' : '#18FF2F'"
|
||||||
title="Asset custody"
|
title="Technical dependency"
|
||||||
>
|
>
|
||||||
{{ project.blockchain_features?.asset_custody_type }}
|
{{ project.technical_spof }}
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.blockchain_features?.upgradability"
|
|
||||||
title="Upgradability"
|
|
||||||
>
|
|
||||||
<b :color="project.blockchain_features?.upgradability?.enabled ? '#FF0000' : '#18FF2F'">
|
|
||||||
{{ project.blockchain_features?.upgradability?.enabled ? 'YES' : 'NO' }}
|
|
||||||
</b>
|
|
||||||
{{ ` – ${project.blockchain_features?.upgradability?.type}` }}
|
|
||||||
</ProjectInfoItem>
|
</ProjectInfoItem>
|
||||||
<ProjectInfoItem
|
<ProjectInfoItem
|
||||||
:check-undefined="project.social_trust"
|
:check-undefined="project.social_trust"
|
||||||
|
@ -55,47 +71,6 @@ defineProps<{
|
||||||
>
|
>
|
||||||
{{ project.third_party_dependency ? 'YES' : 'NO' }}
|
{{ project.third_party_dependency ? 'YES' : 'NO' }}
|
||||||
</ProjectInfoItem>
|
</ProjectInfoItem>
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.technical_spof"
|
|
||||||
:color="project.technical_spof ? '#FF0000' : '#18FF2F'"
|
|
||||||
title="Technical dependency"
|
|
||||||
>
|
|
||||||
{{ project.technical_spof }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
</div>
|
|
||||||
<div my-24px>
|
|
||||||
<hr
|
|
||||||
border-t-2px
|
|
||||||
border-white
|
|
||||||
opacity-20
|
|
||||||
w-80px
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div v-if="project.audits">
|
|
||||||
<h2
|
|
||||||
text-18px
|
|
||||||
text-app-text-grey
|
|
||||||
my-24px
|
|
||||||
>
|
|
||||||
Audits
|
|
||||||
</h2>
|
|
||||||
<template
|
|
||||||
v-for="audit in project.audits"
|
|
||||||
:key="audit.name"
|
|
||||||
>
|
|
||||||
<ProjectSecurityAudit
|
|
||||||
:audit-name="audit.name"
|
|
||||||
:audit-url="audit.link"
|
|
||||||
:date="audit.time"
|
|
||||||
>
|
|
||||||
<NuxtImg
|
|
||||||
:src="audit.logo ?? '/no-image-1-1.svg'"
|
|
||||||
w-64px
|
|
||||||
h-64px
|
|
||||||
object-cover
|
|
||||||
/>
|
|
||||||
</ProjectSecurityAudit>
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</ProjectDetailContainer>
|
</ProjectDetailContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -9,36 +9,69 @@ defineProps<{
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
flex
|
flex
|
||||||
items-center
|
justify-between
|
||||||
gap-16px
|
lg:grid
|
||||||
|
lg:grid-cols-2
|
||||||
|
rounded-full
|
||||||
|
py-12px
|
||||||
|
px-16px
|
||||||
|
bg-app-bg-audits-card
|
||||||
>
|
>
|
||||||
<slot />
|
|
||||||
<div
|
<div
|
||||||
flex
|
grid
|
||||||
flex-col
|
grid-cols-3
|
||||||
text-14px
|
w-full
|
||||||
font-700
|
|
||||||
leading-24px
|
|
||||||
>
|
>
|
||||||
<NuxtLink
|
<h2
|
||||||
hover:underline
|
text="14px lg:16px"
|
||||||
flex
|
leading-20px
|
||||||
items-center
|
font-700
|
||||||
gap-8px
|
col-span="3 lg:2"
|
||||||
:to="auditUrl"
|
|
||||||
>
|
>
|
||||||
{{ auditName }}
|
{{ auditName }}
|
||||||
<UnoIcon
|
</h2>
|
||||||
v-if="auditUrl"
|
<h2
|
||||||
i-web-openinnew
|
|
||||||
text-16px
|
|
||||||
/>
|
|
||||||
</NuxtLink>
|
|
||||||
<span
|
|
||||||
text-14px
|
text-14px
|
||||||
font-400
|
leading-20px
|
||||||
leading-24px
|
hidden
|
||||||
>{{ date }}</span>
|
lg:block
|
||||||
|
>
|
||||||
|
Overview of smart contracts
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
justify-end
|
||||||
|
gap="16px lg:80px"
|
||||||
|
whitespace-nowrap
|
||||||
|
>
|
||||||
|
<h2
|
||||||
|
text-14px
|
||||||
|
leading-20px
|
||||||
|
>
|
||||||
|
{{ date ? formatDate(date) : 'N/A' }}
|
||||||
|
</h2>
|
||||||
|
<NuxtLink
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
gap-4px
|
||||||
|
:to="auditUrl"
|
||||||
|
external
|
||||||
|
target="_blank"
|
||||||
|
text-14px
|
||||||
|
text-app-text-grey
|
||||||
|
leading-20px
|
||||||
|
hover:underline
|
||||||
|
><p
|
||||||
|
hidden
|
||||||
|
lg:block
|
||||||
|
>
|
||||||
|
More info
|
||||||
|
</p> <UnoIcon
|
||||||
|
i-ic-twotone-open-in-new
|
||||||
|
text-22px
|
||||||
|
/></NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -12,7 +12,7 @@ defineProps<{
|
||||||
badge-text="3/10"
|
badge-text="3/10"
|
||||||
>
|
>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-code_v2
|
i-material-symbols-deployed-code-outline
|
||||||
text-24px
|
text-24px
|
||||||
/>
|
/>
|
||||||
</ProjectDetailCategoryDivider>
|
</ProjectDetailCategoryDivider>
|
||||||
|
@ -21,100 +21,54 @@ defineProps<{
|
||||||
grid
|
grid
|
||||||
grid-cols-2
|
grid-cols-2
|
||||||
items-start
|
items-start
|
||||||
mt-32px
|
mt-24px
|
||||||
gap-y-16px
|
gap-y-16px
|
||||||
lg:grid-cols-4
|
lg:grid-cols-4
|
||||||
>
|
>
|
||||||
|
<ProjectInfoItem
|
||||||
|
:check-undefined="project.blockchain_features?.opensource"
|
||||||
|
title="Opensource"
|
||||||
|
bold
|
||||||
|
:color="project.blockchain_features?.opensource ? '#18FF2F' : '#FF0000'"
|
||||||
|
>
|
||||||
|
{{ project.blockchain_features?.opensource ? 'YES' : 'NO' }}
|
||||||
|
</ProjectInfoItem>
|
||||||
|
<ProjectInfoItem
|
||||||
|
:check-undefined="project.blockchain_features?.asset_custody_type"
|
||||||
|
title="Asset custody"
|
||||||
|
:color="project.blockchain_features?.asset_custody_type === 'non-custody' ? '#18FF2F' : project.blockchain_features?.asset_custody_type === 'multisig' ? '#FFB800' : '#FF0000'"
|
||||||
|
bold
|
||||||
|
>
|
||||||
|
{{ project.blockchain_features?.asset_custody_type?.toUpperCase() }}
|
||||||
|
</ProjectInfoItem>
|
||||||
|
<ProjectInfoItem
|
||||||
|
title="Upgradability"
|
||||||
|
bold
|
||||||
|
:check-undefined="project.blockchain_features?.upgradability"
|
||||||
|
:color="project.blockchain_features?.upgradability ? '#FF0000' : '#18FF2F' "
|
||||||
|
>
|
||||||
|
{{ project.blockchain_features?.upgradability ? 'YES' : 'NO' }}
|
||||||
|
</ProjectInfoItem>
|
||||||
<ProjectInfoItem
|
<ProjectInfoItem
|
||||||
:check-undefined="project.technology?.type"
|
:check-undefined="project.technology?.type"
|
||||||
title="Technology type"
|
title="Technology type"
|
||||||
bold
|
bold
|
||||||
>
|
>
|
||||||
{{ project.technology?.type }}
|
{{ project.technology?.type.toUpperCase() }}
|
||||||
</ProjectInfoItem>
|
</ProjectInfoItem>
|
||||||
<ProjectInfoItem
|
<ProjectInfoItem
|
||||||
:check-undefined="project.blockchain_features?.encryption"
|
:check-undefined="project.blockchain_features?.p2p"
|
||||||
title="Encryption"
|
title="Peer to Peer (P2P)"
|
||||||
bold
|
bold
|
||||||
>
|
>
|
||||||
{{ project.blockchain_features?.encryption }}
|
{{ project.blockchain_features?.p2p ? 'YES' : 'NO' }}
|
||||||
</ProjectInfoItem>
|
</ProjectInfoItem>
|
||||||
<ProjectInfoItem
|
<ProjectInfoItem
|
||||||
title="License"
|
:check-undefined="project.storage?.decentralized"
|
||||||
bold
|
title="Decentralized storage"
|
||||||
:check-undefined="project.licences"
|
|
||||||
>
|
|
||||||
{{ project.licences }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.links?.whitepaper"
|
|
||||||
title="Whitepaper"
|
|
||||||
bold
|
|
||||||
:link="project.links?.whitepaper"
|
|
||||||
>
|
|
||||||
{{ project.links?.whitepaper ? 'YES' : 'NO' }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
grid
|
|
||||||
grid-cols-1
|
|
||||||
items-start
|
|
||||||
mt-16px
|
|
||||||
gap-y-16px
|
|
||||||
lg:grid-cols-4
|
|
||||||
>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.project_status"
|
|
||||||
title="Version"
|
|
||||||
bold
|
bold
|
||||||
>
|
>
|
||||||
<div
|
{{ project.storage?.decentralized ? 'YES' : 'NO' }}
|
||||||
v-if="project.project_status?.live_status"
|
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
gap-12px
|
|
||||||
>
|
|
||||||
<UnoIcon
|
|
||||||
i-web-live
|
|
||||||
text-10px
|
|
||||||
class="color-#B5E26B"
|
|
||||||
/>
|
|
||||||
<span>{{ `Live on ${project.project_status.version}` }}</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-else
|
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
gap-12px
|
|
||||||
>
|
|
||||||
<UnoIcon
|
|
||||||
i-web-live
|
|
||||||
text-10px
|
|
||||||
class="color-#e26b6b"
|
|
||||||
/>
|
|
||||||
<span>{{ 'Offline' }}</span>
|
|
||||||
</div>
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.technology?.features"
|
|
||||||
title="Features"
|
|
||||||
bold
|
|
||||||
>
|
|
||||||
{{ project.technology?.features.join(', ') }}
|
|
||||||
</ProjectInfoItem>
|
|
||||||
<ProjectInfoItem
|
|
||||||
:check-undefined="project.client_diversability"
|
|
||||||
title="Client diversability"
|
|
||||||
bold
|
|
||||||
>
|
|
||||||
<template
|
|
||||||
v-for="item in project.client_diversability"
|
|
||||||
:key="item.name"
|
|
||||||
>
|
|
||||||
<NuxtLink :to="item.link">
|
|
||||||
{{ item.name }}
|
|
||||||
</NuxtLink><br>
|
|
||||||
</template>
|
|
||||||
</ProjectInfoItem>
|
</ProjectInfoItem>
|
||||||
</div>
|
</div>
|
||||||
</ProjectDetailContainer>
|
</ProjectDetailContainer>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { InputOption } from '~/types'
|
import type { InputOption } from '~/types'
|
||||||
|
|
||||||
|
defineProps<{ placeholder?: string, includeSort?: boolean }>()
|
||||||
|
|
||||||
const { filter, switcher } = storeToRefs(useData())
|
const { filter, switcher } = storeToRefs(useData())
|
||||||
const options: InputOption[] = [
|
const options: InputOption[] = [
|
||||||
{ label: 'A to Z', value: 'atoz' },
|
{ label: 'A to Z', value: 'atoz' },
|
||||||
|
@ -22,8 +24,8 @@ const isSearchFocused = ref(false)
|
||||||
border-2px
|
border-2px
|
||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
max-w-320px
|
|
||||||
w-full
|
w-full
|
||||||
|
h-40px
|
||||||
hover:opacity-100
|
hover:opacity-100
|
||||||
:class="isSearchFocused ? 'opacity-100' : 'opacity-25'"
|
:class="isSearchFocused ? 'opacity-100' : 'opacity-25'"
|
||||||
>
|
>
|
||||||
|
@ -34,7 +36,7 @@ const isSearchFocused = ref(false)
|
||||||
w-fit
|
w-fit
|
||||||
>
|
>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-web-search
|
i-heroicons-solid-magnifying-glass
|
||||||
text-16px
|
text-16px
|
||||||
:class="isSearchFocused ? 'opacity-100' : 'opacity-50' "
|
:class="isSearchFocused ? 'opacity-100' : 'opacity-50' "
|
||||||
class="uno-icon"
|
class="uno-icon"
|
||||||
|
@ -42,6 +44,7 @@ const isSearchFocused = ref(false)
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
v-model="filter.query"
|
v-model="filter.query"
|
||||||
|
:placeholder="placeholder"
|
||||||
type="text"
|
type="text"
|
||||||
bg-transparent
|
bg-transparent
|
||||||
border-transparent
|
border-transparent
|
||||||
|
@ -54,7 +57,7 @@ const isSearchFocused = ref(false)
|
||||||
@blur="isSearchFocused = false"
|
@blur="isSearchFocused = false"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div v-if="includeSort">
|
||||||
<div
|
<div
|
||||||
flex
|
flex
|
||||||
gap-24px
|
gap-24px
|
||||||
|
|
|
@ -42,8 +42,8 @@ const selectedValue = useVModel(props, 'modelValue', emits)
|
||||||
</span>
|
</span>
|
||||||
<span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
|
<span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
i-heroicons-solid-chevron-down
|
i-ic-baseline-arrow-drop-down
|
||||||
:class="[blackAndWhite ? 'text-app-white' : 'text-app-black']"
|
:class="[blackAndWhite ? ' text-app-white' : 'text-app-black']"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</HeadlessListboxButton>
|
</HeadlessListboxButton>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import type { InputOption } from '~/types'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
options: InputOption[]
|
options: InputOption[]
|
||||||
modelValue: string
|
modelValue: string | number
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emits = defineEmits(['update:modelValue'])
|
const emits = defineEmits(['update:modelValue'])
|
||||||
|
|
|
@ -1,32 +1,49 @@
|
||||||
import type { Category, Project, ProjectShallow } from '~/types'
|
import type { Category, Project, ProjectRating, ProjectRatingItem, ProjectShallow } from '~/types'
|
||||||
|
import type { Asset } from '~/types/asset'
|
||||||
|
import type { Ecosystem } from '~/types/ecosystem'
|
||||||
|
import type { Feature } from '~/types/feature'
|
||||||
|
import type { Rank } from '~/types/rank'
|
||||||
|
import type { Usecase } from '~/types/usecase'
|
||||||
|
|
||||||
export const useData = defineStore('data', () => {
|
export const useData = defineStore('data', () => {
|
||||||
const assetsData = useState<{ id: string, name: string }[]>('assetsData')
|
const projectPhase = useState<{ id: string, name: string }[]>('projectPhase')
|
||||||
const categoriesData = useState<{ id: string, name: string }[]>('categoriesData')
|
const assetCustody = useState<{ id: string, name: string }[]>('assetCustody')
|
||||||
const featuresData = useState<{ id: string, name: string }[]>('featuresData')
|
const signInRequirments = useState<{ id: string, name: string }[]>('signInRequirmenets')
|
||||||
const ecosystemsData = useState<{ id: string, name: string }[]>('ecosystemsData')
|
|
||||||
const usecasesData = useState<{ id: string, name: string }[]>('usecasesData')
|
|
||||||
const projectPhaseData = useState<{ id: string, name: string }[]>('projectPhaseData')
|
|
||||||
const assetCustodyData = useState<{ id: string, name: string }[]>('assetCustodyData')
|
|
||||||
const signInRequirmentsData = useState<{ id: string, name: string }[]>('signInRequirmenetsData')
|
|
||||||
|
|
||||||
const categories = useState<Category[]>('categories')
|
const categories = useState<Category[]>('categories')
|
||||||
|
const usecases = useState<Usecase[]>('usecases')
|
||||||
|
const features = useState<Feature[]>('features')
|
||||||
|
const assets = useState<Asset[]>('assets')
|
||||||
|
const ecosystems = useState<Ecosystem[]>('ecosystems')
|
||||||
const projects = useState<Project[]>('projects')
|
const projects = useState<Project[]>('projects')
|
||||||
const selectedCategoryId = useState(() => 'defi')
|
const ranks = useState<Rank[]>('ranks')
|
||||||
|
|
||||||
|
const selectedCategoryId = useState(() => 'all')
|
||||||
|
const selectedUsecaseId = useState(() => 'all')
|
||||||
|
const selectedEcosystemId = useState(() => 'all')
|
||||||
|
const selectedAssetsUsedId = useState(() => 'all')
|
||||||
|
const selectedFeaturesId = useState(() => 'all')
|
||||||
|
|
||||||
const filter = reactive({
|
const filter = reactive({
|
||||||
query: '',
|
query: '',
|
||||||
sortby: 'atoz',
|
sortby: 'score',
|
||||||
|
sortDirection: 'desc',
|
||||||
})
|
})
|
||||||
const switcher = ref(true)
|
const switcher = ref(true)
|
||||||
|
|
||||||
watch(selectedCategoryId, () => {
|
watch([selectedCategoryId, selectedUsecaseId, selectedEcosystemId, selectedAssetsUsedId, selectedFeaturesId], () => {
|
||||||
if (selectedCategoryId.value !== 'all')
|
if (selectedCategoryId.value !== 'all' || selectedUsecaseId.value !== 'all' || selectedEcosystemId.value !== 'all' || selectedAssetsUsedId.value !== 'all' || selectedFeaturesId.value !== 'all')
|
||||||
filter.query = ''
|
filter.query = ''
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(filter, () => {
|
watch(filter, () => {
|
||||||
if (filter.query !== '')
|
if (filter.query !== '') {
|
||||||
selectedCategoryId.value = 'all'
|
selectedCategoryId.value = 'all'
|
||||||
|
selectedUsecaseId.value = 'all'
|
||||||
|
selectedEcosystemId.value = 'all'
|
||||||
|
selectedAssetsUsedId.value = 'all'
|
||||||
|
selectedFeaturesId.value = 'all'
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
|
@ -34,36 +51,35 @@ export const useData = defineStore('data', () => {
|
||||||
const data = await $fetch<{
|
const data = await $fetch<{
|
||||||
categories: Category[]
|
categories: Category[]
|
||||||
projects: Project[]
|
projects: Project[]
|
||||||
assets: { id: string, name: string }[]
|
|
||||||
features: { id: string, name: string }[]
|
|
||||||
ecosystems: { id: string, name: string }[]
|
|
||||||
usecases: { id: string, name: string }[]
|
|
||||||
project_phase: { id: string, name: string }[]
|
project_phase: { id: string, name: string }[]
|
||||||
asset_custody_type: { id: string, name: string }[]
|
asset_custody_type: { id: string, name: string }[]
|
||||||
sign_in_type_requirments: { id: string, name: string }[]
|
sign_in_type_requirments: { id: string, name: string }[]
|
||||||
|
usecases: Usecase[]
|
||||||
|
ecosystems: Ecosystem[]
|
||||||
|
assets: Asset[]
|
||||||
|
features: Feature[]
|
||||||
|
ranks: Rank[]
|
||||||
}>('/api/data')
|
}>('/api/data')
|
||||||
projects.value = data.projects.filter(p => p.name)
|
projects.value = data.projects.map(project => ({
|
||||||
categories.value = data.categories.map((c) => {
|
...project,
|
||||||
c.projectsCount = projects.value.filter(p =>
|
ratings: generateProjectRating(project),
|
||||||
p.categories?.includes(c.id),
|
})).filter(p => p.name)
|
||||||
).length
|
|
||||||
return c
|
|
||||||
}).filter(c => c.projectsCount > 0)
|
|
||||||
|
|
||||||
assetsData.value = data.assets.map(a => ({ id: a.id.toLowerCase(), name: a.name }))
|
categories.value = data.categories
|
||||||
categoriesData.value = data.categories.map(c => ({ id: c.id.toLowerCase(), name: c.name }))
|
usecases.value = data.usecases
|
||||||
featuresData.value = data.features.map(f => ({ id: f.id.toLowerCase(), name: f.name }))
|
ecosystems.value = data.ecosystems
|
||||||
ecosystemsData.value = data.ecosystems.map(e => ({ id: e.id.toLowerCase(), name: e.name }))
|
assets.value = data.assets
|
||||||
usecasesData.value = data.usecases.map(u => ({ id: u.id.toLowerCase(), name: u.name }))
|
features.value = data.features
|
||||||
projectPhaseData.value = data.project_phase.map(p => ({ id: p.id.toLowerCase(), name: p.name }))
|
ranks.value = data.ranks
|
||||||
assetCustodyData.value = data.asset_custody_type.map(a => ({ id: a.id.toLowerCase(), name: a.name }))
|
|
||||||
signInRequirmentsData.value = data.sign_in_type_requirments.map(s => ({ id: s.id.toLowerCase(), name: s.name }))
|
projectPhase.value = data.project_phase.map(p => ({ id: p.id.toLowerCase(), name: p.name }))
|
||||||
|
assetCustody.value = data.asset_custody_type.map(a => ({ id: a.id.toLowerCase(), name: a.name }))
|
||||||
|
signInRequirments.value = data.sign_in_type_requirments.map(s => ({ id: s.id.toLowerCase(), name: s.name }))
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +98,7 @@ export const useData = defineStore('data', () => {
|
||||||
id: project.id,
|
id: project.id,
|
||||||
title1: project.name,
|
title1: project.name,
|
||||||
description: project.description ?? 'N/A',
|
description: project.description ?? 'N/A',
|
||||||
percentage: Math.floor(Math.random() * 91),
|
percentage: Math.round((project.ratings?.reduce((a, b) => a + b.points, 0) || 0) / 1.5),
|
||||||
forum: project.links?.forum,
|
forum: project.links?.forum,
|
||||||
explorer: project.links?.block_explorer,
|
explorer: project.links?.block_explorer,
|
||||||
twitter: project.links?.twitter,
|
twitter: project.links?.twitter,
|
||||||
|
@ -97,15 +113,33 @@ export const useData = defineStore('data', () => {
|
||||||
support: availableSupport(),
|
support: availableSupport(),
|
||||||
image: project.logos?.[0]?.url ?? '',
|
image: project.logos?.[0]?.url ?? '',
|
||||||
anonymity: true,
|
anonymity: true,
|
||||||
|
categories: project.categories,
|
||||||
|
usecases: project.usecases,
|
||||||
|
ecosystem: project.ecosystem,
|
||||||
|
assets_used: project.assets_used,
|
||||||
|
ratings: project.ratings,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const shallowProjects = computed(() => projects.value.map(project => projectToShallow(project)))
|
const shallowProjects = computed(() => projects.value.map(project => projectToShallow(project)))
|
||||||
|
|
||||||
const getProjectsByCategory = <T extends ProjectShallow>(id: string, options?: { shallow: boolean }): T[] => {
|
const getProjectsByFilters = <T extends ProjectShallow>(options?: { shallow: boolean }): T[] => {
|
||||||
if (id === 'all')
|
const filteredProjects = projects.value
|
||||||
return projects.value.map(project => projectToShallow(project)) as T[]
|
.filter(project =>
|
||||||
else
|
selectedCategoryId.value !== 'all' ? project.categories.includes(selectedCategoryId.value) : true,
|
||||||
return projects.value.filter(project => project.categories?.includes(id)).map(project => options?.shallow ? projectToShallow(project) : project) as T[]
|
)
|
||||||
|
.filter(project =>
|
||||||
|
selectedUsecaseId.value !== 'all' ? project.usecases?.map(u => u.toLowerCase()).includes(selectedUsecaseId.value.toLowerCase()) : true,
|
||||||
|
)
|
||||||
|
.filter(project =>
|
||||||
|
selectedEcosystemId.value !== 'all' ? project.ecosystem?.map(e => e.toLowerCase()).includes(selectedEcosystemId.value.toLowerCase()) : true,
|
||||||
|
)
|
||||||
|
.filter(project =>
|
||||||
|
selectedAssetsUsedId.value !== 'all' ? project.assets_used?.map(a => a.toLowerCase()).includes(selectedAssetsUsedId.value.toLowerCase()) : true,
|
||||||
|
)
|
||||||
|
.filter(project =>
|
||||||
|
selectedFeaturesId.value !== 'all' ? project.technology?.features?.map(f => f.toLowerCase()).includes(selectedFeaturesId.value.toLowerCase()) : true,
|
||||||
|
)
|
||||||
|
return (filteredProjects.map(project => options?.shallow ? projectToShallow(project) : project) as T[])
|
||||||
}
|
}
|
||||||
|
|
||||||
const getProjectById = <T extends Project | ProjectShallow>(id: string, options?: { shallow: boolean }): T => {
|
const getProjectById = <T extends Project | ProjectShallow>(id: string, options?: { shallow: boolean }): T => {
|
||||||
|
@ -119,7 +153,7 @@ export const useData = defineStore('data', () => {
|
||||||
|
|
||||||
const query = filter.query.toLowerCase()
|
const query = filter.query.toLowerCase()
|
||||||
|
|
||||||
const filteredShallowProjects = getProjectsByCategory(selectedCategoryId.value, { shallow: true })
|
const filteredShallowProjects = getProjectsByFilters({ shallow: true })
|
||||||
.filter((project) => {
|
.filter((project) => {
|
||||||
return (
|
return (
|
||||||
project
|
project
|
||||||
|
@ -133,37 +167,126 @@ export const useData = defineStore('data', () => {
|
||||||
return true
|
return true
|
||||||
}).sort((a, b) => {
|
}).sort((a, b) => {
|
||||||
if (filter.sortby === 'score')
|
if (filter.sortby === 'score')
|
||||||
return b.percentage - a.percentage
|
if (filter.sortDirection === 'asc')
|
||||||
if (filter.sortby === 'atoz')
|
return a.percentage - b.percentage
|
||||||
return a.title1.localeCompare(b.title1)
|
else
|
||||||
|
return b.percentage - a.percentage
|
||||||
|
if (filter.sortby === 'title')
|
||||||
|
if (filter.sortDirection === 'asc')
|
||||||
|
return a.title1.toLowerCase().localeCompare(b.title1.toLowerCase())
|
||||||
|
else
|
||||||
|
return b.title1.toLowerCase().localeCompare(a.title1.toLowerCase())
|
||||||
|
if (filter.sortby === 'openess' || filter.sortby === 'technology' || filter.sortby === 'privacy') {
|
||||||
|
const scoreA = a.ratings?.find(r => r.type === filter.sortby)?.points || 0
|
||||||
|
const scoreB = b.ratings?.find(r => r.type === filter.sortby)?.points || 0
|
||||||
|
if (filter.sortDirection === 'asc')
|
||||||
|
return scoreB - scoreA
|
||||||
|
else
|
||||||
|
return scoreA - scoreB
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return 0
|
return 0
|
||||||
})
|
})
|
||||||
|
|
||||||
return filteredShallowProjects
|
return filteredShallowProjects
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const groupedProjectsPerCategory = computed(() => {
|
||||||
|
const groupedProjects = categories.value.map((category) => {
|
||||||
|
// Find all projects that include this category
|
||||||
|
const projectsInCategory = filteredProjects.value.filter(project =>
|
||||||
|
project.categories.includes(category.id),
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: category.name,
|
||||||
|
projects: projectsInCategory,
|
||||||
|
}
|
||||||
|
}).sort((a, b) => b.projects.length - a.projects.length)
|
||||||
|
|
||||||
|
return groupedProjects
|
||||||
|
})
|
||||||
|
|
||||||
const filteredProjectsCount = computed(() => filteredProjects.value.length)
|
const filteredProjectsCount = computed(() => filteredProjects.value.length)
|
||||||
|
|
||||||
|
const getNestedField = (project: Project, field: string) => {
|
||||||
|
const fields = field.split('.')
|
||||||
|
|
||||||
|
return fields.reduce((acc: any, curr: string) => {
|
||||||
|
return acc && acc[curr as keyof typeof acc]
|
||||||
|
}, project)
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateProjectRating = (project: Project) => {
|
||||||
|
const projectRatings: ProjectRating[] = ranks.value?.map((rank) => {
|
||||||
|
let rankPoints = 0
|
||||||
|
|
||||||
|
const ratingStats: ProjectRatingItem[] = rank.references?.map((ref) => {
|
||||||
|
let isValid = false
|
||||||
|
const field = ref.field.includes('.') ? getNestedField(project, ref.field) : project[ref.field]
|
||||||
|
|
||||||
|
let value
|
||||||
|
let positive
|
||||||
|
|
||||||
|
if (ref.condition.minLength) {
|
||||||
|
value = (field as any[])?.length
|
||||||
|
if (value) {
|
||||||
|
isValid = value >= ref.condition.minLength
|
||||||
|
positive = `${value} ${ref.label.positive}${value > 1 ? 's' : ''}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ref.condition.equals) {
|
||||||
|
value = field
|
||||||
|
if (value)
|
||||||
|
isValid = value === ref.condition.equals
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref.condition.exists) {
|
||||||
|
value = field
|
||||||
|
if (value)
|
||||||
|
isValid = !!value
|
||||||
|
}
|
||||||
|
rankPoints += isValid ? ref.points : 0
|
||||||
|
return {
|
||||||
|
isValid,
|
||||||
|
label: ref.label.name,
|
||||||
|
positive: positive ? positive : ref.label.positive,
|
||||||
|
negative: ref.label.negative,
|
||||||
|
value,
|
||||||
|
} as ProjectRatingItem
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
type: rank.id,
|
||||||
|
name: rank.name,
|
||||||
|
items: ratingStats,
|
||||||
|
points: rankPoints,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return projectRatings
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectedCategoryId,
|
selectedCategoryId,
|
||||||
|
selectedUsecaseId,
|
||||||
|
selectedEcosystemId,
|
||||||
|
selectedAssetsUsedId,
|
||||||
|
selectedFeaturesId,
|
||||||
filter,
|
filter,
|
||||||
switcher,
|
switcher,
|
||||||
categories,
|
categories,
|
||||||
assetsData,
|
projectPhase,
|
||||||
categoriesData,
|
assetCustody,
|
||||||
featuresData,
|
signInRequirments,
|
||||||
ecosystemsData,
|
usecases,
|
||||||
usecasesData,
|
features,
|
||||||
projectPhaseData,
|
ecosystems,
|
||||||
assetCustodyData,
|
assets,
|
||||||
signInRequirmentsData,
|
|
||||||
projects,
|
projects,
|
||||||
shallowProjects,
|
shallowProjects,
|
||||||
|
groupedProjectsPerCategory,
|
||||||
filteredProjectsCount,
|
filteredProjectsCount,
|
||||||
fetchData,
|
fetchData,
|
||||||
getProjectById,
|
getProjectById,
|
||||||
getProjectsByCategory,
|
|
||||||
filteredProjects,
|
filteredProjects,
|
||||||
projectToShallow,
|
projectToShallow,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { InputOption } from '~/types'
|
import type { InputOption } from '~/types'
|
||||||
|
|
||||||
const { categories, filteredProjectsCount, selectedCategoryId } = storeToRefs(useData())
|
const { categories, usecases, ecosystems, assets, features, filteredProjectsCount, selectedCategoryId, selectedUsecaseId, selectedEcosystemId, selectedAssetsUsedId, selectedFeaturesId } = storeToRefs(useData())
|
||||||
|
|
||||||
const categoriesOptions = ref(categories.value ? categories.value.map(c => ({ label: c.name, value: c.id, count: c.projectsCount })) : [])
|
|
||||||
const extendedOptions: InputOption[] = [
|
|
||||||
...categoriesOptions.value,
|
|
||||||
]
|
|
||||||
|
|
||||||
const selectedCategory = computed(() => {
|
const selectedCategory = computed(() => {
|
||||||
return categories.value.find(c => c.id === selectedCategoryId.value)
|
return categories.value.find(c => c.id === selectedCategoryId.value)
|
||||||
})
|
})
|
||||||
|
const availableUsecases = computed(() => {
|
||||||
|
if (selectedCategoryId.value === 'all')
|
||||||
|
return usecases.value
|
||||||
|
return usecases.value.filter(u => selectedCategory.value?.usecases?.includes(u.id))
|
||||||
|
})
|
||||||
|
|
||||||
const sortedFilteredCategories = computed(() => ([
|
const categoryOptions = ref<InputOption[]>(categories.value ? [{ label: 'Category', value: 'all' }, ...categories.value.map(c => ({ label: c.name, value: c.id, count: c.projectsCount }))] : [])
|
||||||
categories.value.find(c => c.id === 'defi')!,
|
const usecaseOptions = computed<InputOption[]>(() => availableUsecases.value.length ? [{ label: 'Usecase', value: 'all' }, ...availableUsecases.value.map(u => ({ label: u.name, value: u.id }))] : [])
|
||||||
...[...categories.value].sort((a, b) => a.name.localeCompare(b.name)).filter(c => c.id !== 'defi'),
|
const ecosystemOptions = ref<InputOption[]>(ecosystems.value ? [{ label: 'Ecosystem', value: 'all' }, ...ecosystems.value.map(e => ({ label: e.name, value: e.id }))] : [])
|
||||||
]))
|
const assetOptions = ref<InputOption[]>(assets.value ? [{ label: 'Asset used', value: 'all' }, ...assets.value.map(a => ({ label: `${a.id.toUpperCase()} (${a.name})`, value: a.id }))] : [])
|
||||||
|
const featureOptions = ref<InputOption[]>(features.value ? [{ label: 'Feature', value: 'all' }, ...features.value.map(f => ({ label: f.name, value: f.id }))] : [])
|
||||||
|
|
||||||
const { showBar } = storeToRefs(useNavigaiton())
|
const { showBar } = storeToRefs(useNavigaiton())
|
||||||
const swipeEl = ref()
|
const swipeEl = ref()
|
||||||
|
@ -56,77 +57,67 @@ watch([scrollY, top, y], (newValues, oldValues) => {
|
||||||
w-full
|
w-full
|
||||||
xl:gap-32px
|
xl:gap-32px
|
||||||
>
|
>
|
||||||
<div w-fit>
|
<div
|
||||||
<div
|
flex
|
||||||
ref="scrollEl"
|
flex-col
|
||||||
class="no-scrollbar"
|
w-full
|
||||||
h-100vh
|
>
|
||||||
overflow-y-auto
|
|
||||||
sticky
|
|
||||||
top-32px
|
|
||||||
hidden
|
|
||||||
xl:block
|
|
||||||
min-w-234px
|
|
||||||
pb-48px
|
|
||||||
>
|
|
||||||
<Category
|
|
||||||
v-for="category in sortedFilteredCategories"
|
|
||||||
:key="category.id"
|
|
||||||
:title="category.name"
|
|
||||||
:count="category.projectsCount"
|
|
||||||
:selected="selectedCategoryId === category.id"
|
|
||||||
@click="[navigateTo(`/category/${category.id}`), selectedCategoryId = category.id]"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div w-full>
|
|
||||||
<div
|
<div
|
||||||
flex
|
flex
|
||||||
flex-col
|
flex-col
|
||||||
|
md:flex-row
|
||||||
|
md:justify-between
|
||||||
|
md:items-center
|
||||||
gap-16px
|
gap-16px
|
||||||
w-full
|
mb="16px md:32px"
|
||||||
>
|
>
|
||||||
|
<SearchBox
|
||||||
|
flex-1
|
||||||
|
placeholder:text-app-text-grey
|
||||||
|
:placeholder="`Search in ${filteredProjectsCount} Projects`"
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
xl:hidden
|
md:flex-2
|
||||||
block
|
flex
|
||||||
|
items-center
|
||||||
|
gap-16px
|
||||||
>
|
>
|
||||||
<h2
|
|
||||||
text-14px
|
|
||||||
font-700
|
|
||||||
>
|
|
||||||
Choose category
|
|
||||||
</h2>
|
|
||||||
<CategorySelectBox
|
<CategorySelectBox
|
||||||
v-model="selectedCategoryId"
|
v-model="selectedCategoryId"
|
||||||
:options="extendedOptions"
|
:options="categoryOptions"
|
||||||
|
name="categorySelect"
|
||||||
w-full
|
w-full
|
||||||
@selected="selectedCategoryId === 'all' ? navigateTo(`/`) : navigateTo(`/category/${selectedCategoryId}`)"
|
@selected="selectedCategoryId === 'all' ? navigateTo(`/`) : navigateTo(`/category/${selectedCategoryId}`)"
|
||||||
/>
|
/>
|
||||||
|
<CategorySelectBox
|
||||||
|
v-if="usecases?.length"
|
||||||
|
v-model="selectedUsecaseId"
|
||||||
|
name="usecaseSelect"
|
||||||
|
:options="usecaseOptions"
|
||||||
|
w-full
|
||||||
|
/>
|
||||||
|
<CategorySelectBox
|
||||||
|
v-if="ecosystems?.length"
|
||||||
|
v-model="selectedEcosystemId"
|
||||||
|
name="ecosystemSelect"
|
||||||
|
:options="ecosystemOptions"
|
||||||
|
w-full
|
||||||
|
/>
|
||||||
|
<CategorySelectBox
|
||||||
|
v-if="assets?.length"
|
||||||
|
v-model="selectedAssetsUsedId"
|
||||||
|
name="assetsUsedSelect"
|
||||||
|
:options="assetOptions"
|
||||||
|
w-full
|
||||||
|
/>
|
||||||
|
<CategorySelectBox
|
||||||
|
v-if="features?.length"
|
||||||
|
v-model="selectedFeaturesId"
|
||||||
|
name="featuresSelect"
|
||||||
|
:options="featureOptions"
|
||||||
|
w-full
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<SearchBox />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
flex
|
|
||||||
gap-28px
|
|
||||||
items-center
|
|
||||||
my-24px
|
|
||||||
mt-28px
|
|
||||||
>
|
|
||||||
<h2
|
|
||||||
v-if="selectedCategoryId"
|
|
||||||
w-max
|
|
||||||
font-700
|
|
||||||
text-18px
|
|
||||||
sm:text-28px
|
|
||||||
whitespace-nowrap
|
|
||||||
>
|
|
||||||
{{ selectedCategoryId === 'all' ? `${filteredProjectsCount} All Projects` : `${filteredProjectsCount ?? 0} ${selectedCategory?.name}` }}
|
|
||||||
</h2>
|
|
||||||
<div
|
|
||||||
h-2px
|
|
||||||
w="full"
|
|
||||||
bg-white
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
11
package.json
11
package.json
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "develitesse-nuxt",
|
"name": "develitesse-nuxt",
|
||||||
"private": true,
|
"private": true,
|
||||||
"packageManager": "pnpm@9.9.0",
|
"packageManager": "pnpm@9.10.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "nuxt build",
|
"build": "nuxt build",
|
||||||
"cleanup": "nuxt cleanup",
|
"cleanup": "nuxt cleanup",
|
||||||
|
@ -17,9 +17,15 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@formkit/auto-animate": "^0.8.2",
|
"@formkit/auto-animate": "^0.8.2",
|
||||||
|
"@iconify-json/bi": "^1.2.0",
|
||||||
"@iconify-json/heroicons-outline": "^1.2.0",
|
"@iconify-json/heroicons-outline": "^1.2.0",
|
||||||
"@iconify-json/heroicons-solid": "^1.2.0",
|
"@iconify-json/heroicons-solid": "^1.2.0",
|
||||||
"@iconify-json/eos-icons": "^1.1.10",
|
"@iconify-json/eos-icons": "^1.1.10",
|
||||||
|
"@iconify-json/ic": "^1.2.0",
|
||||||
|
"@iconify-json/iconoir": "^1.2.0",
|
||||||
|
"@iconify-json/material-symbols": "^1.2.1",
|
||||||
|
"@iconify-json/mdi": "^1.2.0",
|
||||||
|
"@iconify-json/simple-icons": "^1.2.2",
|
||||||
"@nuxt/devtools": "^1.4.1",
|
"@nuxt/devtools": "^1.4.1",
|
||||||
"@nuxt/eslint": "0.5.5",
|
"@nuxt/eslint": "0.5.5",
|
||||||
"@nuxt/image": "^1.8.0",
|
"@nuxt/image": "^1.8.0",
|
||||||
|
@ -51,5 +57,8 @@
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*": "eslint --fix"
|
"*": "eslint --fix"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"moment": "^2.30.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
const dataStore = useData()
|
const dataStore = useData()
|
||||||
const { selectedCategoryId, filteredProjects } = storeToRefs(dataStore)
|
const { selectedCategoryId, categories, filteredProjects } = storeToRefs(dataStore)
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
|
@ -8,8 +8,10 @@ onMounted(() => {
|
||||||
if (route.params.id)
|
if (route.params.id)
|
||||||
selectedCategoryId.value = route.params.id as string
|
selectedCategoryId.value = route.params.id as string
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const group = computed(() => [{ title: categories.value.find(c => c.id === selectedCategoryId.value)?.name || '', projects: filteredProjects.value }])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ProjectGrid :projects="filteredProjects" />
|
<ProjectGrid :projects="group" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -7,9 +7,11 @@ useSeoMeta({
|
||||||
ogDescription: 'There are challenges in finding crucial technical details and comparing various privacy-focused projects.',
|
ogDescription: 'There are challenges in finding crucial technical details and comparing various privacy-focused projects.',
|
||||||
ogImage: '/web3privacy_eye.webp',
|
ogImage: '/web3privacy_eye.webp',
|
||||||
})
|
})
|
||||||
const { filteredProjects } = storeToRefs(useData())
|
const { groupedProjectsPerCategory } = storeToRefs(useData())
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ProjectGrid :projects="filteredProjects" />
|
<div>
|
||||||
|
<ProjectGrid :projects="groupedProjectsPerCategory" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -32,7 +32,10 @@ useSeoMeta({
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="project">
|
<div v-if="project">
|
||||||
<div app-container>
|
<div
|
||||||
|
app-container
|
||||||
|
px-16px
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
flex
|
flex
|
||||||
flex-col
|
flex-col
|
||||||
|
@ -46,8 +49,7 @@ useSeoMeta({
|
||||||
<ProjectTechnology :project="project" />
|
<ProjectTechnology :project="project" />
|
||||||
<ProjectPrivacy :project="project" />
|
<ProjectPrivacy :project="project" />
|
||||||
<ProjectSecurity :project="project" />
|
<ProjectSecurity :project="project" />
|
||||||
<!-- <ProjectActivity :project="project" />
|
<ProjectHistory :project="project" />
|
||||||
<ProjectMarket /> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
export default defineNuxtPlugin(() => {
|
|
||||||
const appConfig = useAppConfig()
|
|
||||||
|
|
||||||
const githubApi = $fetch.create({
|
|
||||||
baseURL: 'https://api.github.com',
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${appConfig.github.accessToken}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
provide: {
|
|
||||||
githubApi,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
|
@ -7,10 +7,17 @@ settings:
|
||||||
importers:
|
importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
|
dependencies:
|
||||||
|
moment:
|
||||||
|
specifier: ^2.30.1
|
||||||
|
version: 2.30.1
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@formkit/auto-animate':
|
'@formkit/auto-animate':
|
||||||
specifier: ^0.8.2
|
specifier: ^0.8.2
|
||||||
version: 0.8.2
|
version: 0.8.2
|
||||||
|
'@iconify-json/bi':
|
||||||
|
specifier: ^1.2.0
|
||||||
|
version: 1.2.0
|
||||||
'@iconify-json/eos-icons':
|
'@iconify-json/eos-icons':
|
||||||
specifier: ^1.1.10
|
specifier: ^1.1.10
|
||||||
version: 1.2.0
|
version: 1.2.0
|
||||||
|
@ -20,6 +27,21 @@ importers:
|
||||||
'@iconify-json/heroicons-solid':
|
'@iconify-json/heroicons-solid':
|
||||||
specifier: ^1.2.0
|
specifier: ^1.2.0
|
||||||
version: 1.2.0
|
version: 1.2.0
|
||||||
|
'@iconify-json/ic':
|
||||||
|
specifier: ^1.2.0
|
||||||
|
version: 1.2.0
|
||||||
|
'@iconify-json/iconoir':
|
||||||
|
specifier: ^1.2.0
|
||||||
|
version: 1.2.1
|
||||||
|
'@iconify-json/material-symbols':
|
||||||
|
specifier: ^1.2.1
|
||||||
|
version: 1.2.1
|
||||||
|
'@iconify-json/mdi':
|
||||||
|
specifier: ^1.2.0
|
||||||
|
version: 1.2.0
|
||||||
|
'@iconify-json/simple-icons':
|
||||||
|
specifier: ^1.2.2
|
||||||
|
version: 1.2.3
|
||||||
'@nuxt/devtools':
|
'@nuxt/devtools':
|
||||||
specifier: ^1.4.1
|
specifier: ^1.4.1
|
||||||
version: 1.4.1(rollup@4.21.2)(vite@5.4.2(@types/node@20.8.7)(terser@5.22.0))
|
version: 1.4.1(rollup@4.21.2)(vite@5.4.2(@types/node@20.8.7)(terser@5.22.0))
|
||||||
|
@ -1103,6 +1125,9 @@ packages:
|
||||||
resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==}
|
resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==}
|
||||||
engines: {node: '>=18.18'}
|
engines: {node: '>=18.18'}
|
||||||
|
|
||||||
|
'@iconify-json/bi@1.2.0':
|
||||||
|
resolution: {integrity: sha512-kaBV87cQlyeMkBBiMqsf3b43Nsxdk/rYKvR29dnktht57WUyHCnBAuH+ca/bscX856CzRpVX+sYs7arjrJD0qA==}
|
||||||
|
|
||||||
'@iconify-json/eos-icons@1.2.0':
|
'@iconify-json/eos-icons@1.2.0':
|
||||||
resolution: {integrity: sha512-grdfoS20Z4gWAzNPza7ytguNBWeTOkx4Y6aZHs149t2Z6AhW7zG3VWkkq6M+YuL2G8ugHnBw7ZxgazZ6oiMnIQ==}
|
resolution: {integrity: sha512-grdfoS20Z4gWAzNPza7ytguNBWeTOkx4Y6aZHs149t2Z6AhW7zG3VWkkq6M+YuL2G8ugHnBw7ZxgazZ6oiMnIQ==}
|
||||||
|
|
||||||
|
@ -1112,6 +1137,21 @@ packages:
|
||||||
'@iconify-json/heroicons-solid@1.2.0':
|
'@iconify-json/heroicons-solid@1.2.0':
|
||||||
resolution: {integrity: sha512-o+PjtMXPr4wk0veDS7Eh6H1BnTJT1vD7HcKl+I7ixdYQC8i1P2zdtk0C2v7C9OjJBMsiwJSCxT4qQ3OzONgyjw==}
|
resolution: {integrity: sha512-o+PjtMXPr4wk0veDS7Eh6H1BnTJT1vD7HcKl+I7ixdYQC8i1P2zdtk0C2v7C9OjJBMsiwJSCxT4qQ3OzONgyjw==}
|
||||||
|
|
||||||
|
'@iconify-json/ic@1.2.0':
|
||||||
|
resolution: {integrity: sha512-L4+m77xTQB08X3I+3xs1+IrvK+aNcuN/7ODu5aUPznHKLU+/8UYcsjUgNHze6vPOGPQ0AG+kCwvy91EYPXSRxw==}
|
||||||
|
|
||||||
|
'@iconify-json/iconoir@1.2.1':
|
||||||
|
resolution: {integrity: sha512-x55gpORwMGkmmT9UO11rzfMOp40k0ggQnPiOoh9axbyuHrkFMN7pdoCbaXkzqAdShcoI1dLzARbdqXi2sAPJXQ==}
|
||||||
|
|
||||||
|
'@iconify-json/material-symbols@1.2.1':
|
||||||
|
resolution: {integrity: sha512-r9yaBzlUmN87aCTSoCNtDCd7R9F0iVDjNPL9QHHhm1WglFJvTUKx9iBC5xcZpP0qN0bg9R5FkM90CndWxEBAnw==}
|
||||||
|
|
||||||
|
'@iconify-json/mdi@1.2.0':
|
||||||
|
resolution: {integrity: sha512-E9/3l5Syg3wfuarorFodhn4s8YorxhH3U3U20LaNBNiqw1kFNIDWhF6HymuzAD35k7RH0OBasJ+ZUyFtVVV6eg==}
|
||||||
|
|
||||||
|
'@iconify-json/simple-icons@1.2.3':
|
||||||
|
resolution: {integrity: sha512-KZpqyPkDdyAvrpMz9/FYovwFsr3xrHf9esJeBng3iqNInhuZhF33XO1k6Yf8g2p10ynUW7AYEiGJkYzDi4DENQ==}
|
||||||
|
|
||||||
'@iconify/types@2.0.0':
|
'@iconify/types@2.0.0':
|
||||||
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
||||||
|
|
||||||
|
@ -3952,6 +3992,9 @@ packages:
|
||||||
mlly@1.7.1:
|
mlly@1.7.1:
|
||||||
resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==}
|
resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==}
|
||||||
|
|
||||||
|
moment@2.30.1:
|
||||||
|
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
|
||||||
|
|
||||||
mri@1.2.0:
|
mri@1.2.0:
|
||||||
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
@ -6582,6 +6625,10 @@ snapshots:
|
||||||
|
|
||||||
'@humanwhocodes/retry@0.3.0': {}
|
'@humanwhocodes/retry@0.3.0': {}
|
||||||
|
|
||||||
|
'@iconify-json/bi@1.2.0':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
'@iconify-json/eos-icons@1.2.0':
|
'@iconify-json/eos-icons@1.2.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@iconify/types': 2.0.0
|
'@iconify/types': 2.0.0
|
||||||
|
@ -6594,6 +6641,26 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@iconify/types': 2.0.0
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
|
'@iconify-json/ic@1.2.0':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
|
'@iconify-json/iconoir@1.2.1':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
|
'@iconify-json/material-symbols@1.2.1':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
|
'@iconify-json/mdi@1.2.0':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
|
'@iconify-json/simple-icons@1.2.3':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
'@iconify/types@2.0.0': {}
|
'@iconify/types@2.0.0': {}
|
||||||
|
|
||||||
'@iconify/utils@2.1.32':
|
'@iconify/utils@2.1.32':
|
||||||
|
@ -10173,6 +10240,8 @@ snapshots:
|
||||||
pkg-types: 1.2.0
|
pkg-types: 1.2.0
|
||||||
ufo: 1.5.4
|
ufo: 1.5.4
|
||||||
|
|
||||||
|
moment@2.30.1: {}
|
||||||
|
|
||||||
mri@1.2.0: {}
|
mri@1.2.0: {}
|
||||||
|
|
||||||
mrmime@2.0.0: {}
|
mrmime@2.0.0: {}
|
||||||
|
|
|
@ -1,4 +1,77 @@
|
||||||
{
|
{
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"id": "infrastructure",
|
||||||
|
"name": "Infrastructure",
|
||||||
|
"usecases": [
|
||||||
|
"node",
|
||||||
|
"rpc-provider",
|
||||||
|
"infrastructure",
|
||||||
|
"eth-layer-2",
|
||||||
|
"research-and-development",
|
||||||
|
"computing",
|
||||||
|
"storage",
|
||||||
|
"data-management",
|
||||||
|
"other"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "social-and-communications",
|
||||||
|
"name": "Social & Communications",
|
||||||
|
"usecases": [
|
||||||
|
"dao",
|
||||||
|
"nft-community",
|
||||||
|
"alliances",
|
||||||
|
"messaging",
|
||||||
|
"events",
|
||||||
|
"other"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hardware",
|
||||||
|
"name": "Hardware",
|
||||||
|
"usecases": [
|
||||||
|
"wallets",
|
||||||
|
"node",
|
||||||
|
"other"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "applications",
|
||||||
|
"name": "Applications",
|
||||||
|
"usecases": [
|
||||||
|
"browser",
|
||||||
|
"vpn",
|
||||||
|
"did",
|
||||||
|
"operation-systems",
|
||||||
|
"dapps",
|
||||||
|
"wallets",
|
||||||
|
"ai",
|
||||||
|
"kyc-solution",
|
||||||
|
"other"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "defi",
|
||||||
|
"name": "Defi",
|
||||||
|
"usecases": [
|
||||||
|
"bridge",
|
||||||
|
"defi",
|
||||||
|
"mixing-service",
|
||||||
|
"mixing-management",
|
||||||
|
"currency",
|
||||||
|
"other"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "archived-projects",
|
||||||
|
"name": "Archived projects",
|
||||||
|
"usecases": [
|
||||||
|
"legacy-projects",
|
||||||
|
"deprecated-systems"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"projects": [
|
"projects": [
|
||||||
{
|
{
|
||||||
"id": "01-labs",
|
"id": "01-labs",
|
||||||
|
@ -15885,181 +15958,6 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"assets": [
|
|
||||||
{
|
|
||||||
"id": "eth",
|
|
||||||
"name": "Ethereum"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "btc",
|
|
||||||
"name": "Bitcoin"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "usdc",
|
|
||||||
"name": "Coinbase stable"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "usdt",
|
|
||||||
"name": "Tether"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "dai",
|
|
||||||
"name": "MakerDAO stable"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "atom",
|
|
||||||
"name": "Cosmos"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "scrt",
|
|
||||||
"name": "Secret Network"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "dot",
|
|
||||||
"name": "Polkadot"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "sol",
|
|
||||||
"name": "Solana"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "zcash",
|
|
||||||
"name": "Zcash"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "xmr",
|
|
||||||
"name": "Monero"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "other",
|
|
||||||
"name": "Other"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"categories": [
|
|
||||||
{
|
|
||||||
"id": "infrastructure",
|
|
||||||
"name": "Infrastructure",
|
|
||||||
"usecases": [
|
|
||||||
"node",
|
|
||||||
"rpc-provider",
|
|
||||||
"infrastructure",
|
|
||||||
"eth-layer-2",
|
|
||||||
"research-and-development",
|
|
||||||
"computing",
|
|
||||||
"storage",
|
|
||||||
"data-management",
|
|
||||||
"other"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "social-and-communications",
|
|
||||||
"name": "Social & Communications",
|
|
||||||
"usecases": [
|
|
||||||
"dao",
|
|
||||||
"nft-community",
|
|
||||||
"alliances",
|
|
||||||
"messaging",
|
|
||||||
"events",
|
|
||||||
"other"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "hardware",
|
|
||||||
"name": "Hardware",
|
|
||||||
"usecases": [
|
|
||||||
"wallets",
|
|
||||||
"node",
|
|
||||||
"other"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "applications",
|
|
||||||
"name": "Applications",
|
|
||||||
"usecases": [
|
|
||||||
"browser",
|
|
||||||
"vpn",
|
|
||||||
"did",
|
|
||||||
"operation-systems",
|
|
||||||
"dapps",
|
|
||||||
"wallets",
|
|
||||||
"ai",
|
|
||||||
"kyc-solution",
|
|
||||||
"other"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "defi",
|
|
||||||
"name": "Defi",
|
|
||||||
"usecases": [
|
|
||||||
"bridge",
|
|
||||||
"defi",
|
|
||||||
"mixing-service",
|
|
||||||
"mixing-management",
|
|
||||||
"currency",
|
|
||||||
"other"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "archived-projects",
|
|
||||||
"name": "Archived projects",
|
|
||||||
"usecases": [
|
|
||||||
"legacy-projects",
|
|
||||||
"deprecated-systems"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ecosystems": [
|
|
||||||
{
|
|
||||||
"id": "ethereum",
|
|
||||||
"name": "Ethereum"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "bitcoin",
|
|
||||||
"name": "Bitcoin"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "solana",
|
|
||||||
"name": "Solana"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cosmos",
|
|
||||||
"name": "Cosmos"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "monero",
|
|
||||||
"name": "Monero"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "other",
|
|
||||||
"name": "Other"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"id": "no-compliance",
|
|
||||||
"name": "No compliance"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "non-kyc",
|
|
||||||
"name": "Non-KYC"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "private-by-default",
|
|
||||||
"name": "Private by default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "non-custodial",
|
|
||||||
"name": "Non custodial"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "opensource",
|
|
||||||
"name": "Opensource"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "live-on-mainnet",
|
|
||||||
"name": "Live on Mainnet"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"usecases": [
|
"usecases": [
|
||||||
{
|
{
|
||||||
"id": "wallets",
|
"id": "wallets",
|
||||||
|
@ -16227,5 +16125,360 @@
|
||||||
"id": "seed",
|
"id": "seed",
|
||||||
"name": "Seed"
|
"name": "Seed"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"id": "eth",
|
||||||
|
"name": "Ethereum"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "btc",
|
||||||
|
"name": "Bitcoin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "usdc",
|
||||||
|
"name": "Coinbase stable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "usdt",
|
||||||
|
"name": "Tether"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "dai",
|
||||||
|
"name": "MakerDAO stable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "atom",
|
||||||
|
"name": "Cosmos"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "scrt",
|
||||||
|
"name": "Secret Network"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "dot",
|
||||||
|
"name": "Polkadot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "sol",
|
||||||
|
"name": "Solana"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "zcash",
|
||||||
|
"name": "Zcash"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "xmr",
|
||||||
|
"name": "Monero"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "other",
|
||||||
|
"name": "Other"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"id": "no-compliance",
|
||||||
|
"name": "No compliance"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "non-kyc",
|
||||||
|
"name": "Non-KYC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "private-by-default",
|
||||||
|
"name": "Private by default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "non-custodial",
|
||||||
|
"name": "Non custodial"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "opensource",
|
||||||
|
"name": "Opensource"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "live-on-mainnet",
|
||||||
|
"name": "Live on Mainnet"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ecosystems": [
|
||||||
|
{
|
||||||
|
"id": "ethereum",
|
||||||
|
"name": "Ethereum",
|
||||||
|
"icon": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1696501628"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "bitcoin",
|
||||||
|
"name": "Bitcoin",
|
||||||
|
"icon": "https://assets.coingecko.com/coins/images/1/standard/bitcoin.png?1696501400"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "solana",
|
||||||
|
"name": "Solana",
|
||||||
|
"icon": "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1718769756"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cosmos",
|
||||||
|
"name": "Cosmos",
|
||||||
|
"icon": "https://assets.coingecko.com/coins/images/1481/standard/cosmos_hub.png?1696502525"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "monero",
|
||||||
|
"name": "Monero",
|
||||||
|
"icon": "https://assets.coingecko.com/coins/images/69/standard/monero_logo.png?1696501460"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "other",
|
||||||
|
"name": "Other"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ranks": [
|
||||||
|
{
|
||||||
|
"id": "openess",
|
||||||
|
"name": "Openess",
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"field": "team.teammembers",
|
||||||
|
"label": {
|
||||||
|
"name": "Team",
|
||||||
|
"positive": "Member",
|
||||||
|
"negative": "Anonymous"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"points": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "links.docs",
|
||||||
|
"label": {
|
||||||
|
"name": "Documentation",
|
||||||
|
"positive": "Link",
|
||||||
|
"negative": "Not available"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"exists": true
|
||||||
|
},
|
||||||
|
"points": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "links.github",
|
||||||
|
"label": {
|
||||||
|
"name": "Github",
|
||||||
|
"positive": "Link",
|
||||||
|
"negative": "Not available"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"exists": true
|
||||||
|
},
|
||||||
|
"points": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "links.twitter",
|
||||||
|
"label": {
|
||||||
|
"name": "Twitter",
|
||||||
|
"positive": "Link",
|
||||||
|
"negative": "Not available"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"exists": true
|
||||||
|
},
|
||||||
|
"points": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "links.telegram",
|
||||||
|
"label": {
|
||||||
|
"name": "Twitter",
|
||||||
|
"positive": "Link",
|
||||||
|
"negative": "Not available"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"exists": true
|
||||||
|
},
|
||||||
|
"points": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "links.discord",
|
||||||
|
"label": {
|
||||||
|
"name": "Discord",
|
||||||
|
"positive": "Link",
|
||||||
|
"negative": "Not available"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"exists": true
|
||||||
|
},
|
||||||
|
"points": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "links.lens",
|
||||||
|
"label": {
|
||||||
|
"name": "Lens",
|
||||||
|
"positive": "Link",
|
||||||
|
"negative": "Not available"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"exists": true
|
||||||
|
},
|
||||||
|
"points": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "links.farcaster",
|
||||||
|
"label": {
|
||||||
|
"name": "Farcaster",
|
||||||
|
"positive": "Link",
|
||||||
|
"negative": "Not available"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"exists": true
|
||||||
|
},
|
||||||
|
"points": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "links.whitepaper",
|
||||||
|
"label": {
|
||||||
|
"name": "Whitepaper",
|
||||||
|
"positive": "Link",
|
||||||
|
"negative": "Not available"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"exists": true
|
||||||
|
},
|
||||||
|
"points": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "funding.value",
|
||||||
|
"label": {
|
||||||
|
"name": "Funding",
|
||||||
|
"positive": "Investment",
|
||||||
|
"negative": "Not available"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"exists": true
|
||||||
|
},
|
||||||
|
"points": 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "technology",
|
||||||
|
"name": "Technology",
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"field": "project_status.mainnet",
|
||||||
|
"label": {
|
||||||
|
"name": "Mainnet",
|
||||||
|
"positive": "Yes",
|
||||||
|
"negative": "No"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"exists": true
|
||||||
|
},
|
||||||
|
"points": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "blockchain_features.opensource",
|
||||||
|
"label": {
|
||||||
|
"name": "Open Source",
|
||||||
|
"positive": "Yes",
|
||||||
|
"negative": "No"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"equals": true
|
||||||
|
},
|
||||||
|
"points": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "blockchain_features.asset_custody_type",
|
||||||
|
"label": {
|
||||||
|
"name": "Non Custody",
|
||||||
|
"positive": "None",
|
||||||
|
"negative": "Custodial"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"equals": "non-custody"
|
||||||
|
},
|
||||||
|
"points": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "blockchain_features.upgradability.enabled",
|
||||||
|
"label": {
|
||||||
|
"name": "Upgradability",
|
||||||
|
"positive": "Disabled",
|
||||||
|
"negative": "Enabled"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"equals": false
|
||||||
|
},
|
||||||
|
"points": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "audits",
|
||||||
|
"label": {
|
||||||
|
"name": "Audits",
|
||||||
|
"positive": "Audit",
|
||||||
|
"negative": "None"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"points": 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "privacy",
|
||||||
|
"name": "Privacy",
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"field": "privacy_policy.link",
|
||||||
|
"label": {
|
||||||
|
"name": "Privacy Policy",
|
||||||
|
"positive": "Link",
|
||||||
|
"negative": "Not available"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"exists": true
|
||||||
|
},
|
||||||
|
"points": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "traceability.kyc",
|
||||||
|
"label": {
|
||||||
|
"name": "KYC",
|
||||||
|
"positive": "No",
|
||||||
|
"negative": "Yes"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"equals": false
|
||||||
|
},
|
||||||
|
"points": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "compliance",
|
||||||
|
"label": {
|
||||||
|
"name": "Compliance",
|
||||||
|
"positive": "No",
|
||||||
|
"negative": "OFAC"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"equals": true
|
||||||
|
},
|
||||||
|
"points": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "default_privacy",
|
||||||
|
"label": {
|
||||||
|
"name": "Default Privacy",
|
||||||
|
"positive": "YES",
|
||||||
|
"negative": "No"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"equals": true
|
||||||
|
},
|
||||||
|
"points": 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
4
types/asset.ts
Normal file
4
types/asset.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export interface Asset {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
}
|
5
types/ecosystem.ts
Normal file
5
types/ecosystem.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export interface Ecosystem {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
icon?: string
|
||||||
|
}
|
4
types/feature.ts
Normal file
4
types/feature.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export interface Feature {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
}
|
|
@ -7,12 +7,13 @@ export interface Project {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
categories: string[]
|
categories: string[]
|
||||||
usecases: string[]
|
usecases?: string[]
|
||||||
ecosystem?: string[]
|
ecosystem?: string[]
|
||||||
product_readiness?: string
|
product_readiness?: string
|
||||||
security?: string
|
security?: string
|
||||||
have_token?: boolean
|
have_token?: boolean
|
||||||
token_link?: string
|
token_link?: string
|
||||||
|
assets_used?: string[]
|
||||||
tokens?: {
|
tokens?: {
|
||||||
name?: string
|
name?: string
|
||||||
symbol?: string
|
symbol?: string
|
||||||
|
@ -38,13 +39,13 @@ export interface Project {
|
||||||
telegram?: string
|
telegram?: string
|
||||||
discord?: string
|
discord?: string
|
||||||
blog?: string
|
blog?: string
|
||||||
|
governance?: string
|
||||||
facebook?: string
|
facebook?: string
|
||||||
block_explorer?: string
|
block_explorer?: string
|
||||||
whitepaper?: string
|
whitepaper?: string
|
||||||
github?: string
|
github?: string
|
||||||
docs?: string
|
docs?: string
|
||||||
changelog?: string
|
changelog?: string
|
||||||
governance?: string
|
|
||||||
forum?: string
|
forum?: string
|
||||||
snapshot?: string
|
snapshot?: string
|
||||||
lens?: string
|
lens?: string
|
||||||
|
@ -101,7 +102,6 @@ export interface Project {
|
||||||
audits?: Audit[]
|
audits?: Audit[]
|
||||||
social_trust?: string
|
social_trust?: string
|
||||||
technical_spof?: string
|
technical_spof?: string
|
||||||
assets_used?: string[]
|
|
||||||
history?: {
|
history?: {
|
||||||
title?: string
|
title?: string
|
||||||
event_type?: string
|
event_type?: string
|
||||||
|
@ -126,6 +126,7 @@ export interface Project {
|
||||||
url?: string
|
url?: string
|
||||||
[k: string]: unknown
|
[k: string]: unknown
|
||||||
}[]
|
}[]
|
||||||
|
ratings?: ProjectRating[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProjectShallow {
|
export interface ProjectShallow {
|
||||||
|
@ -147,8 +148,28 @@ export interface ProjectShallow {
|
||||||
audits?: Audit[]
|
audits?: Audit[]
|
||||||
support?: number
|
support?: number
|
||||||
anonymity?: boolean
|
anonymity?: boolean
|
||||||
|
categories: string[]
|
||||||
|
usecases?: string[]
|
||||||
|
ecosystem?: string[]
|
||||||
|
assets_used?: string []
|
||||||
|
ratings?: ProjectRating[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProjectIndexable extends Project {
|
export interface ProjectIndexable extends Project {
|
||||||
[key: string]: unknown
|
[key: string]: unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ProjectRating {
|
||||||
|
type: string
|
||||||
|
name: string
|
||||||
|
items: ProjectRatingItem[]
|
||||||
|
points: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProjectRatingItem {
|
||||||
|
isValid: boolean
|
||||||
|
label: string
|
||||||
|
positive: string
|
||||||
|
negative: string
|
||||||
|
value: any
|
||||||
|
}
|
||||||
|
|
24
types/rank.ts
Normal file
24
types/rank.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import type { Project } from './project'
|
||||||
|
|
||||||
|
export interface Rank {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
references: Reference[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Reference {
|
||||||
|
field: keyof Project
|
||||||
|
label: {
|
||||||
|
name: string
|
||||||
|
positive: string
|
||||||
|
negative: string
|
||||||
|
}
|
||||||
|
condition: Condition
|
||||||
|
points: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Condition {
|
||||||
|
minLength?: number
|
||||||
|
exists?: boolean
|
||||||
|
equals?: boolean | string
|
||||||
|
}
|
4
types/usecase.ts
Normal file
4
types/usecase.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export interface Usecase {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
}
|
|
@ -35,5 +35,8 @@ export const collections = {
|
||||||
open1: '<svg xmlns="http://www.w3.org/2000/svg" width="11" height="11" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="gray" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></svg>',
|
open1: '<svg xmlns="http://www.w3.org/2000/svg" width="11" height="11" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="gray" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></svg>',
|
||||||
matrix: '<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M1.266 1.10241V46.8989H4.5615V48.0014H0V0.00141309H4.5615V1.10391L1.266 1.10241ZM15.3525 15.6179V17.9384H15.414C16.032 17.0459 16.782 16.3679 17.6475 15.8819C18.516 15.3974 19.524 15.1559 20.6475 15.1559C21.726 15.1559 22.7175 15.3674 23.61 15.7814C24.5085 16.2029 25.1805 16.9454 25.6485 17.9999C26.157 17.2499 26.853 16.5854 27.7185 16.0154C28.587 15.4454 29.619 15.1559 30.813 15.1559C31.719 15.1559 32.5545 15.2654 33.3285 15.4919C34.11 15.7094 34.767 16.0619 35.3205 16.5464C35.868 17.0399 36.297 17.6729 36.6105 18.4544C36.915 19.2344 37.071 20.1809 37.071 21.2909V32.7434H32.3775V23.0414C32.3775 22.4699 32.3535 21.9239 32.3055 21.4154C32.2755 20.9549 32.157 20.5094 31.947 20.0954C31.7505 19.7189 31.4475 19.4069 31.071 19.2059C30.6885 18.9779 30.1575 18.8699 29.5005 18.8699C28.836 18.8699 28.305 18.9944 27.8985 19.2434C27.501 19.4939 27.165 19.8374 26.9385 20.2439C26.697 20.6744 26.541 21.1499 26.4765 21.6344C26.3985 22.1579 26.361 22.6829 26.352 23.2064V32.7449H21.6555V23.1434C21.6555 22.6349 21.648 22.1354 21.618 21.6434C21.6015 21.1679 21.5085 20.7074 21.3285 20.2694C21.1725 19.8479 20.877 19.4954 20.5005 19.2614C20.118 19.0109 19.5465 18.8789 18.7965 18.8789C18.57 18.8789 18.2745 18.9254 17.9145 19.0274C17.5545 19.1279 17.196 19.3154 16.86 19.5899C16.5165 19.8719 16.218 20.2694 15.9765 20.7854C15.735 21.2999 15.618 21.9794 15.618 22.8239V32.7539H10.9215V15.6224L15.3525 15.6179ZM46.734 46.8974V1.10091H43.4385V-0.00158691H48V47.9984H43.4385V46.8959L46.734 46.8974Z" fill="white"/></svg>',
|
matrix: '<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M1.266 1.10241V46.8989H4.5615V48.0014H0V0.00141309H4.5615V1.10391L1.266 1.10241ZM15.3525 15.6179V17.9384H15.414C16.032 17.0459 16.782 16.3679 17.6475 15.8819C18.516 15.3974 19.524 15.1559 20.6475 15.1559C21.726 15.1559 22.7175 15.3674 23.61 15.7814C24.5085 16.2029 25.1805 16.9454 25.6485 17.9999C26.157 17.2499 26.853 16.5854 27.7185 16.0154C28.587 15.4454 29.619 15.1559 30.813 15.1559C31.719 15.1559 32.5545 15.2654 33.3285 15.4919C34.11 15.7094 34.767 16.0619 35.3205 16.5464C35.868 17.0399 36.297 17.6729 36.6105 18.4544C36.915 19.2344 37.071 20.1809 37.071 21.2909V32.7434H32.3775V23.0414C32.3775 22.4699 32.3535 21.9239 32.3055 21.4154C32.2755 20.9549 32.157 20.5094 31.947 20.0954C31.7505 19.7189 31.4475 19.4069 31.071 19.2059C30.6885 18.9779 30.1575 18.8699 29.5005 18.8699C28.836 18.8699 28.305 18.9944 27.8985 19.2434C27.501 19.4939 27.165 19.8374 26.9385 20.2439C26.697 20.6744 26.541 21.1499 26.4765 21.6344C26.3985 22.1579 26.361 22.6829 26.352 23.2064V32.7449H21.6555V23.1434C21.6555 22.6349 21.648 22.1354 21.618 21.6434C21.6015 21.1679 21.5085 20.7074 21.3285 20.2694C21.1725 19.8479 20.877 19.4954 20.5005 19.2614C20.118 19.0109 19.5465 18.8789 18.7965 18.8789C18.57 18.8789 18.2745 18.9254 17.9145 19.0274C17.5545 19.1279 17.196 19.3154 16.86 19.5899C16.5165 19.8719 16.218 20.2694 15.9765 20.7854C15.735 21.2999 15.618 21.9794 15.618 22.8239V32.7539H10.9215V15.6224L15.3525 15.6179ZM46.734 46.8974V1.10091H43.4385V-0.00158691H48V47.9984H43.4385V46.8959L46.734 46.8974Z" fill="white"/></svg>',
|
||||||
news: '<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28" fill="none"><g opacity="1"><mask id="mask0_2258_10849" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="28" height="28"><rect width="28" height="28" fill="#D9D9D9"/></mask><g mask="url(#mask0_2258_10849)"><path d="M4.66146 24.5C4.01979 24.5 3.47049 24.2715 3.01354 23.8146C2.5566 23.3576 2.32812 22.8083 2.32812 22.1667V5.83333C2.32812 5.19167 2.5566 4.64236 3.01354 4.18542C3.47049 3.72847 4.01979 3.5 4.66146 3.5H23.3281C23.9698 3.5 24.5191 3.72847 24.976 4.18542C25.433 4.64236 25.6615 5.19167 25.6615 5.83333V22.1667C25.6615 22.8083 25.433 23.3576 24.976 23.8146C24.5191 24.2715 23.9698 24.5 23.3281 24.5H4.66146ZM4.66146 22.1667H23.3281V5.83333H4.66146V22.1667ZM6.99479 19.8333H20.9948V17.5H6.99479V19.8333ZM6.99479 15.1667H11.6615V8.16667H6.99479V15.1667ZM13.9948 15.1667H20.9948V12.8333H13.9948V15.1667ZM13.9948 10.5H20.9948V8.16667H13.9948V10.5Z" fill="white"/></g></g></svg>',
|
news: '<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28" fill="none"><g opacity="1"><mask id="mask0_2258_10849" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="28" height="28"><rect width="28" height="28" fill="#D9D9D9"/></mask><g mask="url(#mask0_2258_10849)"><path d="M4.66146 24.5C4.01979 24.5 3.47049 24.2715 3.01354 23.8146C2.5566 23.3576 2.32812 22.8083 2.32812 22.1667V5.83333C2.32812 5.19167 2.5566 4.64236 3.01354 4.18542C3.47049 3.72847 4.01979 3.5 4.66146 3.5H23.3281C23.9698 3.5 24.5191 3.72847 24.976 4.18542C25.433 4.64236 25.6615 5.19167 25.6615 5.83333V22.1667C25.6615 22.8083 25.433 23.3576 24.976 23.8146C24.5191 24.2715 23.9698 24.5 23.3281 24.5H4.66146ZM4.66146 22.1667H23.3281V5.83333H4.66146V22.1667ZM6.99479 19.8333H20.9948V17.5H6.99479V19.8333ZM6.99479 15.1667H11.6615V8.16667H6.99479V15.1667ZM13.9948 15.1667H20.9948V12.8333H13.9948V15.1667ZM13.9948 10.5H20.9948V8.16667H13.9948V10.5Z" fill="white"/></g></g></svg>',
|
||||||
|
arrow_down: '<svg width="10" height="5" viewBox="0 0 10 5" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 5L0 0H10L5 5Z" fill="black"/></svg>',
|
||||||
|
arrow_up: '<svg width="10" height="5" viewBox="0 0 10 5" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 -4.37114e-07L10 5L0 5L5 -4.37114e-07Z" fill="white"/></svg>',
|
||||||
|
thumb_up: '<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><mask id="mask0_308_7787" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16"><rect width="16" height="16" fill="#D9D9D9"/></mask><g mask="url(#mask0_308_7787)"><path d="M11.9987 14.0013H5.33203V5.33464L9.9987 0.667969L10.832 1.5013C10.9098 1.57908 10.9737 1.68464 11.0237 1.81797C11.0737 1.9513 11.0987 2.07908 11.0987 2.2013V2.43464L10.3654 5.33464H13.9987C14.3543 5.33464 14.6654 5.46797 14.932 5.73463C15.1987 6.0013 15.332 6.31241 15.332 6.66797V8.0013C15.332 8.07908 15.3237 8.16241 15.307 8.2513C15.2904 8.34019 15.2654 8.42352 15.232 8.5013L13.232 13.2013C13.132 13.4235 12.9654 13.6124 12.732 13.768C12.4987 13.9235 12.2543 14.0013 11.9987 14.0013ZM3.9987 5.33464V14.0013H1.33203V5.33464H3.9987Z" fill="white"/></g></svg>',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,9 +51,29 @@ export default defineConfig({
|
||||||
bg: {
|
bg: {
|
||||||
grey: '#ffffff33',
|
grey: '#ffffff33',
|
||||||
dark_grey: '#161616',
|
dark_grey: '#161616',
|
||||||
|
rating: {
|
||||||
|
default: '#494949',
|
||||||
|
red: '#FF4218',
|
||||||
|
orange: '#FF9900',
|
||||||
|
yellow: '#FFE600',
|
||||||
|
green: '#42FF00',
|
||||||
|
hover: '#202020',
|
||||||
|
},
|
||||||
|
team: {
|
||||||
|
grey: '#404040',
|
||||||
|
},
|
||||||
|
funding: {
|
||||||
|
card: '#101010',
|
||||||
|
},
|
||||||
|
audits: {
|
||||||
|
card: '#191919',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
grey: '#909090',
|
grey: '#909090',
|
||||||
|
rating: {
|
||||||
|
negative: '#FFB800',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
50
utils/score.ts
Normal file
50
utils/score.ts
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import type { Project, ProjectIndexable, ProjectShallow } from '~/types'
|
||||||
|
|
||||||
|
const fulfilled = (value: any): boolean => {
|
||||||
|
const type = typeof value
|
||||||
|
switch (type) {
|
||||||
|
case 'string':
|
||||||
|
if (value !== '')
|
||||||
|
return true
|
||||||
|
break
|
||||||
|
case 'object':
|
||||||
|
if (Object.keys(value!).length > 0)
|
||||||
|
return true
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
export const calculateScore = (project: ProjectIndexable | ProjectShallow | Project) => {
|
||||||
|
const criterias: { value: keyof ProjectIndexable, key: keyof ProjectIndexable | '' }[] = [
|
||||||
|
{ value: 'product_readiness', key: '' },
|
||||||
|
{ value: 'github', key: 'links' },
|
||||||
|
{ value: 'docs', key: 'links' },
|
||||||
|
{ value: 'team', key: '' },
|
||||||
|
{ value: 'audits', key: '' },
|
||||||
|
]
|
||||||
|
|
||||||
|
let matched = 0
|
||||||
|
for (let i = 0; i < criterias.length; i++) {
|
||||||
|
let value
|
||||||
|
// value = ((criterias[i].key ?? props.project[criterias[i].value as keyof typeof props.project]) ?? null === null) ? null : (props.project as ProjectIndexable)[criterias[i].key][criterias[i].value]
|
||||||
|
|
||||||
|
const indexableProject = project as ProjectIndexable
|
||||||
|
if (criterias[i].key !== '')
|
||||||
|
value = (indexableProject[criterias[i].key] as any)?.[criterias[i].value]
|
||||||
|
else
|
||||||
|
value = indexableProject?.[criterias[i].value]
|
||||||
|
|
||||||
|
// console.log(props.project?.links?.github);
|
||||||
|
// console.log(Object.keys(props.indexableProject["team"]).length);
|
||||||
|
if (value === null || value === undefined)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (fulfilled(value))
|
||||||
|
matched++
|
||||||
|
}
|
||||||
|
|
||||||
|
return 100 / criterias.length * matched
|
||||||
|
}
|
5
utils/text.ts
Normal file
5
utils/text.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import moment from 'moment'
|
||||||
|
|
||||||
|
export function formatDate(date: Date | string) {
|
||||||
|
return moment(date).format('MM / YYYY')
|
||||||
|
}
|
Loading…
Reference in a new issue