refactor(problems): use Suspense for lazy loading and adjust layout structure
Some checks failed
Build & Push Monaco Docker Image / build-and-push-monaco-docker-image (., Dockerfile, monaco-editor-lsp-next) (push) Failing after 16s

This commit is contained in:
cfngc4594 2025-03-12 08:59:38 +08:00
parent ca2d663533
commit a7a50231d2
7 changed files with 59 additions and 71 deletions

View File

@ -1,30 +1,18 @@
import prisma from "@/lib/prisma"; import { Suspense } from "react";
import ProblemDescriptionFooter from "@/features/playground/problem/description/footer"; import { Loading } from "@/components/loading";
interface ProblemDescriptionLayoutProps { interface ProblemDescriptionLayoutProps {
params: Promise<{ id: string }>;
children: React.ReactNode; children: React.ReactNode;
} }
export default async function ProblemDescriptionLayout({ export default function ProblemDescriptionLayout({
params,
children, children,
}: ProblemDescriptionLayoutProps) { }: ProblemDescriptionLayoutProps) {
const { id } = await params;
const problem = await prisma.problem.findUnique({
where: { id: parseInt(id) },
select: {
title: true,
}
});
const title = problem?.title ?? "";
return ( return (
<div className="h-full flex flex-col"> <div className="h-full flex flex-col">
<div className="flex-1">{children}</div> <Suspense fallback={<Loading />}>
<ProblemDescriptionFooter title={title} /> {children}
</Suspense>
</div> </div>
); );
} }

View File

@ -2,6 +2,7 @@ import prisma from "@/lib/prisma";
import { notFound } from "next/navigation"; import { notFound } from "next/navigation";
import { MdxRenderer } from "@/components/content/mdx-renderer"; import { MdxRenderer } from "@/components/content/mdx-renderer";
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"; import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
import ProblemDescriptionFooter from "@/features/playground/problem/description/footer";
interface ProblemDescriptionPageProps { interface ProblemDescriptionPageProps {
params: Promise<{ id: string }> params: Promise<{ id: string }>
@ -15,6 +16,7 @@ export default async function ProblemDescriptionPage({
const problem = await prisma.problem.findUnique({ const problem = await prisma.problem.findUnique({
where: { id: parseInt(id) }, where: { id: parseInt(id) },
select: { select: {
title: true,
description: true, description: true,
} }
}); });
@ -24,9 +26,14 @@ export default async function ProblemDescriptionPage({
} }
return ( return (
<ScrollArea className="[&>[data-radix-scroll-area-viewport]]:max-h-[calc(100vh-130px)]"> <>
<MdxRenderer source={problem.description} /> <div className="flex-1">
<ScrollBar orientation="horizontal" /> <ScrollArea className="[&>[data-radix-scroll-area-viewport]]:max-h-[calc(100vh-130px)]">
</ScrollArea> <MdxRenderer source={problem.description} />
<ScrollBar orientation="horizontal" />
</ScrollArea>
</div>
<ProblemDescriptionFooter title={problem.title} />
</>
); );
} }

View File

@ -1,30 +1,18 @@
import prisma from "@/lib/prisma"; import { Suspense } from "react";
import ProblemSolutionFooter from "@/features/playground/problem/solution/footer"; import { Loading } from "@/components/loading";
interface ProblemSolutionLayoutProps { interface ProblemSolutionLayoutProps {
params: Promise<{ id: string }>;
children: React.ReactNode; children: React.ReactNode;
} }
export default async function ProblemSolutionLayout({ export default function ProblemSolutionLayout({
params,
children, children,
}: ProblemSolutionLayoutProps) { }: ProblemSolutionLayoutProps) {
const { id } = await params;
const problem = await prisma.problem.findUnique({
where: { id: parseInt(id) },
select: {
title: true,
},
});
const title = problem?.title ?? "";
return ( return (
<div className="h-full flex flex-col"> <div className="h-full flex flex-col">
<div className="flex-1">{children}</div> <Suspense fallback={<Loading />}>
<ProblemSolutionFooter title={title} /> {children}
</Suspense>
</div> </div>
); );
} }

View File

@ -2,6 +2,7 @@ import prisma from "@/lib/prisma";
import { notFound } from "next/navigation"; import { notFound } from "next/navigation";
import { MdxRenderer } from "@/components/content/mdx-renderer"; import { MdxRenderer } from "@/components/content/mdx-renderer";
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"; import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
import ProblemSolutionFooter from "@/features/playground/problem/solution/footer";
interface ProblemSolutionPageProps { interface ProblemSolutionPageProps {
params: Promise<{ id: string }>; params: Promise<{ id: string }>;
@ -15,6 +16,7 @@ export default async function ProblemSolutionPage({
const problem = await prisma.problem.findUnique({ const problem = await prisma.problem.findUnique({
where: { id: parseInt(id) }, where: { id: parseInt(id) },
select: { select: {
title: true,
solution: true, solution: true,
}, },
}); });
@ -24,9 +26,14 @@ export default async function ProblemSolutionPage({
} }
return ( return (
<ScrollArea className="[&>[data-radix-scroll-area-viewport]]:max-h-[calc(100vh-130px)]"> <>
<MdxRenderer source={problem.solution} /> <div className="flex-1">
<ScrollBar orientation="horizontal" /> <ScrollArea className="[&>[data-radix-scroll-area-viewport]]:max-h-[calc(100vh-130px)]">
</ScrollArea> <MdxRenderer source={problem.solution} />
<ScrollBar orientation="horizontal" />
</ScrollArea>
</div>
<ProblemSolutionFooter title={problem.title} />
</>
); );
} }

View File

@ -1,3 +1,6 @@
import { Suspense } from "react";
import { Loading } from "@/components/loading";
interface TerminalTestcaseLayoutProps { interface TerminalTestcaseLayoutProps {
children: React.ReactNode; children: React.ReactNode;
} }
@ -7,7 +10,11 @@ export default function TerminalTestcaseLayout({
}: TerminalTestcaseLayoutProps) { }: TerminalTestcaseLayoutProps) {
return ( return (
<div className="h-full flex flex-col"> <div className="h-full flex flex-col">
<div className="flex-1">{children}</div> <div className="flex-1">
<Suspense fallback={<Loading />}>
{children}
</Suspense>
</div>
</div> </div>
); );
} }

View File

@ -1,37 +1,18 @@
import prisma from "@/lib/prisma"; import { Suspense } from "react";
import WorkspaceEditorHeader from "@/features/playground/workspace/editor/header"; import { Loading } from "@/components/loading";
import WorkspaceEditorFooter from "@/features/playground/workspace/editor/footer";
interface WorkspaceEditorLayoutProps { interface WorkspaceEditorLayoutProps {
params: Promise<{ id: string }>;
children: React.ReactNode; children: React.ReactNode;
} }
export default async function WorkspaceEditorLayout({ export default function WorkspaceEditorLayout({
params,
children, children,
}: WorkspaceEditorLayoutProps) { }: WorkspaceEditorLayoutProps) {
const { id } = await params;
const problem = await prisma.problem.findUnique({
where: { id: parseInt(id) },
select: {
templates: {
select: {
language: true,
template: true,
}
}
}
});
const templates = problem?.templates ?? [];
return ( return (
<div className="h-full flex flex-col"> <div className="h-full flex flex-col">
<WorkspaceEditorHeader templates={templates} /> <Suspense fallback={<Loading />}>
<div className="flex-1">{children}</div> {children}
<WorkspaceEditorFooter /> </Suspense>
</div> </div>
); );
} }

View File

@ -1,5 +1,7 @@
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import CodeEditor from "@/components/code-editor"; import CodeEditor from "@/components/code-editor";
import WorkspaceEditorHeader from "@/features/playground/workspace/editor/header";
import WorkspaceEditorFooter from "@/features/playground/workspace/editor/footer";
interface WorkspaceEditorProps { interface WorkspaceEditorProps {
params: Promise<{ id: string }> params: Promise<{ id: string }>
@ -24,5 +26,13 @@ export default async function WorkspaceEditorPage({
const templates = problem?.templates ?? []; const templates = problem?.templates ?? [];
return <CodeEditor problemId={id} templates={templates} />; return (
<>
<WorkspaceEditorHeader templates={templates} />
<div className="flex-1">
<CodeEditor problemId={id} templates={templates} />
</div>
<WorkspaceEditorFooter />
</>
)
} }