diff --git a/front/FerorIcon.ts b/front/FerorIcon.ts new file mode 100644 index 0000000..5fb5769 --- /dev/null +++ b/front/FerorIcon.ts @@ -0,0 +1,44 @@ +import { newLine } from "."; + +const icon = ` + ▲ + *◼︎◼︎◼︎, + ,◼︎◼︎◼︎◼︎◼︎◼︎◼︎* + ,◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎, + .◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎* + *◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎* + *◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎ + ,◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎,◼︎,◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎, + ,◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎, ..◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎* + ,◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎.. .◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎* + /◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎. *◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎ + ,.◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎, .◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎, + .◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎.. .◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎. + ◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎/ /◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎. + ◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎. *◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎. + .◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎. .◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎,. + ,◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎, .◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎, + ◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◤◥◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎/ /◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎. + ..◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎. ,◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎.. ,◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎. + ..◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎* .◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎, .◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎. + .◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎, ◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎. ,.◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎, + .◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎ *◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎.. *◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎. + ..◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎, ,◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎, .◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎. +`; + +interface FerorIconProps { + width: number; +} + +const FerorIcon = ({ width }: FerorIconProps) => { + const iconLines = icon.split("\n").filter((line) => line.trim() !== ""); + const iconWidth = iconLines[0]!.length; + + // On va ajouter des espaces pour centrer l'icône + const numberOfSpaces = Math.floor((width - iconWidth) / 2); + const spaces = " ".repeat(numberOfSpaces); + + return iconLines.map((line) => `${spaces}${line}`).join(newLine); +}; + +export default FerorIcon; diff --git a/front/Tabs/About.ts b/front/Tabs/About.ts index dfd89b7..cf1db53 100644 --- a/front/Tabs/About.ts +++ b/front/Tabs/About.ts @@ -1,6 +1,7 @@ import { link } from "ansi-escapes"; import { newLine } from ".."; import ScrollComponent from "../ScrollComponent"; +import FerorIcon from "../FerorIcon"; interface AboutProps { width: number; @@ -50,7 +51,10 @@ const About = ({ width, height, scrollPosition }: AboutProps) => { ` If you want to see how it works, you can check out the source code on my ${link( "Forgejo", "https://forge.feror.fr/feror/Portfolio" - )}.${newLine}`; + )}.${newLine}` + + `${newLine}` + + `${FerorIcon({ width })}` + + `${newLine}`; return ScrollComponent({ width, diff --git a/front/Tabs/Project.ts b/front/Tabs/Project.ts new file mode 100644 index 0000000..8d05878 --- /dev/null +++ b/front/Tabs/Project.ts @@ -0,0 +1,33 @@ +import { link } from "ansi-escapes"; +import { newLine } from ".."; + +interface ProjectProps { + title: string; + description: string; + technologies: string[]; + learnMoreLink: string; +} + +const Project = ({ title, description, technologies, learnMoreLink }: ProjectProps) => { + return ( + ` ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓${newLine}` + + ` ┃ \x1b[33m${title.padEnd(80 - 4)}\x1b[0m ┃${newLine}` + + ` ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫${newLine}` + + description + .split(newLine) + .map((line) => ` ┃ ${line.padEnd(80 - 4)} ┃${newLine}`) + .join("") + + ` ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫${newLine}` + + ` ┃ Technologies: \x1b[34m${technologies.join(", ").padEnd(80 - 18)}\x1b[0m ┃${newLine}` + + ` ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫${newLine}` + + ` ┃${link( + " \x1b[32mLearn more\x1b[0m ", + learnMoreLink + )}┃${newLine}` + + ` ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛${newLine}` + ); +}; + +export default Project; + +export type { ProjectProps }; diff --git a/front/Tabs/Projects.ts b/front/Tabs/Projects.ts index 6218c32..e8f8237 100644 --- a/front/Tabs/Projects.ts +++ b/front/Tabs/Projects.ts @@ -1,3 +1,8 @@ +import { newLine } from ".."; +import ScrollComponent from "../ScrollComponent"; +import type { ProjectProps } from "./Project"; +import Project from "./Project"; + interface ProjectsProps { width: number; height: number; @@ -5,6 +10,27 @@ interface ProjectsProps { } const Projects = ({ width, height, scrollPosition }: ProjectsProps) => { - return `Projects ${scrollPosition}`; + const projects: ProjectProps[] = [ + { + title: "Algoforge", + description: + `A platform for creating and sharing graphical algorithms.${newLine}` + + `It was made for the algorithm course at IUT de Bayonne et du Pays Basque.${newLine}` + + `It is made entirely in Vanilla JS. No Framework used.${newLine}` + + `This app thrives for simplicity, efficiency and performance. ${newLine}` + + `${newLine}` + + `Built with love over the course of 3 years,${newLine}` + + `Algoforge was originally meant to replace an aging software.${newLine}` + + `It is now used by students and teachers alike.${newLine}`, + technologies: ["js", "Bun", "Docker"], + learnMoreLink: "https://github.com/Bing-Chill-inc/Algoforge-main", + }, + ]; + return ScrollComponent({ + width, + height, + scrollPosition, + text: projects.map((project) => Project(project)).join(newLine), + }); }; export default Projects;