feat: finished translations, added project grid #1

Merged
hknsh merged 2 commits from features into master 2024-11-10 19:20:26 +00:00
11 changed files with 273 additions and 103 deletions
Showing only changes of commit 56f15b4760 - Show all commits

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

10
src/assets/portfolio.svg Normal file
View file

@ -0,0 +1,10 @@
<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="256" height="256" rx="66" fill="black"/>
<path d="M217.267 102.138C216.483 99.6704 215.85 97.9296 215.744 97.2928C214.395 97.6354 213.008 97.8032 211.616 97.792C209.136 97.792 206.272 97.312 203.315 96.112C196.707 93.4304 192.384 88.2432 191.2 81.6672C190.454 81.8784 189.453 81.9872 188.291 81.9872C184.547 81.9872 179.123 80.8576 175.12 78.3488C167.478 73.5616 165.962 60.2176 165.962 60.2176C157.306 57.712 150.797 47.5296 151.837 38.8672C144.077 36.7808 136.41 32 127.997 32C119.571 32 111.891 36.8064 104.122 38.88C96.0768 41.0304 87.0272 40.7744 79.9936 44.8416C72.8512 48.9792 68.576 56.9792 62.7808 62.7744C56.9792 68.576 48.9792 72.848 44.848 79.9872C40.7744 87.0304 41.0368 96.0736 38.8864 104.118C36.8128 111.888 32 119.578 32 127.997C32 136.419 36.8128 144.102 38.8864 151.875C41.0368 159.914 40.7744 168.963 44.848 176C48.9792 183.142 56.9792 187.418 62.7808 193.213C68.576 199.008 72.848 207.014 79.9936 211.146C87.0272 215.226 96.0768 214.963 104.122 217.114C111.891 219.194 119.571 224 127.997 224C136.429 224 144.109 219.194 151.885 217.114C159.923 214.963 168.973 215.226 176.006 211.146C183.149 207.014 187.424 199.008 193.219 193.213C199.021 187.418 207.021 183.146 211.152 176C215.226 168.963 214.963 159.914 217.114 151.875C219.187 144.099 224 136.419 224 127.997C224 119.578 217.267 102.138 217.267 102.138ZM213.987 125.901C213.59 128.512 211.622 131.312 209.53 134.275C207.254 137.507 204.672 141.174 203.504 145.562C202.71 148.525 202.256 151.482 201.818 154.342C201.13 158.806 200.483 163.018 198.685 166.131C196.845 169.306 193.504 171.974 189.968 174.8C187.722 176.595 185.398 178.445 183.258 180.589C181.117 182.726 179.261 185.053 177.466 187.302C174.64 190.835 171.974 194.17 168.794 196.016C165.686 197.818 161.478 198.467 157.021 199.149C154.157 199.594 151.197 200.048 148.237 200.842C145.382 201.603 142.666 202.666 140.035 203.706C135.798 205.37 131.795 206.938 127.994 206.938C124.192 206.938 120.192 205.363 115.952 203.699C113.328 202.669 110.611 201.606 107.763 200.842C104.797 200.048 101.834 199.59 98.9728 199.149C94.512 198.467 90.304 197.818 87.1904 196.016C84.0128 194.179 81.3472 190.835 78.528 187.302C76.7296 185.053 74.8736 182.726 72.7328 180.589C70.592 178.445 68.2688 176.595 66.0224 174.8C62.4896 171.974 59.1488 169.306 57.3088 166.131C55.5072 163.018 54.8576 158.806 54.1728 154.342C53.7312 151.478 53.28 148.525 52.4896 145.568C51.728 142.704 50.656 139.981 49.6224 137.344C47.968 133.114 46.4 129.12 46.4 125.334C46.4 121.539 47.968 117.539 49.632 113.309C50.6656 110.675 51.7344 107.952 52.4992 105.098C53.2896 102.134 53.744 99.1776 54.1824 96.3136C54.8704 91.8528 55.5168 87.6384 57.3152 84.5248C59.1552 81.3472 62.496 78.6816 66.032 75.8592C68.2784 74.064 70.6016 72.2112 72.7424 70.0704C74.8832 67.9296 76.7392 65.6064 78.5376 63.36C81.36 59.8272 84.0256 56.4896 87.1968 54.6496C90.3104 52.848 94.5216 52.2016 98.9824 51.5136C101.846 51.072 104.806 50.6176 107.766 49.824C110.621 49.0624 113.341 47.9968 115.968 46.9632C120.205 45.3024 124.205 43.7344 128 43.7344C129.094 43.7344 130.211 43.728 131.35 43.7184C132.493 43.712 133.654 43.7024 134.822 43.7024C138.458 43.7024 142.186 43.776 145.574 44.192C146.816 52.7744 152.573 60.9408 160.282 64.8288C161.462 70.1152 164.48 79.2352 171.722 83.7728C176.483 86.7584 182.218 88.0576 186.56 88.3328C189.197 94.4736 194.218 99.328 200.909 102.045C204.18 103.385 207.669 104.113 211.203 104.192C212.838 109.395 215.165 118.138 213.987 125.901Z" fill="white"/>
<path d="M89.343 103.881C91.2482 100.424 93.6851 91.0971 92.7694 88.9027C91.4295 85.6835 86.2976 79.3574 82.942 79.3381C73.342 79.2931 64.3197 87.1325 62.1379 91.0521C59.1663 96.3919 63.6774 106.615 69.682 109.218C78.6767 113.128 83.9345 113.709 89.343 103.881Z" fill="white"/>
<path d="M156.686 127.804C153.831 128.614 147.615 132.321 146.969 134.047C146.01 136.575 145.513 142.975 147.341 144.909C152.574 150.426 161.618 151.303 164.863 150.407C169.285 149.183 172.165 140.999 170.247 136.138C167.368 128.852 164.792 125.526 156.686 127.804Z" fill="white"/>
<path d="M111.657 116.5C108.802 117.31 102.585 121.017 101.94 122.743C100.981 125.271 100.483 131.671 102.312 133.605C107.545 139.122 116.589 139.999 119.834 139.102C124.256 137.878 127.135 129.695 125.218 124.834C122.338 117.547 119.763 114.222 111.657 116.5Z" fill="white"/>
<path d="M122.473 63.0381C119.618 63.8477 113.402 67.5554 112.756 69.2807C111.798 71.8092 111.3 78.2092 113.128 80.1433C118.361 85.6598 127.405 86.5369 130.65 85.6405C135.072 84.4164 137.952 76.2333 136.034 71.3722C133.155 64.0855 130.58 60.7602 122.473 63.0381Z" fill="white"/>
<path d="M90.5426 162.95C84.4981 165.562 81.7355 167.901 83.6284 175.248C84.2983 177.841 87.3744 183.476 88.8064 184.064C90.9052 184.932 96.2184 185.382 97.8195 183.727C102.398 178.975 103.126 170.782 102.38 167.833C101.363 163.823 94.5744 161.211 90.5426 162.95Z" fill="white"/>
<path d="M182.869 106.789C179.031 107.849 176.532 114.949 178.198 119.165C180.696 125.484 186.492 126.557 192.93 122.991C198.372 119.977 198.744 109.674 197.155 107.997C192.616 103.21 185.687 106.008 182.869 106.789Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View file

@ -11,9 +11,9 @@ export function Header() {
return ( return (
<div className="flex-center"> <div className="flex-center">
<header className="h-18 fixed left-0 right-0 top-0 bg-neutral-950 p-8 text-xl"> <header className="h-18 fixed left-0 right-0 top-0 bg-neutral-950 p-8 text-xl z-10">
<div className="mx-auto p-4"> <div className="mx-auto p-4">
<nav className="flex-center space-x-5 md:space-x-12"> <nav className="flex-center space-x-4 md:space-x-12">
<button <button
type="button" type="button"
onClick={() => scroll("home")} onClick={() => scroll("home")}

View file

@ -16,6 +16,8 @@ import MongoDB from "../assets/tech/mongo.svg";
import Postgres from "../assets/tech/postgres.svg"; import Postgres from "../assets/tech/postgres.svg";
import Tailwind from "../assets/frameworks/tailwind.svg"; import Tailwind from "../assets/frameworks/tailwind.svg";
import React from "../assets/frameworks/react.svg"; import React from "../assets/frameworks/react.svg";
import Knedita from "../assets/knedita-light.svg";
import Portfolio from "../assets/portfolio.svg";
export const Icons = { export const Icons = {
languages: { Javascript, Typescript, Rust }, languages: { Javascript, Typescript, Rust },
@ -24,4 +26,5 @@ export const Icons = {
devops: { Docker, Linux, Git, Actions }, devops: { Docker, Linux, Git, Actions },
docs_tests: { Swagger, Jest }, docs_tests: { Swagger, Jest },
db_orm: { Prisma, Postgres, MongoDB }, db_orm: { Prisma, Postgres, MongoDB },
projects: { Knedita, Portfolio },
}; };

View file

@ -0,0 +1,72 @@
import { Icons } from "./Icons";
import { useTranslation } from "react-i18next";
export function ProjectGrid() {
const { t } = useTranslation();
const projects = t("projects.list", { returnObjects: true });
const fetchIcon = (icon) => {
if (icon.startsWith("https")) {
return icon;
}
switch (icon) {
case "knedita-light":
return Icons.projects.Knedita;
case "portfolio":
return Icons.projects.Portfolio;
default:
return null;
}
};
return (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{Object.entries(projects).map(([key, project]) => (
<div key={key} className="bg-neutral-900 p-6 rounded-lg shadow-lg flex flex-col">
<div className="flex items-center space-x-4">
<img
src={fetchIcon(project.icon)}
alt={`${project.name} logo`}
className="h-12 w-12 object-contain rounded-md"
/>
<h2 className="text-xl font-semibold">{project.name}</h2>
</div>
<p className="text-neutral-300 mt-4">{project.description}</p>
<p className="text-neutral-400 text-sm mt-2 mb-2">
{t("projects.license")}: {project.license}
</p>
{project.stack && project.stack.length > 0 && (
<div className="mt-3 mb-4">
<p className="text-neutral-400 text-sm font-medium">
{t("projects.stack")}
</p>
<ul className="flex flex-wrap gap-2 mt-1">
{project.stack.map((item, k) => (
<li
key={k}
className="bg-neutral-700 text-neutral-100 px-2 py-1 rounded text-xs"
>
{item}
</li>
))}
</ul>
</div>
)}
<a
href={project.link}
target="_blank"
rel="noopener noreferrer"
className="block mt-auto text-center bg-indigo-600 text-neutral-100 px-4 py-2 rounded font-semibold hover:bg-indigo-700 transition"
>
{t("projects.checkProject")}
</a>
</div>
))}
</div>
);
}

View file

@ -15,7 +15,6 @@ import './i18n';
export function App() { export function App() {
return ( return (
<LocationProvider> <LocationProvider>
<Header />
<main> <main>
<Router> <Router>
<Route path="/" component={Home} /> <Route path="/" component={Home} />

View file

@ -9,8 +9,44 @@
"i18n": "Also available in:", "i18n": "Also available in:",
"description": "I started studying programming back in 2017 when I was 11 years old! Since then I've been creating a few projects to improve my skills.", "description": "I started studying programming back in 2017 when I was 11 years old! Since then I've been creating a few projects to improve my skills.",
"technologies": "Technologies", "technologies": "Technologies",
"projects": "Projects & Contributions", "projects_contributions": "Projects & Contributions",
"knedita": "An open-source social media.", "projects": {
"biome": "Contributed to the Portuguese translation of the documentation" "license": "License",
"stack": "Stack",
"checkProject": "Check this project",
"list": [
{
"name": "Project Knedita",
"description": "An open-source social media",
"license": "MIT",
"stack": [
"Typescript",
"Bun",
"NestJS",
"Prisma",
"Kysely",
"Postgres",
"Redis"
],
"icon": "knedita-light",
"link": "https://github.com/hknsh/project-knedita"
},
{
"name": "BiomeJS",
"description": "Contributed to the Portuguese translation of the documentation",
"license": "Apache 2.0 & MIT",
"icon": "https://avatars.githubusercontent.com/u/140182603",
"link": "https://github.com/biomejs/biome"
},
{
"name": "hknsh's house",
"description": "My portfolio",
"license": "MIT",
"stack": ["Preact", "Vite", "Bun", "shadcn/ui", "Typescript"],
"icon": "portfolio",
"link": "https://git.hknsh.com/hknsh/hknsh-house"
}
]
}
} }
} }

View file

@ -9,8 +9,44 @@
"i18n": "他の言語でも利用できます:", "i18n": "他の言語でも利用できます:",
"description": "2017年、まだ11歳のときにプログラミングの勉強を始めました。それ以来、スキルを磨くためにいくつかのプロジェクトを作ってきました。", "description": "2017年、まだ11歳のときにプログラミングの勉強を始めました。それ以来、スキルを磨くためにいくつかのプロジェクトを作ってきました。",
"technologies": "技術", "technologies": "技術",
"projects": "プロジェクトと貢献", "projects_contributions": "プロジェクトと貢献",
"knedita": "オープンソースのSNS。", "projects": {
"biome": "ポルトガル語のドキュメント翻訳に貢献しました" "license": "ライセンス",
"stack": "スタック",
"checkProject": "このプロジェクトを見て",
"list": [
{
"name": "Project Knedita",
"description": "オープンソースのSNS",
"license": "MIT",
"stack": [
"Typescript",
"Bun",
"NestJS",
"Prisma",
"Kysely",
"Postgres",
"Redis"
],
"icon": "knedita-light",
"link": "https://github.com/hknsh/project-knedita"
},
{
"name": "BiomeJS",
"description": "ポルトガル語のドキュメント翻訳に貢献しました",
"license": "Apache 2.0 & MIT",
"icon": "https://avatars.githubusercontent.com/u/140182603",
"link": "https://github.com/biomejs/biome"
},
{
"name": "hknsh's house",
"description": "私のポートフォリオ",
"license": "MIT",
"stack": ["Preact", "Vite", "Bun", "shadcn/ui", "Typescript"],
"icon": "portfolio",
"link": "https://git.hknsh.com/hknsh/hknsh-house"
}
]
}
} }
} }

View file

@ -9,8 +9,44 @@
"i18n": "Também disponível em:", "i18n": "Também disponível em:",
"description": "Comecei a estudar programação em 2017, quando eu tinha apenas 11 anos. Desde então venho criando alguns projetos para aprimorar minhas habilidades", "description": "Comecei a estudar programação em 2017, quando eu tinha apenas 11 anos. Desde então venho criando alguns projetos para aprimorar minhas habilidades",
"technologies": "Tecnologias", "technologies": "Tecnologias",
"projects": "Projetos & Contribuições", "projects_contributions": "Projetos & Contribuições",
"knedita": "Uma rede social open-source.", "projects": {
"biome": "Contribuí na tradução em Português da documentação" "license": "Licença",
"stack": "Tecnologias",
"checkProject": "Confira esse projeto!",
"list": [
{
"name": "Project Knedita",
"description": "Uma rede social open-source.",
"license": "MIT",
"stack": [
"Typescript",
"Bun",
"NestJS",
"Prisma",
"Kysely",
"Postgres",
"Redis"
],
"icon": "knedita-light",
"link": "https://github.com/hknsh/project-knedita"
},
{
"name": "BiomeJS",
"description": "Contribuí na tradução em Português da documentação",
"license": "Apache 2.0 & MIT",
"icon": "https://avatars.githubusercontent.com/u/140182603",
"link": "https://github.com/biomejs/biome"
},
{
"name": "hknsh's house",
"description": "Meu portfolio!",
"license": "MIT",
"stack": ["Preact", "Vite", "Bun", "shadcn/ui", "Typescript"],
"icon": "portfolio",
"link": "https://git.hknsh.com/hknsh/hknsh-house"
}
]
}
} }
} }

View file

@ -1,16 +1,10 @@
import { TechnologiesTab } from "@/components/TechnologiesTab"; import { TechnologiesTab } from "@/components/TechnologiesTab";
import { Card, CardContent } from "@/components/ui/card";
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel";
import { Separator } from "@/components/ui/separator"; import { Separator } from "@/components/ui/separator";
import { useState } from "preact/hooks"; import { useState } from "preact/hooks";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useEffect } from "react"; import { useEffect } from "react";
import { Header } from "@/components/Header";
import { ProjectGrid } from "@/components/ProjectGrid";
export function Home() { export function Home() {
const { const {
@ -33,83 +27,70 @@ export function Home() {
localStorage.setItem("language", lang); localStorage.setItem("language", lang);
}; };
return ( return (
<div id="home" className="md:flex-center flex-col pt-24"> <>
<div className="flex flex-col items-start justify-center p-4"> <Header />
<div className="space-y-8 mt-4 md:mt-7">
<h1 className="title">{t("hello")}</h1> <div id="home" className="md:flex-center flex-col pt-24">
<p className="text">{t("introduction")}</p> <div className="flex flex-col items-start justify-center p-4">
<div className="flex flex-col space-y-1 text-left items-start"> <div className="space-y-8 mt-4 md:mt-7">
<p className="text">{t("i18n")}</p> <h1 className="title">{t("hello")}</h1>
<div className="space-y-2"> <p className="text">{t("introduction")}</p>
<ul className="flex flex-row space-x-2"> <div className="flex flex-col space-y-1 text-left items-start">
<li> <p className="text">{t("i18n")}</p>
<button <div className="space-y-2">
type="button" <ul className="flex flex-row space-x-2">
onClick={() => handleChangeLanguage("en")} <li>
className="link text" <button
> type="button"
English, onClick={() => handleChangeLanguage("en")}
</button> className="link text"
</li> >
<li> English,
<button </button>
type="button" </li>
onClick={() => handleChangeLanguage("pt")} <li>
className="link text" <button
> type="button"
Português do Brasil, onClick={() => handleChangeLanguage("pt")}
</button> className="link text"
</li> >
<li> Português do Brasil,
<button </button>
type="button" </li>
onClick={() => handleChangeLanguage("ja")} <li>
className="link text" <button
> type="button"
onClick={() => handleChangeLanguage("ja")}
</button> className="link text"
</li> >
</ul>
</button>
</li>
</ul>
</div>
</div>
<p className="break-words text">{t("description")}</p>
</div>
<Separator className="my-8 bg-neutral-700" />
<div>
<div className="space-y-10 mt-4 md:mt-7">
<h1 className="title">{t("technologies")}</h1>
<TechnologiesTab />
</div> </div>
</div> </div>
<p className="break-words text">{t("description")}</p>
</div>
<Separator className="my-8 bg-neutral-700" /> <Separator className="my-8 bg-neutral-700" />
<div> <div id="projects">
<div className="space-y-10 mt-4 md:mt-7"> <div className="space-y-10 mt-4 md:mt-7">
<h1 className="title">{t("technologies")}</h1> <h1 className="title">{t("projects_contributions")}</h1>
<TechnologiesTab /> <ProjectGrid />
</div> </div>
</div>
<Separator className="my-8 bg-neutral-700" />
<div id="projects">
<div className="space-y-10 mt-4 md:mt-7">
<h1 className="title">{t("projects")}</h1>
<Carousel className="w-full max-w-xs">
<CarouselContent className="-ml-1">
<CarouselItem key="1">
<div className="p-1">
<Card className="bg-neutral-950 text-neutral-100">
<CardContent className="flex aspect-square items-center justify-center p-6">
<span className="text-4xl font-semibold">
Project Knedita
</span>
</CardContent>
</Card>
</div>
</CarouselItem>
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
</div> </div>
</div> </div>
</div> </div>
</div> </>
); );
} }

View file

@ -1,8 +1,11 @@
export function NotFound() { export function NotFound() {
return ( return (
<section> <section className="flex flex-col justify-center items-center h-screen">
<h1>404: Not Found</h1> <h1 className="text-xl font-medium">Looks like you are lost!</h1>
<p>It's gone :(</p> <br />
<a href="/" className="text-base font-medium link">
Let's go back home
</a>
</section> </section>
); );
} }