+6
-107
@@ -9,118 +9,17 @@ import "./main.css";
|
||||
* Primary portfolio application. Utilizes swiper.js (via /components/VerticalSlider.jsx) to
|
||||
* have a scrolling section to section effect.
|
||||
*
|
||||
* This is the primary place where (currently) application data is stored. This information will be read in
|
||||
* from plain-text files in the future for ease of future editing. In the meantime, generated components,
|
||||
* specifically the Skill Card and Project Card (see /components/SkillCard.jsx and /components/ProjectCard.jsx)
|
||||
* get their data from here and thus any additions are made in this file.
|
||||
* Managed by /main.jsx.
|
||||
* Data by /main.jsx.
|
||||
*
|
||||
* TODO: Read in data from a plain text file for easier editing in the future, and to separate domains.
|
||||
* @param projectData JSON[], data necessary to create project cards.
|
||||
* @param skillData JSON, data necessary to create skill cards.
|
||||
*/
|
||||
const App = () => {
|
||||
// DATA VARIABLES
|
||||
const projectData = [
|
||||
{
|
||||
title: "One AI",
|
||||
description:
|
||||
"An end-to-end self-hosted Artificial Intelligence solution, using Meta's Ollama platform to run Large Language Models. Go was used for the backend as a wrapper API and the frontend is Flutter. Here are some of the implemented features:",
|
||||
featureList: [
|
||||
"AES encryption of messages between client and server",
|
||||
"SHA-256 hashing for message validation",
|
||||
"Base64 encoding for file uploads to the server",
|
||||
"Docker container for isolation and security",
|
||||
],
|
||||
image: "/images/one-ai-cropped.png",
|
||||
imageGallery: null,
|
||||
url: "https://github.com/quaxlyqueen/one-ai",
|
||||
},
|
||||
{
|
||||
title: "Snake",
|
||||
description:
|
||||
"A Snake clone in the command line, written in C#. Utilized a Queue data structure to keep track of the snake's body. Implemented features include:",
|
||||
featureList: [
|
||||
"basic pseudo-randomized obstacle generation",
|
||||
"difficulty selection by adjusting the frequency of obstacle generation",
|
||||
"keyboard input to move the snake",
|
||||
"ASCII art for the menu and game over state",
|
||||
],
|
||||
image: "/images/snake.gif",
|
||||
imageGallery: null,
|
||||
url: "https://github.com/quaxlyqueen/2410-Snake",
|
||||
},
|
||||
{
|
||||
title: "Battery Monitor",
|
||||
description:
|
||||
"A battery monitor, written in C with a GUI written in Python. Utilizes the acpi Unix command to gather battery information. Implemented features incldue:",
|
||||
featureList: [
|
||||
"embed Unix commands in C to get the date, time, battery percentage, and battery status",
|
||||
"basic file I/O to store historical battery data",
|
||||
"daemonize to run as a background process",
|
||||
"script to install as a SystemD service",
|
||||
"basic Python GUI in TKinter to provide graph of data",
|
||||
],
|
||||
image: "/images/battery-mon.png",
|
||||
imageGallery: null,
|
||||
url: "https://github.com/quaxlyqueen/battery-mon",
|
||||
},
|
||||
{
|
||||
title: "D&D Character Builder",
|
||||
description:
|
||||
"A Dungeons and Dragons character builder, following the 5th edition rules and creation process. A collaborative project creating a GUI in Java with Swing. Features include:",
|
||||
featureList: [
|
||||
"serialization of character data into custom filetype",
|
||||
"global styling and custom font import",
|
||||
"button hover effects",
|
||||
],
|
||||
image: "/images/dnd.png",
|
||||
imageGallery: null,
|
||||
url: "https://github.com/quaxlyqueen/dnd",
|
||||
},
|
||||
{
|
||||
title: "Calculator",
|
||||
description:
|
||||
"A simple and themable calculator written in Python. This uses CustomTKinter for the GUI and the eva CLI package for the actual calculator functionality. Supports MacOS and Linux. Implemented features include:",
|
||||
featureList: [
|
||||
"custom theming read in from a global .theme file",
|
||||
"button hover effects",
|
||||
"keyboard input",
|
||||
],
|
||||
image: "/images/calculator.gif",
|
||||
imageGallery: null,
|
||||
url: "https://github.com/quaxlyqueen/calculator",
|
||||
},
|
||||
];
|
||||
|
||||
const skillsData = {
|
||||
languages: [
|
||||
"C & C#",
|
||||
"HTML & CSS",
|
||||
"Go",
|
||||
"Java",
|
||||
"JavaScript & Dart",
|
||||
"Python",
|
||||
],
|
||||
tools: [
|
||||
"Git & GitHub",
|
||||
"Docker",
|
||||
"Flutter & React",
|
||||
"Linux & NeoVim",
|
||||
"Cloudflare",
|
||||
"Microsoft Intune",
|
||||
],
|
||||
other: [
|
||||
"Written Communication",
|
||||
"Conflict Resolution",
|
||||
"Project Management",
|
||||
"Event Planning",
|
||||
"Electronics Repair",
|
||||
"Soldering",
|
||||
],
|
||||
};
|
||||
|
||||
const App = ({ projectData, skillData }) => {
|
||||
const slides = [
|
||||
<Home
|
||||
image="/images/profile.jpg"
|
||||
skills={skillsData}
|
||||
skills={skillData}
|
||||
/>,
|
||||
<Projects cardData={projectData} />,
|
||||
<Contact />,
|
||||
|
||||
+4
-4
@@ -5,7 +5,7 @@ import SkillCard from "./components/SkillCard";
|
||||
* "Home" page/slide of my portfolio.
|
||||
*
|
||||
* Managed by /App.jsx.
|
||||
* Data by /App.jsx.
|
||||
* Data by /main.jsx.
|
||||
*
|
||||
* @param image String
|
||||
* @param skills json, containing JSON values of String arrays.
|
||||
@@ -18,10 +18,10 @@ const Home = ({ image, skills }) => {
|
||||
<>
|
||||
<div id="primary">
|
||||
<div className="header">
|
||||
<div className="header-image">
|
||||
<div className="header-image center-row">
|
||||
<img id="profile" src={image} />
|
||||
</div>
|
||||
<div className="header-text">
|
||||
<div className="center-column">
|
||||
<div className="center-column">
|
||||
<h1>Hi, I'm Josh Ashton.</h1>
|
||||
<h3>Junior full-stack developer.</h3>
|
||||
@@ -32,7 +32,7 @@ const Home = ({ image, skills }) => {
|
||||
</div>
|
||||
</div>
|
||||
<div id="skill-cards">
|
||||
<div id="card-grid">
|
||||
<div className="center-row">
|
||||
<SkillCard
|
||||
header="Languages"
|
||||
symbol="code"
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import "swiper/css/scrollbar";
|
||||
* (see /components/ProjectCard.jsx), generated for each element of the parameter cardData.
|
||||
*
|
||||
* Managed by /App.jsx.
|
||||
* Data by /App.jsx.
|
||||
* Data by /main.jsx.
|
||||
*
|
||||
* @param cardData json[], each object contains the following: title, descriptionA, featureList, image, url
|
||||
*
|
||||
|
||||
+85
-8
@@ -1,19 +1,96 @@
|
||||
import React from "react";
|
||||
import PdfViewer from "./components/PdfViewer";
|
||||
|
||||
/*
|
||||
* Page to display my Resume.
|
||||
*
|
||||
* TODO: Rework resume to make it one page
|
||||
* TODO: Convert resume to a React component, with a link to save as PDF
|
||||
* Resume page component.
|
||||
*/
|
||||
export default function Resume() {
|
||||
const Resume = ({ jobData, eduData, skillData }) => {
|
||||
return (
|
||||
<>
|
||||
<div id="resume-section">
|
||||
<h1>Resume</h1>
|
||||
<PdfViewer file="resume.pdf" />
|
||||
<h1>Josh Ashton</h1>
|
||||
<h3>Junior Full-Stack Developer</h3>
|
||||
<h3>Work Experience</h3>
|
||||
<div className="jobs">
|
||||
{jobData.map((job, index) => (
|
||||
<Job key={index} company={job.company} title={job.title} start={job.start} end={job.end} location={job.location} responsibilities={job.responsibilities} />
|
||||
))}
|
||||
</div>
|
||||
<h3>Education</h3>
|
||||
<div className="education-section">
|
||||
{eduData.map((edu, index) => (
|
||||
<Education key={index} institution={edu.institution} degree={edu.degree} gpa={edu.gpa} start={edu.start} end={edu.end} />
|
||||
))}
|
||||
</div>
|
||||
<h3>Skills</h3>
|
||||
<Skill languages={skillData.languages} tools={skillData.tools} other={skillData.other} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function Skill({ languages, tools, other }) {
|
||||
return (
|
||||
<>
|
||||
<div className="resume-skills">
|
||||
<div className="resume-skills-skill">
|
||||
<h4>Languages:</h4>
|
||||
<p>{languages.join(", ")}</p>
|
||||
</div>
|
||||
<div className="resume-skills-skill">
|
||||
<h4>Tools:</h4>
|
||||
<p>{tools.join(", ")}</p>
|
||||
</div>
|
||||
<div className="resume-skills-skill">
|
||||
<h4>Other:</h4>
|
||||
<p>{other.join(", ")}</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function Education({ institution, degree, gpa, start, end }) {
|
||||
return (
|
||||
<>
|
||||
|
||||
<div className="edu">
|
||||
<div className="edu-header">
|
||||
<div className="edu-header-row">
|
||||
<div className="edu-and-degree">
|
||||
<h4>{institution}</h4>
|
||||
<h6>- {degree}</h6>
|
||||
</div>
|
||||
<h6 className="edu-time">{start} - {end}</h6>
|
||||
</div>
|
||||
<h5>{gpa}</h5>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function Job({ company, title, start, end, location, responsibilities }) {
|
||||
return (
|
||||
<>
|
||||
<div className="job">
|
||||
<div className="job-header">
|
||||
<div className="job-header-row">
|
||||
<div className="company-and-location">
|
||||
<h4>{company} </h4>
|
||||
<h6>- {location}</h6>
|
||||
</div>
|
||||
<h6 className="job-time">{start} - {end}</h6>
|
||||
</div>
|
||||
<h5>{title}</h5>
|
||||
</div>
|
||||
<ul className="job-list">
|
||||
{responsibilities.map((r, index) => (
|
||||
<li key={index} className="job-list-item">{r}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Resume;
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import { Document, Page, pdfjs } from "react-pdf";
|
||||
import "react-pdf/dist/Page/TextLayer.css";
|
||||
import "react-pdf/dist/Page/AnnotationLayer.css";
|
||||
|
||||
export default function PdfViewer({ file }) {
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
|
||||
"pdfjs-dist/build/pdf.worker.min.mjs",
|
||||
import.meta.url,
|
||||
).toString();
|
||||
|
||||
const [numPages, setNumPages] = useState(0);
|
||||
const [pageNumber, setPageNumber] = useState(1);
|
||||
function prev() {
|
||||
if (pageNumber >= 2) {
|
||||
setPageNumber(pageNumber - 1);
|
||||
}
|
||||
}
|
||||
|
||||
function next() {
|
||||
if (pageNumber < numPages) {
|
||||
setPageNumber(pageNumber + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="pdf-container">
|
||||
<Document
|
||||
file={file}
|
||||
onLoadSuccess={({ numPages: numPagesInPdf }) => {
|
||||
setNumPages(numPagesInPdf);
|
||||
}}
|
||||
className="pdf-document"
|
||||
>
|
||||
<Page pageNumber={pageNumber} scale={0.8} />
|
||||
</Document>
|
||||
<div className="pdf-buttons shadow">
|
||||
<button className="pdf-button" onClick={() => prev()}>
|
||||
<span className="material-icons">arrow_back</span>
|
||||
</button>
|
||||
<button className="pdf-button" onClick={() => next()}>
|
||||
<span className="material-icons">arrow_forward</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import React from "react";
|
||||
* project.
|
||||
*
|
||||
* Managed by /Projects.jsx.
|
||||
* Data by /App.jsx.
|
||||
* Data by /main.jsx > /App.jsx > /Projects.jsx.
|
||||
*
|
||||
* @param title String
|
||||
* @param description String
|
||||
|
||||
@@ -5,6 +5,9 @@ import React, { useState, useEffect } from "react";
|
||||
*
|
||||
* On mobile, only one card at a time may be active. The currently active card is
|
||||
* managed by the parent component, Home.jsx, via the isActive and onToggle props.
|
||||
*
|
||||
* Managed by /Home.jsx.
|
||||
* Data by /main.jsx > /App.jsx > /Home.jsx
|
||||
*
|
||||
* @param header String, the skill card's header
|
||||
* @param symbol String, a Material Icon from https://fonts.google.com/icons?icon.size=24&icon.color=%23e8eaed
|
||||
@@ -32,7 +35,7 @@ const SkillCard = ({ header, symbol, list, isActive, onToggle }) => {
|
||||
<div className="card shadow">
|
||||
<div className="skill-card-header" onClick={() => onToggle()}>
|
||||
<span className="material-icons skill-symbol">{symbol}</span>
|
||||
<h3>{header}</h3>
|
||||
<h4>{header}</h4>
|
||||
</div>
|
||||
{(isActive || !isMobile) && (
|
||||
<ul>
|
||||
|
||||
+110
-25
@@ -41,39 +41,65 @@ body {
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: clamp(4.25rem, 5.5vw, 10rem);
|
||||
font-weight: 600;
|
||||
letter-spacing: 2px;
|
||||
width: max-content;
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
p,
|
||||
li {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
h3,
|
||||
h4 {
|
||||
color: var(--text);
|
||||
font-weight: 300;
|
||||
line-height: 1.5;
|
||||
h1 {
|
||||
font-size: clamp(4rem, 5vw, 10rem);
|
||||
font-weight: 600;
|
||||
letter-spacing: 2px;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
h2,
|
||||
h3 {
|
||||
font-weight: 500;
|
||||
letter-spacing: 2px;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: clamp(2rem, 3vw, 4rem);
|
||||
font-weight: 600;
|
||||
letter-spacing: 2px;
|
||||
width: max-content;
|
||||
color: var(--text);
|
||||
font-size: clamp(3rem, 4vw, 7rem);
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: clamp(1.5rem, 2vw, 3rem);
|
||||
font-size: clamp(2rem, 3rem, 6rem);
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: clamp(1rem, 1.5vw, 1.25rem);
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: clamp(1rem, 1.5rem, 2rem);
|
||||
h5,
|
||||
h6 {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: clamp(1rem, 1.5vw, 4rem);
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: clamp(1rem, 1.25vw, 3.5rem);
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: clamp(1rem, 1.125vw, 2rem);
|
||||
}
|
||||
|
||||
p,
|
||||
li {
|
||||
font-weight: 300;
|
||||
font-size: clamp(1rem, 1.1vw, 1.5rem);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
@@ -139,7 +165,7 @@ p {
|
||||
}
|
||||
|
||||
.mySwiper {
|
||||
width: 100vw;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -278,8 +304,8 @@ p {
|
||||
border-radius: 18px 18px 0 0;
|
||||
}
|
||||
|
||||
.skill-card-header h3 {
|
||||
font-size: clamp(1.3rem, 2vw, 3rem);
|
||||
.skill-card-header h4 {
|
||||
font-weight: 700;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@@ -299,7 +325,6 @@ p {
|
||||
|
||||
.card ul li {
|
||||
list-style: none;
|
||||
font-size: clamp(1rem, 1.25vw, 1.5rem);
|
||||
color: var(--dark-0);
|
||||
}
|
||||
|
||||
@@ -352,7 +377,6 @@ p {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin-right: 5vw;
|
||||
}
|
||||
|
||||
/* Tooltip container */
|
||||
@@ -424,6 +448,7 @@ p {
|
||||
}
|
||||
|
||||
.project-text p {
|
||||
font-weight: 400;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
@@ -447,7 +472,6 @@ p {
|
||||
}
|
||||
|
||||
.feature-list li {
|
||||
font-size: clamp(1rem, 1.5rem, 2rem);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
@@ -530,6 +554,8 @@ p {
|
||||
#resume-section {
|
||||
margin: 2vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/**PDF Viewer**/
|
||||
@@ -692,6 +718,65 @@ p {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.jobs,
|
||||
.education-section {
|
||||
border-top: 1px solid var(--accent-0);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.job,
|
||||
.edu {
|
||||
width: 100%;
|
||||
padding: 0vw 1vw 1vw 1vw;
|
||||
}
|
||||
|
||||
.job-header-row,
|
||||
.edu-header-row {
|
||||
display: grid;
|
||||
grid-template-columns: 70% 30%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.job-time,
|
||||
.edu-time {
|
||||
justify-self: right;
|
||||
}
|
||||
|
||||
.company-and-location,
|
||||
.edu-and-degree {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.company-and-location h6,
|
||||
.edu-and-degree h6 {
|
||||
margin-left: .25vw;
|
||||
}
|
||||
|
||||
.job-list {
|
||||
margin: 0 auto;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.job-list-item {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.resume-skills {
|
||||
border-top: 1px solid var(--accent-0);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.resume-skills-skill {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.resume-skills-skill p {
|
||||
margin-left: .5vw;
|
||||
padding: 1vw;
|
||||
}
|
||||
|
||||
/**Animations**/
|
||||
@keyframes background-fade {
|
||||
from {
|
||||
|
||||
+146
-3
@@ -6,15 +6,158 @@ import Resume from "./Resume.jsx";
|
||||
import ErrorPage from "./ErrorPage.jsx";
|
||||
|
||||
/*
|
||||
* Root React container and renderer. Also manages the router. Any new pages should be added here.
|
||||
* Root React container and renderer.
|
||||
*
|
||||
* Contains all data and data processing, as well as routing to different pages.
|
||||
* TODO: Read data in from plain text files.
|
||||
*/
|
||||
const container = document.getElementById("app");
|
||||
const root = createRoot(container);
|
||||
|
||||
const projectData = [
|
||||
{
|
||||
title: "One AI",
|
||||
description:
|
||||
"An end-to-end self-hosted Artificial Intelligence solution, using Meta's Ollama platform to run Large Language Models. Go was used for the backend as a wrapper API and the frontend is Flutter. Here are some of the implemented features:",
|
||||
featureList: [
|
||||
"AES encryption of messages between client and server",
|
||||
"SHA-256 hashing for message validation",
|
||||
"Base64 encoding for file uploads to the server",
|
||||
"Docker container for isolation and security",
|
||||
],
|
||||
image: "/images/one-ai-cropped.png",
|
||||
imageGallery: null,
|
||||
url: "https://github.com/quaxlyqueen/one-ai",
|
||||
},
|
||||
{
|
||||
title: "Snake",
|
||||
description:
|
||||
"A Snake clone in the command line, written in C#. Utilized a Queue data structure to keep track of the snake's body. Implemented features include:",
|
||||
featureList: [
|
||||
"basic pseudo-randomized obstacle generation",
|
||||
"difficulty selection by adjusting the frequency of obstacle generation",
|
||||
"keyboard input to move the snake",
|
||||
"ASCII art for the menu and game over state",
|
||||
],
|
||||
image: "/images/snake.gif",
|
||||
imageGallery: null,
|
||||
url: "https://github.com/quaxlyqueen/2410-Snake",
|
||||
},
|
||||
{
|
||||
title: "Battery Monitor",
|
||||
description:
|
||||
"A battery monitor, written in C with a GUI written in Python. Utilizes the acpi Unix command to gather battery information. Implemented features incldue:",
|
||||
featureList: [
|
||||
"embed Unix commands in C to get the date, time, battery percentage, and battery status",
|
||||
"basic file I/O to store historical battery data",
|
||||
"daemonize to run as a background process",
|
||||
"script to install as a SystemD service",
|
||||
"basic Python GUI in TKinter to provide graph of data",
|
||||
],
|
||||
image: "/images/battery-mon.png",
|
||||
imageGallery: null,
|
||||
url: "https://github.com/quaxlyqueen/battery-mon",
|
||||
},
|
||||
{
|
||||
title: "D&D Character Builder",
|
||||
description:
|
||||
"A Dungeons and Dragons character builder, following the 5th edition rules and creation process. A collaborative project creating a GUI in Java with Swing. Features include:",
|
||||
featureList: [
|
||||
"serialization of character data into custom filetype",
|
||||
"global styling and custom font import",
|
||||
"button hover effects",
|
||||
],
|
||||
image: "/images/dnd.png",
|
||||
imageGallery: null,
|
||||
url: "https://github.com/quaxlyqueen/dnd",
|
||||
},
|
||||
{
|
||||
title: "Calculator",
|
||||
description:
|
||||
"A simple and themable calculator written in Python. This uses CustomTKinter for the GUI and the eva CLI package for the actual calculator functionality. Supports MacOS and Linux. Implemented features include:",
|
||||
featureList: [
|
||||
"custom theming read in from a global .theme file",
|
||||
"button hover effects",
|
||||
"keyboard input",
|
||||
],
|
||||
image: "/images/calculator.gif",
|
||||
imageGallery: null,
|
||||
url: "https://github.com/quaxlyqueen/calculator",
|
||||
},
|
||||
];
|
||||
|
||||
const skillData = {
|
||||
languages: [
|
||||
"C & C#",
|
||||
"HTML & CSS",
|
||||
"Go",
|
||||
"Java",
|
||||
"JavaScript & Dart",
|
||||
"Python",
|
||||
],
|
||||
tools: [
|
||||
"Git & GitHub",
|
||||
"Docker",
|
||||
"Flutter & React",
|
||||
"Linux & NeoVim",
|
||||
"Cloudflare",
|
||||
"Microsoft Intune",
|
||||
],
|
||||
other: [
|
||||
"Written Communication",
|
||||
"Conflict Resolution",
|
||||
"Project Management",
|
||||
"Event Planning",
|
||||
"Electronics Repair",
|
||||
"Soldering",
|
||||
],
|
||||
};
|
||||
|
||||
const jobData = [
|
||||
{
|
||||
company: "SLC Public Library",
|
||||
title: "Technology & Digital Equity Assistant",
|
||||
start: "Aug '23",
|
||||
end: "Present",
|
||||
location: "Salt Lake City, UT",
|
||||
responsibilities: [
|
||||
"Assist library patrons with using technology, on devices such as publicly available PCs, laptops, mobile devices, and more.",
|
||||
"Teach fundamental computer usage skills.",
|
||||
"Expose patrons to the importance of digital security, password management, and two-factor authentication.",
|
||||
"Developing workshop curriculum for Raspberry Pi’s."
|
||||
],
|
||||
},
|
||||
{
|
||||
company: "Trust Lands Admin.",
|
||||
title: "IT Intern",
|
||||
start: "Aug '23",
|
||||
end: "Aug '24",
|
||||
location: "Salt Lake City, UT",
|
||||
responsibilities: [
|
||||
"Orchestrated Microsoft Intune setup and deployment to multiple platforms.",
|
||||
"Streamlined IT equipment inventory process",
|
||||
"Provided training to optimize the usage of hardware and software.",
|
||||
"Troubleshoot and repair hardware and software on a variety of devices.",
|
||||
"Developed automation scripts for use in various parts of the business.",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const eduData = [
|
||||
{
|
||||
institution: "Salt Lake Comm. College",
|
||||
degree: "AS Comp Sci",
|
||||
gpa: "3.48 (CS) || 2.87 (Cumulative)",
|
||||
start: "Jan '21",
|
||||
end: "Present",
|
||||
}
|
||||
];
|
||||
|
||||
root.render(
|
||||
<Router>
|
||||
<Routes>
|
||||
<Route exact path="/" element={<App />} />
|
||||
<Route exact path="/resume" element={<Resume />} />
|
||||
<Route exact path="/" element={<App projectData={projectData} skillData={skillData} />} />
|
||||
<Route exact path="/resume" element={<Resume jobData={jobData} eduData={eduData} skillData={skillData} />} />
|
||||
<Route
|
||||
path="*"
|
||||
element={
|
||||
|
||||
Reference in New Issue
Block a user