Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit fa19b37

Browse files
committedNov 29, 2024
Made a bunch of crap and trying to fix it somehow
1 parent 15a4112 commit fa19b37

18 files changed

+276
-335
lines changed
 

‎public/data/index.json

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1-
{
2-
"languages": ["JavaScript", "Sass"]
3-
}
1+
[
2+
{
3+
"language": "Sass",
4+
"icon": "/icons/sass.svg"
5+
},
6+
{
7+
"language": "CSS",
8+
"icon": "/icons/css.svg"
9+
}
10+
]

‎public/icons/css.svg

Lines changed: 8 additions & 0 deletions
Loading

‎public/icons/sass.svg

Lines changed: 3 additions & 0 deletions
Loading

‎src/App.tsx

Lines changed: 85 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,100 @@
11
import Footer from "./layouts/Footer";
22
import Header from "./layouts/Header";
3-
import SnippetList from "./components/SnippetList";
4-
import Sidebar from "./layouts/Sidebar";
5-
import { Navigate, useLocation } from "react-router-dom";
6-
import SnippetModal from "./components/SnippetModal";
3+
import Banner from "./layouts/Banner";
4+
import { useState } from "react";
5+
import Button from "./components/Button";
6+
import { CopyIcon, ExpandIcon } from "./components/Icons";
7+
import slugify from "./utils/slugify";
8+
import { useLanguages } from "./hooks/useLanguages";
9+
import { useCategories } from "./hooks/useCategories";
10+
import { useSnippets } from "./hooks/useSnippets";
11+
12+
type LanguageType = {
13+
language: string;
14+
icon: string;
15+
};
16+
17+
type SnippetType = {
18+
title: string;
19+
description: string;
20+
code: string;
21+
tags: string[];
22+
author: string;
23+
};
724

825
const App = () => {
9-
const location = useLocation();
26+
const [language, setLanguage] = useState<LanguageType>({
27+
language: "Sass",
28+
icon: "/icons/sass.svg",
29+
});
30+
const [category, setCategory] = useState<string>("");
31+
const [snippet, setSnippet] = useState<SnippetType>();
32+
33+
const { fetchedLanguages } = useLanguages();
34+
const { fetchedCategories } = useCategories(language.language);
35+
const { fetchedSnippets } = useSnippets(language.language, category);
1036

11-
if (location.pathname === "/") {
12-
return <Navigate to="/javascript/dom-manipulation" replace />;
13-
}
37+
const handleLanguageChange = (
38+
event: React.ChangeEvent<HTMLSelectElement>
39+
) => {
40+
const language = fetchedLanguages.find(
41+
(lan) => slugify(lan.language) === slugify(event.target.value)
42+
);
43+
if (language) {
44+
setLanguage(language);
45+
}
46+
};
1447

1548
return (
1649
<>
17-
{/* Had to put the modal in App.tsx as well for it to work despite
18-
it's also being created in HTML with portal.
19-
If you know why it's that way, please let me know. */}
20-
<SnippetModal />
50+
{/* <SnippetModal /> */}
2151
<div className="container flow" data-flow-space="xl">
2252
<Header />
23-
<div className="heading">
24-
<h1 className="main-title">
25-
Made to save your <span className="text-highlight">time.</span>
26-
</h1>
27-
<p>
28-
Find the necessary snippet in seconds, across multiple languages.
29-
Just search and copy!
30-
</p>
31-
</div>
53+
<Banner />
3254
<main className="main">
33-
<Sidebar />
34-
<SnippetList />
55+
<aside className="sidebar flow">
56+
<select
57+
id="languages"
58+
className="language-switcher"
59+
onChange={handleLanguageChange}
60+
>
61+
{fetchedLanguages.map(({ language }) => (
62+
<option key={language} value={slugify(language)}>
63+
{language}
64+
</option>
65+
))}
66+
</select>
67+
<ul role="list" className="categories">
68+
{fetchedCategories.map((name) => (
69+
<li className="category">
70+
<button onClick={() => setCategory(name)}>{name}</button>
71+
</li>
72+
))}
73+
</ul>
74+
</aside>
75+
<section className="flow">
76+
<h2 className="section-title">{category}</h2>
77+
<ul role="list" className="snippets">
78+
{fetchedSnippets.map((snippet) => (
79+
<li className="snippet">
80+
<div className="snippet__preview">
81+
<img src={language.icon} alt={language.language} />
82+
<Button isIcon={true} className="snippet__copy">
83+
<CopyIcon />
84+
</Button>
85+
</div>
86+
87+
<div className="snippet__content">
88+
<h3 className="snippet__title">{snippet.title}</h3>
89+
<Button isIcon={true}>
90+
<ExpandIcon />
91+
</Button>
92+
</div>
93+
</li>
94+
))}
95+
</ul>
96+
</section>
3597
</main>
36-
<hr className="divider" />
3798
<Footer />
3899
</div>
39100
</>

‎src/components/Category.tsx

Lines changed: 0 additions & 18 deletions
This file was deleted.

‎src/components/CategoryList.tsx

Lines changed: 0 additions & 45 deletions
This file was deleted.

‎src/components/LanguageSwitch.tsx

Lines changed: 0 additions & 56 deletions
This file was deleted.

‎src/components/Logo.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import { LogoIcon } from "./Icons";
33

44
const Logo = () => {
55
return (
6-
<Link to={"/"} className="logo">
6+
<a href="/" className="logo">
77
<LogoIcon />
88
<span>QuickSnip</span>
9-
</Link>
9+
</a>
1010
);
1111
};
1212

‎src/components/SnippetCard.tsx

Lines changed: 0 additions & 26 deletions
This file was deleted.

‎src/components/SnippetList.tsx

Lines changed: 0 additions & 57 deletions
This file was deleted.

‎src/components/SnippetModal.tsx

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { useEffect, useState } from "react";
22
import ReactDOM from "react-dom";
3-
import { useNavigate, useParams } from "react-router-dom";
43
import { LanguageData, SnippetType } from "../types";
54
import { getSnippetByTitleAndCategory } from "../utils/filters";
65
import { CloseIcon, CopyIcon } from "./Icons";
@@ -11,37 +10,6 @@ const SnippetModal = () => {
1110
const modalRoot = document.getElementById("modal-root");
1211
if (!modalRoot) return null;
1312

14-
const { language, category, snippet_title } = useParams();
15-
const [snippet, setSnippet] = useState<SnippetType | null>(null);
16-
const navigate = useNavigate();
17-
18-
useEffect(() => {
19-
const fetchSnippets = async () => {
20-
try {
21-
const res = await fetch(`/data/${language}.json`);
22-
if (!res.ok) {
23-
throw new Error("Failed to fetch languages in SnippetModal.tsx");
24-
}
25-
const data: LanguageData = await res.json();
26-
27-
// TODO: instead of "", use default category as fallback
28-
const filteredSnippet = getSnippetByTitleAndCategory(
29-
data,
30-
category || "",
31-
snippet_title || ""
32-
);
33-
34-
setSnippet(filteredSnippet);
35-
} catch (error) {
36-
console.error("Error occured with SnippetModal.tsx: ", error);
37-
}
38-
};
39-
40-
fetchSnippets();
41-
}, [snippet_title]);
42-
43-
if (!snippet) return null;
44-
4513
return ReactDOM.createPortal(
4614
<div className="modal-overlay">
4715
<div className="modal | flow" data-flow-space="lg">

‎src/hooks/useCategories.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { useEffect, useState } from "react";
2+
import { LanguageData } from "../types";
3+
4+
export const useCategories = (language: string) => {
5+
const [fetchedCategories, setFetchedCategories] = useState<string[]>([]);
6+
7+
useEffect(() => {
8+
const fetchCategories = async () => {
9+
try {
10+
const res = await fetch(`/data/${language}.json`);
11+
if (!res.ok) {
12+
throw new Error("Failed to fetch languages in CategoryList.tsx");
13+
}
14+
const data: LanguageData = await res.json();
15+
const filteredCategoryNames = data.map(
16+
(category) => category.categoryName
17+
);
18+
19+
setFetchedCategories(filteredCategoryNames);
20+
} catch (error) {
21+
console.error("Error occured with CategoryList.tsx", error);
22+
}
23+
};
24+
25+
fetchCategories();
26+
}, [language]);
27+
28+
return { fetchedCategories };
29+
};

‎src/hooks/useLanguages.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { useEffect, useState } from "react";
2+
3+
type LanguageType = {
4+
language: string;
5+
icon: string;
6+
};
7+
8+
export const useLanguages = () => {
9+
const [fetchedLanguages, setFetchedLanguages] = useState<LanguageType[]>([]);
10+
const [error, setError] = useState<string | null>(null);
11+
const [loading, setLoading] = useState<boolean>(true);
12+
13+
useEffect(() => {
14+
const fetchLanguages = async () => {
15+
try {
16+
const res = await fetch(`/data/index.json`);
17+
if (!res.ok) {
18+
throw new Error("Failed to fetch languages");
19+
}
20+
const data = await res.json();
21+
setFetchedLanguages(data);
22+
} catch (err) {
23+
setError((err as Error).message);
24+
} finally {
25+
setLoading(false);
26+
}
27+
};
28+
29+
fetchLanguages();
30+
}, []);
31+
32+
return { fetchedLanguages, loading, error };
33+
};

‎src/hooks/useSnippets.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { useState, useEffect } from "react";
2+
import { LanguageData } from "../types";
3+
import slugify from "../utils/slugify";
4+
5+
type SnippetType = {
6+
title: string;
7+
description: string;
8+
code: string;
9+
tags: string[];
10+
author: string;
11+
};
12+
13+
export const useSnippets = (language: string, category: string) => {
14+
const [fetchedSnippets, setFetchedSnippets] = useState<SnippetType[]>([]);
15+
16+
useEffect(() => {
17+
const fetchSnippets = async () => {
18+
try {
19+
const res = await fetch(`/data/${slugify(language)}.json`);
20+
if (!res.ok) {
21+
throw new Error("Failed to fetch language data");
22+
}
23+
24+
const data: LanguageData = await res.json();
25+
26+
const fetchedCategory = data.find(
27+
(item) => slugify(item.categoryName) === slugify(category)
28+
);
29+
const snippets = fetchedCategory ? fetchedCategory.snippets : [];
30+
31+
setFetchedSnippets(snippets);
32+
} catch (error) {
33+
throw new Error("Something went wrong!" + error);
34+
}
35+
};
36+
37+
fetchSnippets();
38+
}, [language, category]);
39+
40+
return { fetchedSnippets };
41+
};

‎src/layouts/Banner.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const Banner = () => {
2+
return (
3+
<div className="heading">
4+
<h1 className="main-title">
5+
Made to save your <span className="text-highlight">time.</span>
6+
</h1>
7+
<p>
8+
Find the necessary snippet in seconds, across multiple languages. Just
9+
search and copy!
10+
</p>
11+
</div>
12+
);
13+
};
14+
15+
export default Banner;

‎src/layouts/Footer.tsx

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,44 @@ import Logo from "../components/Logo";
22

33
const Footer = () => {
44
return (
5-
<footer className="footer">
6-
<div className="footer__content flow" data-flow-space="sm">
7-
<Logo />
8-
<p>
9-
<b>QuickSnip</b> is your go-to collection of handy code snippets,
10-
making repetitive tasks easier and faster for developers across
11-
different programming languages.
12-
</p>
13-
<p>
14-
Built by <a href="#">Technophile</a>, and powered by awesome{" "}
15-
<a href="#">community</a>.
16-
</p>
17-
</div>
18-
<nav>
19-
<ul className="flow" data-flow-space="sm">
20-
<li>
21-
<a href="#">Add your own snippet</a>
22-
</li>
23-
<li>
24-
<a href="#">Edit this page on GitHub</a>
25-
</li>
26-
</ul>
27-
</nav>
28-
<nav>
29-
<ul className="flow" data-flow-space="sm">
30-
<li>
31-
<a href="#">See the community</a>
32-
</li>
33-
<li>
34-
<a href="#">Support this project</a>
35-
</li>
36-
</ul>
37-
</nav>
38-
</footer>
5+
<>
6+
<hr className="divider" />
7+
8+
<footer className="footer">
9+
<div className="footer__content flow" data-flow-space="sm">
10+
<Logo />
11+
<p>
12+
<b>QuickSnip</b> is your go-to collection of handy code snippets,
13+
making repetitive tasks easier and faster for developers across
14+
different programming languages.
15+
</p>
16+
<p>
17+
Built by <a href="#">Technophile</a>, and powered by awesome{" "}
18+
<a href="#">community</a>.
19+
</p>
20+
</div>
21+
<nav>
22+
<ul className="flow" data-flow-space="sm">
23+
<li>
24+
<a href="#">Add your own snippet</a>
25+
</li>
26+
<li>
27+
<a href="#">Edit this page on GitHub</a>
28+
</li>
29+
</ul>
30+
</nav>
31+
<nav>
32+
<ul className="flow" data-flow-space="sm">
33+
<li>
34+
<a href="#">See the community</a>
35+
</li>
36+
<li>
37+
<a href="#">Support this project</a>
38+
</li>
39+
</ul>
40+
</nav>
41+
</footer>
42+
</>
3943
);
4044
};
4145

‎src/main.tsx

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,9 @@ import { StrictMode } from "react";
22
import { createRoot } from "react-dom/client";
33
import "./styles/main.css";
44
import App from "./App";
5-
import { createBrowserRouter, RouterProvider } from "react-router-dom";
6-
import CategoryList from "./components/CategoryList";
7-
import SnippetList from "./components/SnippetList";
8-
import SnippetModal from "./components/SnippetModal";
9-
10-
const router = createBrowserRouter([
11-
{
12-
path: "/",
13-
element: <App />,
14-
children: [
15-
{
16-
path: ":language",
17-
element: <CategoryList />,
18-
},
19-
{
20-
path: ":language/:category",
21-
element: <SnippetList />,
22-
},
23-
{
24-
path: ":language/:category/:snippet_title",
25-
element: <SnippetModal />,
26-
},
27-
],
28-
},
29-
]);
305

316
createRoot(document.getElementById("root")!).render(
327
<StrictMode>
33-
<RouterProvider router={router} />
8+
<App />
349
</StrictMode>
3510
);

‎src/utils/filters.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
1+
import { LanguageType, useLanguages } from "../hooks/useLanguages";
12
import { LanguageData, SnippetType } from "../types";
23
import slugify from "./slugify";
34

4-
export const getCategoryNames = (data: LanguageData): string[] => {
5-
return data.map((category) => category.categoryName);
6-
};
5+
// export const getLanguageInfo = (language: string) => {
6+
// const { languages } = useLanguages();
77

8-
export const getSnippetsByCategory = (
9-
data: LanguageData,
10-
categoryName: string
11-
): SnippetType[] | null => {
12-
const category = data.find(
13-
(category) => slugify(category.categoryName) === slugify(categoryName)
14-
);
15-
return category ? category.snippets : null;
16-
};
8+
// for (let i = 0; i < languages.length; i++) {
9+
// if (slugify(languages[i].language) === slugify(language)) {
10+
// return languages[i];
11+
// }
12+
// }
13+
14+
// return languages[0];
15+
// };
1716

1817
export const getSnippetByTitleAndCategory = (
1918
data: LanguageData,

0 commit comments

Comments
 (0)
Please sign in to comment.