mirror of
https://github.com/web3privacy/explorer-app.git
synced 2024-10-15 16:46:26 +02:00
refactor: project store, project save, validations
This commit is contained in:
parent
67660b0972
commit
a94ea73d15
13 changed files with 187 additions and 100 deletions
|
@ -44,7 +44,7 @@ function useTokens(project?: Partial<Project>) {
|
||||||
const { tokens, newToken, addToken, removeToken } = useTokens(props.project)
|
const { tokens, newToken, addToken, removeToken } = useTokens(props.project)
|
||||||
const assetsUsed = ref<string[]>(Array.isArray(props.project?.assets_used) ? props.project?.assets_used.map(a => a.toLowerCase()) : [])
|
const assetsUsed = ref<string[]>(Array.isArray(props.project?.assets_used) ? props.project?.assets_used.map(a => a.toLowerCase()) : [])
|
||||||
|
|
||||||
const { useProject, assetsData } = useData()
|
const { assetsData } = useData()
|
||||||
const { saveProject } = useProject()
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
|
|
|
@ -6,7 +6,7 @@ const props = defineProps<{
|
||||||
project?: Partial<Project>
|
project?: Partial<Project>
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { useProject, categoriesData, usecasesData, ecosystemsData } = useData()
|
const { categoriesData, usecasesData, ecosystemsData } = useData()
|
||||||
const { saveProject } = useProject()
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
const validationSchema = yup.object().shape({
|
const validationSchema = yup.object().shape({
|
||||||
|
@ -31,8 +31,8 @@ const isDead = ref(props.project?.sunset || false)
|
||||||
|
|
||||||
resetForm({
|
resetForm({
|
||||||
values: {
|
values: {
|
||||||
categories: props.project?.categories?.map(c => c.toLowerCase()) || [],
|
categories: Array.isArray(props.project?.categories) ? props.project?.categories?.map(c => c.toLowerCase()) : [],
|
||||||
usecases: props.project?.usecases?.map(u => u.toLowerCase()) || [],
|
usecases: Array.isArray(props.project?.usecases) ? props.project?.usecases?.map(u => u.toLowerCase()) : [],
|
||||||
ecosystems: Array.isArray(props.project?.ecosystem) ? props.project?.ecosystem?.map(e => e.toLowerCase()) : [],
|
ecosystems: Array.isArray(props.project?.ecosystem) ? props.project?.ecosystem?.map(e => e.toLowerCase()) : [],
|
||||||
description: props.project?.description || '',
|
description: props.project?.description || '',
|
||||||
},
|
},
|
||||||
|
@ -55,7 +55,7 @@ function save() {
|
||||||
usecases: usecases.value,
|
usecases: usecases.value,
|
||||||
ecosystem: ecosystems.value,
|
ecosystem: ecosystems.value,
|
||||||
description: description.value,
|
description: description.value,
|
||||||
product_launch_day: new Date(year.value, month.value, day.value).toISOString(),
|
product_launch_day: (year.value && month.value && day.value) ? new Date(year.value, month.value, day.value).toISOString() : undefined,
|
||||||
sunset: isDead.value,
|
sunset: isDead.value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ function useFundings(project?: Partial<Project>) {
|
||||||
|
|
||||||
const { fundings, newFunding, addFunding, removeFunding } = useFundings(props.project)
|
const { fundings, newFunding, addFunding, removeFunding } = useFundings(props.project)
|
||||||
|
|
||||||
const { useProject } = useData()
|
|
||||||
const { saveProject } = useProject()
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
|
|
|
@ -72,7 +72,6 @@ function formatDate(date: string) {
|
||||||
return `${day}/${month}/${year}`
|
return `${day}/${month}/${year}`
|
||||||
}
|
}
|
||||||
|
|
||||||
const { useProject } = useData()
|
|
||||||
const { saveProject } = useProject()
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
|
|
|
@ -19,7 +19,6 @@ const telegram = ref<string>(props.project?.links?.telegram || '')
|
||||||
const lens = ref<string>(props.project?.links?.lens || '')
|
const lens = ref<string>(props.project?.links?.lens || '')
|
||||||
const farcaster = ref<string>(props.project?.links?.farcaster || '')
|
const farcaster = ref<string>(props.project?.links?.farcaster || '')
|
||||||
|
|
||||||
const { useProject } = useData()
|
|
||||||
const { saveProject } = useProject()
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
|
|
|
@ -13,7 +13,7 @@ const signRequirements = ref(Array.isArray(props.project?.tracebility?.sign_in_t
|
||||||
const trackedData = ref(props.project?.tracebility?.tracked_data || '')
|
const trackedData = ref(props.project?.tracebility?.tracked_data || '')
|
||||||
const dataUsage = ref(props.project?.privacy_policy?.data_usage || '')
|
const dataUsage = ref(props.project?.privacy_policy?.data_usage || '')
|
||||||
|
|
||||||
const { useProject, signInRequirmentsData } = useData()
|
const { signInRequirmentsData } = useData()
|
||||||
const { saveProject } = useProject()
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
|
|
|
@ -73,7 +73,6 @@ const thirdPartyDep = ref(props.project?.third_party_dependency || '')
|
||||||
const socialTrust = ref(props.project?.social_trust || '')
|
const socialTrust = ref(props.project?.social_trust || '')
|
||||||
const spof = ref(props.project?.technical_spof || '')
|
const spof = ref(props.project?.technical_spof || '')
|
||||||
|
|
||||||
const { useProject } = useData()
|
|
||||||
const { saveProject } = useProject()
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
|
|
|
@ -39,7 +39,6 @@ function useMembers(project?: Partial<Project>) {
|
||||||
|
|
||||||
const { members, newMember, addMember, removeMember } = useMembers(props.project)
|
const { members, newMember, addMember, removeMember } = useMembers(props.project)
|
||||||
|
|
||||||
const { useProject } = useData()
|
|
||||||
const { saveProject } = useProject()
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
|
|
|
@ -13,7 +13,7 @@ const encryption = ref(props.project?.blockchain_features?.encryption || '')
|
||||||
const peerToPeer = ref(props.project?.blockchain_features?.p2p)
|
const peerToPeer = ref(props.project?.blockchain_features?.p2p)
|
||||||
const decentralizedStorage = ref(props.project?.storage?.decentralized)
|
const decentralizedStorage = ref(props.project?.storage?.decentralized)
|
||||||
|
|
||||||
const { useProject, projectPhaseData, assetCustodyData } = useData()
|
const { projectPhaseData, assetCustodyData } = useData()
|
||||||
const { saveProject } = useProject()
|
const { saveProject } = useProject()
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
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', () => {
|
||||||
|
@ -146,73 +145,6 @@ 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>()
|
|
||||||
const isPublishing = ref(false)
|
|
||||||
|
|
||||||
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() {
|
|
||||||
isPublishing.value = true
|
|
||||||
try {
|
|
||||||
const imageArrayBuffer = await projectImage.value?.arrayBuffer()
|
|
||||||
let imageBuffer: Buffer | undefined
|
|
||||||
let base64Image: string | undefined
|
|
||||||
|
|
||||||
if (imageArrayBuffer) {
|
|
||||||
imageBuffer = Buffer.from(imageArrayBuffer)
|
|
||||||
const base64String = imageBuffer.toString('base64')
|
|
||||||
base64Image = base64String
|
|
||||||
}
|
|
||||||
|
|
||||||
await $fetch(`/api/data`, {
|
|
||||||
method: 'POST',
|
|
||||||
body: {
|
|
||||||
project: project.value,
|
|
||||||
image: {
|
|
||||||
type: projectImage.value?.type,
|
|
||||||
data: base64Image,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
console.error(e)
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
isPublishing.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
project,
|
|
||||||
isPublishing,
|
|
||||||
setProject,
|
|
||||||
clearProject,
|
|
||||||
saveProject,
|
|
||||||
saveProjectImage,
|
|
||||||
publishProject,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectedCategoryId,
|
selectedCategoryId,
|
||||||
filter,
|
filter,
|
||||||
|
@ -234,6 +166,5 @@ export const useData = defineStore('data', () => {
|
||||||
getProjectsByCategory,
|
getProjectsByCategory,
|
||||||
filteredProjects,
|
filteredProjects,
|
||||||
projectToShallow,
|
projectToShallow,
|
||||||
useProject,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
71
composables/useProject.ts
Normal file
71
composables/useProject.ts
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import { Buffer } from 'buffer'
|
||||||
|
import type { Project } from '~/types'
|
||||||
|
|
||||||
|
export const useProject = defineStore('project', () => {
|
||||||
|
const project = ref<Partial<Project>>()
|
||||||
|
const projectImage = ref<File>()
|
||||||
|
const isPublishing = ref(false)
|
||||||
|
|
||||||
|
const { getProjectById } = useData()
|
||||||
|
|
||||||
|
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() {
|
||||||
|
isPublishing.value = true
|
||||||
|
try {
|
||||||
|
const imageArrayBuffer = await projectImage.value?.arrayBuffer()
|
||||||
|
let imageBuffer: Buffer | undefined
|
||||||
|
let base64Image: string | undefined
|
||||||
|
|
||||||
|
if (imageArrayBuffer) {
|
||||||
|
imageBuffer = Buffer.from(imageArrayBuffer)
|
||||||
|
const base64String = imageBuffer.toString('base64')
|
||||||
|
base64Image = base64String
|
||||||
|
}
|
||||||
|
|
||||||
|
await $fetch(`/api/data`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: {
|
||||||
|
project: project.value,
|
||||||
|
image: {
|
||||||
|
type: projectImage.value?.type,
|
||||||
|
data: base64Image,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
isPublishing.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
project,
|
||||||
|
isPublishing,
|
||||||
|
setProject,
|
||||||
|
clearProject,
|
||||||
|
saveProject,
|
||||||
|
saveProjectImage,
|
||||||
|
publishProject,
|
||||||
|
}
|
||||||
|
})
|
|
@ -1,4 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import * as yup from 'yup'
|
||||||
import ProjectCreateCategoriesBasicInfo from '~/components/Project/Create/Categories/BasicInfo.vue'
|
import ProjectCreateCategoriesBasicInfo from '~/components/Project/Create/Categories/BasicInfo.vue'
|
||||||
import ProjectCreateCategoriesAssets from '~/components/Project/Create/Categories/Assets.vue'
|
import ProjectCreateCategoriesAssets from '~/components/Project/Create/Categories/Assets.vue'
|
||||||
import ProjectCreateCategoriesLinks from '~/components/Project/Create/Categories/Links.vue'
|
import ProjectCreateCategoriesLinks from '~/components/Project/Create/Categories/Links.vue'
|
||||||
|
@ -13,8 +14,9 @@ definePageMeta({
|
||||||
layout: 'create',
|
layout: 'create',
|
||||||
})
|
})
|
||||||
|
|
||||||
const { useProject, projects } = useData()
|
const { projects } = useData()
|
||||||
const { saveProject, setProject, project, publishProject, saveProjectImage, isPublishing } = useProject()
|
const { saveProject, setProject, publishProject, saveProjectImage } = useProject()
|
||||||
|
const { project, isPublishing } = storeToRefs(useProject())
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
await until(projects).toMatch(p => p?.length > 0)
|
await until(projects).toMatch(p => p?.length > 0)
|
||||||
|
@ -70,7 +72,9 @@ onChange((files) => {
|
||||||
const projectNameInput = ref<HTMLInputElement | null>(null)
|
const projectNameInput = ref<HTMLInputElement | null>(null)
|
||||||
function useProjectName() {
|
function useProjectName() {
|
||||||
const isEditing = ref(false)
|
const isEditing = ref(false)
|
||||||
const name = ref('Untitled')
|
// const name = ref('Untitled')
|
||||||
|
const { value: name, errorMessage: nameError } = useField<string>('name', yup.string().required().notOneOf(['Untitled', 'Undefined']))
|
||||||
|
name.value = project.value?.name || 'Untitled'
|
||||||
|
|
||||||
function toggleEdit() {
|
function toggleEdit() {
|
||||||
isEditing.value = !isEditing.value
|
isEditing.value = !isEditing.value
|
||||||
|
@ -84,11 +88,12 @@ function useProjectName() {
|
||||||
return {
|
return {
|
||||||
isEditing,
|
isEditing,
|
||||||
name,
|
name,
|
||||||
|
nameError,
|
||||||
toggleEdit,
|
toggleEdit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { isEditing, name, toggleEdit } = useProjectName()
|
const { isEditing, name, nameError, toggleEdit } = useProjectName()
|
||||||
name.value = project.value?.name || 'Untitled'
|
name.value = project.value?.name || 'Untitled'
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
|
@ -97,7 +102,10 @@ function save() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function next() {
|
async function next() {
|
||||||
|
if (nameError.value)
|
||||||
|
return
|
||||||
|
|
||||||
if (selectedTab.value === 'basic_info') {
|
if (selectedTab.value === 'basic_info') {
|
||||||
if (!currentComponent.value.isFormValid())
|
if (!currentComponent.value.isFormValid())
|
||||||
return
|
return
|
||||||
|
@ -110,6 +118,31 @@ function next() {
|
||||||
const nextTab = tabs[currentIndex + 1] || tabs[0]
|
const nextTab = tabs[currentIndex + 1] || tabs[0]
|
||||||
selectedTab.value = nextTab.value
|
selectedTab.value = nextTab.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function publish() {
|
||||||
|
if (selectedTab.value === 'basic_info') {
|
||||||
|
if (!currentComponent.value.isFormValid())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else if (isPublishing) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
await publishProject()
|
||||||
|
navigateTo(`/project/${project.value?.id || project.value?.name?.toLowerCase().replace(/\s+/g, '-')}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function jumpTo(tab: string) {
|
||||||
|
if (selectedTab.value === 'basic_info') {
|
||||||
|
if (!currentComponent.value.isFormValid())
|
||||||
|
return
|
||||||
|
else save()
|
||||||
|
}
|
||||||
|
|
||||||
|
currentComponent.value.save()
|
||||||
|
|
||||||
|
selectedTab.value = tab
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -178,6 +211,7 @@ function next() {
|
||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
gap-12px
|
gap-12px
|
||||||
|
relative
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
v-if="isEditing"
|
v-if="isEditing"
|
||||||
|
@ -216,6 +250,16 @@ function next() {
|
||||||
i-heroicons-solid-pencil
|
i-heroicons-solid-pencil
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
<span
|
||||||
|
v-if="nameError"
|
||||||
|
text-nowrap
|
||||||
|
text-app-danger
|
||||||
|
text-12px
|
||||||
|
absolute
|
||||||
|
lg:bottom--24px
|
||||||
|
bottom--16px
|
||||||
|
select-none
|
||||||
|
>Invalid project name</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -226,7 +270,7 @@ function next() {
|
||||||
lg="mt-24px"
|
lg="mt-24px"
|
||||||
>
|
>
|
||||||
<SelectBox
|
<SelectBox
|
||||||
v-model="selectedTab"
|
:model-value="selectedTab"
|
||||||
label="Choose category"
|
label="Choose category"
|
||||||
:options="tabs.map(t => ({ label: t.label, value: t.value }))"
|
:options="tabs.map(t => ({ label: t.label, value: t.value }))"
|
||||||
:border-opacity="30"
|
:border-opacity="30"
|
||||||
|
@ -234,6 +278,7 @@ function next() {
|
||||||
lg:hidden
|
lg:hidden
|
||||||
block
|
block
|
||||||
mt-16px
|
mt-16px
|
||||||
|
@update:model-value="$event => jumpTo($event)"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
v-for="tab in tabs"
|
v-for="tab in tabs"
|
||||||
|
@ -243,7 +288,7 @@ function next() {
|
||||||
pb-8px
|
pb-8px
|
||||||
leading-40px
|
leading-40px
|
||||||
:class="selectedTab === tab.value ? 'font-bold border-b-4 border-app-white' : ''"
|
:class="selectedTab === tab.value ? 'font-bold border-b-4 border-app-white' : ''"
|
||||||
@click="selectedTab = tab.value"
|
@click="jumpTo(tab.value)"
|
||||||
>
|
>
|
||||||
{{ tab.label }}
|
{{ tab.label }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -258,7 +303,8 @@ function next() {
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
app-container
|
app-container
|
||||||
mb-55px
|
mb-170px
|
||||||
|
lg="mb-55px"
|
||||||
>
|
>
|
||||||
<component
|
<component
|
||||||
:is="getCurrentComponent()"
|
:is="getCurrentComponent()"
|
||||||
|
@ -288,7 +334,7 @@ function next() {
|
||||||
gap-16px
|
gap-16px
|
||||||
justify-center
|
justify-center
|
||||||
text-center
|
text-center
|
||||||
absolute
|
fixed
|
||||||
bottom-0
|
bottom-0
|
||||||
w-full
|
w-full
|
||||||
bg-app-bg-dark_grey
|
bg-app-bg-dark_grey
|
||||||
|
@ -316,6 +362,7 @@ function next() {
|
||||||
w-full
|
w-full
|
||||||
lg="w-fit"
|
lg="w-fit"
|
||||||
border
|
border
|
||||||
|
@click="navigateTo(`/project/${route.params.id}`)"
|
||||||
>
|
>
|
||||||
<span px-24px>CANCEL</span>
|
<span px-24px>CANCEL</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -323,7 +370,7 @@ function next() {
|
||||||
w-full
|
w-full
|
||||||
lg="w-fit"
|
lg="w-fit"
|
||||||
inverted-color
|
inverted-color
|
||||||
@click="isPublishing ? () => null : publishProject()"
|
@click="publish()"
|
||||||
>
|
>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
v-if="isPublishing"
|
v-if="isPublishing"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import * as yup from 'yup'
|
||||||
import ProjectCreateCategoriesBasicInfo from '~/components/Project/Create/Categories/BasicInfo.vue'
|
import ProjectCreateCategoriesBasicInfo from '~/components/Project/Create/Categories/BasicInfo.vue'
|
||||||
import ProjectCreateCategoriesAssets from '~/components/Project/Create/Categories/Assets.vue'
|
import ProjectCreateCategoriesAssets from '~/components/Project/Create/Categories/Assets.vue'
|
||||||
import ProjectCreateCategoriesLinks from '~/components/Project/Create/Categories/Links.vue'
|
import ProjectCreateCategoriesLinks from '~/components/Project/Create/Categories/Links.vue'
|
||||||
|
@ -13,6 +14,9 @@ definePageMeta({
|
||||||
layout: 'create',
|
layout: 'create',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { saveProject, publishProject, saveProjectImage } = useProject()
|
||||||
|
const { project, isPublishing } = storeToRefs(useProject())
|
||||||
|
|
||||||
const tabs = reactive([
|
const tabs = reactive([
|
||||||
{ label: 'Basic Info', value: 'basic_info', component: ProjectCreateCategoriesBasicInfo },
|
{ label: 'Basic Info', value: 'basic_info', component: ProjectCreateCategoriesBasicInfo },
|
||||||
{ label: 'Assets', value: 'assets', component: ProjectCreateCategoriesAssets },
|
{ label: 'Assets', value: 'assets', component: ProjectCreateCategoriesAssets },
|
||||||
|
@ -55,7 +59,9 @@ onChange((files) => {
|
||||||
const projectNameInput = ref<HTMLInputElement | null>(null)
|
const projectNameInput = ref<HTMLInputElement | null>(null)
|
||||||
function useProjectName() {
|
function useProjectName() {
|
||||||
const isEditing = ref(false)
|
const isEditing = ref(false)
|
||||||
const name = ref('Untitled')
|
// const name = ref('Untitled')
|
||||||
|
const { value: name, errorMessage: nameError } = useField<string>('name', yup.string().required().notOneOf(['Untitled', 'Undefined']))
|
||||||
|
name.value = project.value?.name || 'Untitled'
|
||||||
|
|
||||||
function toggleEdit() {
|
function toggleEdit() {
|
||||||
isEditing.value = !isEditing.value
|
isEditing.value = !isEditing.value
|
||||||
|
@ -69,17 +75,16 @@ function useProjectName() {
|
||||||
return {
|
return {
|
||||||
isEditing,
|
isEditing,
|
||||||
name,
|
name,
|
||||||
|
nameError,
|
||||||
toggleEdit,
|
toggleEdit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { isEditing, name, toggleEdit } = useProjectName()
|
const { isEditing, name, nameError, toggleEdit } = useProjectName()
|
||||||
|
|
||||||
const { useProject } = useData()
|
|
||||||
const { saveProject, publishProject, saveProjectImage, isPublishing } = useProject()
|
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
saveProject({
|
saveProject({
|
||||||
|
...project.value,
|
||||||
name: name.value,
|
name: name.value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -97,6 +102,31 @@ function next() {
|
||||||
const nextTab = tabs[currentIndex + 1] || tabs[0]
|
const nextTab = tabs[currentIndex + 1] || tabs[0]
|
||||||
selectedTab.value = nextTab.value
|
selectedTab.value = nextTab.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function publish() {
|
||||||
|
if (selectedTab.value === 'basic_info') {
|
||||||
|
if (!currentComponent.value.isFormValid())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else if (isPublishing) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
await publishProject()
|
||||||
|
navigateTo(`/project/${project.value?.id || project.value?.name?.toLowerCase().replace(/\s+/g, '-')}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function jumpTo(tab: string) {
|
||||||
|
if (selectedTab.value === 'basic_info') {
|
||||||
|
if (!currentComponent.value.isFormValid())
|
||||||
|
return
|
||||||
|
else save()
|
||||||
|
}
|
||||||
|
|
||||||
|
currentComponent.value.save()
|
||||||
|
|
||||||
|
selectedTab.value = tab
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -214,7 +244,7 @@ function next() {
|
||||||
lg="mt-24px"
|
lg="mt-24px"
|
||||||
>
|
>
|
||||||
<SelectBox
|
<SelectBox
|
||||||
v-model="selectedTab"
|
:model-value="selectedTab"
|
||||||
label="Choose category"
|
label="Choose category"
|
||||||
:options="tabs.map(t => ({ label: t.label, value: t.value }))"
|
:options="tabs.map(t => ({ label: t.label, value: t.value }))"
|
||||||
:border-opacity="30"
|
:border-opacity="30"
|
||||||
|
@ -222,6 +252,7 @@ function next() {
|
||||||
lg:hidden
|
lg:hidden
|
||||||
block
|
block
|
||||||
mt-16px
|
mt-16px
|
||||||
|
@update:model-value="$event => jumpTo($event)"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
v-for="tab in tabs"
|
v-for="tab in tabs"
|
||||||
|
@ -235,6 +266,16 @@ function next() {
|
||||||
>
|
>
|
||||||
{{ tab.label }}
|
{{ tab.label }}
|
||||||
</button>
|
</button>
|
||||||
|
<span
|
||||||
|
v-if="nameError"
|
||||||
|
text-nowrap
|
||||||
|
text-app-danger
|
||||||
|
text-12px
|
||||||
|
absolute
|
||||||
|
lg:bottom--24px
|
||||||
|
bottom--16px
|
||||||
|
select-none
|
||||||
|
>Invalid project name</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -246,7 +287,8 @@ function next() {
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
app-container
|
app-container
|
||||||
mb-55px
|
mb-170px
|
||||||
|
lg="mb-55px"
|
||||||
>
|
>
|
||||||
<component
|
<component
|
||||||
:is="getCurrentComponent()"
|
:is="getCurrentComponent()"
|
||||||
|
@ -274,7 +316,7 @@ function next() {
|
||||||
gap-16px
|
gap-16px
|
||||||
justify-center
|
justify-center
|
||||||
text-center
|
text-center
|
||||||
absolute
|
fixed
|
||||||
bottom-0
|
bottom-0
|
||||||
w-full
|
w-full
|
||||||
bg-app-bg-dark_grey
|
bg-app-bg-dark_grey
|
||||||
|
@ -302,6 +344,7 @@ function next() {
|
||||||
w-full
|
w-full
|
||||||
lg="w-fit"
|
lg="w-fit"
|
||||||
border
|
border
|
||||||
|
@click="navigateTo('/')"
|
||||||
>
|
>
|
||||||
<span px-24px>CANCEL</span>
|
<span px-24px>CANCEL</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -309,7 +352,7 @@ function next() {
|
||||||
w-full
|
w-full
|
||||||
lg="w-fit"
|
lg="w-fit"
|
||||||
inverted-color
|
inverted-color
|
||||||
@click="isPublishing ? () => null : publishProject()"
|
@click="publish()"
|
||||||
>
|
>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
v-if="isPublishing"
|
v-if="isPublishing"
|
||||||
|
|
Loading…
Reference in a new issue