implemented projects page and footer. added under construction splash to other pages.

This commit is contained in:
Joshua Ashton
2024-12-19 11:40:32 -07:00
parent 8a34f961fe
commit a067550415
17 changed files with 226 additions and 40 deletions
+10
View File
@@ -12,6 +12,7 @@
"react": "19.0.0-rc-3edc000d-20240926", "react": "19.0.0-rc-3edc000d-20240926",
"react-bootstrap": "^2.10.7", "react-bootstrap": "^2.10.7",
"react-dom": "19.0.0-rc-3edc000d-20240926", "react-dom": "19.0.0-rc-3edc000d-20240926",
"react-icons": "^5.4.0",
"react-router": "^7.0.2", "react-router": "^7.0.2",
"react-scripts": "^5.0.0" "react-scripts": "^5.0.0"
} }
@@ -13914,6 +13915,15 @@
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/react-icons": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.4.0.tgz",
"integrity": "sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==",
"license": "MIT",
"peerDependencies": {
"react": "*"
}
},
"node_modules/react-is": { "node_modules/react-is": {
"version": "17.0.2", "version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
+1
View File
@@ -13,6 +13,7 @@
"react": "19.0.0-rc-3edc000d-20240926", "react": "19.0.0-rc-3edc000d-20240926",
"react-bootstrap": "^2.10.7", "react-bootstrap": "^2.10.7",
"react-dom": "19.0.0-rc-3edc000d-20240926", "react-dom": "19.0.0-rc-3edc000d-20240926",
"react-icons": "^5.4.0",
"react-router": "^7.0.2", "react-router": "^7.0.2",
"react-scripts": "^5.0.0" "react-scripts": "^5.0.0"
}, },

Before

Width:  |  Height:  |  Size: 4.6 MiB

After

Width:  |  Height:  |  Size: 4.6 MiB

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 2.7 MiB

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

+1 -1
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title> <title>Josh Ashton</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
+2
View File
@@ -1,10 +1,12 @@
import Navigation from './components/Navigation'; import Navigation from './components/Navigation';
import Footer from './components/Footer'; import Footer from './components/Footer';
import Splash from './components/Splash';
export default function About() { export default function About() {
return ( return (
<> <>
<Navigation /> <Navigation />
<Splash primaryText="Under Construction" />
<Footer /> <Footer />
</> </>
); );
+2
View File
@@ -1,10 +1,12 @@
import Navigation from './components/Navigation'; import Navigation from './components/Navigation';
import Footer from './components/Footer'; import Footer from './components/Footer';
import Splash from './components/Splash';
export default function Blog() { export default function Blog() {
return ( return (
<> <>
<Navigation /> <Navigation />
<Splash primaryText="Under Construction" />
<Footer /> <Footer />
</> </>
); );
+2
View File
@@ -1,10 +1,12 @@
import Navigation from './components/Navigation'; import Navigation from './components/Navigation';
import Footer from './components/Footer'; import Footer from './components/Footer';
import Splash from './components/Splash';
export default function Contact() { export default function Contact() {
return ( return (
<> <>
<Navigation /> <Navigation />
<Splash primaryText="Under Construction" />
<Footer /> <Footer />
</> </>
); );
+2 -2
View File
@@ -6,8 +6,8 @@ import FeaturedContent from './components/FeaturedContent';
export default function Home() { export default function Home() {
const projectCards = [ const projectCards = [
<ProjectCard img="./assets/img/dnd.png" title="D&D" description="ASDF" url="https://github.com/quaxlyqueen/dnd"/>, <ProjectCard img="./assets/img/dnd.png" name="D&D" description="Dungeons and Dragons character builder app, developed in Java." url="https://github.com/quaxlyqueen/dnd"/>,
<ProjectCard img="./assets/img/graph.png" title="Graph Visualizer" description="ASDF" url="https://github.com/quaxlyqueen/2420-graph-visualizer"/>, <ProjectCard img="./assets/img/graph.png" name="Graph Visualizer" description="Interactive representation of a graph data structure, developed in Java." url="https://github.com/quaxlyqueen/2420-graph-visualizer"/>,
]; ];
return ( return (
<> <>
+29 -9
View File
@@ -1,6 +1,6 @@
import Navigation from './components/Navigation'; import Navigation from './components/Navigation';
import Footer from './components/Footer'; import Footer from './components/Footer';
import ProjectDisplay from './components/ProjectDisplay'; import ProjectCard from './components/ProjectCard';
/* /*
* The Projects page. * The Projects page.
@@ -8,24 +8,44 @@ import ProjectDisplay from './components/ProjectDisplay';
export default function Projects() { export default function Projects() {
/* /*
* An array of project data to feed to the ProjectDisplay component. * An array of project data to feed to the ProjectDisplay component.
{
frontend: "",
backend: "",
id: "",
name: "",
description: "",
url: "",
img: ""
},
*/ */
const data = [ const data = [
{ {
frontend: "flutter", frontend: "java",
backend: "go", backend: "",
id: "one-ai", id: "dnd",
name: 'One AI', name: "D&D",
description: "TODO", description: "Dungeons and Dragons character builder app, developed in Java.",
url: "https://github.com/quaxlyqueen/one-ai" url: "https://github.com/quaxlyqueen/dnd",
img: "/assets/img/dnd.png"
},
{
frontend: "java",
backend: "",
id: "graph",
name: "Graph Visualizer",
description: "Interactive representation of a graph data structure, developed in Java.",
url: "https://github.com/quaxlyqueen/2420-graph-visualizer",
img: "/assets/img/graph.png"
}, },
]; ];
let i = 0;
return ( return (
<> <>
<Navigation /> <Navigation />
<div> <div className="project-grid">
{data.map(item => ( {data.map(item => (
<ProjectDisplay frontend={item.frontend} backend={item.backend} id={item.id} name={item.name} description={item.description} url={item.url} /> <ProjectCard frontend={item.frontend} backend={item.backend} id={item.id} name={item.name} description={item.description} url={item.url} img={item.img} />
))} ))}
</div> </div>
<Footer /> <Footer />
+2
View File
@@ -1,10 +1,12 @@
import Navigation from './components/Navigation'; import Navigation from './components/Navigation';
import Footer from './components/Footer'; import Footer from './components/Footer';
import Splash from './components/Splash';
export default function Resume() { export default function Resume() {
return ( return (
<> <>
<Navigation /> <Navigation />
<Splash primaryText="Under Construction" />
<Footer /> <Footer />
</> </>
); );
+31 -6
View File
@@ -1,3 +1,7 @@
import { FaLinkedinIn } from 'react-icons/fa';
import { FaInstagram } from 'react-icons/fa';
import { FaTwitterinIn } from 'react-icons/fa';
import { FaThreadsIn } from 'react-icons/fa';
/** /**
* *
* *
@@ -6,13 +10,34 @@
*/ */
export default function Footer() { export default function Footer() {
return ( return (
<> <footer className="footer">
<div> <div className="container">
<p>Copyright or open source license here.</p> <div className="row">
<ul> <div className="col-md-6">
<li><a href="contact">Contact</a></li> <p>&copy; {new Date().getFullYear()} Josh Ashton</p>
</div>
<div className="col-md-6">
<ul className="social-links">
<li><a href="/">Home</a></li>
<li><a href="/projects">Projects</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
<li><a href="/resume">Resume</a></li>
<li><a href="/blog">Blog</a></li>
<li>
<a href="https://www.linkedin.com/in/joshuatashton/" target="_blank" rel="noopener noreferrer">
<FaLinkedinIn />
</a>
</li>
<li>
<a href="https://www.instagram.com/joshuatashton/" target="_blank" rel="noopener noreferrer">
<FaInstagram />
</a>
</li>
</ul> </ul>
</div> </div>
</> </div>
</div>
</footer>
); );
} }
+21 -2
View File
@@ -1,19 +1,38 @@
import React, { useState } from 'react';
import Nav from 'react-bootstrap/Nav'; import Nav from 'react-bootstrap/Nav';
import Button from 'react-bootstrap/Button'; import Button from 'react-bootstrap/Button';
/* /*
* Create a nav bar component. * Create a nav bar component.
* *
* Use Bootstrap for styling. * Use Bootstrap for styling.
*
* TODO: Add links as a prop.
*/ */
export default function Navigation() { export default function Navigation() {
const [isNavbarCollapsed, setIsNavbarCollapsed] = useState(false);
const toggleNavbar = () => {
setIsNavbarCollapsed(!isNavbarCollapsed);
};
return ( return (
<> <>
<nav className="navbar navbar-expand-lg navbar-light bg-light"> <nav className="navbar navbar-expand-lg navbar-light bg-light">
<a className="navbar-brand" href="/">Josh Ashton</a> <a className="navbar-brand" href="/">Josh Ashton</a>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <button
className="navbar-toggler"
type="button"
onClick={toggleNavbar}
aria-controls="navbarNav"
aria-expanded={isNavbarCollapsed}
aria-label="Toggle navigation"
>
<span className="navbar-toggler-icon"></span> <span className="navbar-toggler-icon"></span>
</button> </button>
<div className="collapse navbar-collapse" id="navbarNav"> <div
className={`collapse navbar-collapse ${isNavbarCollapsed ? 'show' : ''}`}
id="navbarNav"
>
<ul className="navbar-nav nav-fill w-100"> <ul className="navbar-nav nav-fill w-100">
<a className="nav-link" href="/projects"><li className="nav-item">Projects</li></a> <a className="nav-link" href="/projects"><li className="nav-item">Projects</li></a>
<a className="nav-link" href="/about"><li className="nav-item">About</li></a> <a className="nav-link" href="/about"><li className="nav-item">About</li></a>
+12 -9
View File
@@ -1,20 +1,23 @@
/* /*
* Create a ProjectCard. * Create a ProjectCard.
* *
* @param String frontend "The frontend framework/library used for the project. Used for sorting/filtering."
* @param String backend "The backend framework/library used for the project. Used for sorting/filtering."
* @param String id "Lowercase string representation of the project name."
* @param String name "The name of the project."
* @param String description "A description of the project."
* @param String url "The URL for the repository of the project."
* @param String img "Path to an image." * @param String img "Path to an image."
* @param String title "Title of the card." * @param String imgCaption "Accessibile caption for the image."
* @param String description "A short description for the card."
* @param String url "URL to a project."
*
* TODO: Need to add classes and styling.
*/ */
export default function ProjectCard( {img, title, description, url} ) { export default function ProjectCard( {frontend, backend, id, name, description, url, img, imgCaption} ) {
console.log(img);
return ( return (
<> <>
<div className="card"> <div className={`card ${frontend} ${backend}`}>
<img className="card-img-top" src={img} alt="TODO: Image caption."/> <img className="card-img-top" src={img} alt={imgCaption}/>
<div className="card-body"> <div className="card-body">
<h2 className="card-title dark-text">{title}</h2> <h2 className="card-title dark-text">{name}</h2>
<p className="dark-text">{description}</p> <p className="dark-text">{description}</p>
<a className = "btn btn-primary" target="_blank" href={url}>View Code on GitHub</a> <a className = "btn btn-primary" target="_blank" href={url}>View Code on GitHub</a>
</div> </div>
+22 -2
View File
@@ -1,3 +1,5 @@
import React, { useState } from 'react';
import Button from 'react-bootstrap/Button';
/* /*
* Create a clickable frame which expands to expose additional information on click. * Create a clickable frame which expands to expose additional information on click.
* *
@@ -9,12 +11,30 @@
* TODO: Need to implement onClick * TODO: Need to implement onClick
*/ */
export default function ProjectDisplay( {frontend, backend, id, name, description, url} ) { export default function ProjectDisplay( {frontend, backend, id, name, description, url} ) {
const [isDisplayCollapsed, setIsDisplayCollapsed] = useState(false);
const toggleDisplay = () => {
setIsDisplayCollapsed(!isDisplayCollapsed);
}
return ( return (
<> <>
<div className={`panel ${frontend} ${backend}`} id={id}> <div
className={`panel ${frontend} ${backend} ${isDisplayCollapsed ? 'open open-active' : ''}`}
id={id}
onClick={toggleDisplay}
aria-expanded={!isDisplayCollapsed} // Invert the condition for aria-expanded
>
<h3 className="label">{name}</h3> <h3 className="label">{name}</h3>
{isDisplayCollapsed && ( // Conditionally render additional content
<>
<h4 className="label-text">{description}</h4> <h4 className="label-text">{description}</h4>
<button type="button" className="btn btn-primary"><a target="_blank" href={url}>View Code on GitHub</a></button> <button type="button" className="btn btn-primary">
<a target="_blank" href={url}>
View Code on GitHub
</a>
</button>
</>
)}
</div> </div>
</> </>
); );
+84 -4
View File
@@ -1,6 +1,6 @@
:root { :root {
--main-dark-color: #4A245E; --main-dark-color: #4A245E;
--main-offwhite-color: white, --main-offwhite-color: white;
--main-midtone-color: #9BC995; --main-midtone-color: #9BC995;
--main-accent-color: #673283; --main-accent-color: #673283;
--secondary-accent-color: #98B9AB; --secondary-accent-color: #98B9AB;
@@ -92,7 +92,7 @@ p {
.navbar-brand { .navbar-brand {
padding-left: .5vw; padding-left: .5vw;
color: #4A245E; color: var(--main-dark-color);
font-size: 2vw; font-size: 2vw;
font-weight: bold; font-weight: bold;
@@ -132,7 +132,7 @@ p {
} }
.nav-link:hover { .nav-link:hover {
color: var(--main-dark-color); background-color: var(--main-dark-color);
} }
.bar { .bar {
@@ -206,6 +206,7 @@ input[type="radio"]:hover + label {
background-position: center; background-position: center;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden;
} }
.panel > * { .panel > * {
@@ -247,10 +248,19 @@ input[type="radio"]:hover + label {
} }
.panel.open { .panel.open {
overflow: visible;
flex: 5; flex: 5;
font-size: 2em; font-size: 2em;
} }
.panel .label-text, .panel .btn {
display: none;
}
.panel.open .label-text, .panel.open .btn {
display: block;
}
.carousel-wrapper { .carousel-wrapper {
flex: 0 0 40%; flex: 0 0 40%;
padding-top: 5vw; padding-top: 5vw;
@@ -274,6 +284,24 @@ input[type="radio"]:hover + label {
margin-right: auto; margin-right: auto;
} }
.card {
display: flex; /* Enable flexbox layout */
flex-direction: column; /* Stack items vertically */
align-items: center; /* Center items horizontally */
justify-content: center; /* Center items vertically */
margin: 1vw;
}
.card img {
max-width: 50vw;
max-height: 35vw;
object-fit: cover;
}
.card-body {
text-align: center;
}
.card-text { .card-text {
font-size: 2vw; font-size: 2vw;
} }
@@ -316,10 +344,62 @@ input[type="radio"]:hover + label {
.btn:hover { .btn:hover {
background-color: var(--main-accent-color); background-color: var(--main-accent-color);
border: 2px solid var(--main-offwhite-color);
} }
.btn > a { .btn > a {
text-decoration: none; text-decoration: none;
color: var(--main-offwhite-color); color: var(--main-offwhite-color);
} }
.social-links {
list-style: none; /* Remove default list styling */
display: flex; /* Display list items as flex items */
justify-content: space-between; /* Space items evenly */
}
.social-links li {
margin: 0 10px; /* Add spacing between icons */
}
.social-links li a {
text-decoration: none;
color: var(--main-offwhite-color);
}
.project-grid {
display: flex;
flex-wrap: wrap;
justify-content: space-between; /* Distribute projects evenly */
margin: 2vw auto; /* Center grid horizontally */
}
/* Responsive Breakpoints */
@media (min-width: 992px) { /* Large Screens (3 columns) */
.project-grid {
width: 80%; /* Adjust width as needed */
}
.project-grid > * {
flex: 0 0 30%; /* Set a fixed width for each project */
}
}
@media (min-width: 768px) and (max-width: 991px) { /* Medium Screens (2 columns) */
.project-grid {
width: 80%; /* Adjust width as needed */
}
.project-grid > * {
flex: 0 0 40%; /* Set a fixed width for each project */
}
}
@media (max-width: 767px) { /* Small Screens (1 column) */
.project-grid {
width: 80%;
}
.project-grid > * {
flex: 1 1 80%; /* Set full width for each project */
}
}