162 lines
3.4 KiB
TypeScript
162 lines
3.4 KiB
TypeScript
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);
|
|
},
|
|
},
|
|
);
|
|
},
|
|
},
|
|
});
|