Compare commits

...

8 Commits

Author SHA1 Message Date
GiovaniFZ
7a14a8cb77
conf: integrate i18n for location 2025-02-21 16:26:08 -03:00
GiovaniFZ
f9898669f9
feat: Add more skills 2025-02-17 19:21:34 -03:00
GiovaniFZ
7ff356f4b6
feat: create skills section 2025-02-02 17:21:20 -03:00
GiovaniFZ
9a2998b222
refactor: Commonize Paragraph 2025-02-02 17:18:20 -03:00
GiovaniFZ
b75b81e402
docs: Improve README.md 2025-02-02 17:16:47 -03:00
Giovani Finazzi
1b6a362bb5
Merge pull request #2 from ihatenodejs/main
Styling and grammar changes
2025-02-02 16:52:06 -03:00
ffbab3bfe5 style: add icon to send button, improve styling for textbox, bump packages 2025-02-01 22:54:23 -05:00
7e9f346110 chore: minor grammar fixes, reduce motion (remove typing from some content sections), styling improvements, add font 2025-02-01 22:38:53 -05:00
17 changed files with 604 additions and 548 deletions

View File

@ -1 +1,22 @@
# my-website # my-website
## Introduction
Hey, this is my website! The "Giv's website"
## Used Technologies
- React
- TypeScript
- Vite
## How to access?
If you want to check the deploy, visit the project repo on [Github](https://github.com/GiovaniFZ/my-website).
The access link will be availble on link section.
## Contributions
Any contribution is welcome. If you want to test the website in your own machine to help on this, make sure you have node.js installed, then clone the project repo and do the command:
`npm i`
Then it will be available at localhost://5173.
Enjoy!

918
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,32 +10,36 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@fontsource-variable/red-hat-display": "^5.1.1",
"@fortawesome/fontawesome-svg-core": "^6.7.2", "@fortawesome/fontawesome-svg-core": "^6.7.2",
"@fortawesome/free-brands-svg-icons": "^6.7.2", "@fortawesome/free-brands-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.2", "@fortawesome/react-fontawesome": "^0.2.2",
"@types/node": "^22.10.5", "@types/node": "^22.13.0",
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"fs": "^0.0.1-security", "fs": "^0.0.1-security",
"lucide-react": "^0.469.0", "i18next": "^24.2.2",
"i18next-browser-languagedetector": "^8.0.4",
"lucide-react": "^0.474.0",
"path": "^0.12.7", "path": "^0.12.7",
"pnpm": "^9.15.3", "pnpm": "^9.15.4",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-router-dom": "^7.1.1", "react-i18next": "^15.4.1",
"react-router-dom": "^7.1.5",
"react-typed": "^2.0.12", "react-typed": "^2.0.12",
"styled-components": "^6.1.14" "styled-components": "^6.1.14"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.11.1", "@eslint/js": "^9.19.0",
"@types/react": "^18.3.10", "@types/react": "^18.3.18",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.5",
"@vitejs/plugin-react": "^4.3.2", "@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.11.1", "eslint": "^9.19.0",
"eslint-plugin-react-hooks": "^5.1.0-rc.0", "eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-react-refresh": "^0.4.12", "eslint-plugin-react-refresh": "^0.4.18",
"globals": "^15.9.0", "globals": "^15.14.0",
"typescript": "^5.5.3", "typescript": "^5.7.3",
"typescript-eslint": "^8.7.0", "typescript-eslint": "^8.22.0",
"vite": "^5.4.8" "vite": "^5.4.14"
} }
} }

View File

@ -7,6 +7,8 @@ import About from './pages/about';
import Contact from './pages/contact'; import Contact from './pages/contact';
import Projects from './pages/projects'; import Projects from './pages/projects';
import { HashRouter } from 'react-router-dom'; import { HashRouter } from 'react-router-dom';
import '@fontsource-variable/red-hat-display';
import Skills from './pages/skills';
function App() { function App() {
return ( return (
@ -14,12 +16,18 @@ function App() {
<GlobalStyle /> <GlobalStyle />
<Header /> <Header />
<HashRouter> <HashRouter>
<section id="home"> <section
id="home"
className="firstSection"
>
<Home /> <Home />
</section> </section>
<section id="about"> <section id="about">
<About /> <About />
</section> </section>
<section id="skills">
<Skills />
</section>
<section id="contact"> <section id="contact">
<Contact /> <Contact />
</section> </section>

View File

@ -1,4 +1,4 @@
import styled from 'styled-components'; import styled from "styled-components";
export const Paragraph = styled.p` export const Paragraph = styled.p`
padding-top: 1rem; padding-top: 1rem;

3
src/locales/en-us.json Normal file
View File

@ -0,0 +1,3 @@
{
"about": "I'm Giovani, a software engineering student, interning and studying in Minas Gerais, Brazil!"
}

3
src/locales/pt-br.json Normal file
View File

@ -0,0 +1,3 @@
{
"about": "Meu nome é Giovani, estudante de engenharia de software, estagiando e estudando em Minas Gerais, Brasil!"
}

View File

@ -1,31 +1,15 @@
import { useEffect, useRef } from 'react'; import '../../utils/i18n'
import Typed from 'typed.js';
import { Paragraph } from './styles';
import { MainContainer } from '../../components/MainContent/styles'; import { MainContainer } from '../../components/MainContent/styles';
import { Paragraph } from '../../components/Paragraph/styles';
import { useTranslation } from 'react-i18next';
export default function About() { export default function About() {
const typedElement = useRef(null); const { t } = useTranslation();
useEffect(() => {
const typed = new Typed(typedElement.current, {
strings: ["About me"],
typeSpeed: 50,
backSpeed: 25,
loop: false,
});
return () => {
typed.destroy();
};
}, []);
return ( return (
<MainContainer> <MainContainer>
<h1> <h1>About Me</h1>
<span ref={typedElement} />
</h1>
<Paragraph> <Paragraph>
<span>Hi, I'm Giv, a software engineering student, interning on a nice company located in Minas Gerais in Brazil!</span> <span>{t("about")}</span>
</Paragraph> </Paragraph>
</MainContainer> </MainContainer>
); );

View File

@ -1,10 +1,10 @@
import { useEffect, useRef, useState } from 'react'; import { useState } from 'react';
import Typed from 'typed.js'; import { Button, TextArea } from './styles';
import { Button, Paragraph, TextArea } from './styles';
import { MainContainer } from '../../components/MainContent/styles'; import { MainContainer } from '../../components/MainContent/styles';
import { Send } from 'lucide-react';
import { Paragraph } from '../../components/Paragraph/styles';
export default function Contact() { export default function Contact() {
const typedElement = useRef(null);
const emailAddress = import.meta.env.VITE_GIV_EMAIL; const emailAddress = import.meta.env.VITE_GIV_EMAIL;
const [typedText, setTypedText] = useState(''); const [typedText, setTypedText] = useState('');
@ -13,30 +13,18 @@ export default function Contact() {
window.location.href = mailToTrigger window.location.href = mailToTrigger
} }
useEffect(() => {
const typed = new Typed(typedElement.current, {
strings: ["Contact"],
typeSpeed: 50,
backSpeed: 25,
loop: false,
});
return () => {
typed.destroy();
};
}, []);
return ( return (
<MainContainer> <MainContainer>
<h1> <h1>Contact</h1>
<span ref={typedElement} />
</h1>
<Paragraph> <Paragraph>
<span>If you want to contact me, you can use the links on the Main section, or say something in the field below! (It will open your email client btw)</span> <span>If you want to contact me, you can use the links above, or say put in the field below to send me an email!</span>
</Paragraph> </Paragraph>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<TextArea onChange={(e) => setTypedText(e.target.value)} /> <TextArea
<Button type='submit'>Send</Button> onChange={(e) => setTypedText(e.target.value)}
className="bgb"
/>
<Button type='submit'><Send className="ico" />Send</Button>
</form> </form>
</MainContainer> </MainContainer>
); );

View File

@ -1,10 +1,5 @@
import styled from 'styled-components'; import styled from 'styled-components';
export const Paragraph = styled.p`
padding-top: 1rem;
font-size: 1.25rem;
`;
export const TextArea = styled.textarea` export const TextArea = styled.textarea`
height: 10rem; height: 10rem;
margin-top: 1rem; margin-top: 1rem;

View File

@ -11,8 +11,8 @@ export default function Home() {
useEffect(() => { useEffect(() => {
const typed = new Typed(typedElement.current, { const typed = new Typed(typedElement.current, {
strings: ["Hi, I'm Giv! Welcome to my website!"], strings: ["Hi, I'm Giovani! Welcome to my website!"],
typeSpeed: 30, typeSpeed: 70,
backSpeed: 50, backSpeed: 50,
loop: false, loop: false,
}); });
@ -31,7 +31,7 @@ export default function Home() {
</strong> </strong>
</TopSection> </TopSection>
<HomeLabel> <HomeLabel>
Hey, check My social links! Hey, check out my social links!
</HomeLabel> </HomeLabel>
<IconContainer> <IconContainer>
<IconLink href="https://t.me/@givfnz2" target="_blank" rel="noopener noreferrer"> <IconLink href="https://t.me/@givfnz2" target="_blank" rel="noopener noreferrer">

View File

@ -16,7 +16,7 @@ export const IconLink = styled.a`
`; `;
export const HomeLabel = styled.p` export const HomeLabel = styled.p`
margin-top: 1rem; margin-top: 1.5rem;
`; `;
export const TopSection = styled.div` export const TopSection = styled.div`

View File

@ -0,0 +1,28 @@
import { MainContainer } from "../../components/MainContent/styles";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faAndroid, faAngular, faGit, faLinux, faNode, faReact, faWindows } from '@fortawesome/free-brands-svg-icons'
import { SkillsContainer } from "./styles";
export default function Skills() {
return (
<MainContainer>
<h1>Skills</h1>
<SkillsContainer>
<FontAwesomeIcon size="2x" style={{ color: '#fff' }} icon={faAndroid} />
<p>Android</p>
<FontAwesomeIcon size="2x" icon={faLinux} />
<p>Linux</p>
<FontAwesomeIcon size="2x" icon={faNode} />
<p>Node</p>
<FontAwesomeIcon size="2x" icon={faReact} />
<p>React</p>
<FontAwesomeIcon size="2x" icon={faAngular} />
<p>Angular</p>
<FontAwesomeIcon size="2x" icon={faWindows} />
<p>Windows</p>
<FontAwesomeIcon size="2x" icon={faGit} />
<p>Git</p>
</SkillsContainer>
</MainContainer>
)
}

View File

@ -0,0 +1,10 @@
import styled from "styled-components";
export const SkillsContainer = styled.div`
display: flex;
margin-top: 1rem;
p {
margin-left: 0.3rem;
margin-right: 2.5rem;
}
`

View File

@ -19,8 +19,8 @@ body{
padding: 1rem; padding: 1rem;
} }
body, input, textarea, button{ body, input, textarea, button {
font: 400 1.25rem Roboto, sans-serif; font-family: 'Red Hat Display Variable', sans-serif;
} }
h1 { h1 {
@ -51,8 +51,27 @@ p {
font-size: 1.25rem; font-size: 1.25rem;
} }
.mc{ .mc {
display: flex; display: flex;
padding: 2rem; padding: 2rem;
} }
.firstSection {
padding-top: 3.75rem;
}
.ico {
margin-right: 0.5rem;
height: 0.85rem;
width: 0.85rem;
}
.bgb {
background-color: ${props => props.theme["dark-cream"]};
color: ${props => props.theme.white};
border: none;
&:focus {
box-shadow: none;
}
};
` `

View File

@ -23,4 +23,5 @@ export const defaultTheme = {
'cream': '#D4D4A1', 'cream': '#D4D4A1',
'light-cream': '#F5F5DC', 'light-cream': '#F5F5DC',
'dark-cream': '#636342',
} }

20
src/utils/i18n.ts Normal file
View File

@ -0,0 +1,20 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import en from "../locales/en-us.json";
import pt from "../locales/pt-br.json";
i18n
.use(initReactI18next)
.use(LanguageDetector)
.init({
resources: {
en: { translation: en },
pt: { translation: pt },
},
fallbackLng: "en",
interpolation: { escapeValue: false },
});
export default i18n;