mirror of
https://github.com/DerTyp7/explainegy-nextjs.git
synced 2025-10-29 21:02:13 +01:00
add category
This commit is contained in:
17
app/Nav.tsx
17
app/Nav.tsx
@@ -39,7 +39,7 @@ function toggleTheme() {
|
|||||||
}, 150);
|
}, 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Nav() {
|
export default function Nav({ categories }) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (localStorage.getItem("theme") == "dark") {
|
if (localStorage.getItem("theme") == "dark") {
|
||||||
switchTheme("dark");
|
switchTheme("dark");
|
||||||
@@ -57,16 +57,23 @@ export default function Nav() {
|
|||||||
alt="Nav bar logo"
|
alt="Nav bar logo"
|
||||||
/>
|
/>
|
||||||
<div className={styles.links}>
|
<div className={styles.links}>
|
||||||
<Link href={"/articles"} className={styles.dropDown}>
|
<div className={styles.dropDown}>
|
||||||
Categories
|
Categories
|
||||||
<div className={styles.dropDownContainer}>
|
<div className={styles.dropDownContainer}>
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
{" "}
|
|
||||||
<Link href={"/articles"}>All</Link>
|
<Link href={"/articles"}>All</Link>
|
||||||
<Link href={"/articles/tutorials"}>Tutorials</Link>
|
{categories?.map((cat, i) => {
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<Link href={`/articles/${cat.name.toLowerCase()}`}>
|
||||||
|
{cat?.name}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.containerCenter}>
|
<div className={styles.containerCenter}>
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import styles from "../../styles/DynamicCategoryGrid.module.scss";
|
|
||||||
import Link from "next/link";
|
|
||||||
export default function DynamicCategoryGrid({ categories }) {
|
|
||||||
return (
|
|
||||||
<div className={styles.grid}>
|
|
||||||
{categories.map((cat, i) => {
|
|
||||||
{
|
|
||||||
return (
|
|
||||||
<div key={i} className={styles.linkContainer}>
|
|
||||||
<Link href="#" style={{ backgroundColor: cat.color }}>
|
|
||||||
<div className={styles.svgContainer}>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512">
|
|
||||||
<path d={cat.svg} />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
{cat.name}
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,7 @@ export default async function Head({
|
|||||||
const article: Article = await GetArticle(articleName);
|
const article: Article = await GetArticle(articleName);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<title>{article.title}</title>
|
<title>{article?.title}</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export async function GetContentTableEntries(
|
|||||||
article: Article
|
article: Article
|
||||||
): Promise<ContentTableEntry[]> {
|
): Promise<ContentTableEntry[]> {
|
||||||
const entries = await prisma.contentTableEntry.findMany({
|
const entries = await prisma.contentTableEntry.findMany({
|
||||||
where: { article: article },
|
where: { articleId: article?.id ?? 1 },
|
||||||
orderBy: { orderIndex: "asc" },
|
orderBy: { orderIndex: "asc" },
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ export async function GetContentTableEntries(
|
|||||||
|
|
||||||
export async function GetArticle(articleName: string) {
|
export async function GetArticle(articleName: string) {
|
||||||
const article = await prisma.article.findUnique({
|
const article = await prisma.article.findUnique({
|
||||||
where: { name: articleName.toLowerCase() },
|
where: { name: articleName.toLowerCase() ?? "" },
|
||||||
});
|
});
|
||||||
|
|
||||||
return article;
|
return article;
|
||||||
@@ -39,7 +39,7 @@ export default async function Tutorial({
|
|||||||
}) {
|
}) {
|
||||||
const articleName: string = params.articleName;
|
const articleName: string = params.articleName;
|
||||||
const article: Article = await GetArticle(articleName);
|
const article: Article = await GetArticle(articleName);
|
||||||
const markdown: string = article.markdown;
|
const markdown: string = article?.markdown ?? "";
|
||||||
const contentTableEntries: ContentTableEntry[] = await GetContentTableEntries(
|
const contentTableEntries: ContentTableEntry[] = await GetContentTableEntries(
|
||||||
article
|
article
|
||||||
);
|
);
|
||||||
@@ -49,7 +49,7 @@ export default async function Tutorial({
|
|||||||
<ContentTable contentTableEntries={contentTableEntries} />
|
<ContentTable contentTableEntries={contentTableEntries} />
|
||||||
<div className={styles.tutorialContent}>
|
<div className={styles.tutorialContent}>
|
||||||
<div className={styles.head}>
|
<div className={styles.head}>
|
||||||
<h1>{article.title}</h1>
|
<h1>{article?.title}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="markdown"
|
className="markdown"
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ export async function GetCategories(): Promise<Category[]> {
|
|||||||
return await prisma.category.findMany();
|
return await prisma.category.findMany();
|
||||||
}
|
}
|
||||||
|
|
||||||
const DynamicCategoryGrid = dynamic(() => import("./DynamicCategoryGrid"), {
|
|
||||||
loading: () => <p>Loading...</p>,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default async function CategoryList() {
|
export default async function CategoryList() {
|
||||||
const categories = await GetCategories();
|
const categories = await GetCategories();
|
||||||
|
|
||||||
@@ -20,7 +16,28 @@ export default async function CategoryList() {
|
|||||||
<div className={styles.categoryList}>
|
<div className={styles.categoryList}>
|
||||||
<h1>Overview</h1>
|
<h1>Overview</h1>
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
<DynamicCategoryGrid categories={categories} />
|
<div className={styles.grid}>
|
||||||
|
{categories.map((cat, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i} className={styles.linkContainer}>
|
||||||
|
<Link
|
||||||
|
href={`/articles/${cat.name.toLowerCase()}`}
|
||||||
|
style={{ backgroundColor: cat.color }}
|
||||||
|
>
|
||||||
|
<div className={styles.svgContainer}>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 640 512"
|
||||||
|
>
|
||||||
|
<path d={cat.svg} />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
{cat.name}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,8 +3,14 @@ import "../styles/colorVariables.scss";
|
|||||||
import "../styles/variables.scss";
|
import "../styles/variables.scss";
|
||||||
import Nav from "./Nav";
|
import Nav from "./Nav";
|
||||||
import Footer from "./Footer";
|
import Footer from "./Footer";
|
||||||
|
import { Category } from "@prisma/client";
|
||||||
|
import prisma from "../lib/prisma";
|
||||||
|
|
||||||
export default function RootLayout({
|
export async function GetCategories(): Promise<Category[]> {
|
||||||
|
return await prisma.category.findMany();
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function RootLayout({
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
@@ -15,7 +21,7 @@ export default function RootLayout({
|
|||||||
|
|
||||||
<body className="body">
|
<body className="body">
|
||||||
<header>
|
<header>
|
||||||
<Nav />
|
<Nav categories={await GetCategories()} />
|
||||||
</header>
|
</header>
|
||||||
<main>{children}</main>
|
<main>{children}</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|||||||
@@ -10,5 +10,100 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
gap: 10px 30px;
|
||||||
|
|
||||||
|
@media (max-width: $categoryList-breakpoint-1) {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: $categoryList-breakpoint-2) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
padding: 0px 20px 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.linkContainer {
|
||||||
|
aspect-ratio: 14/9;
|
||||||
|
width: 250px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
@media (max-width: $categoryList-breakpoint-2) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-align: center;
|
||||||
|
aspect-ratio: 14/9;
|
||||||
|
width: 230px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
row-gap: 20px;
|
||||||
|
background-color: #384d54;
|
||||||
|
color: white;
|
||||||
|
font-size: 0.8em;
|
||||||
|
transition: all 100ms linear;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0px 0px 15px 5px rgba(0, 0, 0, 0.481);
|
||||||
|
color: white !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
width: 250px;
|
||||||
|
row-gap: 30px;
|
||||||
|
.svgContainer {
|
||||||
|
svg {
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: $categoryList-breakpoint-2) {
|
||||||
|
font-size: 1.2em;
|
||||||
|
width: 95%;
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0px 0px 15px 5px rgba(0, 0, 0, 0);
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.svgContainer {
|
||||||
|
svg {
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.svgContainer {
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
@media (max-width: $categoryList-breakpoint-2) {
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
}
|
||||||
|
svg {
|
||||||
|
transition: all 100ms linear;
|
||||||
|
fill: rgb(255, 255, 255);
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
|
||||||
|
@media (max-width: $categoryList-breakpoint-2) {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
@import "variables.scss";
|
|
||||||
.grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
gap: 10px 30px;
|
|
||||||
|
|
||||||
@media (max-width: $categoryList-breakpoint-1) {
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
gap: 10px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: $categoryList-breakpoint-2) {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
padding: 0px 20px 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.linkContainer {
|
|
||||||
aspect-ratio: 14/9;
|
|
||||||
width: 250px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
@media (max-width: $categoryList-breakpoint-2) {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
text-align: center;
|
|
||||||
aspect-ratio: 14/9;
|
|
||||||
width: 230px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
row-gap: 20px;
|
|
||||||
background-color: #384d54;
|
|
||||||
color: white;
|
|
||||||
font-size: 0.8em;
|
|
||||||
transition: all 100ms linear;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
box-shadow: 0px 0px 15px 5px rgba(0, 0, 0, 0.481);
|
|
||||||
color: white !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
width: 250px;
|
|
||||||
row-gap: 30px;
|
|
||||||
.svgContainer {
|
|
||||||
svg {
|
|
||||||
width: 70px;
|
|
||||||
height: 70px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: $categoryList-breakpoint-2) {
|
|
||||||
font-size: 1.2em;
|
|
||||||
width: 95%;
|
|
||||||
&:hover {
|
|
||||||
box-shadow: 0px 0px 15px 5px rgba(0, 0, 0, 0);
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.svgContainer {
|
|
||||||
svg {
|
|
||||||
width: 90px;
|
|
||||||
height: 90px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.svgContainer {
|
|
||||||
width: 70px;
|
|
||||||
height: 70px;
|
|
||||||
@media (max-width: $categoryList-breakpoint-2) {
|
|
||||||
width: 90px;
|
|
||||||
height: 90px;
|
|
||||||
}
|
|
||||||
svg {
|
|
||||||
transition: all 100ms linear;
|
|
||||||
fill: rgb(255, 255, 255);
|
|
||||||
width: 60px;
|
|
||||||
height: 60px;
|
|
||||||
|
|
||||||
@media (max-width: $categoryList-breakpoint-2) {
|
|
||||||
width: 80px;
|
|
||||||
height: 80px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user