Now starting with real commit messages

This commit is contained in:
Janis
2022-12-27 21:31:09 +01:00
parent 90f158542a
commit 62701ca998
10 changed files with 210 additions and 38 deletions

View File

@@ -1,10 +1,13 @@
"use client"; "use client";
import { time } from "console";
import styles from "../styles/Nav.module.scss"; import styles from "../styles/Nav.module.scss";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import { useEffect } from "react"; import { useEffect } from "react";
import Category from "./articles/[categoryName]/page";
export type NavCategory = {
name: string;
title: string;
};
function switchTheme(theme) { function switchTheme(theme) {
const bodyElement = document.getElementsByTagName("body")[0]; const bodyElement = document.getElementsByTagName("body")[0];
@@ -39,7 +42,7 @@ function toggleTheme() {
}, 150); }, 150);
} }
export default function Nav({ categories }) { export default function Nav({ categories }: { categories: NavCategory[] }) {
useEffect(() => { useEffect(() => {
if (localStorage.getItem("theme") == "dark") { if (localStorage.getItem("theme") == "dark") {
switchTheme("dark"); switchTheme("dark");
@@ -58,15 +61,18 @@ export default function Nav({ categories }) {
/> />
<div className={styles.links}> <div className={styles.links}>
<div className={styles.dropDown}> <div className={styles.dropDown}>
Categories <Link href="/articles">Categories</Link>
<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>
{categories?.map((cat, i) => { {categories?.map((cat, i) => {
{ {
return ( return (
<Link href={`/articles/${cat.name.toLowerCase()}`}> <Link
{cat?.name} key={i}
href={`/articles/${cat.name.toLowerCase()}`}
>
{cat.title}
</Link> </Link>
); );
} }

View File

@@ -32,12 +32,14 @@ function ParseMarkdown(markdown: string): string {
} }
//* MAIN //* MAIN
export default async function Tutorial({ export default async function ArticlePage({
params, params,
}: { }: {
params: { articleName: string; categoryName: string }; params: { articleName: string; categoryName: string };
}) { }) {
const articleName: string = params.articleName; const articleName: string = params.articleName
.toLowerCase()
.replaceAll("%20", " ");
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(

View File

@@ -1,3 +1,88 @@
export default function Category() { import styles from "../../../styles/Category.module.scss";
return <h1>List all articles in a category</h1>; import Link from "next/link";
import prisma from "../../../lib/prisma";
import { Article, Category } from "@prisma/client";
export async function GetAllArticles(category: Category): Promise<Article[]> {
return await prisma.article.findMany({ where: { category: category } });
}
export async function GetPopularArticles(
category: Category
): Promise<Article[]> {
return await prisma.article.findMany({
where: { category: category },
take: 6,
});
}
export async function GetRecentArticles(
category: Category
): Promise<Article[]> {
return await prisma.article.findMany({
where: { category: category },
take: 6,
orderBy: { dateCreated: "desc" },
});
}
export async function GetCategory(categoryName: string): Promise<Category> {
return await prisma.category.findUnique({ where: { name: categoryName } });
}
export default async function CategoryPage({
params,
}: {
params: { categoryName: string };
}) {
const categoryName = params.categoryName.toLowerCase().replaceAll("%20", " ");
const category: Category = await GetCategory(categoryName);
const allArticles: Article[] = await GetAllArticles(category);
const popularArticles: Article[] = await GetPopularArticles(category);
const recentArticles: Article[] = await GetRecentArticles(category);
return (
<div className={styles.category}>
<h1>{category?.title}</h1>
<div className={styles.content}>
<div className={`${styles.showcase} ${styles.smallShowcase}`}>
<h2>Most popular articles</h2>
{popularArticles?.map((a, i) => {
{
return (
<Link key={i} href={`/articles/${category.name}/${a.name}`}>
{a.name}
</Link>
);
}
})}
</div>
{/* <div className={`${styles.showcase} ${styles.smallShowcase}`}>
<h2>Most recent articles</h2>
{recentArticles?.map((a, i) => {
{
return (
<Link key={i} href={`/articles/${category.name}/${a.name}`}>
{a.name}
</Link>
);
}
})}
</div> */}
<div className={styles.showcase}>
<h2>All articles</h2>
{allArticles?.map((a, i) => {
{
return (
<Link key={i} href={`/articles/${category.name}/${a.name}`}>
{a.name}
</Link>
);
}
})}
</div>
</div>
</div>
);
} }

View File

@@ -1,42 +1,45 @@
import styles from "../../styles/CategoryList.module.scss"; import styles from "../../styles/CategoryList.module.scss";
import Link from "next/link"; import Link from "next/link";
import prisma from "../../lib/prisma"; import prisma from "../../lib/prisma";
import { Category } from "@prisma/client"; import { Category, Svg, Prisma } from "@prisma/client";
import { Suspense } from "react"; import { Suspense } from "react";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
export async function GetCategories(): Promise<Category[]> { type CategoryWithSvg = Prisma.CategoryGetPayload<{ include: { svg: true } }>;
return await prisma.category.findMany();
export async function GetCategories(): Promise<CategoryWithSvg[]> {
return await prisma.category.findMany({ include: { svg: true } });
} }
export default async function CategoryList() { export default async function CategoryList() {
const categories = await GetCategories(); const categories = await GetCategories();
return ( return (
<div className={styles.categoryList}> <div className={styles.categoryList}>
<h1>Overview</h1> <h1>Overview</h1>
<div className={styles.content}> <div className={styles.content}>
<div className={styles.grid}> <div className={styles.grid}>
{categories.map((cat, i) => { {categories?.length > 0
return ( ? categories.map((cat, i) => {
<div key={i} className={styles.linkContainer}> return (
<Link <div key={i} className={styles.linkContainer}>
href={`/articles/${cat.name.toLowerCase()}`} <Link
style={{ backgroundColor: cat.color }} 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} /> <div className={styles.svgContainer}>
</svg> <svg
xmlns="http://www.w3.org/2000/svg"
viewBox={cat?.svg?.viewbox}
>
<path d={cat?.svg?.path} />
</svg>
</div>
{cat.title}
</Link>
</div> </div>
{cat.name} );
</Link> })
</div> : "We did not find any categories"}
);
})}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -5,9 +5,13 @@ import Nav from "./Nav";
import Footer from "./Footer"; import Footer from "./Footer";
import { Category } from "@prisma/client"; import { Category } from "@prisma/client";
import prisma from "../lib/prisma"; import prisma from "../lib/prisma";
import { NavCategory } from "./Nav";
export async function GetCategories(): Promise<Category[]> { export async function GetNavCategories(): Promise<NavCategory[]> {
return await prisma.category.findMany(); const result: NavCategory[] = await prisma.category.findMany({
select: { name: true, title: true },
});
return result;
} }
export default async function RootLayout({ export default async function RootLayout({
@@ -21,7 +25,7 @@ export default async function RootLayout({
<body className="body"> <body className="body">
<header> <header>
<Nav categories={await GetCategories()} /> <Nav categories={await GetNavCategories()} />
</header> </header>
<main>{children}</main> <main>{children}</main>
<Footer /> <Footer />

View File

@@ -3,8 +3,9 @@
"version": "0.2.0", "version": "0.2.0",
"private": true, "private": true,
"scripts": { "scripts": {
"prisma": "prisma generate && prisma db push && prisma studio",
"dev": "next dev", "dev": "next dev",
"build": "prisma generate && prisma migrate deploy && next build", "build": "prisma generate && prisma migrate deploy && prisma db push && next build",
"start": "next start", "start": "next start",
"lint": "next lint" "lint": "next lint"
}, },

View File

@@ -35,8 +35,10 @@ model ContentTableEntry {
model Category { model Category {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
name String @unique name String @unique
title String @unique
color String @unique color String @unique
svg String @default("") svgId Int
svg Svg @relation(fields: [svgId], references: [id])
Article Article[] Article Article[]
dateCreated DateTime @default(now()) dateCreated DateTime @default(now())
dateUpdated DateTime @default(now()) dateUpdated DateTime @default(now())
@@ -45,7 +47,16 @@ model Category {
model ArticleType { model ArticleType {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
name String @unique name String @unique
title String @unique
Article Article[] Article Article[]
dateCreated DateTime @default(now()) dateCreated DateTime @default(now())
dateUpdated DateTime @default(now()) dateUpdated DateTime @default(now())
} }
model Svg {
id Int @id @default(autoincrement())
name String @unique
path String @default("")
viewbox String @default("0 0 512 512")
Category Category[]
}

View File

@@ -0,0 +1,55 @@
@import "variables.scss";
.category {
h1 {
text-align: center;
font-size: 1.5em;
}
.content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-top: 50px;
row-gap: 50px;
padding: 0px 20px 0 20px;
.showcase {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 10px 10px;
@media (max-width: $category-breakpoint-1) {
grid-template-columns: 1fr 1fr;
}
@media (max-width: $category-breakpoint-2) {
grid-template-columns: 1fr;
}
h2 {
font-size: 1em;
grid-column: 1 / -1;
}
a {
background-color: rgba(126, 126, 126, 0.1);
box-shadow: 0px 0px 15px 5px rgba(0, 0, 0, 0.1);
padding: 20px;
transition: all 50ms linear;
text-overflow: ellipsis;
max-width: 300px;
&:hover {
background-color: rgba(126, 126, 126, 0.2);
box-shadow: 0px 0px 15px 5px rgba(0, 0, 0, 0.2);
}
}
}
.smallShowcase {
@media (max-width: $category-breakpoint-2) {
& > a:nth-child(n + 5) {
display: none;
}
}
}
}
}

View File

@@ -48,7 +48,7 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
row-gap: 20px; row-gap: 20px;
background-color: #384d54; background-color: #383d54;
color: white; color: white;
font-size: 0.8em; font-size: 0.8em;
transition: all 100ms linear; transition: all 100ms linear;

View File

@@ -26,3 +26,8 @@ $nav-breakpoint-4: 400px;
/* CategoryList */ /* CategoryList */
$categoryList-breakpoint-1: 850px; $categoryList-breakpoint-1: 850px;
$categoryList-breakpoint-2: 600px; $categoryList-breakpoint-2: 600px;
/* Category */
$category-breakpoint-1: 800px;
$category-breakpoint-2: 550px;