Files
edbridge-scholars/src/pages/student/lessons/LinearParallelPerpendicularLesson.tsx
2026-03-01 20:24:14 +06:00

351 lines
14 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, BookOpen, Layers } from "lucide-react";
import ParallelPerpendicularWidget from "../../../components/lessons/ParallelPerpendicularWidget";
import Quiz from "../../../components/lessons/Quiz";
import { LINEAR_PARALLEL_PERP_QUIZ_DATA } from "../../../utils/constants";
import { Frac } from "../../../components/Math";
interface LessonProps {
onFinish?: () => void;
}
const LinearParallelPerpendicularLesson: 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-blue-100" : "hover:bg-slate-100"}`}
>
<div
className={`w-8 h-8 rounded-full flex items-center justify-center shrink-0 ${isActive ? "bg-blue-600 text-white" : isPast ? "bg-blue-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-blue-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 z-0 hidden lg:block">
<nav className="space-y-2">
<SectionMarker
index={0}
title="Parallel & Perpendicular"
icon={Layers}
/>
<SectionMarker index={1} 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 */}
<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 & Perpendicular Lines
</h2>
<div className="prose prose-slate text-lg text-slate-600 mb-8">
<p>
Parallel and perpendicular line questions appear on almost every
SAT. The core skill is: identify the slope of the given line,
apply the parallel or perpendicular slope rule, then write the new
equation through a given point.
</p>
</div>
<div className="bg-blue-50 border border-blue-200 rounded-2xl p-6 mb-8 space-y-5">
<h3 className="text-lg font-bold text-blue-900">
The Two Slope Rules
</h3>
<div className="grid md:grid-cols-2 gap-4">
<div className="bg-white rounded-xl p-5 border border-blue-100">
<p className="font-bold text-blue-900 mb-3 text-lg">
Parallel Lines
</p>
<div className="bg-blue-50 rounded-lg p-3 text-center mb-3">
<p className="font-mono text-blue-800 font-bold text-xl">
m = m
</p>
<p className="text-xs text-slate-500 mt-1">
Same slope, different y-intercept
</p>
</div>
<ul className="text-slate-600 text-sm space-y-1 list-disc list-inside">
<li>Lines never intersect they run side by side</li>
<li>Same slope guarantees they won't cross</li>
<li>
If y-intercepts also matched, the lines would be identical
</li>
</ul>
<div className="mt-3 bg-blue-50 rounded-lg p-2 font-mono text-xs text-slate-600">
y = 3x + 1 y = 3x 7 (both slope = 3)
</div>
</div>
<div className="bg-white rounded-xl p-5 border border-blue-100">
<p className="font-bold text-indigo-900 mb-3 text-lg">
Perpendicular Lines
</p>
<div className="bg-indigo-50 rounded-lg p-3 text-center mb-3">
<p className="font-mono text-indigo-800 font-bold text-xl">
m × m = 1
</p>
<p className="text-xs text-slate-500 mt-1">
Negative reciprocal slopes
</p>
</div>
<ul className="text-slate-600 text-sm space-y-1 list-disc list-inside">
<li>Lines meet at a 90° angle</li>
<li>Rule: flip the fraction and change the sign</li>
<li>
A horizontal line (slope 0) is to a vertical line
(undefined slope)
</li>
</ul>
<div className="mt-3 bg-indigo-50 rounded-lg p-2 font-mono text-xs text-slate-600">
y = <Frac n="2" d="3" />x + 1 y = <Frac n="3" d="2" />x + 5
</div>
</div>
</div>
{/* Negative Reciprocal Examples */}
<div className="bg-white rounded-xl p-5 border border-blue-100">
<p className="font-bold text-blue-800 mb-3">
Finding Perpendicular Slopes: Worked Examples
</p>
<div className="overflow-x-auto">
<table className="w-full text-sm border-collapse">
<thead>
<tr className="bg-blue-100 text-blue-900">
<th className="p-2 text-left font-bold">
Original Slope
</th>
<th className="p-2 text-left font-bold">
Step 1: Flip the fraction
</th>
<th className="p-2 text-left font-bold">
Step 2: Negate the sign
</th>
<th className="p-2 text-left font-bold">
Perpendicular Slope
</th>
</tr>
</thead>
<tbody className="text-slate-600">
<tr className="border-b border-blue-50">
<td className="p-2 font-mono">2 (= 2÷1)</td>
<td className="p-2">
<Frac n="1" d="2" />
</td>
<td className="p-2">
<Frac n="1" d="2" />
</td>
<td className="p-2 font-bold text-indigo-700">
<Frac n="1" d="2" />
</td>
</tr>
<tr className="border-b border-blue-50 bg-slate-50">
<td className="p-2">
<Frac n="3" d="4" />
</td>
<td className="p-2">
<Frac n="4" d="3" />
</td>
<td className="p-2">
<Frac n="4" d="3" />
</td>
<td className="p-2 font-bold text-indigo-700">
<Frac n="4" d="3" />
</td>
</tr>
<tr className="border-b border-blue-50">
<td className="p-2 font-mono">5</td>
<td className="p-2">
<Frac n="1" d="5" /> (flip)
</td>
<td className="p-2">
<Frac n="1" d="5" /> (negate negative)
</td>
<td className="p-2 font-bold text-indigo-700">
<Frac n="1" d="5" />
</td>
</tr>
<tr className="bg-slate-50">
<td className="p-2 font-mono">0 (horizontal)</td>
<td className="p-2 font-mono"></td>
<td className="p-2 font-mono"></td>
<td className="p-2 font-bold text-indigo-700">
Undefined (vertical)
</td>
</tr>
</tbody>
</table>
</div>
</div>
{/* Full Problem Worked Examples */}
<div className="bg-white rounded-xl p-5 border border-blue-100">
<p className="font-bold text-blue-800 mb-3">
Complete Problem: Writing the Equation
</p>
<div className="space-y-4">
<div className="bg-blue-50 rounded-lg p-4 text-sm">
<p className="font-semibold text-blue-800 mb-2">
Example 1: Find the line parallel to y = 4x 3 passing
through (2, 5)
</p>
<div className="font-mono space-y-1 text-slate-700">
<p>Parallel same slope: m = 4</p>
<p>Use point-slope: y 5 = 4(x 2)</p>
<p>y 5 = 4x 8</p>
<p className="text-blue-700 font-bold">
y = 4x 3 &nbsp; Wait, same as original! Confirm: passes
through (2, 5): 5 = 8 3 = 5
</p>
</div>
</div>
<div className="bg-indigo-50 rounded-lg p-4 text-sm">
<p className="font-semibold text-indigo-800 mb-2">
Example 2: Find the line perpendicular to 2x + 3y = 12
passing through (4, 1)
</p>
<div className="font-mono space-y-1 text-slate-700">
<p>
First, find slope of 2x + 3y = 12: y ={" "}
<Frac n="2" d="3" />x + 4, so m = <Frac n="2" d="3" />
</p>
<p>
Perpendicular slope: flip and negate m ={" "}
<Frac n="3" d="2" />
</p>
<p>
Point-slope: y 1 = <Frac n="3" d="2" />
(x 4)
</p>
<p>
y = <Frac n="3" d="2" />x 6 + 1
</p>
<p className="text-indigo-700 font-bold">
y = <Frac n="3" d="2" />x 5
</p>
</div>
</div>
</div>
</div>
<div className="bg-red-50 border border-red-200 rounded-xl p-4 text-sm">
<p className="font-bold text-red-800 mb-1">
SAT Trap: Parallel Lines Must Have Different Intercepts
</p>
<p className="text-slate-700">
Parallel lines need the <em>same slope</em> but a{" "}
<em>different y-intercept</em>. If the intercepts also match,
the lines are identical infinitely many intersections, not
parallel. The SAT sometimes includes a "same slope, same
intercept" option to trap students.
</p>
</div>
</div>
<ParallelPerpendicularWidget />
<button
onClick={() => scrollToSection(1)}
className="mt-12 group flex items-center text-blue-600 font-bold hover:text-blue-800 transition-colors"
>
Next: Practice Quiz{" "}
<ArrowDown className="ml-2 w-5 h-5 group-hover:translate-y-1 transition-transform" />
</button>
</section>
{/* Section 2: Quiz */}
<section
ref={(el) => {
sectionsRef.current[1] = el;
}}
className="min-h-screen flex flex-col justify-center"
>
<h2 className="text-4xl font-extrabold text-slate-900 mb-8">
Practice Time
</h2>
{LINEAR_PARALLEL_PERP_QUIZ_DATA.map((quiz, idx) => (
<div key={quiz.id} className="mb-12">
<Quiz data={quiz} />
</div>
))}
<div className="p-8 bg-blue-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-blue-900 font-bold rounded-full hover:bg-blue-50 transition-colors"
>
Finish Lesson
</button>
</div>
</section>
</div>
</div>
);
};
export default LinearParallelPerpendicularLesson;