Files
edbridge-scholars/src/pages/student/lessons/LinesAnglesLesson.tsx

716 lines
29 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useRef, useState, useEffect } from "react";
import {
ArrowDown,
Check,
Target,
Layers,
Calculator,
BookOpen,
} from "lucide-react";
import InteractiveTransversal from "../../../components/lessons/InteractiveTransversal";
import InteractiveTriangle from "../../../components/lessons/InteractiveTriangle";
import PolygonWidget from "../../../components/lessons/PolygonWidget";
import Quiz from "../../../components/lessons/Quiz";
import { ANGLES_QUIZ_DATA } from "../../../utils/constants";
import { Frac } from "../../../components/Math";
interface LessonProps {
onFinish?: () => void;
}
const LinesAnglesLesson: React.FC<LessonProps> = ({ onFinish }) => {
const [activeSection, setActiveSection] = useState(0);
const sectionsRef = useRef<(HTMLElement | null)[]>([]);
const scrollToSection = (index: number) => {
setActiveSection(index);
sectionsRef.current[index]?.scrollIntoView({
behavior: "smooth",
block: "start",
});
};
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const index = sectionsRef.current.indexOf(
entry.target as HTMLElement,
);
if (index !== -1) setActiveSection(index);
}
});
},
{ rootMargin: "-20% 0px -60% 0px" },
);
sectionsRef.current.forEach((section) => {
if (section) observer.observe(section);
});
return () => observer.disconnect();
}, []);
const SectionMarker = ({
index,
title,
icon: Icon,
}: {
index: number;
title: string;
icon: any;
}) => {
const isActive = activeSection === index;
const isPast = activeSection > index;
return (
<button
onClick={() => scrollToSection(index)}
className={`flex items-center gap-3 p-3 w-full rounded-lg transition-all ${isActive ? "bg-white shadow-md border border-emerald-100" : "hover:bg-slate-100"}`}
>
<div
className={`w-8 h-8 rounded-full flex items-center justify-center shrink-0 ${isActive ? "bg-emerald-600 text-white" : isPast ? "bg-emerald-400 text-white" : "bg-slate-200 text-slate-500"}`}
>
{isPast ? (
<Check className="w-4 h-4" />
) : (
<Icon className="w-4 h-4" />
)}
</div>
<div className="text-left">
<p
className={`text-sm font-bold ${isActive ? "text-emerald-900" : "text-slate-600"}`}
>
{title}
</p>
</div>
</button>
);
};
return (
<div className="flex flex-col lg:flex-row min-h-screen">
<aside className="w-full lg:w-64 lg:fixed lg:top-20 lg:bottom-0 lg:overflow-y-auto p-4 border-r border-slate-200 bg-slate-50 lg:bg-transparent z-0 hidden lg:block">
<nav className="space-y-2">
<SectionMarker index={0} title="Parallel Lines" icon={Target} />
<SectionMarker index={1} title="Triangles" icon={Layers} />
<SectionMarker
index={2}
title="Special Triangles"
icon={Calculator}
/>
<SectionMarker index={3} title="Polygons" icon={Calculator} />
<SectionMarker index={4} title="Practice" icon={BookOpen} />
</nav>
</aside>
<div className="flex-1 lg:ml-64 p-6 md:p-12 max-w-4xl mx-auto">
{/* Section 1: Parallel Lines */}
<section
ref={(el) => {
sectionsRef.current[0] = el;
}}
className="min-h-screen flex flex-col justify-center mb-24 pt-20 lg:pt-0"
>
<h2 className="text-4xl font-extrabold text-slate-900 mb-6">
Parallel Lines & Transversals
</h2>
<div className="prose prose-slate text-lg text-slate-600 mb-8">
<p>
When two parallel lines are cut by a transversal, 8 angles are
formed. They fall into exactly two groups:{" "}
<strong>equal angles</strong> and{" "}
<strong>supplementary pairs</strong> (summing to 180°). Know one
angle find all eight.
</p>
</div>
<div className="bg-emerald-50 border border-emerald-200 rounded-2xl p-6 mb-8 space-y-5">
<h3 className="text-lg font-bold text-emerald-900">
The 5 Angle-Pair Relationships
</h3>
<div className="overflow-x-auto rounded-xl border border-emerald-200">
<table className="w-full text-sm border-collapse">
<thead>
<tr className="bg-emerald-900 text-white">
<th className="p-3 text-left">Angle Pair</th>
<th className="p-3 text-left">Location</th>
<th className="p-3 text-left">Relationship</th>
</tr>
</thead>
<tbody className="divide-y divide-emerald-100">
<tr className="bg-emerald-50">
<td className="p-3 font-bold text-emerald-800">
Corresponding
</td>
<td className="p-3">
Same side, same position at each intersection
</td>
<td className="p-3 font-bold text-emerald-700">Equal</td>
</tr>
<tr className="bg-white">
<td className="p-3 font-bold text-emerald-800">
Alternate Interior
</td>
<td className="p-3">
Between the parallel lines, opposite sides
</td>
<td className="p-3 font-bold text-emerald-700">Equal</td>
</tr>
<tr className="bg-emerald-50">
<td className="p-3 font-bold text-emerald-800">
Alternate Exterior
</td>
<td className="p-3">
Outside the parallel lines, opposite sides
</td>
<td className="p-3 font-bold text-emerald-700">Equal</td>
</tr>
<tr className="bg-white">
<td className="p-3 font-bold text-slate-600">
Co-Interior (Same-Side)
</td>
<td className="p-3">
Between the lines, same side of transversal
</td>
<td className="p-3 font-bold text-rose-700">
Supplementary (sum = 180°)
</td>
</tr>
<tr className="bg-emerald-50">
<td className="p-3 font-bold text-slate-600">
Vertical Angles
</td>
<td className="p-3">
Opposite each other at an intersection
</td>
<td className="p-3 font-bold text-emerald-700">Equal</td>
</tr>
</tbody>
</table>
</div>
{/* Worked Example */}
<div className="bg-white rounded-xl p-5 border border-emerald-100">
<p className="font-bold text-emerald-800 mb-3">
Worked Example: Find All 8 Angles
</p>
<p className="text-sm text-slate-700 mb-2">
If one angle formed by a transversal cutting two parallel lines
is 65°, find all other angles.
</p>
<div className="bg-emerald-50 rounded-lg p-4 text-sm font-mono text-slate-700 space-y-1">
<p>
Angle 1 = <strong>65°</strong> (given)
</p>
<p>
Vertical angle = <strong>65°</strong> (vertical angles are
equal)
</p>
<p>
Corresponding angle = <strong>65°</strong> (corresponding
angles are equal)
</p>
<p>
Its vertical angle = <strong>65°</strong>
</p>
<p>
All four supplementary angles = 180° 65° ={" "}
<strong>115°</strong>
</p>
<p className="mt-2 text-emerald-800 font-bold">
Result: four 65° angles and four 115° angles.
</p>
</div>
</div>
<div className="bg-sky-50 border border-sky-200 rounded-xl p-4 text-sm">
<p className="font-bold text-sky-900 mb-1">
SAT Strategy: Label with x and 180 x
</p>
<p className="text-slate-700">
When angles are expressed algebraically, label all equal angles
as "x" and all supplementary angles as "180 x." Then set equal
or add to 180 to solve.
</p>
<div className="font-mono text-xs bg-white rounded p-2 mt-2 text-slate-700">
<p>
Example: Corresponding angles 3x + 15 = 2x + 45 x = 30°
</p>
</div>
</div>
</div>
<div className="mb-8">
<InteractiveTransversal />
</div>
<button
onClick={() => scrollToSection(1)}
className="group flex items-center text-emerald-600 font-bold hover:text-emerald-800"
>
Next: Triangles{" "}
<ArrowDown className="ml-2 w-5 h-5 group-hover:translate-y-1 transition-transform" />
</button>
</section>
{/* Section 2: Triangles */}
<section
ref={(el) => {
sectionsRef.current[1] = el;
}}
className="min-h-screen flex flex-col justify-center mb-24"
>
<h2 className="text-4xl font-extrabold text-slate-900 mb-6">
Triangle Theorems
</h2>
<div className="prose prose-slate text-lg text-slate-600 mb-8">
<p>
Two essential theorems unlock almost every SAT triangle problem.
The interactive tool below lets you drag vertices to verify both
dynamically.
</p>
</div>
<div className="bg-emerald-50 border border-emerald-200 rounded-2xl p-6 mb-8 space-y-5">
<h3 className="text-lg font-bold text-emerald-900">
Core Triangle Rules
</h3>
<div className="grid md:grid-cols-2 gap-4">
<div className="bg-white rounded-xl p-5 border border-emerald-200">
<p className="font-bold text-emerald-900 mb-1">
Triangle Sum Theorem
</p>
<div className="font-mono text-center bg-emerald-50 py-2 rounded text-emerald-700 font-bold mb-2">
A + B + C = 180°
</div>
<p className="text-sm text-slate-700">
The three interior angles of any triangle always sum to
exactly 180°. No exceptions.
</p>
</div>
<div className="bg-white rounded-xl p-5 border border-emerald-200">
<p className="font-bold text-emerald-900 mb-1">
Exterior Angle Theorem
</p>
<div className="font-mono text-center bg-emerald-50 py-2 rounded text-emerald-700 font-bold mb-2">
ext = A + B
</div>
<p className="text-sm text-slate-700">
An exterior angle equals the sum of the two non-adjacent
(remote) interior angles.
</p>
</div>
</div>
{/* Worked Examples */}
<div className="bg-white rounded-xl p-5 border border-emerald-100">
<p className="font-bold text-emerald-800 mb-3">Worked Examples</p>
<div className="space-y-3">
<div className="bg-emerald-50 rounded-lg p-4 text-sm">
<p className="font-semibold text-emerald-800 mb-1">
Example 1: Find a missing angle
</p>
<div className="font-mono text-xs text-slate-700 space-y-1">
<p>Two angles are 47° and 83°. Find the third.</p>
<p>
C = 180° 47° 83° ={" "}
<strong className="text-emerald-700">50°</strong>
</p>
</div>
</div>
<div className="bg-emerald-50 rounded-lg p-4 text-sm">
<p className="font-semibold text-emerald-800 mb-1">
Example 2: Exterior angle
</p>
<div className="font-mono text-xs text-slate-700 space-y-1">
<p>
Two interior angles are 40° and 65°. Find the exterior
angle at the third vertex.
</p>
<p>
ext = 40° + 65° ={" "}
<strong className="text-emerald-700">105°</strong>
</p>
</div>
</div>
<div className="bg-emerald-50 rounded-lg p-4 text-sm">
<p className="font-semibold text-emerald-800 mb-1">
Example 3: Isosceles triangle
</p>
<div className="font-mono text-xs text-slate-700 space-y-1">
<p>
An isosceles triangle has vertex angle = 40°. Find the
base angles.
</p>
<p>
Each base angle = <Frac n="180° 40°" d="2" /> ={" "}
<Frac n="140°" d="2" /> ={" "}
<strong className="text-emerald-700">70°</strong>
</p>
</div>
</div>
</div>
</div>
{/* Triangle Inequality */}
<div className="bg-sky-50 border border-sky-200 rounded-xl p-4 text-sm">
<p className="font-bold text-sky-900 mb-1">
Triangle Inequality Theorem
</p>
<p className="text-slate-700 mb-2">
Any two sides of a triangle must sum to more than the third
side.
</p>
<div className="font-mono text-xs bg-white rounded p-2 text-slate-700">
<p>a + b &gt; c, a + c &gt; b, b + c &gt; a</p>
<p className="mt-1">
Example: Can a triangle have sides 3, 5, 9?
</p>
<p>3 + 5 = 8 &lt; 9 NO, not a valid triangle.</p>
</div>
</div>
</div>
<InteractiveTriangle />
<button
onClick={() => scrollToSection(2)}
className="mt-8 group flex items-center text-emerald-600 font-bold hover:text-emerald-800"
>
Next: Special Triangles{" "}
<ArrowDown className="ml-2 w-5 h-5 group-hover:translate-y-1 transition-transform" />
</button>
</section>
{/* Section 3: Special Triangles */}
<section
ref={(el) => {
sectionsRef.current[2] = el;
}}
className="min-h-screen flex flex-col justify-center mb-24"
>
<h2 className="text-4xl font-extrabold text-slate-900 mb-6">
Special Right Triangles
</h2>
<div className="prose prose-slate text-lg text-slate-600 mb-8">
<p>
These two triangle types appear constantly on the SAT. Memorize
their side ratios so you can find any missing side without using
the Pythagorean theorem.
</p>
</div>
<div className="bg-emerald-50 border border-emerald-200 rounded-2xl p-6 mb-8 space-y-5">
<h3 className="text-lg font-bold text-emerald-900">
The Two Special Right Triangles
</h3>
<div className="grid md:grid-cols-2 gap-4">
<div className="bg-white rounded-xl p-5 border border-emerald-200">
<p className="font-bold text-emerald-900 mb-2">
45° 45° 90°
</p>
<div className="font-mono text-center bg-emerald-50 py-3 rounded text-emerald-700 font-bold text-lg mb-2">
Sides: 1 : 1 : 2
</div>
<p className="text-sm text-slate-700 mb-2">
Two equal legs. Hypotenuse = leg × 2.
</p>
<div className="font-mono text-xs bg-slate-50 rounded p-2 text-slate-700">
<p>If leg = 5: hyp = 52</p>
<p>
If hyp = 8: leg = <Frac n="8" d="√2" /> = 42
</p>
</div>
</div>
<div className="bg-white rounded-xl p-5 border border-emerald-200">
<p className="font-bold text-emerald-900 mb-2">
30° 60° 90°
</p>
<div className="font-mono text-center bg-emerald-50 py-3 rounded text-emerald-700 font-bold text-lg mb-2">
Sides: 1 : 3 : 2
</div>
<p className="text-sm text-slate-700 mb-2">
Shortest leg opposite 30°. Hypotenuse = 2 × short leg.
</p>
<div className="font-mono text-xs bg-slate-50 rounded p-2 text-slate-700">
<p>Short leg = 4: long leg = 43, hyp = 8</p>
<p>Hyp = 10: short leg = 5, long leg = 53</p>
</div>
</div>
</div>
{/* Pythagorean Theorem */}
<div className="bg-white rounded-xl p-5 border border-emerald-100">
<p className="font-bold text-emerald-800 mb-3">
Pythagorean Theorem & Common Triples
</p>
<div className="font-mono text-center bg-emerald-50 py-2 rounded text-emerald-700 font-bold text-lg mb-3">
a² + b² = c²
</div>
<p className="text-sm text-slate-600 mb-3">
c is always the hypotenuse (opposite the right angle). Memorize
these Pythagorean triples they appear frequently on the SAT:
</p>
<div className="overflow-x-auto rounded-xl border border-emerald-200">
<table className="w-full text-sm border-collapse">
<thead>
<tr className="bg-emerald-900 text-white">
<th className="p-2 text-center">Triple (a, b, c)</th>
<th className="p-2 text-center">Scaled Version</th>
<th className="p-2 text-center">Verify</th>
</tr>
</thead>
<tbody className="divide-y divide-emerald-100">
<tr className="bg-white text-center">
<td className="p-2 font-bold">3, 4, 5</td>
<td className="p-2 text-slate-600">6-8-10, 9-12-15</td>
<td className="p-2 font-mono text-xs">9 + 16 = 25 </td>
</tr>
<tr className="bg-emerald-50 text-center">
<td className="p-2 font-bold">5, 12, 13</td>
<td className="p-2 text-slate-600">10-24-26</td>
<td className="p-2 font-mono text-xs">
25 + 144 = 169
</td>
</tr>
<tr className="bg-white text-center">
<td className="p-2 font-bold">8, 15, 17</td>
<td className="p-2 text-slate-600"></td>
<td className="p-2 font-mono text-xs">
64 + 225 = 289
</td>
</tr>
<tr className="bg-emerald-50 text-center">
<td className="p-2 font-bold">7, 24, 25</td>
<td className="p-2 text-slate-600"></td>
<td className="p-2 font-mono text-xs">
49 + 576 = 625
</td>
</tr>
</tbody>
</table>
</div>
</div>
{/* Worked examples */}
<div className="space-y-3">
<div className="bg-sky-50 rounded-xl p-4 border border-sky-200 text-sm">
<p className="font-semibold text-sky-800 mb-2">
Worked Example: 30-60-90
</p>
<div className="font-mono text-xs text-slate-700 space-y-1">
<p>
An equilateral triangle has side length 10. Find the height.
</p>
<p>The height bisects it into two 30-60-90 triangles.</p>
<p>Short leg (half the base) = 5</p>
<p>
Long leg (height) = 53 {" "}
<strong className="text-sky-800">8.66</strong>
</p>
</div>
</div>
<div className="bg-sky-50 rounded-xl p-4 border border-sky-200 text-sm">
<p className="font-semibold text-sky-800 mb-2">
Worked Example: Pythagorean Triple
</p>
<div className="font-mono text-xs text-slate-700 space-y-1">
<p>
A right triangle has legs 9 and 12. Find the hypotenuse.
</p>
<p>Recognize: 9 and 12 are multiples of 3 and 4 (× 3).</p>
<p>
This is a 3-4-5 triple × 3: hypotenuse ={" "}
<strong className="text-sky-800">15</strong>
</p>
</div>
</div>
</div>
</div>
<button
onClick={() => scrollToSection(3)}
className="group flex items-center text-emerald-600 font-bold hover:text-emerald-800"
>
Next: Polygons{" "}
<ArrowDown className="ml-2 w-5 h-5 group-hover:translate-y-1 transition-transform" />
</button>
</section>
{/* Section 4: Polygons */}
<section
ref={(el) => {
sectionsRef.current[3] = el;
}}
className="min-h-screen flex flex-col justify-center mb-24"
>
<h2 className="text-4xl font-extrabold text-slate-900 mb-6">
Polygons
</h2>
<div className="prose prose-slate text-lg text-slate-600 mb-8">
<p>
Polygon angle rules extend triangle logic any polygon can be
divided into triangles, which is where the interior angle sum
formula comes from.
</p>
</div>
<div className="bg-emerald-50 border border-emerald-200 rounded-2xl p-6 mb-8 space-y-5">
<h3 className="text-lg font-bold text-emerald-900">
Polygon Angle Formulas
</h3>
<div className="grid md:grid-cols-2 gap-4">
<div className="bg-white rounded-xl p-5 border border-emerald-200">
<p className="font-bold text-emerald-900 mb-1">
Interior Angle Sum
</p>
<div className="font-mono text-center bg-emerald-50 py-2 rounded text-emerald-700 font-bold mb-2">
(n 2) × 180°
</div>
<p className="text-xs text-slate-600">
n = number of sides. Triangle: 180° | Quadrilateral: 360° |
Pentagon: 540° | Hexagon: 720°
</p>
</div>
<div className="bg-white rounded-xl p-5 border border-emerald-200">
<p className="font-bold text-emerald-900 mb-1">
Exterior Angle Sum
</p>
<div className="font-mono text-center bg-emerald-50 py-2 rounded text-emerald-700 font-bold mb-2">
Always = 360°
</div>
<p className="text-xs text-slate-600">
True for ALL convex polygons, regardless of n. Imagine walking
around the polygon you turn a full circle.
</p>
</div>
</div>
{/* Reference table */}
<div className="bg-white rounded-xl p-5 border border-emerald-100">
<p className="font-bold text-emerald-800 mb-3">
Quick Reference: Regular Polygons
</p>
<div className="overflow-x-auto rounded-xl border border-emerald-200">
<table className="w-full text-sm border-collapse">
<thead>
<tr className="bg-emerald-900 text-white">
<th className="p-2 text-center">Polygon</th>
<th className="p-2 text-center">Sides (n)</th>
<th className="p-2 text-center">Interior Sum</th>
<th className="p-2 text-center">Each Interior Angle</th>
</tr>
</thead>
<tbody className="divide-y divide-emerald-100 text-center">
<tr className="bg-white">
<td className="p-2">Triangle</td>
<td className="p-2">3</td>
<td className="p-2">180°</td>
<td className="p-2">60°</td>
</tr>
<tr className="bg-emerald-50">
<td className="p-2">Quadrilateral</td>
<td className="p-2">4</td>
<td className="p-2">360°</td>
<td className="p-2">90°</td>
</tr>
<tr className="bg-white">
<td className="p-2">Pentagon</td>
<td className="p-2">5</td>
<td className="p-2">540°</td>
<td className="p-2">108°</td>
</tr>
<tr className="bg-emerald-50">
<td className="p-2">Hexagon</td>
<td className="p-2">6</td>
<td className="p-2">720°</td>
<td className="p-2">120°</td>
</tr>
<tr className="bg-white">
<td className="p-2">Octagon</td>
<td className="p-2">8</td>
<td className="p-2">1080°</td>
<td className="p-2">135°</td>
</tr>
</tbody>
</table>
</div>
</div>
{/* Formula for one angle */}
<div className="bg-slate-50 border border-slate-200 rounded-xl p-4 text-sm">
<p className="font-bold text-slate-800 mb-1">
Each Interior Angle of a Regular n-gon
</p>
<div className="font-mono text-center bg-white py-2 rounded text-slate-700 font-bold mb-2">
<Frac n="(n 2) × 180°" d="n" />
</div>
<p className="text-slate-600 text-xs">
Example: Regular hexagon <Frac n="(6 2) × 180°" d="6" /> ={" "}
<Frac n="720°" d="6" /> = <strong>120°</strong>
</p>
<p className="text-slate-600 text-xs mt-1">
Example: Regular octagon <Frac n="(8 2) × 180°" d="8" /> ={" "}
<Frac n="1080°" d="8" /> = <strong>135°</strong>
</p>
</div>
</div>
<PolygonWidget />
<button
onClick={() => scrollToSection(4)}
className="mt-12 group flex items-center text-emerald-600 font-bold hover:text-emerald-800"
>
Next: Practice{" "}
<ArrowDown className="ml-2 w-5 h-5 group-hover:translate-y-1 transition-transform" />
</button>
</section>
{/* Section 5: Quiz */}
<section
ref={(el) => {
sectionsRef.current[4] = el;
}}
className="min-h-screen flex flex-col justify-center"
>
<div className="flex items-center gap-4 mb-8">
<div className="p-3 bg-emerald-100 rounded-full">
<BookOpen className="w-8 h-8 text-emerald-600" />
</div>
<h2 className="text-4xl font-extrabold text-slate-900">
Practice Time
</h2>
</div>
{ANGLES_QUIZ_DATA.map((quiz, idx) => (
<div key={quiz.id} className="mb-12">
<div className="flex items-center gap-2 mb-4">
<span className="bg-slate-200 text-slate-600 text-xs font-bold px-2 py-1 rounded uppercase">
Question {idx + 1}
</span>
</div>
<Quiz data={quiz} />
</div>
))}
<div className="p-8 bg-emerald-900 rounded-2xl text-white text-center mt-12">
<h3 className="text-2xl font-bold mb-4">Topic Mastered!</h3>
<button
onClick={onFinish}
className="px-6 py-3 bg-white text-emerald-900 font-bold rounded-full hover:bg-emerald-50 transition-colors"
>
Finish Lesson
</button>
</div>
</section>
</div>
</div>
);
};
export default LinesAnglesLesson;