diff --git a/index.html b/index.html
index 4fe55b3e..a4b611c7 100644
--- a/index.html
+++ b/index.html
@@ -7,6 +7,10 @@
rel="stylesheet"
href="https://fonts.googleapis.com/icon?family=Material+Icons"
/>
+
Josh Ashton
diff --git a/package-lock.json b/package-lock.json
index 322516c7..73affaf7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,10 @@
"name": "portfolio",
"version": "0.0.1",
"dependencies": {
+ "@fortawesome/fontawesome-svg-core": "^6.7.2",
+ "@fortawesome/free-brands-svg-icons": "^6.7.2",
+ "@fortawesome/free-solid-svg-icons": "^6.7.2",
+ "@fortawesome/react-fontawesome": "^0.2.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"swiper": "^10.0.0"
@@ -390,6 +394,64 @@
"node": ">=12"
}
},
+ "node_modules/@fortawesome/fontawesome-common-types": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz",
+ "integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/fontawesome-svg-core": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz",
+ "integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==",
+ "license": "MIT",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.7.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/free-brands-svg-icons": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.7.2.tgz",
+ "integrity": "sha512-zu0evbcRTgjKfrr77/2XX+bU+kuGfjm0LbajJHVIgBWNIDzrhpRxiCPNT8DW5AdmSsq7Mcf9D1bH0aSeSUSM+Q==",
+ "license": "(CC-BY-4.0 AND MIT)",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.7.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/free-solid-svg-icons": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.7.2.tgz",
+ "integrity": "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==",
+ "license": "(CC-BY-4.0 AND MIT)",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.7.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/react-fontawesome": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz",
+ "integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==",
+ "license": "MIT",
+ "dependencies": {
+ "prop-types": "^15.8.1"
+ },
+ "peerDependencies": {
+ "@fortawesome/fontawesome-svg-core": "~1 || ~6",
+ "react": ">=16.3"
+ }
+ },
"node_modules/esbuild": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
@@ -480,6 +542,15 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -516,6 +587,17 @@
"node": "^10 || ^12 || >=14"
}
},
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
"node_modules/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
@@ -541,6 +623,12 @@
"react": "^18.3.1"
}
},
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "license": "MIT"
+ },
"node_modules/rollup": {
"version": "3.29.5",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz",
diff --git a/package.json b/package.json
index 75dcf369..7fa2e039 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,9 @@
{
"dependencies": {
+ "@fortawesome/fontawesome-svg-core": "^6.7.2",
+ "@fortawesome/free-brands-svg-icons": "^6.7.2",
+ "@fortawesome/free-solid-svg-icons": "^6.7.2",
+ "@fortawesome/react-fontawesome": "^0.2.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"swiper": "^10.0.0"
diff --git a/public/images/one-ai-cropped.png b/public/images/one-ai-cropped.png
new file mode 100644
index 00000000..5234b4a4
Binary files /dev/null and b/public/images/one-ai-cropped.png differ
diff --git a/src/App.jsx b/src/App.jsx
index 8461640d..0c9a082b 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,4 +1,4 @@
-import React, { useRef, useState } from "react";
+import React, { useEffect, useState } from "react";
import VerticalSlider from "./components/VerticalSlider";
import Primary from "./Primary";
import Skills from "./Skills";
@@ -12,9 +12,38 @@ import "./main.css";
* TODO: Read in data from a plain text file for easier editing in the future.
*/
export default function App() {
- const cards = [ , , ];
+ // FUNCTION DATA
+ const [isMobile, setIsMobile] = useState(window.innerWidth <= 790);
- const skills = {
+ useEffect(() => {
+ const handleResize = () => setIsMobile(window.innerWidth <= 790);
+ window.addEventListener("resize", handleResize);
+ return () => window.removeEventListener("resize", handleResize);
+ }, []);
+
+ const initState = isMobile ? [true, false, false] : [true, true, true];
+
+ // DATA VARIABLES
+ /*
+ {
+ title: "",
+ description: "",
+ image: "",
+ imageGallery: null,
+ url: ""
+ },
+*/
+ const projectData = [
+ {
+ title: "One AI",
+ description: "ASDF",
+ image: "/images/projects/one-ai.png",
+ imageGallery: null,
+ url: "https://github.com/quaxlyqueen/one-ai",
+ },
+ ];
+
+ const skillsData = {
languages: ["Java", "JavaScript", "Go", "Dart", "Python", "C#"],
tools: [
"Git & GitHub",
@@ -40,11 +69,10 @@ export default function App() {
secondaryText="Junior full-stack developer."
callToAction="Here's my resume."
image="/images/profile.jpg"
- skills={skills}
+ skills={skillsData}
+ initState={initState}
/>,
- ,
- ,
- ,
+ ,
];
return ;
}
diff --git a/src/Primary.jsx b/src/Primary.jsx
index 8ec042e5..35b7585b 100644
--- a/src/Primary.jsx
+++ b/src/Primary.jsx
@@ -1,4 +1,4 @@
-// TODO: Replace h4 callToAction with a button callToAction.
+// TODO: Replace h4 callToAction with a GREEN button callToAction.
import React, { useState } from "react";
import SkillCard from "./components/SkillCard";
@@ -8,6 +8,7 @@ export default function Primary({
callToAction,
image,
skills,
+ initState,
}) {
return (
<>
@@ -28,19 +29,19 @@ export default function Primary({
header="Languages"
symbol="code"
list={skills.languages}
- initState={true}
+ initState={initState[0]}
/>
diff --git a/src/Projects.jsx b/src/Projects.jsx
index 741c0ecf..3fe59b8f 100644
--- a/src/Projects.jsx
+++ b/src/Projects.jsx
@@ -1,5 +1,33 @@
import React from "react";
+import ProjectCard from "./components/ProjectCard";
-export default function Projects() {
- return TODO: Projects()
;
+export default function Projects({ cardData }) {
+ return (
+ <>
+
+
+
+
+ {cardData.map((c) => (
+
+ ))}
+
+
+
+ >
+ );
}
diff --git a/src/components/ProjectCard.jsx b/src/components/ProjectCard.jsx
index e2e44d82..ee6de7ac 100644
--- a/src/components/ProjectCard.jsx
+++ b/src/components/ProjectCard.jsx
@@ -1,5 +1,24 @@
import React from "react";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faGithub } from "@fortawesome/free-brands-svg-icons";
-export default function ProjectCard() {
- return TODO: Need to implement ProjectCard
;
+export default function ProjectCard({
+ title,
+ description,
+ image,
+ imageGallery,
+ url,
+}) {
+ return (
+
+
+
+
+
{title}
+
+
+
{description}
+
+
+ );
}
diff --git a/src/components/SkillCard.jsx b/src/components/SkillCard.jsx
index 7c469bff..b22cf055 100644
--- a/src/components/SkillCard.jsx
+++ b/src/components/SkillCard.jsx
@@ -1,5 +1,7 @@
import React, { useState } from "react";
+// TODO: Add state which only allows one skill card at a time to be expanded.
+// TODO: Ensure that the expandability of the skill card is only an option when @media max-width 790px (mobile)
export default function SkillCard({ header, symbol, list, initState }) {
const [isExpanded, setIsExpanded] = useState(initState); // Initial state
diff --git a/src/main.css b/src/main.css
index d76577d5..6b7e0bbb 100644
--- a/src/main.css
+++ b/src/main.css
@@ -51,6 +51,12 @@ body {
overflow: hidden;
}
+.slide-container {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+}
+
.swiper-pagination-bullet {
width: 18px;
height: 18px;
@@ -73,6 +79,55 @@ body {
column-gap: 1vh;
}
+#project-container {
+ height: 100vh;
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ margin: 5vw;
+}
+
+.project-grid-container {
+ margin: 2vw;
+ display: grid;
+ grid-template-columns: 100%;
+ grid-template-rows: 1% 90%;
+ row-gap: 2vh;
+}
+
+.project-card {
+ background-color: #ebd2ff;
+ height: 70%;
+ display: grid;
+ grid-template-columns: 40% 40%;
+ grid-template-rows: 100%;
+ column-gap: 20vw;
+}
+
+.project-text {
+ display: grid;
+ grid-template-columns: 100%;
+ grid-template-rows: 20% 70%;
+ align-text: left;
+}
+
+.project-text h3 {
+ font-size: clamp(2rem, 2.5vw, 3rem);
+}
+
+.row {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+}
+
+#project-cards-section {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+
#header {
width: 100%;
overflow: hidden;