Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48477d0e9b | ||
|
|
372bff77d0 | ||
|
|
1b8ca5c4da | ||
|
|
78c68efc00 | ||
|
|
9eeb3c5a7b | ||
|
|
44eeae2db3 | ||
|
|
cf1fef8020 | ||
|
|
4f7256da05 | ||
|
|
1c8cebc32b | ||
|
|
4aa5040ef5 | ||
|
|
00324b9667 | ||
|
|
48650c3574 | ||
|
|
2db154c6de | ||
|
|
3347df1e57 | ||
|
|
9943c5df56 | ||
|
|
9ba474fdcf | ||
|
|
a8ef619397 | ||
|
|
b01537fd7b | ||
|
|
eb33c666ec | ||
|
|
23b2ee0446 | ||
|
|
7a2df7fe14 | ||
|
|
6f247c37fd | ||
|
|
7c17607c27 | ||
|
|
623dc6f334 | ||
|
|
13751b5a44 | ||
|
|
43b2ea833b | ||
|
|
abbd6c1bb8 | ||
|
|
e107d0d99e | ||
|
|
559654aa9d | ||
|
|
0b28182458 | ||
|
|
abbdb6027c | ||
|
|
9f5d7a5c3a | ||
|
|
b5ffd5fa1e | ||
|
|
1abc9eeec2 | ||
|
|
dd65c86df2 | ||
|
|
4b6c5f1d8d | ||
|
|
10d993608f | ||
|
|
ac2b4bd4e3 | ||
|
|
af74add495 | ||
|
|
649bf84f1e |
File diff suppressed because one or more lines are too long
+24
@@ -0,0 +1,24 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
Vendored
+15
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Launch Chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "chrome",
|
||||||
|
"url": "http://localhost:3000",
|
||||||
|
"webRoot": "${workspaceFolder}/src"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"typescript.validate.enable": false,
|
||||||
|
"editor.formatOnSave": true
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Personal WebPage
|
||||||
|
|
||||||
|
This project is build with React and Material UI, and it holds a collection of projects, best practices, and technologies that I want to explore.
|
||||||
|
|
||||||
|
You can view it live [here](https://dadobos.github.io/me/).
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
#### First you have to clone the repository
|
||||||
|
|
||||||
|
<code>git clone https://github.com/dadobos/me.git</code>
|
||||||
|
|
||||||
|
#### In the project directory, you can run:
|
||||||
|
|
||||||
|
<code>npm run start</code> or just <code>npm start</code>
|
||||||
|
|
||||||
|
Runs the app in the development mode.\
|
||||||
|
Open [http://localhost:3000](http://localhost:3000/me) to view it in the browser.
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
{
|
|
||||||
"files": {
|
|
||||||
"main.js": "/me/static/js/main.01ab7636.js",
|
|
||||||
"static/js/937.dbf01c24.chunk.js": "/me/static/js/937.dbf01c24.chunk.js",
|
|
||||||
"static/js/241.d1c76bdc.chunk.js": "/me/static/js/241.d1c76bdc.chunk.js",
|
|
||||||
"static/js/434.5a130b80.chunk.js": "/me/static/js/434.5a130b80.chunk.js",
|
|
||||||
"static/js/563.55e2bd58.chunk.js": "/me/static/js/563.55e2bd58.chunk.js",
|
|
||||||
"static/js/992.123c4331.chunk.js": "/me/static/js/992.123c4331.chunk.js",
|
|
||||||
"static/js/488.a9182cb5.chunk.js": "/me/static/js/488.a9182cb5.chunk.js",
|
|
||||||
"static/js/771.edd76315.chunk.js": "/me/static/js/771.edd76315.chunk.js",
|
|
||||||
"static/js/579.d83302b8.chunk.js": "/me/static/js/579.d83302b8.chunk.js",
|
|
||||||
"index.html": "/me/index.html",
|
|
||||||
"main.01ab7636.js.map": "/me/static/js/main.01ab7636.js.map",
|
|
||||||
"937.dbf01c24.chunk.js.map": "/me/static/js/937.dbf01c24.chunk.js.map",
|
|
||||||
"241.d1c76bdc.chunk.js.map": "/me/static/js/241.d1c76bdc.chunk.js.map",
|
|
||||||
"434.5a130b80.chunk.js.map": "/me/static/js/434.5a130b80.chunk.js.map",
|
|
||||||
"563.55e2bd58.chunk.js.map": "/me/static/js/563.55e2bd58.chunk.js.map",
|
|
||||||
"992.123c4331.chunk.js.map": "/me/static/js/992.123c4331.chunk.js.map",
|
|
||||||
"488.a9182cb5.chunk.js.map": "/me/static/js/488.a9182cb5.chunk.js.map",
|
|
||||||
"771.edd76315.chunk.js.map": "/me/static/js/771.edd76315.chunk.js.map",
|
|
||||||
"579.d83302b8.chunk.js.map": "/me/static/js/579.d83302b8.chunk.js.map"
|
|
||||||
},
|
|
||||||
"entrypoints": [
|
|
||||||
"static/js/main.01ab7636.js"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<!doctype html><html lang="en" style="scroll-behavior:smooth"><head><meta charset="utf-8"/><link rel="icon" href="https://res.cloudinary.com/dadobos/image/upload/v1642766520/web/favicon_ugvc88.ico" type="image/x-icon"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="title" content="Dan Adobos — Personal Portfolio"><meta name="description" content="Personal portfolio of Dan Adobos — software engineer and front-end developer. Showcasing projects, open-source work, blog posts, and contact information."><link rel="manifest" href="/me/manifest.json"/><link rel="preconnect" href="https://fonts.googleapis.com"/><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/><link href="https://fonts.googleapis.com/css2?family=Chilanka&family=Lato:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&family=Nanum+Gothic+Coding:wght@400;700&family=Press+Start+2P&family=Roboto:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&family=Yeon+Sung&display=swap" rel="stylesheet"/><link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"/><title>DAD</title><script defer="defer" src="/me/static/js/main.01ab7636.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"jsx": "react",
|
||||||
|
"baseUrl": "src",
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es6"
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
Generated
+21031
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"name": "react-page",
|
||||||
|
"homepage": "https://dadobos.github.io/me/",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emotion/react": "^11.14.0",
|
||||||
|
"@emotion/styled": "^11.14.0",
|
||||||
|
"@mui/icons-material": "^6.5.0",
|
||||||
|
"@mui/material": "^6.5.0",
|
||||||
|
"@mui/styles": "^6.5.0",
|
||||||
|
"@testing-library/jest-dom": "^6.9.1",
|
||||||
|
"@testing-library/react": "^16.3.0",
|
||||||
|
"@testing-library/user-event": "^14.6.1",
|
||||||
|
"react": "^18.0.0",
|
||||||
|
"react-dom": "^18.0.0",
|
||||||
|
"react-intl": "^7.1.14",
|
||||||
|
"react-router-dom": "^7.9.4",
|
||||||
|
"react-scripts": "^5.0.1",
|
||||||
|
"react-spring": "^10.0.3",
|
||||||
|
"styled-components": "^6.1.11",
|
||||||
|
"vanilla-tilt": "^1.8.1",
|
||||||
|
"web-vitals": "^5.1.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "react-scripts start",
|
||||||
|
"build": "react-scripts build",
|
||||||
|
"test": "react-scripts test",
|
||||||
|
"eject": "react-scripts eject",
|
||||||
|
"predeploy": "npm run build",
|
||||||
|
"deploy": "gh-pages -d build"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"extends": [
|
||||||
|
"react-app",
|
||||||
|
"react-app/jest"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"browserslist": {
|
||||||
|
"production": [
|
||||||
|
">0.2%",
|
||||||
|
"not dead",
|
||||||
|
"not op_mini all"
|
||||||
|
],
|
||||||
|
"development": [
|
||||||
|
"last 1 chrome version",
|
||||||
|
"last 1 firefox version",
|
||||||
|
"last 1 safari version"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"gh-pages": "^6.1.1"
|
||||||
|
},
|
||||||
|
"description": "This project is build with React and Material UI, and it holds a collection of projects, best practices, and technologies that I want to explore.",
|
||||||
|
"main": "index.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/dadobos/me.git"
|
||||||
|
},
|
||||||
|
"author": "Dan Andrei Dobos",
|
||||||
|
"license": "ISC",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/dadobos/me/issues"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" style="scroll-behavior: smooth">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link
|
||||||
|
rel="icon"
|
||||||
|
href="https://res.cloudinary.com/dadobos/image/upload/v1642766520/web/favicon_ugvc88.ico"
|
||||||
|
type="image/x-icon"
|
||||||
|
/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<meta name="title" content="Dan Adobos — Personal Portfolio">
|
||||||
|
<meta name="description" content="Personal portfolio of Dan Adobos — software engineer and front-end developer. Showcasing projects, open-source work, blog posts, and contact information.">
|
||||||
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Chilanka&family=Lato:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&family=Nanum+Gothic+Coding:wght@400;700&family=Press+Start+2P&family=Roboto:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&family=Yeon+Sung&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://fonts.googleapis.com/icon?family=Material+Icons"
|
||||||
|
/>
|
||||||
|
<title>DAD</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
<!--
|
||||||
|
This HTML file is a template.
|
||||||
|
If you open it directly in the browser, you will see an empty page.
|
||||||
|
|
||||||
|
You can add webfonts, meta tags, or analytics to this file.
|
||||||
|
The build step will place the bundled scripts into the <body> tag.
|
||||||
|
|
||||||
|
To begin the development, run `npm start` or `yarn start`.
|
||||||
|
To create a production bundle, use `npm run build` or `yarn build`.
|
||||||
|
-->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+79
@@ -0,0 +1,79 @@
|
|||||||
|
import React, { useState, useMemo, createContext, useCallback } from "react";
|
||||||
|
import { BrowserRouter as Router } from "react-router-dom";
|
||||||
|
import { IntlProvider } from "react-intl";
|
||||||
|
|
||||||
|
import {
|
||||||
|
responsiveFontSizes,
|
||||||
|
ThemeProvider,
|
||||||
|
createTheme,
|
||||||
|
} from "@mui/material/styles";
|
||||||
|
import { getMainTheme } from "./themes/Theme";
|
||||||
|
import { CustomRoutes } from "./routes/Routes";
|
||||||
|
|
||||||
|
import messages from "./lang/index"; // new import
|
||||||
|
// import LanguageSwitcher from "./components/LanguageSwitcher"; // new small component
|
||||||
|
|
||||||
|
export const AppContext = createContext({
|
||||||
|
toggleColorMode: () => { },
|
||||||
|
locale: "en",
|
||||||
|
setLocale: () => { },
|
||||||
|
});
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
const [mode, setMode] = useState("dark");
|
||||||
|
|
||||||
|
const [localeState, setLocaleState] = useState(() => {
|
||||||
|
try {
|
||||||
|
const saved = localStorage.getItem("locale");
|
||||||
|
if (saved) return saved;
|
||||||
|
} catch (e) {
|
||||||
|
/* ignore (SSR or disabled storage) */
|
||||||
|
}
|
||||||
|
const nav = typeof navigator !== "undefined" ? navigator.language?.split("-")[0] : null;
|
||||||
|
return messages[nav] ? nav : "en";
|
||||||
|
});
|
||||||
|
|
||||||
|
const setLocale = useCallback((newLocale) => {
|
||||||
|
setLocaleState(newLocale);
|
||||||
|
try {
|
||||||
|
localStorage.setItem("locale", newLocale);
|
||||||
|
} catch (e) {
|
||||||
|
/* ignore write failures */
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const colorMode = useMemo(
|
||||||
|
() => ({
|
||||||
|
toggleColorMode: () => {
|
||||||
|
setMode((prevMode) => (prevMode === "light" ? "dark" : "light"));
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const contextValue = useMemo(
|
||||||
|
() => ({ ...colorMode, locale: localeState, setLocale }),
|
||||||
|
[colorMode, localeState, setLocale],
|
||||||
|
);
|
||||||
|
|
||||||
|
const theme = useMemo(
|
||||||
|
() => responsiveFontSizes(createTheme(getMainTheme(mode))),
|
||||||
|
[mode],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IntlProvider locale={localeState} messages={messages[localeState]} defaultLocale="en">
|
||||||
|
<AppContext.Provider value={contextValue}>
|
||||||
|
<ThemeProvider theme={theme}>
|
||||||
|
{/* quick language switcher; move or style as needed */}
|
||||||
|
{/* <LanguageSwitcher locale={localeState} setLocale={setLocale} /> */}
|
||||||
|
<Router basename={process.env.PUBLIC_URL}>
|
||||||
|
<CustomRoutes />
|
||||||
|
</Router>
|
||||||
|
</ThemeProvider>
|
||||||
|
</AppContext.Provider>
|
||||||
|
</IntlProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { render, screen } from "@testing-library/react";
|
||||||
|
import App from "./App";
|
||||||
|
|
||||||
|
test("renders learn react link", () => {
|
||||||
|
render(<App />);
|
||||||
|
const linkElement = screen.getByText(/learn react/i);
|
||||||
|
expect(linkElement).toBeInTheDocument();
|
||||||
|
});
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionSummary,
|
||||||
|
AccordionDetails,
|
||||||
|
Typography,
|
||||||
|
} from "@mui/material";
|
||||||
|
|
||||||
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||||
|
|
||||||
|
const BlogAccordion = ({ blogContent }) => {
|
||||||
|
// normalize blogContent to an array to avoid `map` errors
|
||||||
|
const items = Array.isArray(blogContent)
|
||||||
|
? blogContent
|
||||||
|
: blogContent
|
||||||
|
? [blogContent]
|
||||||
|
: [];
|
||||||
|
|
||||||
|
if (items.length === 0) return null;
|
||||||
|
|
||||||
|
return items.map(({ title, description }, itemIdx) => {
|
||||||
|
const lines = Array.isArray(description)
|
||||||
|
? description
|
||||||
|
: description
|
||||||
|
? [description]
|
||||||
|
: [];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Accordion key={title ?? itemIdx}>
|
||||||
|
<AccordionSummary
|
||||||
|
expandIcon={<ExpandMoreIcon />}
|
||||||
|
aria-controls={`panel-${itemIdx}-content`}
|
||||||
|
id={`panel-${itemIdx}-header`}>
|
||||||
|
<Typography variant="h5" component="h3">
|
||||||
|
{title}
|
||||||
|
</Typography>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
{lines.map((lineContent, idx) => (
|
||||||
|
<Typography
|
||||||
|
key={`${itemIdx}-${idx}`}
|
||||||
|
variant="subtitle1"
|
||||||
|
style={{ fontSize: "18px" }}
|
||||||
|
paragraph>
|
||||||
|
{lineContent}
|
||||||
|
</Typography>
|
||||||
|
))}
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BlogAccordion;
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
Grid2,
|
||||||
|
Accordion,
|
||||||
|
AccordionSummary,
|
||||||
|
AccordionDetails,
|
||||||
|
Typography,
|
||||||
|
} from "@mui/material";
|
||||||
|
import MainCard from "components/main-card/MainCard";
|
||||||
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||||
|
|
||||||
|
const MainAccordion = ({ items, title }) => {
|
||||||
|
return (
|
||||||
|
<Accordion
|
||||||
|
defaultExpanded
|
||||||
|
slotProps={{ transition: { unmountOnExit: true } }}>
|
||||||
|
<AccordionSummary
|
||||||
|
expandIcon={<ExpandMoreIcon />}
|
||||||
|
aria-controls="panel1a-content"
|
||||||
|
id="panel1a-header">
|
||||||
|
<Typography variant="h5" component="h3">
|
||||||
|
{title}
|
||||||
|
</Typography>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
<Grid2
|
||||||
|
container
|
||||||
|
direction="row"
|
||||||
|
alignItems="flex-start"
|
||||||
|
justifyContent="baseline"
|
||||||
|
spacing={3}>
|
||||||
|
{items.map((project) => (
|
||||||
|
<Grid2 key={project.key + project.title}>
|
||||||
|
<MainCard
|
||||||
|
imageURL={project.imageURL}
|
||||||
|
title={project.title}
|
||||||
|
description={project.description}
|
||||||
|
url={project.url}
|
||||||
|
/>
|
||||||
|
</Grid2>
|
||||||
|
))}
|
||||||
|
</Grid2>
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MainAccordion;
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardMedia,
|
||||||
|
CardActionArea,
|
||||||
|
Typography,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useTheme } from "@mui/material/styles";
|
||||||
|
|
||||||
|
import { Tilt } from "./Tilt";
|
||||||
|
|
||||||
|
const MainCard = ({ imageURL, title, description, url }) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
reverse: true,
|
||||||
|
speed: 1200,
|
||||||
|
easing: "cubic-bezier(.09,.67,.54,.76)",
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tilt
|
||||||
|
// style={{ padding: 0, margin: 0 }}
|
||||||
|
options={options}
|
||||||
|
children={
|
||||||
|
<Card
|
||||||
|
sx={{
|
||||||
|
minWidth: "320px",
|
||||||
|
maxWidth: "320px",
|
||||||
|
marginLeft: "auto",
|
||||||
|
marginRight: "auto",
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
backgroundColor: theme.palette.background.paper,
|
||||||
|
}}>
|
||||||
|
<CardMedia
|
||||||
|
component="img"
|
||||||
|
height="150"
|
||||||
|
image={imageURL}
|
||||||
|
alt={title}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Typography variant="body2">{description}</Typography>
|
||||||
|
|
||||||
|
<CardActionArea>
|
||||||
|
<CardContent
|
||||||
|
color="white"
|
||||||
|
onClick={() => window.open(url, "_blank")}>
|
||||||
|
<Typography gutterBottom variant="h6" component="h4">
|
||||||
|
{title}
|
||||||
|
</Typography>
|
||||||
|
</CardContent>
|
||||||
|
</CardActionArea>
|
||||||
|
</Card>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MainCard;
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import React, { useEffect, useRef } from "react";
|
||||||
|
|
||||||
|
import VanillaTilt from "vanilla-tilt";
|
||||||
|
|
||||||
|
export const Tilt = (props) => {
|
||||||
|
const { options, children } = props;
|
||||||
|
const tilt = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
VanillaTilt.init(tilt.current, options);
|
||||||
|
}, [options]);
|
||||||
|
|
||||||
|
return <div ref={tilt}>{children}</div>;
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./MainCard";
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
export const ReactData = [
|
||||||
|
{
|
||||||
|
imageURL:
|
||||||
|
"https://res.cloudinary.com/dadobos/image/upload/v1673023170/web/uxfuyzap5kbs1si34g29.png",
|
||||||
|
title: "Shop",
|
||||||
|
description: "",
|
||||||
|
url: "https://dadobos.github.io/react-shop/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imageURL:
|
||||||
|
"https://res.cloudinary.com/dadobos/image/upload/v1685729092/web/tzoxavfsfa44z2o9wrgi.png",
|
||||||
|
title: "Quiz App",
|
||||||
|
description: "",
|
||||||
|
url: "https://dadobos.github.io/react-quiz-app/",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const GoData = [
|
||||||
|
{
|
||||||
|
imageURL:
|
||||||
|
"https://res.cloudinary.com/dadobos/image/upload/v1669538934/web/ng0ghejmlsmzhrgyuiz4.png",
|
||||||
|
title: "Pokemon GO Templates",
|
||||||
|
description: "",
|
||||||
|
url: "https://github.com/dadobos/pokemongotemplates",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const WebsitesData = [
|
||||||
|
{
|
||||||
|
imageURL:
|
||||||
|
"https://res.cloudinary.com/dadobos/image/upload/v1653850879/web/TheSquareProject_sgflcj.png",
|
||||||
|
title: "The Square Project",
|
||||||
|
description: "",
|
||||||
|
url: "https://dadobos.github.io/The-Square-Project/",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const JavaData = [
|
||||||
|
{
|
||||||
|
imageURL:
|
||||||
|
"https://res.cloudinary.com/dadobos/image/upload/v1642766521/web/Restaurant_Billing_System_rgpsif.png",
|
||||||
|
title: "Restaurant Billing System",
|
||||||
|
description: "",
|
||||||
|
url: "https://github.com/dadobos/Restaurant",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imageURL:
|
||||||
|
"https://res.cloudinary.com/dadobos/image/upload/v1642766521/web/Billing_System_bazap1.png",
|
||||||
|
title: "Billing System",
|
||||||
|
description: "",
|
||||||
|
url: "https://github.com/dadobos/Billing-System",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const VueData = [
|
||||||
|
{
|
||||||
|
imageURL:
|
||||||
|
"https://res.cloudinary.com/dadobos/image/upload/v1654030260/web/WorldCountries_ekx2of.png",
|
||||||
|
title: "World Countries",
|
||||||
|
description: "",
|
||||||
|
url: "https://dadobos.github.io/worldcountries/",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const CSSData = [
|
||||||
|
{
|
||||||
|
imageURL:
|
||||||
|
"https://res.cloudinary.com/dadobos/image/upload/v1673027279/web/msvc649ua0gahqegu31o.png",
|
||||||
|
title: "Anchor Tag Hide Components",
|
||||||
|
description: "",
|
||||||
|
url: "https://codepen.io/diaid/full/MWOOogX",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imageURL:
|
||||||
|
"https://res.cloudinary.com/dadobos/image/upload/v1673027279/web/dprvsa15ocx3l34dxogo.png",
|
||||||
|
title: "Radio Hide Components",
|
||||||
|
description: "",
|
||||||
|
url: "https://codepen.io/diaid/full/qBVdgWW",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imageURL:
|
||||||
|
"https://res.cloudinary.com/dadobos/image/upload/v1673025125/web/anidcin5lbxo2hced5i4.png",
|
||||||
|
title: "Rounded Paragraph",
|
||||||
|
description: "",
|
||||||
|
url: "https://codepen.io/diaid/full/QWxOgVm",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imageURL:
|
||||||
|
"https://res.cloudinary.com/dadobos/image/upload/v1673027940/web/z9qn4wstdtzpr4cf5xtx.png",
|
||||||
|
title: "Responsive Table",
|
||||||
|
description: "",
|
||||||
|
url: "https://codepen.io/diaid/full/xxJRGMB",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const JSData = [
|
||||||
|
{
|
||||||
|
imageURL:
|
||||||
|
"https://res.cloudinary.com/dadobos/image/upload/v1761648607/web/ADOSIanaslkdfOASadkn.png",
|
||||||
|
title: "Vanilla TS/JS Carousel",
|
||||||
|
description: "",
|
||||||
|
url: "https://codepen.io/diaid/pen/GgoGwva",
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import React from "react";
|
||||||
|
import ReactDOM from "react-dom/client";
|
||||||
|
import App from "./App";
|
||||||
|
import reportWebVitals from "./reportWebVitals";
|
||||||
|
|
||||||
|
const root = ReactDOM.createRoot(document.getElementById("root"));
|
||||||
|
root.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>,
|
||||||
|
);
|
||||||
|
|
||||||
|
// If you want to start measuring performance in your app, pass a function
|
||||||
|
// to log results (for example: reportWebVitals(console.log))
|
||||||
|
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||||
|
reportWebVitals();
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"navigation.home": "home",
|
||||||
|
"navigation.projects": "Projects",
|
||||||
|
"navigation.best-practices": "Best Practices",
|
||||||
|
"navigation.blog": "Blog",
|
||||||
|
"navigation.about": "About",
|
||||||
|
"about.description.line1": "Simple, better.",
|
||||||
|
"blog.pantone.title": "Exploring Pantone Colors: A Journey Through Shades and Hues",
|
||||||
|
"blog.pantone.description.line1": "A Pantone color is a standardized, proprietary color created by the Pantone company, which assigns a unique code to each color. These colors are used in various industries to ensure color consistency across different materials and locations, as they provide a shared language for specifying and reproducing colors accurately. Pantone colors are often more vibrant and consistent than colors created with the standard CMYK or RGB color models.",
|
||||||
|
|
||||||
|
"blog.pantone.description.line2": "For 2025, the Pantone Color Institute selects PANTONE 17-1230 Mocha Mousse, a warming, brown hue imbued with richness. It nurtures us with its suggestion of the delectable qualities of chocolate and coffee, answering our desire for comfort.",
|
||||||
|
|
||||||
|
"blog.lighthouse.title": "How to achieve 100% on Lighthouse Audit",
|
||||||
|
"blog.lighthouse.description.line1": "Achieving a perfect score of 100% on a Lighthouse audit is a significant accomplishment that reflects a website's excellence in performance, accessibility, best practices, SEO, and progressive web app (PWA) standards. Lighthouse is an open-source tool developed by Google that helps developers improve the quality of their web pages by providing audits and recommendations across these key areas.",
|
||||||
|
"blog.lighthouse.description.line2": "The secret to achieving a perfect score of 100% on a Lighthouse audit lies in meticulous attention to detail and adherence to best practices across all evaluated categories. By optimizing performance through techniques such as lazy loading, minimizing render-blocking resources, and leveraging browser caching, you can significantly enhance page load times. Ensuring accessibility involves implementing semantic HTML, providing alternative text for images, and ensuring keyboard navigability. Following best practices includes using HTTPS, avoiding deprecated APIs, and ensuring responsive design. For SEO, optimizing meta tags, using descriptive URLs, and ensuring mobile-friendliness are crucial. Lastly, adhering to PWA standards by enabling service workers and providing a web app manifest can further boost the score. Continuous testing and iteration based on Lighthouse feedback are essential to maintain and improve the score over time."
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export { default as en } from "./en.json";
|
||||||
|
export { default as es } from "./nl.json";
|
||||||
|
|
||||||
|
const messages = {
|
||||||
|
en: require("./en.json"),
|
||||||
|
nl: require("./nl.json"),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default messages;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"navigation.home": "Startpagina",
|
||||||
|
"navigation.projects": "Projecten",
|
||||||
|
"navigation.best-practices": "Beste praktijken",
|
||||||
|
"navigation.blog": "Blog",
|
||||||
|
"navigation.about": "Over",
|
||||||
|
"about.description.line1": "Eenvoudig, beter.",
|
||||||
|
"blog.pantone.title": "Pantone-kleuren verkennen: een reis door tinten en nuances",
|
||||||
|
"blog.pantone.description.line1": "Een Pantone-kleur is een gestandaardiseerde, propriëtaire kleur die is ontwikkeld door het bedrijf Pantone, dat elke kleur een unieke code toekent. Deze kleuren worden in diverse sectoren gebruikt om kleurconsistentie te waarborgen over verschillende materialen en locaties, omdat ze een gemeenschappelijke taal bieden voor het nauwkeurig specificeren en reproduceren van kleuren. Pantone-kleuren zijn vaak levendiger en consistenter dan kleuren die met de standaard CMYK- of RGB-kleurmodellen worden gemaakt.",
|
||||||
|
|
||||||
|
"blog.pantone.description.line2": "Voor 2025 kiest het Pantone Color Institute PANTONE 17-1230 Mocha Mousse, een verwarmende bruine tint vol diepte. Hij omhult ons met zijn suggestie van de verrukkelijke eigenschappen van chocolade en koffie en spreekt onze behoefte aan troost aan.",
|
||||||
|
"blog.lighthouse.title": "Hoe 100% behalen op Lighthouse Audit",
|
||||||
|
"blog.lighthouse.description.line1": "Het behalen van een perfecte score van 100% op een Lighthouse-audit is een belangrijke prestatie die de uitmuntendheid van een website weerspiegelt op het gebied van prestaties, toegankelijkheid, best practices, SEO en progressive web app (PWA) standaarden. Lighthouse is een open-source tool ontwikkeld door Google die ontwikkelaars helpt de kwaliteit van hun webpagina's te verbeteren door audits en aanbevelingen te geven op deze belangrijke gebieden.",
|
||||||
|
"blog.lighthouse.description.line2": "Het geheim om een perfecte score van 100% te behalen op een Lighthouse-audit ligt in nauwgezette aandacht voor detail en het naleven van best practices in alle geëvalueerde categorieën. Door de prestaties te optimaliseren met technieken zoals lazy loading, het minimaliseren van render-blockerende bronnen en het benutten van browsercaching, kun je de laadtijden aanzienlijk verbeteren. Toegankelijkheid waarborgen betekent het implementeren van semantische HTML, alternatieve tekst voor afbeeldingen bieden en zorgen voor toetsenbordnavigatie. Best practices volgen omvat het gebruik van HTTPS, het vermijden van verouderde API's en het zorgen voor een responsief ontwerp. Voor SEO is het optimaliseren van metatags, het gebruiken van beschrijvende URL's en het waarborgen van mobielvriendelijkheid cruciaal. Tot slot kan het naleven van PWA-standaarden door service workers in te schakelen en een webapp-manifest te bieden de score verder verhogen. Voortdurend testen en itereren op basis van Lighthouse-feedback is essentieel om de score in de loop van de tijd te behouden en te verbeteren."
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { Grid, Grow, useScrollTrigger } from "@mui/material";
|
||||||
|
import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
|
||||||
|
import { useTheme } from "@mui/material/styles";
|
||||||
|
|
||||||
|
function ScrollTop(props) {
|
||||||
|
const { children, window } = props;
|
||||||
|
|
||||||
|
// Note that you normally won't need to set the window ref as useScrollTrigger
|
||||||
|
// will default to window.
|
||||||
|
// This is only being set here because the demo is in an iframe.
|
||||||
|
const trigger = useScrollTrigger({
|
||||||
|
target: window ? window() : undefined,
|
||||||
|
disableHysteresis: true,
|
||||||
|
threshold: 100,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleClick = (event) => {
|
||||||
|
const anchor = (event.target.ownerDocument || document).querySelector(
|
||||||
|
"#back-to-top-anchor",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (anchor) {
|
||||||
|
anchor.scrollIntoView({ behavior: "smooth", block: "center" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grow in={trigger}>
|
||||||
|
<div onClick={handleClick} role="presentation">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</Grow>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const BackToTop = (props) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
return (
|
||||||
|
<Grid
|
||||||
|
sx={{
|
||||||
|
position: "fixed",
|
||||||
|
bottom: theme.spacing(2),
|
||||||
|
left: theme.spacing(1),
|
||||||
|
}}
|
||||||
|
id="footer"
|
||||||
|
>
|
||||||
|
<ScrollTop {...props}>
|
||||||
|
<KeyboardArrowUpIcon
|
||||||
|
sx={{
|
||||||
|
width: "5rem",
|
||||||
|
height: "5rem",
|
||||||
|
[theme.breakpoints.down("md")]: { width: "3rem", height: "3rem" },
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ScrollTop>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default BackToTop;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./BackToTop";
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import React, { useContext } from "react";
|
||||||
|
import { IconButton } from "@mui/material";
|
||||||
|
import { useTheme } from "@mui/material/styles";
|
||||||
|
import { AppContext } from "App";
|
||||||
|
import WbSunnyOutlinedIcon from "@mui/icons-material/WbSunnyOutlined";
|
||||||
|
import NightsStayOutlinedIcon from "@mui/icons-material/NightsStayOutlined";
|
||||||
|
|
||||||
|
const DarkModeToggle = () => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IconButton
|
||||||
|
aria-label="Dark Mode Toggle"
|
||||||
|
onClick={appContext.toggleColorMode}
|
||||||
|
size="large"
|
||||||
|
sx={{
|
||||||
|
alignSelf: "right",
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
fontSize: "24px",
|
||||||
|
}}>
|
||||||
|
{theme.palette.mode === "dark" ? (
|
||||||
|
<WbSunnyOutlinedIcon />
|
||||||
|
) : (
|
||||||
|
<NightsStayOutlinedIcon />
|
||||||
|
)}
|
||||||
|
</IconButton>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DarkModeToggle;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./DarkModeToggle";
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Container } from "@mui/material";
|
||||||
|
|
||||||
|
const FullScreenContainer = (props) => {
|
||||||
|
const { children } = props;
|
||||||
|
// const theme = useTheme();
|
||||||
|
return (
|
||||||
|
<Container
|
||||||
|
maxWidth="lg"
|
||||||
|
sx={{
|
||||||
|
minHeight: "calc(100vh - 24px )",
|
||||||
|
paddingTop: "6rem",
|
||||||
|
paddingBottom: "2rem",
|
||||||
|
flex: 1,
|
||||||
|
fallbacks: [
|
||||||
|
{ minHeight: "-moz-calc(100% - 24px)" },
|
||||||
|
{ minHeight: "-webkit-calc(100% - 24px)" },
|
||||||
|
{ minHeight: "-o-calc(100% - 24px)" },
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FullScreenContainer;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./FullScreenContainer";
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { useScrollTrigger, Slide } from "@mui/material";
|
||||||
|
|
||||||
|
const HideOnScroll = (props) => {
|
||||||
|
const { children, window } = props;
|
||||||
|
const trigger = useScrollTrigger({
|
||||||
|
target: window ? window() : undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Slide appear={false} direction="down" in={!trigger}>
|
||||||
|
{children}
|
||||||
|
</Slide>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HideOnScroll;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./HideOnScroll.jsx";
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import React, { useContext } from "react";
|
||||||
|
import { AppContext } from "App";
|
||||||
|
import { useTheme } from "@mui/material/styles";
|
||||||
|
import { IconButton, Tooltip } from "@mui/material";
|
||||||
|
import Zoom from "@mui/material/Zoom";
|
||||||
|
|
||||||
|
// import { FormattedMessage } from "react-intl";
|
||||||
|
import LanguageOutlinedIcon from "@mui/icons-material/LanguageOutlined";
|
||||||
|
|
||||||
|
const LanguageSwitcher = () => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
const currentLocale = appContext && appContext.locale === "en" ? "NL" : "EN";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip
|
||||||
|
title={currentLocale}
|
||||||
|
disableInteractive
|
||||||
|
slots={{
|
||||||
|
transition: Zoom,
|
||||||
|
}}>
|
||||||
|
<span>
|
||||||
|
<IconButton
|
||||||
|
aria-label="Language Switcher"
|
||||||
|
onClick={() => {
|
||||||
|
const setLocale = appContext && appContext.setLocale;
|
||||||
|
if (typeof setLocale === "function") {
|
||||||
|
setLocale(appContext.locale === "en" ? "nl" : "en");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
size="large"
|
||||||
|
sx={{
|
||||||
|
alignSelf: "right",
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
fontSize: "24px",
|
||||||
|
}}>
|
||||||
|
{<LanguageOutlinedIcon />}
|
||||||
|
</IconButton>
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LanguageSwitcher;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./LanguageSwitcher";
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import React, { useContext } from "react";
|
||||||
|
|
||||||
|
import { ThemeProvider } from "@mui/material/styles";
|
||||||
|
|
||||||
|
import { AppContext } from "App";
|
||||||
|
import { getLandingWhite } from "themes/Theme";
|
||||||
|
import FullScreenContainer from "layouts/common/fullScreenContainer";
|
||||||
|
|
||||||
|
import BackToTop from "../common/backToTop";
|
||||||
|
import Header from "./components/header";
|
||||||
|
|
||||||
|
const LandingLayout = (props) => {
|
||||||
|
const { children } = props;
|
||||||
|
|
||||||
|
const colorMode = useContext(AppContext);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppContext.Provider value={colorMode}>
|
||||||
|
<ThemeProvider theme={getLandingWhite}>
|
||||||
|
<div id="back-to-top-anchor" />
|
||||||
|
<Header />
|
||||||
|
<FullScreenContainer>
|
||||||
|
{children}
|
||||||
|
<BackToTop />
|
||||||
|
</FullScreenContainer>
|
||||||
|
</ThemeProvider>
|
||||||
|
</AppContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LandingLayout;
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
import {
|
||||||
|
AppBar,
|
||||||
|
Toolbar,
|
||||||
|
CssBaseline,
|
||||||
|
Typography,
|
||||||
|
Breadcrumbs,
|
||||||
|
Link as MaterialLink,
|
||||||
|
IconButton,
|
||||||
|
Box,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useTheme } from "@mui/material/styles";
|
||||||
|
import ThreeSixtyIcon from "@mui/icons-material/ThreeSixtyOutlined";
|
||||||
|
|
||||||
|
import LanguageSwitcher from "layouts/common/languageSwitcher";
|
||||||
|
import DarkModeToggle from "layouts/common/darkModeToggle";
|
||||||
|
import HideOnScroll from "layouts/common/hideOnScroll";
|
||||||
|
|
||||||
|
const Header = () => {
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CssBaseline />
|
||||||
|
<HideOnScroll>
|
||||||
|
<AppBar
|
||||||
|
position="fixed"
|
||||||
|
component="nav"
|
||||||
|
sx={{
|
||||||
|
background: "transparent",
|
||||||
|
zIndex: 1301,
|
||||||
|
[theme.breakpoints.down("lg")]: {
|
||||||
|
backgroundColor: theme.palette.background.default,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
elevation={0}>
|
||||||
|
<Toolbar>
|
||||||
|
<Typography component="div" sx={{ flexGrow: 1, display: "block" }}>
|
||||||
|
<Breadcrumbs aria-label="breadcrumb">
|
||||||
|
<Typography
|
||||||
|
component="span"
|
||||||
|
sx={{
|
||||||
|
textTransform: "uppercase",
|
||||||
|
letterSpacing: ".2rem",
|
||||||
|
fontSize: "1.6rem",
|
||||||
|
}}>
|
||||||
|
Dan Dobos
|
||||||
|
</Typography>
|
||||||
|
{/*href="#about" is used to navigate within the page */}
|
||||||
|
<MaterialLink
|
||||||
|
color="textPrimary"
|
||||||
|
href="#about"
|
||||||
|
sx={{ cursor: "pointer" }}>
|
||||||
|
About
|
||||||
|
</MaterialLink>
|
||||||
|
</Breadcrumbs>
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Box sx={{ display: "block" }}>
|
||||||
|
<Link to="/projects">
|
||||||
|
<IconButton
|
||||||
|
aria-label="Projects"
|
||||||
|
size="large"
|
||||||
|
sx={{ color: theme.palette.text.secondary }}>
|
||||||
|
<ThreeSixtyIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Link>
|
||||||
|
<LanguageSwitcher />
|
||||||
|
<DarkModeToggle />
|
||||||
|
</Box>
|
||||||
|
</Toolbar>
|
||||||
|
</AppBar>
|
||||||
|
</HideOnScroll>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default Header;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./Header";
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./LandingLayout.jsx";
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import Header from "./components/header";
|
||||||
|
import Footer from "./components/footer";
|
||||||
|
import FullScreenContainer from "layouts/common/fullScreenContainer";
|
||||||
|
import BackToTop from "../common/backToTop";
|
||||||
|
|
||||||
|
const MainLayout = (props) => {
|
||||||
|
const { children } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div id="back-to-top-anchor" />
|
||||||
|
<Header />
|
||||||
|
<FullScreenContainer>
|
||||||
|
{children}
|
||||||
|
<BackToTop />
|
||||||
|
</FullScreenContainer>
|
||||||
|
<Footer />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MainLayout;
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Grid2, Typography } from "@mui/material";
|
||||||
|
|
||||||
|
const Footer = () => {
|
||||||
|
const getCurrentYear = () => {
|
||||||
|
return new Date().getFullYear();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid2
|
||||||
|
container
|
||||||
|
sx={{
|
||||||
|
marginTop: "auto",
|
||||||
|
zIndex: 1300,
|
||||||
|
minHeight: "24px",
|
||||||
|
}}
|
||||||
|
justifyContent="center">
|
||||||
|
<Grid2>
|
||||||
|
<Typography
|
||||||
|
inline="true"
|
||||||
|
variant="body1"
|
||||||
|
fontFamily="Nanum Gothic Coding">
|
||||||
|
Dan Dobos © {getCurrentYear()}
|
||||||
|
</Typography>
|
||||||
|
</Grid2>
|
||||||
|
</Grid2>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Footer;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./Footer";
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { AppBar, Toolbar, CssBaseline, Box } from "@mui/material";
|
||||||
|
|
||||||
|
import LanguageSwitcher from "layouts/common/languageSwitcher";
|
||||||
|
import DarkModeToggle from "layouts/common/darkModeToggle";
|
||||||
|
import HideOnScroll from "layouts/common/hideOnScroll";
|
||||||
|
import Navigation from "./navigation";
|
||||||
|
|
||||||
|
const Header = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CssBaseline />
|
||||||
|
<HideOnScroll>
|
||||||
|
<AppBar sx={{ position: "fixed", zIndex: 1301 }} elevation={0}>
|
||||||
|
<Toolbar>
|
||||||
|
<Navigation />
|
||||||
|
<Box sx={{ display: { sm: "inline-flex", xs: "none" } }}>
|
||||||
|
<LanguageSwitcher />
|
||||||
|
<DarkModeToggle />
|
||||||
|
</Box>
|
||||||
|
</Toolbar>
|
||||||
|
</AppBar>
|
||||||
|
</HideOnScroll>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default Header;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./Header";
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
import React, { useState, useEffect, createRef, useMemo, useRef } from "react";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import {
|
||||||
|
Container,
|
||||||
|
Tabs,
|
||||||
|
Tab,
|
||||||
|
useMediaQuery,
|
||||||
|
IconButton,
|
||||||
|
SwipeableDrawer,
|
||||||
|
Paper,
|
||||||
|
ListItem,
|
||||||
|
ListItemText,
|
||||||
|
List,
|
||||||
|
ListItemButton,
|
||||||
|
Box,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useTheme } from "@mui/material/styles";
|
||||||
|
import MenuIcon from "@mui/icons-material/Menu";
|
||||||
|
import MenuOpenIcon from "@mui/icons-material/MenuOpen";
|
||||||
|
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
import LanguageSwitcher from "layouts/common/languageSwitcher";
|
||||||
|
import DarkModeToggle from "layouts/common/darkModeToggle";
|
||||||
|
|
||||||
|
const Navigation = () => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const t = useIntl();
|
||||||
|
|
||||||
|
const matches = useMediaQuery(theme.breakpoints.down("sm"));
|
||||||
|
const iOS =
|
||||||
|
typeof navigator !== "undefined" &&
|
||||||
|
/iPad|iPhone|iPod/.test(navigator.userAgent);
|
||||||
|
|
||||||
|
const [value, setValue] = useState(1);
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
|
||||||
|
const tabsActions = useRef(null);
|
||||||
|
const wrapper = createRef();
|
||||||
|
|
||||||
|
const handleTabsChange = (e, newValue) => {
|
||||||
|
setValue(newValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDrawerClose = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
const routes = useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
name: t.formatMessage({
|
||||||
|
id: "navigation.home",
|
||||||
|
defaultMessage: "Home",
|
||||||
|
}),
|
||||||
|
link: "/",
|
||||||
|
activeIndex: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t.formatMessage({
|
||||||
|
id: "navigation.projects",
|
||||||
|
defaultMessage: "Projects",
|
||||||
|
}),
|
||||||
|
link: "/projects",
|
||||||
|
activeIndex: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t.formatMessage({
|
||||||
|
id: "navigation.best-practices",
|
||||||
|
defaultMessage: "Best Practices",
|
||||||
|
}),
|
||||||
|
link: "/best-practices",
|
||||||
|
activeIndex: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t.formatMessage({
|
||||||
|
id: "navigation.blog",
|
||||||
|
defaultMessage: "Blog",
|
||||||
|
}),
|
||||||
|
link: "/blog",
|
||||||
|
activeIndex: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t.formatMessage({
|
||||||
|
id: "navigation.about",
|
||||||
|
defaultMessage: "About",
|
||||||
|
}),
|
||||||
|
link: "/about",
|
||||||
|
activeIndex: 4,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[t]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
routes.forEach((route) => {
|
||||||
|
switch (window.location.pathname) {
|
||||||
|
case `${route.link}`:
|
||||||
|
if (value !== route.activeIndex) {
|
||||||
|
setValue(route.activeIndex);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [value, routes]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container ref={wrapper}>
|
||||||
|
<Paper
|
||||||
|
elevation={0}
|
||||||
|
sx={{
|
||||||
|
display: { sm: "none", xs: "flex" },
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
backgroundColor: "inherit",
|
||||||
|
color: theme.palette.secondary.contrastText,
|
||||||
|
boxShadow: "none",
|
||||||
|
}}>
|
||||||
|
<IconButton
|
||||||
|
size="large"
|
||||||
|
onClick={() => setOpenDrawer(!openDrawer)}
|
||||||
|
sx={{ color: theme.palette.text.secondary }}>
|
||||||
|
{openDrawer ? <MenuOpenIcon /> : <MenuIcon />}
|
||||||
|
</IconButton>
|
||||||
|
<Box sx={{ display: "inline-flex" }}>
|
||||||
|
<LanguageSwitcher />
|
||||||
|
<DarkModeToggle />
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
{matches ? (
|
||||||
|
<SwipeableDrawer
|
||||||
|
disableBackdropTransition={!iOS}
|
||||||
|
disableDiscovery={iOS}
|
||||||
|
disableSwipeToOpen={false}
|
||||||
|
open={openDrawer}
|
||||||
|
onOpen={() => setOpenDrawer(true)}
|
||||||
|
onClose={() => setOpenDrawer(false)}
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
}}>
|
||||||
|
<List sx={{ paddingTop: "4rem" }}>
|
||||||
|
{routes.map((route) => (
|
||||||
|
<ListItem
|
||||||
|
sx={{
|
||||||
|
// padding: "1.5rem 2rem ",
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
width: "100%",
|
||||||
|
"&.Mui-selected": {
|
||||||
|
backgroundColor: theme.palette.background.paper,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
key={`${route.activeIndex}`}
|
||||||
|
disablePadding>
|
||||||
|
<ListItemButton
|
||||||
|
component={Link}
|
||||||
|
to={route.link}
|
||||||
|
value={route.activeIndex}
|
||||||
|
selected={value === route.activeIndex}
|
||||||
|
onClick={() => {
|
||||||
|
setValue(route.activeIndex);
|
||||||
|
handleDrawerClose();
|
||||||
|
}}
|
||||||
|
sx={{ padding: "1.5rem 2rem" }}>
|
||||||
|
<ListItemText
|
||||||
|
disableTypography
|
||||||
|
sx={{
|
||||||
|
alignItems: "flex-start",
|
||||||
|
fontSize: "1.2rem",
|
||||||
|
textTransform: "capitalize",
|
||||||
|
}}>
|
||||||
|
{route.name}
|
||||||
|
</ListItemText>
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</SwipeableDrawer>
|
||||||
|
) : (
|
||||||
|
<Paper
|
||||||
|
elevation={0}
|
||||||
|
sx={{
|
||||||
|
display: { sm: "block", xs: "none" },
|
||||||
|
}}>
|
||||||
|
<Tabs
|
||||||
|
action={tabsActions}
|
||||||
|
value={value}
|
||||||
|
onChange={handleTabsChange}
|
||||||
|
centered
|
||||||
|
TabIndicatorProps={{
|
||||||
|
style: {
|
||||||
|
background: theme.palette.secondary.contrastText,
|
||||||
|
height: "3px",
|
||||||
|
},
|
||||||
|
}}>
|
||||||
|
{routes.map((route) => (
|
||||||
|
<Tab
|
||||||
|
disableRipple
|
||||||
|
key={`${route.activeIndex}`}
|
||||||
|
label={route.name}
|
||||||
|
component={Link}
|
||||||
|
to={route.link}
|
||||||
|
sx={{
|
||||||
|
fontSize: "1.2rem",
|
||||||
|
"&.Mui-selected": {
|
||||||
|
color: theme.palette.secondary.contrastText,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Tabs>
|
||||||
|
</Paper>
|
||||||
|
)}
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default Navigation;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./Navigation";
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./MainLayout";
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Container, Grid2, Typography, Link } from "@mui/material";
|
||||||
|
import { useTheme } from "@mui/material/styles";
|
||||||
|
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
const About = () => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const t = useIntl();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container id="about">
|
||||||
|
<Grid2
|
||||||
|
container
|
||||||
|
direction="row"
|
||||||
|
alignItems="stretch"
|
||||||
|
justifyContent="flex-end">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
minHeight: "70vh",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "flex-end",
|
||||||
|
}}>
|
||||||
|
<Grid2
|
||||||
|
container
|
||||||
|
direction="column"
|
||||||
|
alignItems="flex-end"
|
||||||
|
justifyContent="flex-end"
|
||||||
|
spacing={3}>
|
||||||
|
<Grid2>
|
||||||
|
<Typography align="right" inline="true" sx={{ fontSize: "32px" }}>
|
||||||
|
Software Developer
|
||||||
|
</Typography>
|
||||||
|
</Grid2>
|
||||||
|
<Grid2>
|
||||||
|
<Typography
|
||||||
|
variant="h1"
|
||||||
|
gutterBottom
|
||||||
|
inline="true"
|
||||||
|
sx={{
|
||||||
|
fontFamily: "Chilanka",
|
||||||
|
textTransform: "uppercase",
|
||||||
|
letterSpacing: "2rem",
|
||||||
|
textAlign: "left",
|
||||||
|
[theme.breakpoints.down("md")]: {
|
||||||
|
textAlign: "right",
|
||||||
|
letterSpacing: "1rem",
|
||||||
|
},
|
||||||
|
}}>
|
||||||
|
Dan Dobos
|
||||||
|
</Typography>
|
||||||
|
</Grid2>
|
||||||
|
|
||||||
|
<Grid2>
|
||||||
|
<Typography align="right" inline="true" sx={{ fontSize: "22px" }}>
|
||||||
|
{t.formatMessage({
|
||||||
|
id: "about.description.line1",
|
||||||
|
defaultMessage: "Simple, better.",
|
||||||
|
})}
|
||||||
|
</Typography>
|
||||||
|
</Grid2>
|
||||||
|
|
||||||
|
<Grid2>
|
||||||
|
<Typography align="right" inline="true">
|
||||||
|
Contact
|
||||||
|
</Typography>
|
||||||
|
<Link
|
||||||
|
variant="h6"
|
||||||
|
href="mailto:danandreidobos@gmail.com"
|
||||||
|
target="_blank"
|
||||||
|
color="inherit">
|
||||||
|
danandreidobos@gmail.com
|
||||||
|
</Link>
|
||||||
|
</Grid2>
|
||||||
|
</Grid2>
|
||||||
|
</div>
|
||||||
|
</Grid2>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default About;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./About";
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { CSSData, JSData } from "data/Data";
|
||||||
|
import MainAccordion from "components/main-accordion/MainAccordion";
|
||||||
|
|
||||||
|
const BestPractices = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<MainAccordion items={CSSData} title="CSS Only" />
|
||||||
|
<MainAccordion items={JSData} title="Vanilla JS/TS" />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BestPractices;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./BestPractices";
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
// import { BlogContent } from "data/Data";
|
||||||
|
|
||||||
|
import BlogAccordion from "components/blog-accordion/BlogAccordion";
|
||||||
|
|
||||||
|
const Blog = () => {
|
||||||
|
const t = useIntl();
|
||||||
|
return (
|
||||||
|
// <div style={{ minHeight: 'calc(100vh-128px)' }}>Blog ...in progress</div>
|
||||||
|
<>
|
||||||
|
<BlogAccordion
|
||||||
|
blogContent={{
|
||||||
|
title: t.formatMessage({ id: "blog.pantone.title" }),
|
||||||
|
description: [
|
||||||
|
t.formatMessage({ id: "blog.pantone.description.line1" }),
|
||||||
|
t.formatMessage({ id: "blog.pantone.description.line2" }),
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<BlogAccordion
|
||||||
|
blogContent={{
|
||||||
|
title: t.formatMessage({ id: "blog.lighthouse.title" }),
|
||||||
|
description: [
|
||||||
|
t.formatMessage({ id: "blog.lighthouse.description.line1" }),
|
||||||
|
t.formatMessage({ id: "blog.lighthouse.description.line2" }),
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Blog;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./Blog";
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Grid2, Typography, Divider } from "@mui/material";
|
||||||
|
import About from "../about";
|
||||||
|
import Blog from "../blog";
|
||||||
|
import BestPractices from "../best-practices";
|
||||||
|
import Projects from "../projects";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
const Home = () => {
|
||||||
|
const t = useIntl();
|
||||||
|
return (
|
||||||
|
<Grid2 container direction="column" alignItems="stretch">
|
||||||
|
<Grid2 container direction="column">
|
||||||
|
<Grid2>
|
||||||
|
<Typography
|
||||||
|
variant="h4"
|
||||||
|
component="h2"
|
||||||
|
marginTop={4}
|
||||||
|
marginBottom={2}>
|
||||||
|
{t.formatMessage({
|
||||||
|
id: "navigation.projects",
|
||||||
|
defaultMessage: "Projects",
|
||||||
|
})}
|
||||||
|
</Typography>
|
||||||
|
<Divider variant="inset" />
|
||||||
|
</Grid2>
|
||||||
|
<Grid2>
|
||||||
|
<Projects />
|
||||||
|
</Grid2>
|
||||||
|
</Grid2>
|
||||||
|
|
||||||
|
<Grid2 container direction="column">
|
||||||
|
<Grid2>
|
||||||
|
<Typography
|
||||||
|
variant="h4"
|
||||||
|
component="h2"
|
||||||
|
marginTop={4}
|
||||||
|
marginBottom={2}>
|
||||||
|
{t.formatMessage({
|
||||||
|
id: "navigation.best-practices",
|
||||||
|
defaultMessage: "Best Practices",
|
||||||
|
})}
|
||||||
|
</Typography>
|
||||||
|
<Divider variant="inset" />
|
||||||
|
</Grid2>
|
||||||
|
<Grid2>
|
||||||
|
<BestPractices />
|
||||||
|
</Grid2>
|
||||||
|
</Grid2>
|
||||||
|
|
||||||
|
<Grid2 container direction="column">
|
||||||
|
<Grid2>
|
||||||
|
<Typography
|
||||||
|
variant="h4"
|
||||||
|
component="h2"
|
||||||
|
marginTop={4}
|
||||||
|
marginBottom={2}>
|
||||||
|
{t.formatMessage({
|
||||||
|
id: "navigation.blog",
|
||||||
|
defaultMessage: "Blog",
|
||||||
|
})}
|
||||||
|
</Typography>
|
||||||
|
<Divider variant="inset" />
|
||||||
|
</Grid2>
|
||||||
|
<Grid2>
|
||||||
|
<Blog />
|
||||||
|
</Grid2>
|
||||||
|
</Grid2>
|
||||||
|
|
||||||
|
<Grid2 container justifyContent="flex-end">
|
||||||
|
<Grid2>
|
||||||
|
<About />
|
||||||
|
</Grid2>
|
||||||
|
</Grid2>
|
||||||
|
</Grid2>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Home;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./Landing";
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Box } from "@mui/material";
|
||||||
|
import {
|
||||||
|
// AngularData,
|
||||||
|
ReactData,
|
||||||
|
WebsitesData,
|
||||||
|
VueData,
|
||||||
|
GoData,
|
||||||
|
JavaData,
|
||||||
|
} from "data/Data";
|
||||||
|
import MainAccordion from "components/main-accordion/MainAccordion";
|
||||||
|
|
||||||
|
const Projects = () => {
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%", // added so children can take full width
|
||||||
|
alignItems: "stretch", // optional, ensures flex children stretch
|
||||||
|
}}>
|
||||||
|
<MainAccordion items={ReactData} title="React" />
|
||||||
|
<MainAccordion items={WebsitesData} title="HTML" />
|
||||||
|
<MainAccordion items={VueData} title="Vue" />
|
||||||
|
<MainAccordion items={GoData} title="Golang" />
|
||||||
|
<MainAccordion items={JavaData} title="Java" />
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Projects;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./Projects";
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
const reportWebVitals = (onPerfEntry) => {
|
||||||
|
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||||
|
import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||||
|
getCLS(onPerfEntry);
|
||||||
|
getFID(onPerfEntry);
|
||||||
|
getFCP(onPerfEntry);
|
||||||
|
getLCP(onPerfEntry);
|
||||||
|
getTTFB(onPerfEntry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default reportWebVitals;
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import React, { Suspense, lazy } from "react";
|
||||||
|
import { Routes, Route } from "react-router-dom";
|
||||||
|
import CircularProgress from "@mui/material/CircularProgress";
|
||||||
|
import ErrorBoundary from "./components/errorBoundary";
|
||||||
|
|
||||||
|
import MainLayout from "../layouts/main";
|
||||||
|
import LandingLayout from "../layouts/landing";
|
||||||
|
|
||||||
|
const Home = lazy(() => import("../pages/landing"));
|
||||||
|
const About = lazy(() => import("../pages/about"));
|
||||||
|
const Projects = lazy(() => import("../pages/projects"));
|
||||||
|
const Blog = lazy(() => import("../pages/blog"));
|
||||||
|
const BestPractices = lazy(() => import("../pages/best-practices"));
|
||||||
|
|
||||||
|
export const CustomRoutes = () => {
|
||||||
|
return (
|
||||||
|
<Suspense fallback={<CircularProgress color="secondary" />}>
|
||||||
|
<ErrorBoundary>
|
||||||
|
<Routes>
|
||||||
|
<Route
|
||||||
|
path="/"
|
||||||
|
element={
|
||||||
|
<LandingLayout>
|
||||||
|
<Home />
|
||||||
|
</LandingLayout>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Route
|
||||||
|
path="about"
|
||||||
|
element={
|
||||||
|
<MainLayout>
|
||||||
|
<About />
|
||||||
|
</MainLayout>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Route
|
||||||
|
path="projects"
|
||||||
|
element={
|
||||||
|
<MainLayout>
|
||||||
|
<Projects />
|
||||||
|
</MainLayout>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Route
|
||||||
|
path="blog"
|
||||||
|
element={
|
||||||
|
<MainLayout>
|
||||||
|
<Blog />
|
||||||
|
</MainLayout>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Route
|
||||||
|
path="best-practices"
|
||||||
|
element={
|
||||||
|
<MainLayout>
|
||||||
|
<BestPractices />
|
||||||
|
</MainLayout>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Routes>
|
||||||
|
</ErrorBoundary>
|
||||||
|
</Suspense>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// export default CustomRoutes;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// import React from 'react';
|
||||||
|
// import { Route } from 'react-router-dom';
|
||||||
|
|
||||||
|
// const Layout = ({ layout: Layout, component: Component }) => {
|
||||||
|
// return (
|
||||||
|
// <Layout>
|
||||||
|
// <Component />
|
||||||
|
// </Layout>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export default Layout;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./CustomRoute";
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import React, { Component } from "react";
|
||||||
|
|
||||||
|
class ErrorBoundary extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = { error: null, errorInfo: null };
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidCatch(error, errorInfo) {
|
||||||
|
// Catch errors in any components below and re-render with error message
|
||||||
|
this.setState({
|
||||||
|
error: error,
|
||||||
|
errorInfo: errorInfo,
|
||||||
|
});
|
||||||
|
// You can also log error messages to an error reporting service here
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.errorInfo) {
|
||||||
|
// Error path
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>Something went wrong.</h2>
|
||||||
|
<details sx={{ whiteSpace: "pre-wrap" }}>
|
||||||
|
{this.state.error && this.state.error.toString()}
|
||||||
|
<br />
|
||||||
|
{this.state.errorInfo.componentStack}
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Normally, just render children
|
||||||
|
return this.props.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ErrorBoundary;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./ErrorBoundary";
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
// export { default } from './Routes';
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||||
|
// allows you to do things like:
|
||||||
|
// expect(element).toHaveTextContent(/react/i)
|
||||||
|
// learn more: https://github.com/testing-library/jest-dom
|
||||||
|
import "@testing-library/jest-dom";
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
export const White = "#ffffff";
|
||||||
|
export const Magnolia = "#F3EFF5";
|
||||||
|
export const Celeste = "#CDFFF9";
|
||||||
|
export const Cultured = "#eceff1";
|
||||||
|
export const Platinum = "#E5E5E5";
|
||||||
|
export const ChartreuseTraditional = "#E4FF1A";
|
||||||
|
export const TeaGreen = "#CAE7B9";
|
||||||
|
export const GrannySmithApple = "#ADF6B1";
|
||||||
|
export const MaizeCrayola = "#E8C547";
|
||||||
|
export const Safron = "#EAC435";
|
||||||
|
export const Periwinkle = "#B7B5E4";
|
||||||
|
export const Mango = "#F7B801";
|
||||||
|
export const SeaGreenCrayola = "#0FFFC1";
|
||||||
|
export const WildBlueYonder = "#99B2DD";
|
||||||
|
export const Capri = "#5CC8FF";
|
||||||
|
export const TumbleWeed = "#CEA07E";
|
||||||
|
export const AcidGreen = "#BDBF09";
|
||||||
|
export const MangoTango = "#F5853F";
|
||||||
|
export const DarkOrange = "#FF8811";
|
||||||
|
export const MaximumBlue = "#42BFDD";
|
||||||
|
export const Grullo = "#A69888";
|
||||||
|
export const Citron = "#9EA93F";
|
||||||
|
export const BrandyPunch = "#ce8f28";
|
||||||
|
export const FruitSalad = "#509f60";
|
||||||
|
export const RussianGreen = "#678D58";
|
||||||
|
export const BrownSugar = "#B4654A";
|
||||||
|
export const Flame = "#cf5c36";
|
||||||
|
export const Pomegranate = "#f44336";
|
||||||
|
export const MiddleRedPurple = "#AF5D63";
|
||||||
|
export const IlluminatingEmerald = "#3E9276";
|
||||||
|
export const Cadet = "#5A7881";
|
||||||
|
export const EnglishVermillion = "#D64045";
|
||||||
|
export const AntiqueFuchsia = "#875C74";
|
||||||
|
export const SlimyGreen = "#2B9720";
|
||||||
|
export const PersianGreen = "#009688";
|
||||||
|
export const Cerise = "#D1345B";
|
||||||
|
export const InternationalGoldenGateBridge = "#BB4430";
|
||||||
|
export const ImperialRed = "#EF233C";
|
||||||
|
export const RedRYB = "#FF220C";
|
||||||
|
export const Ruby = "#D81E5B";
|
||||||
|
export const SpanishGreen = "#058E3F";
|
||||||
|
export const UARed = "#E01A4F";
|
||||||
|
export const Eggplant = "#75485E";
|
||||||
|
export const TwilightLavander = "#754668";
|
||||||
|
export const DavysGray = "#565656";
|
||||||
|
export const TucanRed = "#754043";
|
||||||
|
export const DeepSpaceSparkle = "#335C67";
|
||||||
|
export const VioletColorWheel = "#7E0FFF";
|
||||||
|
export const Spectra = "#315460";
|
||||||
|
export const Charcoal = "#37474f";
|
||||||
|
export const RubyRed = "#A31621";
|
||||||
|
export const BlueGreen = "#004d40";
|
||||||
|
export const OuterSpaceCrayola = "#22363C";
|
||||||
|
export const Rosewood = "#5E0B15";
|
||||||
|
export const DarkPurple = "#0F0326";
|
||||||
|
export const Black = "#000000";
|
||||||
|
//The Pantone Color of the Year 2025, PANTONE 17-1230 Mocha Mousse aka Chamoisee
|
||||||
|
export const Chamoisee = "#A47864";
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
import { createTheme, responsiveFontSizes } from "@mui/material/styles";
|
||||||
|
|
||||||
|
import overrides from "./overrides";
|
||||||
|
import {
|
||||||
|
AcidGreen,
|
||||||
|
Chamoisee,
|
||||||
|
Cultured,
|
||||||
|
DavysGray,
|
||||||
|
OuterSpaceCrayola,
|
||||||
|
SeaGreenCrayola,
|
||||||
|
VioletColorWheel,
|
||||||
|
White,
|
||||||
|
} from "./Colors";
|
||||||
|
|
||||||
|
// Main layout
|
||||||
|
export const getMainTheme = (mode) => ({
|
||||||
|
palette: {
|
||||||
|
mode,
|
||||||
|
...(mode === "light"
|
||||||
|
? {
|
||||||
|
// palette values for light mode
|
||||||
|
|
||||||
|
primary: {
|
||||||
|
main: Chamoisee,
|
||||||
|
contrastText: White,
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: White,
|
||||||
|
contrastText: White,
|
||||||
|
},
|
||||||
|
divider: Chamoisee,
|
||||||
|
background: {
|
||||||
|
default: Chamoisee,
|
||||||
|
paper: Chamoisee,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: White,
|
||||||
|
secondary: White,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
// palette values for dark mode
|
||||||
|
primary: {
|
||||||
|
main: OuterSpaceCrayola,
|
||||||
|
contrastText: AcidGreen,
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: AcidGreen,
|
||||||
|
contrastText: AcidGreen,
|
||||||
|
},
|
||||||
|
divider: AcidGreen,
|
||||||
|
background: {
|
||||||
|
default: OuterSpaceCrayola,
|
||||||
|
paper: OuterSpaceCrayola,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: Cultured,
|
||||||
|
secondary: Cultured,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
lightAccent: { main: VioletColorWheel },
|
||||||
|
darkAccent: { main: SeaGreenCrayola },
|
||||||
|
contrastThreshold: 3,
|
||||||
|
tonalOffset: 0.2,
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
...overrides,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Landing page
|
||||||
|
export const getLandingWhite = (theme) =>
|
||||||
|
responsiveFontSizes(
|
||||||
|
createTheme({
|
||||||
|
typography: {
|
||||||
|
fontFamily: "Yeon Sung",
|
||||||
|
transform: "matrix(1, 0, 0, 1, 0, 0)",
|
||||||
|
},
|
||||||
|
palette: {
|
||||||
|
mode: theme.palette.mode,
|
||||||
|
...(theme.palette.mode === "light"
|
||||||
|
? {
|
||||||
|
background: {
|
||||||
|
default: DavysGray,
|
||||||
|
paper: DavysGray,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: White,
|
||||||
|
secondary: White,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
...overrides,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
// export *from './Theme';
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { Pomegranate, BrandyPunch, White, Spectra, FruitSalad } from "../Theme";
|
||||||
|
|
||||||
|
const MuiAlert = {
|
||||||
|
root: {
|
||||||
|
fontSize: "16px",
|
||||||
|
borderRadius: 0,
|
||||||
|
},
|
||||||
|
standardError: {
|
||||||
|
color: White,
|
||||||
|
fontWeight: 300,
|
||||||
|
backgroundColor: Pomegranate,
|
||||||
|
},
|
||||||
|
standardWarning: {
|
||||||
|
color: White,
|
||||||
|
fontWeight: 300,
|
||||||
|
backgroundColor: BrandyPunch,
|
||||||
|
},
|
||||||
|
standardInfo: {
|
||||||
|
color: White,
|
||||||
|
fontWeight: 300,
|
||||||
|
backgroundColor: Spectra,
|
||||||
|
},
|
||||||
|
standardSuccess: {
|
||||||
|
color: White,
|
||||||
|
fontWeight: 300,
|
||||||
|
backgroundColor: FruitSalad,
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
display: "flex",
|
||||||
|
opacity: 1,
|
||||||
|
fontsize: "16px",
|
||||||
|
marginLeft: "3rem",
|
||||||
|
marginRight: "1rem",
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
padding: "16px 0 8px 0",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default MuiAlert;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
const MuiButtonBase = {
|
||||||
|
defaultProps: {
|
||||||
|
// The props to change the default for.
|
||||||
|
disableRipple: true, // No more ripple, on the whole application 💣!
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MuiButtonBase;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
const MuiCard = {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
// maxWidth: '420px',
|
||||||
|
// marginLeft: 'auto',
|
||||||
|
// marginRight: 'auto',
|
||||||
|
// '&:hover': {
|
||||||
|
// transition: 'all .7s ease',
|
||||||
|
// boxShadow: '1px 1px 20px 10px rgba(15,255,193,0.75)',
|
||||||
|
// },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MuiCard;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
const MuiCardActionArea = {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
"@media (min-width: 900px)": {
|
||||||
|
filter: "grayscale(1);",
|
||||||
|
"&:hover": {
|
||||||
|
filter: "grayscale(0);",
|
||||||
|
transition: "all .3s ease",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MuiCardActionArea;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Cultured, Charcoal } from "../Theme";
|
||||||
|
|
||||||
|
const MuiInputBase = {
|
||||||
|
input: {
|
||||||
|
height: "1.3rem",
|
||||||
|
"&:disabled": {
|
||||||
|
background: Cultured,
|
||||||
|
color: Charcoal,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default MuiInputBase;
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { RussianGreen } from "../Theme";
|
||||||
|
|
||||||
|
const MuiMenuItem = {
|
||||||
|
root: {
|
||||||
|
// fontFamily: 'Poppins',
|
||||||
|
fontSize: "14px",
|
||||||
|
lineHeight: "19px",
|
||||||
|
textAlign: "left",
|
||||||
|
color: RussianGreen,
|
||||||
|
padding: ".5rem",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default MuiMenuItem;
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { RussianGreen, Cultured, Charcoal, White, Platinum } from "../Theme";
|
||||||
|
|
||||||
|
const MuiOutlinedInput = {
|
||||||
|
root: {
|
||||||
|
position: "relative",
|
||||||
|
"&:hover:not($disabled):not($focused):not($error) $notchedOutline": {
|
||||||
|
border: `1px solid ${RussianGreen}`,
|
||||||
|
|
||||||
|
// Reset on touch devices, it doesn't add specificity
|
||||||
|
"@media (hover: none)": {
|
||||||
|
borderColor: RussianGreen,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// border focused
|
||||||
|
"&$focused $notchedOutline": {
|
||||||
|
borderColor: RussianGreen,
|
||||||
|
},
|
||||||
|
"&$disabled $notchedOutline": {
|
||||||
|
background: Cultured,
|
||||||
|
borderColor: Platinum,
|
||||||
|
opacity: 0.8,
|
||||||
|
color: Charcoal,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
//border before
|
||||||
|
notchedOutline: {
|
||||||
|
borderColor: Cultured,
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
background: White,
|
||||||
|
padding: ".5rem",
|
||||||
|
borderRadius: "3px",
|
||||||
|
fontFamily: "Poppins",
|
||||||
|
fontSize: " 14px",
|
||||||
|
lineHeight: "19px",
|
||||||
|
color: Charcoal,
|
||||||
|
|
||||||
|
"&:disabled": {
|
||||||
|
background: Cultured,
|
||||||
|
opacity: 0.8,
|
||||||
|
color: Charcoal,
|
||||||
|
},
|
||||||
|
notchedOutline: {
|
||||||
|
border: "transparent",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
multiline: {
|
||||||
|
padding: ".5rem !important",
|
||||||
|
border: "0px",
|
||||||
|
margin: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default MuiOutlinedInput;
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import { BlueGreen, RussianGreen, Cultured, Charcoal, White } from "../Theme";
|
||||||
|
|
||||||
|
const MuiSelect = {
|
||||||
|
root: {
|
||||||
|
background: White,
|
||||||
|
padding: ".5rem",
|
||||||
|
borderRadius: "3px",
|
||||||
|
fontFamily: "Poppins",
|
||||||
|
fontSize: "14px",
|
||||||
|
lineHeight: "19px",
|
||||||
|
textAlign: "left",
|
||||||
|
color: Charcoal,
|
||||||
|
border: `1px solid ${Cultured}`,
|
||||||
|
"&:focus": {
|
||||||
|
borderRadius: "3px",
|
||||||
|
borderColor: "transparent",
|
||||||
|
background: White,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
minWidth: "5.5rem",
|
||||||
|
borderRadius: "3px",
|
||||||
|
border: `1px solid ${RussianGreen}`,
|
||||||
|
fontSize: "16px",
|
||||||
|
lineHeight: "19px",
|
||||||
|
"&:focus": {
|
||||||
|
borderRadius: "3px",
|
||||||
|
borderColor: RussianGreen,
|
||||||
|
background: White,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
selectMenu: {
|
||||||
|
background: White,
|
||||||
|
color: RussianGreen,
|
||||||
|
"&:notchedOutline": {
|
||||||
|
borderColor: "transparent !important",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
outlined: {
|
||||||
|
color: `${Charcoal} !important`,
|
||||||
|
borderColor: "transparent",
|
||||||
|
fontSize: "14px",
|
||||||
|
lineHeight: "19px",
|
||||||
|
"&:hover ": {
|
||||||
|
borderColor: "transparent",
|
||||||
|
outline: "none",
|
||||||
|
},
|
||||||
|
"&:focus": {
|
||||||
|
background: White,
|
||||||
|
borderColor: "transparent",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
iconOutlined: {
|
||||||
|
color: BlueGreen,
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
color: RussianGreen,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MuiSelect;
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { BlueGreen, Cultured, Charcoal } from "../Theme";
|
||||||
|
|
||||||
|
const MuiSwitch = {
|
||||||
|
root: {
|
||||||
|
overflow: "visible",
|
||||||
|
width: "4rem",
|
||||||
|
},
|
||||||
|
switchBase: {
|
||||||
|
background: "transparent",
|
||||||
|
"&$checked": {
|
||||||
|
transform: "translateX(26px)",
|
||||||
|
"&$checked + $track": {
|
||||||
|
backgroundColor: Cultured,
|
||||||
|
border: "none",
|
||||||
|
boxShadow: "none",
|
||||||
|
width: 36,
|
||||||
|
},
|
||||||
|
"& $thumb": {
|
||||||
|
backgroundColor: BlueGreen,
|
||||||
|
boxShadow: "0px 2px 5px rgba(0, 0, 0, 0.25)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
thumb: {
|
||||||
|
backgroundColor: Charcoal,
|
||||||
|
boxShadow: "0px 2px 5px rgba(0, 0, 0, 0.25)",
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
},
|
||||||
|
track: { backgroundColor: Cultured, width: 36 },
|
||||||
|
checked: {},
|
||||||
|
};
|
||||||
|
export default MuiSwitch;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import MuiCard from "./MuiCard";
|
||||||
|
import MuiCardActionArea from "./MuiCardActionArea";
|
||||||
|
import MuiButtonBase from "./MuiButtonBase";
|
||||||
|
// import MuiAlert from './MuiAlert';
|
||||||
|
// import MuiInputBase from './MuiInputBase';
|
||||||
|
// import MuiMenuItem from './MuiMenuItem';
|
||||||
|
// import MuiOutlinedInput from './MuiOutlinedInput';
|
||||||
|
// import MuiSelect from './MuiSelect';
|
||||||
|
// import MuiSwitch from './MuiSwitch';
|
||||||
|
|
||||||
|
/* eslint import/no-anonymous-default-export: [2, {"allowObject": true}] */
|
||||||
|
export default {
|
||||||
|
MuiCard,
|
||||||
|
MuiCardActionArea,
|
||||||
|
MuiButtonBase,
|
||||||
|
// MuiAlert,
|
||||||
|
// MuiInputBase,
|
||||||
|
// MuiMenuItem,
|
||||||
|
// MuiOutlinedInput,
|
||||||
|
// MuiSelect,
|
||||||
|
// MuiSwitch,
|
||||||
|
};
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
"use strict";(self.webpackChunkreact_page=self.webpackChunkreact_page||[]).push([[241],{1241:(e,n,i)=>{i.r(n),i.d(n,{default:()=>d});i(5043);var t=i(9252),r=i(766),l=i(4496),a=i(8446),s=i(6240),o=i(97),c=i(579);const d=()=>{const e=(0,s.A)(),n=(0,o.A)();return(0,c.jsx)(t.A,{id:"about",children:(0,c.jsx)(r.A,{container:!0,direction:"row",alignItems:"stretch",justifyContent:"flex-end",children:(0,c.jsx)("div",{style:{minHeight:"70vh",display:"flex",alignItems:"flex-end"},children:(0,c.jsxs)(r.A,{container:!0,direction:"column",alignItems:"flex-end",justifyContent:"flex-end",spacing:3,children:[(0,c.jsx)(r.A,{children:(0,c.jsx)(l.A,{align:"right",inline:"true",sx:{fontSize:"32px"},children:"Software Developer"})}),(0,c.jsx)(r.A,{children:(0,c.jsx)(l.A,{variant:"h1",gutterBottom:!0,inline:"true",sx:{fontFamily:"Chilanka",textTransform:"uppercase",letterSpacing:"2rem",textAlign:"left",[e.breakpoints.down("md")]:{textAlign:"right",letterSpacing:"1rem"}},children:"Dan Dobos"})}),(0,c.jsx)(r.A,{children:(0,c.jsx)(l.A,{align:"right",inline:"true",sx:{fontSize:"22px"},children:n.formatMessage({id:"about.description.line1",defaultMessage:"Simple, better."})})}),(0,c.jsxs)(r.A,{children:[(0,c.jsx)(l.A,{align:"right",inline:"true",children:"Contact"}),(0,c.jsx)(a.A,{variant:"h6",href:"mailto:danandreidobos@gmail.com",target:"_blank",color:"inherit",children:"danandreidobos@gmail.com"})]})]})})})})}}}]);
|
|
||||||
//# sourceMappingURL=241.d1c76bdc.chunk.js.map
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"static/js/241.d1c76bdc.chunk.js","mappings":"mNAMA,MA2EA,EA3EcA,KACb,MAAMC,GAAQC,EAAAA,EAAAA,KACRC,GAAIC,EAAAA,EAAAA,KAEV,OACCC,EAAAA,EAAAA,KAACC,EAAAA,EAAS,CAACC,GAAG,QAAOC,UACpBH,EAAAA,EAAAA,KAACI,EAAAA,EAAK,CACLC,WAAS,EACTC,UAAU,MACVC,WAAW,UACXC,eAAe,WAAUL,UACzBH,EAAAA,EAAAA,KAAA,OACCS,MAAO,CACNC,UAAW,OACXC,QAAS,OACTJ,WAAY,YACXJ,UACFS,EAAAA,EAAAA,MAACR,EAAAA,EAAK,CACLC,WAAS,EACTC,UAAU,SACVC,WAAW,WACXC,eAAe,WACfK,QAAS,EAAEV,SAAA,EACXH,EAAAA,EAAAA,KAACI,EAAAA,EAAK,CAAAD,UACLH,EAAAA,EAAAA,KAACc,EAAAA,EAAU,CAACC,MAAM,QAAQC,OAAO,OAAOC,GAAI,CAAEC,SAAU,QAASf,SAAC,0BAInEH,EAAAA,EAAAA,KAACI,EAAAA,EAAK,CAAAD,UACLH,EAAAA,EAAAA,KAACc,EAAAA,EAAU,CACVK,QAAQ,KACRC,cAAY,EACZJ,OAAO,OACPC,GAAI,CACHI,WAAY,WACZC,cAAe,YACfC,cAAe,OACfC,UAAW,OACX,CAAC5B,EAAM6B,YAAYC,KAAK,OAAQ,CAC/BF,UAAW,QACXD,cAAe,SAEfpB,SAAC,iBAKLH,EAAAA,EAAAA,KAACI,EAAAA,EAAK,CAAAD,UACLH,EAAAA,EAAAA,KAACc,EAAAA,EAAU,CAACC,MAAM,QAAQC,OAAO,OAAOC,GAAI,CAAEC,SAAU,QAASf,SAC/DL,EAAE6B,cAAc,CAChBzB,GAAI,0BACJ0B,eAAgB,yBAKnBhB,EAAAA,EAAAA,MAACR,EAAAA,EAAK,CAAAD,SAAA,EACLH,EAAAA,EAAAA,KAACc,EAAAA,EAAU,CAACC,MAAM,QAAQC,OAAO,OAAMb,SAAC,aAGxCH,EAAAA,EAAAA,KAAC6B,EAAAA,EAAI,CACJV,QAAQ,KACRW,KAAK,kCACLC,OAAO,SACPC,MAAM,UAAS7B,SAAC,yC","sources":["pages/about/About.jsx"],"sourcesContent":["import React from \"react\";\nimport { Container, Grid2, Typography, Link } from \"@mui/material\";\nimport { useTheme } from \"@mui/material/styles\";\n\nimport { useIntl } from \"react-intl\";\n\nconst About = () => {\n\tconst theme = useTheme();\n\tconst t = useIntl();\n\n\treturn (\n\t\t<Container id=\"about\">\n\t\t\t<Grid2\n\t\t\t\tcontainer\n\t\t\t\tdirection=\"row\"\n\t\t\t\talignItems=\"stretch\"\n\t\t\t\tjustifyContent=\"flex-end\">\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tminHeight: \"70vh\",\n\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\talignItems: \"flex-end\",\n\t\t\t\t\t}}>\n\t\t\t\t\t<Grid2\n\t\t\t\t\t\tcontainer\n\t\t\t\t\t\tdirection=\"column\"\n\t\t\t\t\t\talignItems=\"flex-end\"\n\t\t\t\t\t\tjustifyContent=\"flex-end\"\n\t\t\t\t\t\tspacing={3}>\n\t\t\t\t\t\t<Grid2>\n\t\t\t\t\t\t\t<Typography align=\"right\" inline=\"true\" sx={{ fontSize: \"32px\" }}>\n\t\t\t\t\t\t\t\tSoftware Developer\n\t\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t</Grid2>\n\t\t\t\t\t\t<Grid2>\n\t\t\t\t\t\t\t<Typography\n\t\t\t\t\t\t\t\tvariant=\"h1\"\n\t\t\t\t\t\t\t\tgutterBottom\n\t\t\t\t\t\t\t\tinline=\"true\"\n\t\t\t\t\t\t\t\tsx={{\n\t\t\t\t\t\t\t\t\tfontFamily: \"Chilanka\",\n\t\t\t\t\t\t\t\t\ttextTransform: \"uppercase\",\n\t\t\t\t\t\t\t\t\tletterSpacing: \"2rem\",\n\t\t\t\t\t\t\t\t\ttextAlign: \"left\",\n\t\t\t\t\t\t\t\t\t[theme.breakpoints.down(\"md\")]: {\n\t\t\t\t\t\t\t\t\t\ttextAlign: \"right\",\n\t\t\t\t\t\t\t\t\t\tletterSpacing: \"1rem\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t}}>\n\t\t\t\t\t\t\t\tDan Dobos\n\t\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t</Grid2>\n\n\t\t\t\t\t\t<Grid2>\n\t\t\t\t\t\t\t<Typography align=\"right\" inline=\"true\" sx={{ fontSize: \"22px\" }}>\n\t\t\t\t\t\t\t\t{t.formatMessage({\n\t\t\t\t\t\t\t\t\tid: \"about.description.line1\",\n\t\t\t\t\t\t\t\t\tdefaultMessage: \"Simple, better.\",\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t</Grid2>\n\n\t\t\t\t\t\t<Grid2>\n\t\t\t\t\t\t\t<Typography align=\"right\" inline=\"true\">\n\t\t\t\t\t\t\t\tContact\n\t\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tvariant=\"h6\"\n\t\t\t\t\t\t\t\thref=\"mailto:danandreidobos@gmail.com\"\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\tcolor=\"inherit\">\n\t\t\t\t\t\t\t\tdanandreidobos@gmail.com\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</Grid2>\n\t\t\t\t\t</Grid2>\n\t\t\t\t</div>\n\t\t\t</Grid2>\n\t\t</Container>\n\t);\n};\n\nexport default About;\n"],"names":["About","theme","useTheme","t","useIntl","_jsx","Container","id","children","Grid2","container","direction","alignItems","justifyContent","style","minHeight","display","_jsxs","spacing","Typography","align","inline","sx","fontSize","variant","gutterBottom","fontFamily","textTransform","letterSpacing","textAlign","breakpoints","down","formatMessage","defaultMessage","Link","href","target","color"],"sourceRoot":""}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
"use strict";(self.webpackChunkreact_page=self.webpackChunkreact_page||[]).push([[434],{3434:(e,t,i)=>{i.r(t),i.d(t,{default:()=>d});i(5043);var o=i(7353),a=i(9975),s=i(6322),n=i(579);const d=()=>(0,n.jsxs)(o.A,{sx:{display:"flex",flexDirection:"column",width:"100%",alignItems:"stretch"},children:[(0,n.jsx)(s.A,{items:a.c3,title:"React"}),(0,n.jsx)(s.A,{items:a.b8,title:"HTML"}),(0,n.jsx)(s.A,{items:a.ri,title:"Vue"}),(0,n.jsx)(s.A,{items:a.dX,title:"Golang"}),(0,n.jsx)(s.A,{items:a.Pz,title:"Java"})]})},6322:(e,t,i)=>{i.d(t,{A:()=>f});var o=i(5043),a=i(3766),s=i(6605),n=i(4496),d=i(710),r=i(766),l=i(2110),p=i(6591),c=i(2828),u=i(6494),g=i(6240),m=i(9368),h=i.n(m),b=i(579);const x=e=>{const{options:t,children:i}=e,a=(0,o.useRef)(null);return(0,o.useEffect)(()=>{h().init(a.current,t)},[t]),(0,b.jsx)("div",{ref:a,children:i})},j=e=>{let{imageURL:t,title:i,description:o,url:a}=e;const s=(0,g.A)();return(0,b.jsx)(x,{options:{reverse:!0,speed:1200,easing:"cubic-bezier(.09,.67,.54,.76)"},children:(0,b.jsxs)(l.A,{sx:{minWidth:"320px",maxWidth:"320px",marginLeft:"auto",marginRight:"auto",color:s.palette.text.secondary,backgroundColor:s.palette.background.paper},children:[(0,b.jsx)(p.A,{component:"img",height:"150",image:t,alt:i}),(0,b.jsx)(n.A,{variant:"body2",children:o}),(0,b.jsx)(c.A,{children:(0,b.jsx)(u.A,{color:"white",onClick:()=>window.open(a,"_blank"),children:(0,b.jsx)(n.A,{gutterBottom:!0,variant:"h6",component:"h4",children:i})})})]})})};var v=i(8293);const f=e=>{let{items:t,title:i}=e;return(0,b.jsxs)(a.A,{defaultExpanded:!0,slotProps:{transition:{unmountOnExit:!0}},children:[(0,b.jsx)(s.A,{expandIcon:(0,b.jsx)(v.A,{}),"aria-controls":"panel1a-content",id:"panel1a-header",children:(0,b.jsx)(n.A,{variant:"h5",component:"h3",children:i})}),(0,b.jsx)(d.A,{children:(0,b.jsx)(r.A,{container:!0,direction:"row",alignItems:"flex-start",justifyContent:"baseline",spacing:3,children:t.map(e=>(0,b.jsx)(r.A,{children:(0,b.jsx)(j,{imageURL:e.imageURL,title:e.title,description:e.description,url:e.url})},e.key+e.title))})})]})}},9975:(e,t,i)=>{i.d(t,{E:()=>l,Iz:()=>r,Pz:()=>n,b8:()=>s,c3:()=>o,dX:()=>a,ri:()=>d});const o=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1673023170/web/uxfuyzap5kbs1si34g29.png",title:"Shop",description:"",url:"https://dadobos.github.io/react-shop/"},{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1685729092/web/tzoxavfsfa44z2o9wrgi.png",title:"Quiz App",description:"",url:"https://dadobos.github.io/react-quiz-app/"}],a=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1669538934/web/ng0ghejmlsmzhrgyuiz4.png",title:"Pokemon GO Templates",description:"",url:"https://github.com/dadobos/pokemongotemplates"}],s=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1653850879/web/TheSquareProject_sgflcj.png",title:"The Square Project",description:"",url:"https://dadobos.github.io/The-Square-Project/"}],n=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1642766521/web/Restaurant_Billing_System_rgpsif.png",title:"Restaurant Billing System",description:"",url:"https://github.com/dadobos/Restaurant"},{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1642766521/web/Billing_System_bazap1.png",title:"Billing System",description:"",url:"https://github.com/dadobos/Billing-System"}],d=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1654030260/web/WorldCountries_ekx2of.png",title:"World Countries",description:"",url:"https://dadobos.github.io/worldcountries/"}],r=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1673027279/web/msvc649ua0gahqegu31o.png",title:"Anchor Tag Hide Components",description:"",url:"https://codepen.io/diaid/full/MWOOogX"},{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1673027279/web/dprvsa15ocx3l34dxogo.png",title:"Radio Hide Components",description:"",url:"https://codepen.io/diaid/full/qBVdgWW"},{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1673025125/web/anidcin5lbxo2hced5i4.png",title:"Rounded Paragraph",description:"",url:"https://codepen.io/diaid/full/QWxOgVm"},{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1673027940/web/z9qn4wstdtzpr4cf5xtx.png",title:"Responsive Table",description:"",url:"https://codepen.io/diaid/full/xxJRGMB"}],l=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1761648607/web/ADOSIanaslkdfOASadkn.png",title:"Vanilla TS/JS Carousel",description:"",url:"https://codepen.io/diaid/pen/GgoGwva"}]}}]);
|
|
||||||
//# sourceMappingURL=434.5a130b80.chunk.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
|||||||
"use strict";(self.webpackChunkreact_page=self.webpackChunkreact_page||[]).push([[488],{2488:(e,a,p)=>{new WeakMap;new Set}}]);
|
|
||||||
//# sourceMappingURL=488.a9182cb5.chunk.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
|||||||
"use strict";(self.webpackChunkreact_page=self.webpackChunkreact_page||[]).push([[563],{7563:(e,t,n)=>{n.r(t),n.d(t,{default:()=>p});n(5043);var i=n(97),a=n(3766),o=n(6605),s=n(4496),r=n(710),l=n(8293),c=n(579);const d=e=>{let{blogContent:t}=e;const n=Array.isArray(t)?t:t?[t]:[];return 0===n.length?null:n.map((e,t)=>{let{title:n,description:i}=e;const d=Array.isArray(i)?i:i?[i]:[];return(0,c.jsxs)(a.A,{children:[(0,c.jsx)(o.A,{expandIcon:(0,c.jsx)(l.A,{}),"aria-controls":"panel-".concat(t,"-content"),id:"panel-".concat(t,"-header"),children:(0,c.jsx)(s.A,{variant:"h5",component:"h3",children:n})}),(0,c.jsx)(r.A,{children:d.map((e,n)=>(0,c.jsx)(s.A,{variant:"subtitle1",style:{fontSize:"18px"},paragraph:!0,children:e},"".concat(t,"-").concat(n)))})]},null!==n&&void 0!==n?n:t)})},p=()=>{const e=(0,i.A)();return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(d,{blogContent:{title:e.formatMessage({id:"blog.pantone.title"}),description:[e.formatMessage({id:"blog.pantone.description.line1"}),e.formatMessage({id:"blog.pantone.description.line2"})]}}),(0,c.jsx)(d,{blogContent:{title:e.formatMessage({id:"blog.lighthouse.title"}),description:[e.formatMessage({id:"blog.lighthouse.description.line1"}),e.formatMessage({id:"blog.lighthouse.description.line2"})]}})]})}}}]);
|
|
||||||
//# sourceMappingURL=563.55e2bd58.chunk.js.map
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"static/js/563.55e2bd58.chunk.js","mappings":"mNAUA,MA2CA,EA3CsBA,IAAsB,IAArB,YAAEC,GAAaD,EAErC,MAAME,EAAQC,MAAMC,QAAQH,GACzBA,EACAA,EACA,CAACA,GACD,GAEH,OAAqB,IAAjBC,EAAMG,OAAqB,KAExBH,EAAMI,IAAI,CAAAC,EAAyBC,KAAa,IAArC,MAAEC,EAAK,YAAEC,GAAaH,EACvC,MAAMI,EAAQR,MAAMC,QAAQM,GACzBA,EACAA,EACA,CAACA,GACD,GAEH,OACCE,EAAAA,EAAAA,MAACC,EAAAA,EAAS,CAAAC,SAAA,EACTC,EAAAA,EAAAA,KAACC,EAAAA,EAAgB,CAChBC,YAAYF,EAAAA,EAAAA,KAACG,EAAAA,EAAc,IAC3B,yBAAAC,OAAwBX,EAAO,YAC/BY,GAAE,SAAAD,OAAWX,EAAO,WAAUM,UAC9BC,EAAAA,EAAAA,KAACM,EAAAA,EAAU,CAACC,QAAQ,KAAKC,UAAU,KAAIT,SACrCL,OAGHM,EAAAA,EAAAA,KAACS,EAAAA,EAAgB,CAAAV,SACfH,EAAML,IAAI,CAACmB,EAAaC,KACxBX,EAAAA,EAAAA,KAACM,EAAAA,EAAU,CAEVC,QAAQ,YACRK,MAAO,CAAEC,SAAU,QACnBC,WAAS,EAAAf,SACRW,GAAW,GAAAN,OAJJX,EAAO,KAAAW,OAAIO,SAZF,OAALjB,QAAK,IAALA,EAAAA,EAASD,MCO5B,EA3BasB,KACZ,MAAMC,GAAIC,EAAAA,EAAAA,KACV,OAECpB,EAAAA,EAAAA,MAAAqB,EAAAA,SAAA,CAAAnB,SAAA,EACCC,EAAAA,EAAAA,KAACmB,EAAa,CACbjC,YAAa,CACZQ,MAAOsB,EAAEI,cAAc,CAAEf,GAAI,uBAC7BV,YAAa,CACZqB,EAAEI,cAAc,CAAEf,GAAI,mCACtBW,EAAEI,cAAc,CAAEf,GAAI,wCAIzBL,EAAAA,EAAAA,KAACmB,EAAa,CACbjC,YAAa,CACZQ,MAAOsB,EAAEI,cAAc,CAAEf,GAAI,0BAC7BV,YAAa,CACZqB,EAAEI,cAAc,CAAEf,GAAI,sCACtBW,EAAEI,cAAc,CAAEf,GAAI,6C","sources":["components/blog-accordion/BlogAccordion.jsx","pages/blog/Blog.jsx"],"sourcesContent":["import React from \"react\";\nimport {\n\tAccordion,\n\tAccordionSummary,\n\tAccordionDetails,\n\tTypography,\n} from \"@mui/material\";\n\nimport ExpandMoreIcon from \"@mui/icons-material/ExpandMore\";\n\nconst BlogAccordion = ({ blogContent }) => {\n\t// normalize blogContent to an array to avoid `map` errors\n\tconst items = Array.isArray(blogContent)\n\t\t? blogContent\n\t\t: blogContent\n\t\t? [blogContent]\n\t\t: [];\n\n\tif (items.length === 0) return null;\n\n\treturn items.map(({ title, description }, itemIdx) => {\n\t\tconst lines = Array.isArray(description)\n\t\t\t? description\n\t\t\t: description\n\t\t\t? [description]\n\t\t\t: [];\n\n\t\treturn (\n\t\t\t<Accordion key={title ?? itemIdx}>\n\t\t\t\t<AccordionSummary\n\t\t\t\t\texpandIcon={<ExpandMoreIcon />}\n\t\t\t\t\taria-controls={`panel-${itemIdx}-content`}\n\t\t\t\t\tid={`panel-${itemIdx}-header`}>\n\t\t\t\t\t<Typography variant=\"h5\" component=\"h3\">\n\t\t\t\t\t\t{title}\n\t\t\t\t\t</Typography>\n\t\t\t\t</AccordionSummary>\n\t\t\t\t<AccordionDetails>\n\t\t\t\t\t{lines.map((lineContent, idx) => (\n\t\t\t\t\t\t<Typography\n\t\t\t\t\t\t\tkey={`${itemIdx}-${idx}`}\n\t\t\t\t\t\t\tvariant=\"subtitle1\"\n\t\t\t\t\t\t\tstyle={{ fontSize: \"18px\" }}\n\t\t\t\t\t\t\tparagraph>\n\t\t\t\t\t\t\t{lineContent}\n\t\t\t\t\t\t</Typography>\n\t\t\t\t\t))}\n\t\t\t\t</AccordionDetails>\n\t\t\t</Accordion>\n\t\t);\n\t});\n};\n\nexport default BlogAccordion;\n","import React from \"react\";\n\nimport { useIntl } from \"react-intl\";\n\n// import { BlogContent } from \"data/Data\";\n\nimport BlogAccordion from \"components/blog-accordion/BlogAccordion\";\n\nconst Blog = () => {\n\tconst t = useIntl();\n\treturn (\n\t\t// <div style={{ minHeight: 'calc(100vh-128px)' }}>Blog ...in progress</div>\n\t\t<>\n\t\t\t<BlogAccordion\n\t\t\t\tblogContent={{\n\t\t\t\t\ttitle: t.formatMessage({ id: \"blog.pantone.title\" }),\n\t\t\t\t\tdescription: [\n\t\t\t\t\t\tt.formatMessage({ id: \"blog.pantone.description.line1\" }),\n\t\t\t\t\t\tt.formatMessage({ id: \"blog.pantone.description.line2\" }),\n\t\t\t\t\t],\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t<BlogAccordion\n\t\t\t\tblogContent={{\n\t\t\t\t\ttitle: t.formatMessage({ id: \"blog.lighthouse.title\" }),\n\t\t\t\t\tdescription: [\n\t\t\t\t\t\tt.formatMessage({ id: \"blog.lighthouse.description.line1\" }),\n\t\t\t\t\t\tt.formatMessage({ id: \"blog.lighthouse.description.line2\" }),\n\t\t\t\t\t],\n\t\t\t\t}}\n\t\t\t/>\n\t\t</>\n\t);\n};\n\nexport default Blog;\n"],"names":["_ref","blogContent","items","Array","isArray","length","map","_ref2","itemIdx","title","description","lines","_jsxs","Accordion","children","_jsx","AccordionSummary","expandIcon","ExpandMoreIcon","concat","id","Typography","variant","component","AccordionDetails","lineContent","idx","style","fontSize","paragraph","Blog","t","useIntl","_Fragment","BlogAccordion","formatMessage"],"sourceRoot":""}
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
|||||||
"use strict";(self.webpackChunkreact_page=self.webpackChunkreact_page||[]).push([[992],{6322:(e,t,i)=>{i.d(t,{A:()=>y});var o=i(5043),a=i(3766),s=i(6605),n=i(4496),d=i(710),r=i(766),l=i(2110),p=i(6591),c=i(2828),u=i(6494),g=i(6240),m=i(9368),h=i.n(m),b=i(579);const x=e=>{const{options:t,children:i}=e,a=(0,o.useRef)(null);return(0,o.useEffect)(()=>{h().init(a.current,t)},[t]),(0,b.jsx)("div",{ref:a,children:i})},j=e=>{let{imageURL:t,title:i,description:o,url:a}=e;const s=(0,g.A)();return(0,b.jsx)(x,{options:{reverse:!0,speed:1200,easing:"cubic-bezier(.09,.67,.54,.76)"},children:(0,b.jsxs)(l.A,{sx:{minWidth:"320px",maxWidth:"320px",marginLeft:"auto",marginRight:"auto",color:s.palette.text.secondary,backgroundColor:s.palette.background.paper},children:[(0,b.jsx)(p.A,{component:"img",height:"150",image:t,alt:i}),(0,b.jsx)(n.A,{variant:"body2",children:o}),(0,b.jsx)(c.A,{children:(0,b.jsx)(u.A,{color:"white",onClick:()=>window.open(a,"_blank"),children:(0,b.jsx)(n.A,{gutterBottom:!0,variant:"h6",component:"h4",children:i})})})]})})};var v=i(8293);const y=e=>{let{items:t,title:i}=e;return(0,b.jsxs)(a.A,{defaultExpanded:!0,slotProps:{transition:{unmountOnExit:!0}},children:[(0,b.jsx)(s.A,{expandIcon:(0,b.jsx)(v.A,{}),"aria-controls":"panel1a-content",id:"panel1a-header",children:(0,b.jsx)(n.A,{variant:"h5",component:"h3",children:i})}),(0,b.jsx)(d.A,{children:(0,b.jsx)(r.A,{container:!0,direction:"row",alignItems:"flex-start",justifyContent:"baseline",spacing:3,children:t.map(e=>(0,b.jsx)(r.A,{children:(0,b.jsx)(j,{imageURL:e.imageURL,title:e.title,description:e.description,url:e.url})},e.key+e.title))})})]})}},6992:(e,t,i)=>{i.r(t),i.d(t,{default:()=>n});i(5043);var o=i(9975),a=i(6322),s=i(579);const n=()=>(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(a.A,{items:o.Iz,title:"CSS Only"}),(0,s.jsx)(a.A,{items:o.E,title:"Vanilla JS/TS"})]})},9975:(e,t,i)=>{i.d(t,{E:()=>l,Iz:()=>r,Pz:()=>n,b8:()=>s,c3:()=>o,dX:()=>a,ri:()=>d});const o=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1673023170/web/uxfuyzap5kbs1si34g29.png",title:"Shop",description:"",url:"https://dadobos.github.io/react-shop/"},{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1685729092/web/tzoxavfsfa44z2o9wrgi.png",title:"Quiz App",description:"",url:"https://dadobos.github.io/react-quiz-app/"}],a=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1669538934/web/ng0ghejmlsmzhrgyuiz4.png",title:"Pokemon GO Templates",description:"",url:"https://github.com/dadobos/pokemongotemplates"}],s=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1653850879/web/TheSquareProject_sgflcj.png",title:"The Square Project",description:"",url:"https://dadobos.github.io/The-Square-Project/"}],n=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1642766521/web/Restaurant_Billing_System_rgpsif.png",title:"Restaurant Billing System",description:"",url:"https://github.com/dadobos/Restaurant"},{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1642766521/web/Billing_System_bazap1.png",title:"Billing System",description:"",url:"https://github.com/dadobos/Billing-System"}],d=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1654030260/web/WorldCountries_ekx2of.png",title:"World Countries",description:"",url:"https://dadobos.github.io/worldcountries/"}],r=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1673027279/web/msvc649ua0gahqegu31o.png",title:"Anchor Tag Hide Components",description:"",url:"https://codepen.io/diaid/full/MWOOogX"},{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1673027279/web/dprvsa15ocx3l34dxogo.png",title:"Radio Hide Components",description:"",url:"https://codepen.io/diaid/full/qBVdgWW"},{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1673025125/web/anidcin5lbxo2hced5i4.png",title:"Rounded Paragraph",description:"",url:"https://codepen.io/diaid/full/QWxOgVm"},{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1673027940/web/z9qn4wstdtzpr4cf5xtx.png",title:"Responsive Table",description:"",url:"https://codepen.io/diaid/full/xxJRGMB"}],l=[{imageURL:"https://res.cloudinary.com/dadobos/image/upload/v1761648607/web/ADOSIanaslkdfOASadkn.png",title:"Vanilla TS/JS Carousel",description:"",url:"https://codepen.io/diaid/pen/GgoGwva"}]}}]);
|
|
||||||
//# sourceMappingURL=992.123c4331.chunk.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,77 +0,0 @@
|
|||||||
/**
|
|
||||||
* @license React
|
|
||||||
* react-dom.production.min.js
|
|
||||||
*
|
|
||||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @license React
|
|
||||||
* react-is.production.js
|
|
||||||
*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @license React
|
|
||||||
* react-jsx-runtime.production.min.js
|
|
||||||
*
|
|
||||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @license React
|
|
||||||
* react.production.min.js
|
|
||||||
*
|
|
||||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @license React
|
|
||||||
* scheduler.production.min.js
|
|
||||||
*
|
|
||||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @mui/styled-engine v6.5.0
|
|
||||||
*
|
|
||||||
* @license MIT
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* react-router v7.9.4
|
|
||||||
*
|
|
||||||
* Copyright (c) Remix Software Inc.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE.md file in the root directory of this source tree.
|
|
||||||
*
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @license React v16.13.1
|
|
||||||
* react-is.production.min.js
|
|
||||||
*
|
|
||||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user