mirror of
https://github.com/DerTyp7/explainegy-nextjs.git
synced 2025-10-29 12:52:13 +01:00
contens
This commit is contained in:
@@ -7,7 +7,7 @@ export default function RootLayout({
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<html>
|
<html style={{ scrollBehavior: "smooth" }}>
|
||||||
<head></head>
|
<head></head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
|
|||||||
@@ -1,5 +1,26 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { TutorialMeta } from "./page";
|
||||||
|
import styles from "../../../styles/TutorialContentTable.module.scss";
|
||||||
|
|
||||||
export default function ContentTable() {
|
export default function ContentTable({
|
||||||
return <div>ContentTable</div>;
|
tutorialMeta,
|
||||||
|
}: {
|
||||||
|
tutorialMeta: TutorialMeta;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className={styles.tutorialContentTable}>
|
||||||
|
<div className={styles.stickyContainer}>
|
||||||
|
<div className={styles.list}>
|
||||||
|
<h2>Contents</h2>
|
||||||
|
{tutorialMeta?.contentTable?.map((e, i) => {
|
||||||
|
return (
|
||||||
|
<a key={i} href={"#" + e.anchor}>
|
||||||
|
{e.title}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,3 @@
|
|||||||
import ContentTable from "./ContentTable";
|
|
||||||
import Sidebar from "./Sidebar";
|
|
||||||
import styles from "../../../styles/Tutorial.module.scss";
|
|
||||||
|
|
||||||
export default function Layout({ children }) {
|
export default function Layout({ children }) {
|
||||||
return (
|
return <div>{children}</div>;
|
||||||
<div className={styles.tutorial}>
|
|
||||||
<ContentTable />
|
|
||||||
<div>{children}</div>
|
|
||||||
<Sidebar />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,21 +2,31 @@ import { marked } from "marked";
|
|||||||
import { db, storage } from "../../../firebase-config";
|
import { db, storage } from "../../../firebase-config";
|
||||||
import { collection, doc, getDoc, getDocs } from "firebase/firestore";
|
import { collection, doc, getDoc, getDocs } from "firebase/firestore";
|
||||||
import { getDownloadURL, ref } from "firebase/storage";
|
import { getDownloadURL, ref } from "firebase/storage";
|
||||||
import styles from "../../../styles/TutorialContent.module.scss";
|
import ContentTable from "./ContentTable";
|
||||||
|
import Sidebar from "./Sidebar";
|
||||||
|
import styles from "../../../styles/Tutorial.module.scss";
|
||||||
import LoadPrism from "./LoadPrism";
|
import LoadPrism from "./LoadPrism";
|
||||||
|
|
||||||
type TutorialMeta = {
|
export type ContentTable = {
|
||||||
|
anchor: string;
|
||||||
title: string;
|
title: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TutorialMeta = {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
contentTable: ContentTable[];
|
||||||
|
};
|
||||||
|
|
||||||
async function GetTutorialMeta(tutorialId: string): Promise<TutorialMeta> {
|
async function GetTutorialMeta(tutorialId: string): Promise<TutorialMeta> {
|
||||||
const firebaseData = await getDoc(doc(db, "tutorials", tutorialId));
|
const firebaseData = await getDoc(doc(db, "tutorials", tutorialId));
|
||||||
const firebaseJsonData = firebaseData.data();
|
const firebaseJsonData = firebaseData.data();
|
||||||
|
|
||||||
const tutorial: TutorialMeta = {
|
const tutorial: TutorialMeta = {
|
||||||
|
id: tutorialId,
|
||||||
title: firebaseJsonData?.title ?? "Tutorial not found!",
|
title: firebaseJsonData?.title ?? "Tutorial not found!",
|
||||||
|
contentTable: firebaseJsonData?.contentTable ?? [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return tutorial;
|
return tutorial;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,9 +46,11 @@ async function FetchTutorialMarkdown(tutorialId: string) {
|
|||||||
|
|
||||||
function ParseMarkdown(markdown: string): string {
|
function ParseMarkdown(markdown: string): string {
|
||||||
let result = marked.parse(markdown);
|
let result = marked.parse(markdown);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//* MAIN
|
||||||
export default async function Tutorial({
|
export default async function Tutorial({
|
||||||
params,
|
params,
|
||||||
}: {
|
}: {
|
||||||
@@ -49,17 +61,21 @@ export default async function Tutorial({
|
|||||||
const markdown: string = await FetchTutorialMarkdown(tutorialId);
|
const markdown: string = await FetchTutorialMarkdown(tutorialId);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.tutorialContent}>
|
<div className={styles.tutorial}>
|
||||||
<div className={styles.head}>
|
<ContentTable tutorialMeta={tutorialMeta} />
|
||||||
<h1>{tutorialMeta.title}</h1>
|
<div className={styles.tutorialContent}>
|
||||||
|
<div className={styles.head}>
|
||||||
|
<h1>{tutorialMeta.title}</h1>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={styles.markdown}
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: ParseMarkdown(markdown),
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
<LoadPrism />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<Sidebar />
|
||||||
className={styles.markdown}
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: ParseMarkdown(markdown),
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
<LoadPrism />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
export default function Layout({ children }) {
|
|
||||||
return <>{children}</>;
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,33 @@
|
|||||||
|
@import "variables.scss";
|
||||||
.tutorial {
|
.tutorial {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 0.5fr 1fr 0.5fr;
|
gap: 20px;
|
||||||
column-gap: 10px;
|
grid-template-columns: 200px minmax(0px, 1fr) 200px;
|
||||||
|
margin: 0px auto;
|
||||||
|
max-width: 1500px;
|
||||||
|
padding: 0px 24px;
|
||||||
|
|
||||||
|
.tutorialContent {
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
.markdown {
|
||||||
|
padding: 0 10px 0 10px;
|
||||||
|
color: $md-color-font;
|
||||||
|
list-style: inside;
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
color: $md-color-headline;
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
border: 1px solid $md-color-hr;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
@import "variables.scss";
|
|
||||||
|
|
||||||
.tutorialContent {
|
|
||||||
max-width: 100%;
|
|
||||||
|
|
||||||
.head {
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown {
|
|
||||||
padding: 0 10px 0 10px;
|
|
||||||
color: $md-color-font;
|
|
||||||
list-style: inside;
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
color: $md-color-headline;
|
|
||||||
}
|
|
||||||
hr {
|
|
||||||
border: 1px solid $md-color-hr;
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
17
styles/TutorialContentTable.module.scss
Normal file
17
styles/TutorialContentTable.module.scss
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
@import "variables.scss";
|
||||||
|
|
||||||
|
.tutorialContentTable {
|
||||||
|
.stickyContainer {
|
||||||
|
position: sticky;
|
||||||
|
top: 60px;
|
||||||
|
.list {
|
||||||
|
align-items: flex-start;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
row-gap: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user