feat(problem): refactor layout and page components

- Refactored `ProblemLayout` to pass panel components (Description, Solutions, etc.) as props.
- Updated `ProblemPage` to dynamically render dock panels with content from props, instead of static components.
- Removed `DefaultDockviewOptions` and integrated custom panel configuration directly in `ProblemPage`.
- Enhanced `DockView` to support dynamic panel content rendering based on passed props.
This commit is contained in:
cfngc4594 2025-04-13 11:56:01 +08:00
parent a897e00a72
commit a559c326a8
2 changed files with 160 additions and 25 deletions

View File

@ -1,20 +1,42 @@
import prisma from "@/lib/prisma";
import { notFound } from "next/navigation";
import ProblemPage from "@/app/(app)/problems/[id]/page";
import { ProblemStoreProvider } from "@/providers/problem-store-provider";
import { PlaygroundHeader } from "@/components/features/playground/header";
interface ProblemProps {
params: Promise<{ id: string }>;
children: React.ReactNode;
Description: React.ReactNode;
Solutions: React.ReactNode;
Submissions: React.ReactNode;
Code: React.ReactNode;
Testcase: React.ReactNode;
TestResult: React.ReactNode;
Bot: React.ReactNode;
}
export default async function ProblemLayout({
params,
children,
Description,
Solutions,
Submissions,
Code,
Testcase,
TestResult,
Bot,
}: ProblemProps) {
const { id } = await params;
const [problem, editorLanguageConfigs, languageServerConfigs, submissions] = await Promise.all([
if (!id) {
return notFound();
}
const [
problem,
editorLanguageConfigs,
languageServerConfigs,
submissions,
] = await Promise.all([
prisma.problem.findUnique({
where: { id },
include: {
@ -30,7 +52,7 @@ export default async function ProblemLayout({
prisma.languageServerConfig.findMany(),
prisma.submission.findMany({
where: { problemId: id },
})
}),
]);
if (!problem) {
@ -48,7 +70,15 @@ export default async function ProblemLayout({
>
<PlaygroundHeader />
<main className="flex flex-grow overflow-y-hidden p-2.5 pt-0">
{children}
<ProblemPage
Description={Description}
Solutions={Solutions}
Submissions={Submissions}
Code={Code}
Testcase={Testcase}
TestResult={TestResult}
Bot={Bot}
/>
</main>
</ProblemStoreProvider>
</div>

View File

@ -1,35 +1,140 @@
"use client";
import {
Bot,
Code,
BotIcon,
CircleCheckBigIcon,
FileTextIcon,
FlaskConicalIcon,
SquareCheckIcon,
SquarePenIcon,
TerminalIcon,
} from "lucide-react";
import Dockview from "@/components/dockview";
import { useDockviewStore } from "@/stores/dockview";
interface ProblemPageProps {
Description: React.ReactNode;
Solutions: React.ReactNode;
Submissions: React.ReactNode;
Code: React.ReactNode;
Testcase: React.ReactNode;
TestResult: React.ReactNode;
Bot: React.ReactNode;
}
export default function ProblemPage({
Description,
Solutions,
Submissions,
Code,
Testcase,
TestResult,
} from "@/app/(app)/problems/[id]/features";
import DockView from "@/components/dockview";
import { useDockviewStore } from "@/stores/dockview";
import { DefaultDockviewOptions } from "@/config/dockview";
export default function ProblemPage() {
Bot,
}: ProblemPageProps) {
const { setApi } = useDockviewStore();
return (
<DockView
<Dockview
storageKey="dockview:problem"
components={{
Description: () => <Description />,
Solutions: () => <Solutions />,
Submissions: () => <Submissions />,
Code: () => <Code />,
Testcase: () => <Testcase />,
TestResult: () => <TestResult />,
Bot: () => <Bot />,
}}
options={DefaultDockviewOptions.filter((panel) => panel.id !== "Bot")}
onApiReady={setApi}
options={[
{
id: "Description",
component: "Description",
tabComponent: "Description",
title: "Description",
params: {
icon: FileTextIcon,
content: Description,
},
},
{
id: "Solutions",
component: "Solutions",
tabComponent: "Solutions",
title: "Solutions",
params: {
icon: FlaskConicalIcon,
content: Solutions,
},
position: {
referencePanel: "Description",
direction: "within",
},
inactive: true,
},
{
id: "Submissions",
component: "Submissions",
tabComponent: "Submissions",
title: "Submissions",
params: {
icon: CircleCheckBigIcon,
content: Submissions,
},
position: {
referencePanel: "Solutions",
direction: "within",
},
inactive: true,
},
{
id: "Code",
component: "Code",
tabComponent: "Code",
title: "Code",
params: {
icon: SquarePenIcon,
content: Code,
},
position: {
referencePanel: "Submissions",
direction: "right",
},
},
{
id: "Testcase",
component: "Testcase",
tabComponent: "Testcase",
title: "Testcase",
params: {
icon: SquareCheckIcon,
content: Testcase,
},
position: {
referencePanel: "Code",
direction: "below",
},
},
{
id: "TestResult",
component: "TestResult",
tabComponent: "TestResult",
title: "Test Result",
params: {
icon: TerminalIcon,
content: TestResult,
},
position: {
referencePanel: "Testcase",
direction: "within",
},
inactive: true,
},
{
id: "Bot",
component: "Bot",
tabComponent: "Bot",
title: "Bot",
params: {
icon: BotIcon,
content: Bot,
autoAdd: false,
},
position: {
direction: "right",
},
},
]}
/>
);
}