All
{categories?.map((cat, i) => {
{
return (
-
- {cat?.name}
+
+ {cat.title}
);
}
diff --git a/app/articles/[categoryName]/[articleName]/page.tsx b/app/articles/[categoryName]/[articleName]/page.tsx
index b1cf088..fa8d6e2 100644
--- a/app/articles/[categoryName]/[articleName]/page.tsx
+++ b/app/articles/[categoryName]/[articleName]/page.tsx
@@ -32,12 +32,14 @@ function ParseMarkdown(markdown: string): string {
}
//* MAIN
-export default async function Tutorial({
+export default async function ArticlePage({
params,
}: {
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 markdown: string = article?.markdown ?? "";
const contentTableEntries: ContentTableEntry[] = await GetContentTableEntries(
diff --git a/app/articles/[categoryName]/page.tsx b/app/articles/[categoryName]/page.tsx
index 3d17852..71df7e8 100644
--- a/app/articles/[categoryName]/page.tsx
+++ b/app/articles/[categoryName]/page.tsx
@@ -1,3 +1,88 @@
-export default function Category() {
- return
List all articles in a category
;
+import styles from "../../../styles/Category.module.scss";
+import Link from "next/link";
+import prisma from "../../../lib/prisma";
+import { Article, Category } from "@prisma/client";
+
+export async function GetAllArticles(category: Category): Promise
{
+ return await prisma.article.findMany({ where: { category: category } });
+}
+
+export async function GetPopularArticles(
+ category: Category
+): Promise {
+ return await prisma.article.findMany({
+ where: { category: category },
+ take: 6,
+ });
+}
+
+export async function GetRecentArticles(
+ category: Category
+): Promise {
+ return await prisma.article.findMany({
+ where: { category: category },
+ take: 6,
+ orderBy: { dateCreated: "desc" },
+ });
+}
+
+export async function GetCategory(categoryName: string): Promise {
+ 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 (
+
+
{category?.title}
+
+
+
Most popular articles
+ {popularArticles?.map((a, i) => {
+ {
+ return (
+
+ {a.name}
+
+ );
+ }
+ })}
+
+
+ {/*
+
Most recent articles
+ {recentArticles?.map((a, i) => {
+ {
+ return (
+
+ {a.name}
+
+ );
+ }
+ })}
+ */}
+
+
+
All articles
+ {allArticles?.map((a, i) => {
+ {
+ return (
+
+ {a.name}
+
+ );
+ }
+ })}
+
+
+
+ );
}
diff --git a/app/articles/page.tsx b/app/articles/page.tsx
index 99e380b..6ab00cd 100644
--- a/app/articles/page.tsx
+++ b/app/articles/page.tsx
@@ -1,42 +1,45 @@
import styles from "../../styles/CategoryList.module.scss";
import Link from "next/link";
import prisma from "../../lib/prisma";
-import { Category } from "@prisma/client";
+import { Category, Svg, Prisma } from "@prisma/client";
import { Suspense } from "react";
import dynamic from "next/dynamic";
-export async function GetCategories(): Promise {
- return await prisma.category.findMany();
+type CategoryWithSvg = Prisma.CategoryGetPayload<{ include: { svg: true } }>;
+
+export async function GetCategories(): Promise {
+ return await prisma.category.findMany({ include: { svg: true } });
}
export default async function CategoryList() {
const categories = await GetCategories();
-
return (
Overview
- {categories.map((cat, i) => {
- return (
-
-
-
-
- );
- })}
+ );
+ })
+ : "We did not find any categories"}
diff --git a/app/layout.tsx b/app/layout.tsx
index d31ccdc..e1f9d7a 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -5,9 +5,13 @@ import Nav from "./Nav";
import Footer from "./Footer";
import { Category } from "@prisma/client";
import prisma from "../lib/prisma";
+import { NavCategory } from "./Nav";
-export async function GetCategories(): Promise
{
- return await prisma.category.findMany();
+export async function GetNavCategories(): Promise {
+ const result: NavCategory[] = await prisma.category.findMany({
+ select: { name: true, title: true },
+ });
+ return result;
}
export default async function RootLayout({
@@ -21,7 +25,7 @@ export default async function RootLayout({
{children}
diff --git a/package.json b/package.json
index dcf06ff..939e001 100644
--- a/package.json
+++ b/package.json
@@ -3,8 +3,9 @@
"version": "0.2.0",
"private": true,
"scripts": {
+ "prisma": "prisma generate && prisma db push && prisma studio",
"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",
"lint": "next lint"
},
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 6814b83..7834824 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -35,8 +35,10 @@ model ContentTableEntry {
model Category {
id Int @id @default(autoincrement())
name String @unique
+ title String @unique
color String @unique
- svg String @default("")
+ svgId Int
+ svg Svg @relation(fields: [svgId], references: [id])
Article Article[]
dateCreated DateTime @default(now())
dateUpdated DateTime @default(now())
@@ -45,7 +47,16 @@ model Category {
model ArticleType {
id Int @id @default(autoincrement())
name String @unique
+ title String @unique
Article Article[]
dateCreated 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[]
+}
diff --git a/styles/Category.module.scss b/styles/Category.module.scss
new file mode 100644
index 0000000..f4bbd44
--- /dev/null
+++ b/styles/Category.module.scss
@@ -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;
+ }
+ }
+ }
+ }
+}
diff --git a/styles/CategoryList.module.scss b/styles/CategoryList.module.scss
index 94a8197..f4138b0 100644
--- a/styles/CategoryList.module.scss
+++ b/styles/CategoryList.module.scss
@@ -48,7 +48,7 @@
justify-content: center;
align-items: center;
row-gap: 20px;
- background-color: #384d54;
+ background-color: #383d54;
color: white;
font-size: 0.8em;
transition: all 100ms linear;
diff --git a/styles/variables.scss b/styles/variables.scss
index 807d20f..385e28d 100644
--- a/styles/variables.scss
+++ b/styles/variables.scss
@@ -26,3 +26,8 @@ $nav-breakpoint-4: 400px;
/* CategoryList */
$categoryList-breakpoint-1: 850px;
$categoryList-breakpoint-2: 600px;
+
+/* Category */
+
+$category-breakpoint-1: 800px;
+$category-breakpoint-2: 550px;