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

Bug fixes and polishing
This commit is contained in:
MufCZ 2024-10-01 15:53:20 +02:00 committed by GitHub
commit cd476c6367
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 298 additions and 372 deletions

View file

@ -38,8 +38,8 @@ resetForm({
},
})
function isFormValid() {
validate()
async function isFormValid() {
await validate()
if (meta.value.valid) {
return true

View file

@ -11,7 +11,7 @@ type Fundings = {
}
function useFundings(project?: Partial<Project>) {
const fundings = ref<Fundings[]>(Array.isArray(project?.funding) ? project?.funding as unknown as Fundings[] : [project?.funding as unknown as Fundings])
const fundings = ref(Array.isArray(project?.funding) ? project.funding : (project?.funding ? [project.funding] : []))
const newFunding = reactive<Fundings>({
name: '',
link: '',
@ -58,7 +58,7 @@ defineExpose({
/>
<ProjectCreateComponentsItem
v-for="funding in fundings"
:key="funding.name"
:key="funding?.name"
@remove="() => removeFunding(fundings?.indexOf(funding))"
>
<template #label>
@ -69,13 +69,13 @@ defineExpose({
<span
class="text-app-black text-14px font-700"
lg="text-16px"
> {{ funding.name }}
> {{ funding?.name }}
</span>
</div>
</template>
<template #desc>
<NuxtLink
:to="funding.link"
:to="funding?.link"
hover:text-app-black
class="text-app-black/50 text-16px hidden"
lg="block"

View file

@ -76,30 +76,25 @@ const days = computed(() => {
lg="w-1/2"
relative
>
<SelectBox
<ProjectCreateComponentsSelect
v-model="day"
w-full
class="lg:w-full!"
:options="days.map(day => ({ label: day.toString(), value: day }))"
placeholder="Day"
:border-opacity="30"
:is-margin-top="false"
/>
<SelectBox
<ProjectCreateComponentsSelect
v-model="month"
w-full
mx--2px
class="lg:w-full!"
ml--2px
:options="months.map(month => ({ label: month.label, value: month.value }))"
placeholder="Month"
:border-opacity="30"
:is-margin-top="false"
/>
<SelectBox
<ProjectCreateComponentsSelect
v-model="year"
w-full
class="lg:w-full!"
ml--2px
:options="years.map(year => ({ label: year.toString(), value: year }))"
placeholder="Year"
:border-opacity="30"
:is-margin-top="false"
/>
</div>
<span

View file

@ -45,13 +45,13 @@ const model = defineModel<string>()
lg="flex flex-row gap-24px items-center"
relative
>
<div v-bind="$attrs">
<div v-bind="$attrs" shrink-0>
<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="relative w-full p-8px text-left border-2px text-app-white bg-black sm:text-sm sm:leading-6 focus:outline-none focus:ring-0 focus:border-white"
:class="error ? 'border-app-danger/50' : 'border-white/30'"
/>
<input
@ -59,7 +59,7 @@ const model = defineModel<string>()
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="relative w-full p-8px text-left border-2px text-app-white bg-black sm:text-sm sm:leading-6 focus:outline-none focus:ring-0 focus:border-white"
:class="error ? 'border-app-danger/50' : 'border-white/30'"
>
</div>

View file

@ -7,7 +7,7 @@ const emits = defineEmits(['update:modelValue'])
interface SelectProps {
options: InputOption[]
label?: string
modelValue: string
modelValue: any
placeholder?: string
required?: boolean
hint?: string
@ -24,7 +24,10 @@ const selectedValue = useVModel(props, 'modelValue', emits)
lg="flex flex-row gap-24px"
relative
>
<div lg="w-1/2">
<div
v-bind="$attrs"
lg="w-1/2"
>
<HeadlessListbox
v-model="selectedValue"
as="div"
@ -48,11 +51,11 @@ const selectedValue = useVModel(props, 'modelValue', emits)
>
<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"
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 aria-expanded:border-white aria-expanded:z-10"
>
<span
class="block truncate mr-8px"
:class="[selectedValue ? 'text-app-white' : 'font-400 text-white/50']"
:style="[selectedValue ? 'text-app-white' : 'font-400 text-white/50']"
>
{{ props.options.find(option => option.value === selectedValue)?.label || props.placeholder }}
</span>
@ -71,7 +74,7 @@ const selectedValue = useVModel(props, 'modelValue', emits)
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"
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"
>
<HeadlessListboxOption
v-for="option in props.options"

View file

@ -97,10 +97,9 @@ function addOption() {
</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'"
:class="error ? 'border-app-danger/50' : 'border-white/30 aria-expanded:border-white'"
>
<div class="flex flex-wrap gap-8px">
<span
@ -123,8 +122,7 @@ function addOption() {
</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"
class="text-14px lg:focus:text-14px focus:text-16px font-400 leading-20px ml-8px w-fit bg-transparent border-none focus:ring-0 focus:outline-none"
:placeholder="placeholder"
@keyup.enter="addOption"
@change="query = $event.target.value"

View file

@ -9,6 +9,7 @@ export const useProject = defineStore('project', () => {
const { getProjectById } = useData()
function setProject(id: string) {
clearProject()
project.value = getProjectById(id, { shallow: false }) as Project
delete project.value.ratings
}

View 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,
}
})

View file

@ -1,21 +1,10 @@
<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({
layout: 'create',
})
const { projects } = useData()
const { saveProject, setProject, publishProject, saveProjectImage } = useProject()
const { setProject, saveProjectImage } = useProject()
const { project, isPublishing } = storeToRefs(useProject())
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({
accept: 'image/*', // Set to accept only image files
})
@ -69,84 +37,19 @@ onChange((files) => {
saveProjectImage(file)
})
const projectNameInput = ref<HTMLInputElement | null>(null)
function useProjectName() {
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'
const { next, jumpTo, publish, toggleEditName } = useProjectForm()
const { currentComponent, selectedTab, tabsArray, isEditingName, name, nameError } = storeToRefs(useProjectForm())
name.value = project.value?.name || 'Untitled'
function toggleEdit() {
isEditing.value = !isEditing.value
if (isEditing.value) {
const projectNameInput = ref<HTMLInputElement | null>(null)
watch(isEditingName, () => {
if (isEditingName.value) {
setTimeout(() => {
projectNameInput.value?.focus()
}, 0)
}
}
})
return {
isEditing,
name,
nameError,
toggleEdit,
}
}
const { isEditing, name, nameError, toggleEdit } = useProjectName()
name.value = project.value?.name || 'Untitled'
function save() {
saveProject({
...project.value,
name: name.value,
})
}
async function next() {
if (nameError.value)
return
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
}
async function publish() {
if (selectedTab.value === 'basic_info') {
if (!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, '-')}`)
}
function jumpTo(tab: string) {
if (selectedTab.value === 'basic_info') {
if (!currentComponent.value.isFormValid())
return
else save()
}
currentComponent.value.save()
selectedTab.value = tab
}
const transitionDone = ref(false)
</script>
@ -219,7 +122,7 @@ const transitionDone = ref(false)
relative
>
<input
v-if="isEditing"
v-if="isEditingName"
ref="projectNameInput"
v-model="name"
w-fit
@ -230,7 +133,7 @@ const transitionDone = ref(false)
leading-28px
bg-app-bg-dark_grey
onfocus="this.style.width = 0; this.style.width = this.scrollWidth + 2 + 'px';"
@blur="toggleEdit()"
@blur="toggleEditName()"
>
<h2
v-else
@ -241,8 +144,8 @@ const transitionDone = ref(false)
{{ name }}
</h2>
<button
v-if="!isEditing"
@click="toggleEdit()"
v-if="!isEditingName"
@click="toggleEditName()"
>
<UnoIcon
text-20px
@ -270,26 +173,25 @@ const transitionDone = ref(false)
gap-46px
lg="mt-24px"
>
<SelectBox
<ProjectCreateComponentsSelect
:model-value="selectedTab"
label="Choose category"
:options="tabs.map(t => ({ label: t.label, value: t.value }))"
:border-opacity="100"
:options="tabsArray.map((t, index) => ({ label: t.label, value: index }))"
w-full
lg:hidden
class="lg:hidden! block!"
block
mt-16px
@update:model-value="$event => jumpTo($event)"
/>
<button
v-for="tab in tabs"
v-for="(tab, index) in tabsArray"
:key="tab.value"
lg:block
hidden
pb-8px
leading-40px
:class="selectedTab === tab.value ? 'font-bold border-b-4 border-app-white' : ''"
@click="jumpTo(tab.value)"
:class="selectedTab === index ? 'font-bold border-b-4 border-app-white' : ''"
@click="jumpTo(index)"
>
{{ tab.label }}
</button>
@ -316,7 +218,7 @@ const transitionDone = ref(false)
@after-enter="transitionDone = true"
>
<component
:is="getCurrentComponent()"
:is="tabsArray[selectedTab].component"
ref="currentComponent"
:project="project"
w-full
@ -326,7 +228,7 @@ const transitionDone = ref(false)
/>
</Transition>
<component
:is="getCurrentComponent()"
:is="tabsArray[selectedTab].component"
v-else
ref="currentComponent"
:project="project"
@ -336,7 +238,7 @@ const transitionDone = ref(false)
gap-8px
/>
<Button
v-if="selectedTab !== tabs[tabs.length - 1].value"
v-if="selectedTab !== tabsArray.length - 1"
class="hidden!"
mt-48px
lg="w-fit flex!"
@ -348,13 +250,20 @@ const transitionDone = ref(false)
</ClientOnly>
</div>
</div>
<Transition
name="fade"
mode="out-in"
appear
>
<div
v-if="transitionDone"
flex
flex-col
gap-10px
justify-center
text-center
md:fixed
block
lg:fixed
bottom-0
w-full
bg-app-bg-dark_grey
@ -363,7 +272,7 @@ const transitionDone = ref(false)
p-12px
>
<Button
v-if="selectedTab !== tabs[tabs.length - 1].value"
v-if="selectedTab !== tabsArray.length - 1"
flex
lg="w-fit hidden!"
border
@ -372,7 +281,7 @@ const transitionDone = ref(false)
<span px-24px>NEXT SECTION</span>
</Button>
<span
v-if="selectedTab !== tabs[tabs.length - 1].value"
v-if="selectedTab !== tabsArray.length - 1"
lg="hidden"
block
text="12px italic app-white/50"
@ -406,6 +315,7 @@ const transitionDone = ref(false)
</Button>
</div>
</div>
</Transition>
</div>
</template>

View file

@ -1,43 +1,11 @@
<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({
layout: 'create',
})
const { saveProject, publishProject, saveProjectImage } = useProject()
const { saveProjectImage } = 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({
accept: 'image/*', // Set to accept only image files
})
@ -56,80 +24,18 @@ onChange((files) => {
saveProjectImage(file)
})
const projectNameInput = ref<HTMLInputElement | null>(null)
function useProjectName() {
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'
const { next, jumpTo, publish, toggleEditName } = useProjectForm()
const { currentComponent, selectedTab, tabsArray, isEditingName, name, nameError } = storeToRefs(useProjectForm())
function toggleEdit() {
isEditing.value = !isEditing.value
if (isEditing.value) {
const projectNameInput = ref<HTMLInputElement | null>(null)
watch(isEditingName, () => {
if (isEditingName.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,
})
}
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
}
async function publish() {
if (selectedTab.value === 'basic_info') {
if (!currentComponent.value.isFormValid())
return
else save()
}
else if (isPublishing) {
return
}
currentComponent.value?.save()
await publishProject()
navigateTo('/')
}
function jumpTo(tab: string) {
if (selectedTab.value === 'basic_info') {
if (!currentComponent.value.isFormValid())
return
else save()
}
currentComponent.value.save()
selectedTab.value = tab
}
const transitionDone = ref(false)
</script>
@ -203,7 +109,7 @@ const transitionDone = ref(false)
relative
>
<input
v-if="isEditing"
v-if="isEditingName"
ref="projectNameInput"
v-model="name"
w-fit
@ -214,7 +120,7 @@ const transitionDone = ref(false)
leading-28px
bg-app-bg-dark_grey
onfocus="this.style.width = 0; this.style.width = this.scrollWidth + 2 + 'px';"
@blur="toggleEdit()"
@blur="toggleEditName()"
>
<h2
v-else
@ -225,8 +131,8 @@ const transitionDone = ref(false)
{{ name }}
</h2>
<button
v-if="!isEditing"
@click="toggleEdit()"
v-if="!isEditingName"
@click="toggleEditName()"
>
<UnoIcon
text-20px
@ -254,26 +160,24 @@ const transitionDone = ref(false)
gap-46px
lg="mt-24px"
>
<SelectBox
<ProjectCreateComponentsSelect
:model-value="selectedTab"
label="Choose category"
:options="tabs.map(t => ({ label: t.label, value: t.value }))"
:border-opacity="30"
:options="tabsArray.map((t, index) => ({ label: t.label, value: index }))"
w-full
lg:hidden
block
class="lg:hidden! block!"
mt-16px
@update:model-value="$event => jumpTo($event)"
/>
<button
v-for="tab in tabs"
v-for="(tab, index) in tabsArray"
: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"
:class="selectedTab === index ? 'font-bold border-b-4 border-app-white' : ''"
@click="jumpTo(index)"
>
{{ tab.label }}
</button>
@ -288,7 +192,6 @@ const transitionDone = ref(false)
>
<div
app-container
mb-170px
lg="mb-55px"
>
<ClientOnly>
@ -300,7 +203,7 @@ const transitionDone = ref(false)
@after-enter="transitionDone = true"
>
<component
:is="getCurrentComponent()"
:is="tabsArray[selectedTab].component"
ref="currentComponent"
:project="project"
w-full
@ -310,7 +213,7 @@ const transitionDone = ref(false)
/>
</Transition>
<component
:is="getCurrentComponent()"
:is="tabsArray[selectedTab].component"
v-else
ref="currentComponent"
:project="project"
@ -320,7 +223,7 @@ const transitionDone = ref(false)
gap-24px
/>
<Button
v-if="selectedTab !== tabs[tabs.length - 1].value"
v-if="selectedTab !== tabsArray.length - 1"
class="hidden!"
mt-48px
lg="w-fit flex!"
@ -332,13 +235,20 @@ const transitionDone = ref(false)
</ClientOnly>
</div>
</div>
<Transition
name="fade"
mode="out-in"
appear
>
<div
v-if="transitionDone"
flex
flex-col
gap-16px
justify-center
text-center
fixed
block
lg:fixed
bottom-0
w-full
bg-app-bg-dark_grey
@ -347,7 +257,7 @@ const transitionDone = ref(false)
p-12px
>
<Button
v-if="selectedTab !== tabs[tabs.length - 1].value"
v-if="selectedTab !== tabsArray.length - 1"
flex
lg="w-fit hidden!"
border
@ -356,7 +266,7 @@ const transitionDone = ref(false)
<span px-24px>NEXT SECTION</span>
</Button>
<span
v-if="selectedTab !== tabs[tabs.length - 1].value"
v-if="selectedTab !== tabsArray.length - 1"
lg="hidden"
block
text="12px italic app-white/50"
@ -374,7 +284,7 @@ const transitionDone = ref(false)
w-full
lg="w-fit"
inverted-color
@click="publish()"
@click="publish(true)"
>
<UnoIcon
v-if="isPublishing"
@ -390,6 +300,7 @@ const transitionDone = ref(false)
</Button>
</div>
</div>
</Transition>
</div>
</template>