mirror of
https://github.com/cfngc4594/monaco-editor-lsp-next.git
synced 2025-05-18 15:26:36 +00:00
feat(submission-details): display last failed test case details and error messages
This commit is contained in:
parent
b18dedcc23
commit
207697c592
@ -1,20 +1,30 @@
|
||||
"use client";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useEffect } from "react";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/components/ui/accordion";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ArrowLeftIcon } from "lucide-react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useProblem } from "@/hooks/use-problem";
|
||||
import MdxPreview from "@/components/mdx-preview";
|
||||
import { useDockviewStore } from "@/stores/dockview";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { getStatusColorClass, statusMap } from "@/lib/status";
|
||||
import type { TestcaseResultWithTestcase } from "@/types/prisma";
|
||||
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
|
||||
import { formatDistanceToNow, isBefore, subDays, format } from "date-fns";
|
||||
|
||||
export default function DetailsPage() {
|
||||
const { api, submission } = useDockviewStore();
|
||||
const { editorLanguageConfigs, problemId } = useProblem();
|
||||
const [lastFailedTestcase, setLastFailedTestcase] =
|
||||
useState<TestcaseResultWithTestcase | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!api || !problemId || !submission?.id) return;
|
||||
@ -24,7 +34,19 @@ export default function DetailsPage() {
|
||||
api.removePanel(detailsPanel);
|
||||
}
|
||||
}
|
||||
}, [api, problemId, submission])
|
||||
}, [api, problemId, submission]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!submission?.id || !submission.testcaseResults) return;
|
||||
const failedTestcases = submission.testcaseResults.filter(
|
||||
(result) =>
|
||||
(submission.status === "WA" && !result.isCorrect) ||
|
||||
(submission.status === "TLE" && !result.isCorrect) ||
|
||||
(submission.status === "MLE" && !result.isCorrect) ||
|
||||
(submission.status === "RE" && !result.isCorrect)
|
||||
);
|
||||
setLastFailedTestcase(failedTestcases[0]);
|
||||
}, [submission]);
|
||||
|
||||
if (!api || !problemId || !submission?.id) return null;
|
||||
|
||||
@ -43,7 +65,7 @@ export default function DetailsPage() {
|
||||
if (detailsPanel) {
|
||||
api.removePanel(detailsPanel);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col border border-t-0 border-muted rounded-b-3xl bg-background">
|
||||
@ -70,9 +92,7 @@ export default function DetailsPage() {
|
||||
getStatusColorClass(submission.status)
|
||||
)}
|
||||
>
|
||||
<span>
|
||||
{statusMap.get(submission.status)?.message}
|
||||
</span>
|
||||
<span>{statusMap.get(submission.status)?.message}</span>
|
||||
</h3>
|
||||
<div className="flex max-w-full flex-1 items-center gap-1 overflow-hidden text-xs">
|
||||
<span className="whitespace-nowrap">Submitted on</span>
|
||||
@ -84,7 +104,74 @@ export default function DetailsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-col gap-6">
|
||||
{lastFailedTestcase && (
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Accordion
|
||||
type="single"
|
||||
collapsible
|
||||
className="w-full -space-y-px"
|
||||
>
|
||||
<AccordionItem
|
||||
value="input"
|
||||
className="bg-background has-focus-visible:border-ring has-focus-visible:ring-ring/50 relative border px-4 py-1 outline-none first:rounded-t-md last:rounded-b-md last:border-b has-focus-visible:z-10 has-focus-visible:ring-[3px]"
|
||||
>
|
||||
<AccordionTrigger className="py-2 text-[15px] leading-6 hover:no-underline focus-visible:ring-0">
|
||||
<h4 className="text-sm font-medium">Input</h4>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="text-muted-foreground pb-2">
|
||||
<div className="space-y-4">
|
||||
{lastFailedTestcase.testcase.data.map((field) => (
|
||||
<div key={field.id} className="space-y-2">
|
||||
<label className="text-sm font-medium">
|
||||
{`${field.label} =`}
|
||||
</label>
|
||||
<Input
|
||||
type="text"
|
||||
value={field.value}
|
||||
readOnly
|
||||
className="bg-muted border-transparent shadow-none rounded-lg h-10"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<h4 className="text-sm font-medium">Expected Output</h4>
|
||||
<Input
|
||||
type="text"
|
||||
value={lastFailedTestcase.testcase.expectedOutput}
|
||||
readOnly
|
||||
className="bg-muted border-transparent shadow-none rounded-lg h-10 font-mono"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{submission.status === "WA" && (
|
||||
<div className="space-y-2">
|
||||
<h4 className="text-sm font-medium">Your Output</h4>
|
||||
<Input
|
||||
type="text"
|
||||
value={lastFailedTestcase.output}
|
||||
readOnly
|
||||
className="bg-muted border-transparent shadow-none rounded-lg h-10 font-mono"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(submission.status === "CE" ||
|
||||
submission.status === "SE") && (
|
||||
<MdxPreview
|
||||
source={`\`\`\`shell\n${submission.message}\n\`\`\``}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="flex items-center pb-2">
|
||||
<div className="flex items-center gap-2 text-sm font-medium">
|
||||
<span>Code</span>
|
||||
@ -95,7 +182,8 @@ export default function DetailsPage() {
|
||||
<span>
|
||||
{
|
||||
editorLanguageConfigs.find(
|
||||
(config) => config.language === submission.language
|
||||
(config) =>
|
||||
config.language === submission.language
|
||||
)?.label
|
||||
}
|
||||
</span>
|
||||
|
Loading…
Reference in New Issue
Block a user