Prepared Nile v1

This commit is contained in:
Dunemask 2022-12-24 20:49:01 -05:00
parent ca9280f324
commit 0b19036190
145 changed files with 5541 additions and 1285 deletions

View file

@ -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
View 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
View 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>
);
}

View file

@ -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
View 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
View 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
View 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
View 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
View 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>
);
}

View 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>
);
}

View 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>
);
}

View 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>
);
}

View 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>
);
}

View 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>
);
}

View 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>
);
}

View 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
View 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>
);
}

View 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>
);
}

View file

@ -0,0 +1,3 @@
export default function NotFound() {
return <h1>Page not found!</h1>;
}