Files
pihkaal-me/app/stores/projects.ts

175 lines
3.8 KiB
TypeScript

import type {
DataCollectionItemBase,
ProjectsCollectionItem,
} from "@nuxt/content";
import gsap from "gsap";
type ProjectItem = Omit<
ProjectsCollectionItem,
keyof DataCollectionItemBase
> & {
id: string;
};
export type Project = Omit<ProjectItem, "en" | "fr"> & {
description: string;
summary: string;
tasks: string[];
};
export const useProjectsStore = defineStore("projects", {
state: () => ({
projects: [] as Project[],
currentProject: 0,
loading: true,
offsetX: 0,
intro: {
fadeOpacity: 1,
},
outro: {
fadeOpacity: 0,
},
isIntro: true,
isOutro: false,
showConfirmationPopup: false,
}),
actions: {
async loadProjects() {
const { locale } = useI18n();
this.loading = true;
const items = await queryCollection("projects")
.order("order", "ASC")
.all();
if (!items) throw "Cannot load projects";
this.projects = items.map((item) => {
const slug = item.id.split("/")[2]!;
const localeData = item[locale.value as "en"] ?? item.en;
if (!localeData) {
console.warn(`Missing '${locale.value}' for ${slug}`);
}
const { en: _en, fr: _fr, ...meta } = item;
return {
...meta,
id: slug.replace(/-([a-z])/g, (_: string, letter: string) =>
letter.toUpperCase(),
),
description: localeData.description ?? "",
summary: localeData.summary ?? "",
tasks: localeData.tasks ?? [],
};
});
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);
},
},
);
},
},
});