Skip to content
Merged
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
4 changes: 2 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
rel="stylesheet"
/>
</head>
<body>
<div id="root" class="bg-primary"></div>
<body class="h-dvh">
<div id="root" class="h-full bg-primary"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
5 changes: 0 additions & 5 deletions src/App.tsx

This file was deleted.

16 changes: 13 additions & 3 deletions src/components/Layout/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default function Footer() {
<div className="footer-container text-primary">
<h4 className="flex items-center gap-2 text-xl font-bold">
<Code size={48} className="text-primary" />
Code Cafe
Code Café
</h4>
<p className="text-sm">Your home for coding and community</p>
</div>
Expand All @@ -25,9 +25,19 @@ export default function Footer() {
<div className="footer-container text-primary">
<h4 className="mb-4 text-xl font-bold">Resources</h4>
<ul className="list-none">
<li className="mb-3 text-sm">Documentation</li>
<li className="mb-3 text-sm">
<Link to="/resources">Resources</Link>
</li>
<li className="mb-3 text-sm">Blog</li>
<li className="mb-3 text-sm">GitHub</li>
<li className="mb-3 text-sm">
<a
href="https://github.com/CodeCafeCommunity/codecafecommunity.github.io"
target="_blank"
rel="noreferrer"
>
GitHub
</a>
</li>
</ul>
</div>
</footer>
Expand Down
7 changes: 6 additions & 1 deletion src/components/Layout/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default function Header() {
src={"/images/coffee_cup.png"}
alt="Code Cafe Logo"
/>
<h1 className="text-3xl text-secondary">Code Cafe</h1>
<h1 className="text-3xl text-secondary">Code Café</h1>
</NavLink>
<nav>
<ul className="flex list-none gap-3 text-secondary">
Expand All @@ -23,6 +23,11 @@ export default function Header() {
About Us
</NavLink>
</li>
<li>
<NavLink className="hover:text-accent" to="/resources">
Resources
</NavLink>
</li>
<li>
<NavLink className="hover:text-accent" to="/events">
Events
Expand Down
4 changes: 2 additions & 2 deletions src/components/Layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { Outlet } from "react-router";

export default function Layout() {
return (
<>
<div className="flex h-full flex-col justify-between">
<Header />
<Outlet />
<Footer />
</>
</div>
);
}
30 changes: 30 additions & 0 deletions src/data/resources/css.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"pageName": "CSS Resources",
"entries": [
{
"title": "CSS Official Docs",
"url": "https://developer.mozilla.org/en-US/docs/Web/CSS",
"tags": ["css", "official docs"]
},
{
"title": "Tailwind Official Docs",
"url": "https://tailwindcss.com",
"tags": [
"css",
"official docs",
"tailwind",
"test1",
"test2",
"test3",
"test4",
"test5",
"test6"
]
},
{
"title": "CSS Flexbox Layout Guide",
"url": "https://css-tricks.com/snippets/css/a-guide-to-flexbox/",
"tags": ["css", "cheatsheet"]
}
]
}
10 changes: 10 additions & 0 deletions src/data/resources/html.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"pageName": "HTML Resources",
"entries": [
{
"title": "HTML Official Docs",
"url": "https://developer.mozilla.org/en-US/docs/Web/HTML",
"tags": ["html", "official docs"]
}
]
}
15 changes: 15 additions & 0 deletions src/data/resources/javascript.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"pageName": "JavaScript Resources",
"entries": [
{
"title": "JavaScript Official Docs",
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript",
"tags": ["javascript", "official docs"]
},
{
"title": "javacript.info",
"url": "https://javascript.info",
"tags": ["javascript", "crash course"]
}
]
}
4 changes: 4 additions & 0 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import "./index.css";
import Layout from "./components/Layout";
import Home from "./routes/Home";
import About from "./routes/About";
import Resources from "./routes/Resources";
import ResourcePage from "./routes/Resources/ResourcePage";

const root = document.getElementById("root");

Expand All @@ -16,6 +18,8 @@ if (root) {
<Route element={<Layout />}>
<Route index element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/resources" element={<Resources />} />
<Route path="/resources/:category" element={<ResourcePage />} />
</Route>
</Routes>
</BrowserRouter>
Expand Down
2 changes: 1 addition & 1 deletion src/routes/Home/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export default function Hero() {
return (
<section
id="hero"
className="flex min-h-[8vh] flex-col items-center justify-evenly bg-primary py-8 text-accent"
className="flex flex-col items-center justify-evenly bg-primary py-8 text-accent"
>
<div className="flex flex-wrap items-center justify-center p-8 text-center lg:p-5 xl:flex-nowrap">
<div className="flex flex-col items-center">
Expand Down
21 changes: 21 additions & 0 deletions src/routes/Resources/CategoryCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Link } from "react-router";

interface Props {
name: string;
slug: string;
}

const CategoryCard = ({ name, slug }: Props) => {
return (
<>
<Link
to={slug}
className="my-4 min-w-[50%] rounded-lg border-2 border-primary px-6 py-12 text-center text-2xl shadow-lg shadow-primary hover:bg-primary hover:text-accent hover:shadow-2xl hover:shadow-primary"
>
{name}
</Link>
</>
);
};

export default CategoryCard;
27 changes: 27 additions & 0 deletions src/routes/Resources/ResourceCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Entry } from "./types";

const ResourceCard = ({ entry }: { entry: Entry }) => {
return (
<div className="min-h-24 w-96 rounded-md bg-slate-400 text-center shadow-lg shadow-gray-600 hover:shadow-2xl hover:shadow-gray-600">
<a
href={entry.url}
target="_blank"
rel="noreferrer"
className="flex h-full w-full flex-col justify-around px-6 py-4"
>
<p className="pb-4 text-xl text-primary">{entry.title}</p>
<div className="flex flex-wrap justify-center gap-2">
{entry.tags.map((t) => (
<div
key={t}
className="rounded-xl border-transparent bg-slate-300 px-2 pb-1"
>
{t}
</div>
))}
</div>
</a>
</div>
);
};
export default ResourceCard;
92 changes: 92 additions & 0 deletions src/routes/Resources/ResourcePage.tsx
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably the only suggestion I would add is for an extra button on the resource page to return to all the categories

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I'll open up a ticket for that so we don't make this PR any bigger 👍

Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { useEffect, useState } from "react";
import { useParams } from "react-router";
import { JsonData, Entry } from "./types";
import ResourceCard from "./ResourceCard";
import { extractTags, sortEntries } from "./utils";

const ResourcePage = () => {
const { category } = useParams();
const [data, setData] = useState<JsonData | null>(null);
const [entries, setEntries] = useState<Entry[]>([]);
const [tags, setTags] = useState<string[]>([]);
const [filters, setFilters] = useState<string[]>([]);

useEffect(() => {
const fetchData = async () => {
if (category) {
const dataObject = (await import(
`../../data/resources/${category}.json`
)) as { default: JsonData };
return dataObject.default;
} else {
return { pageName: "", entries: [] };
}
};

fetchData()
.then((json) => {
if (json.entries.length > 0) {
setData(json);
setEntries(sortEntries(json.entries));
setTags(extractTags(json.entries));
}
})
.catch(console.error);
}, [category]);

const filterColor = (tag: string) =>
filters.includes(tag) ? "bg-slate-400" : "bg-slate-300";

if (data) {
return (
<>
<section className="w-full bg-background">
<h3 className="my-12 text-center text-4xl text-primary">
{data.pageName}
</h3>
<div className="mb-6 flex w-full flex-col items-center justify-center text-center">
<h4 className="text-xl font-bold text-primary">Categories</h4>
<div className="mt-4 flex w-96 flex-wrap justify-center gap-2 xl:w-[600px]">
{tags.map((t) => (
<div
key={t}
onClick={() => {
setFilters([...filters, t]);
setEntries(entries.filter((e) => e.tags.includes(t)));
}}
>
<button
className={`rounded-xl border-transparent bg-slate-300 px-2 pb-1 ${filterColor(t)}`}
>
{t}
</button>
</div>
))}
{filters.length > 0 && (
<button
className="rounded-xl bg-accent px-2 pb-1 text-primary"
onClick={() => {
setFilters([]);
setEntries(sortEntries(data.entries));
}}
>
Clear filters &times;
</button>
)}
</div>
</div>
<div className="flex w-full justify-center pb-12">
<div className="mx-4 flex flex-wrap justify-center gap-6 sm:w-5/6 xl:w-3/4">
{entries.map((e) => (
<ResourceCard entry={e} key={e.title} />
))}
</div>
</div>
</section>
</>
);
}

return <></>;
};
export default ResourcePage;
21 changes: 21 additions & 0 deletions src/routes/Resources/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import CategoryCard from "./CategoryCard";

const Resources = () => (
<main className="flex h-full w-full flex-col">
<section className="flex h-full flex-col justify-center">
<h3 className="my-12 text-center text-3xl text-secondary">Resources</h3>
<div className="flex w-full justify-center bg-background">
<div className="grid grid-cols-3 place-items-center gap-y-6 sm:w-5/6 xl:w-3/4">
<CategoryCard name="HTML" slug="html" />
<CategoryCard name="CSS" slug="css" />
<CategoryCard name="JavaScript" slug="javascript" />
<CategoryCard name="Python" slug="python" />
<CategoryCard name="Java" slug="java" />
<CategoryCard name="C++" slug="c-plus-plus" />
</div>
</div>
</section>
</main>
);

export default Resources;
10 changes: 10 additions & 0 deletions src/routes/Resources/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export interface JsonData {
pageName: string;
entries: Entry[];
}

export interface Entry {
title: string;
url: string;
tags: string[];
}
16 changes: 16 additions & 0 deletions src/routes/Resources/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Entry } from "./types";

export const sortEntries = (entries: Entry[]) =>
entries.sort((a, b) => (sanitize(a.title) < sanitize(b.title) ? -1 : 1));

const sanitize = (title: string) =>
title.toLowerCase().replace("the", "").trim();

export const extractTags = (entries: Entry[]) => [
...new Set(
entries.reduce<string[]>((acc, cur) => {
acc.push(...cur.tags);
return acc;
}, []),
),
];