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:
19
app/Nav.tsx
19
app/Nav.tsx
@@ -39,7 +39,7 @@ function toggleTheme() {
|
||||
}, 150);
|
||||
}
|
||||
|
||||
export default function Nav() {
|
||||
export default function Nav({ categories }) {
|
||||
useEffect(() => {
|
||||
if (localStorage.getItem("theme") == "dark") {
|
||||
switchTheme("dark");
|
||||
@@ -57,16 +57,23 @@ export default function Nav() {
|
||||
alt="Nav bar logo"
|
||||
/>
|
||||
<div className={styles.links}>
|
||||
<Link href={"/articles"} className={styles.dropDown}>
|
||||
<div className={styles.dropDown}>
|
||||
Categories
|
||||
<div className={styles.dropDownContainer}>
|
||||
<div className={styles.content}>
|
||||
{" "}
|
||||
<Link href={"/articles"}>All</Link>
|
||||
<Link href={"/articles/tutorials"}>Tutorials</Link>
|
||||
</div>
|
||||
</div>
|
||||
{categories?.map((cat, i) => {
|
||||
{
|
||||
return (
|
||||
<Link href={`/articles/${cat.name.toLowerCase()}`}>
|
||||
{cat?.name}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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);
|
||||
return (
|
||||
<>
|
||||
<title>{article.title}</title>
|
||||
<title>{article?.title}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -10,7 +10,7 @@ export async function GetContentTableEntries(
|
||||
article: Article
|
||||
): Promise<ContentTableEntry[]> {
|
||||
const entries = await prisma.contentTableEntry.findMany({
|
||||
where: { article: article },
|
||||
where: { articleId: article?.id ?? 1 },
|
||||
orderBy: { orderIndex: "asc" },
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@ export async function GetContentTableEntries(
|
||||
|
||||
export async function GetArticle(articleName: string) {
|
||||
const article = await prisma.article.findUnique({
|
||||
where: { name: articleName.toLowerCase() },
|
||||
where: { name: articleName.toLowerCase() ?? "" },
|
||||
});
|
||||
|
||||
return article;
|
||||
@@ -39,7 +39,7 @@ export default async function Tutorial({
|
||||
}) {
|
||||
const articleName: string = params.articleName;
|
||||
const article: Article = await GetArticle(articleName);
|
||||
const markdown: string = article.markdown;
|
||||
const markdown: string = article?.markdown ?? "";
|
||||
const contentTableEntries: ContentTableEntry[] = await GetContentTableEntries(
|
||||
article
|
||||
);
|
||||
@@ -49,7 +49,7 @@ export default async function Tutorial({
|
||||
<ContentTable contentTableEntries={contentTableEntries} />
|
||||
<div className={styles.tutorialContent}>
|
||||
<div className={styles.head}>
|
||||
<h1>{article.title}</h1>
|
||||
<h1>{article?.title}</h1>
|
||||
</div>
|
||||
<div
|
||||
className="markdown"
|
||||
|
||||
@@ -9,10 +9,6 @@ export async function GetCategories(): Promise<Category[]> {
|
||||
return await prisma.category.findMany();
|
||||
}
|
||||
|
||||
const DynamicCategoryGrid = dynamic(() => import("./DynamicCategoryGrid"), {
|
||||
loading: () => <p>Loading...</p>,
|
||||
});
|
||||
|
||||
export default async function CategoryList() {
|
||||
const categories = await GetCategories();
|
||||
|
||||
@@ -20,7 +16,28 @@ export default async function CategoryList() {
|
||||
<div className={styles.categoryList}>
|
||||
<h1>Overview</h1>
|
||||
<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>
|
||||
);
|
||||
|
||||
@@ -3,8 +3,14 @@ import "../styles/colorVariables.scss";
|
||||
import "../styles/variables.scss";
|
||||
import Nav from "./Nav";
|
||||
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: React.ReactNode;
|
||||
@@ -15,7 +21,7 @@ export default function RootLayout({
|
||||
|
||||
<body className="body">
|
||||
<header>
|
||||
<Nav />
|
||||
<Nav categories={await GetCategories()} />
|
||||
</header>
|
||||
<main>{children}</main>
|
||||
<Footer />
|
||||
|
||||
@@ -10,5 +10,100 @@
|
||||
display: flex;
|
||||
justify-content: 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