[FEATURE] Add Resume, Contact, Routing Fix, and About sections (#9)

Co-authored-by: dunemask <dunemask@gmail.com>
Co-authored-by: Dunemask <dunemask@gmail.com>
Reviewed-on: https://gitea.dunemask.net/elysium/nile/pulls/9
This commit is contained in:
dunemask 2023-09-25 20:49:09 +00:00
parent cc360597f8
commit 7d3c264b30
17 changed files with 500 additions and 64 deletions

View file

@ -26,7 +26,7 @@ keepalive_timeout 65;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
try_files $uri /index.html;
}
location ~ ^/$ {

BIN
public/resume/About.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View file

@ -17,10 +17,12 @@ import { useTheme } from "@mui/material/styles";
import MenuIcon from "@mui/icons-material/Menu";
const links = [
// { url: "/", title: "Home" },
{ url: "/#portfolio", title: "Portfolio" },
{ url: "/#achievements", title: "Achivements" },
// { url: "/#achievements", title: "Achievements" },
{ url: "/#about", title: "About" },
{ url: "/#contact", title: "Contact" },
//{ url: "/references", title: "References" },
// { url: "/resume", title: "Resume" },
];
export default function Navbar() {

View file

@ -1,8 +1,14 @@
import { Routes, Route, Navigate } from "react-router-dom";
import Toolbar from "@mui/material/Toolbar";
import Delta from "./pages/delta/Delta.jsx";
import References from "./pages/references/References.jsx";
import Resume from "./pages/resume/Resume.jsx";
import { useScrollToLocation } from "./hooks.jsx";
const redirects = [
{ path: "/r1", rewrite: "/resume" },
{ path: "/r2", rewrite: "/resume" },
{ path: "/r3", rewrite: "/resume" },
];
export default function Routing() {
useScrollToLocation();
return (
@ -10,7 +16,10 @@ export default function Routing() {
<Toolbar disableGutters />
<Routes>
<Route path="/" element={<Delta />} />
{/*<Route path="/references" element={<References />} />*/}
{/* <Route path="/resume" element={<Resume />} /> */}
{redirects.map((r, i) => (
<Route key={i} path={r.path} element={<Navigate to={r.rewrite} />} />
))}
<Route path="*" element={<Navigate to="/" replace />} />
<Route path="/*" element={<Navigate to="/" replace />} />
</Routes>

View file

@ -0,0 +1,18 @@
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import "@css/experience-display.css";
export default function ExperienceDisplay(props) {
const { title, subtitle, children } = props;
return (
<Box
className="experience-display"
sx={{ borderLeft: "2px solid #F3AC20", paddingLeft: "20px", mt: "1rem" }}
>
<Typography variant="h6">{title}</Typography>
<Typography variant="body2" sx={{ opacity: 0.7 }}>
{subtitle}
</Typography>
<Box className="experience-display-content">{children}</Box>
</Box>
);
}

View file

@ -0,0 +1,3 @@
export default function PageNav(props) {
const { links } = props;
}

View file

@ -0,0 +1,9 @@
.experience-display::before {
content: "";
position: absolute;
padding: 6px;
border: 2px solid #f3ac20;
border-radius: 50%;
margin-left: -28px;
margin-top: -16px;
}

View file

@ -19,7 +19,11 @@ export function useScrollToLocation() {
const id = hash.replace("#", "");
const element = document.getElementById(id);
if (!element) return;
element.scrollIntoView({ behavior: "smooth", block: "start" });
element.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "nearest",
});
scrolledRef.current = true;
});
}

View file

@ -1,28 +1,135 @@
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useTheme } from "@mui/material/styles";
export default function Projects() {
const dob = new Date(2002, 4, 3);
const age = Math.abs(
new Date(Date.now() - dob.getTime()).getUTCFullYear() - 1970,
);
function AboutContact(props) {
const { title, info } = props;
return (
<Typography sx={{ fontWeight: 600 }}>
{`${title}:`}
<span
style={{
fontFamily: "inherit",
paddingLeft: ".5rem",
fontSize: "14px",
}}
>
{info}
</span>
</Typography>
);
}
export default function About() {
const theme = useTheme();
const fullSizePhoto = useMediaQuery(theme.breakpoints.down("md"));
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{" "}
<a
href="https://www.linkedin.com/in/elijah-parker-dunemask"
style={{
textDecoration: "none",
fontSize: "inherit",
fontFamily: "inherit",
<Box
sx={{
m: "0rem 0 2rem 0",
padding: "0 2rem",
textAlign: "left",
}}
style={{ scrollMarginTop: "4rem" }}
id="about"
>
<div style={{ display: "flex" }}>
<Typography variant="h2" sx={{ margin: "2rem auto", fontSize: 30 }}>
About
</Typography>
</div>
<Box sx={{ display: "flex", flexWrap: "wrap" }}>
{!fullSizePhoto && (
<img
src="/resume/About.jpeg"
style={{
width: "100%",
maxWidth: "400px",
height: "100%",
padding: "0 1rem",
borderRadius: "10%",
}}
/>
)}
{fullSizePhoto && (
<img
src="/resume/About.jpeg"
style={{
width: "90%",
height: "90%",
margin: "0 auto",
borderRadius: "10%",
}}
/>
)}
<Box
sx={{
minWidth: "180px",
maxWidth: fullSizePhoto ? "100%" : "700px",
width: "100%",
display: fullSizePhoto ? "flex" : "block",
flex: "1 1 180px",
flexWrap: "wrap",
margin: fullSizePhoto ? "0" : "0 0 0 1rem",
pt: fullSizePhoto ? "2rem" : "0",
}}
>
here
</a>
</Typography>
<Typography variant="h6" component="div" sx={{ fontWeight: 600 }}>
React Fullstack Software Engineer
</Typography>
<Typography variant="body1">
Hello! I'm Elijah Parker, a fullstack software engineer from Utah.
I have a passion for developing software that achieves "the
impossible". I have experience using a wide variety of
technologies including React, Python, Java, and Kubernetes. I'm
currently seeking an entry-level part time position or internship
with flexible hours to accommodate pursuit of a bachelorette
degree.
</Typography>
<Box
className="about-contacts"
sx={{
pt: "2rem",
display: "flex",
flexWrap: "wrap",
width: "100%",
overflow: "hidden",
}}
>
<Box className="about-contacts-left" sx={{ minWidth: "50%" }}>
<AboutContact
title="Email"
info={
<a
href="mailto:elijahglennparker@outlook.com"
style={{ textDecoration: "none", fontSize: "14px" }}
>
elijahglennparker@outlook.com
</a>
}
/>
<AboutContact title="From" info="Utah, USA" />
</Box>
<Box className="about-contacts-right" sx={{ minWidth: "50%" }}>
<AboutContact title="Age" info={age} />
<AboutContact title="Freelance" info="Available" />
</Box>
</Box>
<Typography variant="body1" sx={{ mt: "2rem" }}>
Additionally, I have worked with a wide range of tools and
frameworks including Git, PostgreSQL, MongoDB, Docker, Kubernetes,
Garden, JavaFX, MaterialUI, Spring Boot, Express, Gitlab, Gitea
CI/CD.
</Typography>
</Box>
</Box>
</Box>
</Box>
);

View file

@ -1,12 +1,39 @@
import { useState } from "react";
import { Link } from "react-router-dom";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
import TextField from "@mui/material/TextField";
import MailIcon from "@mui/icons-material/Mail";
import LocationOnIcon from "@mui/icons-material/LocationOn";
import PhoneIphoneIcon from "@mui/icons-material/PhoneIphone";
import ContactStrip from "./ContactStrip.jsx";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useTheme, styled } from "@mui/material/styles";
import "@css/contact.css";
const ContactMessageButton = styled(Button)({
backgroundColor: "white",
color: "#F3AC20",
borderColor: "#F3AC20",
"&:hover": {
backgroundColor: "#F3AC20",
color: "white",
borderColor: "#F3AC20",
},
});
export default function Contact() {
const theme = useTheme();
const minifyContact = useMediaQuery(theme.breakpoints.down("md"));
const [contactName, setContactName] = useState();
const [contactEmail, setContactEmail] = useState();
const [contactSubject, setContactSubject] = useState();
const [contactBody, setContactBody] = useState();
const fillForm = (form) => (e) => form(e.target.value);
return (
<Box style={{ padding: 10, scrollMarginTop: "4rem" }} id="contact">
<Box
@ -47,12 +74,79 @@ export default function Contact() {
info="+1 (234) 456 7890"
/>*/}
</Box>
{/*<Box className="messaging">
<TextField label="Name" size="small" />
<TextField label="Subject" size="small"/>
<TextField label="Email" size="small"/>
<TextField label="Message" size="small" multiline/>
</Box>*/}
<Box
className="messaging"
sx={{
display: "flex",
flexWrap: "wrap",
gap: "1.5rem",
maxWidth: "42em",
width: "100%",
m: "0 auto",
}}
>
<Box
className="messaging-head"
sx={{
display: "flex",
justifyContent: "center",
gap: "1.5rem",
width: "100%",
flexWrap: "wrap",
}}
>
<TextField
label="Name"
size="small"
sx={{
maxWidth: minifyContact ? "100%" : "20em",
width: "100%",
}}
onChange={fillForm(setContactName)}
required
type="name"
/>
<TextField
label="Email"
size="small"
sx={{
maxWidth: minifyContact ? "100%" : "20em",
width: "100%",
}}
onChange={fillForm(setContactEmail)}
required
type="email"
/>
</Box>
<TextField
label="Subject"
size="small"
sx={{ width: "100%" }}
onChange={fillForm(setContactSubject)}
required
/>
<TextField
label="Message"
size="small"
multiline
sx={{ width: "100%" }}
maxRows={5}
minRows={3}
onChange={fillForm(setContactBody)}
required
/>
<ContactMessageButton
variant="outlined"
sx={{ m: "0 auto", width: "100%", maxWidth: "16em" }}
component={Link}
to={`mailto:elijahglennparker@outlook.com?subject=${contactSubject} | ${contactName} | ${contactEmail}&body=${contactBody}`}
disabled={
!(contactSubject && contactBody && contactName && contactEmail)
}
>
Send Message
</ContactMessageButton>
</Box>
</Box>
</Box>
</Box>

View file

@ -1,23 +1,33 @@
import React, { Suspense } from "react";
import About from "./About.jsx";
import Box from "@mui/material/Box";
import Header from "./Header.jsx";
import Projects from "./Projects.jsx";
import Contact from "./Contact.jsx";
//import Environments from "./Environments.jsx";
import ContentWrapper from "@components/ContentWrapper.jsx";
const Skills = React.lazy(() => import("./Skills.jsx"));
const Social = React.lazy(() => import("./Social.jsx"));
const Contact = React.lazy(() => import("./Contact.jsx"));
const Education = React.lazy(() => import("./Education.jsx"));
const Experience = React.lazy(() => import("./Experience.jsx"));
const About = React.lazy(() => import("./About.jsx"));
export default function Delta() {
return (
<ContentWrapper id="delta">
<About />
<Header />
<Projects />
<Suspense>
<About />
<Box style={{ display: "flex", flexWrap: "wrap" }}>
<Education />
<Experience />
</Box>
<Skills />
<Social />
<Contact />
</Suspense>
<Contact />
</ContentWrapper>
);
}

View file

@ -0,0 +1,67 @@
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import ExperienceDisplay from "@components/ExperienceDisplay.jsx";
export default function Education() {
return (
<Box
style={{
padding: 10,
scrollMarginTop: "4rem",
maxWidth: "500px",
margin: "0 auto",
textAlign: "left",
width: "100%",
}}
id="education"
>
<Typography
variant="h2"
sx={{ margin: "1rem auto", fontSize: 30, pb: ".5rem" }}
>
Education
</Typography>
<Box className="education-list">
<ExperienceDisplay
title="Computer Science Student"
subtitle="Jan 2024 - Present"
>
<Typography sx={{ pt: "1rem" }}>
Pursuing B.S. in Computer Science: Software Engineering program,
completed 7 credits. Anticipated graduation December 2027
</Typography>
</ExperienceDisplay>
<ExperienceDisplay
title="Full Stack Web Development"
subtitle="Dec 2018 - May 2020 | Bottega devCamp"
>
<Typography sx={{ pt: "1rem" }}>
Certificate of Competency in advanced Python, database foundations,
system analysis, UML, and advanced web development using HTML,
JavaScript, React, XML, and JSON
</Typography>
</ExperienceDisplay>
<ExperienceDisplay
title="High School Diploma"
subtitle="Aug 2017 - May 2020 | American Fork Highschool"
>
<Typography sx={{ pt: "1rem" }}>
GPA 3.9, CS Department Choice Award, Co-founder and President
Computer Science Club, 4 years programming, student tutor, AP
courses in Computer Science, Calculus, Mechanics, and Government
</Typography>
</ExperienceDisplay>
<ExperienceDisplay
title="Cyber Security and Networking"
subtitle="Jan 2019 - May 2019 | AFAs CyberPatriot"
>
<Typography sx={{ pt: "1rem" }}>
2nd Place state networking security challenge, curriculum included
Ubuntu security policies and PAM, networking, init systems, advanced
command line, processes, and scheduled tasks
</Typography>
</ExperienceDisplay>
</Box>
</Box>
);
}

View file

@ -0,0 +1,74 @@
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import ExperienceDisplay from "@components/ExperienceDisplay.jsx";
export default function Experience() {
return (
<Box
style={{
padding: 10,
scrollMarginTop: "4rem",
maxWidth: "500px",
margin: "0 auto",
textAlign: "left",
width: "100%",
}}
id="experience"
>
<Typography
variant="h2"
sx={{ margin: "1rem auto", fontSize: 30, pb: ".5rem" }}
>
Experience
</Typography>
<Box className="experience-list">
<ExperienceDisplay
title="Software Engineer Intern"
subtitle="Jun - Nov 2021 | Podium, Lehi UT"
>
<Typography variant="body1" sx={{ fontWeight: 600, pt: "1rem" }}>
Technologies used:{" "}
<span
style={{
fontFamily: "inherit",
fontSize: "14px",
}}
>
React, Python, Java, RabbitMQ
</span>
</Typography>
<ul style={{ paddingLeft: "25px" }}>
<li>
<Typography>
Developed automated end to end UI & API tests and automated
collection of test coverage
</Typography>
</li>
<li>
<Typography>
Modularized API testing resources as project lead
</Typography>
</li>
<li>
<Typography>
Automated scripting framework to gauge product reliability as
project lead
</Typography>
</li>
<li>
<Typography>
Improved performance of core QA services by 20%
</Typography>
</li>
<li>
<Typography>
Created fullstack application using React and Express to manage
QA data as solo developer
</Typography>
</li>
</ul>
</ExperienceDisplay>
</Box>
</Box>
);
}

View file

@ -0,0 +1,29 @@
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
export default function Header() {
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{" "}
<a
href="/#contact"
style={{
textDecoration: "none",
fontSize: "inherit",
fontFamily: "inherit",
}}
>
here
</a>
</Typography>
</Box>
</Box>
);
}

View file

@ -1,7 +1,6 @@
import React from "react";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import ContentWrapper from "../../components/ContentWrapper";
import ContactCard from "./ContactCard.jsx";
const people = [
@ -36,35 +35,32 @@ const people = [
export default function References() {
return (
<Box id="references">
<ContentWrapper>
<Box className="references-list">
<Box sx={{ maxWidth: 570, margin: "4rem auto", padding: "2rem" }}>
<Typography variant="h4" sx={{ fontWeight: 600 }}>
References{" "}
</Typography>{" "}
</Box>
<Box
sx={{
display: "flex",
flexWrap: "wrap",
justifyContent: "center",
}}
>
{people.map((p, i) => (
<ContactCard
key={i}
name={p.name}
title={p.title}
email={p.email}
linkedin={p.linkedin}
description={p.description}
avatar={p.avatar}
/>
))}
</Box>
</Box>
</ContentWrapper>
<Box style={{ padding: 10, scrollMarginTop: "4rem" }} id="references">
<div style={{ display: "flex" }}>
<Typography variant="h2" sx={{ margin: "2rem auto", fontSize: 30 }}>
References
</Typography>
</div>
<Box
sx={{
display: "flex",
flexWrap: "wrap",
justifyContent: "center",
}}
>
{people.map((p, i) => (
<ContactCard
key={i}
name={p.name}
title={p.title}
email={p.email}
linkedin={p.linkedin}
description={p.description}
avatar={p.avatar}
/>
))}
</Box>
</Box>
);
}

View file

@ -0,0 +1,14 @@
import React from "react";
import Box from "@mui/material/Box";
import ContentWrapper from "../../components/ContentWrapper";
import References from "./References.jsx";
export default function Resume() {
return (
<Box id="resume">
<ContentWrapper>
<References />
</ContentWrapper>
</Box>
);
}