171 lines
5.7 KiB
TypeScript
171 lines
5.7 KiB
TypeScript
import React from "react";
|
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
import {
|
|
ResizableHandle,
|
|
ResizablePanel,
|
|
ResizablePanelGroup,
|
|
} from "@/components/ui/resizable";
|
|
import { unified } from "unified";
|
|
import remarkParse from "remark-parse";
|
|
import remarkRehype from "remark-rehype";
|
|
import rehypeStringify from "rehype-stringify";
|
|
import rehypePrettyCode from "rehype-pretty-code";
|
|
import markdownStyles from "@/styles/markdown-styles.module.css";
|
|
import { tutorialData } from "@/constants/tutorial-data";
|
|
import { notFound } from "next/navigation";
|
|
import { buttonVariants } from "@/components/ui/button";
|
|
import Link from "next/link";
|
|
import { cn } from "@/lib/utils";
|
|
import EditorWindow from "@/components/task/editor-window";
|
|
import { LANGUAGE_VERSIONS } from "@/constants/language-options";
|
|
|
|
async function main(tutorialCode: string) {
|
|
const file = await unified()
|
|
.use(remarkParse)
|
|
.use(remarkRehype)
|
|
.use(rehypePrettyCode, {})
|
|
.use(rehypeStringify)
|
|
.process(tutorialCode);
|
|
|
|
return file;
|
|
}
|
|
|
|
const languages = Object.keys(LANGUAGE_VERSIONS);
|
|
|
|
const Page = async ({ params }: { params: { taskId: string[] } }) => {
|
|
if (!params.taskId[0] || !languages.includes(params.taskId[0])) {
|
|
notFound();
|
|
}
|
|
|
|
const langTutorial = tutorialData.find(
|
|
(t) => t.language === params.taskId[0],
|
|
)!;
|
|
|
|
const tutorial = langTutorial.tutorial.find(
|
|
(t) => t.id === (Number(params.taskId[1]) || 1),
|
|
);
|
|
|
|
const tutorialIndex = langTutorial.tutorial.findIndex(
|
|
(t) => t.id === (Number(params.taskId[1]) || 1),
|
|
);
|
|
|
|
if (!tutorial || tutorialIndex === -1) {
|
|
notFound();
|
|
}
|
|
|
|
const code = await main(tutorial?.content || "");
|
|
return (
|
|
<>
|
|
<div className="md:hidden w-full h-full">
|
|
<ResizablePanelGroup
|
|
direction="vertical"
|
|
className="max-w-[1440px] mx-auto h-full"
|
|
>
|
|
<ResizablePanel defaultSize={50}>
|
|
<ScrollArea className="h-[calc(100vh-55px)] border-b">
|
|
<div className="px-4 py-6 flex flex-col gap-4 h-full mb-[50vh]">
|
|
<div
|
|
className={cn("grow", markdownStyles["markdown"])}
|
|
dangerouslySetInnerHTML={{ __html: String(code) }}
|
|
></div>
|
|
<div className="flex justify-between">
|
|
<div className="mb-6">
|
|
{langTutorial?.tutorial[tutorialIndex - 1] && (
|
|
<Link
|
|
href={`/dashboard/task/${params.taskId[0]}/${
|
|
Number(params.taskId[1]) - 1
|
|
}`}
|
|
className={buttonVariants({
|
|
variant: "outline",
|
|
})}
|
|
>
|
|
Prev
|
|
</Link>
|
|
)}
|
|
</div>
|
|
|
|
<div className="mb-6">
|
|
{langTutorial?.tutorial[tutorialIndex + 1] && (
|
|
<Link
|
|
href={`/dashboard/task/${params.taskId[0]}/${
|
|
Number(params.taskId[1]) + 1
|
|
}`}
|
|
className={buttonVariants({ variant: "outline" })}
|
|
>
|
|
Next
|
|
</Link>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</ScrollArea>
|
|
</ResizablePanel>
|
|
<ResizableHandle withHandle />
|
|
<ResizablePanel defaultSize={50}>
|
|
<EditorWindow
|
|
language={params.taskId[0]}
|
|
step={Number(params.taskId[1]) || 1}
|
|
/>
|
|
</ResizablePanel>
|
|
</ResizablePanelGroup>
|
|
</div>
|
|
<div className="hidden md:block w-full h-full">
|
|
<ResizablePanelGroup
|
|
direction="horizontal"
|
|
className="max-w-[1440px] mx-auto h-full"
|
|
>
|
|
<ResizablePanel defaultSize={50}>
|
|
<ScrollArea className="h-[calc(100vh-55px)]">
|
|
<div className="px-4 py-6 flex flex-col gap-4 h-full">
|
|
<div
|
|
className={cn("grow", markdownStyles["markdown"])}
|
|
dangerouslySetInnerHTML={{ __html: String(code) }}
|
|
></div>
|
|
|
|
<div className="flex justify-between">
|
|
<div className="mb-6">
|
|
{langTutorial?.tutorial[tutorialIndex - 1] && (
|
|
<Link
|
|
href={`/dashboard/task/${params.taskId[0]}/${
|
|
Number(params.taskId[1]) - 1
|
|
}`}
|
|
className={buttonVariants({
|
|
variant: "outline",
|
|
})}
|
|
>
|
|
Prev
|
|
</Link>
|
|
)}
|
|
</div>
|
|
|
|
<div className="mb-6">
|
|
{langTutorial?.tutorial[tutorialIndex + 1] && (
|
|
<Link
|
|
href={`/dashboard/task/${params.taskId[0]}/${
|
|
Number(params.taskId[1]) + 1
|
|
}`}
|
|
className={buttonVariants({ variant: "outline" })}
|
|
>
|
|
Next
|
|
</Link>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</ScrollArea>
|
|
</ResizablePanel>
|
|
<ResizableHandle withHandle />
|
|
<ResizablePanel defaultSize={50}>
|
|
<EditorWindow
|
|
language={params.taskId[0]}
|
|
step={Number(params.taskId[1]) || 1}
|
|
/>
|
|
</ResizablePanel>
|
|
</ResizablePanelGroup>
|
|
</div>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default Page;
|