mirror of
https://github.com/DerTyp7/explainegy-nextjs.git
synced 2025-10-29 21:02:13 +01:00
ads
This commit is contained in:
14
app/Nav.tsx
14
app/Nav.tsx
@@ -4,9 +4,6 @@ import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Category } from "@prisma/client";
|
||||
import urlJoin from "url-join";
|
||||
import { apiUrl } from "./global";
|
||||
import { GetStaticProps } from "next";
|
||||
|
||||
function switchTheme(theme) {
|
||||
const bodyElement = document.getElementsByTagName("body")[0];
|
||||
@@ -71,7 +68,16 @@ export default function Nav({ categories }: { categories: Category[] }) {
|
||||
return (
|
||||
<nav className={styles.nav}>
|
||||
<div className={styles.containerLeft}>
|
||||
<Image src={"/images/logo.svg"} height={40} width={160} alt="Nav bar logo" />
|
||||
<Image
|
||||
src={"/images/logo.svg"}
|
||||
height={40}
|
||||
width={160}
|
||||
alt="Nav bar logo"
|
||||
onClick={() => {
|
||||
window.open("/", "_self");
|
||||
}}
|
||||
className={styles.logo}
|
||||
/>
|
||||
<div className={styles.links}>
|
||||
<div className={styles.dropDown}>
|
||||
<Link href="/articles">Categories</Link>
|
||||
|
||||
@@ -9,17 +9,9 @@ import urlJoin from "url-join";
|
||||
import { apiUrl } from "../../../global";
|
||||
import { Prisma } from "@prisma/client";
|
||||
|
||||
type ArticleWithContentTableEntries = Prisma.ArticleGetPayload<{ include: { contentTableEntries: true } }>;
|
||||
type ArticleWithCategory = Prisma.ArticleGetPayload<{ include: { category: true } }>;
|
||||
|
||||
// export async function GetContentTableEntries(article: Article): Promise<ContentTableEntry[]> {
|
||||
// const entries = await prisma.contentTableEntry.findMany({
|
||||
// where: { articleId: article?.id ?? 1 },
|
||||
// orderBy: { orderIndex: "asc" },
|
||||
// });
|
||||
|
||||
// return entries;
|
||||
// }
|
||||
type ArticleWithIncludes = Prisma.ArticleGetPayload<{
|
||||
include: { contentTableEntries: true; category: true; image: true };
|
||||
}>;
|
||||
|
||||
export async function GetArticle(articleName: string): Promise<any> {
|
||||
const result: Response = await fetch(urlJoin(apiUrl, `articles/${articleName ?? ""}`), {
|
||||
@@ -38,7 +30,10 @@ function ParseMarkdown(markdown: string): string {
|
||||
//* MAIN
|
||||
export default async function ArticlePage({ params }: { params: { articleName: string; categoryName: string } }) {
|
||||
const articleName: string = params.articleName.toLowerCase().replaceAll("%20", " ");
|
||||
const article: ArticleWithContentTableEntries = await GetArticle(articleName);
|
||||
const article: ArticleWithIncludes = await GetArticle(articleName);
|
||||
const dateUpdated: Date = new Date(article.dateUpdated);
|
||||
const dateCreated: Date = new Date(article.dateCreated);
|
||||
const dateOptions: Intl.DateTimeFormatOptions = { month: "long", day: "numeric", year: "numeric" };
|
||||
const markdown: string = article?.markdown ?? "";
|
||||
|
||||
return (
|
||||
@@ -46,22 +41,27 @@ export default async function ArticlePage({ params }: { params: { articleName: s
|
||||
<ContentTable contentTableEntries={article.contentTableEntries} />
|
||||
<div className={styles.tutorialContent}>
|
||||
<div className={styles.header}>
|
||||
<p className="text-muted">Published on January 13, 2022</p>
|
||||
<p className={`${styles.dates} text-muted`}>
|
||||
{`Published on ${dateCreated.toLocaleDateString("en-US", dateOptions)}`}
|
||||
<br />
|
||||
{dateUpdated > dateCreated ? `Updated on ${dateUpdated.toLocaleDateString("en-US", dateOptions)}` : ""}
|
||||
</p>
|
||||
|
||||
<h1>{article?.title}</h1>
|
||||
<div className={styles.tags}>
|
||||
<a href="#">Docker</a> <a href="#">Setup</a> <a href="#">Ubuntu</a>
|
||||
</div>
|
||||
<Image
|
||||
src={"/images/test.jpg"}
|
||||
src={article?.image?.url ?? ""}
|
||||
height={350}
|
||||
width={750}
|
||||
alt="Image"
|
||||
alt={article?.image?.alt ?? ""}
|
||||
quality={100}
|
||||
placeholder="blur"
|
||||
blurDataURL="/images/blur.png"
|
||||
loading="lazy"
|
||||
/>
|
||||
<p>{article?.introduction}</p>
|
||||
</div>
|
||||
<div
|
||||
className="markdown"
|
||||
@@ -77,7 +77,7 @@ export default async function ArticlePage({ params }: { params: { articleName: s
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const articles: ArticleWithCategory[] = await (
|
||||
const articles: ArticleWithIncludes[] = await (
|
||||
await fetch(urlJoin(apiUrl, `articles/`), {
|
||||
cache: "force-cache",
|
||||
next: { revalidate: 60 * 10 },
|
||||
|
||||
@@ -48,7 +48,7 @@ export default async function CategoryPage({ params }: { params: { categoryName:
|
||||
const allArticles: Article[] = await GetAllArticles(categoryName);
|
||||
const popularArticles: Article[] = await GetPopularArticles(categoryName);
|
||||
const recentArticles: Article[] = await GetRecentArticles(categoryName);
|
||||
console.log(popularArticles);
|
||||
|
||||
return (
|
||||
<div className={styles.category}>
|
||||
<h1>{category?.title}</h1>
|
||||
|
||||
@@ -3,7 +3,7 @@ import prisma from "../../../lib/prisma";
|
||||
import { Article, Prisma, ContentTableEntry } from '@prisma/client';
|
||||
import { ResponseError } from "../../../types/responseErrors";
|
||||
|
||||
type ArticleWithIncludes = Prisma.ArticleGetPayload<{ include: { contentTableEntries: true, category: true } }>
|
||||
type ArticleWithIncludes = Prisma.ArticleGetPayload<{ include: { contentTableEntries: true, category: true, image: true } }>
|
||||
|
||||
function sortContentTableEntries(entries: ContentTableEntry[]): ContentTableEntry[] {
|
||||
return entries.sort((a, b) => a.orderIndex - b.orderIndex);
|
||||
@@ -16,7 +16,7 @@ export default async function handler(req: Request, res: Response) {
|
||||
const articleName: string = req.query.articleName.toString();
|
||||
|
||||
await prisma.article
|
||||
.findUnique({ where: { name: articleName }, include: { category: true, contentTableEntries: true } })
|
||||
.findUnique({ where: { name: articleName }, include: { category: true, contentTableEntries: true, image: true } })
|
||||
.then((result: ArticleWithIncludes) => {
|
||||
if (result !== null) {
|
||||
result.contentTableEntries = sortContentTableEntries(result.contentTableEntries);
|
||||
|
||||
@@ -11,12 +11,13 @@ model Article {
|
||||
id Int @id @default(autoincrement())
|
||||
name String @unique
|
||||
title String @unique
|
||||
introduction String @default("")
|
||||
imageId Int?
|
||||
image Image? @relation(fields: [imageId], references: [id])
|
||||
markdown String
|
||||
contentTableEntries ContentTableEntry[]
|
||||
categoryId Int?
|
||||
category Category? @relation(fields: [categoryId], references: [id])
|
||||
typeId Int?
|
||||
type ArticleType? @relation(fields: [typeId], references: [id])
|
||||
dateCreated DateTime @default(now())
|
||||
dateUpdated DateTime @default(now())
|
||||
}
|
||||
@@ -44,20 +45,13 @@ model Category {
|
||||
dateUpdated DateTime @default(now())
|
||||
}
|
||||
|
||||
model ArticleType {
|
||||
id Int @id @default(autoincrement())
|
||||
name String @unique
|
||||
title String @unique
|
||||
Article Article[]
|
||||
dateCreated DateTime @default(now())
|
||||
dateUpdated DateTime @default(now())
|
||||
}
|
||||
|
||||
model Image {
|
||||
id Int @id @default(autoincrement())
|
||||
name String @unique
|
||||
alt String @default("")
|
||||
url String @default("")
|
||||
dateCreated DateTime @default(now())
|
||||
Article Article[]
|
||||
}
|
||||
|
||||
model Svg {
|
||||
|
||||
@@ -22,12 +22,35 @@
|
||||
padding: 10px 0px 10px 0px;
|
||||
gap: 10px 0px;
|
||||
|
||||
h1 {
|
||||
.dates {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
img {
|
||||
width: min(100%, 750px);
|
||||
height: auto;
|
||||
aspect-ratio: 15/7;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.tags {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 5px 10px;
|
||||
a {
|
||||
font-size: 0.8em;
|
||||
background-color: var(--color-background-article-tag);
|
||||
opacity: 0.9;
|
||||
color: var(--color-font-article-tag);
|
||||
padding: 5px 10px 5px 10px;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: var(--color-font-article-tag) !important;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
column-gap: 20px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
cursor: pointer;
|
||||
}
|
||||
.links {
|
||||
font-size: 0.8em;
|
||||
font-weight: bold;
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
--color-background-dropdown: var(--color-background-body);
|
||||
--color-accent: #2294ff;
|
||||
--color-font-link: var(--color-accent);
|
||||
|
||||
--color-font-article-tag: #fff;
|
||||
--color-background-article-tag: #007aec;
|
||||
--color-font-link-hover: #5caffc;
|
||||
|
||||
/* Colors: Markdown */
|
||||
|
||||
Reference in New Issue
Block a user