import { useMemo, useState } from "react"; import { useParams } from "react-router-dom"; import { useQueryClient } from "@tanstack/react-query"; import { Headphones, Mic, BookMarked, PenLine, CheckCircle2, CircleDot, Lock, ClipboardCheck, Award, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Progress } from "@/components/ui/progress"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Separator } from "@/components/ui/separator"; import { useAiCourse, useAiCourseTracks, useCreateIeltsCourse } from "@/hooks/queries/useAiCourse"; import { queryKeys } from "@/hooks/queries/keys"; import type { AICourseTrack, AIGenerationStep, AITrackModule } from "@/types"; import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, LineChart, Line, } from "recharts"; import { toast } from "sonner"; const SKILL_ICONS = [PenLine, BookMarked, Mic, Headphones]; export default function AiIeltsCourse() { const { courseId: cid } = useParams<{ courseId: string }>(); const courseId = Number(cid); const qc = useQueryClient(); const { data: course, isLoading } = useAiCourse(Number.isFinite(courseId) ? courseId : undefined); const { data: tracksRaw } = useAiCourseTracks(Number.isFinite(courseId) ? courseId : undefined); const createIelts = useCreateIeltsCourse(); const [targetBand, setTargetBand] = useState(""); const [readinessOpen, setReadinessOpen] = useState(false); const skillsRanked = course?.skills_ranked_by_gap && course.skills_ranked_by_gap.length > 0 ? course.skills_ranked_by_gap : [ { skill: "Writing", gap: 1.2 }, { skill: "Speaking", gap: 0.9 }, { skill: "Reading", gap: 0.4 }, { skill: "Listening", gap: 0.3 }, ]; const weakTypes = course?.weak_question_types ?? { Writing: ["Task 2 argument depth"], Reading: ["True/False/Not Given"], Speaking: ["Part 2 long turn"], Listening: ["Form completion"], }; const skillPanels: { skill: string; steps: AIGenerationStep[]; progress_percent: number }[] = course?.ielts_generation_by_skill?.length ? course.ielts_generation_by_skill : ["Writing", "Reading", "Speaking", "Listening"].map((skill, i) => ({ skill, steps: [ { name: "Blueprint", status: i === 0 ? ("in_progress" as const) : ("pending" as const) }, { name: "Items", status: "pending" as const }, { name: "Rubric alignment", status: "pending" as const }, ], progress_percent: [35, 20, 10, 5][i] ?? 0, })); const tracks: AICourseTrack[] = useMemo(() => { if (tracksRaw?.length) return tracksRaw; return ["Writing", "Reading", "Speaking", "Listening"].map((name, ti) => ({ name: `${name} skill`, progress_percent: 15 + ti * 8, modules: ieltsModules(name), })); }, [tracksRaw]); const bandSeries = [ { label: "L", v: course?.current_bands?.Listening ?? 6.0 }, { label: "R", v: course?.current_bands?.Reading ?? 6.5 }, { label: "W", v: course?.current_bands?.Writing ?? 5.5 }, { label: "S", v: course?.current_bands?.Speaking ?? 6.0 }, ]; if (isLoading) { return
Band-focused practice generated for you
{course?.exam_type ?? "Academic"}
{Object.entries(course?.current_bands ?? { L: 6, R: 6.5, W: 5.5, S: 6 }) .map(([k, v]) => `${k}: ${v}`) .join(" · ")}