feat(lessons): add lessons from client db
This commit is contained in:
93
src/components/lessons/SlopeInterceptWidget.tsx
Normal file
93
src/components/lessons/SlopeInterceptWidget.tsx
Normal file
@ -0,0 +1,93 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const SlopeInterceptWidget: React.FC = () => {
|
||||
const [m, setM] = useState(2);
|
||||
const [b, setB] = useState(1);
|
||||
|
||||
// Visualization config
|
||||
const range = 10;
|
||||
const scale = 25; // px per unit
|
||||
const center = 150;
|
||||
|
||||
const toPx = (val: number, isY = false) => isY ? center - val * scale : center + val * scale;
|
||||
|
||||
// Points for triangle
|
||||
const p1 = { x: 0, y: b };
|
||||
const p2 = { x: 1, y: m * 1 + b };
|
||||
// Triangle vertex (1, b)
|
||||
const p3 = { x: 1, y: b };
|
||||
|
||||
return (
|
||||
<div className="bg-white p-6 rounded-xl shadow-lg border border-slate-200">
|
||||
<div className="flex flex-col md:flex-row gap-8">
|
||||
<div className="w-full md:w-1/3 space-y-6">
|
||||
<div className="p-4 bg-slate-50 rounded-xl border border-slate-200 text-center">
|
||||
<div className="text-sm text-slate-500 font-bold uppercase mb-1">Equation</div>
|
||||
<div className="text-2xl font-mono font-bold text-slate-800">
|
||||
y = <span className="text-blue-600">{m}</span>x + <span className="text-rose-600">{b}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="text-xs font-bold text-blue-600 uppercase">Slope (m) = {m}</label>
|
||||
<input
|
||||
type="range" min="-5" max="5" step="0.5"
|
||||
value={m} onChange={e => setM(parseFloat(e.target.value))}
|
||||
className="w-full h-2 bg-blue-100 rounded-lg appearance-none cursor-pointer accent-blue-600 mt-2"
|
||||
/>
|
||||
<p className="text-xs text-slate-400 mt-1">Rate of Change (Rise / Run)</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="text-xs font-bold text-rose-600 uppercase">Y-Intercept (b) = {b}</label>
|
||||
<input
|
||||
type="range" min="-5" max="5" step="1"
|
||||
value={b} onChange={e => setB(parseFloat(e.target.value))}
|
||||
className="w-full h-2 bg-rose-100 rounded-lg appearance-none cursor-pointer accent-rose-600 mt-2"
|
||||
/>
|
||||
<p className="text-xs text-slate-400 mt-1">Starting Value (when x=0)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full md:flex-1 h-[300px] bg-white border border-slate-200 rounded-xl relative overflow-hidden">
|
||||
<svg width="100%" height="100%" viewBox="0 0 300 300" className="absolute top-0 left-0">
|
||||
<defs>
|
||||
<pattern id="si-grid" width={scale} height={scale} patternUnits="userSpaceOnUse">
|
||||
<path d={`M ${scale} 0 L 0 0 0 ${scale}`} fill="none" stroke="#f1f5f9" strokeWidth="1"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="url(#si-grid)" />
|
||||
|
||||
{/* Axes */}
|
||||
<line x1="0" y1={center} x2="300" y2={center} stroke="#cbd5e1" strokeWidth="2" />
|
||||
<line x1={center} y1="0" x2={center} y2="300" stroke="#cbd5e1" strokeWidth="2" />
|
||||
|
||||
{/* The Line */}
|
||||
<line
|
||||
x1={toPx(-range)} y1={toPx(m * -range + b, true)}
|
||||
x2={toPx(range)} y2={toPx(m * range + b, true)}
|
||||
stroke="#1e293b" strokeWidth="3"
|
||||
/>
|
||||
|
||||
{/* Slope Triangle (between x=0 and x=1) */}
|
||||
<path
|
||||
d={`M ${toPx(p1.x)} ${toPx(p1.y, true)} L ${toPx(p3.x)} ${toPx(p3.y, true)} L ${toPx(p2.x)} ${toPx(p2.y, true)} Z`}
|
||||
fill="rgba(37, 99, 235, 0.1)" stroke="#2563eb" strokeWidth="1" strokeDasharray="4,2"
|
||||
/>
|
||||
|
||||
{/* Intercept Point */}
|
||||
<circle cx={toPx(0)} cy={toPx(b, true)} r="5" fill="#e11d48" stroke="white" strokeWidth="2" />
|
||||
<text x={toPx(0) + 10} y={toPx(b, true)} className="text-xs font-bold fill-rose-600">b={b}</text>
|
||||
|
||||
{/* Rise/Run Labels */}
|
||||
<text x={toPx(0.5)} y={toPx(b, true) + (m>0 ? 15 : -10)} textAnchor="middle" className="text-[10px] font-bold fill-blue-400">Run: 1</text>
|
||||
<text x={toPx(1) + 5} y={toPx(b + m/2, true)} className="text-[10px] font-bold fill-blue-600">Rise: {m}</text>
|
||||
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SlopeInterceptWidget;
|
||||
Reference in New Issue
Block a user