feat(lessons): add lessons from client db

This commit is contained in:
shafin-r
2026-03-01 20:24:14 +06:00
parent 2eaf77e13c
commit 2a00c44157
152 changed files with 74587 additions and 222 deletions

View File

@ -0,0 +1,114 @@
import React, { useState } from 'react';
const FrequencyMeanWidget: React.FC = () => {
// Data: Value -> Frequency
const [counts, setCounts] = useState({ 0: 3, 1: 5, 2: 6, 3: 4, 4: 2 });
const handleChange = (val: number, delta: number) => {
setCounts(prev => ({
...prev,
[val]: Math.max(0, (prev[val as keyof typeof prev] || 0) + delta)
}));
};
const values = [0, 1, 2, 3, 4];
const totalStudents = values.reduce((sum, v) => sum + counts[v as keyof typeof counts], 0);
const totalBooks = values.reduce((sum, v) => sum + v * counts[v as keyof typeof counts], 0);
const mean = totalStudents > 0 ? (totalBooks / totalStudents).toFixed(2) : '0';
// Calculate Median position
let cumulative = 0;
let medianVal = 0;
const mid = (totalStudents + 1) / 2;
if (totalStudents > 0) {
for (const v of values) {
cumulative += counts[v as keyof typeof counts];
if (cumulative >= mid) {
medianVal = v;
break;
}
}
}
return (
<div className="bg-white p-6 rounded-xl shadow-lg border border-slate-200">
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
{/* Table Control */}
<div>
<h4 className="font-bold text-slate-700 mb-4 flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-amber-500"></span>
Edit Frequencies
</h4>
<div className="overflow-hidden rounded-lg border border-slate-200">
<table className="w-full text-sm text-center">
<thead className="bg-slate-50 text-slate-500 font-bold uppercase">
<tr>
<th className="p-3 border-b border-r border-slate-200">Books Read</th>
<th className="p-3 border-b border-slate-200">Students (Freq)</th>
</tr>
</thead>
<tbody className="divide-y divide-slate-100">
{values.map(v => (
<tr key={v} className="group hover:bg-amber-50/50 transition-colors">
<td className="p-3 border-r border-slate-100 font-mono font-bold text-slate-700">{v}</td>
<td className="p-2 flex justify-center items-center gap-3">
<button
onClick={() => handleChange(v, -1)}
className="w-6 h-6 rounded bg-slate-100 hover:bg-slate-200 text-slate-600 font-bold flex items-center justify-center transition-colors"
>-</button>
<span className="w-4 font-mono font-bold text-slate-800">{counts[v as keyof typeof counts]}</span>
<button
onClick={() => handleChange(v, 1)}
className="w-6 h-6 rounded bg-amber-100 hover:bg-amber-200 text-amber-700 font-bold flex items-center justify-center transition-colors"
>+</button>
</td>
</tr>
))}
<tr className="bg-slate-50 font-bold text-slate-800">
<td className="p-3 border-r border-slate-200">TOTAL</td>
<td className="p-3">{totalStudents}</td>
</tr>
</tbody>
</table>
</div>
</div>
{/* Visualization & Stats */}
<div className="flex flex-col justify-between">
<div className="bg-slate-50 p-4 rounded-xl border border-slate-200 mb-6">
<h4 className="text-xs font-bold text-slate-400 uppercase mb-3">Dot Plot Preview</h4>
<div className="flex justify-between items-end h-32 px-2 pb-2 border-b border-slate-300">
{values.map(v => (
<div key={v} className="flex flex-col-reverse items-center gap-1 w-8">
{Array.from({length: counts[v as keyof typeof counts]}).map((_, i) => (
<div key={i} className="w-3 h-3 rounded-full bg-amber-500 shadow-sm"></div>
))}
</div>
))}
</div>
<div className="flex justify-between px-2 pt-2 text-xs font-mono font-bold text-slate-500">
{values.map(v => <span key={v} className="w-8 text-center">{v}</span>)}
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="p-4 bg-indigo-50 border border-indigo-100 rounded-lg">
<p className="text-xs font-bold text-indigo-400 uppercase">Weighted Mean</p>
<p className="text-2xl font-bold text-indigo-700">{mean}</p>
<p className="text-[10px] text-indigo-400 mt-1">Total Books ({totalBooks}) / Students ({totalStudents})</p>
</div>
<div className="p-4 bg-emerald-50 border border-emerald-100 rounded-lg">
<p className="text-xs font-bold text-emerald-400 uppercase">Median</p>
<p className="text-2xl font-bold text-emerald-700">{medianVal}</p>
<p className="text-[10px] text-emerald-400 mt-1">Middle Position (~{mid.toFixed(1)})</p>
</div>
</div>
</div>
</div>
</div>
);
};
export default FrequencyMeanWidget;