mirror of
https://github.com/web3privacy/explorer-app.git
synced 2024-10-15 16:46:26 +02:00
refactor: project create/edit
This commit is contained in:
parent
ed9e80af29
commit
9a43af8b7a
4 changed files with 156 additions and 239 deletions
|
@ -9,6 +9,7 @@ export const useProject = defineStore('project', () => {
|
||||||
const { getProjectById } = useData()
|
const { getProjectById } = useData()
|
||||||
|
|
||||||
function setProject(id: string) {
|
function setProject(id: string) {
|
||||||
|
clearProject()
|
||||||
project.value = getProjectById(id, { shallow: false }) as Project
|
project.value = getProjectById(id, { shallow: false }) as Project
|
||||||
delete project.value.ratings
|
delete project.value.ratings
|
||||||
}
|
}
|
||||||
|
|
108
composables/useProjectForm.ts
Normal file
108
composables/useProjectForm.ts
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
import * as yup from 'yup'
|
||||||
|
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'
|
||||||
|
|
||||||
|
export const useProjectForm = defineStore('useProjectForm', () => {
|
||||||
|
const { saveProject, publishProject } = useProject()
|
||||||
|
const { project, isPublishing } = storeToRefs(useProject())
|
||||||
|
|
||||||
|
const isEditingName = ref(false)
|
||||||
|
const { value: name, errorMessage: nameError } = useField<string>('name', yup.string().required().notOneOf(['Untitled', 'Undefined', 'Create', 'create']))
|
||||||
|
name.value = project.value?.name || 'Untitled'
|
||||||
|
|
||||||
|
function toggleEditName() {
|
||||||
|
isEditingName.value = !isEditingName.value
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveName() {
|
||||||
|
saveProject({
|
||||||
|
...project.value,
|
||||||
|
name: name.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabs = reactive({
|
||||||
|
BASIC_INFO: { label: 'Basic Info', value: 'basic_info', component: markRaw(ProjectCreateCategoriesBasicInfo) },
|
||||||
|
ASSETS: { label: 'Assets', value: 'assets', component: markRaw(ProjectCreateCategoriesAssets) },
|
||||||
|
LINKS: { label: 'Links', value: 'links', component: markRaw(ProjectCreateCategoriesLinks) },
|
||||||
|
TECHNOLOGY: { label: 'Technology', value: 'technology', component: markRaw(ProjectCreateCategoriesTechnology) },
|
||||||
|
PRIVACY: { label: 'Privacy', value: 'privacy', component: markRaw(ProjectCreateCategoriesPrivacy) },
|
||||||
|
SECURITY: { label: 'Security', value: 'security', component: markRaw(ProjectCreateCategoriesSecurity) },
|
||||||
|
TEAM: { label: 'Team', value: 'team', component: markRaw(ProjectCreateCategoriesTeam) },
|
||||||
|
FUNDING: { label: 'Funding', value: 'funding', component: markRaw(ProjectCreateCategoriesFunding) },
|
||||||
|
HISTORY: { label: 'History', value: 'history', component: markRaw(ProjectCreateCategoriesHistory) },
|
||||||
|
})
|
||||||
|
|
||||||
|
const selectedTab = ref(0)
|
||||||
|
const tabsArray = computed(() => Object.values(tabs))
|
||||||
|
const currentComponent = ref()
|
||||||
|
|
||||||
|
async function next() {
|
||||||
|
if (selectedTab.value === 0) {
|
||||||
|
if (!(await currentComponent.value.isFormValid()) || nameError.value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
saveName()
|
||||||
|
currentComponent.value.save()
|
||||||
|
|
||||||
|
if (selectedTab.value === tabsArray.value.length - 1)
|
||||||
|
return
|
||||||
|
selectedTab.value = selectedTab.value + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
async function jumpTo(index: number) {
|
||||||
|
if (selectedTab.value === 0) {
|
||||||
|
if (!(await currentComponent.value.isFormValid()) || nameError.value)
|
||||||
|
return
|
||||||
|
if (nameError.value)
|
||||||
|
return
|
||||||
|
else saveName()
|
||||||
|
}
|
||||||
|
|
||||||
|
saveName()
|
||||||
|
currentComponent.value.save()
|
||||||
|
|
||||||
|
selectedTab.value = index
|
||||||
|
}
|
||||||
|
|
||||||
|
async function publish(isNew?: boolean) {
|
||||||
|
if (selectedTab.value === 0) {
|
||||||
|
if (!(await currentComponent.value.isFormValid()) || nameError.value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else if (isPublishing) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
saveName()
|
||||||
|
currentComponent.value?.save()
|
||||||
|
|
||||||
|
await publishProject()
|
||||||
|
if (isNew)
|
||||||
|
navigateTo('/')
|
||||||
|
else
|
||||||
|
navigateTo(`/project/${project.value?.id || project.value?.name?.toLowerCase().replace(/\s+/g, '-')}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
isEditingName,
|
||||||
|
name,
|
||||||
|
nameError,
|
||||||
|
toggleEditName,
|
||||||
|
saveName,
|
||||||
|
selectedTab,
|
||||||
|
tabsArray,
|
||||||
|
currentComponent,
|
||||||
|
next,
|
||||||
|
publish,
|
||||||
|
jumpTo,
|
||||||
|
}
|
||||||
|
})
|
|
@ -1,21 +1,10 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import * as yup from 'yup'
|
|
||||||
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({
|
definePageMeta({
|
||||||
layout: 'create',
|
layout: 'create',
|
||||||
})
|
})
|
||||||
|
|
||||||
const { projects } = useData()
|
const { projects } = useData()
|
||||||
const { saveProject, setProject, publishProject, saveProjectImage } = useProject()
|
const { setProject, saveProjectImage } = useProject()
|
||||||
const { project, isPublishing } = storeToRefs(useProject())
|
const { project, isPublishing } = storeToRefs(useProject())
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
@ -30,27 +19,6 @@ if (!project.value) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabs = reactive([
|
|
||||||
{ label: 'Basic Info', value: 'basic_info', component: markRaw(ProjectCreateCategoriesBasicInfo) },
|
|
||||||
{ label: 'Assets', value: 'assets', component: markRaw(ProjectCreateCategoriesAssets) },
|
|
||||||
{ label: 'Links', value: 'links', component: markRaw(ProjectCreateCategoriesLinks) },
|
|
||||||
{ label: 'Technology', value: 'technology', component: markRaw(ProjectCreateCategoriesTechnology) },
|
|
||||||
{ label: 'Privacy', value: 'privacy', component: markRaw(ProjectCreateCategoriesPrivacy) },
|
|
||||||
{ label: 'Security', value: 'security', component: markRaw(ProjectCreateCategoriesSecurity) },
|
|
||||||
{ label: 'Team', value: 'team', component: markRaw(ProjectCreateCategoriesTeam) },
|
|
||||||
{ label: 'Funding', value: 'funding', component: markRaw(ProjectCreateCategoriesFunding) },
|
|
||||||
{ label: 'History', value: 'history', component: markRaw(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({
|
const { open, onChange } = useFileDialog({
|
||||||
accept: 'image/*', // Set to accept only image files
|
accept: 'image/*', // Set to accept only image files
|
||||||
})
|
})
|
||||||
|
@ -69,84 +37,19 @@ onChange((files) => {
|
||||||
saveProjectImage(file)
|
saveProjectImage(file)
|
||||||
})
|
})
|
||||||
|
|
||||||
const projectNameInput = ref<HTMLInputElement | null>(null)
|
const { next, jumpTo, publish, toggleEditName } = useProjectForm()
|
||||||
function useProjectName() {
|
const { currentComponent, selectedTab, tabsArray, isEditingName, name, nameError } = storeToRefs(useProjectForm())
|
||||||
const isEditing = ref(false)
|
|
||||||
// const name = ref('Untitled')
|
|
||||||
const { value: name, errorMessage: nameError } = useField<string>('name', yup.string().required().notOneOf(['Untitled', 'Undefined', 'Create', 'create']))
|
|
||||||
name.value = project.value?.name || 'Untitled'
|
|
||||||
|
|
||||||
function toggleEdit() {
|
|
||||||
isEditing.value = !isEditing.value
|
|
||||||
if (isEditing.value) {
|
|
||||||
setTimeout(() => {
|
|
||||||
projectNameInput.value?.focus()
|
|
||||||
}, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
isEditing,
|
|
||||||
name,
|
|
||||||
nameError,
|
|
||||||
toggleEdit,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const { isEditing, name, nameError, toggleEdit } = useProjectName()
|
|
||||||
name.value = project.value?.name || 'Untitled'
|
name.value = project.value?.name || 'Untitled'
|
||||||
|
|
||||||
function save() {
|
const projectNameInput = ref<HTMLInputElement | null>(null)
|
||||||
saveProject({
|
watch(isEditingName, () => {
|
||||||
...project.value,
|
if (isEditingName.value) {
|
||||||
name: name.value,
|
setTimeout(() => {
|
||||||
})
|
projectNameInput.value?.focus()
|
||||||
}
|
}, 0)
|
||||||
|
|
||||||
async function next() {
|
|
||||||
if (nameError.value)
|
|
||||||
return
|
|
||||||
|
|
||||||
if (selectedTab.value === 'basic_info') {
|
|
||||||
if (!(await 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
|
|
||||||
}
|
|
||||||
|
|
||||||
async function publish() {
|
|
||||||
if (selectedTab.value === 'basic_info') {
|
|
||||||
if (!(await currentComponent.value.isFormValid()))
|
|
||||||
return
|
|
||||||
else save()
|
|
||||||
}
|
|
||||||
else if (isPublishing) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
currentComponent.value.save()
|
|
||||||
|
|
||||||
await publishProject()
|
|
||||||
navigateTo(`/project/${project.value?.id || project.value?.name?.toLowerCase().replace(/\s+/g, '-')}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function jumpTo(tab: string) {
|
|
||||||
if (selectedTab.value === 'basic_info') {
|
|
||||||
if (!(await currentComponent.value.isFormValid()))
|
|
||||||
return
|
|
||||||
else save()
|
|
||||||
}
|
|
||||||
|
|
||||||
currentComponent.value.save()
|
|
||||||
|
|
||||||
selectedTab.value = tab
|
|
||||||
}
|
|
||||||
const transitionDone = ref(false)
|
const transitionDone = ref(false)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -219,7 +122,7 @@ const transitionDone = ref(false)
|
||||||
relative
|
relative
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
v-if="isEditing"
|
v-if="isEditingName"
|
||||||
ref="projectNameInput"
|
ref="projectNameInput"
|
||||||
v-model="name"
|
v-model="name"
|
||||||
w-fit
|
w-fit
|
||||||
|
@ -230,7 +133,7 @@ const transitionDone = ref(false)
|
||||||
leading-28px
|
leading-28px
|
||||||
bg-app-bg-dark_grey
|
bg-app-bg-dark_grey
|
||||||
onfocus="this.style.width = 0; this.style.width = this.scrollWidth + 2 + 'px';"
|
onfocus="this.style.width = 0; this.style.width = this.scrollWidth + 2 + 'px';"
|
||||||
@blur="toggleEdit()"
|
@blur="toggleEditName()"
|
||||||
>
|
>
|
||||||
<h2
|
<h2
|
||||||
v-else
|
v-else
|
||||||
|
@ -241,8 +144,8 @@ const transitionDone = ref(false)
|
||||||
{{ name }}
|
{{ name }}
|
||||||
</h2>
|
</h2>
|
||||||
<button
|
<button
|
||||||
v-if="!isEditing"
|
v-if="!isEditingName"
|
||||||
@click="toggleEdit()"
|
@click="toggleEditName()"
|
||||||
>
|
>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
text-20px
|
text-20px
|
||||||
|
@ -273,7 +176,7 @@ const transitionDone = ref(false)
|
||||||
<SelectBox
|
<SelectBox
|
||||||
:model-value="selectedTab"
|
:model-value="selectedTab"
|
||||||
label="Choose category"
|
label="Choose category"
|
||||||
:options="tabs.map(t => ({ label: t.label, value: t.value }))"
|
:options="tabsArray.map(t => ({ label: t.label, value: t.value }))"
|
||||||
:border-opacity="100"
|
:border-opacity="100"
|
||||||
w-full
|
w-full
|
||||||
lg:hidden
|
lg:hidden
|
||||||
|
@ -282,14 +185,14 @@ const transitionDone = ref(false)
|
||||||
@update:model-value="$event => jumpTo($event)"
|
@update:model-value="$event => jumpTo($event)"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
v-for="tab in tabs"
|
v-for="(tab, index) in tabsArray"
|
||||||
:key="tab.value"
|
:key="tab.value"
|
||||||
lg:block
|
lg:block
|
||||||
hidden
|
hidden
|
||||||
pb-8px
|
pb-8px
|
||||||
leading-40px
|
leading-40px
|
||||||
:class="selectedTab === tab.value ? 'font-bold border-b-4 border-app-white' : ''"
|
:class="selectedTab === index ? 'font-bold border-b-4 border-app-white' : ''"
|
||||||
@click="jumpTo(tab.value)"
|
@click="jumpTo(index)"
|
||||||
>
|
>
|
||||||
{{ tab.label }}
|
{{ tab.label }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -316,7 +219,7 @@ const transitionDone = ref(false)
|
||||||
@after-enter="transitionDone = true"
|
@after-enter="transitionDone = true"
|
||||||
>
|
>
|
||||||
<component
|
<component
|
||||||
:is="getCurrentComponent()"
|
:is="tabsArray[selectedTab].component"
|
||||||
ref="currentComponent"
|
ref="currentComponent"
|
||||||
:project="project"
|
:project="project"
|
||||||
w-full
|
w-full
|
||||||
|
@ -326,7 +229,7 @@ const transitionDone = ref(false)
|
||||||
/>
|
/>
|
||||||
</Transition>
|
</Transition>
|
||||||
<component
|
<component
|
||||||
:is="getCurrentComponent()"
|
:is="tabsArray[selectedTab].component"
|
||||||
v-else
|
v-else
|
||||||
ref="currentComponent"
|
ref="currentComponent"
|
||||||
:project="project"
|
:project="project"
|
||||||
|
@ -336,7 +239,7 @@ const transitionDone = ref(false)
|
||||||
gap-8px
|
gap-8px
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
v-if="selectedTab !== tabs[tabs.length - 1].value"
|
v-if="selectedTab !== tabsArray.length - 1"
|
||||||
class="hidden!"
|
class="hidden!"
|
||||||
mt-48px
|
mt-48px
|
||||||
lg="w-fit flex!"
|
lg="w-fit flex!"
|
||||||
|
@ -363,7 +266,7 @@ const transitionDone = ref(false)
|
||||||
p-12px
|
p-12px
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
v-if="selectedTab !== tabs[tabs.length - 1].value"
|
v-if="selectedTab !== tabsArray.length - 1"
|
||||||
flex
|
flex
|
||||||
lg="w-fit hidden!"
|
lg="w-fit hidden!"
|
||||||
border
|
border
|
||||||
|
@ -372,7 +275,7 @@ const transitionDone = ref(false)
|
||||||
<span px-24px>NEXT SECTION</span>
|
<span px-24px>NEXT SECTION</span>
|
||||||
</Button>
|
</Button>
|
||||||
<span
|
<span
|
||||||
v-if="selectedTab !== tabs[tabs.length - 1].value"
|
v-if="selectedTab !== tabsArray.length - 1"
|
||||||
lg="hidden"
|
lg="hidden"
|
||||||
block
|
block
|
||||||
text="12px italic app-white/50"
|
text="12px italic app-white/50"
|
||||||
|
|
|
@ -1,43 +1,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import * as yup from 'yup'
|
|
||||||
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({
|
definePageMeta({
|
||||||
layout: 'create',
|
layout: 'create',
|
||||||
})
|
})
|
||||||
|
|
||||||
const { saveProject, publishProject, saveProjectImage } = useProject()
|
const { saveProjectImage } = useProject()
|
||||||
const { project, isPublishing } = storeToRefs(useProject())
|
const { project, isPublishing } = storeToRefs(useProject())
|
||||||
|
|
||||||
const tabs = reactive([
|
|
||||||
{ label: 'Basic Info', value: 'basic_info', component: markRaw(ProjectCreateCategoriesBasicInfo) },
|
|
||||||
{ label: 'Assets', value: 'assets', component: markRaw(ProjectCreateCategoriesAssets) },
|
|
||||||
{ label: 'Links', value: 'links', component: markRaw(ProjectCreateCategoriesLinks) },
|
|
||||||
{ label: 'Technology', value: 'technology', component: markRaw(ProjectCreateCategoriesTechnology) },
|
|
||||||
{ label: 'Privacy', value: 'privacy', component: markRaw(ProjectCreateCategoriesPrivacy) },
|
|
||||||
{ label: 'Security', value: 'security', component: markRaw(ProjectCreateCategoriesSecurity) },
|
|
||||||
{ label: 'Team', value: 'team', component: markRaw(ProjectCreateCategoriesTeam) },
|
|
||||||
{ label: 'Funding', value: 'funding', component: markRaw(ProjectCreateCategoriesFunding) },
|
|
||||||
{ label: 'History', value: 'history', component: markRaw(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({
|
const { open, onChange } = useFileDialog({
|
||||||
accept: 'image/*', // Set to accept only image files
|
accept: 'image/*', // Set to accept only image files
|
||||||
})
|
})
|
||||||
|
@ -56,81 +24,18 @@ onChange((files) => {
|
||||||
saveProjectImage(file)
|
saveProjectImage(file)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { next, jumpTo, publish, toggleEditName } = useProjectForm()
|
||||||
|
const { currentComponent, selectedTab, tabsArray, isEditingName, name, nameError } = storeToRefs(useProjectForm())
|
||||||
|
|
||||||
const projectNameInput = ref<HTMLInputElement | null>(null)
|
const projectNameInput = ref<HTMLInputElement | null>(null)
|
||||||
function useProjectName() {
|
watch(isEditingName, () => {
|
||||||
const isEditing = ref(false)
|
if (isEditingName.value) {
|
||||||
// const name = ref('Untitled')
|
setTimeout(() => {
|
||||||
const { value: name, errorMessage: nameError } = useField<string>('name', yup.string().required().notOneOf(['Untitled', 'Undefined', 'Create', 'create']))
|
projectNameInput.value?.focus()
|
||||||
name.value = project.value?.name || 'Untitled'
|
}, 0)
|
||||||
|
|
||||||
function toggleEdit() {
|
|
||||||
isEditing.value = !isEditing.value
|
|
||||||
if (isEditing.value) {
|
|
||||||
setTimeout(() => {
|
|
||||||
projectNameInput.value?.focus()
|
|
||||||
}, 0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
|
||||||
isEditing,
|
|
||||||
name,
|
|
||||||
nameError,
|
|
||||||
toggleEdit,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const { isEditing, name, nameError, toggleEdit } = useProjectName()
|
|
||||||
|
|
||||||
function save() {
|
|
||||||
saveProject({
|
|
||||||
...project.value,
|
|
||||||
name: name.value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function next() {
|
|
||||||
if (selectedTab.value === 'basic_info') {
|
|
||||||
if (!(await 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
|
|
||||||
}
|
|
||||||
|
|
||||||
async function publish() {
|
|
||||||
if (selectedTab.value === 'basic_info') {
|
|
||||||
if (!(await currentComponent.value.isFormValid()))
|
|
||||||
return
|
|
||||||
else save()
|
|
||||||
}
|
|
||||||
else if (isPublishing) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
currentComponent.value?.save()
|
|
||||||
|
|
||||||
await publishProject()
|
|
||||||
navigateTo('/')
|
|
||||||
}
|
|
||||||
|
|
||||||
async function jumpTo(tab: string) {
|
|
||||||
console.log(tab, selectedTab.value)
|
|
||||||
if (selectedTab.value === 'basic_info') {
|
|
||||||
if (!(await currentComponent.value.isFormValid()))
|
|
||||||
return
|
|
||||||
else save()
|
|
||||||
}
|
|
||||||
|
|
||||||
currentComponent.value.save()
|
|
||||||
|
|
||||||
selectedTab.value = tab
|
|
||||||
}
|
|
||||||
const transitionDone = ref(false)
|
const transitionDone = ref(false)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -204,7 +109,7 @@ const transitionDone = ref(false)
|
||||||
relative
|
relative
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
v-if="isEditing"
|
v-if="isEditingName"
|
||||||
ref="projectNameInput"
|
ref="projectNameInput"
|
||||||
v-model="name"
|
v-model="name"
|
||||||
w-fit
|
w-fit
|
||||||
|
@ -215,7 +120,7 @@ const transitionDone = ref(false)
|
||||||
leading-28px
|
leading-28px
|
||||||
bg-app-bg-dark_grey
|
bg-app-bg-dark_grey
|
||||||
onfocus="this.style.width = 0; this.style.width = this.scrollWidth + 2 + 'px';"
|
onfocus="this.style.width = 0; this.style.width = this.scrollWidth + 2 + 'px';"
|
||||||
@blur="toggleEdit()"
|
@blur="toggleEditName()"
|
||||||
>
|
>
|
||||||
<h2
|
<h2
|
||||||
v-else
|
v-else
|
||||||
|
@ -226,8 +131,8 @@ const transitionDone = ref(false)
|
||||||
{{ name }}
|
{{ name }}
|
||||||
</h2>
|
</h2>
|
||||||
<button
|
<button
|
||||||
v-if="!isEditing"
|
v-if="!isEditingName"
|
||||||
@click="toggleEdit()"
|
@click="toggleEditName()"
|
||||||
>
|
>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
text-20px
|
text-20px
|
||||||
|
@ -258,7 +163,7 @@ const transitionDone = ref(false)
|
||||||
<SelectBox
|
<SelectBox
|
||||||
:model-value="selectedTab"
|
:model-value="selectedTab"
|
||||||
label="Choose category"
|
label="Choose category"
|
||||||
:options="tabs.map(t => ({ label: t.label, value: t.value }))"
|
:options="tabsArray.map(t => ({ label: t.label, value: t.value }))"
|
||||||
:border-opacity="30"
|
:border-opacity="30"
|
||||||
w-full
|
w-full
|
||||||
lg:hidden
|
lg:hidden
|
||||||
|
@ -267,14 +172,14 @@ const transitionDone = ref(false)
|
||||||
@update:model-value="$event => jumpTo($event)"
|
@update:model-value="$event => jumpTo($event)"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
v-for="tab in tabs"
|
v-for="(tab, index) in tabsArray"
|
||||||
:key="tab.value"
|
:key="tab.value"
|
||||||
lg:block
|
lg:block
|
||||||
hidden
|
hidden
|
||||||
pb-8px
|
pb-8px
|
||||||
leading-40px
|
leading-40px
|
||||||
:class="selectedTab === tab.value ? 'font-bold border-b-4 border-app-white' : ''"
|
:class="selectedTab === index ? 'font-bold border-b-4 border-app-white' : ''"
|
||||||
@click="jumpTo(tab.value)"
|
@click="jumpTo(index)"
|
||||||
>
|
>
|
||||||
{{ tab.label }}
|
{{ tab.label }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -301,7 +206,7 @@ const transitionDone = ref(false)
|
||||||
@after-enter="transitionDone = true"
|
@after-enter="transitionDone = true"
|
||||||
>
|
>
|
||||||
<component
|
<component
|
||||||
:is="getCurrentComponent()"
|
:is="tabsArray[selectedTab].component"
|
||||||
ref="currentComponent"
|
ref="currentComponent"
|
||||||
:project="project"
|
:project="project"
|
||||||
w-full
|
w-full
|
||||||
|
@ -311,7 +216,7 @@ const transitionDone = ref(false)
|
||||||
/>
|
/>
|
||||||
</Transition>
|
</Transition>
|
||||||
<component
|
<component
|
||||||
:is="getCurrentComponent()"
|
:is="tabsArray[selectedTab].component"
|
||||||
v-else
|
v-else
|
||||||
ref="currentComponent"
|
ref="currentComponent"
|
||||||
:project="project"
|
:project="project"
|
||||||
|
@ -321,7 +226,7 @@ const transitionDone = ref(false)
|
||||||
gap-24px
|
gap-24px
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
v-if="selectedTab !== tabs[tabs.length - 1].value"
|
v-if="selectedTab !== tabsArray.length - 1"
|
||||||
class="hidden!"
|
class="hidden!"
|
||||||
mt-48px
|
mt-48px
|
||||||
lg="w-fit flex!"
|
lg="w-fit flex!"
|
||||||
|
@ -348,7 +253,7 @@ const transitionDone = ref(false)
|
||||||
p-12px
|
p-12px
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
v-if="selectedTab !== tabs[tabs.length - 1].value"
|
v-if="selectedTab !== tabsArray.length - 1"
|
||||||
flex
|
flex
|
||||||
lg="w-fit hidden!"
|
lg="w-fit hidden!"
|
||||||
border
|
border
|
||||||
|
@ -357,7 +262,7 @@ const transitionDone = ref(false)
|
||||||
<span px-24px>NEXT SECTION</span>
|
<span px-24px>NEXT SECTION</span>
|
||||||
</Button>
|
</Button>
|
||||||
<span
|
<span
|
||||||
v-if="selectedTab !== tabs[tabs.length - 1].value"
|
v-if="selectedTab !== tabsArray.length - 1"
|
||||||
lg="hidden"
|
lg="hidden"
|
||||||
block
|
block
|
||||||
text="12px italic app-white/50"
|
text="12px italic app-white/50"
|
||||||
|
@ -375,7 +280,7 @@ const transitionDone = ref(false)
|
||||||
w-full
|
w-full
|
||||||
lg="w-fit"
|
lg="w-fit"
|
||||||
inverted-color
|
inverted-color
|
||||||
@click="publish()"
|
@click="publish(true)"
|
||||||
>
|
>
|
||||||
<UnoIcon
|
<UnoIcon
|
||||||
v-if="isPublishing"
|
v-if="isPublishing"
|
||||||
|
|
Loading…
Reference in a new issue