228 lines
7.2 KiB
TypeScript
228 lines
7.2 KiB
TypeScript
"use client";
|
|
|
|
import React, { useEffect, useState } from "react";
|
|
import { compileCode } from "./compiler";
|
|
import { v4 as uuid } from "uuid";
|
|
import { CodeEditor } from "./code-editor";
|
|
import { ErrorBoundary } from "react-error-boundary";
|
|
import PreviewErrorFallback from "./preview-error-fallback";
|
|
import {
|
|
ResizableHandle,
|
|
ResizablePanel,
|
|
ResizablePanelGroup,
|
|
} from "@/components/ui/resizable";
|
|
import { ThemeDropdown } from "./theme-dropdown";
|
|
import LanguagesDropdown from "./languages-dropdown";
|
|
import Output from "./output";
|
|
import { tutorialData } from "@/constants/tutorial-data";
|
|
import { notFound, useRouter } from "next/navigation";
|
|
import { defineTheme } from "@/utils/define-theme";
|
|
import Preview from "./preview";
|
|
import { MyComponents } from "./my-components";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
export default function EditorWindow({
|
|
activeMobileView: activeMobileView,
|
|
language: lang,
|
|
step,
|
|
}: {
|
|
activeMobileView: "tutorial" | "code" | "output";
|
|
language: string;
|
|
step: number;
|
|
}) {
|
|
const [componentName, setComponentName] = useState<any>("");
|
|
const [theme, setTheme] = useState("cobalt");
|
|
// const [language, setLanguage] = useState(languageOptions[0]);
|
|
// const [language, setLanguage] = useState("react");
|
|
// const [defaultCode, setDefaultCode] = useState("");
|
|
const [codeValue, setCodeValue] = useState("");
|
|
const router = useRouter();
|
|
|
|
const handleCodeChange = (code: string | undefined) => {
|
|
try {
|
|
setCodeValue(code || "");
|
|
const func = compileCode(code || "");
|
|
const id = uuid();
|
|
MyComponents[id] = func(React);
|
|
setComponentName(id);
|
|
} catch (err) {
|
|
console.log(err);
|
|
// setComponentName("error");
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
defineTheme("cobalt").then((_) => setTheme("cobalt"));
|
|
}, []);
|
|
|
|
function handleThemeChange(th: string) {
|
|
const themee = th;
|
|
// console.log("theme...", theme);
|
|
|
|
if (["light", "vs-dark"].includes(themee)) {
|
|
setTheme(themee);
|
|
} else {
|
|
defineTheme(themee).then((_) => setTheme(themee));
|
|
}
|
|
}
|
|
|
|
const handleLanguageChange = (lang: string) => {
|
|
router.push(`/dashboard/task/${lang}/1`);
|
|
// try {
|
|
// if (lang === "react") {
|
|
// const func = compileCode(CODE_SNIPPETS[lang]);
|
|
// const id = uuid();
|
|
// MyComponents[id] = func(React);
|
|
// setComponentName(id);
|
|
// }
|
|
|
|
// setLanguage(lang);
|
|
// // @ts-ignore
|
|
// setCodeValue(CODE_SNIPPETS[lang]);
|
|
// // @ts-ignore
|
|
// // setDefaultCode(CODE_SNIPPETS[language]);
|
|
// } catch (error) {
|
|
// // console.log(error);
|
|
// }
|
|
};
|
|
|
|
const tutorial = tutorialData
|
|
.find((t) => t.language === lang)
|
|
?.tutorial.find((t) => t.id === step);
|
|
|
|
if (!tutorial) {
|
|
notFound();
|
|
}
|
|
// console.log(tutorial);
|
|
|
|
return (
|
|
<>
|
|
<div className="md:hidden">
|
|
{/* <ResizablePanelGroup direction="vertical" className="border-r">
|
|
<ResizablePanel defaultSize={50}> */}
|
|
<div
|
|
className={cn(
|
|
"fixed left-0 top-0 h-[calc(100vh-59px)] w-screen translate-x-full transition-transform ",
|
|
activeMobileView === "tutorial"
|
|
? "translate-x-full"
|
|
: activeMobileView === "code"
|
|
? "translate-x-0"
|
|
: activeMobileView === "output"
|
|
? "-translate-x-full"
|
|
: "",
|
|
)}
|
|
>
|
|
<div className="p-2 flex gap-4">
|
|
<ThemeDropdown
|
|
handleThemeChange={handleThemeChange}
|
|
theme={theme}
|
|
/>
|
|
{/* <LanguagesDropdown
|
|
handleLanguageChange={handleLanguageChange}
|
|
language={lang}
|
|
/> */}
|
|
</div>
|
|
<div className="h-[calc(100vh-calc(57px+53px))]">
|
|
<CodeEditor
|
|
codeValue={codeValue}
|
|
// @ts-ignore
|
|
// defaultCode={CODE_SNIPPETS[language]}
|
|
defaultCode={tutorial?.code || ""}
|
|
onChange={handleCodeChange}
|
|
theme={theme}
|
|
// language={language}
|
|
language={lang}
|
|
/>
|
|
</div>
|
|
</div>
|
|
{/* </ResizablePanel> */}
|
|
{/* <ResizableHandle withHandle /> */}
|
|
{/* <ResizablePanel defaultSize={50}> */}
|
|
<ErrorBoundary FallbackComponent={PreviewErrorFallback}>
|
|
<div
|
|
className={cn(
|
|
"bg-white text-black p-4 fixed left-0 h-[calc(100vh-59px)] w-screen transition-transform translate-x-[200%]",
|
|
activeMobileView === "tutorial"
|
|
? "translate-x-[200%]"
|
|
: activeMobileView === "code"
|
|
? "translate-x-[100%]"
|
|
: activeMobileView === "output"
|
|
? "translate-x-0"
|
|
: "",
|
|
)}
|
|
>
|
|
{lang === "react" ? (
|
|
<Preview
|
|
componentName={componentName}
|
|
tutorialCode={tutorial?.code || ""}
|
|
/>
|
|
) : (
|
|
<Output
|
|
// @ts-ignore
|
|
codeValue={codeValue || tutorial?.code || ""}
|
|
// codeValue={codeValue || CODE_SNIPPETS[language]}
|
|
// language={language}
|
|
language={lang}
|
|
/>
|
|
)}
|
|
</div>
|
|
</ErrorBoundary>
|
|
{/* </ResizablePanel> */}
|
|
{/* </ResizablePanelGroup> */}
|
|
</div>
|
|
|
|
<div className="hidden md:block h-[calc(100vh-55px)]">
|
|
<ResizablePanelGroup direction="vertical" className="border-r">
|
|
<ResizablePanel defaultSize={50}>
|
|
<div className="h-full ">
|
|
<div className="p-2 flex gap-4">
|
|
<ThemeDropdown
|
|
handleThemeChange={handleThemeChange}
|
|
theme={theme}
|
|
/>
|
|
{/* <LanguagesDropdown
|
|
handleLanguageChange={handleLanguageChange}
|
|
language={lang}
|
|
/> */}
|
|
</div>
|
|
<div className="h-full">
|
|
<CodeEditor
|
|
codeValue={codeValue}
|
|
// @ts-ignore
|
|
// defaultCode={CODE_SNIPPETS[language]}
|
|
defaultCode={tutorial?.code || ""}
|
|
onChange={handleCodeChange}
|
|
theme={theme}
|
|
// language={language}
|
|
language={lang}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</ResizablePanel>
|
|
<ResizableHandle withHandle />
|
|
<ResizablePanel defaultSize={50}>
|
|
<ErrorBoundary FallbackComponent={PreviewErrorFallback}>
|
|
<div className="bg-white text-black h-full p-4">
|
|
{lang === "react" ? (
|
|
<Preview
|
|
componentName={componentName}
|
|
tutorialCode={tutorial?.code || ""}
|
|
/>
|
|
) : (
|
|
<Output
|
|
// @ts-ignore
|
|
codeValue={codeValue || tutorial?.code || ""}
|
|
// codeValue={codeValue || CODE_SNIPPETS[language]}
|
|
// language={language}
|
|
language={lang}
|
|
/>
|
|
)}
|
|
</div>
|
|
</ErrorBoundary>
|
|
</ResizablePanel>
|
|
</ResizablePanelGroup>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|