Files
edbridge-scholars/src/pages/student/lessons/EBRWCraftStructureLesson.tsx
2026-03-12 02:39:34 +06:00

310 lines
14 KiB
TypeScript

import React, { useRef, useState, useEffect } from "react";
import { ArrowDown, Check, BookOpen, AlertTriangle, Zap } from "lucide-react";
import EvidenceHunterWidget, {
type EvidenceExercise,
} from "../../../components/lessons/EvidenceHunterWidget";
import { PracticeFromDataset } from "../../../components/lessons/LessonShell";
import {
TEXT_STRUCTURE_EASY,
TEXT_STRUCTURE_MEDIUM,
} from "../../../data/rw/text-structure-purpose";
interface LessonProps {
onFinish?: () => void;
}
const EVIDENCE_EXERCISES: EvidenceExercise[] = [
{
question: "What is the primary purpose of sentence 4 in this passage?",
passage: [
"Automation has already transformed manufacturing, eliminating millions of repetitive assembly-line jobs over the past three decades.",
"Optimists argue that, just as industrialization created new types of work, AI will generate new categories of employment.",
"Economists at the Brookings Institution project that 36 million American jobs face high exposure to automation within the next decade.",
"Yet history offers a cautionary note: the transition from agricultural to industrial economies, though ultimately beneficial, caused decades of widespread unemployment and social upheaval.",
"Without deliberate policy intervention, the current transition may prove equally disruptive.",
],
evidenceIndex: 3,
explanation:
'Sentence 4 serves to qualify and complicate the optimists\' argument in sentence 2 — it concedes that historical transitions were ultimately beneficial, but shows they were also extremely disruptive. This is a "concession and complication" move. On the SAT, look for words like "yet," "however," "though" that signal this function.',
},
{
question:
"Which sentence most clearly establishes the author's central perspective in this passage?",
passage: [
"In 1905, Einstein published four papers that would revolutionize physics.",
"Among them was the special theory of relativity, which overturned Newtonian mechanics that had stood unchallenged for over 200 years.",
"Physicists at the time were deeply skeptical — the implications were simply too radical to accept without extensive verification.",
"Science, at its best, is not a collection of fixed truths but an evolving conversation shaped by evidence, argument, and the occasional genius willing to question everything.",
"Einstein's annus mirabilis remains the most dramatic example of this process in modern science.",
],
evidenceIndex: 3,
explanation:
"Sentence 4 is where the author steps back from narrating events to state their own perspective on what science is: an evolving conversation. This is a craft move — transitioning from historical account to authorial commentary. The SAT often places the author's stated viewpoint in the middle or end of a passage, not the beginning.",
},
{
question: "What is the structural function of sentence 2 in this passage?",
passage: [
"Digital misinformation spreads with unprecedented speed on social media platforms.",
"A landmark MIT study found that false news spreads six times faster on Twitter than true news.",
"The researchers attribute this difference to the novelty and emotional resonance of misinformation — falsehoods are simply more surprising and engaging than accurate reporting.",
"This poses serious challenges for democracies that depend on an informed citizenry.",
"Platform companies and legislators are still struggling to find effective interventions.",
],
evidenceIndex: 1,
explanation:
"Sentence 2 provides specific quantitative evidence (the MIT study) to support the claim made in sentence 1. Its function is to substantiate — to give a concrete, credible example that proves the opening assertion. On SAT craft questions, sentences that cite studies, statistics, or expert sources typically function as evidence or support.",
},
];
const EBRWCraftStructureLesson: React.FC<LessonProps> = ({ onFinish }) => {
const [activeSection, setActiveSection] = useState(0);
const sectionsRef = useRef<(HTMLElement | null)[]>([]);
useEffect(() => {
const observers: IntersectionObserver[] = [];
sectionsRef.current.forEach((el, idx) => {
if (!el) return;
const obs = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) setActiveSection(idx);
},
{ threshold: 0.3 },
);
obs.observe(el);
observers.push(obs);
});
return () => observers.forEach((o) => o.disconnect());
}, []);
const scrollToSection = (i: number) => {
setActiveSection(i);
sectionsRef.current[i]?.scrollIntoView({ behavior: "smooth" });
};
const SectionMarker = ({
index,
title,
icon: Icon,
}: {
index: number;
title: string;
icon: React.ComponentType<React.SVGProps<SVGSVGElement>>;
}) => {
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 text-left transition-all ${isActive ? "bg-fuchsia-50" : "hover:bg-slate-50"}`}
>
<div
className={`w-8 h-8 rounded-full flex items-center justify-center shrink-0 ${isActive ? "bg-fuchsia-600 text-white" : isPast ? "bg-fuchsia-400 text-white" : "bg-slate-200 text-slate-500"}`}
>
{isPast ? (
<Check className="w-4 h-4" />
) : (
<Icon className="w-4 h-4" />
)}
</div>
<p
className={`text-sm font-bold ${isActive ? "text-fuchsia-900" : "text-slate-600"}`}
>
{title}
</p>
</button>
);
};
return (
<div className="flex flex-col lg:flex-row min-h-screen">
<aside className="w-full lg:w-64 lg:fixed lg:top-14 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 pt-6">
<SectionMarker index={0} title="Craft & Purpose" icon={BookOpen} />
<SectionMarker
index={1}
title="Evidence Hunter"
icon={AlertTriangle}
/>
<SectionMarker index={2} title="Practice Quiz" icon={Zap} />
</nav>
</aside>
<div className="flex-1 lg:ml-64 p-6 md:p-12 max-w-4xl mx-auto">
{/* Section 0: Craft & Purpose */}
<section
ref={(el) => {
sectionsRef.current[0] = el;
}}
className="min-h-screen flex flex-col justify-center mb-24 pt-20 lg:pt-0"
>
<div className="inline-flex items-center gap-2 bg-fuchsia-100 text-fuchsia-700 px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wider mb-4">
Craft &amp; Structure
</div>
<h2 className="text-4xl font-extrabold text-slate-900 mb-2">
Craft &amp; Purpose
</h2>
<p className="text-lg text-slate-500 mb-8">
SAT craft questions ask WHY the author made a choice not WHAT the
text says. Master the four analytical lenses below to handle every
question type.
</p>
{/* Rule Grid */}
<div className="rounded-2xl p-6 mb-8 bg-fuchsia-50 border border-fuchsia-200 space-y-5">
<h3 className="text-lg font-bold text-fuchsia-900">
Four Analytical Lenses
</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{[
{
title: "Author's Purpose",
body: "Why did the author include THIS paragraph, sentence, or detail? Options: to introduce, contrast, provide evidence, concede, qualify, or conclude.",
},
{
title: "Transition Function",
body: "What does this sentence DO in relation to what came before? Contrast? Continuation? Consequence?",
},
{
title: "Point of View",
body: "What is the narrator's or author's perspective? First person (I/we) vs. third person (objective or omniscient).",
},
{
title: "Rhetorical Effect",
body: "How does the author create impact? Through analogy, anecdote, expert citation, rhetorical question, or repetition?",
},
].map((rule, i) => (
<div
key={i}
className="bg-white rounded-xl p-4 border border-fuchsia-100"
>
<p className="text-sm font-bold text-fuchsia-800 mb-1">
{rule.title}
</p>
<p className="text-xs text-slate-600 leading-relaxed">
{rule.body}
</p>
</div>
))}
</div>
</div>
{/* Static annotation visual */}
<div className="rounded-2xl p-6 mb-8 bg-fuchsia-50 border border-fuchsia-200 space-y-3">
<h3 className="text-lg font-bold text-fuchsia-900 mb-1">
How to Annotate a Craft Question
</h3>
<div className="bg-fuchsia-100 rounded-xl p-4 border border-fuchsia-200">
<p className="text-xs font-bold text-fuchsia-800 mb-1">
Question type:
</p>
<p className="text-sm text-fuchsia-900">
"The main purpose of the third paragraph is to..."
</p>
</div>
<div className="bg-green-100 rounded-xl p-4 border border-green-200">
<p className="text-xs font-bold text-green-800 mb-1">Strategy:</p>
<p className="text-sm text-green-900">
Read the paragraph. Then ask: does it introduce an idea, provide
evidence, counter an argument, or conclude?
</p>
</div>
<div className="bg-orange-100 rounded-xl p-4 border border-orange-200">
<p className="text-xs font-bold text-orange-800 mb-1">Trap:</p>
<p className="text-sm text-orange-900">
Confusing a detail's FUNCTION with its CONTENT. "To describe X"
is content. "To provide evidence for the claim in paragraph 2"
is function.
</p>
</div>
</div>
{/* Trap callout */}
<div className="bg-red-50 border border-red-200 rounded-xl p-5 mb-8">
<p className="text-sm font-bold text-red-800 mb-1">
SAT Craft Question Trap
</p>
<p className="text-sm text-slate-700">
SAT craft questions ask WHY the author made a choice, not WHAT the
text says. Always frame your thinking in terms of author intent.
</p>
</div>
{/* Golden Rule */}
<div className="bg-fuchsia-900 rounded-2xl p-6 mb-8">
<p className="text-xs font-bold text-fuchsia-300 uppercase tracking-wider mb-2">
Golden Rule
</p>
<p className="text-base font-bold text-white">
Every element has a structural job. Identify it: introduce,
evidence, concede, contrast, conclude, qualify, or illustrate.
</p>
</div>
<button
onClick={() => scrollToSection(1)}
className="mt-4 group flex items-center text-fuchsia-600 font-bold hover:text-fuchsia-800 transition-colors"
>
Next: Evidence Hunter{" "}
<ArrowDown className="ml-2 w-5 h-5 group-hover:translate-y-1 transition-transform" />
</button>
</section>
{/* Section 1: Evidence Hunter */}
<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-2">
Evidence Hunter
</h2>
<p className="text-lg text-slate-500 mb-8">
Read each passage. Identify the sentence that serves the stated
structural purpose, then reveal the explanation.
</p>
<EvidenceHunterWidget
exercises={EVIDENCE_EXERCISES}
accentColor="fuchsia"
/>
<button
onClick={() => scrollToSection(2)}
className="mt-12 group flex items-center text-fuchsia-600 font-bold hover:text-fuchsia-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: Practice Quiz */}
<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">
Practice Quiz
</h2>
{TEXT_STRUCTURE_EASY.slice(0, 2).map((q) => (
<PracticeFromDataset key={q.id} question={q} color="fuchsia" />
))}
{TEXT_STRUCTURE_MEDIUM.slice(0, 1).map((q) => (
<PracticeFromDataset key={q.id} question={q} color="fuchsia" />
))}
<div className="mt-8 text-center">
<button
onClick={onFinish}
className="px-6 py-3 bg-fuchsia-900 text-white font-bold rounded-full hover:bg-fuchsia-700 transition-colors"
>
Finish Lesson
</button>
</div>
</section>
</div>
</div>
);
};
export default EBRWCraftStructureLesson;