Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import RoboSub from "./Pages/RoboSub";
import AUVTechnology from "./Pages/AUVTechnology";
import Sponsors from "./Pages/Sponsors";
import OurTeam from "./Pages/OurTeam";
import Blog from "./Pages/Blog";
import {blogs} from "./data/blogData"
import "./App.css";

function App() {
Expand All @@ -24,6 +26,7 @@ function App() {
<Route path="/ourteam" element={<OurTeam />} />
<Route path="/sponsors" element={<Sponsors />} />
<Route path="/contact" element={<Contact />} />
<Route path="/blog" element={<Blog blogs={blogs} />} />
</Routes>
</main>
{/* We'll add a footer component later */}
Expand Down
9 changes: 9 additions & 0 deletions src/Components/Navbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ function Navbar() {
About Us
</Link>
</li>
<li>
<Link
to="/blog"
className={isActive("/blog") ? "active" : ""}
onClick={closeMenu}
>
Blog
</Link>
</li>
<li>
<Link
to="/robosub"
Expand Down
108 changes: 108 additions & 0 deletions src/Pages/Blog.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React, { useState } from "react";
import "../styles/Blog.css";

function Blog({ blogs }) {
const [filterYear, setFilterYear] = useState(null);
const [filterCategory, setFilterCategory] = useState(null);

const filteredBlogs = blogs.filter((blog) => {
const matchesYear = filterYear ? blog.year === filterYear : true;
const matchesCategory = filterCategory ? blog.category === filterCategory : true;
return matchesYear && matchesCategory;
});

const years = Array.from(new Set(blogs.map(b => b.year))).sort((a,b) => b-a);
const categories = Array.from(new Set(blogs.map(b => b.category)));

const handleYearClick = (year) => {
setFilterYear(year);
setFilterCategory(null);
};

const handleCategoryClick = (cat) => {
setFilterCategory(cat);
setFilterYear(null);
};

const getFilterText = () => {
if (filterYear) {
return `${filterYear}`;
} else if (filterCategory) {
return `${filterCategory}`;
}
return null;
};

return (
<div className="blog-page">
<section className="blog-hero-section">
<div className="container">
<div className="hero-content">
<h1 className="hero-title">Our Blog</h1>
<div className="hero-divider"></div>
<p className="hero-subtitle">MIL blog posts since 2011</p>
{getFilterText() && (
<p className="filter-display">{getFilterText()}</p>
)}
</div>
</div>
</section>

<section className="blog-list-section">
<div className="container blog-layout">
<div className="blog-list-column">
{filteredBlogs.length > 0 ? (
filteredBlogs.map((blog, index) => {
const blogDate = new Date(`${blog.year}-${blog.month}-${blog.day}`);
return (
<div className="blog-card" key={index}>
<div className="blog-card-header">
<h2 className="blog-title">{blog.title}</h2>
<p className="blog-date">
{blogDate.toLocaleDateString(undefined, {
year: "numeric",
month: "long",
day: "numeric",
})} | {blog.category} | {blog.author}
</p>
</div>
<div className="blog-card-body">
<p className="blog-description">{blog.description}</p>
</div>
</div>
);
})
) : (
<p className="no-blogs">No blog posts available.</p>
)}
</div>

<aside className="blog-sidebar">
<div className="archive">
<h3>Archive</h3>
{years.map(year => {
const count = blogs.filter(b => b.year === year).length;
return (
<p key={year} className="sidebar-link" onClick={() => handleYearClick(year)}>
{year} ({count})
</p>
);
})}
</div>

<div className="categories">
<h3>Categories</h3>
{categories.map(cat => (
<p key={cat} className="sidebar-link" onClick={() => handleCategoryClick(cat)}>
{cat}
</p>
))}
</div>
</aside>
</div>
</section>
</div>
);
}

export default Blog;
21 changes: 21 additions & 0 deletions src/data/blogData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export const blogs = [
{
title: "Post1 placeholder",
year: "2025",
month: "06",
day: "12",
category: "Sponsorship News",
description: "Post 1",
author: "SubjuGator"
},
{
title: "Post2 placeholder",
year: "2025",
month: "06",
day: "12",
category: "Team News",
description: "Post 2",
author: "SubjuGator"
}
];

127 changes: 127 additions & 0 deletions src/styles/Blog.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
.blog-page {
background-color: var(--color-background);
color: #fff;
min-height: 100vh;
}

.blog-hero-section {
min-height: 40vh;
display: flex;
align-items: flex-end;
justify-content: center;
position: relative;
background-image: url("/src/assets/blog-hero.jpg");
background-size: cover;
background-position: center;
background-repeat: no-repeat;
overflow: hidden;
}

.blog-hero-section .hero-content {
text-align: center;
margin-bottom: 40px;
}

.blog-list-section {
padding: 50px 20px;
}

.blog-list-section .container.blog-layout {
display: grid;
grid-template-columns: minmax(0, 1060px) 300px;
gap: 40px;
max-width: 1400px;
margin: 0 auto;
}

.blog-list-column {
display: flex;
flex-direction: column;
gap: 30px;
width: 100%;
}

.blog-card {
background-color: var(--color-ui-dark);
border-radius: 10px;
padding: 30px;
border: 1px solid rgba(255, 255, 255, 0.08);
transition: transform 0.3s ease, box-shadow 0.3s ease;
width: 100%;
min-height: 250px;
display: flex;
flex-direction: column;
justify-content: space-between;
}

.blog-card:hover {
transform: translateY(-6px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
border-color: rgba(250, 70, 22, 0.3);
}

.blog-card-header {
display: flex;
flex-direction: column;
align-items: flex-start;
margin-bottom: 15px;
}

.blog-title {
font-size: 1.8rem;
margin: 0;
color: #fff;
}

.blog-date {
font-size: 1.5rem;
color: rgba(255, 255, 255, 0.6);
margin-top: 5px;
}

.blog-description {
font-size: 1.5rem;
line-height: 1.6;
color: rgba(255, 255, 255, 0.85);
}

.no-blogs {
text-align: center;
color: rgba(255, 255, 255, 0.6);
font-size: 1.1rem;
}

.blog-sidebar {
background-color: var(--color-ui-dark);
padding: 20px;
border-radius: 10px;
height: fit-content;
}

.blog-sidebar h3 {
margin-bottom: 10px;
color: #fff;
}

.sidebar-link {
cursor: pointer;
color: rgba(255, 255, 255, 0.8);
margin-bottom: 5px;
}

.sidebar-link:hover {
color: #fa4616;
text-decoration: underline;
}

.sidebar-clear:hover {
color: #fa4616;
text-decoration: underline;
}

.filter-display {
margin-top: 15px;
font-size: 2.5rem;
color: #fff;
font-weight: 600;
}