mirror of
				https://github.com/DerTyp7/explainegy-nextjs.git
				synced 2025-10-31 05:37:12 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			90 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { marked } from "marked";
 | |
| import { db, storage } from "../../../firebase-config";
 | |
| import { collection, doc, getDoc, getDocs } from "firebase/firestore";
 | |
| import { getDownloadURL, ref } from "firebase/storage";
 | |
| import ContentTable from "./ContentTable";
 | |
| import Sidebar from "./Sidebar";
 | |
| import styles from "../../../styles/Tutorial.module.scss";
 | |
| import LoadPrism from "./LoadPrism";
 | |
| 
 | |
| export type ContentTable = {
 | |
| 	anchor: string;
 | |
| 	title: string;
 | |
| };
 | |
| 
 | |
| export type TutorialMeta = {
 | |
| 	id: string;
 | |
| 	title: string;
 | |
| 	contentTable: ContentTable[];
 | |
| };
 | |
| 
 | |
| async function GetTutorialMeta(tutorialId: string): Promise<TutorialMeta> {
 | |
| 	const firebaseData = await getDoc(doc(db, "tutorials", tutorialId));
 | |
| 	const firebaseJsonData = firebaseData.data();
 | |
| 
 | |
| 	const tutorial: TutorialMeta = {
 | |
| 		id: tutorialId,
 | |
| 		title: firebaseJsonData?.title ?? "Tutorial not found!",
 | |
| 		contentTable: firebaseJsonData?.contentTable ?? [],
 | |
| 	};
 | |
| 	return tutorial;
 | |
| }
 | |
| 
 | |
| async function FetchTutorialMarkdown(tutorialId: string) {
 | |
| 	try {
 | |
| 		const url = await getDownloadURL(
 | |
| 			ref(storage, `markdowns/${tutorialId}.md`)
 | |
| 		);
 | |
| 		const data = await fetch(url, {
 | |
| 			next: { revalidate: 10 },
 | |
| 		});
 | |
| 		return await data.text();
 | |
| 	} catch {
 | |
| 		return "";
 | |
| 	}
 | |
| }
 | |
| 
 | |
| function ParseMarkdown(markdown: string): string {
 | |
| 	let result = marked.parse(markdown);
 | |
| 
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| //* MAIN
 | |
| export default async function Tutorial({
 | |
| 	params,
 | |
| }: {
 | |
| 	params: { tutorialId: string };
 | |
| }) {
 | |
| 	const tutorialId: string = params.tutorialId;
 | |
| 	const tutorialMeta: TutorialMeta = await GetTutorialMeta(tutorialId);
 | |
| 	const markdown: string = await FetchTutorialMarkdown(tutorialId);
 | |
| 
 | |
| 	return (
 | |
| 		<div className={styles.tutorial}>
 | |
| 			<ContentTable tutorialMeta={tutorialMeta} />
 | |
| 			<div className={styles.tutorialContent}>
 | |
| 				<div className={styles.head}>
 | |
| 					<h1>{tutorialMeta.title}</h1>
 | |
| 				</div>
 | |
| 				<div
 | |
| 					className={styles.markdown}
 | |
| 					dangerouslySetInnerHTML={{
 | |
| 						__html: ParseMarkdown(markdown),
 | |
| 					}}
 | |
| 				></div>
 | |
| 				<LoadPrism />
 | |
| 			</div>
 | |
| 			<Sidebar />
 | |
| 		</div>
 | |
| 	);
 | |
| }
 | |
| 
 | |
| export async function generateStaticParams() {
 | |
| 	const data = await getDocs(collection(db, "tutorials"));
 | |
| 
 | |
| 	return data.docs.map((doc) => ({
 | |
| 		tutorialId: doc.id,
 | |
| 	}));
 | |
| }
 | 
