feat: update page titles and add new components for home and projects, huge design overhaul

This commit is contained in:
Aidan 2025-01-10 02:24:24 -05:00
parent afa2d0e714
commit 1562a483ed
17 changed files with 566 additions and 111 deletions

7
.gitignore vendored
View File

@ -22,3 +22,10 @@ dist-ssr
*.njsproj *.njsproj
*.sln *.sln
*.sw? *.sw?
# Bun
bun.lockb
# ts build info
tsconfig.app.tsbuildinfo
tsconfig.node.tsbuildinfo

View File

@ -1,50 +1 @@
# React + TypeScript + Vite # my-website
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
## Expanding the ESLint configuration
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
- Configure the top-level `parserOptions` property like this:
```js
export default tseslint.config({
languageOptions: {
// other options...
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
},
})
```
- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
- Optionally add `...tseslint.configs.stylisticTypeChecked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
```js
// eslint.config.js
import react from 'eslint-plugin-react'
export default tseslint.config({
// Set the react version
settings: { react: { version: '18.3' } },
plugins: {
// Add the react plugin
react,
},
rules: {
// other rules...
// Enable its recommended rules
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
},
})
```

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Giv's website</title> <title>Giv's Website</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

225
package-lock.json generated
View File

@ -8,9 +8,12 @@
"name": "givs-website-react", "name": "givs-website-react",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"lucide-react": "^0.469.0",
"pnpm": "^9.15.3", "pnpm": "^9.15.3",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1" "react-dom": "^18.3.1",
"react-router-dom": "^7.1.1",
"styled-components": "^6.1.14"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.11.1", "@eslint/js": "^9.11.1",
@ -330,6 +333,27 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@emotion/is-prop-valid": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
"integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
"license": "MIT",
"dependencies": {
"@emotion/memoize": "^0.8.1"
}
},
"node_modules/@emotion/memoize": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
"integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==",
"license": "MIT"
},
"node_modules/@emotion/unitless": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
"integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==",
"license": "MIT"
},
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.21.5", "version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
@ -1202,6 +1226,12 @@
"@babel/types": "^7.20.7" "@babel/types": "^7.20.7"
} }
}, },
"node_modules/@types/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
"license": "MIT"
},
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
@ -1239,6 +1269,12 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"node_modules/@types/stylis": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz",
"integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==",
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.8.1", "version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.1.tgz",
@ -1612,6 +1648,15 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/camelize": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
"integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001668", "version": "1.0.30001668",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001668.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001668.tgz",
@ -1673,6 +1718,15 @@
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
"dev": true "dev": true
}, },
"node_modules/cookie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
"integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.6", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@ -1687,11 +1741,30 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/css-color-keywords": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
"integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
"license": "ISC",
"engines": {
"node": ">=4"
}
},
"node_modules/css-to-react-native": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
"integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
"license": "MIT",
"dependencies": {
"camelize": "^1.0.0",
"css-color-keywords": "^1.0.0",
"postcss-value-parser": "^4.0.2"
}
},
"node_modules/csstype": { "node_modules/csstype": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
"dev": true
}, },
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.7", "version": "4.3.7",
@ -2396,6 +2469,15 @@
"yallist": "^3.0.2" "yallist": "^3.0.2"
} }
}, },
"node_modules/lucide-react": {
"version": "0.469.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.469.0.tgz",
"integrity": "sha512-28vvUnnKQ/dBwiCQtwJw7QauYnE7yd2Cyp4tTTJpvglX4EMpbflcdBgrgToX2j71B3YvugK/NH3BGUk+E/p/Fw==",
"license": "ISC",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/merge2": { "node_modules/merge2": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@ -2440,7 +2522,6 @@
"version": "3.3.8", "version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@ -2546,8 +2627,7 @@
"node_modules/picocolors": { "node_modules/picocolors": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
"integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="
"dev": true
}, },
"node_modules/picomatch": { "node_modules/picomatch": {
"version": "2.3.1", "version": "2.3.1",
@ -2604,6 +2684,12 @@
"node": "^10 || ^12 || >=14" "node": "^10 || ^12 || >=14"
} }
}, },
"node_modules/postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"license": "MIT"
},
"node_modules/prelude-ls": { "node_modules/prelude-ls": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@ -2674,6 +2760,46 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/react-router": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.1.tgz",
"integrity": "sha512-39sXJkftkKWRZ2oJtHhCxmoCrBCULr/HAH4IT5DHlgu/Q0FCPV0S4Lx+abjDTx/74xoZzNYDYbOZWlJjruyuDQ==",
"license": "MIT",
"dependencies": {
"@types/cookie": "^0.6.0",
"cookie": "^1.0.1",
"set-cookie-parser": "^2.6.0",
"turbo-stream": "2.4.0"
},
"engines": {
"node": ">=20.0.0"
},
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
}
}
},
"node_modules/react-router-dom": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.1.1.tgz",
"integrity": "sha512-vSrQHWlJ5DCfyrhgo0k6zViOe9ToK8uT5XGSmnuC2R3/g261IdIMpZVqfjD6vWSXdnf5Czs4VA/V60oVR6/jnA==",
"license": "MIT",
"dependencies": {
"react-router": "7.1.1"
},
"engines": {
"node": ">=20.0.0"
},
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18"
}
},
"node_modules/resolve-from": { "node_modules/resolve-from": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@ -2768,6 +2894,18 @@
"semver": "bin/semver.js" "semver": "bin/semver.js"
} }
}, },
"node_modules/set-cookie-parser": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
"license": "MIT"
},
"node_modules/shallowequal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==",
"license": "MIT"
},
"node_modules/shebang-command": { "node_modules/shebang-command": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -2793,7 +2931,6 @@
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@ -2810,6 +2947,68 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/styled-components": {
"version": "6.1.14",
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.14.tgz",
"integrity": "sha512-KtfwhU5jw7UoxdM0g6XU9VZQFV4do+KrM8idiVCH5h4v49W+3p3yMe0icYwJgZQZepa5DbH04Qv8P0/RdcLcgg==",
"license": "MIT",
"dependencies": {
"@emotion/is-prop-valid": "1.2.2",
"@emotion/unitless": "0.8.1",
"@types/stylis": "4.2.5",
"css-to-react-native": "3.2.0",
"csstype": "3.1.3",
"postcss": "8.4.38",
"shallowequal": "1.1.0",
"stylis": "4.3.2",
"tslib": "2.6.2"
},
"engines": {
"node": ">= 16"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/styled-components"
},
"peerDependencies": {
"react": ">= 16.8.0",
"react-dom": ">= 16.8.0"
}
},
"node_modules/styled-components/node_modules/postcss": {
"version": "8.4.38",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.0",
"source-map-js": "^1.2.0"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/stylis": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz",
"integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==",
"license": "MIT"
},
"node_modules/supports-color": { "node_modules/supports-color": {
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@ -2861,6 +3060,18 @@
"typescript": ">=4.2.0" "typescript": ">=4.2.0"
} }
}, },
"node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
"license": "0BSD"
},
"node_modules/turbo-stream": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
"integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
"license": "ISC"
},
"node_modules/type-check": { "node_modules/type-check": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",

View File

@ -10,10 +10,18 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.7.2",
"@fortawesome/free-brands-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"@types/node": "^22.10.5",
"fs": "^0.0.1-security",
"lucide-react": "^0.469.0", "lucide-react": "^0.469.0",
"path": "^0.12.7",
"pnpm": "^9.15.3", "pnpm": "^9.15.3",
"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-typed": "^2.0.12",
"styled-components": "^6.1.14" "styled-components": "^6.1.14"
}, },
"devDependencies": { "devDependencies": {

25
public/github.json Normal file
View File

@ -0,0 +1,25 @@
[
{
"name": "Giv-Shuffler",
"description": "Sorts n numbers in a range, according with the count that the user chooses.",
"stars": 3,
"language": "TypeScript",
"url": "https://github.com/GiovaniFZ/Giv-Shuffler"
},
{
"name": "Mini-Calculadora",
"description": "Projeto React para o Postaqui.",
"stars": 0,
"language": "JavaScript",
"url": "https://github.com/GiovaniFZ/Mini-Calculadora"
},
{
"name": "MCalendar",
"description": "WhatsApp Calendar",
"stars": 0,
"language": "Java",
"url": "https://github.com/GiovaniFZ/MCalendar"
}
]

View File

@ -1,17 +1,30 @@
import { ThemeProvider } from 'styled-components'; import { ThemeProvider } from 'styled-components';
import Header from './components/Header' import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Header from './components/Header';
import { defaultTheme } from './styles/themes/default'; import { defaultTheme } from './styles/themes/default';
import { GlobalStyle } from './styles/global'; import { GlobalStyle } from './styles/global';
import Home from './pages/home';
import About from './pages/about';
import Contact from './pages/contact';
import Projects from './pages/projects';
function App() { function App() {
return ( return (
<ThemeProvider theme={defaultTheme}> <ThemeProvider theme={defaultTheme}>
<GlobalStyle /> <GlobalStyle />
<Header> <Router>
</Header> <Header />
<div className="mc">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
<Route path="/projects" element={<Projects />} />
</Routes>
</div>
</Router>
</ThemeProvider> </ThemeProvider>
) );
} }
export default App export default App;

View File

@ -1,12 +1,14 @@
import { HeaderContainer } from "./styles"; import { HeaderContainer, NavLink, HomeLink } from "./styles";
export default function Header(){ export default function Header(){
return( return(
<HeaderContainer> <HeaderContainer>
<p>I'm Giv!</p> <HomeLink href="/">Giv's Website</HomeLink>
<a>About me</a> <nav>
<a>Contact</a> <NavLink href="/about">About Me</NavLink>
<a>Projects</a> <NavLink href="/contact">Contact</NavLink>
</HeaderContainer> <NavLink href="/projects">Projects</NavLink>
) </nav>
</HeaderContainer>
)
} }

View File

@ -1,11 +1,41 @@
import styled from "styled-components"; import styled from "styled-components";
export const HomeLink = styled.a`
font-size: 1.5rem;
font-weight: bold;
color: ${props => props.theme.white};
text-decoration: none;
transition: color 0.3s;
&:hover {
color: ${props => props.theme["cream"]};
}
`;
export const NavLink = styled.a`
font-size: 1rem;
color: ${props => props.theme.white};
text-decoration: none;
transition: color 0.3s;
&:hover {
color: ${props => props.theme["cream"]};
}
`;
export const HeaderContainer = styled.div` export const HeaderContainer = styled.div`
border-radius: 8px; display: flex;
width: 100%; justify-content: space-between;
height: 70px; align-items: center;
background-color: ${props => props.theme["green-500"]}; padding: 0 2rem;
a{ border-radius: 8px;
font-size: 30px, width: 100%;
} height: 70px;
` background-color: ${props => props.theme["green-500"]};
color: ${props => props.theme.white};
nav {
display: flex;
gap: 1rem;
}
`;

View File

@ -1,3 +1,3 @@
export default function About(){ export default function About(){
return <h1>About</h1> return <h1>About Me</h1>
} }

View File

@ -1,3 +1,3 @@
export default function Contact(){ export default function Contact(){
return <h1>About</h1> return <h1>Contact Me</h1>
} }

41
src/pages/home/index.tsx Normal file
View File

@ -0,0 +1,41 @@
import Typed from 'typed.js';
import { useEffect, useRef } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTelegram, faGithub } from '@fortawesome/free-brands-svg-icons';
import { IconContainer, IconLink, HomeLabel } from './styles';
export default function Home() {
const typedElement = useRef(null);
useEffect(() => {
const typed = new Typed(typedElement.current, {
strings: ["Hi, I'm Giv! Welcome to my website~", "I hope you enjoy checking out my projects!", "Giv-Fnz"],
typeSpeed: 30,
backSpeed: 50,
loop: false,
});
return () => {
typed.destroy();
};
}, []);
return (
<div>
<h1>
<span ref={typedElement} />
</h1>
<HomeLabel>
Check out some of my social links!
</HomeLabel>
<IconContainer>
<IconLink href="https://t.me/@givfnz2" target="_blank" rel="noopener noreferrer">
<FontAwesomeIcon icon={faTelegram} size="3x" />
</IconLink>
<IconLink href="https://github.com/GiovaniFZ" target="_blank" rel="noopener noreferrer">
<FontAwesomeIcon icon={faGithub} size="3x" />
</IconLink>
</IconContainer>
</div>
);
}

20
src/pages/home/styles.ts Normal file
View File

@ -0,0 +1,20 @@
import styled from 'styled-components';
export const IconContainer = styled.div`
display: flex;
gap: 1rem;
margin-top: 1rem;
`;
export const IconLink = styled.a`
color: ${props => props.theme["light-cream"]};
transition: color 0.3s;
&:hover {
color: ${props => props.theme["cream"]};
}
`;
export const HomeLabel = styled.p`
margin-top: 1rem;
`;

View File

@ -1,3 +1,52 @@
export default function Projects(){ import { useEffect, useState } from 'react';
return <h1>Projects</h1> import {
Container,
Title,
ProjectGrid,
ProjectCard,
ProjectName,
ProjectDescription,
ProjectMeta,
ProjectLanguage,
ProjectStars,
} from './styles';
interface Repo {
name: string;
description: string;
stars: number;
language: string;
url: string;
}
export default function Projects() {
const [projects, setProjects] = useState<Repo[]>([]);
useEffect(() => {
async function loadProjects() {
const response = await fetch('/github.json');
const projects = await response.json();
setProjects(projects);
}
loadProjects();
}, []);
return (
<Container>
<Title>Projects</Title>
<ProjectGrid>
{projects.map((project) => (
<ProjectCard key={project.name} href={project.url} target="_blank" rel="noopener noreferrer">
<ProjectName>{project.name}</ProjectName>
<ProjectDescription>{project.description}</ProjectDescription>
<ProjectMeta>
<ProjectLanguage>{project.language}</ProjectLanguage>
<ProjectStars> {project.stars.toLocaleString()}</ProjectStars>
</ProjectMeta>
</ProjectCard>
))}
</ProjectGrid>
</Container>
);
} }

View File

@ -0,0 +1,59 @@
import styled from 'styled-components';
export const Container = styled.div`
padding: 2rem;
background-color: ${props => props.theme.background};
color: ${props => props.theme.text};
width: 100%; /* Ensure the container takes up the full width */
`;
export const Title = styled.h1`
font-size: 2.5rem;
margin-bottom: 2rem;
`;
export const ProjectGrid = styled.div`
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
width: 100%;
`;
export const ProjectCard = styled.a`
background: ${props => props.theme.cardBackground};
padding: 1.5rem;
border-radius: 8px;
text-decoration: none;
color: ${props => props.theme.cardText};
box-shadow: 0 4px 6px ${props => props.theme.cardShadow};
transition: transform 0.2s;
width: 100%;
&:hover {
transform: translateY(-5px);
}
`;
export const ProjectName = styled.h2`
font-size: 1.5rem;
margin-bottom: 0.5rem;
`;
export const ProjectDescription = styled.p`
font-size: 1rem;
margin-bottom: 1rem;
`;
export const ProjectMeta = styled.div`
display: flex;
justify-content: space-between;
font-size: 0.875rem;
`;
export const ProjectLanguage = styled.span`
font-weight: bold;
`;
export const ProjectStars = styled.span`
color: ${props => props.theme.highlight};
`;

View File

@ -1,26 +1,59 @@
import { createGlobalStyle } from "styled-components"; import { createGlobalStyle } from "styled-components";
export const GlobalStyle = createGlobalStyle` export const GlobalStyle = createGlobalStyle`
*{ *{
margin: 0; margin: 0;
padding: 0; padding: 0;
box-sizing: border-box; box-sizing: border-box;
} }
:focus{ :focus{
outline: 0; outline: 0;
box-shadow: 0 0 0 2px ${props => props.theme['green-500']} box-shadow: 0 0 0 2px #d4d4a1
} }
body{ body{
background-color: ${props => props.theme["gray-800"]}; background-color: ${props => props.theme["gray-800"]};
color: ${props => props.theme.white}; color: ${props => props.theme.white};
-webkit-font-smoothing: antialised; -webkit-font-smoothing: antialised;
padding: 1rem;
} }
body, input, textarea, button{ body, input, textarea, button{
font: 400 1rem Roboto, sans-serif; font: 400 1.25rem Roboto, sans-serif;
} }
h1 {
font-size: 2.5rem;
}
h2 {
font-size: 2rem;
}
h3 {
font-size: 1.75rem;
}
h4 {
font-size: 1.5rem;
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
font-size: 1.25rem;
}
.mc{
display: flex;
padding: 2rem;
padding-top: 3rem;
}
` `

View File

@ -1,21 +1,27 @@
export const defaultTheme = { export const defaultTheme = {
white: '#FFF', white: '#FFF',
black: '#000', black: '#000',
cardBackground: '#2C3534',
cardText: '#ffffff',
cardShadow: 'rgba(0, 0, 0, 0.5)',
highlight: '#ffcc00',
'green-100': '#34E0CC', 'green-100': '#34E0CC',
'green-200': '#3CB4A6', 'green-200': '#3CB4A6',
'green-300': '#458A82', 'green-300': '#458A82',
'green-400': '#3F5F5B', 'green-400': '#3F5F5B',
'green-500': '#2C3534', 'green-500': '#2C3534',
'green-600': '#080A0A', 'green-600': '#080A0A',
'gray-100': '#E1E1E6', 'gray-100': '#E1E1E6',
'gray-300': '#C4C4CC', 'gray-300': '#C4C4CC',
'gray-400': '#8D8D99', 'gray-400': '#8D8D99',
'gray-500': '#7C7C8A', 'gray-500': '#7C7C8A',
'gray-600': '#323238', 'gray-600': '#323238',
'gray-700': '#29292E', 'gray-700': '#29292E',
'gray-800': '#202024', 'gray-800': '#202024',
'gray-900': '#121214', 'gray-900': '#121214',
'cream': '#D4D4A1',
'light-cream': '#F5F5DC',
} }