From 9a43af8b7a62af6a23930f03adfdb930f94ace76 Mon Sep 17 00:00:00 2001 From: DomWane Date: Tue, 1 Oct 2024 14:54:35 +0200 Subject: [PATCH] refactor: project create/edit --- composables/useProject.ts | 1 + composables/useProjectForm.ts | 108 +++++++++++++++++++++++++ pages/project/[id]/edit.vue | 143 ++++++---------------------------- pages/project/create.vue | 143 ++++++---------------------------- 4 files changed, 156 insertions(+), 239 deletions(-) create mode 100644 composables/useProjectForm.ts diff --git a/composables/useProject.ts b/composables/useProject.ts index c03c5bd..ec06c46 100644 --- a/composables/useProject.ts +++ b/composables/useProject.ts @@ -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 } diff --git a/composables/useProjectForm.ts b/composables/useProjectForm.ts new file mode 100644 index 0000000..265747e --- /dev/null +++ b/composables/useProjectForm.ts @@ -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('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, + } +}) diff --git a/pages/project/[id]/edit.vue b/pages/project/[id]/edit.vue index d6b85ac..1d7d3c2 100644 --- a/pages/project/[id]/edit.vue +++ b/pages/project/[id]/edit.vue @@ -1,21 +1,10 @@ @@ -219,7 +122,7 @@ const transitionDone = ref(false) relative >

@@ -316,7 +219,7 @@ const transitionDone = ref(false) @after-enter="transitionDone = true" > -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,81 +24,18 @@ onChange((files) => { saveProjectImage(file) }) +const { next, jumpTo, publish, toggleEditName } = useProjectForm() +const { currentComponent, selectedTab, tabsArray, isEditingName, name, nameError } = storeToRefs(useProjectForm()) + const projectNameInput = ref(null) -function useProjectName() { - const isEditing = ref(false) - // const name = ref('Untitled') - const { value: name, errorMessage: nameError } = useField('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) - } +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, - }) -} - -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) @@ -204,7 +109,7 @@ const transitionDone = ref(false) relative >

@@ -301,7 +206,7 @@ const transitionDone = ref(false) @after-enter="transitionDone = true" >