This commit is contained in:
Janis
2023-02-07 15:42:40 +01:00
parent d2ff34d3b6
commit 29f359610f
16 changed files with 421 additions and 264 deletions

View File

@@ -5,7 +5,6 @@ import styles from "@/styles/modules/AdminNav.module.scss";
function AdminNav() {
return (
<div className={styles.adminNav}>
<Link href={"/admin"}>Admin</Link>
<Link href={"/admin/editor/article/0"}>New article</Link>
<Link href={"/admin/editor/category/0"}>New category</Link>
</div>

View File

@@ -0,0 +1,31 @@
import React from "react";
import { apiUrl } from "@/global";
import urlJoin from "url-join";
import { useRouter } from "next/navigation";
export default function ArticleControl({ articleId }: { articleId: string }) {
const router = useRouter();
async function deleteArticle() {
await fetch(urlJoin(apiUrl, `articles/${articleId}`), { method: "DELETE" })
.then((response) => response.json())
.then((result) => {
console.log(result);
});
router.push("/articles");
}
function editArticle() {
router.push("/admin/editor/article/" + articleId);
}
return (
<div>
<button className="danger" onClick={deleteArticle}>
Delete
</button>
<button className="warning" onClick={editArticle}>
Edit
</button>
</div>
);
}

View File

@@ -0,0 +1,31 @@
import React from "react";
import { apiUrl } from "@/global";
import urlJoin from "url-join";
import { useRouter } from "next/navigation";
export default function CategoryControl({ categoryId }: { categoryId: string }) {
const router = useRouter();
async function deleteCategory() {
await fetch(urlJoin(apiUrl, `categories/${categoryId}`), { method: "DELETE" })
.then((response) => response.json())
.then((result) => {
console.log(result);
});
router.push("/articles");
}
function editCategory() {
router.push("/admin/editor/category/" + categoryId);
}
return (
<div>
<button className="danger" onClick={deleteCategory}>
Delete
</button>
<button className="warning" onClick={editCategory}>
Edit
</button>
</div>
);
}

View File

@@ -1,31 +1,25 @@
import React from "react";
import styles from "@/styles/modules/ArticleContentTable.module.scss";
import { IContentTableEntry } from "../types/contentTable";
import { CLIENT_RENEG_LIMIT } from "tls";
export default function ContentTable({
contentTableData,
}: {
contentTableData: any;
}) {
return (
<div className={styles.articleContentTable}>
<div className={styles.stickyContainer}>
<div className={styles.list}>
<h2>Contents</h2>
{contentTableData?.map((e: IContentTableEntry, i: number) => {
return (
<a key={i} href={"#" + e.anchor}>
{e.title}
</a>
);
})}
</div>
{contentTableData?.length < 15 ? (
<div className={styles.adContainer}>Future advertisement</div>
) : (
""
)}
</div>
</div>
);
export default function ContentTable({ contentTableData }: { contentTableData: IContentTableEntry[] }) {
console.log(contentTableData);
return (
<div className={styles.articleContentTable}>
<div className={styles.stickyContainer}>
<div className={styles.list}>
<h2>Contents</h2>
{contentTableData.map((e: IContentTableEntry, i: number) => {
return (
<a key={i} href={"#" + e.anchor}>
{e.title}
</a>
);
})}
</div>
{contentTableData?.length < 15 ? <div className={styles.adContainer}>Future advertisement</div> : ""}
</div>
</div>
);
}

View File

@@ -3,147 +3,168 @@ import Image from "next/image";
import Link from "next/link";
import { useEffect, useState } from "react";
import { Category } from "@prisma/client";
import prisma, { CategoryWithIncludes } from "@/lib/prisma";
import { CLIENT_RENEG_LIMIT } from "tls";
import { apiUrl } from "@/global";
import urlJoin from "url-join";
function switchTheme(theme: string) {
const bodyElement = document.getElementsByTagName("body")[0];
const bodyElement = document.getElementsByTagName("body")[0];
if (theme == "dark") {
bodyElement.classList.remove("theme-light");
} else {
bodyElement.classList.add("theme-light");
}
if (theme == "dark") {
bodyElement.classList.remove("theme-light");
} else {
bodyElement.classList.add("theme-light");
}
}
function toggleTheme() {
const svgElement = document.getElementById("themeSwitchSvg");
const svgElement = document.getElementById("themeSwitchSvg");
if (svgElement) {
if (localStorage.getItem("theme") == "light") {
svgElement.style.animationDirection = "normal";
svgElement.style.animationName = styles.spinThemeSwitch;
} else {
svgElement.style.animationDirection = "reverse";
svgElement.style.animationName = styles.spinThemeSwitch;
}
if (svgElement) {
if (localStorage.getItem("theme") == "light") {
svgElement.style.animationDirection = "normal";
svgElement.style.animationName = styles.spinThemeSwitch;
} else {
svgElement.style.animationDirection = "reverse";
svgElement.style.animationName = styles.spinThemeSwitch;
}
setTimeout(() => {
if (localStorage.getItem("theme") == "light") {
localStorage.setItem("theme", "dark");
switchTheme("dark");
} else {
localStorage.setItem("theme", "light");
switchTheme("light");
}
svgElement.style.animationName = "";
}, 150);
}
setTimeout(() => {
if (localStorage.getItem("theme") == "light") {
localStorage.setItem("theme", "dark");
switchTheme("dark");
} else {
localStorage.setItem("theme", "light");
switchTheme("light");
}
svgElement.style.animationName = "";
}, 150);
}
}
export default function Nav({ categories }: { categories: Category[] }) {
const [searchResults, setSearchResults] = useState<
{ name: string; title: string }[]
>([]);
export default function Nav() {
const [searchResults, setSearchResults] = useState<{ name: string; title: string }[]>([]);
const [categories, setCategories] = useState<Category[]>([]);
async function handleSearchInput(event: React.ChangeEvent<HTMLInputElement>) {
const query = event.target.value;
let result = await fetch(`/api/search?q=${query}`);
let json = await result.json();
async function handleSearchInput(event: React.ChangeEvent<HTMLInputElement>) {
const query = event.target.value;
let result = await fetch(`/api/search?q=${query}`);
let json = await result.json();
if (json.length == 0 && query.length > 0) {
setSearchResults([{ name: "", title: "No article found..." }]);
} else {
setSearchResults(json);
}
}
if (json.length == 0 && query.length > 0) {
setSearchResults([{ name: "", title: "No article found..." }]);
} else {
setSearchResults(json);
}
}
useEffect(() => {
if (localStorage.getItem("theme") == "dark") {
switchTheme("dark");
} else {
switchTheme("light");
}
}, []);
useEffect(() => {
if (localStorage.getItem("theme") == "dark") {
switchTheme("dark");
} else {
switchTheme("light");
}
}, []);
useEffect(() => {
console.log(searchResults);
}, [searchResults]);
useEffect(() => {
console.log(searchResults);
}, [searchResults]);
return (
<nav className={styles.nav}>
<div className={styles.containerLeft}>
<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>
<div className={styles.dropDownContainer}>
<div className={styles.content}>
<Link href={"/articles"}>All</Link>
useEffect(() => {
async function getCategories() {
await fetch(urlJoin(apiUrl, "categories"))
.then((response) => response.json())
.then((result: Category[]) => {
setCategories(result);
});
}
{categories?.map((cat, i) => {
{
return (
<Link
key={i}
href={`/articles/${cat.name.toLowerCase()}`}
>
{cat.title}
</Link>
);
}
})}
</div>
</div>
</div>
</div>
</div>
<div className={styles.containerCenter}>
<div className={styles.searchBar}>
<div className={styles.icon}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352c79.5 0 144-64.5 144-144s-64.5-144-144-144S64 128.5 64 208s64.5 144 144 144z" />
</svg>
</div>
<input onInput={handleSearchInput} type="text" name="" id="" />
</div>
<div className={styles.searchResults}>
<div className={styles.content}>
{searchResults.map((s) => {
{
return (
<Link href={`/articles/${s.name.toLowerCase()}`}>
{s.title}
</Link>
);
}
})}
</div>
</div>
</div>
<div className={styles.containerRight}>
<div
className={styles.themeSwitch}
onClick={() => {
toggleTheme();
}}
>
<svg
id="themeSwitchSvg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
>
<path d="M448 256c0-106-86-192-192-192V448c106 0 192-86 192-192zm64 0c0 141.4-114.6 256-256 256S0 397.4 0 256S114.6 0 256 0S512 114.6 512 256z" />
</svg>
</div>
</div>
</nav>
);
getCategories();
}, []);
return (
<nav className={styles.nav}>
<div className={styles.containerLeft}>
<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>
<div className={styles.dropDownContainer}>
<div className={styles.content}>
<Link href={"/articles"}>All</Link>
{categories?.map((cat, i) => {
{
return (
<Link key={i} href={`/articles/${cat.name.toLowerCase()}`}>
{cat.title}
</Link>
);
}
})}
</div>
</div>
</div>
</div>
</div>
<div className={styles.containerCenter}>
<div className={styles.searchBar}>
<div className={styles.icon}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352c79.5 0 144-64.5 144-144s-64.5-144-144-144S64 128.5 64 208s64.5 144 144 144z" />
</svg>
</div>
<input onInput={handleSearchInput} type="text" name="" id="" />
</div>
<div className={styles.searchResults}>
<div className={styles.content}>
{searchResults.map((s) => {
{
return <Link href={`/articles/${s.name.toLowerCase()}`}>{s.title}</Link>;
}
})}
</div>
</div>
</div>
<div className={styles.containerRight}>
<div
className={styles.themeSwitch}
onClick={() => {
toggleTheme();
}}
>
<svg id="themeSwitchSvg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M448 256c0-106-86-192-192-192V448c106 0 192-86 192-192zm64 0c0 141.4-114.6 256-256 256S0 397.4 0 256S114.6 0 256 0S512 114.6 512 256z" />
</svg>
</div>
</div>
</nav>
);
}
export async function getServerSideProps() {
let categories: Category[] = [];
await prisma.category.findMany({ include: { articles: true, svg: true } }).then(
(result: Category[]) => {
if (result) {
categories = JSON.parse(JSON.stringify(result));
}
},
(reason: any) => {
console.log(reason);
}
);
return {
props: { categories: categories }, // will be passed to the page component as props
};
}