mirror of
https://github.com/web3privacy/explorer-app.git
synced 2024-10-15 16:46:26 +02:00
feat: form & github api
This commit is contained in:
parent
c249e433bc
commit
241776eaf1
43 changed files with 3521 additions and 128 deletions
35
app.config.ts
Normal file
35
app.config.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
export default defineAppConfig({
|
||||||
|
github: {
|
||||||
|
appId: 995628,
|
||||||
|
privateKey: `
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEAwkAjU2VY6eUsWm9VrbYyEGZRtY5aSBjWv2O2LvE71F5qOb1E
|
||||||
|
BcXAOVLFP3wU3+y4Nu9Qz9eKumALmKKokzd6KGrVyiIvCOjA8YtzKpHKa24a/TqH
|
||||||
|
ek6z1OvyAH+Zk+PoRGY5KU4YD17Hb81aysO6umI7Hn7NKzuDLHqmE2SmrzXeT7iQ
|
||||||
|
n0+yfwvJPeT+LyCxF42RgPSAzEWhf1Ng/v1neMyr6dfKPKD93KSJJ3rJd1rVZNlY
|
||||||
|
vMAfzR8kmfFEoQqBjtyW+OdTURSTQtjm+wsD+qGT4560mU22ZIY1yzNugsiSKdIG
|
||||||
|
bZR7uLC6Ljg7o0TH+HUCwm3w3N/V8EcWq6AIkQIDAQABAoIBAHR9jjHHB2lM/CpH
|
||||||
|
tjP0nVVkZv/gHJg7/RzNqUXBeUXEUSPLMu3bR4mY751Axiv7hAW9wtLByfo2+v1Q
|
||||||
|
HpQaovF2EDumAFrxajPwkuImiCOg5iKSZQieBg5caMaPvwQHmxTZ0NHKeXdOOX/8
|
||||||
|
wMP0WRjJK/b/x/5zNBkKfGoI5EURlyC7Q6wlmW6DGnFPjy7vC7ZKWj1dKfyNK8ZJ
|
||||||
|
T3absmwGva7cJd3a8nQ1DKK+Tl3RmYoLQpdXPfWDV9/omiSE+EcR0eIm5/v8vQgE
|
||||||
|
UMGv9fPAXo9D5pgEaGqV5zekLUKH2W8xt9pvHDnrjoGSEWGjT88xyJG37DRXa+wR
|
||||||
|
quLZ36ECgYEA648dDFMYyhThxbamtzOFCgBM1FYZGSV4618OIvTeQquuKtWjHnMV
|
||||||
|
2kvl5iUsmLALCLMJeCc8B7Hc4gZsYcm8VrvhvVsv8P1w6ea+wO/g25Q1hKwf9y2k
|
||||||
|
xdgDomAZxrJ7hXy57JTTZBvvUFOdok7jgCQAGWQg4zXTzoR1Hf1sInUCgYEA0xtd
|
||||||
|
xxRiVKh1Ei5sRgdUxE1rixRFhEZCdpu8ha1mC3cDlCCiie3ia4VWAkDN7eU8V0gX
|
||||||
|
DfD4CrxLThWRWlivfT9uhsncXibza9b+QIc0yluReM4+iswA5bd429cZx6kvivgj
|
||||||
|
FtYd0QKyHduxyAjUfB5JAtO2jJN4J3IWyd6y0i0CgYEAwwXKw/BsXqqpPZr6LkUu
|
||||||
|
SVh0Q3xA7UvT7/LT7mcTONmQqhAUK9qWZhRec4ulf4iIqhwoo9y/25MLT+qHgvKV
|
||||||
|
xq1ouPAtIfWCrXSHy48OeF0dbglfsbKNb+tnHuE3lgUhNSRNfiy9U225VaTUppNv
|
||||||
|
0SB9IIiAnfxrrtiFal3tUB0CgYEAt4bwFRXMkorNFFxVduACupIP755U/TTTrSeh
|
||||||
|
Upm3wDncW5evlre/gvgtGNJb9Pi4Z6zdlhoqmbKuyRiJAAFft0RBA19UfGnib5s9
|
||||||
|
+L1SkKXgpySuTJ4kHZFOudibqe+UzH0CjGTjEQUF8l0/hobeq3Tsxk9mQXonGCvg
|
||||||
|
UemQjpUCgYAvooI/aHrWyFZTigM63W5py4e6YMRvrvZbCBu4qougpJ4TQDnG2tMf
|
||||||
|
qW6A1gT6hIC54kGOn6WuO20CVVTZpImEwUYQchsvhsKVAxjp3dq8fw1KIuCPrZAs
|
||||||
|
u1mh4iVpLYIyyyeazf2RhFXBNU49DIS8xYndO970Q9pHZhz629f+qA==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
|
`,
|
||||||
|
installationId: 54778330,
|
||||||
|
},
|
||||||
|
})
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineProps<{
|
defineProps<{
|
||||||
border?: boolean
|
border?: boolean
|
||||||
|
invertedColor?: boolean
|
||||||
}>()
|
}>()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -8,14 +9,14 @@ defineProps<{
|
||||||
<div
|
<div
|
||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
|
justify-center
|
||||||
gap-12px
|
gap-12px
|
||||||
px-12px
|
px-12px
|
||||||
py-6px
|
py-6px
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
text-app-white
|
:class="[border ? 'border-2px border-app-white' : 'border-0',
|
||||||
:class="[border ? 'border-2px border-app-white' : 'border-0']"
|
invertedColor ? 'bg-app-white text-app-black hover:text-app-white hover:bg-app-black' : 'text-app-white bg-app-black hover:text-app-black hover:bg-app-white',
|
||||||
hover:text-app-black
|
]"
|
||||||
hover:bg-app-white
|
|
||||||
>
|
>
|
||||||
<template v-if="!!$slots.prefix">
|
<template v-if="!!$slots.prefix">
|
||||||
<div text-24px>
|
<div text-24px>
|
||||||
|
|
|
@ -27,7 +27,7 @@ function onOptionSelected(value: string) {
|
||||||
<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 w-full cursor-pointer py-8px p-16px text-left border-2px text-app-white sm:text-sm sm:leading-6"
|
||||||
>
|
>
|
||||||
<span class="block truncate mr-8px">{{ isOptionSelected?.label }} <span opacity-50>({{ isOptionSelected?.count }})</span></span>
|
<span class="block truncate mr-8px">{{ isOptionSelected?.label }} <span v-if="isOptionSelected?.count" 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-heroicons-solid-chevron-down
|
||||||
|
@ -61,7 +61,7 @@ function onOptionSelected(value: string) {
|
||||||
:class="[selected ? 'font-semibold' : 'font-normal']"
|
:class="[selected ? 'font-semibold' : 'font-normal']"
|
||||||
>
|
>
|
||||||
{{ option.label }}
|
{{ option.label }}
|
||||||
<span opacity-50>({{ option.count }})</span>
|
<span v-if="option.count" opacity-50>({{ option.count }})</span>
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
</HeadlessListboxOption>
|
</HeadlessListboxOption>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineProps<{
|
defineProps<{
|
||||||
to: string
|
to?: string
|
||||||
}>()
|
}>()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ watch(y, (newY, oldY) => {
|
||||||
lg:bg-app-bg-dark_grey
|
lg:bg-app-bg-dark_grey
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="!isProjectRoute"
|
v-if="!isProjectRoute && !route.fullPath.includes('create') && !route.fullPath.includes('edit')"
|
||||||
relative
|
relative
|
||||||
app-container
|
app-container
|
||||||
w-full
|
w-full
|
||||||
|
@ -355,7 +355,10 @@ watch(y, (newY, oldY) => {
|
||||||
:class="[(!showBar && width < 768) ? 'translate-y--128px' : 'translate-y-0px']"
|
:class="[(!showBar && width < 768) ? 'translate-y--128px' : 'translate-y-0px']"
|
||||||
duration-200ms
|
duration-200ms
|
||||||
>
|
>
|
||||||
<ProjectNavigation md:mt-16px />
|
<ProjectNavigation
|
||||||
|
v-if="!route.fullPath.includes('create') && !route.fullPath.includes('edit')"
|
||||||
|
md:mt-16px
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
|
|
181
components/Project/Create/Categories/Assets.vue
Normal file
181
components/Project/Create/Categories/Assets.vue
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Project } from '~/types'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
project?: Partial<Project>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
type Token = {
|
||||||
|
name: string
|
||||||
|
symbol: string
|
||||||
|
contract_address: string
|
||||||
|
token_link: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function useTokens(project?: Partial<Project>) {
|
||||||
|
const tokens = ref<Token[]>(project?.tokens as Token[] || [])
|
||||||
|
const newToken = reactive<Token>({
|
||||||
|
symbol: '',
|
||||||
|
name: '',
|
||||||
|
contract_address: '',
|
||||||
|
token_link: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
function addToken() {
|
||||||
|
tokens.value.push({ ...newToken })
|
||||||
|
newToken.symbol = ''
|
||||||
|
newToken.name = ''
|
||||||
|
newToken.contract_address = ''
|
||||||
|
newToken.token_link = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeToken(index: number) {
|
||||||
|
tokens.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
tokens,
|
||||||
|
newToken,
|
||||||
|
addToken,
|
||||||
|
removeToken,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 { useProject, assetsData } = useData()
|
||||||
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
saveProject({
|
||||||
|
assets_used: assetsUsed.value,
|
||||||
|
have_token: tokens.value.length > 0 && tokens.value.some(token => token.contract_address),
|
||||||
|
tokens: tokens.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
save,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div mt-24px>
|
||||||
|
<ClientOnly>
|
||||||
|
<ProjectCreateComponentsSelectChips
|
||||||
|
v-model="assetsUsed"
|
||||||
|
label="Assets used"
|
||||||
|
:options="assetsData?.map(asset => ({ label: asset.name, value: asset.id }))"
|
||||||
|
placeholder="Add assets"
|
||||||
|
hint="Most used assets user can use to interact with your project"
|
||||||
|
can-add-new
|
||||||
|
/>
|
||||||
|
</ClientOnly>
|
||||||
|
<ProjectCreateComponentsCategoryDivider
|
||||||
|
w-full
|
||||||
|
title="NATIVE TOKENS"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsItem
|
||||||
|
v-for="token in tokens"
|
||||||
|
:key="token.name"
|
||||||
|
@remove="() => removeToken(tokens.indexOf(token))"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
gap-2px
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="text-app-black text-14px font-700"
|
||||||
|
lg="text-16px"
|
||||||
|
> {{ token.symbol }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="token.name"
|
||||||
|
class="text-app-black text-14px font-400"
|
||||||
|
lg="text-16px"
|
||||||
|
> {{ `(${token.name})` }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #desc>
|
||||||
|
<NuxtLink
|
||||||
|
target="_blank"
|
||||||
|
:to="token.token_link"
|
||||||
|
hover:text-app-black
|
||||||
|
class="text-app-black/50 text-16px hidden"
|
||||||
|
lg="block"
|
||||||
|
>Etherscan
|
||||||
|
</NuxtLink>
|
||||||
|
</template>
|
||||||
|
</ProjectCreateComponentsItem>
|
||||||
|
<ProjectCreateComponentsItemAdd
|
||||||
|
button-label="ADD TOKEN"
|
||||||
|
@add="addToken()"
|
||||||
|
>
|
||||||
|
<template #content>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-16px
|
||||||
|
lg="gap-24px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-8px
|
||||||
|
lg="flex-row gap-24px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="w-100%"
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-16px
|
||||||
|
lg="flex-row gap-24px"
|
||||||
|
>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="newToken.symbol"
|
||||||
|
w-full
|
||||||
|
label="Token symbol"
|
||||||
|
placeholder="Token symbol"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="newToken.name"
|
||||||
|
w-full
|
||||||
|
label="Token name"
|
||||||
|
placeholder="Token name"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="w-100%"
|
||||||
|
lg="mt-32px left-1/2 self-center"
|
||||||
|
font-400
|
||||||
|
italic
|
||||||
|
lg:text-14px
|
||||||
|
text-12px
|
||||||
|
text-app-white
|
||||||
|
opacity-50
|
||||||
|
>
|
||||||
|
{{ 'Does your project have native token? Enter Symbol, name and address' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="newToken.contract_address"
|
||||||
|
lg="w-1/2"
|
||||||
|
label="Token contract address"
|
||||||
|
placeholder="Contract address"
|
||||||
|
hint="Enter token contract address"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="newToken.token_link"
|
||||||
|
lg="w-1/2"
|
||||||
|
label="URL for explorer"
|
||||||
|
placeholder="Token explorer URL"
|
||||||
|
hint="Link to any explorer showing data about your native token"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</ProjectCreateComponentsItemAdd>
|
||||||
|
</div>
|
||||||
|
</template>
|
130
components/Project/Create/Categories/BasicInfo.vue
Normal file
130
components/Project/Create/Categories/BasicInfo.vue
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import * as yup from 'yup'
|
||||||
|
import type { Project } from '~/types'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
project?: Partial<Project>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const { useProject, categoriesData, usecasesData, ecosystemsData } = useData()
|
||||||
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
|
const validationSchema = yup.object().shape({
|
||||||
|
categories: yup.array().of(yup.string()).required().min(1),
|
||||||
|
usecases: yup.array().of(yup.string()).required().min(1),
|
||||||
|
ecosystems: yup.array().of(yup.string()).required().min(1),
|
||||||
|
description: yup.string().required(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const { validate, meta, resetForm } = useForm({
|
||||||
|
validationSchema,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { value: categories, errorMessage: categoriesError } = useField<string[]>('categories')
|
||||||
|
const { value: usecases, errorMessage: usecasesError } = useField<string[]>('usecases')
|
||||||
|
const { value: ecosystems, errorMessage: ecosystemsError } = useField<string[]>('ecosystems')
|
||||||
|
const { value: description, errorMessage: descriptionError } = useField<string>('description')
|
||||||
|
const day = ref(new Date(props.project?.product_launch_day || '').getDay())
|
||||||
|
const month = ref(new Date(props.project?.product_launch_day || '').getMonth())
|
||||||
|
const year = ref(new Date(props.project?.product_launch_day || '').getFullYear())
|
||||||
|
const isDead = ref(props.project?.sunset || false)
|
||||||
|
|
||||||
|
resetForm({
|
||||||
|
values: {
|
||||||
|
categories: props.project?.categories?.map(c => c.toLowerCase()) || [],
|
||||||
|
usecases: props.project?.usecases?.map(u => u.toLowerCase()) || [],
|
||||||
|
ecosystems: Array.isArray(props.project?.ecosystem) ? props.project?.ecosystem?.map(e => e.toLowerCase()) : [],
|
||||||
|
description: props.project?.description || '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
function isFormValid() {
|
||||||
|
validate()
|
||||||
|
|
||||||
|
if (meta.value.valid) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
saveProject({
|
||||||
|
categories: categories.value,
|
||||||
|
usecases: usecases.value,
|
||||||
|
ecosystem: ecosystems.value,
|
||||||
|
description: description.value,
|
||||||
|
product_launch_day: new Date(year.value, month.value, day.value).toISOString(),
|
||||||
|
sunset: isDead.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
isFormValid,
|
||||||
|
save,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div mt-24px>
|
||||||
|
<ClientOnly>
|
||||||
|
<ProjectCreateComponentsSelectChips
|
||||||
|
v-model="categories"
|
||||||
|
label="Categories"
|
||||||
|
required
|
||||||
|
:options="categoriesData?.map(cat => ({ label: cat.name, value: cat.id }))"
|
||||||
|
placeholder="Add category"
|
||||||
|
hint="Choose categories that fits your project"
|
||||||
|
:error="categoriesError"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsSelectChips
|
||||||
|
v-model="usecases"
|
||||||
|
label="Use-cases"
|
||||||
|
required
|
||||||
|
:options="usecasesData?.map(uc => ({ label: uc.name, value: uc.id }))"
|
||||||
|
placeholder="Add use-case"
|
||||||
|
hint="What can be your project used for?"
|
||||||
|
:error="usecasesError"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsSelectChips
|
||||||
|
v-model="ecosystems"
|
||||||
|
label="Ecosystems"
|
||||||
|
required
|
||||||
|
:options="ecosystemsData?.map(ec => ({ label: ec.name, value: ec.id }))"
|
||||||
|
placeholder="Add ecosystem"
|
||||||
|
hint="Choose ecosystems that is your project part of"
|
||||||
|
:error="ecosystemsError"
|
||||||
|
/>
|
||||||
|
</ClientOnly>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="description"
|
||||||
|
lg="w-1/2"
|
||||||
|
label="Description"
|
||||||
|
text-area
|
||||||
|
required
|
||||||
|
hint="What kind of technology you use, what are your special features
|
||||||
|
and why should user use your project."
|
||||||
|
placeholder="Write something about your project"
|
||||||
|
:error="descriptionError"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsDatePicker
|
||||||
|
v-model:day="day"
|
||||||
|
v-model:month="month"
|
||||||
|
v-model:year="year"
|
||||||
|
label="Project launch date"
|
||||||
|
hint="Date of project emergence (Optional)"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
text-16px
|
||||||
|
font-400
|
||||||
|
lg="text-16px"
|
||||||
|
>Other Information
|
||||||
|
</span>
|
||||||
|
<ProjectCreateComponentsToggle
|
||||||
|
v-model="isDead"
|
||||||
|
label="Sunset (project is dead)"
|
||||||
|
hint="Check if project is currently running and working"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
116
components/Project/Create/Categories/Funding.vue
Normal file
116
components/Project/Create/Categories/Funding.vue
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Project } from '~/types'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
project?: Partial<Project>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
type Fundings = {
|
||||||
|
name: string
|
||||||
|
link: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function useFundings(project?: Partial<Project>) {
|
||||||
|
const fundings = ref<Fundings[]>(project?.funding as Fundings[] || [])
|
||||||
|
const newFunding = reactive<Fundings>({
|
||||||
|
name: '',
|
||||||
|
link: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
function addFunding() {
|
||||||
|
fundings.value.push({ ...newFunding })
|
||||||
|
newFunding.name = ''
|
||||||
|
newFunding.link = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeFunding(index: number) {
|
||||||
|
fundings.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
fundings,
|
||||||
|
newFunding,
|
||||||
|
addFunding,
|
||||||
|
removeFunding,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { fundings, newFunding, addFunding, removeFunding } = useFundings(props.project)
|
||||||
|
|
||||||
|
const { useProject } = useData()
|
||||||
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
saveProject({
|
||||||
|
funding: fundings.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
save,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ProjectCreateComponentsCategoryDivider
|
||||||
|
w-full
|
||||||
|
title="FUNDING"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsItem
|
||||||
|
v-for="funding in fundings"
|
||||||
|
:key="funding.name"
|
||||||
|
@remove="() => removeFunding(fundings.indexOf(funding))"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
gap-2px
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="text-app-black text-14px font-700"
|
||||||
|
lg="text-16px"
|
||||||
|
> {{ funding.name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #desc>
|
||||||
|
<NuxtLink
|
||||||
|
:to="funding.link"
|
||||||
|
hover:text-app-black
|
||||||
|
class="text-app-black/50 text-16px hidden"
|
||||||
|
lg="block"
|
||||||
|
>Link
|
||||||
|
</NuxtLink>
|
||||||
|
</template>
|
||||||
|
</ProjectCreateComponentsItem>
|
||||||
|
<ProjectCreateComponentsItemAdd
|
||||||
|
button-label="ADD FUNDING"
|
||||||
|
@add="addFunding()"
|
||||||
|
>
|
||||||
|
<template #content>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-16px
|
||||||
|
lg="gap-24px"
|
||||||
|
>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="newFunding.name"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Name"
|
||||||
|
placeholder="Investor's name"
|
||||||
|
hint="Name of entity investing into project"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="newFunding.link"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Link confirming investment"
|
||||||
|
placeholder="Add URL"
|
||||||
|
hint="Link to Article, PR or other sources confirming funding information"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</ProjectCreateComponentsItemAdd>
|
||||||
|
</div>
|
||||||
|
</template>
|
166
components/Project/Create/Categories/History.vue
Normal file
166
components/Project/Create/Categories/History.vue
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Project } from '~/types'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
project?: Partial<Project>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
type Event = {
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
link: string
|
||||||
|
time: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function useEvents(project?: Partial<Project>) {
|
||||||
|
const events = ref<Event[]>(project?.history as Event[] || [])
|
||||||
|
const newEvent = reactive<Event>({
|
||||||
|
title: '',
|
||||||
|
description: '',
|
||||||
|
link: '',
|
||||||
|
time: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const day = ref<number>()
|
||||||
|
const month = ref<number>()
|
||||||
|
const year = ref<number>()
|
||||||
|
|
||||||
|
function addEvent() {
|
||||||
|
events.value.push({ ...newEvent })
|
||||||
|
newEvent.title = ''
|
||||||
|
newEvent.description = ''
|
||||||
|
newEvent.link = ''
|
||||||
|
newEvent.time = ''
|
||||||
|
day.value = undefined
|
||||||
|
month.value = undefined
|
||||||
|
year.value = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeEvent(index: number) {
|
||||||
|
events.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
events,
|
||||||
|
newEvent,
|
||||||
|
day,
|
||||||
|
month,
|
||||||
|
year,
|
||||||
|
addEvent,
|
||||||
|
removeEvent,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { events, newEvent, addEvent, removeEvent, day, month, year } = useEvents(props.project)
|
||||||
|
|
||||||
|
watch([day, month, year], () => {
|
||||||
|
const yearValue = year.value
|
||||||
|
const monthValue = month.value
|
||||||
|
const dayValue = day.value
|
||||||
|
|
||||||
|
if (!yearValue || !monthValue || !dayValue) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
newEvent.time = new Date(yearValue, monthValue - 1, dayValue).toString()
|
||||||
|
})
|
||||||
|
|
||||||
|
function formatDate(date: string) {
|
||||||
|
const d = new Date(date)
|
||||||
|
const day = String(d.getDate()).padStart(2, '0')
|
||||||
|
const month = String(d.getMonth() + 1).padStart(2, '0')
|
||||||
|
const year = d.getFullYear()
|
||||||
|
return `${day}/${month}/${year}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const { useProject } = useData()
|
||||||
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
saveProject({
|
||||||
|
history: events.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
save,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div mt-24px>
|
||||||
|
<ProjectCreateComponentsItem
|
||||||
|
v-for="event in events"
|
||||||
|
:key="event.title"
|
||||||
|
@remove="() => removeEvent(events.indexOf(event))"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
gap-2px
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="text-app-black text-14px font-700"
|
||||||
|
lg="text-16px"
|
||||||
|
> {{ event.title }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #desc>
|
||||||
|
<span
|
||||||
|
class="text-app-black/50 text-16px hidden"
|
||||||
|
lg="block"
|
||||||
|
>{{ formatDate(event.time) }}
|
||||||
|
</span>
|
||||||
|
<NuxtLink
|
||||||
|
:to="event.link"
|
||||||
|
hover:text-app-black
|
||||||
|
class="text-app-black/50 text-16px hidden"
|
||||||
|
lg="block"
|
||||||
|
>Link
|
||||||
|
</NuxtLink>
|
||||||
|
</template>
|
||||||
|
</ProjectCreateComponentsItem>
|
||||||
|
<ProjectCreateComponentsItemAdd
|
||||||
|
button-label="ADD EVENT"
|
||||||
|
@add="addEvent()"
|
||||||
|
>
|
||||||
|
<template #content>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-16px
|
||||||
|
lg="gap-24px"
|
||||||
|
>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="newEvent.title"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Event title"
|
||||||
|
placeholder="Enter title of event"
|
||||||
|
hint="Specific name of events (or what happened)"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="newEvent.description"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Event description"
|
||||||
|
placeholder="Describe this event"
|
||||||
|
hint="Detailed description of event (max. 1000 glyphs)"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="newEvent.link"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Event URL"
|
||||||
|
placeholder="Enter URL with event details"
|
||||||
|
hint="Link to Article, PR or other sources confirming event information"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsDatePicker
|
||||||
|
v-model:day="day"
|
||||||
|
v-model:month="month"
|
||||||
|
v-model:year="year"
|
||||||
|
label="Date of event"
|
||||||
|
placeholder="When this event happened?"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</ProjectCreateComponentsItemAdd>
|
||||||
|
</div>
|
||||||
|
</template>
|
160
components/Project/Create/Categories/Links.vue
Normal file
160
components/Project/Create/Categories/Links.vue
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Project } from '~/types'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
project?: Partial<Project>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const web = ref<string>(props.project?.links?.web || '')
|
||||||
|
const blog = ref<string>(props.project?.links?.blog || '')
|
||||||
|
const github = ref<string>(props.project?.links?.github || '')
|
||||||
|
const forum = ref<string>(props.project?.links?.forum || '')
|
||||||
|
const docs = ref<string>(props.project?.links?.docs || '')
|
||||||
|
const whitepaper = ref<string>(props.project?.links?.whitepaper || '')
|
||||||
|
const block_explorer = ref<string>(props.project?.links?.block_explorer || '')
|
||||||
|
const governance = ref<string>(props.project?.links?.governance || '')
|
||||||
|
const twitter = ref<string>(props.project?.links?.twitter || '')
|
||||||
|
const discord = ref<string>(props.project?.links?.discord || '')
|
||||||
|
const telegram = ref<string>(props.project?.links?.telegram || '')
|
||||||
|
const lens = ref<string>(props.project?.links?.lens || '')
|
||||||
|
const farcaster = ref<string>(props.project?.links?.farcaster || '')
|
||||||
|
|
||||||
|
const { useProject } = useData()
|
||||||
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
saveProject({
|
||||||
|
links: {
|
||||||
|
web: web.value,
|
||||||
|
blog: blog.value,
|
||||||
|
github: github.value,
|
||||||
|
forum: forum.value,
|
||||||
|
docs: docs.value,
|
||||||
|
whitepaper: whitepaper.value,
|
||||||
|
block_explorer: block_explorer.value,
|
||||||
|
governance: governance.value,
|
||||||
|
twitter: twitter.value,
|
||||||
|
discord: discord.value,
|
||||||
|
telegram: telegram.value,
|
||||||
|
lens: lens.value,
|
||||||
|
farcaster: farcaster.value,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
save,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div mt-24px>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-16px
|
||||||
|
lg="grid grid-cols-2 gap-24px"
|
||||||
|
>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="web"
|
||||||
|
w-full
|
||||||
|
label="Website"
|
||||||
|
placeholder="ex. https://www.yourproject.com"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="blog"
|
||||||
|
w-full
|
||||||
|
label="Blog"
|
||||||
|
placeholder="https://blog,yourproject.com"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="github"
|
||||||
|
w-full
|
||||||
|
label="Github repository"
|
||||||
|
placeholder="Github.com/Yourproject"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="forum"
|
||||||
|
w-full
|
||||||
|
label="Forum"
|
||||||
|
placeholder="https://forum,yourproject.com"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ProjectCreateComponentsCategoryDivider
|
||||||
|
w-full
|
||||||
|
title="TECHNOGY DETAILS"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-16px
|
||||||
|
lg="grid grid-cols-2 gap-24px"
|
||||||
|
>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="docs"
|
||||||
|
w-full
|
||||||
|
label="Documentation"
|
||||||
|
placeholder="https://docs.yourproject.com"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="whitepaper"
|
||||||
|
w-full
|
||||||
|
label="Whitepaper"
|
||||||
|
placeholder="https://www.yourproject.com/whitepaper.pdf"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="block_explorer"
|
||||||
|
w-full
|
||||||
|
label="Explorer"
|
||||||
|
placeholder="https://explorer.yourproject.com"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="governance"
|
||||||
|
w-full
|
||||||
|
label="Governance"
|
||||||
|
placeholder="https://governance.yourproject.com"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ProjectCreateComponentsCategoryDivider
|
||||||
|
w-full
|
||||||
|
title="SOCIAL NETWORKS"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-16px
|
||||||
|
lg="grid grid-cols-2 gap-24px"
|
||||||
|
>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="twitter"
|
||||||
|
w-full
|
||||||
|
label="Twitter"
|
||||||
|
placeholder="Twitter profile URL"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="discord"
|
||||||
|
w-full
|
||||||
|
label="Discord"
|
||||||
|
placeholder="Discord invite link"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="telegram"
|
||||||
|
w-full
|
||||||
|
label="Telegram"
|
||||||
|
placeholder="Telegram channel URL"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="lens"
|
||||||
|
w-full
|
||||||
|
label="Lens"
|
||||||
|
placeholder="Lens profile URL"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="farcaster"
|
||||||
|
w-full
|
||||||
|
label="Farcaster"
|
||||||
|
placeholder="Farcaster profile URL"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
104
components/Project/Create/Categories/Privacy.vue
Normal file
104
components/Project/Create/Categories/Privacy.vue
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Project } from '~/types'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
project?: Partial<Project>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const privacyPolicyUrl = ref(props.project?.privacy_policy?.link || '')
|
||||||
|
const compliance = ref(props.project?.compliance || '')
|
||||||
|
const kyc = ref(props.project?.tracebility?.kyc || false)
|
||||||
|
const defaultPrivacy = ref(props.project?.default_privacy || false)
|
||||||
|
const signRequirements = ref(Array.isArray(props.project?.tracebility?.sign_in_type_requirments) ? props.project?.tracebility?.sign_in_type_requirments?.map(s => s.toLowerCase()) : [])
|
||||||
|
const trackedData = ref(props.project?.tracebility?.tracked_data || '')
|
||||||
|
const dataUsage = ref(props.project?.privacy_policy?.data_usage || '')
|
||||||
|
|
||||||
|
const { useProject, signInRequirmentsData } = useData()
|
||||||
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
saveProject({
|
||||||
|
privacy_policy: {
|
||||||
|
defined: privacyPolicyUrl.value ? true : false,
|
||||||
|
link: privacyPolicyUrl.value,
|
||||||
|
data_usage: dataUsage.value,
|
||||||
|
},
|
||||||
|
compliance: compliance.value,
|
||||||
|
tracebility: {
|
||||||
|
kyc: kyc.value,
|
||||||
|
tracked_data: trackedData.value,
|
||||||
|
},
|
||||||
|
default_privacy: defaultPrivacy.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
save,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div mt-24px>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-24px
|
||||||
|
>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="privacyPolicyUrl"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Link to project’s Privacy Policy"
|
||||||
|
placeholder="https://policy.yourproject.com"
|
||||||
|
hint="URL of document defining you privacy policy and data usage"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="compliance"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Compliance"
|
||||||
|
placeholder="Enter compliance that project follow"
|
||||||
|
hint="Is project Compliant with regulations? (ex. OFAC, Privacy Act)"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsToggle
|
||||||
|
v-model="kyc"
|
||||||
|
label="KYC (Know your customer)"
|
||||||
|
hint="Is project requiering KYC for its users?"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsToggle
|
||||||
|
v-model="defaultPrivacy"
|
||||||
|
label="Defult privacy"
|
||||||
|
hint="Is maximum privacy turned on by default,"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ProjectCreateComponentsCategoryDivider
|
||||||
|
w-full
|
||||||
|
title="ADDITIONAL INFO"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-24px
|
||||||
|
>
|
||||||
|
<ProjectCreateComponentsSelectChips
|
||||||
|
v-model="signRequirements"
|
||||||
|
label="Sign-in requirements"
|
||||||
|
:options="signInRequirmentsData.map(s => ({ label: s.name, value: s.id }))"
|
||||||
|
placeholder="Add requirement"
|
||||||
|
hint="What do you need to provide to use your project?"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="trackedData"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Tracked data"
|
||||||
|
placeholder="Enter tracked data"
|
||||||
|
hint="What data does project collect? (ex. IP, Location, E-mail, Wallet,...)"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="dataUsage"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Data usage"
|
||||||
|
placeholder="What are you using data for?"
|
||||||
|
hint="How does project use user info (resseling, information gathering, none,...)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
199
components/Project/Create/Categories/Security.vue
Normal file
199
components/Project/Create/Categories/Security.vue
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Project } from '~/types'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
project?: Partial<Project>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
type Audit = {
|
||||||
|
name: string
|
||||||
|
url: string
|
||||||
|
time: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function useAudits(project?: Partial<Project>) {
|
||||||
|
const audits = ref<Audit[]>(project?.audits as Audit[] || [])
|
||||||
|
const newAudit = reactive<Audit>({
|
||||||
|
name: '',
|
||||||
|
url: '',
|
||||||
|
time: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const day = ref<number>()
|
||||||
|
const month = ref<number>()
|
||||||
|
const year = ref<number>()
|
||||||
|
|
||||||
|
function addAudit() {
|
||||||
|
audits.value.push({ ...newAudit })
|
||||||
|
newAudit.name = ''
|
||||||
|
newAudit.url = ''
|
||||||
|
newAudit.time = ''
|
||||||
|
day.value = undefined
|
||||||
|
month.value = undefined
|
||||||
|
year.value = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeAudit(index: number) {
|
||||||
|
audits.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
audits,
|
||||||
|
newAudit,
|
||||||
|
day,
|
||||||
|
month,
|
||||||
|
year,
|
||||||
|
addAudit,
|
||||||
|
removeAudit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { audits, newAudit, addAudit, removeAudit, day, month, year } = useAudits(props.project)
|
||||||
|
|
||||||
|
watch([day, month, year], () => {
|
||||||
|
const yearValue = year.value
|
||||||
|
const monthValue = month.value
|
||||||
|
const dayValue = day.value
|
||||||
|
|
||||||
|
if (!yearValue || !monthValue || !dayValue) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
newAudit.time = new Date(yearValue, monthValue - 1, dayValue).toString()
|
||||||
|
})
|
||||||
|
|
||||||
|
function formatDate(date: string) {
|
||||||
|
const d = new Date(date)
|
||||||
|
const day = String(d.getDate()).padStart(2, '0')
|
||||||
|
const month = String(d.getMonth() + 1).padStart(2, '0')
|
||||||
|
const year = d.getFullYear()
|
||||||
|
return `${day}/${month}/${year}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const thirdPartyDep = ref(props.project?.third_party_dependency || '')
|
||||||
|
const socialTrust = ref(props.project?.social_trust || '')
|
||||||
|
const spof = ref(props.project?.technical_spof || '')
|
||||||
|
|
||||||
|
const { useProject } = useData()
|
||||||
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
saveProject({
|
||||||
|
audits: audits.value,
|
||||||
|
third_party_dependency: thirdPartyDep.value,
|
||||||
|
social_trust: socialTrust.value,
|
||||||
|
technical_spof: spof.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
save,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ProjectCreateComponentsCategoryDivider
|
||||||
|
w-full
|
||||||
|
title="AUDITS"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsItem
|
||||||
|
v-for="audit in audits"
|
||||||
|
:key="audit.name"
|
||||||
|
@remove="() => removeAudit(audits.indexOf(audit))"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
gap-2px
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="text-app-black text-14px font-700"
|
||||||
|
lg="text-16px"
|
||||||
|
> {{ audit.name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #desc>
|
||||||
|
<span
|
||||||
|
class="text-app-black/50 text-16px hidden"
|
||||||
|
lg="block"
|
||||||
|
>{{ formatDate(audit.time) }}
|
||||||
|
</span>
|
||||||
|
<NuxtLink
|
||||||
|
target="_blank"
|
||||||
|
:to="audit.url"
|
||||||
|
hover:text-app-black
|
||||||
|
class="text-app-black/50 text-16px hidden"
|
||||||
|
lg="block"
|
||||||
|
>Link
|
||||||
|
</NuxtLink>
|
||||||
|
</template>
|
||||||
|
</ProjectCreateComponentsItem>
|
||||||
|
<ProjectCreateComponentsItemAdd
|
||||||
|
button-label="ADD AUDIT"
|
||||||
|
@add="addAudit()"
|
||||||
|
>
|
||||||
|
<template #content>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-16px
|
||||||
|
lg="gap-24px"
|
||||||
|
>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="newAudit.name"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Audit name"
|
||||||
|
placeholder="Audit name"
|
||||||
|
hint="Title and Name of audit company"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="newAudit.url"
|
||||||
|
lg="w-50%"
|
||||||
|
label="URL of audit"
|
||||||
|
placeholder="URL of audit"
|
||||||
|
hint="Enter URL of audit"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsDatePicker
|
||||||
|
v-model:day="day"
|
||||||
|
v-model:month="month"
|
||||||
|
v-model:year="year"
|
||||||
|
label="Date of audit"
|
||||||
|
placeholder="When has been project audited?"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</ProjectCreateComponentsItemAdd>
|
||||||
|
<ProjectCreateComponentsCategoryDivider
|
||||||
|
w-full
|
||||||
|
title="ADDITIONAL INFO"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="thirdPartyDep"
|
||||||
|
textarea
|
||||||
|
:textarea-rows="3"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Third party dependency"
|
||||||
|
placeholder="Write about dependencies"
|
||||||
|
hint="Is your project dependend on third service like Uniswap pools, Network or third party contract, Chainlink oracle,...?"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="socialTrust"
|
||||||
|
textarea
|
||||||
|
:textarea-rows="3"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Social trust"
|
||||||
|
placeholder="Who does project trust with treasury and security?"
|
||||||
|
hint="Who is governing project and how? DAO, Multisig wallet of X,"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="spof"
|
||||||
|
textarea
|
||||||
|
:textarea-rows="3"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Single point of failure"
|
||||||
|
placeholder="What is single point of failture for project"
|
||||||
|
hint="What have to happen to shutdown, hack project or leak data? ex. Hack of SHA256, Stolen admin keys,..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
127
components/Project/Create/Categories/Team.vue
Normal file
127
components/Project/Create/Categories/Team.vue
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Project } from '~/types'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
project?: Partial<Project>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const isAnonymousTeam = ref<boolean>(props.project?.team?.anonymous || false)
|
||||||
|
|
||||||
|
type Member = {
|
||||||
|
name: string
|
||||||
|
link: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function useMembers(project?: Partial<Project>) {
|
||||||
|
const members = ref<Member[]>(project?.team?.teammembers as Member[] || [])
|
||||||
|
const newMember = reactive<Member>({
|
||||||
|
name: '',
|
||||||
|
link: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
function addMember() {
|
||||||
|
members.value.push({ ...newMember })
|
||||||
|
newMember.name = ''
|
||||||
|
newMember.link = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeMember(index: number) {
|
||||||
|
members.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
members,
|
||||||
|
newMember,
|
||||||
|
addMember,
|
||||||
|
removeMember,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { members, newMember, addMember, removeMember } = useMembers(props.project)
|
||||||
|
|
||||||
|
const { useProject } = useData()
|
||||||
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
saveProject({
|
||||||
|
team: {
|
||||||
|
anonymous: isAnonymousTeam.value,
|
||||||
|
teammembers: members.value,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
save,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div mt-24px>
|
||||||
|
<ProjectCreateComponentsToggle
|
||||||
|
v-model="isAnonymousTeam"
|
||||||
|
label="Anonymous team"
|
||||||
|
hint="Are developers able to upgrade and change deployed contract?"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsCategoryDivider
|
||||||
|
w-full
|
||||||
|
title="TEAM MEMBERS"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsItem
|
||||||
|
v-for="member in members"
|
||||||
|
:key="member.name"
|
||||||
|
@remove="() => removeMember(members.indexOf(member))"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
gap-2px
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="text-app-black text-14px font-700"
|
||||||
|
lg="text-16px"
|
||||||
|
> {{ member.name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #desc>
|
||||||
|
<NuxtLink
|
||||||
|
target="_blank"
|
||||||
|
:to="member.link"
|
||||||
|
hover:text-app-black
|
||||||
|
class="text-app-black/50 text-16px hidden"
|
||||||
|
lg="block"
|
||||||
|
>Link
|
||||||
|
</NuxtLink>
|
||||||
|
</template>
|
||||||
|
</ProjectCreateComponentsItem>
|
||||||
|
<ProjectCreateComponentsItemAdd
|
||||||
|
button-label="ADD MEMBER"
|
||||||
|
@add="addMember()"
|
||||||
|
>
|
||||||
|
<template #content>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-16px
|
||||||
|
lg="gap-24px"
|
||||||
|
>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="newMember.name"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Team member name"
|
||||||
|
placeholder="Enter member name"
|
||||||
|
hint="Full member's name"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="newMember.link"
|
||||||
|
lg="w-50%"
|
||||||
|
label="Profile URL"
|
||||||
|
placeholder="Linkedin, Farcaster, Twitter,..."
|
||||||
|
hint="Link to member’s social profile (ex. Twitter, Linkedin, Lens,...)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</ProjectCreateComponentsItemAdd>
|
||||||
|
</div>
|
||||||
|
</template>
|
107
components/Project/Create/Categories/Technology.vue
Normal file
107
components/Project/Create/Categories/Technology.vue
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Project } from '~/types'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
project?: Partial<Project>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const version = ref(props.project?.project_phase?.toLowerCase() || undefined)
|
||||||
|
const openSource = ref(props.project?.blockchain_features?.opensource || false)
|
||||||
|
const upgradability = ref(props.project?.blockchain_features?.upgradability?.enabled || false)
|
||||||
|
const assetType = ref(props.project?.blockchain_features?.asset_custody_type?.toLowerCase() || '')
|
||||||
|
const encryption = ref(props.project?.blockchain_features?.encryption || '')
|
||||||
|
const peerToPeer = ref(props.project?.blockchain_features?.p2p)
|
||||||
|
const decentralizedStorage = ref(props.project?.storage?.decentralized)
|
||||||
|
|
||||||
|
const { useProject, projectPhaseData, assetCustodyData } = useData()
|
||||||
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
saveProject({
|
||||||
|
project_phase: version.value,
|
||||||
|
blockchain_features: {
|
||||||
|
opensource: openSource.value,
|
||||||
|
upgradability: {
|
||||||
|
enabled: upgradability.value,
|
||||||
|
},
|
||||||
|
asset_custody_type: assetType.value,
|
||||||
|
encryption: encryption.value,
|
||||||
|
p2p: peerToPeer.value,
|
||||||
|
},
|
||||||
|
storage: {
|
||||||
|
decentralized: decentralizedStorage.value,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
save,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ProjectCreateComponentsCategoryDivider
|
||||||
|
w-full
|
||||||
|
title="VERSION"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsRadio
|
||||||
|
v-model="version"
|
||||||
|
:options="projectPhaseData.map(p => ({ label: p.name, value: p.id }))"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsCategoryDivider
|
||||||
|
w-full
|
||||||
|
title="FEATURES"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-24px
|
||||||
|
>
|
||||||
|
<ProjectCreateComponentsToggle
|
||||||
|
v-model="openSource"
|
||||||
|
label="Open source"
|
||||||
|
hint="Check when projects source code is openly available and editable"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsToggle
|
||||||
|
v-model="upgradability"
|
||||||
|
label="Upgradability"
|
||||||
|
hint="Are developers able to upgrade and change deployed contract?"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ProjectCreateComponentsSelect
|
||||||
|
v-model="assetType"
|
||||||
|
:options="assetCustodyData.map(c => ({ label: c.name, value: c.id }))"
|
||||||
|
label="Asset custody type"
|
||||||
|
placeholder="Select custody type"
|
||||||
|
hint="How are user’s fund handled? (non-custody, multisig, pool,...)"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsCategoryDivider
|
||||||
|
w-full
|
||||||
|
title="ADDITIONAL INFO"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-24px
|
||||||
|
>
|
||||||
|
<ProjectCreateComponentsInput
|
||||||
|
v-model="encryption"
|
||||||
|
lg="w-1/2"
|
||||||
|
label="Technology type / Encryption"
|
||||||
|
hint="Define technologies your project uses for privacy ex. Zero-Knowledge (ZK), SHA256,"
|
||||||
|
placeholder="Technology name"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsToggle
|
||||||
|
v-model="peerToPeer"
|
||||||
|
label="Peer to Peer (P2P)"
|
||||||
|
hint="Check when you transfer / communicate withou intermediaries"
|
||||||
|
/>
|
||||||
|
<ProjectCreateComponentsToggle
|
||||||
|
v-model="decentralizedStorage"
|
||||||
|
label="Decentralized storage"
|
||||||
|
hint="Is your data hosted on IPFS, Filecoin or other decentralized storage?"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
38
components/Project/Create/Components/CategoryDivider.vue
Normal file
38
components/Project/Create/Components/CategoryDivider.vue
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineProps<{
|
||||||
|
title: string
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
w-full
|
||||||
|
flex
|
||||||
|
justify-between
|
||||||
|
gap-8px
|
||||||
|
my-40px
|
||||||
|
lg="gap-32px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
gap-8px
|
||||||
|
text-16px
|
||||||
|
font-700
|
||||||
|
class="text-app-white/50"
|
||||||
|
>
|
||||||
|
<span text-nowrap>{{ title }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
w-full
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
>
|
||||||
|
<hr
|
||||||
|
border="t-2px white/50"
|
||||||
|
w-full
|
||||||
|
shrink-1
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
119
components/Project/Create/Components/DatePicker.vue
Normal file
119
components/Project/Create/Components/DatePicker.vue
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
export interface SelectProps {
|
||||||
|
label?: string
|
||||||
|
hint?: string
|
||||||
|
placeholder?: string
|
||||||
|
required?: boolean
|
||||||
|
modelValue?: any
|
||||||
|
}
|
||||||
|
|
||||||
|
defineProps<SelectProps>()
|
||||||
|
|
||||||
|
const months = [
|
||||||
|
{ label: 'January', value: 1 },
|
||||||
|
{ label: 'February', value: 2 },
|
||||||
|
{ label: 'March', value: 3 },
|
||||||
|
{ label: 'April', value: 4 },
|
||||||
|
{ label: 'May', value: 5 },
|
||||||
|
{ label: 'June', value: 6 },
|
||||||
|
{ label: 'July', value: 7 },
|
||||||
|
{ label: 'August', value: 8 },
|
||||||
|
{ label: 'September', value: 9 },
|
||||||
|
{ label: 'October', value: 10 },
|
||||||
|
{ label: 'November', value: 11 },
|
||||||
|
{ label: 'December', value: 12 },
|
||||||
|
]
|
||||||
|
const years = Array.from({ length: 101 }, (_, i) => new Date().getFullYear() - i)
|
||||||
|
|
||||||
|
const day = defineModel<number>('day')
|
||||||
|
const month = defineModel<number>('month')
|
||||||
|
const year = defineModel<number>('year')
|
||||||
|
|
||||||
|
const daysInMonth = (month: number, year: number) => {
|
||||||
|
const monthObj = months.find(m => m.value === month)
|
||||||
|
if (!monthObj) {
|
||||||
|
throw new Error(`Invalid month value: ${month}`)
|
||||||
|
}
|
||||||
|
const monthIndex = months.indexOf(monthObj)
|
||||||
|
return new Date(year, monthIndex + 1, 0).getDate()
|
||||||
|
}
|
||||||
|
|
||||||
|
const days = computed(() => {
|
||||||
|
if (month.value && year.value) {
|
||||||
|
return Array.from({ length: daysInMonth(month.value, year.value) }, (_, i) => i + 1)
|
||||||
|
}
|
||||||
|
return Array.from({ length: 31 }, (_, i) => i + 1)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-8px
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
v-if="label"
|
||||||
|
font-400
|
||||||
|
text-14px
|
||||||
|
lg:text-16px
|
||||||
|
text-app-white
|
||||||
|
>
|
||||||
|
{{ label }}
|
||||||
|
<span
|
||||||
|
v-if="required"
|
||||||
|
text-app-danger
|
||||||
|
text-16px
|
||||||
|
>*</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="flex flex-col"
|
||||||
|
gap-8px
|
||||||
|
lg="flex flex-row gap-24px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="flex flex-row"
|
||||||
|
lg="w-1/2"
|
||||||
|
relative
|
||||||
|
>
|
||||||
|
<SelectBox
|
||||||
|
v-model="day"
|
||||||
|
w-full
|
||||||
|
:options="days.map(day => ({ label: day.toString(), value: day }))"
|
||||||
|
placeholder="Day"
|
||||||
|
:border-opacity="30"
|
||||||
|
:is-margin-top="false"
|
||||||
|
/>
|
||||||
|
<SelectBox
|
||||||
|
v-model="month"
|
||||||
|
w-full
|
||||||
|
mx--2px
|
||||||
|
:options="months.map(month => ({ label: month.label, value: month.value }))"
|
||||||
|
placeholder="Month"
|
||||||
|
:border-opacity="30"
|
||||||
|
:is-margin-top="false"
|
||||||
|
/>
|
||||||
|
<SelectBox
|
||||||
|
v-model="year"
|
||||||
|
w-full
|
||||||
|
:options="years.map(year => ({ label: year.toString(), value: year }))"
|
||||||
|
placeholder="Year"
|
||||||
|
:border-opacity="30"
|
||||||
|
:is-margin-top="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
v-if="hint"
|
||||||
|
lg="left-1/2 self-center"
|
||||||
|
font-400
|
||||||
|
italic
|
||||||
|
lg:text-14px
|
||||||
|
text-12px
|
||||||
|
text-app-white
|
||||||
|
opacity-50
|
||||||
|
>
|
||||||
|
{{ hint }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
81
components/Project/Create/Components/Input.vue
Normal file
81
components/Project/Create/Components/Input.vue
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
export interface SelectProps {
|
||||||
|
label?: string
|
||||||
|
hint?: string
|
||||||
|
placeholder?: string
|
||||||
|
required?: boolean
|
||||||
|
modelValue?: any
|
||||||
|
textarea?: boolean
|
||||||
|
textareaRows?: number
|
||||||
|
lgWidth?: string
|
||||||
|
error?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
defineProps<SelectProps>()
|
||||||
|
|
||||||
|
const model = defineModel<string>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="w-full!"
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-8px
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
v-if="label"
|
||||||
|
font-400
|
||||||
|
text-14px
|
||||||
|
lg:text-16px
|
||||||
|
text-app-white
|
||||||
|
>
|
||||||
|
{{ label }}
|
||||||
|
<span
|
||||||
|
v-if="required"
|
||||||
|
text-app-danger
|
||||||
|
text-16px
|
||||||
|
>*</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
w-full
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-8px
|
||||||
|
lg="flex flex-row gap-24px"
|
||||||
|
relative
|
||||||
|
>
|
||||||
|
<div v-bind="$attrs">
|
||||||
|
<textarea
|
||||||
|
v-if="textarea"
|
||||||
|
v-model="model"
|
||||||
|
:rows="textareaRows"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
class="relative w-full p-8px text-left border-2px text-app-white bg-black sm:text-sm sm:leading-6 focus:ring-0 focus:outline-none"
|
||||||
|
:class="error ? 'border-app-danger/50' : 'border-white/30'"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-else
|
||||||
|
v-model="model"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
type="text"
|
||||||
|
class="relative w-full p-8px text-left border-2px text-app-white bg-black sm:text-sm sm:leading-6 focus:ring-0 focus:outline-none"
|
||||||
|
:class="error ? 'border-app-danger/50' : 'border-white/30'"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
v-if="hint"
|
||||||
|
lg="left-1/2 self-center"
|
||||||
|
v-bind="$attrs"
|
||||||
|
font-400
|
||||||
|
italic
|
||||||
|
lg:text-14px
|
||||||
|
text-12px
|
||||||
|
text-app-white
|
||||||
|
opacity-50
|
||||||
|
>
|
||||||
|
{{ hint }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
33
components/Project/Create/Components/Item.vue
Normal file
33
components/Project/Create/Components/Item.vue
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
const emits = defineEmits(['remove'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
justify-between
|
||||||
|
items-center
|
||||||
|
py-12px
|
||||||
|
px-16px
|
||||||
|
bg-app-white
|
||||||
|
>
|
||||||
|
<slot name="label" />
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
gap-16px
|
||||||
|
>
|
||||||
|
<slot
|
||||||
|
class="text-app-black/50"
|
||||||
|
name="desc"
|
||||||
|
/>
|
||||||
|
<button @click="emits('remove')">
|
||||||
|
<UnoIcon
|
||||||
|
i-heroicons-solid-x
|
||||||
|
text-12px
|
||||||
|
text-app-black
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
31
components/Project/Create/Components/ItemAdd.vue
Normal file
31
components/Project/Create/Components/ItemAdd.vue
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineProps<{
|
||||||
|
buttonLabel: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emits = defineEmits(['add'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
w-full
|
||||||
|
border-2
|
||||||
|
border-app-white
|
||||||
|
p-24px
|
||||||
|
>
|
||||||
|
<slot name="content" />
|
||||||
|
<Button
|
||||||
|
mt-16px
|
||||||
|
lg="w-fit mt-24px"
|
||||||
|
border
|
||||||
|
inverted-color
|
||||||
|
@click="emits('add')"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
px-24px
|
||||||
|
>{{ buttonLabel }}</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</template>
|
61
components/Project/Create/Components/Radio.vue
Normal file
61
components/Project/Create/Components/Radio.vue
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
interface OptionItem<T> {
|
||||||
|
label: string
|
||||||
|
value: T
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SelectProps {
|
||||||
|
options: OptionItem<string>[]
|
||||||
|
}
|
||||||
|
|
||||||
|
defineProps<SelectProps>()
|
||||||
|
|
||||||
|
const selected = defineModel<string>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div w-full>
|
||||||
|
<div w-full>
|
||||||
|
<HeadlessRadioGroup v-model="selected">
|
||||||
|
<div class="flex flex-wrap gap-20px">
|
||||||
|
<HeadlessRadioGroupOption
|
||||||
|
v-for="option in options"
|
||||||
|
:key="option.label"
|
||||||
|
v-slot="{ checked }"
|
||||||
|
as="template"
|
||||||
|
:value="option.value"
|
||||||
|
>
|
||||||
|
<div class="cursor-pointer w-49% flex items-center gap-22px">
|
||||||
|
<div
|
||||||
|
rounded-full
|
||||||
|
p-6px
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
justify-centerě
|
||||||
|
:class="checked ? 'bg-app-white text-app-black' : 'outline outline-2px outline-offset--2 outline-app-white text-app-white'"
|
||||||
|
>
|
||||||
|
<UnoIcon
|
||||||
|
v-if="checked"
|
||||||
|
i-heroicons-solid-check
|
||||||
|
text-20px
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
w-20px
|
||||||
|
h-20px
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<HeadlessRadioGroupLabel
|
||||||
|
as="p"
|
||||||
|
:class="checked ? 'text-app-white' : 'text-app-white/50'"
|
||||||
|
class="font-medium"
|
||||||
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</HeadlessRadioGroupLabel>
|
||||||
|
</div>
|
||||||
|
</HeadlessRadioGroupOption>
|
||||||
|
</div>
|
||||||
|
</HeadlessRadioGroup>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
107
components/Project/Create/Components/Select.vue
Normal file
107
components/Project/Create/Components/Select.vue
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { InputOption } from '~/types'
|
||||||
|
|
||||||
|
const props = defineProps<SelectProps>()
|
||||||
|
const emits = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
|
interface SelectProps {
|
||||||
|
options: InputOption[]
|
||||||
|
label?: string
|
||||||
|
modelValue: string
|
||||||
|
placeholder?: string
|
||||||
|
required?: boolean
|
||||||
|
hint?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedValue = useVModel(props, 'modelValue', emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-8px
|
||||||
|
lg="flex flex-row gap-24px"
|
||||||
|
relative
|
||||||
|
>
|
||||||
|
<div lg="w-1/2">
|
||||||
|
<HeadlessListbox
|
||||||
|
v-model="selectedValue"
|
||||||
|
as="div"
|
||||||
|
>
|
||||||
|
<HeadlessListboxLabel
|
||||||
|
v-if="label"
|
||||||
|
font-400
|
||||||
|
text-14px
|
||||||
|
lg:text-16px
|
||||||
|
text-app-white
|
||||||
|
>
|
||||||
|
{{ label }}
|
||||||
|
<span
|
||||||
|
v-if="required"
|
||||||
|
text-app-danger
|
||||||
|
text-16px
|
||||||
|
>*</span>
|
||||||
|
</HeadlessListboxLabel>
|
||||||
|
<div
|
||||||
|
class="relative font-700 mt-2 bg-app-black"
|
||||||
|
>
|
||||||
|
<HeadlessListboxButton
|
||||||
|
as="div"
|
||||||
|
class="relative w-full cursor-pointer p-8px text-left border-2px text-app-white bg-black border-white/30 sm:text-sm sm:leading-6"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="block truncate mr-8px"
|
||||||
|
:class="[selectedValue ? 'text-app-white' : 'font-400 text-white/50']"
|
||||||
|
>
|
||||||
|
{{ props.options.find(option => option.value === selectedValue)?.label || props.placeholder }}
|
||||||
|
</span>
|
||||||
|
<span class="absolute inset-y-0 right-0 flex items-center pr-2">
|
||||||
|
<UnoIcon
|
||||||
|
i-heroicons-solid-chevron-down
|
||||||
|
class="text-app-white"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</HeadlessListboxButton>
|
||||||
|
|
||||||
|
<transition
|
||||||
|
leave-active-class="transition ease-in duration-100"
|
||||||
|
leave-from-class="opacity-100"
|
||||||
|
leave-to-class="opacity-0"
|
||||||
|
>
|
||||||
|
<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 border-white/30"
|
||||||
|
>
|
||||||
|
<HeadlessListboxOption
|
||||||
|
v-for="option in props.options"
|
||||||
|
:key="option.value"
|
||||||
|
v-slot="{ selected }"
|
||||||
|
as="template"
|
||||||
|
:value="option.value"
|
||||||
|
class="w-full relative cursor-pointer select-none py-8px p-16px border-white/30"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="block truncate"
|
||||||
|
:class="[selected ? 'font-semibold' : 'font-normal']"
|
||||||
|
>{{ option.label }}</span>
|
||||||
|
</HeadlessListboxOption>
|
||||||
|
</HeadlessListboxOptions>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</HeadlessListbox>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
v-if="hint"
|
||||||
|
lg="mt-28px left-1/2 self-center"
|
||||||
|
font-400
|
||||||
|
italic
|
||||||
|
lg:text-14px
|
||||||
|
text-12px
|
||||||
|
text-app-white
|
||||||
|
opacity-50
|
||||||
|
>
|
||||||
|
{{ hint }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
213
components/Project/Create/Components/SelectChips.vue
Normal file
213
components/Project/Create/Components/SelectChips.vue
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
interface OptionItem<T> {
|
||||||
|
label: string
|
||||||
|
value: T
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SelectProps {
|
||||||
|
options: OptionItem<any>[]
|
||||||
|
label?: string
|
||||||
|
hint?: string
|
||||||
|
placeholder?: string
|
||||||
|
required?: boolean
|
||||||
|
multiple?: boolean
|
||||||
|
canAddNew?: boolean
|
||||||
|
modelValue?: any
|
||||||
|
error?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<SelectProps>(), {
|
||||||
|
multiple: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
|
const modelValue = useVModel(props, 'modelValue', emits)
|
||||||
|
|
||||||
|
const query = ref('')
|
||||||
|
const newOptions = ref<OptionItem<any>[]>([])
|
||||||
|
|
||||||
|
const options = computed(() => {
|
||||||
|
return [...props.options, ...newOptions.value]
|
||||||
|
})
|
||||||
|
|
||||||
|
const filteredOptions = computed(() =>
|
||||||
|
query.value === ''
|
||||||
|
? options.value
|
||||||
|
: options.value.filter(o => o.label.toLowerCase().includes(query.value.toLowerCase())),
|
||||||
|
)
|
||||||
|
|
||||||
|
// const modelValue = ref(props.modelValue || (props.multiple ? [] : null))
|
||||||
|
|
||||||
|
const selectedOptions = computed(() => props.multiple ? options.value.filter(o => modelValue.value?.includes(o.value)) : [])
|
||||||
|
|
||||||
|
function deleteOption(value: string) {
|
||||||
|
const index = modelValue.value.indexOf(value)
|
||||||
|
if (index !== -1)
|
||||||
|
modelValue.value.splice(index, 1)
|
||||||
|
|
||||||
|
newOptions.value = newOptions.value.filter((o: any) => o.value !== value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function addOption() {
|
||||||
|
if (query.value === '' || !props.canAddNew) return
|
||||||
|
|
||||||
|
if (!options.value.some(o => o.value === query.value)) {
|
||||||
|
newOptions.value.push({ label: query.value, value: query.value })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.multiple) {
|
||||||
|
if (!modelValue.value) modelValue.value = []
|
||||||
|
modelValue.value.push(query.value)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
modelValue.value = query.value
|
||||||
|
}
|
||||||
|
|
||||||
|
query.value = ''
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-8px
|
||||||
|
lg="flex flex-row gap-24px"
|
||||||
|
relative
|
||||||
|
>
|
||||||
|
<div lg="w-1/2">
|
||||||
|
<HeadlessCombobox
|
||||||
|
v-model="modelValue"
|
||||||
|
:multiple="props.multiple"
|
||||||
|
>
|
||||||
|
<HeadlessComboboxLabel
|
||||||
|
v-if="label"
|
||||||
|
font-400
|
||||||
|
text-14px
|
||||||
|
lg:text-16px
|
||||||
|
text-app-white
|
||||||
|
>
|
||||||
|
{{ label }}
|
||||||
|
<span
|
||||||
|
v-if="required"
|
||||||
|
text-app-danger
|
||||||
|
text-16px
|
||||||
|
>*</span>
|
||||||
|
</HeadlessComboboxLabel>
|
||||||
|
<div class="relative font-700 mt-2 bg-app-black">
|
||||||
|
<HeadlessComboboxButton
|
||||||
|
as="div"
|
||||||
|
class="relative w-full cursor-pointer p-8px text-left border-2px text-app-white bg-black sm:text-sm sm:leading-6"
|
||||||
|
:class="error ? 'border-app-danger/50' : 'border-white/30'"
|
||||||
|
>
|
||||||
|
<div class="flex flex-wrap gap-8px">
|
||||||
|
<span
|
||||||
|
v-for="option in selectedOptions"
|
||||||
|
:key="option.value"
|
||||||
|
class="font-700 text-14px leading-20px flex gap-8px items-center bg-app-white text-black px-8px py-4px"
|
||||||
|
lg="text-16px"
|
||||||
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="ml-1 text-black"
|
||||||
|
@click.stop="deleteOption(option.value)"
|
||||||
|
>
|
||||||
|
<UnoIcon
|
||||||
|
i-heroicons-solid-x
|
||||||
|
text-16px
|
||||||
|
text-black
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
<HeadlessComboboxInput
|
||||||
|
class="text-14px font-400 leading-20px ml-8px w-fit bg-transparent border-none focus:ring-0 focus:outline-none"
|
||||||
|
lg="16px"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
@keyup.enter="addOption"
|
||||||
|
@change="query = $event.target.value"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span class="absolute inset-y-0 right-0 flex items-center pr-2">
|
||||||
|
<UnoIcon
|
||||||
|
i-heroicons-solid-chevron-down
|
||||||
|
class="text-app-white"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</HeadlessComboboxButton>
|
||||||
|
</div>
|
||||||
|
<Transition
|
||||||
|
leave-active-class="transition ease-in duration-100"
|
||||||
|
leave-from-class="opacity-100"
|
||||||
|
leave-to-class="opacity-0"
|
||||||
|
@after-leave="query = ''"
|
||||||
|
>
|
||||||
|
<HeadlessComboboxOptions
|
||||||
|
lg="w-1/2"
|
||||||
|
class="w-full absolute z-100 max-h-60 divide-y-2px border-2px border-t-0 overflow-auto bg-app-black text-app-white focus:outline-none sm:text-sm border-white/30"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="filteredOptions.length === 0 && query !== '' && props.canAddNew"
|
||||||
|
class="gap-4px flex items-center relative cursor-default select-none px-4 py-2 text-app-white"
|
||||||
|
@click="addOption"
|
||||||
|
>
|
||||||
|
<UnoIcon
|
||||||
|
i-heroicons-solid-plus
|
||||||
|
class="text-app-white"
|
||||||
|
/>
|
||||||
|
<span>Add</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="filteredOptions.length === 0 && query !== '' && !props.canAddNew"
|
||||||
|
class="relative cursor-default select-none px-4 py-2 text-app-white opacity-50"
|
||||||
|
>
|
||||||
|
Nothing found.
|
||||||
|
</div>
|
||||||
|
<HeadlessComboboxOption
|
||||||
|
v-for="option in filteredOptions"
|
||||||
|
:key="option.value"
|
||||||
|
v-slot="{ selected, active }"
|
||||||
|
class="border-white/30"
|
||||||
|
as="template"
|
||||||
|
:value="option.value"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
class="w-full relative cursor-pointer select-none py-8px p-16px"
|
||||||
|
:class="[active ? 'bg-#ffffff1a' : 'text-white']"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="block truncate"
|
||||||
|
:class="[selected ? 'font-semibold' : 'font-normal']"
|
||||||
|
>{{ option.label }}</span>
|
||||||
|
<span
|
||||||
|
v-if="selected"
|
||||||
|
class="absolute inset-y-0 right-0 flex items-center pr-3 text-white"
|
||||||
|
>
|
||||||
|
<UnoIcon
|
||||||
|
i-heroicons-solid-check
|
||||||
|
text-20px
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</HeadlessComboboxOption>
|
||||||
|
</HeadlessComboboxOptions>
|
||||||
|
</Transition>
|
||||||
|
</HeadlessCombobox>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
v-if="hint"
|
||||||
|
lg="mt-28px left-1/2 self-center"
|
||||||
|
font-400
|
||||||
|
italic
|
||||||
|
lg:text-14px
|
||||||
|
text-12px
|
||||||
|
text-app-white
|
||||||
|
opacity-50
|
||||||
|
>
|
||||||
|
{{ hint }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
81
components/Project/Create/Components/Toggle.vue
Normal file
81
components/Project/Create/Components/Toggle.vue
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineProps<{
|
||||||
|
label?: string
|
||||||
|
hint?: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const enabled = defineModel<boolean>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-8px
|
||||||
|
lg="flex flex-row gap-24px"
|
||||||
|
relative
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
gap-24px
|
||||||
|
lg="w-1/2"
|
||||||
|
>
|
||||||
|
<HeadlessSwitch
|
||||||
|
v-model="enabled"
|
||||||
|
:class="enabled ? 'bg-white/10' : 'bg-white/10'"
|
||||||
|
class="relative inline-flex h-[28px] w-[68px] shrink-0 cursor-pointer transition-colors duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-white/75"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
:class="enabled ? 'translate-x-9 bg-app-white' : 'translate-x-0 bg-app-black border-2 border-app-white'"
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
class="pointer-events-none inline-block h-[28px] w-[32px] transform shadow-lg ring-0 transition duration-200 ease-in-out"
|
||||||
|
>
|
||||||
|
<UnoIcon
|
||||||
|
v-if="enabled"
|
||||||
|
transition
|
||||||
|
duration-200
|
||||||
|
ease-in-out
|
||||||
|
i-heroicons-solid-check
|
||||||
|
w-full
|
||||||
|
text-20px
|
||||||
|
text-app-black
|
||||||
|
/>
|
||||||
|
<UnoIcon
|
||||||
|
v-else
|
||||||
|
transition
|
||||||
|
duration-200
|
||||||
|
ease-in-out
|
||||||
|
i-heroicons-solid-x
|
||||||
|
w-full
|
||||||
|
text-20px
|
||||||
|
text-app-white
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</HeadlessSwitch>
|
||||||
|
<span
|
||||||
|
v-if="label"
|
||||||
|
text-14px
|
||||||
|
font-400
|
||||||
|
lg="text-16px"
|
||||||
|
:class="enabled ? 'text-app-white' : 'text-app-white/50'"
|
||||||
|
>
|
||||||
|
{{ label }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
v-if="hint"
|
||||||
|
lg="left-1/2 self-center"
|
||||||
|
font-400
|
||||||
|
italic
|
||||||
|
lg:text-14px
|
||||||
|
text-12px
|
||||||
|
text-app-white
|
||||||
|
opacity-50
|
||||||
|
>
|
||||||
|
{{ hint }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -41,8 +41,6 @@ const calculateScore = computed(() => {
|
||||||
else
|
else
|
||||||
value = indexableProject?.[criterias[i].value]
|
value = indexableProject?.[criterias[i].value]
|
||||||
|
|
||||||
// console.log(props.project?.links?.github);
|
|
||||||
// console.log(Object.keys(props.indexableProject["team"]).length);
|
|
||||||
if (value === null || value === undefined)
|
if (value === null || value === undefined)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@ import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const githubProjectUrl = computed(() => {
|
// const githubProjectUrl = computed(() => {
|
||||||
return `https://github.com/web3privacy/explorer-data/blob/main/src/projects/${route.params.id}/index.yaml`
|
// return `https://github.com/web3privacy/explorer-data/blob/main/src/projects/${route.params.id}/index.yaml`
|
||||||
})
|
// })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -20,7 +20,7 @@ const githubProjectUrl = computed(() => {
|
||||||
>
|
>
|
||||||
<NavigationButton
|
<NavigationButton
|
||||||
w-230px
|
w-230px
|
||||||
@click="$router.back()"
|
@click="$router.push('/')"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
block
|
block
|
||||||
|
@ -46,9 +46,8 @@ const githubProjectUrl = computed(() => {
|
||||||
<EditButton
|
<EditButton
|
||||||
px-16px
|
px-16px
|
||||||
py-8px
|
py-8px
|
||||||
hover:bg-white
|
hover="cursor-pointer bg-white text-black"
|
||||||
hover:text-black
|
@click="$router.push('/project/' + route.params.id + '/edit')"
|
||||||
:to="githubProjectUrl"
|
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
text-16px
|
text-16px
|
||||||
|
|
|
@ -4,14 +4,18 @@ import type { InputOption } from '~/types'
|
||||||
const props = withDefaults(defineProps<SelectProps>(), {
|
const props = withDefaults(defineProps<SelectProps>(), {
|
||||||
isMarginTop: true,
|
isMarginTop: true,
|
||||||
blackAndWhite: true,
|
blackAndWhite: true,
|
||||||
|
borderOpacity: 100,
|
||||||
})
|
})
|
||||||
const emits = defineEmits(['update:modelValue'])
|
const emits = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
interface SelectProps {
|
interface SelectProps {
|
||||||
options: InputOption[]
|
options: InputOption[]
|
||||||
modelValue: string
|
label?: string
|
||||||
|
modelValue: any
|
||||||
isMarginTop?: boolean
|
isMarginTop?: boolean
|
||||||
blackAndWhite?: boolean
|
blackAndWhite?: boolean
|
||||||
|
borderOpacity?: number
|
||||||
|
placeholder?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedValue = useVModel(props, 'modelValue', emits)
|
const selectedValue = useVModel(props, 'modelValue', emits)
|
||||||
|
@ -27,14 +31,19 @@ const selectedValue = useVModel(props, 'modelValue', emits)
|
||||||
:class="[isMarginTop ? 'mt-2' : 'mt-0', blackAndWhite ? 'bg-app-black' : 'bg-app-white']"
|
:class="[isMarginTop ? 'mt-2' : 'mt-0', blackAndWhite ? 'bg-app-black' : 'bg-app-white']"
|
||||||
>
|
>
|
||||||
<HeadlessListboxButton
|
<HeadlessListboxButton
|
||||||
class="relative w-full cursor-pointer py-8px p-16px text-left border-2px sm:text-sm sm:leading-6"
|
class="relative w-full cursor-pointer py-8px p-16px text-left border-2px sm:text-sm sm:leading-6"
|
||||||
:class="[blackAndWhite ? ' text-app-white' : 'text-app-black']"
|
:class="[blackAndWhite ? 'text-app-white' : 'text-app-black', `border-white/${borderOpacity}`]"
|
||||||
>
|
>
|
||||||
<span class="block truncate mr-8px">{{ props.options.find(option => option.value === selectedValue)?.label }}</span>
|
<span
|
||||||
|
class="block truncate mr-8px"
|
||||||
|
:class="[selectedValue ? 'text-app-white' : 'font-400 text-white/50']"
|
||||||
|
>
|
||||||
|
{{ props.options.find(option => option.value === selectedValue)?.label || props.placeholder }}
|
||||||
|
</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-heroicons-solid-chevron-down
|
||||||
:class="[blackAndWhite ? ' text-app-white' : 'text-app-black']"
|
:class="[blackAndWhite ? 'text-app-white' : 'text-app-black']"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</HeadlessListboxButton>
|
</HeadlessListboxButton>
|
||||||
|
@ -45,24 +54,22 @@ const selectedValue = useVModel(props, 'modelValue', emits)
|
||||||
leave-to-class="opacity-0"
|
leave-to-class="opacity-0"
|
||||||
>
|
>
|
||||||
<HeadlessListboxOptions
|
<HeadlessListboxOptions
|
||||||
|
:class="`border-white/${borderOpacity}`"
|
||||||
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-full divide-y-2px 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"
|
||||||
:key="option.value"
|
:key="option.value"
|
||||||
v-slot="{ active, selected }"
|
v-slot="{ selected }"
|
||||||
as="template"
|
as="template"
|
||||||
:value="option.value"
|
:value="option.value"
|
||||||
|
class="py-8px p-16px cursor-pointer"
|
||||||
|
:class="`border-white/${borderOpacity}`"
|
||||||
>
|
>
|
||||||
<li
|
<span
|
||||||
class="w-full relative cursor-pointer select-none py-8px p-16px"
|
class="block truncate"
|
||||||
:class="[active ? 'bg-#ffffff1a' : 'text-white']"
|
:class="[selected ? 'font-semibold' : 'font-normal']"
|
||||||
>
|
>{{ option.label }}</span>
|
||||||
<span
|
|
||||||
class="block truncate"
|
|
||||||
:class="[selected ? 'font-semibold' : 'font-normal']"
|
|
||||||
>{{ option.label }}</span>
|
|
||||||
</li>
|
|
||||||
</HeadlessListboxOption>
|
</HeadlessListboxOption>
|
||||||
</HeadlessListboxOptions>
|
</HeadlessListboxOptions>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
|
import { Buffer } from 'buffer'
|
||||||
import type { Category, Project, ProjectShallow } from '~/types'
|
import type { Category, Project, ProjectShallow } from '~/types'
|
||||||
|
|
||||||
export const useData = defineStore('data', () => {
|
export const useData = defineStore('data', () => {
|
||||||
|
const assetsData = useState<{ id: string, name: string }[]>('assetsData')
|
||||||
|
const categoriesData = useState<{ id: string, name: string }[]>('categoriesData')
|
||||||
|
const featuresData = useState<{ id: string, name: string }[]>('featuresData')
|
||||||
|
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 projects = useState<Project[]>('projects')
|
const projects = useState<Project[]>('projects')
|
||||||
const selectedCategoryId = useState(() => 'defi')
|
const selectedCategoryId = useState(() => 'defi')
|
||||||
|
@ -25,6 +35,13 @@ 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 }[]
|
||||||
|
asset_custody_type: { id: string, name: string }[]
|
||||||
|
sign_in_type_requirments: { id: string, name: string }[]
|
||||||
}>('/api/data')
|
}>('/api/data')
|
||||||
projects.value = data.projects.filter(p => p.name)
|
projects.value = data.projects.filter(p => p.name)
|
||||||
categories.value = data.categories.map((c) => {
|
categories.value = data.categories.map((c) => {
|
||||||
|
@ -33,6 +50,15 @@ export const useData = defineStore('data', () => {
|
||||||
).length
|
).length
|
||||||
return c
|
return c
|
||||||
}).filter(c => c.projectsCount > 0)
|
}).filter(c => c.projectsCount > 0)
|
||||||
|
|
||||||
|
assetsData.value = data.assets.map(a => ({ id: a.id.toLowerCase(), name: a.name }))
|
||||||
|
categoriesData.value = data.categories.map(c => ({ id: c.id.toLowerCase(), name: c.name }))
|
||||||
|
featuresData.value = data.features.map(f => ({ id: f.id.toLowerCase(), name: f.name }))
|
||||||
|
ecosystemsData.value = data.ecosystems.map(e => ({ id: e.id.toLowerCase(), name: e.name }))
|
||||||
|
usecasesData.value = data.usecases.map(u => ({ id: u.id.toLowerCase(), name: u.name }))
|
||||||
|
projectPhaseData.value = data.project_phase.map(p => ({ id: p.id.toLowerCase(), name: p.name }))
|
||||||
|
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 }))
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
|
@ -120,11 +146,74 @@ export const useData = defineStore('data', () => {
|
||||||
|
|
||||||
const filteredProjectsCount = computed(() => filteredProjects.value.length)
|
const filteredProjectsCount = computed(() => filteredProjects.value.length)
|
||||||
|
|
||||||
|
function useProject() {
|
||||||
|
const project = ref<Partial<Project>>()
|
||||||
|
const projectImage = ref<File>()
|
||||||
|
|
||||||
|
function setProject(id: string) {
|
||||||
|
project.value = getProjectById(id, { shallow: false }) as Project
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearProject() {
|
||||||
|
project.value = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveProject(data: Partial<Project>) {
|
||||||
|
project.value = {
|
||||||
|
...project.value,
|
||||||
|
...data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveProjectImage(image: File) {
|
||||||
|
projectImage.value = image
|
||||||
|
}
|
||||||
|
|
||||||
|
async function publishProject() {
|
||||||
|
try {
|
||||||
|
const imageArrayBuffer = await projectImage.value?.arrayBuffer()
|
||||||
|
let imageBuffer: Buffer | undefined
|
||||||
|
if (imageArrayBuffer)
|
||||||
|
imageBuffer = Buffer.from(imageArrayBuffer)
|
||||||
|
await $fetch(`/api/data`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: {
|
||||||
|
project: project.value,
|
||||||
|
image: {
|
||||||
|
type: projectImage.value?.type,
|
||||||
|
data: imageBuffer?.toString('base64'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
project,
|
||||||
|
setProject,
|
||||||
|
clearProject,
|
||||||
|
saveProject,
|
||||||
|
saveProjectImage,
|
||||||
|
publishProject,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectedCategoryId,
|
selectedCategoryId,
|
||||||
filter,
|
filter,
|
||||||
switcher,
|
switcher,
|
||||||
categories,
|
categories,
|
||||||
|
assetsData,
|
||||||
|
categoriesData,
|
||||||
|
featuresData,
|
||||||
|
ecosystemsData,
|
||||||
|
usecasesData,
|
||||||
|
projectPhaseData,
|
||||||
|
assetCustodyData,
|
||||||
|
signInRequirmentsData,
|
||||||
projects,
|
projects,
|
||||||
shallowProjects,
|
shallowProjects,
|
||||||
filteredProjectsCount,
|
filteredProjectsCount,
|
||||||
|
@ -133,5 +222,6 @@ export const useData = defineStore('data', () => {
|
||||||
getProjectsByCategory,
|
getProjectsByCategory,
|
||||||
filteredProjects,
|
filteredProjects,
|
||||||
projectToShallow,
|
projectToShallow,
|
||||||
|
useProject,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
6
layouts/create.vue
Normal file
6
layouts/create.vue
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<template>
|
||||||
|
<div h-full w-full>
|
||||||
|
<Navigation />
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -10,6 +10,7 @@ export default defineNuxtConfig({
|
||||||
'nuxt-lodash',
|
'nuxt-lodash',
|
||||||
'nuxt-headlessui',
|
'nuxt-headlessui',
|
||||||
'@nuxt/image',
|
'@nuxt/image',
|
||||||
|
'@vee-validate/nuxt',
|
||||||
],
|
],
|
||||||
sourcemap: {
|
sourcemap: {
|
||||||
server: true,
|
server: true,
|
||||||
|
|
|
@ -26,16 +26,20 @@
|
||||||
"@nuxtjs/color-mode": "^3.4.4",
|
"@nuxtjs/color-mode": "^3.4.4",
|
||||||
"@pinia/nuxt": "^0.5.4",
|
"@pinia/nuxt": "^0.5.4",
|
||||||
"@unocss/nuxt": "^0.62.3",
|
"@unocss/nuxt": "^0.62.3",
|
||||||
|
"@vee-validate/nuxt": "^4.13.2",
|
||||||
"@vueuse/nuxt": "^11.0.3",
|
"@vueuse/nuxt": "^11.0.3",
|
||||||
"eslint": "^9.9.1",
|
"eslint": "^9.9.1",
|
||||||
"nuxt": "^3.13.0",
|
"nuxt": "^3.13.0",
|
||||||
"nuxt-headlessui": "^1.2.0",
|
"nuxt-headlessui": "^1.2.0",
|
||||||
"nuxt-lodash": "^2.5.3",
|
"nuxt-lodash": "^2.5.3",
|
||||||
|
"octokit": "^4.0.2",
|
||||||
"pinia": "^2.2.2",
|
"pinia": "^2.2.2",
|
||||||
"taze": "^0.16.7",
|
"taze": "^0.16.7",
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.5.4",
|
||||||
"vitest": "^2.0.5",
|
"vitest": "^2.0.5",
|
||||||
"vue-tsc": "^2.1.4"
|
"vue-tsc": "^2.1.4",
|
||||||
|
"yaml": "^2.5.1",
|
||||||
|
"yup": "^1.4.0"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"vue": "latest"
|
"vue": "latest"
|
||||||
|
|
333
pages/project/[id]/edit.vue
Normal file
333
pages/project/[id]/edit.vue
Normal file
|
@ -0,0 +1,333 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import ProjectCreateCategoriesBasicInfo from '~/components/Project/Create/Categories/BasicInfo.vue'
|
||||||
|
import ProjectCreateCategoriesAssets from '~/components/Project/Create/Categories/Assets.vue'
|
||||||
|
import ProjectCreateCategoriesLinks from '~/components/Project/Create/Categories/Links.vue'
|
||||||
|
import ProjectCreateCategoriesTechnology from '~/components/Project/Create/Categories/Technology.vue'
|
||||||
|
import ProjectCreateCategoriesPrivacy from '~/components/Project/Create/Categories/Privacy.vue'
|
||||||
|
import ProjectCreateCategoriesSecurity from '~/components/Project/Create/Categories/Security.vue'
|
||||||
|
import ProjectCreateCategoriesTeam from '~/components/Project/Create/Categories/Team.vue'
|
||||||
|
import ProjectCreateCategoriesFunding from '~/components/Project/Create/Categories/Funding.vue'
|
||||||
|
import ProjectCreateCategoriesHistory from '~/components/Project/Create/Categories/History.vue'
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
layout: 'create',
|
||||||
|
})
|
||||||
|
|
||||||
|
const { useProject, projects } = useData()
|
||||||
|
const { saveProject, setProject, project, publishProject, saveProjectImage } = useProject()
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
await until(projects).toMatch(p => p?.length > 0)
|
||||||
|
setProject(route.params.id as string)
|
||||||
|
|
||||||
|
if (!project.value) {
|
||||||
|
throw createError({
|
||||||
|
statusCode: 404,
|
||||||
|
message: 'Project not found',
|
||||||
|
fatal: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabs = reactive([
|
||||||
|
{ label: 'Basic Info', value: 'basic_info', component: ProjectCreateCategoriesBasicInfo },
|
||||||
|
{ label: 'Assets', value: 'assets', component: ProjectCreateCategoriesAssets },
|
||||||
|
{ label: 'Links', value: 'links', component: ProjectCreateCategoriesLinks },
|
||||||
|
{ label: 'Technology', value: 'technology', component: ProjectCreateCategoriesTechnology },
|
||||||
|
{ label: 'Privacy', value: 'privacy', component: ProjectCreateCategoriesPrivacy },
|
||||||
|
{ label: 'Security', value: 'security', component: ProjectCreateCategoriesSecurity },
|
||||||
|
{ label: 'Team', value: 'team', component: ProjectCreateCategoriesTeam },
|
||||||
|
{ label: 'Funding', value: 'funding', component: ProjectCreateCategoriesFunding },
|
||||||
|
{ label: 'History', value: 'history', component: ProjectCreateCategoriesHistory },
|
||||||
|
])
|
||||||
|
|
||||||
|
const selectedTab = ref(tabs[0].value)
|
||||||
|
|
||||||
|
function getCurrentComponent() {
|
||||||
|
const tab = tabs.find(t => t.value === selectedTab.value) || tabs[0]
|
||||||
|
return tab.component || null
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentComponent = ref()
|
||||||
|
|
||||||
|
const { open, onChange } = useFileDialog({
|
||||||
|
accept: 'image/*', // Set to accept only image files
|
||||||
|
})
|
||||||
|
|
||||||
|
const logoSrc = ref(project.value?.logos?.[0].url || '/no-image-1-1.svg')
|
||||||
|
|
||||||
|
onChange((files) => {
|
||||||
|
if (!files?.[0]) return
|
||||||
|
const file = files[0]
|
||||||
|
const reader = new FileReader()
|
||||||
|
reader.onload = (e) => {
|
||||||
|
logoSrc.value = e.target?.result as string
|
||||||
|
}
|
||||||
|
reader.readAsDataURL(file)
|
||||||
|
|
||||||
|
saveProjectImage(file)
|
||||||
|
})
|
||||||
|
|
||||||
|
const projectNameInput = ref<HTMLInputElement | null>(null)
|
||||||
|
function useProjectName() {
|
||||||
|
const isEditing = ref(false)
|
||||||
|
const name = ref('Untitled')
|
||||||
|
|
||||||
|
function toggleEdit() {
|
||||||
|
isEditing.value = !isEditing.value
|
||||||
|
if (isEditing.value) {
|
||||||
|
setTimeout(() => {
|
||||||
|
projectNameInput.value?.focus()
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
isEditing,
|
||||||
|
name,
|
||||||
|
toggleEdit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { isEditing, name, toggleEdit } = useProjectName()
|
||||||
|
name.value = project.value?.name || 'Untitled'
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
saveProject({
|
||||||
|
name: name.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
if (selectedTab.value === 'basic_info') {
|
||||||
|
if (!currentComponent.value.isFormValid())
|
||||||
|
return
|
||||||
|
else save()
|
||||||
|
}
|
||||||
|
|
||||||
|
currentComponent.value.save()
|
||||||
|
|
||||||
|
const currentIndex = tabs.findIndex(tab => tab.value === selectedTab.value)
|
||||||
|
const nextTab = tabs[currentIndex + 1] || tabs[0]
|
||||||
|
selectedTab.value = nextTab.value
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div w-full>
|
||||||
|
<div
|
||||||
|
bg-app-bg-dark_grey
|
||||||
|
px-16px
|
||||||
|
py-24px
|
||||||
|
lg="pb-0px mb--1px"
|
||||||
|
>
|
||||||
|
<div app-container>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
gap-16px
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
relative
|
||||||
|
class="parent"
|
||||||
|
>
|
||||||
|
<NuxtImg
|
||||||
|
lg="w-100px h-100px"
|
||||||
|
w-64px
|
||||||
|
h-64px
|
||||||
|
bg-app-bg-grey
|
||||||
|
object-cover
|
||||||
|
border-2
|
||||||
|
class="border-app-white/30"
|
||||||
|
:src="logoSrc ?? '/no-image-1-1.svg'"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
h-24px
|
||||||
|
hidden
|
||||||
|
parent-hover:flex
|
||||||
|
absolute
|
||||||
|
bottom-0
|
||||||
|
w-full
|
||||||
|
border-t-0
|
||||||
|
border-2
|
||||||
|
border-black
|
||||||
|
border-opacity-50
|
||||||
|
h-fit
|
||||||
|
justify-center
|
||||||
|
text="12px"
|
||||||
|
font-700
|
||||||
|
bg-app-white
|
||||||
|
text-app-black
|
||||||
|
@click="open()"
|
||||||
|
>
|
||||||
|
Upload Logo
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-8px
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
font-400
|
||||||
|
text="14px app-white/50"
|
||||||
|
leading-20px
|
||||||
|
>
|
||||||
|
{{ 'Project Name' }}
|
||||||
|
</h3>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
gap-12px
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
v-if="isEditing"
|
||||||
|
ref="projectNameInput"
|
||||||
|
v-model="name"
|
||||||
|
w-fit
|
||||||
|
onkeydown="this.style.width = 0; this.style.width = this.scrollWidth + 2 + 'px';"
|
||||||
|
type="text"
|
||||||
|
font-700
|
||||||
|
text-20px
|
||||||
|
leading-28px
|
||||||
|
bg-app-bg-dark_grey
|
||||||
|
onfocus="this.style.width = 0; this.style.width = this.scrollWidth + 2 + 'px';"
|
||||||
|
>
|
||||||
|
<h2
|
||||||
|
v-else
|
||||||
|
font-700
|
||||||
|
text-20px
|
||||||
|
leading-28px
|
||||||
|
>
|
||||||
|
{{ name }}
|
||||||
|
</h2>
|
||||||
|
<button @click="toggleEdit()">
|
||||||
|
<UnoIcon
|
||||||
|
v-if="isEditing"
|
||||||
|
text-24px
|
||||||
|
class="text-app-white/30"
|
||||||
|
hover:text-app-white
|
||||||
|
i-heroicons-solid-check
|
||||||
|
/>
|
||||||
|
<UnoIcon
|
||||||
|
v-else
|
||||||
|
text-20px
|
||||||
|
class="text-app-white/30"
|
||||||
|
hover:text-app-white
|
||||||
|
i-heroicons-solid-pencil
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
w-full
|
||||||
|
gap-46px
|
||||||
|
lg="mt-24px"
|
||||||
|
>
|
||||||
|
<SelectBox
|
||||||
|
v-model="selectedTab"
|
||||||
|
label="Choose category"
|
||||||
|
:options="tabs.map(t => ({ label: t.label, value: t.value }))"
|
||||||
|
:border-opacity="30"
|
||||||
|
w-full
|
||||||
|
lg:hidden
|
||||||
|
block
|
||||||
|
mt-16px
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
v-for="tab in tabs"
|
||||||
|
:key="tab.value"
|
||||||
|
lg:block
|
||||||
|
hidden
|
||||||
|
pb-8px
|
||||||
|
leading-40px
|
||||||
|
:class="selectedTab === tab.value ? 'font-bold border-b-4 border-app-white' : ''"
|
||||||
|
@click="selectedTab = tab.value"
|
||||||
|
>
|
||||||
|
{{ tab.label }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
border-t-2
|
||||||
|
class="border-app-white/30"
|
||||||
|
px-16px
|
||||||
|
py-24px
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
app-container
|
||||||
|
mb-55px
|
||||||
|
>
|
||||||
|
<component
|
||||||
|
:is="getCurrentComponent()"
|
||||||
|
v-if="project"
|
||||||
|
ref="currentComponent"
|
||||||
|
:project="project"
|
||||||
|
w-full
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-24px
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
v-if="selectedTab !== tabs[tabs.length - 1].value"
|
||||||
|
class="hidden!"
|
||||||
|
mt-48px
|
||||||
|
lg="w-fit flex!"
|
||||||
|
border
|
||||||
|
@click="next()"
|
||||||
|
>
|
||||||
|
<span px-24px>NEXT SECTION</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-16px
|
||||||
|
justify-center
|
||||||
|
text-center
|
||||||
|
absolute
|
||||||
|
bottom-0
|
||||||
|
w-full
|
||||||
|
bg-app-bg-dark_grey
|
||||||
|
class="border-app-white/30"
|
||||||
|
lg="bg-app-black w-fit border-l-2 border-t-2 right-0 border-app-white"
|
||||||
|
p-12px
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
v-if="selectedTab !== tabs[tabs.length - 1].value"
|
||||||
|
flex
|
||||||
|
lg="w-fit hidden!"
|
||||||
|
border
|
||||||
|
@click="next()"
|
||||||
|
>
|
||||||
|
<span px-24px>NEXT SECTION</span>
|
||||||
|
</Button>
|
||||||
|
<span
|
||||||
|
v-if="selectedTab !== tabs[tabs.length - 1].value"
|
||||||
|
lg="hidden"
|
||||||
|
block
|
||||||
|
text="12px italic app-white/50"
|
||||||
|
>or you can submit changes by publishing them</span>
|
||||||
|
<div flex>
|
||||||
|
<Button
|
||||||
|
w-full
|
||||||
|
lg="w-fit"
|
||||||
|
border
|
||||||
|
>
|
||||||
|
<span px-24px>CANCEL</span>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
w-full
|
||||||
|
lg="w-fit"
|
||||||
|
inverted-color
|
||||||
|
@click="publishProject()"
|
||||||
|
>
|
||||||
|
<span px-24px>PUBLISH</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
319
pages/project/create.vue
Normal file
319
pages/project/create.vue
Normal file
|
@ -0,0 +1,319 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import ProjectCreateCategoriesBasicInfo from '~/components/Project/Create/Categories/BasicInfo.vue'
|
||||||
|
import ProjectCreateCategoriesAssets from '~/components/Project/Create/Categories/Assets.vue'
|
||||||
|
import ProjectCreateCategoriesLinks from '~/components/Project/Create/Categories/Links.vue'
|
||||||
|
import ProjectCreateCategoriesTechnology from '~/components/Project/Create/Categories/Technology.vue'
|
||||||
|
import ProjectCreateCategoriesPrivacy from '~/components/Project/Create/Categories/Privacy.vue'
|
||||||
|
import ProjectCreateCategoriesSecurity from '~/components/Project/Create/Categories/Security.vue'
|
||||||
|
import ProjectCreateCategoriesTeam from '~/components/Project/Create/Categories/Team.vue'
|
||||||
|
import ProjectCreateCategoriesFunding from '~/components/Project/Create/Categories/Funding.vue'
|
||||||
|
import ProjectCreateCategoriesHistory from '~/components/Project/Create/Categories/History.vue'
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
layout: 'create',
|
||||||
|
})
|
||||||
|
|
||||||
|
const tabs = reactive([
|
||||||
|
{ label: 'Basic Info', value: 'basic_info', component: ProjectCreateCategoriesBasicInfo },
|
||||||
|
{ label: 'Assets', value: 'assets', component: ProjectCreateCategoriesAssets },
|
||||||
|
{ label: 'Links', value: 'links', component: ProjectCreateCategoriesLinks },
|
||||||
|
{ label: 'Technology', value: 'technology', component: ProjectCreateCategoriesTechnology },
|
||||||
|
{ label: 'Privacy', value: 'privacy', component: ProjectCreateCategoriesPrivacy },
|
||||||
|
{ label: 'Security', value: 'security', component: ProjectCreateCategoriesSecurity },
|
||||||
|
{ label: 'Team', value: 'team', component: ProjectCreateCategoriesTeam },
|
||||||
|
{ label: 'Funding', value: 'funding', component: ProjectCreateCategoriesFunding },
|
||||||
|
{ label: 'History', value: 'history', component: ProjectCreateCategoriesHistory },
|
||||||
|
])
|
||||||
|
|
||||||
|
const selectedTab = ref(tabs[0].value)
|
||||||
|
|
||||||
|
function getCurrentComponent() {
|
||||||
|
const tab = tabs.find(t => t.value === selectedTab.value) || tabs[0]
|
||||||
|
return tab.component || null
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentComponent = ref()
|
||||||
|
|
||||||
|
const { open, onChange } = useFileDialog({
|
||||||
|
accept: 'image/*', // Set to accept only image files
|
||||||
|
})
|
||||||
|
|
||||||
|
const logoSrc = ref('/no-image-1-1.svg')
|
||||||
|
|
||||||
|
onChange((files) => {
|
||||||
|
if (!files?.[0]) return
|
||||||
|
const file = files[0]
|
||||||
|
const reader = new FileReader()
|
||||||
|
reader.onload = (e) => {
|
||||||
|
logoSrc.value = e.target?.result as string
|
||||||
|
}
|
||||||
|
reader.readAsDataURL(file)
|
||||||
|
|
||||||
|
saveProjectImage(file)
|
||||||
|
})
|
||||||
|
|
||||||
|
const projectNameInput = ref<HTMLInputElement | null>(null)
|
||||||
|
function useProjectName() {
|
||||||
|
const isEditing = ref(false)
|
||||||
|
const name = ref('Untitled')
|
||||||
|
|
||||||
|
function toggleEdit() {
|
||||||
|
isEditing.value = !isEditing.value
|
||||||
|
if (isEditing.value) {
|
||||||
|
setTimeout(() => {
|
||||||
|
projectNameInput.value?.focus()
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
isEditing,
|
||||||
|
name,
|
||||||
|
toggleEdit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { isEditing, name, toggleEdit } = useProjectName()
|
||||||
|
|
||||||
|
const { useProject } = useData()
|
||||||
|
const { saveProject, publishProject, saveProjectImage } = useProject()
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
saveProject({
|
||||||
|
name: name.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
if (selectedTab.value === 'basic_info') {
|
||||||
|
if (!currentComponent.value.isFormValid())
|
||||||
|
return
|
||||||
|
else save()
|
||||||
|
}
|
||||||
|
|
||||||
|
currentComponent.value.save()
|
||||||
|
|
||||||
|
const currentIndex = tabs.findIndex(tab => tab.value === selectedTab.value)
|
||||||
|
const nextTab = tabs[currentIndex + 1] || tabs[0]
|
||||||
|
selectedTab.value = nextTab.value
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div w-full>
|
||||||
|
<div
|
||||||
|
bg-app-bg-dark_grey
|
||||||
|
px-16px
|
||||||
|
py-24px
|
||||||
|
lg="pb-0px mb--1px"
|
||||||
|
>
|
||||||
|
<div app-container>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
gap-16px
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
relative
|
||||||
|
class="parent"
|
||||||
|
>
|
||||||
|
<NuxtImg
|
||||||
|
lg="w-100px h-100px"
|
||||||
|
w-64px
|
||||||
|
h-64px
|
||||||
|
bg-app-bg-grey
|
||||||
|
object-cover
|
||||||
|
border-2
|
||||||
|
class="border-app-white/30"
|
||||||
|
opacity-30
|
||||||
|
:src="logoSrc ?? '/no-image-1-1.svg'"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
h-24px
|
||||||
|
hidden
|
||||||
|
parent-hover:flex
|
||||||
|
absolute
|
||||||
|
bottom-0
|
||||||
|
w-full
|
||||||
|
border-t-0
|
||||||
|
border-2
|
||||||
|
border-black
|
||||||
|
border-opacity-80
|
||||||
|
h-fit
|
||||||
|
justify-center
|
||||||
|
text="12px"
|
||||||
|
font-700
|
||||||
|
bg-app-white
|
||||||
|
text-app-black
|
||||||
|
@click="open()"
|
||||||
|
>
|
||||||
|
Upload Logo
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-8px
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
font-400
|
||||||
|
text="14px app-white/50"
|
||||||
|
leading-20px
|
||||||
|
>
|
||||||
|
{{ 'Project Name' }}
|
||||||
|
</h3>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
gap-12px
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
v-if="isEditing"
|
||||||
|
ref="projectNameInput"
|
||||||
|
v-model="name"
|
||||||
|
w-fit
|
||||||
|
onkeydown="this.style.width = 0; this.style.width = this.scrollWidth + 2 + 'px';"
|
||||||
|
type="text"
|
||||||
|
font-700
|
||||||
|
text-20px
|
||||||
|
leading-28px
|
||||||
|
bg-app-bg-dark_grey
|
||||||
|
onfocus="this.style.width = 0; this.style.width = this.scrollWidth + 2 + 'px';"
|
||||||
|
>
|
||||||
|
<h2
|
||||||
|
v-else
|
||||||
|
font-700
|
||||||
|
text-20px
|
||||||
|
leading-28px
|
||||||
|
>
|
||||||
|
{{ name }}
|
||||||
|
</h2>
|
||||||
|
<button @click="toggleEdit()">
|
||||||
|
<UnoIcon
|
||||||
|
v-if="isEditing"
|
||||||
|
text-24px
|
||||||
|
class="text-app-white/30"
|
||||||
|
hover:text-app-white
|
||||||
|
i-heroicons-solid-check
|
||||||
|
/>
|
||||||
|
<UnoIcon
|
||||||
|
v-else
|
||||||
|
text-20px
|
||||||
|
class="text-app-white/30"
|
||||||
|
hover:text-app-white
|
||||||
|
i-heroicons-solid-pencil
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
w-full
|
||||||
|
gap-46px
|
||||||
|
lg="mt-24px"
|
||||||
|
>
|
||||||
|
<SelectBox
|
||||||
|
v-model="selectedTab"
|
||||||
|
label="Choose category"
|
||||||
|
:options="tabs.map(t => ({ label: t.label, value: t.value }))"
|
||||||
|
:border-opacity="30"
|
||||||
|
w-full
|
||||||
|
lg:hidden
|
||||||
|
block
|
||||||
|
mt-16px
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
v-for="tab in tabs"
|
||||||
|
:key="tab.value"
|
||||||
|
lg:block
|
||||||
|
hidden
|
||||||
|
pb-8px
|
||||||
|
leading-40px
|
||||||
|
:class="selectedTab === tab.value ? 'font-bold border-b-4 border-app-white' : ''"
|
||||||
|
@click="selectedTab = tab.value"
|
||||||
|
>
|
||||||
|
{{ tab.label }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
border-t-2
|
||||||
|
class="border-app-white/30"
|
||||||
|
px-16px
|
||||||
|
py-24px
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
app-container
|
||||||
|
mb-55px
|
||||||
|
>
|
||||||
|
<component
|
||||||
|
:is="getCurrentComponent()"
|
||||||
|
ref="currentComponent"
|
||||||
|
w-full
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-24px
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
v-if="selectedTab !== tabs[tabs.length - 1].value"
|
||||||
|
class="hidden!"
|
||||||
|
mt-48px
|
||||||
|
lg="w-fit flex!"
|
||||||
|
border
|
||||||
|
@click="next()"
|
||||||
|
>
|
||||||
|
<span px-24px>NEXT SECTION</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
flex
|
||||||
|
flex-col
|
||||||
|
gap-16px
|
||||||
|
justify-center
|
||||||
|
text-center
|
||||||
|
absolute
|
||||||
|
bottom-0
|
||||||
|
w-full
|
||||||
|
bg-app-bg-dark_grey
|
||||||
|
class="border-app-white/30"
|
||||||
|
lg="bg-app-black w-fit border-l-2 border-t-2 right-0 border-app-white"
|
||||||
|
p-12px
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
v-if="selectedTab !== tabs[tabs.length - 1].value"
|
||||||
|
flex
|
||||||
|
lg="w-fit hidden!"
|
||||||
|
border
|
||||||
|
@click="next()"
|
||||||
|
>
|
||||||
|
<span px-24px>NEXT SECTION</span>
|
||||||
|
</Button>
|
||||||
|
<span
|
||||||
|
v-if="selectedTab !== tabs[tabs.length - 1].value"
|
||||||
|
lg="hidden"
|
||||||
|
block
|
||||||
|
text="12px italic app-white/50"
|
||||||
|
>or you can submit changes by publishing them</span>
|
||||||
|
<div flex>
|
||||||
|
<Button
|
||||||
|
w-full
|
||||||
|
lg="w-fit"
|
||||||
|
border
|
||||||
|
>
|
||||||
|
<span px-24px>CANCEL</span>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
w-full
|
||||||
|
lg="w-fit"
|
||||||
|
inverted-color
|
||||||
|
@click="publishProject()"
|
||||||
|
>
|
||||||
|
<span px-24px>PUBLISH</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
16
plugins/githubApi.ts
Normal file
16
plugins/githubApi.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
export default defineNuxtPlugin(() => {
|
||||||
|
const appConfig = useAppConfig()
|
||||||
|
|
||||||
|
const githubApi = $fetch.create({
|
||||||
|
baseURL: 'https://api.github.com',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${appConfig.github.accessToken}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
provide: {
|
||||||
|
githubApi,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
452
pnpm-lock.yaml
452
pnpm-lock.yaml
|
@ -38,6 +38,9 @@ importers:
|
||||||
'@unocss/nuxt':
|
'@unocss/nuxt':
|
||||||
specifier: ^0.62.3
|
specifier: ^0.62.3
|
||||||
version: 0.62.3(magicast@0.3.5)(postcss@8.4.44)(rollup@4.21.2)(vite@5.4.2(@types/node@20.8.7)(terser@5.22.0))(webpack@5.89.0(esbuild@0.23.1))
|
version: 0.62.3(magicast@0.3.5)(postcss@8.4.44)(rollup@4.21.2)(vite@5.4.2(@types/node@20.8.7)(terser@5.22.0))(webpack@5.89.0(esbuild@0.23.1))
|
||||||
|
'@vee-validate/nuxt':
|
||||||
|
specifier: ^4.13.2
|
||||||
|
version: 4.13.2(magicast@0.3.5)(rollup@4.21.2)(vue@3.4.38(typescript@5.5.4))
|
||||||
'@vueuse/nuxt':
|
'@vueuse/nuxt':
|
||||||
specifier: ^11.0.3
|
specifier: ^11.0.3
|
||||||
version: 11.0.3(magicast@0.3.5)(nuxt@3.13.0(@parcel/watcher@2.4.1)(@types/node@20.8.7)(encoding@0.1.13)(eslint@9.9.1(jiti@1.21.6))(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.3)(rollup@4.21.2)(terser@5.22.0)(typescript@5.5.4)(vite@5.4.2(@types/node@20.8.7)(terser@5.22.0))(vue-tsc@2.1.4(typescript@5.5.4)))(rollup@4.21.2)(vue@3.4.38(typescript@5.5.4))
|
version: 11.0.3(magicast@0.3.5)(nuxt@3.13.0(@parcel/watcher@2.4.1)(@types/node@20.8.7)(encoding@0.1.13)(eslint@9.9.1(jiti@1.21.6))(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.3)(rollup@4.21.2)(terser@5.22.0)(typescript@5.5.4)(vite@5.4.2(@types/node@20.8.7)(terser@5.22.0))(vue-tsc@2.1.4(typescript@5.5.4)))(rollup@4.21.2)(vue@3.4.38(typescript@5.5.4))
|
||||||
|
@ -53,6 +56,9 @@ importers:
|
||||||
nuxt-lodash:
|
nuxt-lodash:
|
||||||
specifier: ^2.5.3
|
specifier: ^2.5.3
|
||||||
version: 2.5.3(rollup@4.21.2)
|
version: 2.5.3(rollup@4.21.2)
|
||||||
|
octokit:
|
||||||
|
specifier: ^4.0.2
|
||||||
|
version: 4.0.2
|
||||||
pinia:
|
pinia:
|
||||||
specifier: ^2.2.2
|
specifier: ^2.2.2
|
||||||
version: 2.2.2(typescript@5.5.4)(vue@3.4.38(typescript@5.5.4))
|
version: 2.2.2(typescript@5.5.4)(vue@3.4.38(typescript@5.5.4))
|
||||||
|
@ -68,6 +74,12 @@ importers:
|
||||||
vue-tsc:
|
vue-tsc:
|
||||||
specifier: ^2.1.4
|
specifier: ^2.1.4
|
||||||
version: 2.1.4(typescript@5.5.4)
|
version: 2.1.4(typescript@5.5.4)
|
||||||
|
yaml:
|
||||||
|
specifier: ^2.5.1
|
||||||
|
version: 2.5.1
|
||||||
|
yup:
|
||||||
|
specifier: ^1.4.0
|
||||||
|
version: 1.4.0
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
|
@ -1320,6 +1332,113 @@ packages:
|
||||||
'@nuxtjs/color-mode@3.4.4':
|
'@nuxtjs/color-mode@3.4.4':
|
||||||
resolution: {integrity: sha512-VSNJVGnRIjiGmfbMa0cN+rwNRowDRTL/wku/z5MpKSanVo3khIRitBNqNviso1l3T+LW0pLHeXBNp6L8g/l1EA==}
|
resolution: {integrity: sha512-VSNJVGnRIjiGmfbMa0cN+rwNRowDRTL/wku/z5MpKSanVo3khIRitBNqNviso1l3T+LW0pLHeXBNp6L8g/l1EA==}
|
||||||
|
|
||||||
|
'@octokit/app@15.1.0':
|
||||||
|
resolution: {integrity: sha512-TkBr7QgOmE6ORxvIAhDbZsqPkF7RSqTY4pLTtUQCvr6dTXqvi2fFo46q3h1lxlk/sGMQjqyZ0kEahkD/NyzOHg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/auth-app@7.1.1':
|
||||||
|
resolution: {integrity: sha512-kRAd6yelV9OgvlEJE88H0VLlQdZcag9UlLr7dV0YYP37X8PPDvhgiTy66QVhDXdyoT0AleFN2w/qXkPdrSzINg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/auth-oauth-app@8.1.1':
|
||||||
|
resolution: {integrity: sha512-5UtmxXAvU2wfcHIPPDWzVSAWXVJzG3NWsxb7zCFplCWEmMCArSZV0UQu5jw5goLQXbFyOr5onzEH37UJB3zQQg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/auth-oauth-device@7.1.1':
|
||||||
|
resolution: {integrity: sha512-HWl8lYueHonuyjrKKIup/1tiy0xcmQCdq5ikvMO1YwkNNkxb6DXfrPjrMYItNLyCP/o2H87WuijuE+SlBTT8eg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/auth-oauth-user@5.1.1':
|
||||||
|
resolution: {integrity: sha512-rRkMz0ErOppdvEfnemHJXgZ9vTPhBuC6yASeFaB7I2yLMd7QpjfrL1mnvRPlyKo+M6eeLxrKanXJ9Qte29SRsw==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/auth-token@5.1.1':
|
||||||
|
resolution: {integrity: sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/auth-unauthenticated@6.1.0':
|
||||||
|
resolution: {integrity: sha512-zPSmfrUAcspZH/lOFQnVnvjQZsIvmfApQH6GzJrkIunDooU1Su2qt2FfMTSVPRp7WLTQyC20Kd55lF+mIYaohQ==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/core@6.1.2':
|
||||||
|
resolution: {integrity: sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/endpoint@10.1.1':
|
||||||
|
resolution: {integrity: sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/graphql@8.1.1':
|
||||||
|
resolution: {integrity: sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/oauth-app@7.1.3':
|
||||||
|
resolution: {integrity: sha512-EHXbOpBkSGVVGF1W+NLMmsnSsJRkcrnVmDKt0TQYRBb6xWfWzoi9sBD4DIqZ8jGhOWO/V8t4fqFyJ4vDQDn9bg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/oauth-authorization-url@7.1.1':
|
||||||
|
resolution: {integrity: sha512-ooXV8GBSabSWyhLUowlMIVd9l1s2nsOGQdlP2SQ4LnkEsGXzeCvbSbCPdZThXhEFzleGPwbapT0Sb+YhXRyjCA==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/oauth-methods@5.1.2':
|
||||||
|
resolution: {integrity: sha512-C5lglRD+sBlbrhCUTxgJAFjWgJlmTx5bQ7Ch0+2uqRjYv7Cfb5xpX4WuSC9UgQna3sqRGBL9EImX9PvTpMaQ7g==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/openapi-types@22.2.0':
|
||||||
|
resolution: {integrity: sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==}
|
||||||
|
|
||||||
|
'@octokit/openapi-webhooks-types@8.3.0':
|
||||||
|
resolution: {integrity: sha512-vKLsoR4xQxg4Z+6rU/F65ItTUz/EXbD+j/d4mlq2GW8TsA4Tc8Kdma2JTAAJ5hrKWUQzkR/Esn2fjsqiVRYaQg==}
|
||||||
|
|
||||||
|
'@octokit/plugin-paginate-graphql@5.2.2':
|
||||||
|
resolution: {integrity: sha512-7znSVvlNAOJisCqAnjN1FtEziweOHSjPGAuc5W58NeGNAr/ZB57yCsjQbXDlWsVryA7hHQaEQPcBbJYFawlkyg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
peerDependencies:
|
||||||
|
'@octokit/core': '>=6'
|
||||||
|
|
||||||
|
'@octokit/plugin-paginate-rest@11.3.3':
|
||||||
|
resolution: {integrity: sha512-o4WRoOJZlKqEEgj+i9CpcmnByvtzoUYC6I8PD2SA95M+BJ2x8h7oLcVOg9qcowWXBOdcTRsMZiwvM3EyLm9AfA==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
peerDependencies:
|
||||||
|
'@octokit/core': '>=6'
|
||||||
|
|
||||||
|
'@octokit/plugin-rest-endpoint-methods@13.2.4':
|
||||||
|
resolution: {integrity: sha512-gusyAVgTrPiuXOdfqOySMDztQHv6928PQ3E4dqVGEtOvRXAKRbJR4b1zQyniIT9waqaWk/UDaoJ2dyPr7Bk7Iw==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
peerDependencies:
|
||||||
|
'@octokit/core': '>=6'
|
||||||
|
|
||||||
|
'@octokit/plugin-retry@7.1.1':
|
||||||
|
resolution: {integrity: sha512-G9Ue+x2odcb8E1XIPhaFBnTTIrrUDfXN05iFXiqhR+SeeeDMMILcAnysOsxUpEWcQp2e5Ft397FCXTcPkiPkLw==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
peerDependencies:
|
||||||
|
'@octokit/core': '>=6'
|
||||||
|
|
||||||
|
'@octokit/plugin-throttling@9.3.1':
|
||||||
|
resolution: {integrity: sha512-Qd91H4liUBhwLB2h6jZ99bsxoQdhgPk6TdwnClPyTBSDAdviGPceViEgUwj+pcQDmB/rfAXAXK7MTochpHM3yQ==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
peerDependencies:
|
||||||
|
'@octokit/core': ^6.0.0
|
||||||
|
|
||||||
|
'@octokit/request-error@6.1.4':
|
||||||
|
resolution: {integrity: sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/request@9.1.3':
|
||||||
|
resolution: {integrity: sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/types@13.5.0':
|
||||||
|
resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==}
|
||||||
|
|
||||||
|
'@octokit/webhooks-methods@5.1.0':
|
||||||
|
resolution: {integrity: sha512-yFZa3UH11VIxYnnoOYCVoJ3q4ChuSOk2IVBBQ0O3xtKX4x9bmKb/1t+Mxixv2iUhzMdOl1qeWJqEhouXXzB3rQ==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/webhooks@13.3.0':
|
||||||
|
resolution: {integrity: sha512-TUkJLtI163Bz5+JK0O+zDkQpn4gKwN+BovclUvCj6pI/6RXrFqQvUMRS2M+Rt8Rv0qR3wjoMoOPmpJKeOh0nBg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
'@parcel/watcher-android-arm64@2.4.1':
|
'@parcel/watcher-android-arm64@2.4.1':
|
||||||
resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==}
|
resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==}
|
||||||
engines: {node: '>= 10.0.0'}
|
engines: {node: '>= 10.0.0'}
|
||||||
|
@ -1668,12 +1787,12 @@ packages:
|
||||||
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
|
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
|
||||||
engines: {node: '>=10.13.0'}
|
engines: {node: '>=10.13.0'}
|
||||||
|
|
||||||
|
'@types/aws-lambda@8.10.145':
|
||||||
|
resolution: {integrity: sha512-dtByW6WiFk5W5Jfgz1VM+YPA21xMXTuSFoLYIDY0L44jDLLflVPtZkYuu3/YxpGcvjzKFBZLU+GyKjR0HOYtyw==}
|
||||||
|
|
||||||
'@types/eslint-scope@3.7.6':
|
'@types/eslint-scope@3.7.6':
|
||||||
resolution: {integrity: sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==}
|
resolution: {integrity: sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==}
|
||||||
|
|
||||||
'@types/eslint@8.44.6':
|
|
||||||
resolution: {integrity: sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==}
|
|
||||||
|
|
||||||
'@types/eslint@9.6.1':
|
'@types/eslint@9.6.1':
|
||||||
resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==}
|
resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==}
|
||||||
|
|
||||||
|
@ -1878,6 +1997,9 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
webpack: ^4 || ^5
|
webpack: ^4 || ^5
|
||||||
|
|
||||||
|
'@vee-validate/nuxt@4.13.2':
|
||||||
|
resolution: {integrity: sha512-rpYYO2isCrgHRdJnKRXGPn8aqhyZvCPUJgNubftPum1txbngkO/LNiFsZdFDO7auGprDAQf7axpszRfeKoCGVg==}
|
||||||
|
|
||||||
'@vercel/nft@0.26.5':
|
'@vercel/nft@0.26.5':
|
||||||
resolution: {integrity: sha512-NHxohEqad6Ra/r4lGknO52uc/GrWILXAMs1BB4401GTqww0fw1bAqzpG1XHuDO+dprg4GvsD9ZLLSsdo78p9hQ==}
|
resolution: {integrity: sha512-NHxohEqad6Ra/r4lGknO52uc/GrWILXAMs1BB4401GTqww0fw1bAqzpG1XHuDO+dprg4GvsD9ZLLSsdo78p9hQ==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
|
@ -2235,6 +2357,9 @@ packages:
|
||||||
base64-js@1.5.1:
|
base64-js@1.5.1:
|
||||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||||
|
|
||||||
|
before-after-hook@3.0.2:
|
||||||
|
resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==}
|
||||||
|
|
||||||
binary-extensions@2.2.0:
|
binary-extensions@2.2.0:
|
||||||
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -2251,6 +2376,9 @@ packages:
|
||||||
boolbase@1.0.0:
|
boolbase@1.0.0:
|
||||||
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
|
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
|
||||||
|
|
||||||
|
bottleneck@2.19.5:
|
||||||
|
resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==}
|
||||||
|
|
||||||
brace-expansion@1.1.11:
|
brace-expansion@1.1.11:
|
||||||
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
|
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
|
||||||
|
|
||||||
|
@ -2821,9 +2949,6 @@ packages:
|
||||||
errx@0.1.0:
|
errx@0.1.0:
|
||||||
resolution: {integrity: sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q==}
|
resolution: {integrity: sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q==}
|
||||||
|
|
||||||
es-module-lexer@1.3.1:
|
|
||||||
resolution: {integrity: sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==}
|
|
||||||
|
|
||||||
es-module-lexer@1.5.4:
|
es-module-lexer@1.5.4:
|
||||||
resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==}
|
resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==}
|
||||||
|
|
||||||
|
@ -3560,9 +3685,6 @@ packages:
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
jsonc-parser@3.2.0:
|
|
||||||
resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==}
|
|
||||||
|
|
||||||
jsonfile@6.1.0:
|
jsonfile@6.1.0:
|
||||||
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
|
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
|
||||||
|
|
||||||
|
@ -3821,9 +3943,6 @@ packages:
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
mlly@1.4.2:
|
|
||||||
resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==}
|
|
||||||
|
|
||||||
mlly@1.7.1:
|
mlly@1.7.1:
|
||||||
resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==}
|
resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==}
|
||||||
|
|
||||||
|
@ -3994,6 +4113,10 @@ packages:
|
||||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
octokit@4.0.2:
|
||||||
|
resolution: {integrity: sha512-wbqF4uc1YbcldtiBFfkSnquHtECEIpYD78YUXI6ri1Im5OO2NLo6ZVpRdbJpdnpZ05zMrVPssNiEo6JQtea+Qg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
ofetch@1.3.3:
|
ofetch@1.3.3:
|
||||||
resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==}
|
resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==}
|
||||||
|
|
||||||
|
@ -4168,9 +4291,6 @@ packages:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
pkg-types@1.0.3:
|
|
||||||
resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==}
|
|
||||||
|
|
||||||
pkg-types@1.2.0:
|
pkg-types@1.2.0:
|
||||||
resolution: {integrity: sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==}
|
resolution: {integrity: sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==}
|
||||||
|
|
||||||
|
@ -4394,6 +4514,9 @@ packages:
|
||||||
resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
|
resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
|
property-expr@2.0.6:
|
||||||
|
resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==}
|
||||||
|
|
||||||
protocols@2.0.1:
|
protocols@2.0.1:
|
||||||
resolution: {integrity: sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==}
|
resolution: {integrity: sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==}
|
||||||
|
|
||||||
|
@ -4883,6 +5006,9 @@ packages:
|
||||||
text-table@0.2.0:
|
text-table@0.2.0:
|
||||||
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
||||||
|
|
||||||
|
tiny-case@1.0.3:
|
||||||
|
resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==}
|
||||||
|
|
||||||
tiny-invariant@1.3.1:
|
tiny-invariant@1.3.1:
|
||||||
resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==}
|
resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==}
|
||||||
|
|
||||||
|
@ -4920,6 +5046,9 @@ packages:
|
||||||
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
|
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
|
||||||
engines: {node: '>=0.6'}
|
engines: {node: '>=0.6'}
|
||||||
|
|
||||||
|
toposort@2.0.2:
|
||||||
|
resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==}
|
||||||
|
|
||||||
totalist@3.0.1:
|
totalist@3.0.1:
|
||||||
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
|
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -4964,10 +5093,18 @@ packages:
|
||||||
resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==}
|
resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
type-fest@2.19.0:
|
||||||
|
resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
|
||||||
|
engines: {node: '>=12.20'}
|
||||||
|
|
||||||
type-fest@3.13.1:
|
type-fest@3.13.1:
|
||||||
resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==}
|
resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==}
|
||||||
engines: {node: '>=14.16'}
|
engines: {node: '>=14.16'}
|
||||||
|
|
||||||
|
type-fest@4.26.1:
|
||||||
|
resolution: {integrity: sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==}
|
||||||
|
engines: {node: '>=16'}
|
||||||
|
|
||||||
typescript@5.5.4:
|
typescript@5.5.4:
|
||||||
resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
|
resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
|
||||||
engines: {node: '>=14.17'}
|
engines: {node: '>=14.17'}
|
||||||
|
@ -5022,6 +5159,12 @@ packages:
|
||||||
resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==}
|
resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==}
|
||||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
||||||
|
|
||||||
|
universal-github-app-jwt@2.2.0:
|
||||||
|
resolution: {integrity: sha512-G5o6f95b5BggDGuUfKDApKaCgNYy2x7OdHY0zSMF081O0EJobw+1130VONhrA7ezGSV2FNOGyM+KQpQZAr9bIQ==}
|
||||||
|
|
||||||
|
universal-user-agent@7.0.2:
|
||||||
|
resolution: {integrity: sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==}
|
||||||
|
|
||||||
universalify@2.0.0:
|
universalify@2.0.0:
|
||||||
resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==}
|
resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==}
|
||||||
engines: {node: '>= 10.0.0'}
|
engines: {node: '>= 10.0.0'}
|
||||||
|
@ -5184,6 +5327,11 @@ packages:
|
||||||
resolution: {integrity: sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==}
|
resolution: {integrity: sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==}
|
||||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
||||||
|
|
||||||
|
vee-validate@4.13.2:
|
||||||
|
resolution: {integrity: sha512-HlpR/6MJ92TW9f135umMZKUqdd/tFQTxLNSf2ImbU4Y/MlLVAUpF1l64VdjTOhbClAqPjCb5p/SqHDxLpUHXrw==}
|
||||||
|
peerDependencies:
|
||||||
|
vue: ^3.4.26
|
||||||
|
|
||||||
vite-hot-client@0.2.3:
|
vite-hot-client@0.2.3:
|
||||||
resolution: {integrity: sha512-rOGAV7rUlUHX89fP2p2v0A2WWvV3QMX2UYq0fRqsWSvFvev4atHWqjwGoKaZT1VTKyLGk533ecu3eyd0o59CAg==}
|
resolution: {integrity: sha512-rOGAV7rUlUHX89fP2p2v0A2WWvV3QMX2UYq0fRqsWSvFvev4atHWqjwGoKaZT1VTKyLGk533ecu3eyd0o59CAg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -5486,8 +5634,8 @@ packages:
|
||||||
yallist@4.0.0:
|
yallist@4.0.0:
|
||||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||||
|
|
||||||
yaml@2.5.0:
|
yaml@2.5.1:
|
||||||
resolution: {integrity: sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==}
|
resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==}
|
||||||
engines: {node: '>= 14'}
|
engines: {node: '>= 14'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
@ -5507,6 +5655,9 @@ packages:
|
||||||
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
|
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
|
||||||
engines: {node: '>=12.20'}
|
engines: {node: '>=12.20'}
|
||||||
|
|
||||||
|
yup@1.4.0:
|
||||||
|
resolution: {integrity: sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==}
|
||||||
|
|
||||||
zhead@2.2.4:
|
zhead@2.2.4:
|
||||||
resolution: {integrity: sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==}
|
resolution: {integrity: sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==}
|
||||||
|
|
||||||
|
@ -6771,9 +6922,9 @@ snapshots:
|
||||||
ignore: 5.2.4
|
ignore: 5.2.4
|
||||||
jiti: 1.20.0
|
jiti: 1.20.0
|
||||||
knitwork: 1.0.0
|
knitwork: 1.0.0
|
||||||
mlly: 1.4.2
|
mlly: 1.7.1
|
||||||
pathe: 1.1.1
|
pathe: 1.1.1
|
||||||
pkg-types: 1.0.3
|
pkg-types: 1.2.0
|
||||||
scule: 1.0.0
|
scule: 1.0.0
|
||||||
semver: 7.5.4
|
semver: 7.5.4
|
||||||
ufo: 1.3.1
|
ufo: 1.3.1
|
||||||
|
@ -6809,7 +6960,7 @@ snapshots:
|
||||||
defu: 6.1.2
|
defu: 6.1.2
|
||||||
hookable: 5.5.3
|
hookable: 5.5.3
|
||||||
pathe: 1.1.1
|
pathe: 1.1.1
|
||||||
pkg-types: 1.0.3
|
pkg-types: 1.2.0
|
||||||
postcss-import-resolver: 2.0.0
|
postcss-import-resolver: 2.0.0
|
||||||
std-env: 3.4.3
|
std-env: 3.4.3
|
||||||
ufo: 1.3.1
|
ufo: 1.3.1
|
||||||
|
@ -6952,6 +7103,152 @@ snapshots:
|
||||||
- rollup
|
- rollup
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
'@octokit/app@15.1.0':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/auth-app': 7.1.1
|
||||||
|
'@octokit/auth-unauthenticated': 6.1.0
|
||||||
|
'@octokit/core': 6.1.2
|
||||||
|
'@octokit/oauth-app': 7.1.3
|
||||||
|
'@octokit/plugin-paginate-rest': 11.3.3(@octokit/core@6.1.2)
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
'@octokit/webhooks': 13.3.0
|
||||||
|
|
||||||
|
'@octokit/auth-app@7.1.1':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/auth-oauth-app': 8.1.1
|
||||||
|
'@octokit/auth-oauth-user': 5.1.1
|
||||||
|
'@octokit/request': 9.1.3
|
||||||
|
'@octokit/request-error': 6.1.4
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
lru-cache: 10.4.3
|
||||||
|
universal-github-app-jwt: 2.2.0
|
||||||
|
universal-user-agent: 7.0.2
|
||||||
|
|
||||||
|
'@octokit/auth-oauth-app@8.1.1':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/auth-oauth-device': 7.1.1
|
||||||
|
'@octokit/auth-oauth-user': 5.1.1
|
||||||
|
'@octokit/request': 9.1.3
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
universal-user-agent: 7.0.2
|
||||||
|
|
||||||
|
'@octokit/auth-oauth-device@7.1.1':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/oauth-methods': 5.1.2
|
||||||
|
'@octokit/request': 9.1.3
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
universal-user-agent: 7.0.2
|
||||||
|
|
||||||
|
'@octokit/auth-oauth-user@5.1.1':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/auth-oauth-device': 7.1.1
|
||||||
|
'@octokit/oauth-methods': 5.1.2
|
||||||
|
'@octokit/request': 9.1.3
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
universal-user-agent: 7.0.2
|
||||||
|
|
||||||
|
'@octokit/auth-token@5.1.1': {}
|
||||||
|
|
||||||
|
'@octokit/auth-unauthenticated@6.1.0':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/request-error': 6.1.4
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
|
||||||
|
'@octokit/core@6.1.2':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/auth-token': 5.1.1
|
||||||
|
'@octokit/graphql': 8.1.1
|
||||||
|
'@octokit/request': 9.1.3
|
||||||
|
'@octokit/request-error': 6.1.4
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
before-after-hook: 3.0.2
|
||||||
|
universal-user-agent: 7.0.2
|
||||||
|
|
||||||
|
'@octokit/endpoint@10.1.1':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
universal-user-agent: 7.0.2
|
||||||
|
|
||||||
|
'@octokit/graphql@8.1.1':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/request': 9.1.3
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
universal-user-agent: 7.0.2
|
||||||
|
|
||||||
|
'@octokit/oauth-app@7.1.3':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/auth-oauth-app': 8.1.1
|
||||||
|
'@octokit/auth-oauth-user': 5.1.1
|
||||||
|
'@octokit/auth-unauthenticated': 6.1.0
|
||||||
|
'@octokit/core': 6.1.2
|
||||||
|
'@octokit/oauth-authorization-url': 7.1.1
|
||||||
|
'@octokit/oauth-methods': 5.1.2
|
||||||
|
'@types/aws-lambda': 8.10.145
|
||||||
|
universal-user-agent: 7.0.2
|
||||||
|
|
||||||
|
'@octokit/oauth-authorization-url@7.1.1': {}
|
||||||
|
|
||||||
|
'@octokit/oauth-methods@5.1.2':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/oauth-authorization-url': 7.1.1
|
||||||
|
'@octokit/request': 9.1.3
|
||||||
|
'@octokit/request-error': 6.1.4
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
|
||||||
|
'@octokit/openapi-types@22.2.0': {}
|
||||||
|
|
||||||
|
'@octokit/openapi-webhooks-types@8.3.0': {}
|
||||||
|
|
||||||
|
'@octokit/plugin-paginate-graphql@5.2.2(@octokit/core@6.1.2)':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/core': 6.1.2
|
||||||
|
|
||||||
|
'@octokit/plugin-paginate-rest@11.3.3(@octokit/core@6.1.2)':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/core': 6.1.2
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
|
||||||
|
'@octokit/plugin-rest-endpoint-methods@13.2.4(@octokit/core@6.1.2)':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/core': 6.1.2
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
|
||||||
|
'@octokit/plugin-retry@7.1.1(@octokit/core@6.1.2)':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/core': 6.1.2
|
||||||
|
'@octokit/request-error': 6.1.4
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
bottleneck: 2.19.5
|
||||||
|
|
||||||
|
'@octokit/plugin-throttling@9.3.1(@octokit/core@6.1.2)':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/core': 6.1.2
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
bottleneck: 2.19.5
|
||||||
|
|
||||||
|
'@octokit/request-error@6.1.4':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
|
||||||
|
'@octokit/request@9.1.3':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/endpoint': 10.1.1
|
||||||
|
'@octokit/request-error': 6.1.4
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
universal-user-agent: 7.0.2
|
||||||
|
|
||||||
|
'@octokit/types@13.5.0':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/openapi-types': 22.2.0
|
||||||
|
|
||||||
|
'@octokit/webhooks-methods@5.1.0': {}
|
||||||
|
|
||||||
|
'@octokit/webhooks@13.3.0':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/openapi-webhooks-types': 8.3.0
|
||||||
|
'@octokit/request-error': 6.1.4
|
||||||
|
'@octokit/webhooks-methods': 5.1.0
|
||||||
|
|
||||||
'@parcel/watcher-android-arm64@2.4.1':
|
'@parcel/watcher-android-arm64@2.4.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
@ -7221,15 +7518,12 @@ snapshots:
|
||||||
|
|
||||||
'@trysound/sax@0.2.0': {}
|
'@trysound/sax@0.2.0': {}
|
||||||
|
|
||||||
|
'@types/aws-lambda@8.10.145': {}
|
||||||
|
|
||||||
'@types/eslint-scope@3.7.6':
|
'@types/eslint-scope@3.7.6':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/eslint': 8.44.6
|
'@types/eslint': 9.6.1
|
||||||
'@types/estree': 1.0.3
|
'@types/estree': 1.0.5
|
||||||
|
|
||||||
'@types/eslint@8.44.6':
|
|
||||||
dependencies:
|
|
||||||
'@types/estree': 1.0.3
|
|
||||||
'@types/json-schema': 7.0.14
|
|
||||||
|
|
||||||
'@types/eslint@9.6.1':
|
'@types/eslint@9.6.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -7572,6 +7866,17 @@ snapshots:
|
||||||
- rollup
|
- rollup
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
'@vee-validate/nuxt@4.13.2(magicast@0.3.5)(rollup@4.21.2)(vue@3.4.38(typescript@5.5.4))':
|
||||||
|
dependencies:
|
||||||
|
'@nuxt/kit': 3.13.0(magicast@0.3.5)(rollup@4.21.2)
|
||||||
|
local-pkg: 0.5.0
|
||||||
|
vee-validate: 4.13.2(vue@3.4.38(typescript@5.5.4))
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- magicast
|
||||||
|
- rollup
|
||||||
|
- supports-color
|
||||||
|
- vue
|
||||||
|
|
||||||
'@vercel/nft@0.26.5(encoding@0.1.13)':
|
'@vercel/nft@0.26.5(encoding@0.1.13)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@mapbox/node-pre-gyp': 1.0.11(encoding@0.1.13)
|
'@mapbox/node-pre-gyp': 1.0.11(encoding@0.1.13)
|
||||||
|
@ -7947,9 +8252,9 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
event-target-shim: 5.0.1
|
event-target-shim: 5.0.1
|
||||||
|
|
||||||
acorn-import-assertions@1.9.0(acorn@8.11.2):
|
acorn-import-assertions@1.9.0(acorn@8.12.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.11.2
|
acorn: 8.12.1
|
||||||
|
|
||||||
acorn-import-attributes@1.9.5(acorn@8.12.1):
|
acorn-import-attributes@1.9.5(acorn@8.12.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -8085,6 +8390,8 @@ snapshots:
|
||||||
|
|
||||||
base64-js@1.5.1: {}
|
base64-js@1.5.1: {}
|
||||||
|
|
||||||
|
before-after-hook@3.0.2: {}
|
||||||
|
|
||||||
binary-extensions@2.2.0: {}
|
binary-extensions@2.2.0: {}
|
||||||
|
|
||||||
bindings@1.5.0:
|
bindings@1.5.0:
|
||||||
|
@ -8102,6 +8409,8 @@ snapshots:
|
||||||
|
|
||||||
boolbase@1.0.0: {}
|
boolbase@1.0.0: {}
|
||||||
|
|
||||||
|
bottleneck@2.19.5: {}
|
||||||
|
|
||||||
brace-expansion@1.1.11:
|
brace-expansion@1.1.11:
|
||||||
dependencies:
|
dependencies:
|
||||||
balanced-match: 1.0.2
|
balanced-match: 1.0.2
|
||||||
|
@ -8195,11 +8504,11 @@ snapshots:
|
||||||
dotenv: 16.3.1
|
dotenv: 16.3.1
|
||||||
giget: 1.1.3
|
giget: 1.1.3
|
||||||
jiti: 1.20.0
|
jiti: 1.20.0
|
||||||
mlly: 1.4.2
|
mlly: 1.7.1
|
||||||
ohash: 1.1.3
|
ohash: 1.1.3
|
||||||
pathe: 1.1.1
|
pathe: 1.1.1
|
||||||
perfect-debounce: 1.0.0
|
perfect-debounce: 1.0.0
|
||||||
pkg-types: 1.0.3
|
pkg-types: 1.2.0
|
||||||
rc9: 2.1.1
|
rc9: 2.1.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
@ -8662,8 +8971,6 @@ snapshots:
|
||||||
|
|
||||||
errx@0.1.0: {}
|
errx@0.1.0: {}
|
||||||
|
|
||||||
es-module-lexer@1.3.1: {}
|
|
||||||
|
|
||||||
es-module-lexer@1.5.4: {}
|
es-module-lexer@1.5.4: {}
|
||||||
|
|
||||||
esbuild@0.19.10:
|
esbuild@0.19.10:
|
||||||
|
@ -9595,8 +9902,6 @@ snapshots:
|
||||||
|
|
||||||
json5@2.2.3: {}
|
json5@2.2.3: {}
|
||||||
|
|
||||||
jsonc-parser@3.2.0: {}
|
|
||||||
|
|
||||||
jsonfile@6.1.0:
|
jsonfile@6.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
universalify: 2.0.0
|
universalify: 2.0.0
|
||||||
|
@ -9668,7 +9973,7 @@ snapshots:
|
||||||
|
|
||||||
local-pkg@0.5.0:
|
local-pkg@0.5.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
mlly: 1.4.2
|
mlly: 1.7.1
|
||||||
pkg-types: 1.2.0
|
pkg-types: 1.2.0
|
||||||
|
|
||||||
locate-path@5.0.0:
|
locate-path@5.0.0:
|
||||||
|
@ -9851,13 +10156,6 @@ snapshots:
|
||||||
|
|
||||||
mkdirp@1.0.4: {}
|
mkdirp@1.0.4: {}
|
||||||
|
|
||||||
mlly@1.4.2:
|
|
||||||
dependencies:
|
|
||||||
acorn: 8.10.0
|
|
||||||
pathe: 1.1.1
|
|
||||||
pkg-types: 1.0.3
|
|
||||||
ufo: 1.3.1
|
|
||||||
|
|
||||||
mlly@1.7.1:
|
mlly@1.7.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.12.1
|
acorn: 8.12.1
|
||||||
|
@ -10205,6 +10503,19 @@ snapshots:
|
||||||
|
|
||||||
object-assign@4.1.1: {}
|
object-assign@4.1.1: {}
|
||||||
|
|
||||||
|
octokit@4.0.2:
|
||||||
|
dependencies:
|
||||||
|
'@octokit/app': 15.1.0
|
||||||
|
'@octokit/core': 6.1.2
|
||||||
|
'@octokit/oauth-app': 7.1.3
|
||||||
|
'@octokit/plugin-paginate-graphql': 5.2.2(@octokit/core@6.1.2)
|
||||||
|
'@octokit/plugin-paginate-rest': 11.3.3(@octokit/core@6.1.2)
|
||||||
|
'@octokit/plugin-rest-endpoint-methods': 13.2.4(@octokit/core@6.1.2)
|
||||||
|
'@octokit/plugin-retry': 7.1.1(@octokit/core@6.1.2)
|
||||||
|
'@octokit/plugin-throttling': 9.3.1(@octokit/core@6.1.2)
|
||||||
|
'@octokit/request-error': 6.1.4
|
||||||
|
'@octokit/types': 13.5.0
|
||||||
|
|
||||||
ofetch@1.3.3:
|
ofetch@1.3.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
destr: 2.0.2
|
destr: 2.0.2
|
||||||
|
@ -10373,12 +10684,6 @@ snapshots:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.5.4
|
typescript: 5.5.4
|
||||||
|
|
||||||
pkg-types@1.0.3:
|
|
||||||
dependencies:
|
|
||||||
jsonc-parser: 3.2.0
|
|
||||||
mlly: 1.4.2
|
|
||||||
pathe: 1.1.1
|
|
||||||
|
|
||||||
pkg-types@1.2.0:
|
pkg-types@1.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
confbox: 0.1.7
|
confbox: 0.1.7
|
||||||
|
@ -10597,6 +10902,8 @@ snapshots:
|
||||||
kleur: 3.0.3
|
kleur: 3.0.3
|
||||||
sisteransi: 1.0.5
|
sisteransi: 1.0.5
|
||||||
|
|
||||||
|
property-expr@2.0.6: {}
|
||||||
|
|
||||||
protocols@2.0.1: {}
|
protocols@2.0.1: {}
|
||||||
|
|
||||||
prr@1.0.1: {}
|
prr@1.0.1: {}
|
||||||
|
@ -10793,7 +11100,7 @@ snapshots:
|
||||||
|
|
||||||
schema-utils@3.3.0:
|
schema-utils@3.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/json-schema': 7.0.14
|
'@types/json-schema': 7.0.15
|
||||||
ajv: 6.12.6
|
ajv: 6.12.6
|
||||||
ajv-keywords: 3.5.2(ajv@6.12.6)
|
ajv-keywords: 3.5.2(ajv@6.12.6)
|
||||||
|
|
||||||
|
@ -11141,7 +11448,7 @@ snapshots:
|
||||||
|
|
||||||
terser-webpack-plugin@5.3.9(esbuild@0.23.1)(webpack@5.89.0(esbuild@0.23.1)):
|
terser-webpack-plugin@5.3.9(esbuild@0.23.1)(webpack@5.89.0(esbuild@0.23.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/trace-mapping': 0.3.20
|
'@jridgewell/trace-mapping': 0.3.25
|
||||||
jest-worker: 27.5.1
|
jest-worker: 27.5.1
|
||||||
schema-utils: 3.3.0
|
schema-utils: 3.3.0
|
||||||
serialize-javascript: 6.0.1
|
serialize-javascript: 6.0.1
|
||||||
|
@ -11159,6 +11466,8 @@ snapshots:
|
||||||
|
|
||||||
text-table@0.2.0: {}
|
text-table@0.2.0: {}
|
||||||
|
|
||||||
|
tiny-case@1.0.3: {}
|
||||||
|
|
||||||
tiny-invariant@1.3.1: {}
|
tiny-invariant@1.3.1: {}
|
||||||
|
|
||||||
tinybench@2.9.0: {}
|
tinybench@2.9.0: {}
|
||||||
|
@ -11184,6 +11493,8 @@ snapshots:
|
||||||
|
|
||||||
toidentifier@1.0.1: {}
|
toidentifier@1.0.1: {}
|
||||||
|
|
||||||
|
toposort@2.0.2: {}
|
||||||
|
|
||||||
totalist@3.0.1: {}
|
totalist@3.0.1: {}
|
||||||
|
|
||||||
tr46@0.0.3: {}
|
tr46@0.0.3: {}
|
||||||
|
@ -11218,8 +11529,12 @@ snapshots:
|
||||||
|
|
||||||
type-fest@0.8.1: {}
|
type-fest@0.8.1: {}
|
||||||
|
|
||||||
|
type-fest@2.19.0: {}
|
||||||
|
|
||||||
type-fest@3.13.1: {}
|
type-fest@3.13.1: {}
|
||||||
|
|
||||||
|
type-fest@4.26.1: {}
|
||||||
|
|
||||||
typescript@5.5.4: {}
|
typescript@5.5.4: {}
|
||||||
|
|
||||||
ufo@1.3.1: {}
|
ufo@1.3.1: {}
|
||||||
|
@ -11293,9 +11608,9 @@ snapshots:
|
||||||
fast-glob: 3.3.1
|
fast-glob: 3.3.1
|
||||||
local-pkg: 0.4.3
|
local-pkg: 0.4.3
|
||||||
magic-string: 0.30.5
|
magic-string: 0.30.5
|
||||||
mlly: 1.4.2
|
mlly: 1.7.1
|
||||||
pathe: 1.1.1
|
pathe: 1.1.1
|
||||||
pkg-types: 1.0.3
|
pkg-types: 1.2.0
|
||||||
scule: 1.0.0
|
scule: 1.0.0
|
||||||
strip-literal: 1.3.0
|
strip-literal: 1.3.0
|
||||||
unplugin: 1.5.0
|
unplugin: 1.5.0
|
||||||
|
@ -11310,6 +11625,10 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
imurmurhash: 0.1.4
|
imurmurhash: 0.1.4
|
||||||
|
|
||||||
|
universal-github-app-jwt@2.2.0: {}
|
||||||
|
|
||||||
|
universal-user-agent@7.0.2: {}
|
||||||
|
|
||||||
universalify@2.0.0: {}
|
universalify@2.0.0: {}
|
||||||
|
|
||||||
unocss@0.62.3(@unocss/webpack@0.62.3(rollup@4.21.2)(webpack@5.89.0(esbuild@0.23.1)))(postcss@8.4.44)(rollup@4.21.2)(vite@5.4.2(@types/node@20.8.7)(terser@5.22.0)):
|
unocss@0.62.3(@unocss/webpack@0.62.3(rollup@4.21.2)(webpack@5.89.0(esbuild@0.23.1)))(postcss@8.4.44)(rollup@4.21.2)(vite@5.4.2(@types/node@20.8.7)(terser@5.22.0)):
|
||||||
|
@ -11357,7 +11676,7 @@ snapshots:
|
||||||
pathe: 1.1.2
|
pathe: 1.1.2
|
||||||
scule: 1.3.0
|
scule: 1.3.0
|
||||||
unplugin: 1.12.3
|
unplugin: 1.12.3
|
||||||
yaml: 2.5.0
|
yaml: 2.5.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
vue-router: 4.4.3(vue@3.4.38(typescript@5.5.4))
|
vue-router: 4.4.3(vue@3.4.38(typescript@5.5.4))
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -11488,6 +11807,12 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
builtins: 5.0.1
|
builtins: 5.0.1
|
||||||
|
|
||||||
|
vee-validate@4.13.2(vue@3.4.38(typescript@5.5.4)):
|
||||||
|
dependencies:
|
||||||
|
'@vue/devtools-api': 6.6.3
|
||||||
|
type-fest: 4.26.1
|
||||||
|
vue: 3.4.38(typescript@5.5.4)
|
||||||
|
|
||||||
vite-hot-client@0.2.3(vite@5.4.2(@types/node@20.8.7)(terser@5.22.0)):
|
vite-hot-client@0.2.3(vite@5.4.2(@types/node@20.8.7)(terser@5.22.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
vite: 5.4.2(@types/node@20.8.7)(terser@5.22.0)
|
vite: 5.4.2(@types/node@20.8.7)(terser@5.22.0)
|
||||||
|
@ -11724,16 +12049,16 @@ snapshots:
|
||||||
webpack@5.89.0(esbuild@0.23.1):
|
webpack@5.89.0(esbuild@0.23.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/eslint-scope': 3.7.6
|
'@types/eslint-scope': 3.7.6
|
||||||
'@types/estree': 1.0.3
|
'@types/estree': 1.0.5
|
||||||
'@webassemblyjs/ast': 1.11.6
|
'@webassemblyjs/ast': 1.11.6
|
||||||
'@webassemblyjs/wasm-edit': 1.11.6
|
'@webassemblyjs/wasm-edit': 1.11.6
|
||||||
'@webassemblyjs/wasm-parser': 1.11.6
|
'@webassemblyjs/wasm-parser': 1.11.6
|
||||||
acorn: 8.11.2
|
acorn: 8.12.1
|
||||||
acorn-import-assertions: 1.9.0(acorn@8.11.2)
|
acorn-import-assertions: 1.9.0(acorn@8.12.1)
|
||||||
browserslist: 4.22.2
|
browserslist: 4.23.3
|
||||||
chrome-trace-event: 1.0.3
|
chrome-trace-event: 1.0.3
|
||||||
enhanced-resolve: 5.15.0
|
enhanced-resolve: 5.15.0
|
||||||
es-module-lexer: 1.3.1
|
es-module-lexer: 1.5.4
|
||||||
eslint-scope: 5.1.1
|
eslint-scope: 5.1.1
|
||||||
events: 3.3.0
|
events: 3.3.0
|
||||||
glob-to-regexp: 0.4.1
|
glob-to-regexp: 0.4.1
|
||||||
|
@ -11804,7 +12129,7 @@ snapshots:
|
||||||
|
|
||||||
yallist@4.0.0: {}
|
yallist@4.0.0: {}
|
||||||
|
|
||||||
yaml@2.5.0: {}
|
yaml@2.5.1: {}
|
||||||
|
|
||||||
yargs-parser@21.1.1: {}
|
yargs-parser@21.1.1: {}
|
||||||
|
|
||||||
|
@ -11822,6 +12147,13 @@ snapshots:
|
||||||
|
|
||||||
yocto-queue@1.0.0: {}
|
yocto-queue@1.0.0: {}
|
||||||
|
|
||||||
|
yup@1.4.0:
|
||||||
|
dependencies:
|
||||||
|
property-expr: 2.0.6
|
||||||
|
tiny-case: 1.0.3
|
||||||
|
toposort: 2.0.2
|
||||||
|
type-fest: 2.19.0
|
||||||
|
|
||||||
zhead@2.2.4: {}
|
zhead@2.2.4: {}
|
||||||
|
|
||||||
zip-stream@6.0.1:
|
zip-stream@6.0.1:
|
||||||
|
|
127
server/api/data.post.ts
Normal file
127
server/api/data.post.ts
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
import { App } from 'octokit'
|
||||||
|
import yaml from 'yaml'
|
||||||
|
import type { Project } from '~/types'
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const body = await readBody<{ project: Project, image?: { type: string, data: string } }>(event)
|
||||||
|
const yamlProject = yaml.stringify(body.project)
|
||||||
|
const { appId, privateKey, installationId } = useAppConfig().github
|
||||||
|
|
||||||
|
const id = body.project.id || body.project.name.toLowerCase().replace(/\s+/g, '-')
|
||||||
|
|
||||||
|
const app = new App({
|
||||||
|
appId,
|
||||||
|
privateKey,
|
||||||
|
})
|
||||||
|
await app.octokit.rest.apps.getAuthenticated()
|
||||||
|
const octokit = await app.getInstallationOctokit(installationId)
|
||||||
|
|
||||||
|
const owner = 'develit-io'
|
||||||
|
const repo = 'test-repo'
|
||||||
|
const baseBranch = 'main'
|
||||||
|
const newBranchName = `${id}-project-update`
|
||||||
|
const commitMessage = `${body.project.id ? `Updating the project: ${body.project.name}` : `Initiating the creation of project: ${body.project.name}`}`
|
||||||
|
|
||||||
|
const files = [
|
||||||
|
{
|
||||||
|
path: `src/projects/${id}/index.yaml`,
|
||||||
|
content: yamlProject,
|
||||||
|
encoding: 'utf-8',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
if (body.image?.data && body.image?.type) {
|
||||||
|
files.push(
|
||||||
|
{
|
||||||
|
path: `src/projects/${id}/logo.${body.image.type.split('/')[1]}`,
|
||||||
|
content: body.image.data,
|
||||||
|
encoding: 'base64',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createBranch(owner: string, repo: string, newBranchName: string, baseBranch: string) {
|
||||||
|
const { data: baseBranchData } = await octokit.rest.git.getRef({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
ref: `heads/${baseBranch}`,
|
||||||
|
})
|
||||||
|
|
||||||
|
await octokit.rest.git.createRef({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
ref: `refs/heads/${newBranchName}`,
|
||||||
|
sha: baseBranchData.object.sha,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function commitChangesToNewBranch(owner: string, repo: string, newBranch: string, message: string, files: { path: string, content: string }[]) {
|
||||||
|
const { data: latestCommit } = await octokit.rest.repos.getCommit({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
ref: newBranch,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { data: baseTree } = await octokit.rest.git.getTree({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
tree_sha: latestCommit.commit.tree.sha,
|
||||||
|
})
|
||||||
|
|
||||||
|
const tree = files.map(file => ({
|
||||||
|
path: file.path,
|
||||||
|
mode: '100644' as const,
|
||||||
|
type: 'blob' as const,
|
||||||
|
content: file.content,
|
||||||
|
}))
|
||||||
|
|
||||||
|
const { data: newTree } = await octokit.rest.git.createTree({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
base_tree: baseTree.sha,
|
||||||
|
tree,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { data: newCommit } = await octokit.rest.git.createCommit({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
message,
|
||||||
|
tree: newTree.sha,
|
||||||
|
parents: [latestCommit.sha],
|
||||||
|
})
|
||||||
|
|
||||||
|
await octokit.rest.git.updateRef({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
ref: `heads/${newBranch}`,
|
||||||
|
sha: newCommit.sha,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createPullRequest(owner: string, repo: string, head: string, base: string, title: string, body: string) {
|
||||||
|
const { data: pullRequest } = await octokit.rest.pulls.create({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
title,
|
||||||
|
head,
|
||||||
|
base,
|
||||||
|
body,
|
||||||
|
})
|
||||||
|
|
||||||
|
return pullRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await createBranch(owner, repo, newBranchName, baseBranch)
|
||||||
|
console.log(`Branch ${newBranchName} created successfully!`)
|
||||||
|
|
||||||
|
await commitChangesToNewBranch(owner, repo, newBranchName, commitMessage, files)
|
||||||
|
console.log(`Changes committed to branch ${newBranchName} successfully!`)
|
||||||
|
|
||||||
|
const pullRequestData = await createPullRequest(owner, repo, newBranchName, baseBranch, `${body.project.id ? `Update project: ${body.project.name}` : `Create project: ${body.project.name}`}`, `${body.project.id ? `Updating the project: ${body.project.name}` : `Initiating the creation of project: ${body.project.name}`}`)
|
||||||
|
console.log('Pull request created:', pullRequestData)
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error('Error during GitHub operations:', error)
|
||||||
|
}
|
||||||
|
})
|
|
@ -16185,5 +16185,47 @@
|
||||||
"id": "other",
|
"id": "other",
|
||||||
"name": "Other"
|
"name": "Other"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"project_phase": [
|
||||||
|
{
|
||||||
|
"id": "mainnet",
|
||||||
|
"name": "Mainnet"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "testnet",
|
||||||
|
"name": "Testnet"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "alpha",
|
||||||
|
"name": "Alpha"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "beta",
|
||||||
|
"name": "Beta"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mvp",
|
||||||
|
"name": "MVP"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"asset_custody_type": [
|
||||||
|
{
|
||||||
|
"id": "non-custody",
|
||||||
|
"name": "Non-custody"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sign_in_type_requirments": [
|
||||||
|
{
|
||||||
|
"id": "wallet",
|
||||||
|
"name": "Wallet"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "email",
|
||||||
|
"name": "Email"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "seed",
|
||||||
|
"name": "Seed"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
export interface Category {
|
export interface Category {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
|
usecases: string[]
|
||||||
projectsCount: number
|
projectsCount: number
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export interface InputOption {
|
export interface InputOption {
|
||||||
label: string
|
label: string
|
||||||
value: string
|
value: string | number
|
||||||
count?: number
|
count?: number
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ export interface Member {
|
||||||
role?: string
|
role?: string
|
||||||
link?: string
|
link?: string
|
||||||
[k: string]: unknown
|
[k: string]: unknown
|
||||||
}
|
}[]
|
||||||
company?: {
|
company?: {
|
||||||
name?: string
|
name?: string
|
||||||
link?: string
|
link?: string
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { Member } from './member'
|
import type { Team } from './team'
|
||||||
import type { Fund } from './fund'
|
import type { Fund } from './fund'
|
||||||
import type { ClientDiversability } from './clientDiversability'
|
import type { ClientDiversability } from './clientDiversability'
|
||||||
import type { Audit } from './audit'
|
import type { Audit } from './audit'
|
||||||
|
@ -7,22 +7,25 @@ export interface Project {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
categories: string[]
|
categories: string[]
|
||||||
ecosystem?: string
|
usecases: 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
|
||||||
tokens?: {
|
tokens?: {
|
||||||
name?: string
|
name?: string
|
||||||
symbol: string
|
symbol?: string
|
||||||
network?: string
|
network?: string
|
||||||
contract_address?: string
|
contract_address?: string
|
||||||
link?: string
|
token_link?: string
|
||||||
[k: string]: unknown
|
[k: string]: unknown
|
||||||
}[]
|
}[]
|
||||||
description?: string
|
description?: string
|
||||||
project_type?: string
|
project_type?: string
|
||||||
product_launch_day?: string
|
product_launch_day?: string
|
||||||
|
project_phase?: string
|
||||||
|
sunset: boolean
|
||||||
technology?: {
|
technology?: {
|
||||||
type: string
|
type: string
|
||||||
name?: string
|
name?: string
|
||||||
|
@ -41,6 +44,7 @@ export interface Project {
|
||||||
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
|
||||||
|
@ -62,17 +66,17 @@ export interface Project {
|
||||||
}
|
}
|
||||||
[k: string]: unknown
|
[k: string]: unknown
|
||||||
opensource: boolean
|
opensource: boolean
|
||||||
viewing_key: boolean
|
viewing_key?: boolean
|
||||||
dissapearing_tx: boolean
|
dissapearing_tx?: boolean
|
||||||
frontend_anonymity: string
|
frontend_anonymity?: string
|
||||||
identity_integration: null
|
identity_integration?: null
|
||||||
connected_tx: boolean
|
connected_tx?: boolean
|
||||||
revealed_recipient: boolean
|
revealed_recipient?: boolean
|
||||||
revealed_sender: boolean
|
revealed_sender?: boolean
|
||||||
revealed_ammount: boolean
|
revealed_ammount?: boolean
|
||||||
reversability_condition: string
|
reversability_condition?: string
|
||||||
data_masking: string
|
data_masking?: string
|
||||||
asset_custody_type: string
|
asset_custody_type?: string
|
||||||
}
|
}
|
||||||
licences?: string
|
licences?: string
|
||||||
privacy_policy?: {
|
privacy_policy?: {
|
||||||
|
@ -81,7 +85,7 @@ export interface Project {
|
||||||
data_usage?: string
|
data_usage?: string
|
||||||
[k: string]: unknown
|
[k: string]: unknown
|
||||||
}
|
}
|
||||||
team?: Member[]
|
team?: Team
|
||||||
storage?: {
|
storage?: {
|
||||||
decentralized?: boolean
|
decentralized?: boolean
|
||||||
[k: string]: unknown
|
[k: string]: unknown
|
||||||
|
@ -89,7 +93,7 @@ export interface Project {
|
||||||
tracebility?: {
|
tracebility?: {
|
||||||
tracked_data?: string
|
tracked_data?: string
|
||||||
kyc?: boolean
|
kyc?: boolean
|
||||||
sign_in_type_requirments?: string
|
sign_in_type_requirments?: string[]
|
||||||
[k: string]: unknown
|
[k: string]: unknown
|
||||||
}
|
}
|
||||||
third_party_dependency?: string
|
third_party_dependency?: string
|
||||||
|
@ -97,6 +101,7 @@ 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
|
||||||
|
@ -104,7 +109,7 @@ export interface Project {
|
||||||
time?: string
|
time?: string
|
||||||
link?: string
|
link?: string
|
||||||
[k: string]: unknown
|
[k: string]: unknown
|
||||||
}
|
}[]
|
||||||
client_diversability?: ClientDiversability[]
|
client_diversability?: ClientDiversability[]
|
||||||
default_privacy?: boolean
|
default_privacy?: boolean
|
||||||
funding?: Fund[]
|
funding?: Fund[]
|
||||||
|
@ -129,19 +134,19 @@ export interface ProjectShallow {
|
||||||
title1: string
|
title1: string
|
||||||
description: string
|
description: string
|
||||||
percentage: number
|
percentage: number
|
||||||
forum?: string | undefined
|
forum?: string
|
||||||
github?: string | undefined
|
github?: string
|
||||||
website?: string | undefined
|
website?: string
|
||||||
twitter?: string | undefined
|
twitter?: string
|
||||||
coingecko?: string | undefined
|
coingecko?: string
|
||||||
explorer?: string | undefined
|
explorer?: string
|
||||||
newsletter?: string | undefined
|
newsletter?: string
|
||||||
readyness?: string | undefined
|
readyness?: string
|
||||||
team: Member[] | undefined
|
team?: Team
|
||||||
docs: string | undefined
|
docs?: string
|
||||||
audits?: Audit[] | undefined
|
audits?: Audit[]
|
||||||
support?: number | undefined
|
support?: number
|
||||||
anonymity?: boolean | undefined
|
anonymity?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProjectIndexable extends Project {
|
export interface ProjectIndexable extends Project {
|
||||||
|
|
19
types/team.ts
Normal file
19
types/team.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
export interface Team {
|
||||||
|
name?: string
|
||||||
|
role?: string
|
||||||
|
link?: string
|
||||||
|
avatar?: string
|
||||||
|
anonymous?: boolean
|
||||||
|
teammembers?: {
|
||||||
|
name?: string
|
||||||
|
role?: string
|
||||||
|
link?: string
|
||||||
|
[k: string]: unknown
|
||||||
|
}[]
|
||||||
|
company?: {
|
||||||
|
name?: string
|
||||||
|
link?: string
|
||||||
|
contacts?: string
|
||||||
|
[k: string]: unknown
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,6 +47,7 @@ export default defineConfig({
|
||||||
black: '#000',
|
black: '#000',
|
||||||
green: '#B5E26B',
|
green: '#B5E26B',
|
||||||
red: '#FF5252',
|
red: '#FF5252',
|
||||||
|
danger: '#FF0000',
|
||||||
bg: {
|
bg: {
|
||||||
grey: '#ffffff33',
|
grey: '#ffffff33',
|
||||||
dark_grey: '#161616',
|
dark_grey: '#161616',
|
||||||
|
|
Loading…
Reference in a new issue