feat(testcase): add dynamic testcase card and form for problem view
Some checks failed
Build & Push Judge4c Docker Image / build-and-push-judge4c-docker-image (., Dockerfile, judge4c) (push) Failing after 1s

This commit is contained in:
cfngc4594 2025-04-09 21:26:06 +08:00
parent 51b9d7fa72
commit 3f10c08a6c
3 changed files with 119 additions and 1 deletions

View File

@ -1,3 +1,12 @@
import TestcaseCard from "@/components/testcase-card";
import { useProblemStore } from "@/providers/problem-store-provider";
export default function Testcase() {
return <div className="h-full px-4">Testcase</div>;
const problem = useProblemStore((state) => state.problem);
return (
<div className="h-full rounded-b-3xl border border-t-0 border-muted bg-background">
<TestcaseCard testcases={problem.testcases} />
</div>
);
}

View File

@ -0,0 +1,43 @@
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ui/tabs";
import { TestcaseWithDetails } from "@/types/prisma";
import TestcaseForm from "@/components/testcase-form";
interface TestcaseCardProps {
testcases: TestcaseWithDetails;
}
export default function TestcaseCard({ testcases }: TestcaseCardProps) {
return (
<Tabs defaultValue="case-1" className="items-center px-5 py-4">
<TabsList className="bg-transparent p-0">
{testcases.map((_, index) => (
<TabsTrigger
key={`tab-${index}`}
value={`case-${index + 1}`}
className="data-[state=active]:bg-muted data-[state=active]:shadow-none"
>
Case {index + 1}
</TabsTrigger>
))}
</TabsList>
{testcases.map((testcase, index) => {
const formData = testcase.data.reduce((acc, field) => {
acc[field.label] = field.value;
return acc;
}, {} as Record<string, string>);
return (
<TabsContent key={`content-${index}`} value={`case-${index + 1}`}>
<TestcaseForm {...formData} />
</TabsContent>
);
})}
</Tabs>
);
}

View File

@ -0,0 +1,66 @@
"use client";
import * as z from "zod";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { toast } from "sonner";
import { useForm } from "react-hook-form";
import { Input } from "@/components/ui/input";
import { zodResolver } from "@hookform/resolvers/zod";
const formSchema = z.record(z.string().min(1));
interface TestcaseFormInterface {
[key: string]: string | undefined;
}
export default function TestcaseForm(props: TestcaseFormInterface) {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: props,
});
function onSubmit(values: z.infer<typeof formSchema>) {
try {
console.log(values);
toast.success(JSON.stringify(values, null, 2));
} catch (error) {
console.error("Form submission error", error);
toast.error("Failed to submit the form. Please try again.");
}
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4" id="testcase-form">
{Object.keys(props).map((fieldName) => (
<FormField
key={fieldName}
control={form.control}
name={fieldName}
render={({ field }) => (
<FormItem>
<FormLabel>{`${fieldName} =`}</FormLabel>
<FormControl>
<Input
className="bg-muted border-transparent shadow-none rounded-lg h-10"
placeholder={`Enter ${fieldName}`}
type="text"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
))}
</form>
</Form>
);
}