Refactor project data structure, add internationalization support, and enhance UI components
- Updated project data files to improve formatting and consistency. - Introduced language support with English and Dutch translations. - Implemented language switcher and dark mode toggle in the header and footer. - Enhanced navigation components to utilize internationalized strings. - Refactored layout components to use Grid2 for better responsiveness. - Improved accessibility and usability across various components.
This commit is contained in:
Vendored
+4
-4
@@ -5,11 +5,11 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"type": "pwa-chrome",
|
"name": "Launch Chrome",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Launch Chrome against localhost",
|
"type": "chrome",
|
||||||
"url": "http://localhost:8080",
|
"url": "http://localhost:3000",
|
||||||
"webRoot": "${workspaceFolder}"
|
"webRoot": "${workspaceFolder}/src"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+21029
-18756
File diff suppressed because it is too large
Load Diff
+63
-62
@@ -1,64 +1,65 @@
|
|||||||
{
|
{
|
||||||
"name": "react-page",
|
"name": "react-page",
|
||||||
"homepage": "https://dadobos.github.io/me/",
|
"homepage": "https://dadobos.github.io/me/",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@mui/icons-material": "^6.4.12",
|
"@mui/icons-material": "^6.5.0",
|
||||||
"@mui/material": "^7.3.4",
|
"@mui/material": "^6.5.0",
|
||||||
"@mui/styles": "^6.0.0",
|
"@mui/styles": "^6.5.0",
|
||||||
"@testing-library/jest-dom": "^6.9.1",
|
"@testing-library/jest-dom": "^6.9.1",
|
||||||
"@testing-library/react": "^16.3.0",
|
"@testing-library/react": "^16.3.0",
|
||||||
"@testing-library/user-event": "^14.6.1",
|
"@testing-library/user-event": "^14.6.1",
|
||||||
"react": "^19.2.0",
|
"react": "^18.0.0",
|
||||||
"react-dom": "^19.2.0",
|
"react-dom": "^18.0.0",
|
||||||
"react-router-dom": "^7.9.4",
|
"react-intl": "^7.1.14",
|
||||||
"react-scripts": "^5.0.1",
|
"react-router-dom": "^7.9.4",
|
||||||
"react-spring": "^10.0.3",
|
"react-scripts": "^5.0.1",
|
||||||
"styled-components": "^6.1.11",
|
"react-spring": "^10.0.3",
|
||||||
"vanilla-tilt": "^1.8.1",
|
"styled-components": "^6.1.11",
|
||||||
"web-vitals": "^5.1.0"
|
"vanilla-tilt": "^1.8.1",
|
||||||
},
|
"web-vitals": "^5.1.0"
|
||||||
"scripts": {
|
},
|
||||||
"start": "react-scripts start",
|
"scripts": {
|
||||||
"build": "react-scripts build",
|
"start": "react-scripts start",
|
||||||
"test": "react-scripts test",
|
"build": "react-scripts build",
|
||||||
"eject": "react-scripts eject",
|
"test": "react-scripts test",
|
||||||
"predeploy": "npm run build",
|
"eject": "react-scripts eject",
|
||||||
"deploy": "gh-pages -d build"
|
"predeploy": "npm run build",
|
||||||
},
|
"deploy": "gh-pages -d build"
|
||||||
"eslintConfig": {
|
},
|
||||||
"extends": [
|
"eslintConfig": {
|
||||||
"react-app",
|
"extends": [
|
||||||
"react-app/jest"
|
"react-app",
|
||||||
]
|
"react-app/jest"
|
||||||
},
|
]
|
||||||
"browserslist": {
|
},
|
||||||
"production": [
|
"browserslist": {
|
||||||
">0.2%",
|
"production": [
|
||||||
"not dead",
|
">0.2%",
|
||||||
"not op_mini all"
|
"not dead",
|
||||||
],
|
"not op_mini all"
|
||||||
"development": [
|
],
|
||||||
"last 1 chrome version",
|
"development": [
|
||||||
"last 1 firefox version",
|
"last 1 chrome version",
|
||||||
"last 1 safari version"
|
"last 1 firefox version",
|
||||||
]
|
"last 1 safari version"
|
||||||
},
|
]
|
||||||
"devDependencies": {
|
},
|
||||||
"gh-pages": "^6.1.1"
|
"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",
|
"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.",
|
||||||
"repository": {
|
"main": "index.js",
|
||||||
"type": "git",
|
"repository": {
|
||||||
"url": "git+https://github.com/dadobos/me.git"
|
"type": "git",
|
||||||
},
|
"url": "git+https://github.com/dadobos/me.git"
|
||||||
"author": "Dan Andrei Dobos",
|
},
|
||||||
"license": "ISC",
|
"author": "Dan Andrei Dobos",
|
||||||
"bugs": {
|
"license": "ISC",
|
||||||
"url": "https://github.com/dadobos/me/issues"
|
"bugs": {
|
||||||
}
|
"url": "https://github.com/dadobos/me/issues"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.4 KiB |
+7
-23
@@ -1,25 +1,9 @@
|
|||||||
{
|
{
|
||||||
"short_name": "DAD",
|
"short_name": "DAD",
|
||||||
"name": "Dan Andrei Dobos",
|
"name": "Dan Andrei Dobos",
|
||||||
"icons": [
|
"icons": [],
|
||||||
{
|
"start_url": "/me",
|
||||||
"src": "favicon.ico",
|
"display": "standalone",
|
||||||
"sizes": "64x64 32x32 24x24 16x16",
|
"theme_color": "#000000",
|
||||||
"type": "image/x-icon"
|
"background_color": "#ffffff"
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "logo192.png",
|
|
||||||
"type": "image/png",
|
|
||||||
"sizes": "192x192"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "logo512.png",
|
|
||||||
"type": "image/png",
|
|
||||||
"sizes": "512x512"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"start_url": ".",
|
|
||||||
"display": "standalone",
|
|
||||||
"theme_color": "#000000",
|
|
||||||
"background_color": "#ffffff"
|
|
||||||
}
|
}
|
||||||
|
|||||||
+48
-10
@@ -1,5 +1,6 @@
|
|||||||
import React, { useState, useMemo, createContext } from "react";
|
import React, { useState, useMemo, createContext, useCallback } from "react";
|
||||||
import { BrowserRouter as Router } from "react-router-dom";
|
import { BrowserRouter as Router } from "react-router-dom";
|
||||||
|
import { IntlProvider } from "react-intl";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
responsiveFontSizes,
|
responsiveFontSizes,
|
||||||
@@ -9,10 +10,38 @@ import {
|
|||||||
import { MainTheme } from "./themes/Theme";
|
import { MainTheme } from "./themes/Theme";
|
||||||
import { CustomRoutes } from "./routes/Routes";
|
import { CustomRoutes } from "./routes/Routes";
|
||||||
|
|
||||||
export const ColorModeContext = createContext({ toggleColorMode: () => {} });
|
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 App = () => {
|
||||||
const [mode, setMode] = useState("dark");
|
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(
|
const colorMode = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
toggleColorMode: () => {
|
toggleColorMode: () => {
|
||||||
@@ -22,20 +51,29 @@ const App = () => {
|
|||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const contextValue = useMemo(
|
||||||
|
() => ({ ...colorMode, locale: localeState, setLocale }),
|
||||||
|
[colorMode, localeState, setLocale],
|
||||||
|
);
|
||||||
|
|
||||||
const theme = useMemo(
|
const theme = useMemo(
|
||||||
() => responsiveFontSizes(createTheme(MainTheme(mode))),
|
() => responsiveFontSizes(createTheme(MainTheme(mode))),
|
||||||
[mode],
|
[mode],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ColorModeContext.Provider value={colorMode}>
|
<IntlProvider locale={localeState} messages={messages[localeState]} defaultLocale="en">
|
||||||
<ThemeProvider theme={theme}>
|
<AppContext.Provider value={contextValue}>
|
||||||
<Router basename={process.env.PUBLIC_URL}>
|
<ThemeProvider theme={theme}>
|
||||||
<CustomRoutes />
|
{/* quick language switcher; move or style as needed */}
|
||||||
</Router>
|
{/* <LanguageSwitcher locale={localeState} setLocale={setLocale} /> */}
|
||||||
</ThemeProvider>
|
<Router basename={process.env.PUBLIC_URL}>
|
||||||
</ColorModeContext.Provider>
|
<CustomRoutes />
|
||||||
|
</Router>
|
||||||
|
</ThemeProvider>
|
||||||
|
</AppContext.Provider>
|
||||||
|
</IntlProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
@@ -1,37 +1,48 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
Accordion,
|
Accordion,
|
||||||
AccordionSummary,
|
AccordionSummary,
|
||||||
AccordionDetails,
|
AccordionDetails,
|
||||||
Typography,
|
Typography,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
|
||||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||||
|
|
||||||
const BlogAccordion = ({ blogContent }) => {
|
const BlogAccordion = ({ blogContent }) => {
|
||||||
return blogContent.map(({ title, description }) => (
|
// normalize blogContent to an array to avoid `map` errors
|
||||||
<Accordion
|
const items = Array.isArray(blogContent)
|
||||||
// defaultExpanded
|
? blogContent
|
||||||
// slotProps={{ unmountOnExit: true }}
|
: blogContent
|
||||||
key={title}
|
? [blogContent]
|
||||||
sx={{ background: "transparent" }}
|
: [];
|
||||||
>
|
|
||||||
<AccordionSummary
|
if (items.length === 0) return null;
|
||||||
expandIcon={<ExpandMoreIcon />}
|
|
||||||
aria-controls="panel1a-content"
|
return items.map(({ title, description }, itemIdx) => {
|
||||||
id="panel1a-header"
|
const lines = Array.isArray(description)
|
||||||
>
|
? description
|
||||||
<Typography variant="h5">{title}</Typography>
|
: description
|
||||||
</AccordionSummary>
|
? [description]
|
||||||
<AccordionDetails>
|
: [];
|
||||||
{description.map((lineContent, idx) => (
|
|
||||||
<Typography key={idx} paragraph>
|
return (
|
||||||
{lineContent}
|
<Accordion key={title ?? itemIdx}>
|
||||||
</Typography>
|
<AccordionSummary
|
||||||
))}
|
expandIcon={<ExpandMoreIcon />}
|
||||||
</AccordionDetails>
|
aria-controls={`panel-${itemIdx}-content`}
|
||||||
</Accordion>
|
id={`panel-${itemIdx}-header`}>
|
||||||
));
|
<Typography variant="h5">{title}</Typography>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
{lines.map((lineContent, idx) => (
|
||||||
|
<Typography key={`${itemIdx}-${idx}`} paragraph>
|
||||||
|
{lineContent}
|
||||||
|
</Typography>
|
||||||
|
))}
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
|
);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export default BlogAccordion;
|
export default BlogAccordion;
|
||||||
|
|||||||
@@ -1,57 +1,52 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
Grid,
|
Grid2,
|
||||||
Accordion,
|
Accordion,
|
||||||
AccordionSummary,
|
AccordionSummary,
|
||||||
AccordionDetails,
|
AccordionDetails,
|
||||||
Typography,
|
Typography,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import MainCard from "components/main-card/MainCard";
|
import MainCard from "components/main-card/MainCard";
|
||||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||||
|
|
||||||
const MainAccordion = ({ items, title }) => {
|
const MainAccordion = ({ items, title }) => {
|
||||||
return (
|
return (
|
||||||
<Accordion
|
<Accordion
|
||||||
defaultExpanded
|
defaultExpanded
|
||||||
TransitionProps={{ unmountOnExit: true }}
|
slotProps={{ transition: { unmountOnExit: true } }}>
|
||||||
sx={{ background: "transparent" }}
|
<AccordionSummary
|
||||||
>
|
expandIcon={<ExpandMoreIcon />}
|
||||||
<AccordionSummary
|
aria-controls="panel1a-content"
|
||||||
expandIcon={<ExpandMoreIcon />}
|
id="panel1a-header">
|
||||||
aria-controls="panel1a-content"
|
<Typography variant="h5">{title}</Typography>
|
||||||
id="panel1a-header"
|
</AccordionSummary>
|
||||||
>
|
<AccordionDetails>
|
||||||
<Typography variant="h5">{title}</Typography>
|
<Grid2
|
||||||
</AccordionSummary>
|
container
|
||||||
<AccordionDetails>
|
direction="row"
|
||||||
<Grid
|
alignItems="flex-start"
|
||||||
container
|
justifyContent="baseline"
|
||||||
direction="row"
|
spacing={3}>
|
||||||
alignItems="flex-start"
|
{items.map((project) => (
|
||||||
justifyContent="baseline"
|
<Grid2
|
||||||
spacing={3}
|
item
|
||||||
>
|
xs={12}
|
||||||
{items.map((project) => (
|
sm={6}
|
||||||
<Grid
|
md={4}
|
||||||
item
|
key={project.title}
|
||||||
xs={12}
|
sx={{ alignItems: "center", justifyContent: "center" }}>
|
||||||
sm={6}
|
<MainCard
|
||||||
md={4}
|
imageURL={project.imageURL}
|
||||||
key={project.title}
|
title={project.title}
|
||||||
sx={{ alignItems: "center", justifyContent: "center" }}
|
description={project.description}
|
||||||
>
|
url={project.url}
|
||||||
<MainCard
|
/>
|
||||||
imageURL={project.imageURL}
|
</Grid2>
|
||||||
title={project.title}
|
))}
|
||||||
description={project.description}
|
</Grid2>
|
||||||
url={project.url}
|
</AccordionDetails>
|
||||||
/>
|
</Accordion>
|
||||||
</Grid>
|
);
|
||||||
))}
|
|
||||||
</Grid>
|
|
||||||
</AccordionDetails>
|
|
||||||
</Accordion>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MainAccordion;
|
export default MainAccordion;
|
||||||
|
|||||||
+77
-98
@@ -1,115 +1,94 @@
|
|||||||
export const ReactData = [
|
export const ReactData = [
|
||||||
{
|
{
|
||||||
imageURL:
|
imageURL:
|
||||||
"https://res.cloudinary.com/dadobos/image/upload/v1673023170/web/uxfuyzap5kbs1si34g29.png",
|
"https://res.cloudinary.com/dadobos/image/upload/v1673023170/web/uxfuyzap5kbs1si34g29.png",
|
||||||
title: "React Shop",
|
title: "React Shop",
|
||||||
description: "",
|
description: "",
|
||||||
url: "https://dadobos.github.io/react-shop/",
|
url: "https://dadobos.github.io/react-shop/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
imageURL:
|
imageURL:
|
||||||
"https://res.cloudinary.com/dadobos/image/upload/v1685729092/web/tzoxavfsfa44z2o9wrgi.png",
|
"https://res.cloudinary.com/dadobos/image/upload/v1685729092/web/tzoxavfsfa44z2o9wrgi.png",
|
||||||
title: "React Quiz App",
|
title: "React Quiz App",
|
||||||
description: "",
|
description: "",
|
||||||
url: "https://dadobos.github.io/react-quiz-app/",
|
url: "https://dadobos.github.io/react-quiz-app/",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const GoData = [
|
export const GoData = [
|
||||||
{
|
{
|
||||||
imageURL:
|
imageURL:
|
||||||
"https://res.cloudinary.com/dadobos/image/upload/v1669538934/web/ng0ghejmlsmzhrgyuiz4.png",
|
"https://res.cloudinary.com/dadobos/image/upload/v1669538934/web/ng0ghejmlsmzhrgyuiz4.png",
|
||||||
title: "Pokemon GO Templates",
|
title: "Pokemon GO Templates",
|
||||||
description: "",
|
description: "",
|
||||||
url: "https://github.com/dadobos/pokemongotemplates",
|
url: "https://github.com/dadobos/pokemongotemplates",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const WebsitesData = [
|
export const WebsitesData = [
|
||||||
{
|
{
|
||||||
imageURL:
|
imageURL:
|
||||||
"https://res.cloudinary.com/dadobos/image/upload/v1653850879/web/TheSquareProject_sgflcj.png",
|
"https://res.cloudinary.com/dadobos/image/upload/v1653850879/web/TheSquareProject_sgflcj.png",
|
||||||
title: "The Square Project",
|
title: "The Square Project",
|
||||||
description: "",
|
description: "",
|
||||||
url: "https://dadobos.github.io/The-Square-Project/",
|
url: "https://dadobos.github.io/The-Square-Project/",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const JavaData = [
|
export const JavaData = [
|
||||||
{
|
{
|
||||||
imageURL:
|
imageURL:
|
||||||
"https://res.cloudinary.com/dadobos/image/upload/v1642766521/web/Restaurant_Billing_System_rgpsif.png",
|
"https://res.cloudinary.com/dadobos/image/upload/v1642766521/web/Restaurant_Billing_System_rgpsif.png",
|
||||||
title: "Restaurant Billing System",
|
title: "Restaurant Billing System",
|
||||||
description: "",
|
description: "",
|
||||||
url: "https://github.com/dadobos/Restaurant",
|
url: "https://github.com/dadobos/Restaurant",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
imageURL:
|
imageURL:
|
||||||
"https://res.cloudinary.com/dadobos/image/upload/v1642766521/web/Billing_System_bazap1.png",
|
"https://res.cloudinary.com/dadobos/image/upload/v1642766521/web/Billing_System_bazap1.png",
|
||||||
title: "Billing System",
|
title: "Billing System",
|
||||||
description: "",
|
description: "",
|
||||||
url: "https://github.com/dadobos/Billing-System",
|
url: "https://github.com/dadobos/Billing-System",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const VueData = [
|
export const VueData = [
|
||||||
{
|
{
|
||||||
imageURL:
|
imageURL:
|
||||||
"https://res.cloudinary.com/dadobos/image/upload/v1654030260/web/WorldCountries_ekx2of.png",
|
"https://res.cloudinary.com/dadobos/image/upload/v1654030260/web/WorldCountries_ekx2of.png",
|
||||||
title: "World Countries",
|
title: "World Countries",
|
||||||
description: "",
|
description: "",
|
||||||
url: "https://dadobos.github.io/worldcountries/",
|
url: "https://dadobos.github.io/worldcountries/",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const CSSData = [
|
export const CSSData = [
|
||||||
{
|
{
|
||||||
imageURL:
|
imageURL:
|
||||||
"https://res.cloudinary.com/dadobos/image/upload/v1673027279/web/msvc649ua0gahqegu31o.png",
|
"https://res.cloudinary.com/dadobos/image/upload/v1673027279/web/msvc649ua0gahqegu31o.png",
|
||||||
title: "Anchor Tag Hide Components",
|
title: "Anchor Tag Hide Components",
|
||||||
description: "",
|
description: "",
|
||||||
url: "https://codepen.io/diaid/full/MWOOogX",
|
url: "https://codepen.io/diaid/full/MWOOogX",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
imageURL:
|
imageURL:
|
||||||
"https://res.cloudinary.com/dadobos/image/upload/v1673027279/web/dprvsa15ocx3l34dxogo.png",
|
"https://res.cloudinary.com/dadobos/image/upload/v1673027279/web/dprvsa15ocx3l34dxogo.png",
|
||||||
title: "Radio Hide Components",
|
title: "Radio Hide Components",
|
||||||
description: "",
|
description: "",
|
||||||
url: "https://codepen.io/diaid/full/qBVdgWW",
|
url: "https://codepen.io/diaid/full/qBVdgWW",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
imageURL:
|
imageURL:
|
||||||
"https://res.cloudinary.com/dadobos/image/upload/v1673025125/web/anidcin5lbxo2hced5i4.png",
|
"https://res.cloudinary.com/dadobos/image/upload/v1673025125/web/anidcin5lbxo2hced5i4.png",
|
||||||
title: "Rounded Paragraph",
|
title: "Rounded Paragraph",
|
||||||
description: "",
|
description: "",
|
||||||
url: "https://codepen.io/diaid/full/QWxOgVm",
|
url: "https://codepen.io/diaid/full/QWxOgVm",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
imageURL:
|
imageURL:
|
||||||
"https://res.cloudinary.com/dadobos/image/upload/v1673027940/web/z9qn4wstdtzpr4cf5xtx.png",
|
"https://res.cloudinary.com/dadobos/image/upload/v1673027940/web/z9qn4wstdtzpr4cf5xtx.png",
|
||||||
title: "Responsive Table",
|
title: "Responsive Table",
|
||||||
description: "",
|
description: "",
|
||||||
url: "https://codepen.io/diaid/full/xxJRGMB",
|
url: "https://codepen.io/diaid/full/xxJRGMB",
|
||||||
},
|
},
|
||||||
];
|
|
||||||
|
|
||||||
export const PantoneBlog = [
|
|
||||||
`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.`,
|
|
||||||
];
|
|
||||||
|
|
||||||
export const BlogContent = [
|
|
||||||
{
|
|
||||||
title: "Pantone color 2025",
|
|
||||||
description: [
|
|
||||||
"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.",
|
|
||||||
|
|
||||||
"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.",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "How I achieved 100% on Lighthouse Audit",
|
|
||||||
description: ["TBA"],
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"navigation.home": "home",
|
||||||
|
"navigation.projects": "Projects",
|
||||||
|
"navigation.best-practices": "Best Practices",
|
||||||
|
"navigation.blog": "Blog",
|
||||||
|
"navigation.about": "About",
|
||||||
|
"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,14 @@
|
|||||||
|
{
|
||||||
|
"navigation.home": "Startpagina",
|
||||||
|
"navigation.projects": "Projecten",
|
||||||
|
"navigation.best-practices": "Beste praktijken",
|
||||||
|
"navigation.blog": "Blog",
|
||||||
|
"navigation.about": "Over",
|
||||||
|
"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."
|
||||||
|
}
|
||||||
@@ -1,26 +1,25 @@
|
|||||||
import React, { useContext } from "react";
|
import React, { useContext } from "react";
|
||||||
import { IconButton } from "@mui/material";
|
import { IconButton } from "@mui/material";
|
||||||
import { useTheme } from "@mui/material/styles";
|
import { useTheme } from "@mui/material/styles";
|
||||||
import { ColorModeContext } from "App";
|
import { AppContext } from "App";
|
||||||
import WbSunnyOutlinedIcon from "@mui/icons-material/WbSunnyOutlined";
|
import WbSunnyOutlinedIcon from "@mui/icons-material/WbSunnyOutlined";
|
||||||
import NightsStayOutlinedIcon from "@mui/icons-material/NightsStayOutlined";
|
import NightsStayOutlinedIcon from "@mui/icons-material/NightsStayOutlined";
|
||||||
|
|
||||||
const DarkModeToggle = () => {
|
const DarkModeToggle = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const colorMode = useContext(ColorModeContext);
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={colorMode.toggleColorMode}
|
onClick={appContext.toggleColorMode}
|
||||||
sx={{ color: theme.palette.text.secondary }}
|
sx={{ color: theme.palette.text.secondary }}>
|
||||||
>
|
{theme.palette.mode === "dark" ? (
|
||||||
{theme.palette.mode === "dark" ? (
|
<WbSunnyOutlinedIcon />
|
||||||
<WbSunnyOutlinedIcon />
|
) : (
|
||||||
) : (
|
<NightsStayOutlinedIcon />
|
||||||
<NightsStayOutlinedIcon />
|
)}
|
||||||
)}
|
</IconButton>
|
||||||
</IconButton>
|
);
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DarkModeToggle;
|
export default DarkModeToggle;
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import React, { useContext } from "react";
|
||||||
|
import { AppContext } from "App";
|
||||||
|
import { useTheme } from "@mui/material/styles";
|
||||||
|
import { IconButton } from "@mui/material";
|
||||||
|
// import { FormattedMessage } from "react-intl";
|
||||||
|
import LanguageOutlinedIcon from "@mui/icons-material/LanguageOutlined";
|
||||||
|
|
||||||
|
const LanguageSwitcher = () => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
return (
|
||||||
|
<IconButton
|
||||||
|
onClick={() => {
|
||||||
|
const setLocale = appContext && appContext.setLocale;
|
||||||
|
if (typeof setLocale === "function") {
|
||||||
|
setLocale(appContext.locale === "en" ? "nl" : "en");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
alignSelf: "right",
|
||||||
|
}}>
|
||||||
|
{<LanguageOutlinedIcon />}
|
||||||
|
</IconButton>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LanguageSwitcher;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./LanguageSwitcher";
|
||||||
@@ -2,7 +2,7 @@ import React, { useContext } from "react";
|
|||||||
|
|
||||||
import { ThemeProvider } from "@mui/material/styles";
|
import { ThemeProvider } from "@mui/material/styles";
|
||||||
|
|
||||||
import { ColorModeContext } from "App";
|
import { AppContext } from "App";
|
||||||
import { LandingWhite } from "themes/Theme";
|
import { LandingWhite } from "themes/Theme";
|
||||||
import FullScreenContainer from "layouts/common/fullScreenContainer";
|
import FullScreenContainer from "layouts/common/fullScreenContainer";
|
||||||
|
|
||||||
@@ -10,22 +10,22 @@ import BackToTop from "../common/backToTop";
|
|||||||
import Header from "./components/header";
|
import Header from "./components/header";
|
||||||
|
|
||||||
const LandingLayout = (props) => {
|
const LandingLayout = (props) => {
|
||||||
const { children } = props;
|
const { children } = props;
|
||||||
|
|
||||||
const colorMode = useContext(ColorModeContext);
|
const colorMode = useContext(AppContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ColorModeContext.Provider value={colorMode}>
|
<AppContext.Provider value={colorMode}>
|
||||||
<ThemeProvider theme={LandingWhite}>
|
<ThemeProvider theme={LandingWhite}>
|
||||||
<div id="back-to-top-anchor" />
|
<div id="back-to-top-anchor" />
|
||||||
<Header />
|
<Header />
|
||||||
<FullScreenContainer>
|
<FullScreenContainer>
|
||||||
{children}
|
{children}
|
||||||
<BackToTop />
|
<BackToTop />
|
||||||
</FullScreenContainer>
|
</FullScreenContainer>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</ColorModeContext.Provider>
|
</AppContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LandingLayout;
|
export default LandingLayout;
|
||||||
|
|||||||
@@ -3,88 +3,85 @@ import React from "react";
|
|||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AppBar,
|
AppBar,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
CssBaseline,
|
CssBaseline,
|
||||||
Typography,
|
Typography,
|
||||||
Breadcrumbs,
|
Breadcrumbs,
|
||||||
Link as MaterialLink,
|
Link as MaterialLink,
|
||||||
Grid,
|
Grid2,
|
||||||
IconButton,
|
IconButton,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { useTheme } from "@mui/material/styles";
|
import { useTheme } from "@mui/material/styles";
|
||||||
import ThreeSixtyOutlinedIcon from "@mui/icons-material/ThreeSixtyOutlined";
|
import ThreeSixtyOutlinedIcon from "@mui/icons-material/ThreeSixtyOutlined";
|
||||||
|
|
||||||
|
import LanguageSwitcher from "layouts/common/languageSwitcher";
|
||||||
import DarkModeToggle from "layouts/common/darkModeToggle";
|
import DarkModeToggle from "layouts/common/darkModeToggle";
|
||||||
import HideOnScroll from "layouts/common/hideOnScroll";
|
import HideOnScroll from "layouts/common/hideOnScroll";
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<HideOnScroll>
|
<HideOnScroll>
|
||||||
<AppBar
|
<AppBar
|
||||||
position="fixed"
|
position="fixed"
|
||||||
sx={{
|
sx={{
|
||||||
background: "transparent",
|
background: "transparent",
|
||||||
zIndex: 1301,
|
zIndex: 1301,
|
||||||
[theme.breakpoints.down("lg")]: {
|
[theme.breakpoints.down("lg")]: {
|
||||||
backgroundColor: theme.palette.background.default,
|
backgroundColor: theme.palette.background.default,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
elevation={0}
|
elevation={0}>
|
||||||
>
|
<Toolbar>
|
||||||
<Toolbar>
|
<Grid2
|
||||||
<Grid
|
container
|
||||||
container
|
sx={{
|
||||||
sx={{
|
width: "100%",
|
||||||
width: "100%",
|
justifyContent: "space-between",
|
||||||
justifyContent: "space-between",
|
alignItems: "center",
|
||||||
alignItems: "center",
|
}}>
|
||||||
}}
|
<Grid2 item>
|
||||||
>
|
<Breadcrumbs aria-label="breadcrumb">
|
||||||
<Grid item>
|
<Typography
|
||||||
<Breadcrumbs aria-label="breadcrumb">
|
variant="h5"
|
||||||
<Typography
|
sx={{
|
||||||
variant="h5"
|
textTransform: "uppercase",
|
||||||
sx={{
|
letterSpacing: ".2rem",
|
||||||
textTransform: "uppercase",
|
}}>
|
||||||
letterSpacing: ".2rem",
|
Dan Dobos
|
||||||
}}
|
</Typography>
|
||||||
>
|
{/*href="#about" is used to navigate within the page */}
|
||||||
Dan Dobos
|
<MaterialLink
|
||||||
</Typography>
|
color="textPrimary"
|
||||||
{/*href="#about" is used to navigate within the page */}
|
href="#about"
|
||||||
<MaterialLink
|
sx={{ cursor: "pointer" }}>
|
||||||
color="textPrimary"
|
About
|
||||||
href="#about"
|
</MaterialLink>
|
||||||
sx={{ cursor: "pointer" }}
|
</Breadcrumbs>
|
||||||
>
|
</Grid2>
|
||||||
About
|
<Grid2 item>
|
||||||
</MaterialLink>
|
<Grid2 container alignItems="center">
|
||||||
</Breadcrumbs>
|
<Link to="/projects">
|
||||||
</Grid>
|
<IconButton
|
||||||
<Grid item>
|
aria-label="Projects"
|
||||||
<Grid container alignItems="center">
|
disableRipple
|
||||||
<Link to="/projects">
|
sx={{ mr: 1, color: theme.palette.text.secondary }}>
|
||||||
<IconButton
|
<ThreeSixtyOutlinedIcon />
|
||||||
aria-label="Projects"
|
</IconButton>
|
||||||
disableRipple
|
</Link>
|
||||||
sx={{ mr: 1 }}
|
<LanguageSwitcher />
|
||||||
>
|
<DarkModeToggle />
|
||||||
<ThreeSixtyOutlinedIcon />
|
</Grid2>
|
||||||
</IconButton>
|
</Grid2>
|
||||||
</Link>
|
</Grid2>
|
||||||
<DarkModeToggle />
|
</Toolbar>
|
||||||
</Grid>
|
</AppBar>
|
||||||
</Grid>
|
</HideOnScroll>
|
||||||
</Grid>
|
</>
|
||||||
</Toolbar>
|
);
|
||||||
</AppBar>
|
|
||||||
</HideOnScroll>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
export default Header;
|
export default Header;
|
||||||
|
|||||||
@@ -1,32 +1,30 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Grid, Typography } from "@mui/material";
|
import { Grid2, Typography } from "@mui/material";
|
||||||
|
|
||||||
const Footer = () => {
|
const Footer = () => {
|
||||||
const getCurrentYear = () => {
|
const getCurrentYear = () => {
|
||||||
return new Date().getFullYear();
|
return new Date().getFullYear();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid
|
<Grid2
|
||||||
container
|
container
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: "auto",
|
marginTop: "auto",
|
||||||
zIndex: 1300,
|
zIndex: 1300,
|
||||||
minHeight: "24px",
|
minHeight: "24px",
|
||||||
}}
|
}}
|
||||||
justifyContent="center"
|
justifyContent="center">
|
||||||
>
|
<Grid2 item>
|
||||||
<Grid item>
|
<Typography
|
||||||
<Typography
|
inline="true"
|
||||||
inline="true"
|
variant="body1"
|
||||||
variant="body1"
|
fontFamily="Nanum Gothic Coding">
|
||||||
fontFamily="Nanum Gothic Coding"
|
Dan Dobos © {getCurrentYear()}
|
||||||
>
|
</Typography>
|
||||||
Dan Dobos © {getCurrentYear()}
|
</Grid2>
|
||||||
</Typography>
|
</Grid2>
|
||||||
</Grid>
|
);
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Footer;
|
export default Footer;
|
||||||
|
|||||||
@@ -2,25 +2,27 @@ import React from "react";
|
|||||||
|
|
||||||
import { AppBar, Toolbar, CssBaseline, Box } from "@mui/material";
|
import { AppBar, Toolbar, CssBaseline, Box } from "@mui/material";
|
||||||
|
|
||||||
|
import LanguageSwitcher from "layouts/common/languageSwitcher";
|
||||||
import DarkModeToggle from "layouts/common/darkModeToggle";
|
import DarkModeToggle from "layouts/common/darkModeToggle";
|
||||||
import HideOnScroll from "layouts/common/hideOnScroll";
|
import HideOnScroll from "layouts/common/hideOnScroll";
|
||||||
import Navigation from "./navigation";
|
import Navigation from "./navigation";
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<HideOnScroll>
|
<HideOnScroll>
|
||||||
<AppBar sx={{ position: "fixed", zIndex: 1301 }} elevation={0}>
|
<AppBar sx={{ position: "fixed", zIndex: 1301 }} elevation={0}>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Navigation />
|
<Navigation />
|
||||||
<Box sx={{ display: { sm: "block", xs: "none" } }}>
|
<Box sx={{ display: { sm: "inline-flex", xs: "none" } }}>
|
||||||
<DarkModeToggle />
|
<LanguageSwitcher />
|
||||||
</Box>
|
<DarkModeToggle />
|
||||||
</Toolbar>
|
</Box>
|
||||||
</AppBar>
|
</Toolbar>
|
||||||
</HideOnScroll>
|
</AppBar>
|
||||||
</>
|
</HideOnScroll>
|
||||||
);
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
export default Header;
|
export default Header;
|
||||||
|
|||||||
@@ -1,206 +1,220 @@
|
|||||||
import React, { useState, useEffect, createRef, useMemo, useRef } from "react";
|
import React, { useState, useEffect, createRef, useMemo, useRef } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
Tabs,
|
Tabs,
|
||||||
Tab,
|
Tab,
|
||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
IconButton,
|
IconButton,
|
||||||
SwipeableDrawer,
|
SwipeableDrawer,
|
||||||
Paper,
|
Paper,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
List,
|
List,
|
||||||
|
ListItemButton,
|
||||||
|
Box,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { useTheme } from "@mui/material/styles";
|
import { useTheme } from "@mui/material/styles";
|
||||||
import MenuIcon from "@mui/icons-material/Menu";
|
import MenuIcon from "@mui/icons-material/Menu";
|
||||||
import MenuOpenIcon from "@mui/icons-material/MenuOpen";
|
import MenuOpenIcon from "@mui/icons-material/MenuOpen";
|
||||||
|
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
import LanguageSwitcher from "layouts/common/languageSwitcher";
|
||||||
import DarkModeToggle from "layouts/common/darkModeToggle";
|
import DarkModeToggle from "layouts/common/darkModeToggle";
|
||||||
|
|
||||||
const Navigation = () => {
|
const Navigation = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const t = useIntl();
|
||||||
|
|
||||||
const matches = useMediaQuery(theme.breakpoints.down("sm"));
|
const matches = useMediaQuery(theme.breakpoints.down("sm"));
|
||||||
const iOS =
|
const iOS =
|
||||||
typeof navigator !== "undefined" &&
|
typeof navigator !== "undefined" &&
|
||||||
/iPad|iPhone|iPod/.test(navigator.userAgent);
|
/iPad|iPhone|iPod/.test(navigator.userAgent);
|
||||||
|
|
||||||
const [value, setValue] = useState(1);
|
const [value, setValue] = useState(1);
|
||||||
const [openDrawer, setOpenDrawer] = useState(false);
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
|
||||||
const tabsActions = useRef(null);
|
const tabsActions = useRef(null);
|
||||||
const wrapper = createRef();
|
const wrapper = createRef();
|
||||||
|
|
||||||
const handleTabsChange = (e, newValue) => {
|
const handleTabsChange = (e, newValue) => {
|
||||||
setValue(newValue);
|
setValue(newValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDrawerClose = () => {
|
const handleDrawerClose = () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setOpenDrawer(false);
|
setOpenDrawer(false);
|
||||||
}, 100);
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
const routes = useMemo(
|
const routes = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
name: "Home",
|
name: t.formatMessage({
|
||||||
link: "/",
|
id: "navigation.home",
|
||||||
activeIndex: 0,
|
defaultMessage: "Home",
|
||||||
},
|
}),
|
||||||
{
|
link: "/",
|
||||||
name: "Projects",
|
activeIndex: 0,
|
||||||
link: "/projects",
|
},
|
||||||
activeIndex: 1,
|
{
|
||||||
},
|
name: t.formatMessage({
|
||||||
{
|
id: "navigation.projects",
|
||||||
name: "Best Practices",
|
defaultMessage: "Projects",
|
||||||
link: "/best-practices",
|
}),
|
||||||
activeIndex: 2,
|
link: "/projects",
|
||||||
},
|
activeIndex: 1,
|
||||||
{
|
},
|
||||||
name: "Blog",
|
{
|
||||||
link: "/blog",
|
name: t.formatMessage({
|
||||||
activeIndex: 3,
|
id: "navigation.best-practices",
|
||||||
},
|
defaultMessage: "Best Practices",
|
||||||
{
|
}),
|
||||||
name: "About",
|
link: "/best-practices",
|
||||||
link: "/about",
|
activeIndex: 2,
|
||||||
activeIndex: 4,
|
},
|
||||||
},
|
{
|
||||||
],
|
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(() => {
|
useEffect(() => {
|
||||||
routes.forEach((route) => {
|
routes.forEach((route) => {
|
||||||
switch (window.location.pathname) {
|
switch (window.location.pathname) {
|
||||||
case `${route.link}`:
|
case `${route.link}`:
|
||||||
if (value !== route.activeIndex) {
|
if (value !== route.activeIndex) {
|
||||||
setValue(route.activeIndex);
|
setValue(route.activeIndex);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [value, routes]);
|
}, [value, routes]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container ref={wrapper}>
|
<Container ref={wrapper}>
|
||||||
<Paper
|
<Paper
|
||||||
elevation={0}
|
elevation={0}
|
||||||
sx={{
|
sx={{
|
||||||
display: { sm: "none", xs: "flex" },
|
display: { sm: "none", xs: "flex" },
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
backgroundColor: "inherit",
|
backgroundColor: "inherit",
|
||||||
color: theme.palette.secondary.contrastText,
|
color: theme.palette.secondary.contrastText,
|
||||||
boxShadow: "none",
|
boxShadow: "none",
|
||||||
}}
|
}}>
|
||||||
>
|
<IconButton
|
||||||
<IconButton
|
size="large"
|
||||||
size="large"
|
onClick={() => setOpenDrawer(!openDrawer)}
|
||||||
onClick={() => setOpenDrawer(!openDrawer)}
|
sx={{ color: theme.palette.text.secondary }}>
|
||||||
color="inherit"
|
{openDrawer ? <MenuOpenIcon /> : <MenuIcon />}
|
||||||
>
|
</IconButton>
|
||||||
{openDrawer ? (
|
<Box sx={{ display: "inline-flex" }}>
|
||||||
<MenuOpenIcon fontSize="inherit" />
|
<LanguageSwitcher />
|
||||||
) : (
|
<DarkModeToggle />
|
||||||
<MenuIcon fontSize="inherit" />
|
</Box>
|
||||||
)}
|
</Paper>
|
||||||
</IconButton>
|
|
||||||
<DarkModeToggle style={{ alignSelf: "right", color: "inherit" }} />
|
|
||||||
</Paper>
|
|
||||||
|
|
||||||
{matches ? (
|
{matches ? (
|
||||||
<SwipeableDrawer
|
<SwipeableDrawer
|
||||||
disableBackdropTransition={!iOS}
|
disableBackdropTransition={!iOS}
|
||||||
disableDiscovery={iOS}
|
disableDiscovery={iOS}
|
||||||
disableSwipeToOpen={false}
|
disableSwipeToOpen={false}
|
||||||
open={openDrawer}
|
open={openDrawer}
|
||||||
onOpen={() => setOpenDrawer(true)}
|
onOpen={() => setOpenDrawer(true)}
|
||||||
onClose={() => setOpenDrawer(false)}
|
onClose={() => setOpenDrawer(false)}
|
||||||
sx={{
|
sx={{
|
||||||
backgroundColor: "transparent",
|
backgroundColor: "transparent",
|
||||||
}}
|
}}>
|
||||||
>
|
<List sx={{ paddingTop: "4rem" }}>
|
||||||
<List sx={{ paddingTop: "4rem" }}>
|
{routes.map((route) => (
|
||||||
{routes.map((route) => (
|
<ListItem
|
||||||
<ListItem
|
sx={{
|
||||||
sx={{
|
// padding: "1.5rem 2rem ",
|
||||||
padding: "1.5rem 2rem ",
|
color: theme.palette.text.secondary,
|
||||||
color: theme.palette.text.secondary,
|
width: "100%",
|
||||||
width: "100%",
|
"&.Mui-selected": {
|
||||||
"&.Mui-selected": {
|
backgroundColor: theme.palette.background.paper,
|
||||||
backgroundColor: theme.palette.background.paper,
|
},
|
||||||
},
|
}}
|
||||||
}}
|
key={`${route.activeIndex}`}
|
||||||
key={`${route}${route.activeIndex}`}
|
disablePadding>
|
||||||
button
|
<ListItemButton
|
||||||
component={Link}
|
component={Link}
|
||||||
to={route.link}
|
to={route.link}
|
||||||
value={route.activeIndex}
|
value={route.activeIndex}
|
||||||
selected={value === route.activeIndex}
|
selected={value === route.activeIndex}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setValue(route.activeIndex);
|
setValue(route.activeIndex);
|
||||||
|
handleDrawerClose();
|
||||||
handleDrawerClose();
|
}}
|
||||||
}}
|
sx={{ padding: "1.5rem 2rem" }}>
|
||||||
>
|
<ListItemText
|
||||||
<ListItemText
|
disableTypography
|
||||||
disableTypography
|
sx={{
|
||||||
sx={{
|
alignItems: "flex-start",
|
||||||
alignItems: "flex-start",
|
fontSize: "1.2rem",
|
||||||
fontSize: "1.2rem",
|
textTransform: "capitalize",
|
||||||
textTransform: "capitalize",
|
}}>
|
||||||
}}
|
{route.name}
|
||||||
>
|
</ListItemText>
|
||||||
{route.name}
|
</ListItemButton>
|
||||||
</ListItemText>
|
</ListItem>
|
||||||
</ListItem>
|
))}
|
||||||
))}
|
</List>
|
||||||
</List>
|
</SwipeableDrawer>
|
||||||
</SwipeableDrawer>
|
) : (
|
||||||
) : (
|
<Paper
|
||||||
<Paper
|
elevation={0}
|
||||||
elevation={0}
|
sx={{
|
||||||
sx={{
|
display: { sm: "block", xs: "none" },
|
||||||
display: { sm: "block", xs: "none" },
|
}}>
|
||||||
}}
|
<Tabs
|
||||||
>
|
action={tabsActions}
|
||||||
<Tabs
|
value={value}
|
||||||
action={tabsActions}
|
onChange={handleTabsChange}
|
||||||
value={value}
|
centered
|
||||||
onChange={handleTabsChange}
|
TabIndicatorProps={{
|
||||||
centered
|
style: {
|
||||||
TabIndicatorProps={{
|
background: theme.palette.secondary.contrastText,
|
||||||
style: {
|
height: "3px",
|
||||||
background: theme.palette.secondary.contrastText,
|
},
|
||||||
height: "3px",
|
}}>
|
||||||
},
|
{routes.map((route) => (
|
||||||
}}
|
<Tab
|
||||||
>
|
disableRipple
|
||||||
{routes.map((route) => (
|
key={`${route.activeIndex}`}
|
||||||
<Tab
|
label={route.name}
|
||||||
disableRipple
|
component={Link}
|
||||||
key={`${route.activeIndex}`}
|
to={route.link}
|
||||||
label={route.name}
|
sx={{
|
||||||
component={Link}
|
fontSize: "1.2rem",
|
||||||
to={route.link}
|
"&.Mui-selected": {
|
||||||
sx={{
|
color: theme.palette.secondary.contrastText,
|
||||||
fontSize: "1.2rem",
|
},
|
||||||
"&.Mui-selected": {
|
}}
|
||||||
color: theme.palette.secondary.contrastText,
|
/>
|
||||||
},
|
))}
|
||||||
}}
|
</Tabs>
|
||||||
/>
|
</Paper>
|
||||||
))}
|
)}
|
||||||
</Tabs>
|
</Container>
|
||||||
</Paper>
|
);
|
||||||
)}
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
export default Navigation;
|
export default Navigation;
|
||||||
|
|||||||
+67
-72
@@ -1,82 +1,77 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Container, Grid, Typography, Link } from "@mui/material";
|
import { Container, Grid2, Typography, Link } from "@mui/material";
|
||||||
import { useTheme } from "@mui/material/styles";
|
import { useTheme } from "@mui/material/styles";
|
||||||
|
|
||||||
const About = () => {
|
const About = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container id="about">
|
<Container id="about">
|
||||||
<Grid
|
<Grid2
|
||||||
container
|
container
|
||||||
direction="row"
|
direction="row"
|
||||||
alignItems="stretch"
|
alignItems="stretch"
|
||||||
justifyContent="flex-end"
|
justifyContent="flex-end">
|
||||||
>
|
<div
|
||||||
<div
|
style={{
|
||||||
style={{
|
minHeight: "70vh",
|
||||||
minHeight: "70vh",
|
display: "flex",
|
||||||
display: "flex",
|
alignItems: "flex-end",
|
||||||
alignItems: "flex-end",
|
}}>
|
||||||
}}
|
<Grid2
|
||||||
>
|
container
|
||||||
<Grid
|
direction="column"
|
||||||
container
|
alignItems="flex-end"
|
||||||
direction="column"
|
justifyContent="flex-end"
|
||||||
alignItems="flex-end"
|
spacing={3}>
|
||||||
justifyContent="flex-end"
|
<Grid2 item>
|
||||||
spacing={3}
|
<Typography variant="h4" align="right" inline="true">
|
||||||
>
|
Software Developer
|
||||||
<Grid item>
|
</Typography>
|
||||||
<Typography variant="h4" align="right" inline="true">
|
</Grid2>
|
||||||
Software Developer
|
<Grid2 item>
|
||||||
</Typography>
|
<Typography
|
||||||
</Grid>
|
variant="h1"
|
||||||
<Grid item>
|
gutterBottom
|
||||||
<Typography
|
inline="true"
|
||||||
variant="h1"
|
sx={{
|
||||||
gutterBottom
|
fontFamily: "Chilanka",
|
||||||
inline="true"
|
textTransform: "uppercase",
|
||||||
sx={{
|
letterSpacing: "2rem",
|
||||||
fontFamily: "Chilanka",
|
textAlign: "left",
|
||||||
textTransform: "uppercase",
|
[theme.breakpoints.down("md")]: {
|
||||||
letterSpacing: "2rem",
|
textAlign: "right",
|
||||||
textAlign: "left",
|
letterSpacing: "1rem",
|
||||||
[theme.breakpoints.down("md")]: {
|
},
|
||||||
textAlign: "right",
|
}}>
|
||||||
letterSpacing: "1rem",
|
Dan Dobos
|
||||||
},
|
</Typography>
|
||||||
}}
|
</Grid2>
|
||||||
>
|
|
||||||
Dan Dobos
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Grid item>
|
<Grid2 item>
|
||||||
<Typography align="right" inline="true" variant="h6">
|
<Typography align="right" inline="true" variant="h6">
|
||||||
Characterized by the desire of understanding and implementing
|
Characterized by the desire of understanding and implementing
|
||||||
technological innovations.
|
technological innovations.
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid2>
|
||||||
|
|
||||||
<Grid item>
|
<Grid2 item>
|
||||||
<Typography align="right" inline="true">
|
<Typography align="right" inline="true">
|
||||||
Contact
|
Contact
|
||||||
</Typography>
|
</Typography>
|
||||||
<Link
|
<Link
|
||||||
variant="h6"
|
variant="h6"
|
||||||
href="mailto:danandreidobos@gmail.com"
|
href="mailto:danandreidobos@gmail.com"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
color="inherit"
|
color="inherit">
|
||||||
>
|
danandreidobos@gmail.com
|
||||||
danandreidobos@gmail.com
|
</Link>
|
||||||
</Link>
|
</Grid2>
|
||||||
</Grid>
|
</Grid2>
|
||||||
</Grid>
|
</div>
|
||||||
</div>
|
</Grid2>
|
||||||
</Grid>
|
</Container>
|
||||||
</Container>
|
);
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default About;
|
export default About;
|
||||||
|
|||||||
+27
-7
@@ -1,16 +1,36 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { BlogContent } from "data/Data";
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
// import { BlogContent } from "data/Data";
|
||||||
|
|
||||||
import BlogAccordion from "components/blog-accordion/BlogAccordion";
|
import BlogAccordion from "components/blog-accordion/BlogAccordion";
|
||||||
|
|
||||||
const Blog = () => {
|
const Blog = () => {
|
||||||
return (
|
const t = useIntl();
|
||||||
// <div style={{ minHeight: 'calc(100vh-128px)' }}>Blog ...in progress</div>
|
return (
|
||||||
<>
|
// <div style={{ minHeight: 'calc(100vh-128px)' }}>Blog ...in progress</div>
|
||||||
<BlogAccordion blogContent={BlogContent} />
|
<>
|
||||||
</>
|
<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;
|
export default Blog;
|
||||||
|
|||||||
@@ -1,50 +1,67 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Grid, Typography, Divider } from "@mui/material";
|
import { Grid2, Typography, Divider } from "@mui/material";
|
||||||
import About from "../about";
|
import About from "../about";
|
||||||
import Blog from "../blog";
|
import Blog from "../blog";
|
||||||
import BestPractices from "../best-practices";
|
import BestPractices from "../best-practices";
|
||||||
import Projects from "../projects";
|
import Projects from "../projects";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
return (
|
const t = useIntl();
|
||||||
<Grid container direction="row" alignItems="stretch" spacing={3}>
|
return (
|
||||||
<Grid item container direction="column">
|
<Grid2 container direction="row" alignItems="stretch" spacing={3}>
|
||||||
<Grid item>
|
<Grid2 item container direction="column">
|
||||||
<Typography variant="h3">Projects</Typography>
|
<Grid2 item>
|
||||||
<Divider variant="inset" />
|
<Typography variant="h3">
|
||||||
</Grid>
|
{t.formatMessage({
|
||||||
<Grid item>
|
id: "navigation.projects",
|
||||||
<Projects />
|
defaultMessage: "Projects",
|
||||||
</Grid>
|
})}
|
||||||
</Grid>
|
</Typography>
|
||||||
|
<Divider variant="inset" />
|
||||||
|
</Grid2>
|
||||||
|
<Grid2 item>
|
||||||
|
<Projects />
|
||||||
|
</Grid2>
|
||||||
|
</Grid2>
|
||||||
|
|
||||||
<Grid item container direction="column">
|
<Grid2 item container direction="column">
|
||||||
<Grid item>
|
<Grid2 item>
|
||||||
<Typography variant="h3">Best Practices</Typography>
|
<Typography variant="h3">
|
||||||
<Divider variant="inset" />
|
{t.formatMessage({
|
||||||
</Grid>
|
id: "navigation.best-practices",
|
||||||
<Grid item>
|
defaultMessage: "Best Practices",
|
||||||
<BestPractices />
|
})}
|
||||||
</Grid>
|
</Typography>
|
||||||
</Grid>
|
<Divider variant="inset" />
|
||||||
|
</Grid2>
|
||||||
|
<Grid2 item>
|
||||||
|
<BestPractices />
|
||||||
|
</Grid2>
|
||||||
|
</Grid2>
|
||||||
|
|
||||||
<Grid item container direction="column">
|
<Grid2 item container direction="column">
|
||||||
<Grid item>
|
<Grid2 item>
|
||||||
<Typography variant="h3">Blog</Typography>
|
<Typography variant="h3">
|
||||||
<Divider variant="inset" />
|
{t.formatMessage({
|
||||||
</Grid>
|
id: "navigation.blog",
|
||||||
<Grid item>
|
defaultMessage: "Blog",
|
||||||
<Blog />
|
})}
|
||||||
</Grid>
|
</Typography>
|
||||||
</Grid>
|
<Divider variant="inset" />
|
||||||
|
</Grid2>
|
||||||
|
<Grid2 item>
|
||||||
|
<Blog />
|
||||||
|
</Grid2>
|
||||||
|
</Grid2>
|
||||||
|
|
||||||
<Grid item container justifyContent="flex-end">
|
<Grid2 item container justifyContent="flex-end">
|
||||||
<Grid item>
|
<Grid2 item>
|
||||||
<About />
|
<About />
|
||||||
</Grid>
|
</Grid2>
|
||||||
</Grid>
|
</Grid2>
|
||||||
</Grid>
|
</Grid2>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Home;
|
export default Home;
|
||||||
|
|||||||
Reference in New Issue
Block a user