import type { DataCollectionItemBase, ProjectsCollectionItem, } from "@nuxt/content"; import gsap from "gsap"; export const useProjectsStore = defineStore("projects", { state: () => ({ projects: [] as (Omit< ProjectsCollectionItem, keyof DataCollectionItemBase > & { id: string })[], currentProject: 0, loading: true, offsetX: 0, intro: { fadeOpacity: 1, }, outro: { fadeOpacity: 0, }, isIntro: true, isOutro: false, showConfirmationPopup: false, }), actions: { async loadProjects() { this.loading = true; const projects = await queryCollection("projects") .order("order", "ASC") .select( "id", "order", "scope", "title", "link", "description", "summary", "technologies", "tasks", ) .all(); if (!projects) throw "Cannot load projects"; this.projects = projects.map((project) => ({ ...project, id: project.id .split("/")[2]! .replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()), })); this.loading = false; }, visitProject() { const link = this.projects[this.currentProject]?.link; if (link) { navigateTo(link, { open: { target: "_blank" } }); const achievements = useAchievementsStore(); achievements.unlock("projects_open_link"); } }, scrollProjects(direction: "left" | "right") { let offset = 0; if ( direction === "right" && this.currentProject < this.projects.length - 1 ) { this.currentProject += 1; offset = 104; } else if (direction === "left" && this.currentProject > 0) { this.currentProject -= 1; offset = -104; } if (offset !== 0) { gsap.fromTo( this, { offsetX: offset }, { offsetX: 0, duration: 0.1, ease: "none", }, ); } if (this.currentProject >= 4) { setTimeout(() => { const achievements = useAchievementsStore(); achievements.unlock("projects_view_5"); }, 500); } }, // TODO: not used anymore scrollToProject(index: number) { if (index === this.currentProject) return; const offset = (index - this.currentProject) * 69; this.currentProject = index; gsap.fromTo( this, { offsetX: offset }, { offsetX: 0, duration: 0.1, ease: "none", }, ); }, animateIntro() { this.isIntro = true; gsap.fromTo( this.intro, { fadeOpacity: 1 }, { delay: 3, fadeOpacity: 0, duration: 0.35, ease: "none", onComplete: () => { this.isIntro = false; }, }, ); }, animateOutro() { this.isOutro = true; gsap.fromTo( this.outro, { fadeOpacity: 0 }, { delay: 0.5, fadeOpacity: 1, duration: 0.35, ease: "none", onComplete: () => { setTimeout(() => { this.isOutro = false; const app = useAppStore(); app.navigateTo("home"); }, 3000); }, }, ); }, }, });