Prepared Nile v1
This commit is contained in:
parent
ca9280f324
commit
0b19036190
145 changed files with 5541 additions and 1285 deletions
|
@ -1,4 +1,8 @@
|
|||
import { createRoot } from "react-dom/client";
|
||||
import Nile from "./Nile.jsx";
|
||||
import Footer from "./pages/delta/Footer.jsx";
|
||||
|
||||
const root = createRoot(document.getElementById("root")).render(<Nile />);
|
||||
const nileRoot = createRoot(document.getElementById("root"));
|
||||
nileRoot.render(<Nile />);
|
||||
/*const footerRoot = createRoot(document.getElementById("footer"))
|
||||
footerRoot.render(<Footer />);*/
|
||||
|
|
4
src/Loading.jsx
Normal file
4
src/Loading.jsx
Normal file
|
@ -0,0 +1,4 @@
|
|||
import React from "react";
|
||||
export default function Loading() {
|
||||
return <h1>They see me loading, they hating...</h1>;
|
||||
}
|
58
src/Navbar.jsx
Normal file
58
src/Navbar.jsx
Normal file
|
@ -0,0 +1,58 @@
|
|||
// React
|
||||
import { Link } from "react-router-dom";
|
||||
import AppBar from "@mui/material/AppBar";
|
||||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Toolbar from "@mui/material/Toolbar";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import { Button } from "@mui/material";
|
||||
import useMediaQuery from "@mui/material/useMediaQuery";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
|
||||
export default function Navbar() {
|
||||
const theme = useTheme();
|
||||
const hideNavLinks = useMediaQuery(theme.breakpoints.down("md"));
|
||||
return (
|
||||
<AppBar position="fixed" sx={{ bgcolor: "black" }}>
|
||||
<Box
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
margin: "0 auto",
|
||||
width: "100%",
|
||||
maxWidth: 1200,
|
||||
display: "block",
|
||||
}}
|
||||
>
|
||||
<Toolbar disableGutters sx={{ display: "flex", padding: "0 10px" }}>
|
||||
<a href="/">
|
||||
<IconButton
|
||||
size="large"
|
||||
edge="start"
|
||||
color="inherit"
|
||||
aria-label="menu"
|
||||
sx={{ mr: -0.5 }}
|
||||
>
|
||||
<img src="/images/logo.png" width="40" height="40" />
|
||||
</IconButton>
|
||||
</a>
|
||||
<Typography variant="h6" noWrap component="div">
|
||||
Dunemask
|
||||
</Typography>
|
||||
{!hideNavLinks && (
|
||||
<Box sx={{ marginLeft: "auto" }}>
|
||||
<Link to="#portfolio" style={{ textDecoration: "none" }}>
|
||||
<Button sx={{ color: "white" }}>Portfolio</Button>
|
||||
</Link>
|
||||
<Link to="#achievements" style={{ textDecoration: "none" }}>
|
||||
<Button sx={{ color: "white" }}>Achievements</Button>
|
||||
</Link>
|
||||
<Link to="#contact" style={{ textDecoration: "none" }}>
|
||||
<Button sx={{ color: "white" }}>Contact</Button>
|
||||
</Link>
|
||||
</Box>
|
||||
)}
|
||||
</Toolbar>
|
||||
</Box>
|
||||
</AppBar>
|
||||
);
|
||||
}
|
16
src/Nile.jsx
16
src/Nile.jsx
|
@ -1,3 +1,17 @@
|
|||
import { BrowserRouter } from "react-router-dom";
|
||||
import Routing from "./Routing.jsx";
|
||||
import Navbar from "./Navbar.jsx";
|
||||
import { useEffect } from "react";
|
||||
export default function Nile() {
|
||||
return <h1>Dunemask's Website</h1>;
|
||||
useEffect(() => {
|
||||
const loadingElements = document.getElementById("loading");
|
||||
if (!loadingElements) return;
|
||||
loadingElements.remove();
|
||||
});
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Navbar />
|
||||
<Routing />
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
|
|
19
src/Routing.jsx
Normal file
19
src/Routing.jsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { Routes, Route, Navigate } from "react-router-dom";
|
||||
import AppBar from "@mui/material/AppBar";
|
||||
import Toolbar from "@mui/material/Toolbar";
|
||||
import Delta from "./pages/delta/Delta.jsx";
|
||||
import NotFound from "./pages/handlers/NotFound.jsx";
|
||||
import { useScrollToLocation } from "./hooks.jsx";
|
||||
export default function Routing() {
|
||||
useScrollToLocation();
|
||||
return (
|
||||
<div className="view">
|
||||
<Toolbar disableGutters />
|
||||
<Routes>
|
||||
<Route path="/" element={<Delta />} />
|
||||
<Route path="/404" element={<NotFound />} />
|
||||
<Route path="*" element={<Navigate to="/404" replace />} />
|
||||
</Routes>
|
||||
</div>
|
||||
);
|
||||
}
|
42
src/css/footer.css
Normal file
42
src/css/footer.css
Normal file
|
@ -0,0 +1,42 @@
|
|||
footer {
|
||||
padding-top: 100px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding-top: 10px;
|
||||
color: black;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.connections {
|
||||
margin-right: 0;
|
||||
margin-left: auto;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.connections a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
padding: 0px 4px;
|
||||
width: 40;
|
||||
height: 40;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.connections a:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.copyright {
|
||||
display: flex;
|
||||
margin: auto 0;
|
||||
}
|
||||
|
||||
.copyright h1 {
|
||||
padding-left: 10px;
|
||||
font-size: 10px;
|
||||
line-height: inherit;
|
||||
}
|
23
src/hooks.jsx
Normal file
23
src/hooks.jsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
import React from "react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
export function useScrollToLocation() {
|
||||
const scrolledRef = React.useRef(false);
|
||||
const navigate = useNavigate();
|
||||
const { hash } = useLocation();
|
||||
const hashRef = React.useRef(hash);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!hash) return;
|
||||
if (hashRef.current !== hash) {
|
||||
hashRef.current = hash;
|
||||
scrolledRef.current = false;
|
||||
}
|
||||
if (scrolledRef.current) return;
|
||||
const id = hash.replace("#", "");
|
||||
const element = document.getElementById(id);
|
||||
if (!element) return;
|
||||
navigate();
|
||||
element.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
scrolledRef.current = true;
|
||||
});
|
||||
}
|
19
src/pages/delta/About.jsx
Normal file
19
src/pages/delta/About.jsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
export default function Projects() {
|
||||
return (
|
||||
<Box>
|
||||
<Box sx={{ maxWidth: 570, margin: "4rem auto", padding: "2rem" }}>
|
||||
<Typography variant="h4" component="div" sx={{ fontWeight: 600 }}>
|
||||
React Fullstack Software Engineer
|
||||
</Typography>
|
||||
<Typography variant="body1">
|
||||
Specializing in DevOps tools and code reliability. If you're a
|
||||
business seeking to improve developer velocity or are looking to hire,
|
||||
contact me here
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
45
src/pages/delta/Delta.jsx
Normal file
45
src/pages/delta/Delta.jsx
Normal file
|
@ -0,0 +1,45 @@
|
|||
import React from "react";
|
||||
import Box from "@mui/material/Box";
|
||||
import About from "./About.jsx";
|
||||
import Projects from "./Projects.jsx";
|
||||
import Environments from "./Environments.jsx";
|
||||
import Footer from "./Footer.jsx";
|
||||
|
||||
const Skills = React.lazy(() => import("./Skills.jsx"));
|
||||
const Social = React.lazy(() => import("./Social.jsx"));
|
||||
|
||||
export default function Delta() {
|
||||
return (
|
||||
<Box id="delta">
|
||||
<div style={{ position: "relative", display: "block" }}>
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
display: "flex",
|
||||
zIndex: -1,
|
||||
opacity: 0.2,
|
||||
marginTop: -40,
|
||||
marginLeft: -20,
|
||||
overflow: "hidden",
|
||||
justifyContent: "center",
|
||||
margin: "auto",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src="/images/phx-mini.png"
|
||||
style={{ minWidth: "260px", width: "50%", maxWidth: 512 }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ margin: "0 auto", textAlign: "center", maxWidth: 1200 }}>
|
||||
<About />
|
||||
<Projects />
|
||||
<Skills />
|
||||
{/* <Environments /> */}
|
||||
<Social />
|
||||
</div>
|
||||
<Footer />
|
||||
</Box>
|
||||
);
|
||||
}
|
82
src/pages/delta/Environments.jsx
Normal file
82
src/pages/delta/Environments.jsx
Normal file
|
@ -0,0 +1,82 @@
|
|||
import { SiKubernetes } from "react-icons/si";
|
||||
import Accordion from "@mui/material/Accordion";
|
||||
import AccordionSummary from "@mui/material/AccordionSummary";
|
||||
import AccordionDetails from "@mui/material/AccordionDetails";
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
import Box from "@mui/material/Box";
|
||||
|
||||
export default function Environments() {
|
||||
return (
|
||||
<Box style={{ padding: 10 }}>
|
||||
<Accordion
|
||||
style={{ boxShadow: "none" }}
|
||||
defaultExpanded
|
||||
disableGutters
|
||||
square
|
||||
>
|
||||
<AccordionSummary
|
||||
content={{ margin: 0 }}
|
||||
expandIcon={<ExpandMoreIcon />}
|
||||
style={{ margin: 0 }}
|
||||
>
|
||||
<h3>Environments</h3>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
flex: 1,
|
||||
margin: "auto",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
<Box style={{ flex: 1, textAlign: "left" }}>
|
||||
<div style={{ display: "inline-flex" }}>
|
||||
<h3 style={{ fontSize: 20 }}>Kubernetes</h3>
|
||||
<SiKubernetes
|
||||
style={{
|
||||
margin: "auto",
|
||||
marginLeft: 10,
|
||||
width: 40,
|
||||
height: 40,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<p>
|
||||
Section about deployment of applications to a Kubernetes
|
||||
cluster.
|
||||
</p>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
flex: 1,
|
||||
margin: "auto",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
<Box style={{ flex: 1, textAlign: "left" }}>
|
||||
<div style={{ display: "inline-flex" }}>
|
||||
<h3 style={{ fontSize: 20 }}>Garden</h3>
|
||||
<img
|
||||
src="/images/gardenio-icon.svg"
|
||||
style={{
|
||||
margin: "auto",
|
||||
marginLeft: 10,
|
||||
width: 28,
|
||||
height: 28,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<p>
|
||||
Section about deployment using Garden for development and
|
||||
production
|
||||
</p>
|
||||
</Box>
|
||||
</Box>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</Box>
|
||||
);
|
||||
}
|
24
src/pages/delta/Footer.jsx
Normal file
24
src/pages/delta/Footer.jsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
import GitHubIcon from "@mui/icons-material/GitHub";
|
||||
import LinkedInIcon from "@mui/icons-material/LinkedIn";
|
||||
import "../../css/footer.css";
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<div className="footer" style={{ maxWidth: 1200, margin: "0 auto" }}>
|
||||
<div className="copyright">
|
||||
<h1>{`Dunemask © ${new Date().getFullYear()} All Rights Reserved`}</h1>
|
||||
</div>
|
||||
<div className="connections">
|
||||
<a href="/">
|
||||
<img src="/images/dune-wing.svg" width="24" height="24" />
|
||||
</a>
|
||||
<a href="https://github.com/dunemask">
|
||||
<GitHubIcon style={{ color: "black" }} />
|
||||
</a>
|
||||
<a href="https://www.linkedin.com/in/elijah-parker-dunemask">
|
||||
<LinkedInIcon style={{ color: "black" }} />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
28
src/pages/delta/PhotoHover.jsx
Normal file
28
src/pages/delta/PhotoHover.jsx
Normal file
|
@ -0,0 +1,28 @@
|
|||
import Modal from "@mui/material/Modal";
|
||||
import Fade from "@mui/material/Fade";
|
||||
|
||||
export default function PhotoHover({ image, alt, open, setOpen }) {
|
||||
const handleClose = () => setOpen(false);
|
||||
const openFullImage = () => window.open(image);
|
||||
return (
|
||||
<Modal
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
closeAfterTransition
|
||||
>
|
||||
<Fade in={open} timeout={500}>
|
||||
<img
|
||||
src={image}
|
||||
alt={alt}
|
||||
style={{ maxHeight: "90%", maxWidth: "90%", outline: "none" }}
|
||||
onClick={openFullImage}
|
||||
/>
|
||||
</Fade>
|
||||
</Modal>
|
||||
);
|
||||
}
|
93
src/pages/delta/ProjectTile.jsx
Normal file
93
src/pages/delta/ProjectTile.jsx
Normal file
|
@ -0,0 +1,93 @@
|
|||
import Box from "@mui/material/Box";
|
||||
import useMediaQuery from "@mui/material/useMediaQuery";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
export default function ProjectTile({
|
||||
image,
|
||||
title,
|
||||
year,
|
||||
children: description,
|
||||
disableGutter,
|
||||
openPhoto,
|
||||
}) {
|
||||
const theme = useTheme();
|
||||
const smallMode = useMediaQuery(theme.breakpoints.down("md"));
|
||||
|
||||
const imageClick = () => openPhoto(image);
|
||||
return (
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
alignItems: "center!important",
|
||||
flexWrap: smallMode ? "wrap" : "nowrap",
|
||||
marginBottom: disableGutter ? "" : "4rem",
|
||||
}}
|
||||
>
|
||||
<div style={{ width: "100%" }}>
|
||||
<img
|
||||
src={image}
|
||||
style={{ width: "90%", maxWidth: 512, marginLeft: "auto" }}
|
||||
onClick={imageClick}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Box
|
||||
style={{
|
||||
width: "100%",
|
||||
alignItems: "flex-start",
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
flexDirection: "column",
|
||||
margin: "auto",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "inline-flex",
|
||||
width: "100%",
|
||||
justifyContent: smallMode ? "center" : "",
|
||||
}}
|
||||
>
|
||||
<Typography variant="h5" component="div" style={{ fontWeight: 800 }}>
|
||||
{title}
|
||||
</Typography>
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: "#f3ac20",
|
||||
color: "white",
|
||||
borderRadius: ".25rem",
|
||||
padding: 5,
|
||||
fontWeight: 500,
|
||||
margin: "auto 0 auto 10px",
|
||||
}}
|
||||
>
|
||||
{year}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: smallMode ? "center" : "",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
gutterBottom
|
||||
variant="subtitle1"
|
||||
component="div"
|
||||
style={{
|
||||
textAlign: smallMode ? "" : "left",
|
||||
marginTop: 10,
|
||||
width: "80%",
|
||||
maxWidth: 512,
|
||||
}}
|
||||
>
|
||||
{description}
|
||||
</Typography>
|
||||
</div>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
110
src/pages/delta/Projects copy.jsx
Normal file
110
src/pages/delta/Projects copy.jsx
Normal file
|
@ -0,0 +1,110 @@
|
|||
import { FaReact, FaPython, FaJava } from "react-icons/fa";
|
||||
import { SiKubernetes } from "react-icons/si";
|
||||
import Accordion from "@mui/material/Accordion";
|
||||
import AccordionSummary from "@mui/material/AccordionSummary";
|
||||
import AccordionDetails from "@mui/material/AccordionDetails";
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
import Box from "@mui/material/Box";
|
||||
|
||||
export default function Projects() {
|
||||
return (
|
||||
<Box style={{ padding: 10 }}>
|
||||
<Accordion
|
||||
style={{ boxShadow: "none", margin: 0 }}
|
||||
defaultExpanded
|
||||
disableGutters
|
||||
square
|
||||
>
|
||||
<AccordionSummary
|
||||
content={{ margin: 0 }}
|
||||
expandIcon={<ExpandMoreIcon />}
|
||||
style={{ margin: 0 }}
|
||||
>
|
||||
<h3>Projects</h3>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Box
|
||||
className="top-projects"
|
||||
style={{
|
||||
display: "flex",
|
||||
flex: 1,
|
||||
margin: "auto",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
<Box style={{ flex: 1, padding: "0 10px" }}>
|
||||
<div style={{ display: "inline-flex" }}>
|
||||
<h3>React</h3>
|
||||
<FaReact
|
||||
style={{
|
||||
margin: "auto",
|
||||
marginLeft: 10,
|
||||
width: 20,
|
||||
height: 20,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<p>Khufu</p>
|
||||
<p>Qualiteer</p>
|
||||
</Box>
|
||||
<Box style={{ flex: 1, padding: "0 10px" }}>
|
||||
<div style={{ display: "inline-flex" }}>
|
||||
<h3>Kubernetes</h3>
|
||||
<SiKubernetes
|
||||
style={{
|
||||
margin: "auto",
|
||||
marginLeft: 10,
|
||||
width: 20,
|
||||
height: 20,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<p>Oasis</p>
|
||||
<p>Garden</p>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
className="top-projects"
|
||||
style={{
|
||||
display: "flex",
|
||||
flex: 1,
|
||||
margin: "auto",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
<Box style={{ flex: 1, padding: "0 10px" }}>
|
||||
<div style={{ display: "inline-flex" }}>
|
||||
<h3>Python</h3>
|
||||
<FaPython
|
||||
style={{
|
||||
margin: "auto",
|
||||
marginLeft: 10,
|
||||
width: 20,
|
||||
height: 20,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<p>Reed</p>
|
||||
<p>TODO</p>
|
||||
</Box>
|
||||
<Box style={{ flex: 1, padding: "0 10px" }}>
|
||||
<div style={{ display: "inline-flex" }}>
|
||||
<h3>Java</h3>
|
||||
<FaJava
|
||||
style={{
|
||||
margin: "auto",
|
||||
marginLeft: 10,
|
||||
width: 20,
|
||||
height: 20,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<p>Dunemasking</p>
|
||||
<p>JavaFX</p>
|
||||
</Box>
|
||||
</Box>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</Box>
|
||||
);
|
||||
}
|
82
src/pages/delta/Projects.jsx
Normal file
82
src/pages/delta/Projects.jsx
Normal file
|
@ -0,0 +1,82 @@
|
|||
import { useState } from "react";
|
||||
import Box from "@mui/material/Box";
|
||||
|
||||
import ProjectTile from "./ProjectTile.jsx";
|
||||
import PhotoHover from "./PhotoHover.jsx";
|
||||
|
||||
export default function Projects() {
|
||||
const [image, setImage] = useState();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
function openPhoto(image) {
|
||||
setImage(image);
|
||||
setOpen(true);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box style={{ padding: 10, scrollMarginTop: "4rem" }} id="portfolio">
|
||||
<PhotoHover
|
||||
image={image}
|
||||
open={open}
|
||||
setOpen={setOpen}
|
||||
alt={"Missing Project Photo"}
|
||||
/>
|
||||
<div style={{ display: "flex" }}>
|
||||
<h3 style={{ fontSize: "1.75rem", margin: "2rem auto" }}>Portfolio</h3>
|
||||
</div>
|
||||
<ProjectTile
|
||||
image="/portfolio/projects/qualiteer.png"
|
||||
title="Qualiteer"
|
||||
year="2022"
|
||||
openPhoto={openPhoto}
|
||||
>
|
||||
Manage failing tests and silence unecessary alerts. Check the state of
|
||||
your services worldwide and improve developer confidence with a simple
|
||||
interface.
|
||||
</ProjectTile>
|
||||
<ProjectTile
|
||||
image="/portfolio/projects/khufu.png"
|
||||
title="Khufu"
|
||||
year="2021"
|
||||
openPhoto={openPhoto}
|
||||
>
|
||||
Basic cloud file management built on React class components. Simple
|
||||
interface allows users to upload, delete, and multiple files.
|
||||
</ProjectTile>
|
||||
<ProjectTile
|
||||
image="/portfolio/projects/codepen.png"
|
||||
title="Codepen"
|
||||
year="2020"
|
||||
openPhoto={openPhoto}
|
||||
>
|
||||
Visual replication of the website{" "}
|
||||
<a
|
||||
href="https://codepen.io"
|
||||
style={{ color: "black", fontFamily: "inherit" }}
|
||||
>
|
||||
codepen.io
|
||||
</a>{" "}
|
||||
webpage in 2020. Simple demonstration of css and html
|
||||
</ProjectTile>
|
||||
<ProjectTile
|
||||
image="/portfolio/projects/movieplayer.png"
|
||||
title="Media Player"
|
||||
year="2018"
|
||||
openPhoto={openPhoto}
|
||||
>
|
||||
Simple media player built on javafx. Player supports media seeking,
|
||||
playback controls, and speed distortion.
|
||||
</ProjectTile>
|
||||
<ProjectTile
|
||||
image="/portfolio/projects/voxelcraft.png"
|
||||
title="Voxelcraft"
|
||||
year="2018"
|
||||
openPhoto={openPhoto}
|
||||
>
|
||||
Voxel game built on a simple rendering engine written with JavaFX.
|
||||
Generate your terrain and form your ideal world by exploring and
|
||||
harvesting resources.
|
||||
</ProjectTile>
|
||||
</Box>
|
||||
);
|
||||
}
|
51
src/pages/delta/SkillPaper.jsx
Normal file
51
src/pages/delta/SkillPaper.jsx
Normal file
|
@ -0,0 +1,51 @@
|
|||
import Box from "@mui/material/Box";
|
||||
import Card from "@mui/material/Card";
|
||||
import CardContent from "@mui/material/CardContent";
|
||||
import CardMedia from "@mui/material/CardMedia";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
export default function SkillPaper({
|
||||
src,
|
||||
bgColor,
|
||||
fgColor,
|
||||
heading,
|
||||
Icon,
|
||||
openPhoto,
|
||||
}) {
|
||||
const mediaClick = () => openPhoto(src);
|
||||
return (
|
||||
<Box>
|
||||
<Card
|
||||
sx={{
|
||||
margin: "0 auto",
|
||||
boxShadow:
|
||||
"0 10px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)",
|
||||
}}
|
||||
>
|
||||
<CardMedia
|
||||
sx={{ minHeight: 380 }}
|
||||
image={src}
|
||||
title="Fullstack Development Certificate"
|
||||
onClick={mediaClick}
|
||||
/>
|
||||
<CardContent sx={{ color: fgColor, backgroundColor: bgColor }}>
|
||||
<Typography variant="h5" component="div">
|
||||
<div style={{ display: "inline-flex" }}>
|
||||
<h3>{heading}</h3>
|
||||
{
|
||||
<Icon
|
||||
style={{
|
||||
margin: "auto",
|
||||
marginLeft: 10,
|
||||
width: 24,
|
||||
height: 24,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Box>
|
||||
);
|
||||
}
|
194
src/pages/delta/Skills.jsx
Normal file
194
src/pages/delta/Skills.jsx
Normal file
|
@ -0,0 +1,194 @@
|
|||
import React, { useState } from "react";
|
||||
import { FaReact, FaPython, FaJava, FaHtml5 } from "react-icons/fa";
|
||||
import { SiJavascript } from "react-icons/si";
|
||||
import Carousel from "react-material-ui-carousel";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Box from "@mui/material/Box";
|
||||
import Card from "@mui/material/Card";
|
||||
import CardContent from "@mui/material/CardContent";
|
||||
import CardMedia from "@mui/material/CardMedia";
|
||||
import SkillPaper from "./SkillPaper.jsx";
|
||||
import PhotoHover from "./PhotoHover.jsx";
|
||||
|
||||
export default function Skills() {
|
||||
const [image, setImage] = useState();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
function openPhoto(image) {
|
||||
setImage(image);
|
||||
setOpen(true);
|
||||
}
|
||||
|
||||
const bottegaCertClick = () => openPhoto("/portfolio/bottega-cert.png");
|
||||
const testoutCertClick = () => openPhoto("/portfolio/linux-cert.png");
|
||||
|
||||
const skills = [
|
||||
<SkillPaper
|
||||
openPhoto={openPhoto}
|
||||
src="/portfolio/iq/python.png"
|
||||
fgColor="white"
|
||||
bgColor="#3f7ed4"
|
||||
heading="Python"
|
||||
Icon={FaPython}
|
||||
/>,
|
||||
<SkillPaper
|
||||
openPhoto={openPhoto}
|
||||
src="/portfolio/iq/react.png"
|
||||
fgColor="black"
|
||||
bgColor="#61dafb"
|
||||
heading="React"
|
||||
Icon={FaReact}
|
||||
/>,
|
||||
<SkillPaper
|
||||
openPhoto={openPhoto}
|
||||
src="/portfolio/iq/java.png"
|
||||
fgColor="white"
|
||||
bgColor="#ea8c10 "
|
||||
heading="Java"
|
||||
Icon={FaJava}
|
||||
/>,
|
||||
<SkillPaper
|
||||
openPhoto={openPhoto}
|
||||
src="/portfolio/iq/javascript.png"
|
||||
fgColor="black"
|
||||
bgColor="#edd43a"
|
||||
heading="Javascript"
|
||||
Icon={SiJavascript}
|
||||
/>,
|
||||
<SkillPaper
|
||||
openPhoto={openPhoto}
|
||||
src="/portfolio/iq/html.png"
|
||||
fgColor="white"
|
||||
bgColor="#e9562f"
|
||||
heading="HTML 5"
|
||||
Icon={FaHtml5}
|
||||
/>,
|
||||
];
|
||||
|
||||
return (
|
||||
<Box style={{ padding: 10, scrollMarginTop: "4rem" }} id="achievements">
|
||||
<PhotoHover
|
||||
image={image}
|
||||
open={open}
|
||||
setOpen={setOpen}
|
||||
alt={"Certificate"}
|
||||
/>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
flex: 1,
|
||||
margin: "auto",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
<Box style={{ flex: 1 }}>
|
||||
<div style={{ display: "flex" }}>
|
||||
<h3 style={{ fontSize: 20, margin: "2rem auto" }}>
|
||||
Certifications
|
||||
</h3>
|
||||
</div>
|
||||
<Box
|
||||
style={{
|
||||
flex: 1,
|
||||
textAlign: "left",
|
||||
display: "flex",
|
||||
flexGrow: 1,
|
||||
flexWrap: "wrap",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<Card
|
||||
sx={{
|
||||
maxWidth: 374,
|
||||
margin: "10px auto",
|
||||
boxShadow:
|
||||
"0 10px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)",
|
||||
}}
|
||||
>
|
||||
<CardMedia
|
||||
sx={{ minHeight: 320, maxWidth: 374 }}
|
||||
image="/portfolio/bottega-cert.png"
|
||||
title="Fullstack Development Certificate"
|
||||
onClick={bottegaCertClick}
|
||||
/>
|
||||
<CardContent sx={{ color: "white", backgroundColor: "#1d9246" }}>
|
||||
<Typography gutterBottom variant="h5" component="div">
|
||||
Fullstack Certification
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
Certificate of profeciency in Python3, React, CSS, and
|
||||
Javascript
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card
|
||||
sx={{
|
||||
maxWidth: 374,
|
||||
margin: "10px auto",
|
||||
boxShadow:
|
||||
"0 10px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)",
|
||||
}}
|
||||
>
|
||||
<CardMedia
|
||||
sx={{ minHeight: 320, maxWidth: 374 }}
|
||||
image="/portfolio/linux-cert.png"
|
||||
title="Linux Client Administration Certificate"
|
||||
onClick={testoutCertClick}
|
||||
/>
|
||||
<CardContent
|
||||
sx={{
|
||||
color: "white",
|
||||
backgroundColor: "#c3802b",
|
||||
}}
|
||||
>
|
||||
<Typography gutterBottom variant="h5" component="div">
|
||||
Linux Administration Certificate
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
Certificate of profeciency in Linux client administration
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
flex: 1,
|
||||
margin: "auto",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
<Box style={{ flex: 1, textAlign: "left" }}>
|
||||
<div style={{ display: "flex", paddingTop: 30 }}>
|
||||
<h3 style={{ fontSize: 20, margin: "2rem auto" }}>
|
||||
Pluralsight Scores
|
||||
</h3>
|
||||
</div>
|
||||
<Box sx={{ display: "block" }}>
|
||||
<Box
|
||||
sx={{
|
||||
maxWidth: 374,
|
||||
display: "block",
|
||||
margin: "auto",
|
||||
boxShadow:
|
||||
"0 10px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)",
|
||||
}}
|
||||
>
|
||||
<Carousel
|
||||
interval={8000}
|
||||
navButtonsAlwaysVisible
|
||||
indicatorContainerProps={{ style: { display: "none" } }}
|
||||
>
|
||||
{skills.map((skill, i) => (
|
||||
<React.Fragment key={skill}>{skill}</React.Fragment>
|
||||
))}
|
||||
</Carousel>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
56
src/pages/delta/Social.jsx
Normal file
56
src/pages/delta/Social.jsx
Normal file
|
@ -0,0 +1,56 @@
|
|||
import Accordion from "@mui/material/Accordion";
|
||||
import AccordionSummary from "@mui/material/AccordionSummary";
|
||||
import Box from "@mui/material/Box";
|
||||
import MailIcon from "@mui/icons-material/Mail";
|
||||
import GitHubIcon from "@mui/icons-material/GitHub";
|
||||
import LinkedInIcon from "@mui/icons-material/LinkedIn";
|
||||
import { FaGitlab } from "react-icons/fa";
|
||||
|
||||
const socialLinks = [
|
||||
{
|
||||
url: "https://www.linkedin.com/in/elijah-parker-dunemask/",
|
||||
icon: <LinkedInIcon />,
|
||||
},
|
||||
{
|
||||
url: "mailto: elijahglennparker@outlook.com",
|
||||
icon: <MailIcon />,
|
||||
},
|
||||
{
|
||||
url: "https://gitlab.com/dunemask",
|
||||
icon: <FaGitlab />,
|
||||
},
|
||||
{
|
||||
url: "https://github.com/dunemask",
|
||||
icon: <GitHubIcon />,
|
||||
},
|
||||
];
|
||||
|
||||
export default function Social() {
|
||||
return (
|
||||
<Box style={{ padding: 10, scrollMarginTop: "4rem" }} id="contact">
|
||||
<Accordion
|
||||
style={{ boxShadow: "none" }}
|
||||
defaultExpanded
|
||||
disableGutters
|
||||
square
|
||||
>
|
||||
<AccordionSummary content={{ margin: 0 }} style={{ margin: 0 }}>
|
||||
<h3 style={{ paddingRight: 20 }}>Social</h3>
|
||||
<Box
|
||||
style={{ display: "flex", marginLeft: "auto", flexWrap: "wrap" }}
|
||||
>
|
||||
{socialLinks.map((v, i) => (
|
||||
<a
|
||||
key={i}
|
||||
href={v.url}
|
||||
style={{ margin: "auto 0", color: "black", padding: "10px" }}
|
||||
>
|
||||
{v.icon}
|
||||
</a>
|
||||
))}
|
||||
</Box>
|
||||
</AccordionSummary>
|
||||
</Accordion>
|
||||
</Box>
|
||||
);
|
||||
}
|
3
src/pages/handlers/NotFound.jsx
Normal file
3
src/pages/handlers/NotFound.jsx
Normal file
|
@ -0,0 +1,3 @@
|
|||
export default function NotFound() {
|
||||
return <h1>Page not found!</h1>;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue