"use client"; import { useState, useCallback } from "react"; import { Card } from "@/components/ui/card"; import { ClientOnly } from "@/components/ui/client-only"; import { StepControls } from "./step-controls"; import { MathDisplay } from "@/components/math/math-display"; import { CartesianGrid, type GridPoint } from "./cartesian-grid"; interface Step { label: string; math: string; points: GridPoint[]; highlight?: { x: number; y: number }; guide?: "x" | "y" | "both"; } function randInt(min: number, max: number) { return Math.floor(Math.random() * (max - min + 1)) + min; } function quadrantName(x: number, y: number): string { if (x === 0 && y === 0) return "the origin"; if (x === 0) return "on the y-axis"; if (y === 0) return "on the x-axis"; if (x > 0 && y > 0) return "the top-right quadrant"; if (x < 0 && y > 0) return "the top-left quadrant"; if (x < 0 && y < 0) return "the bottom-left quadrant"; return "the bottom-right quadrant"; } function buildReadSteps(x: number, y: number): Step[] { const point: GridPoint = { x, y, tone: "solid" }; return [ { label: "Here is a point. Let's read off its coordinates.", math: `(?,\\ ?)`, points: [point], }, { label: `Trace straight ${y >= 0 ? "DOWN" : "UP"} to the x-axis. It lands on ${x}.`, math: `x = ${x}`, points: [point], highlight: { x, y }, guide: "x", }, { label: `Now trace straight across to the y-axis. It lands on ${y}.`, math: `y = ${y}`, points: [point], highlight: { x, y }, guide: "both", }, { label: `The coordinates are (${x}, ${y}) — x first, then y. This point is in ${quadrantName(x, y)}.`, math: `(${x},\\ ${y})`, points: [{ x, y, label: `(${x}, ${y})`, tone: "solid" }], highlight: { x, y }, guide: "both", }, ]; } // ── Quick practice: read the coordinates ───────────────────────────────────── function ReadPractice() { const [target, setTarget] = useState(() => ({ x: randInt(-9, 9), y: randInt(-9, 9) })); const [xVal, setXVal] = useState(""); const [yVal, setYVal] = useState(""); const [feedback, setFeedback] = useState<"correct" | "swapped" | "incorrect" | null>(null); const [score, setScore] = useState({ correct: 0, total: 0 }); function check() { const gx = parseInt(xVal, 10); const gy = parseInt(yVal, 10); if (isNaN(gx) || isNaN(gy)) return; if (gx === target.x && gy === target.y) { setFeedback("correct"); setScore((s) => ({ correct: s.correct + 1, total: s.total + 1 })); } else if (gx === target.y && gy === target.x && target.x !== target.y) { setFeedback("swapped"); setScore((s) => ({ correct: s.correct, total: s.total + 1 })); } else { setFeedback("incorrect"); setScore((s) => ({ correct: s.correct, total: s.total + 1 })); } } function next() { setTarget({ x: randInt(-9, 9), y: randInt(-9, 9) }); setXVal(""); setYVal(""); setFeedback(null); } return (

Quick Practice

{score.correct}/{score.total}

What are the coordinates of this point?

( { setXVal(e.target.value); setFeedback(null); }} disabled={feedback === "correct"} className="w-20 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-7" placeholder="x" aria-label="x coordinate" /> , { setYVal(e.target.value); setFeedback(null); }} disabled={feedback === "correct"} onKeyDown={(e) => { if (e.key === "Enter") { if (feedback === "correct") next(); else check(); } }} className="w-20 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-7" placeholder="y" aria-label="y coordinate" /> ) {feedback === "correct" ? ( ) : ( )}
{feedback === "correct" &&

Correct! ({target.x}, {target.y})

} {feedback === "swapped" && (

You swapped them — the x-coordinate comes first! Try again.

)} {feedback === "incorrect" && (

Not quite. Trace down to the x-axis, then across to the y-axis.

)}
); } // ── Main explorer ──────────────────────────────────────────────────────────── export function ReadCoordinatesExplorer() { const [point, setPoint] = useState(() => ({ x: 3, y: 2 })); const [steps, setSteps] = useState(() => buildReadSteps(3, 2)); const [currentStep, setCurrentStep] = useState(0); const [isPlaying, setIsPlaying] = useState(false); const done = steps ? currentStep >= steps.length - 1 : false; const reset = useCallback(() => { setCurrentStep(0); setIsPlaying(false); }, []); function newPoint() { let x = randInt(-9, 9); const y = randInt(-9, 9); if (x === point.x && y === point.y) x = -x || 1; setPoint({ x, y }); setSteps(buildReadSteps(x, y)); setCurrentStep(0); setIsPlaying(false); } const stepForward = useCallback(() => { if (!steps || currentStep >= steps.length - 1) return; setCurrentStep((s) => s + 1); if (currentStep + 1 >= steps.length - 1) setIsPlaying(false); }, [steps, currentStep]); const stepBack = useCallback(() => { if (currentStep <= 0) return; setCurrentStep((s) => s - 1); }, [currentStep]); const togglePlay = useCallback(() => setIsPlaying((p) => !p), []); const step = steps ? steps[currentStep] : null; return (

Read the coordinates of the point

{/* Display card */} {step && ( <>

{step.label}

)}
{/* Controls */} 0} /> {/* Quick practice */} }>
); }