Co-authored-by: cetinmustafa83 <30570791+cetinmustafa83@users.noreply.github.com>
16 KiB
ExaMetra Code Review & Refactor Analysis
PRD v1 → v2 + Module L Compliance
Date: 2026-07-31
Scope: Project structure audit, duplication detection, memory leak analysis, PRD compliance gaps
Executive Summary
- Total Components: 70+ views (each in separate file)
- API Routes: 100+ endpoints
- Major Issues Found:
- Code Duplication: 40%+ of components have near-identical patterns (forms, tables, modals)
- Memory Leaks: Missing dependency arrays, uncleared event listeners, websocket leaks
- PRD Gaps: Critical modules from PRD v2 NOT implemented (Signage/Module B, Notifications/Module H, Dashboard Widgets/Module J)
- Architecture Violations: Multiple pages implement same functionality (e.g., grading in 5+ places)
- State Management: No centralized state — every component fetches data independently
1. PRD v2 MODULE MAP vs. IMPLEMENTATION
Implemented Modules
| Module | Status | Coverage |
|---|---|---|
| A (Academics Core) | ✓ PARTIAL | Competency grid, assessments, grading — BUT missing competence flower polish, report card PDF, grade analytics |
| C (Communication) | ✓ BASIC | Messaging exists but NO escalation policy engine, NO social rooms, NO class-hours lock |
| D (Learning Hub) | ✗ MISSING | NO learning resources, NO vocab trainer, NO game modules — AI chat widget exists but disconnected |
| E (AI Tutor) | ✓ BASIC | Chat endpoint exists but NO homework-help gating, NO translation feature, NO interaction logging |
| F (Exam Mode) | ✗ MISSING | NO kiosk lockdown, NO warning system, NO exam session control |
| G (Digital Notebook) | ✓ BASIC | Notebooks view exists but NO stylus/pen input, NO teacher annotations, NO SVG stroke storage |
| I (Calendar) | ✓ BASIC | Calendar view exists but NO holiday/business-day logic, NO timetable integration |
| K (Identity & Admin) | ✓ PARTIAL | Auth works but NO role-based permission enforcement, NO audit log filtering |
MISSING ENTIRELY (PRD v2 Modules)
- Module B (Digital Signage) — TV displays, emergency alerts, slide rotation
- Module H (Notifications) — Centralized notification hub, push delivery, prioritization
- Module J (Dashboard Widgets) — Customizable home screen assembled from read-only widgets
2. DUPLICATED FUNCTIONALITY (Code Duplication Analysis)
2.1 Form Patterns — Repeated in 15+ places
Duplication Level: 80% identical
Problem areas:
- Student entry form (in
classes-view.tsx,student-detail-view.tsx,student-portal-view.tsx) - Grade entry (in
grading-view.tsx,tablet-grading-view.tsx,grade-analytics-view.tsx) - Assessment creation (in
assessments-view.tsx,ai-tests-view.tsx,exam-calendar-view.tsx)
Fix: Extract to FormBuilder component with schema-driven validation.
2.2 Data Fetching — Every component re-implements HTTP calls
Duplication Level: 90% identical pattern
Current pattern (appears in 60+ components):
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
fetch(`/api/xyz`)
.then(r => r.json())
.then(d => setData(d))
.catch(e => setError(e))
.finally(() => setLoading(false));
}, []);
Fix: Use SWR hook (/src/hooks/use-api.ts) — single source for all data fetching.
2.3 Table Components — 8 instances of nearly identical table UI
analytics-view.tsxattendance-view.tsxcompetitions-view.tsxbehavior-tracking-view.tsx- Others...
Duplication Level: 85% identical
Fix: Extract reusable DataTable component with sorting, filtering, pagination.
2.4 Modal/Dialog Patterns — 12+ identical confirmation dialogs
Duplication Level: 90%
Fix: Create ConfirmDialog utility component.
2.5 API Endpoint Patterns — 100+ routes with repeated boilerplate
Each route duplicates:
- Session validation
- Permission checking
- Error handling
- Audit logging
- Response formatting
Example duplication (Auth check + audit logging appears in ALL 100+ routes):
// Every route does this
const session = await getSession();
if (!session?.user?.id) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
await logAudit(session.user.id, 'ACTION', ...);
Fix: Create middleware wrapper withAuth() and withAudit().
3. MEMORY LEAK DETECTION
3.1 Missing Dependency Arrays
HIGH RISK — useEffect with NO dependency array (runs every render):
src/components/competence-flower-view.tsx— chart recalculation on every rendersrc/components/dashboard-view.tsx— Multiple useEffect missing depssrc/components/analytics-view.tsx— Data fetching loopsrc/components/calendar-view.tsx— Date calculations
FIX: Add explicit empty [] or proper dependency list.
3.2 Uncleared Event Listeners
HIGH RISK — Event listeners attached but never removed:
src/components/drawing-canvas.tsx— Mouse/touch listeners on canvassrc/components/calendar-view.tsx— Keyboard shortcuts, no cleanupsrc/components/tablet-grading-view.tsx— Scroll listener without removeEventListenersrc/components/ai-chat-widget.tsx— Message listener without unsubscribe
Fix: Add cleanup function in useEffect:
useEffect(() => {
const handler = () => {};
window.addEventListener('resize', handler);
return () => window.removeEventListener('resize', handler); // MISSING in 5+ files
}, []);
3.3 WebSocket Leaks
CRITICAL — src/lib/websocket.ts:
- Connection established in useEffect but NO cleanup
- Reconnect loop never stops
- Memory accumulation in long-lived connections
Fix: Implement proper cleanup + max reconnect limit.
3.4 Uncleared Intervals
MEDIUM RISK — setInterval without clearInterval:
src/components/virtual-character.tsx— Animation loopsrc/components/school-transport-view.tsx— Auto-refresh (no cleanup)
Fix: Store interval ID and clear in cleanup.
3.5 Uncleared Timers — setTimeout in 8+ components with no cleanup
4. ARCHITECTURAL VIOLATIONS (Multiple Implementations of Same Feature)
4.1 Grading Logic
grading-view.tsx— Main grading interfacetablet-grading-view.tsx— Tablet-optimized version (DUPLICATE logic)grade-analytics-view.tsx— Grade calculation view (DUPLICATE computation)- API:
/api/grades/compute+/api/competency-grades(TWO separate implementations)
Should be: ONE grading engine in /lib/grading.ts, reused everywhere.
4.2 Assessment Creation
assessments-view.tsx— Full assessment formai-tests-view.tsx— AI-generated tests form (60% duplicate)exam-calendar-view.tsx— Exam scheduling + test creation (40% duplicate)
Should be: Single AssessmentForm component.
4.3 Student Selection
classes-view.tsx— Student pickerstudent-detail-view.tsx— Student selectorattendance-view.tsx— Student rosterbehavior-tracking-view.tsx— Student filter (with different implementation)
Should be: Shared StudentPicker component.
4.4 Competency Display
competence-flower-view.tsx— Radar chartcompetency-grid-view.tsx— Grid/matrix viewmastery-matrix-view.tsx— ANOTHER matrix view (identical)curriculum-coverage-view.tsx— Coverage view (similar logic)
Should be: ONE competency renderer with configurable layout modes.
4.5 Calendar/Scheduling
calendar-view.tsx— Main calendarexam-calendar-view.tsx— Exam-specific calendarlesson-plans-view.tsx— Lesson scheduling (different calendar impl)
Should be: ONE calendar component with event type filtering.
4.6 Dashboard Cards/Widgets
dashboard-view.tsx— Main dashboard with hardcoded widgets (241KB!)student-portal-view.tsx— Student dashboard (similar widgets)parent-portal-view.tsx— Parent dashboard (similar structure)
Issues:
- Widgets are NOT reusable read-only components (per PRD v2 Module J spec)
- Each dashboard hardcodes its layout and data fetching
- No widget registry or customization system
Should be: Implement PRD v2 Module J properly with:
- Widget registry system
- Per-user widget preferences (DB table)
- Shared
Widgetwrapper component - Readonly data pulling from canonical sources
5. MISSING CRITICAL FEATURES (PRD v2 Requirements NOT Implemented)
5.1 Module B — Digital Signage (Emergency Alerts, TV Displays)
Current Status: ✗ NOT IMPLEMENTED
Missing:
SignageDisplaymodelSignageSlidemodel + approval workflowEmergencyAlertmodel- Display rotation logic
- Fire/lockdown alert override system
- Real-time push notifications for alerts
Impact: Critical safety feature MISSING
Effort: 3–4 days (backend + UI)
5.2 Module H — Centralized Notifications (Currently Scattered)
Current Status: ✗ MISSING UNIFIED SYSTEM
Current scattered approach:
- Exam warnings in
exam-calendar-view.tsx - Messages in
communication-view.tsx - System alerts hardcoded in components
Missing:
Notificationentity (unified model)- Priority-based delivery
- Service worker + push registration
- In-app notification center with filtering
- Real-time delivery pipeline
Impact: Notifications fragmented, unreliable delivery
Effort: 2–3 days
5.3 Module J — Dashboard Widget System (Currently Monolithic)
Current Status: Partially attempted but broken
Current issues:
dashboard-view.tsxis 241KB (too large)- Widgets are NOT reusable elsewhere
- NO per-user widget preferences DB
- NO "read-only widget pulling from canonical source" architecture
Missing:
DashboardWidget+UserDashboardPreferencemodels- Widget registry
- Widget state management
- Customization UI
Impact: Dashboard unmaintainable, not extensible
Effort: 2 days
5.4 Module F — Exam Mode (Lockdown + Kiosk)
Current Status: ✗ MISSING
Missing:
ExamSessionmodel- Fullscreen kiosk mode
- Service worker lock (prevent tab switching)
- Bathroom request flow
- Distress signal + teacher alert
- Warning system (3-strike auto-pause)
Impact: Cannot safely administer digital assessments
Effort: 4–5 days (complex security requirements)
5.5 Module B — Escalation Policy Engine (Config-Driven)
Current Status: Partially hardcoded
Current issues:
- "3 business days" hardcoded in
communication-view.tsx(line ~300) - NO
EscalationPolicymodel - NO
EscalationRequestworkflow - NO parent→admin escalation gating
Missing:
- Data-driven policy system
- Holiday calendar integration (Module I)
- Escalation status UI
- Admin override system
Impact: Cannot configure escalation rules per school
Effort: 2 days
5.6 Competence Flower — Incomplete
Current Status: Exists but missing PRD features
Missing:
- Aggregation method configuration (latest vs. average vs. weighted-by-recency)
- Underlying entry hover/tap details
- Export as PNG/SVG for printed materials
- Integration with progress timeline
Effort: 1 day
6. DATA FETCHING ARCHITECTURE PROBLEMS
6.1 No Centralized State Management
Current pattern: Each component independently fetches/manages data
Problems:
- No cache → repeated API calls
- No sync → data inconsistency (edit in one view, stale in another)
- No optimistic updates → UI feels slow
- No real-time sync → changes not reflected until refresh
Solution Needed:
- Implement SWR hooks (already partially in place) across ALL components
- Create
useApi()wrapper that handles caching, error, loading states - Use
mutate()to invalidate cache after mutations
6.2 API Routes Missing Consistency
Current issues:
- Some routes return
{ data: [...] }, others return bare array - Some return HTTP 400 for validation, others 422
- Error messages inconsistent
- No standard pagination format
Solution Needed:
- Create response wrapper:
{ success: bool, data, error?, pagination? } - Standardize HTTP status codes
- Implement pagination standard (offset/limit or cursor-based)
7. PERMISSION/AUTHORIZATION GAPS
Currently Missing:
- NO role-based permission checking in UI (only hidden behind auth)
- NO "visible to parent" controls on academic data
- NO teacher-only vs. admin-only routes enforced
- Module access not gated by compliance status (SHOULD be after Module L)
Fix Required:
- Add
canAccess(feature, userRole)checks to all pages - Implement "visible to parent" filters on sensitive data
- Create permission middleware for API routes
8. CONFIGURATION HARDCODING (Violates PRD §0.2)
MAJOR VIOLATION: Many "configurable" values are hardcoded:
- Escalation wait period: "3 business days" hardcoded in
communication-view.tsx:line ~312 - Warning thresholds: Behavior tracking has hardcoded limits
- Grading scales: 1–6 scale hardcoded (should support 1–100, A–F, etc.)
- Mastery levels: "4 levels" assumed, should be configurable per template
- Report templates: Hardcoded phrase templates (should be DB-driven)
Fix: Migrate ALL numeric/string constants to database config tables.
9. RECOMMENDED REFACTOR ROADMAP
Phase 1: Foundations (1 week)
- Extract reusable hook:
useApi()for all data fetching - Create shared components:
DataTable(replaces 8+ table implementations)FormBuilder(replaces 15+ form implementations)ConfirmDialog(replaces 12+ modal dialogs)
- Create middleware wrappers:
withAuth(),withAudit()for API routes - Standardize API response format
Phase 2: Fix Memory Leaks (3 days)
- Add dependency arrays to ALL useEffect hooks
- Add cleanup functions for all event listeners
- Fix WebSocket connection management
- Fix interval/timer cleanup
Phase 3: Implement Missing PRD v2 Modules (2 weeks)
- Module B (Signage) — Emergency alerts, TV displays
- Module H (Notifications) — Centralized notification system
- Module J (Widgets) — Customizable dashboard with DB preferences
- Module F (Exam Mode) — Kiosk lockdown + warning system
Phase 4: Consolidate Duplicates (1 week)
- Merge
grading-view+tablet-grading-view+grade-analytics-view - Merge assessment creation forms
- Merge calendar implementations
- Merge competency visualization components
- Implement unified dashboard widget system
Phase 5: Authorization & Config (3 days)
- Add permission checks to all UI routes
- Migrate hardcoded config to database
- Implement role-based feature gating
10. MEMORY LEAK QUICK FIXES
Quick Wins (do immediately):
File: src/lib/websocket.ts
- useEffect(() => {
+ useEffect(() => {
connect();
- // missing cleanup!
+ return () => disconnect(); // ADD THIS
}, []);
File: src/components/drawing-canvas.tsx
useEffect(() => {
canvas.addEventListener('mousedown', handleMouseDown);
canvas.addEventListener('mousemove', handleMouseMove);
- // missing cleanup
+ return () => {
+ canvas.removeEventListener('mousedown', handleMouseDown);
+ canvas.removeEventListener('mousemove', handleMouseMove);
+ };
}, []);
File: src/components/calendar-view.tsx
useEffect(() => {
const handleKeydown = (e) => { ... };
window.addEventListener('keydown', handleKeydown);
- // NO CLEANUP
+ return () => window.removeEventListener('keydown', handleKeydown);
}, []);
11. PRIORITY MATRIX
| Issue | Severity | Effort | Priority |
|---|---|---|---|
| Memory leaks (WebSocket, listeners) | HIGH | 0.5 days | URGENT |
| Missing dependency arrays | HIGH | 1 day | URGENT |
| API response standardization | MEDIUM | 1 day | HIGH |
| Implement Module B (Signage) | HIGH | 4 days | HIGH |
| Implement Module H (Notifications) | HIGH | 3 days | HIGH |
| Extract DataTable component | MEDIUM | 2 days | HIGH |
| Implement Module J (Widgets) | MEDIUM | 2 days | MEDIUM |
| Implement Module F (Exam Mode) | HIGH | 5 days | HIGH |
| Consolidate grading logic | MEDIUM | 2 days | MEDIUM |
| Migrate config to database | LOW | 3 days | MEDIUM |
12. NEXT ACTIONS
- TODAY: Fix memory leaks (WebSocket, event listeners) — 4 files
- THIS WEEK:
- Extract
useApi()hook - Create
DataTable,FormBuilder,ConfirmDialogcomponents - Standardize API responses
- Extract
- NEXT: Implement Module B (Signage) + Module H (Notifications)