-
CAPTCHA
-
- Verification widget placeholder
+
+ Verification
+
+
+ {captchaConfig?.site_key ? (
+
+ ) : (
+
CAPTCHA not configured — registration allowed
+ )}
+ {captchaToken && (
+
+ Verified
+
+ )}
{form.formState.errors.root && (
diff --git a/src/pages/RubricsPage.tsx b/src/pages/RubricsPage.tsx
index f6f86d3..23c2e79 100644
--- a/src/pages/RubricsPage.tsx
+++ b/src/pages/RubricsPage.tsx
@@ -1,4 +1,5 @@
import { useState } from "react";
+import { useQuery } from "@tanstack/react-query";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
@@ -8,11 +9,21 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
-import { Search, Plus } from "lucide-react";
+import { Search, Plus, Loader2 } from "lucide-react";
import AiTipBanner from "@/components/ai/AiTipBanner";
import AiCreationAssistant from "@/components/ai/AiCreationAssistant";
+import { examsService } from "@/services/exams.service";
-const rubrics = [
+interface RubricItem {
+ id: number;
+ name: string;
+ levels: string[];
+ criteria: number;
+ created: string;
+ skill?: string;
+}
+
+const FALLBACK_RUBRICS: RubricItem[] = [
{ id: 1, name: "IELTS Writing Task 2", levels: ["A1","A2","B1","B2","C1","C2"], criteria: 4, created: "2025-01-05" },
{ id: 2, name: "Speaking Fluency", levels: ["A1","A2","B1","B2","C1","C2"], criteria: 3, created: "2025-01-10" },
{ id: 3, name: "Reading Comprehension", levels: ["A1","A2","B1","B2","C1"], criteria: 5, created: "2025-02-01" },
@@ -26,6 +37,13 @@ const rubricGroups = [
export default function RubricsPage() {
const [search, setSearch] = useState("");
+ const rubricsQ = useQuery({
+ queryKey: ["rubrics"],
+ queryFn: () => examsService.listRubrics({}),
+ });
+ const backendRubrics = (rubricsQ.data?.items ?? []) as RubricItem[];
+ const rubrics = backendRubrics.length > 0 ? backendRubrics : FALLBACK_RUBRICS;
+
return (
diff --git a/src/pages/admin/CustomExamCreate.tsx b/src/pages/admin/CustomExamCreate.tsx
index 633e13a..811c244 100644
--- a/src/pages/admin/CustomExamCreate.tsx
+++ b/src/pages/admin/CustomExamCreate.tsx
@@ -583,10 +583,27 @@ function NewQuestionInline({ sectionIndex, form }: { sectionIndex: number; form: