Co-authored-by: cetinmustafa83 <30570791+cetinmustafa83@users.noreply.github.com>
12 KiB
ExaMetra Refactor Action Plan
PRD v1 → v2 → Production Ready
Current State Analysis:
- 70+ view components
- 100+ API routes
- Estimated 40% code duplication
- 4 major PRD v2 modules not implemented
- Multiple memory leak patterns (detected but mostly fixed)
Phase 1: Quick Wins (Week 1)
1.1 Implement Centralized API Fetching Hook
File: src/hooks/use-api.ts
Replace the 60+ identical fetch patterns with SWR:
// Before: Repeated in every component
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
fetch(`/api/xyz`)
.then(r => r.json())
.then(d => setData(d))
.catch(e => setError(e))
.finally(() => setLoading(false));
}, []);
// After: Single hook in 60+ places
const { data, isLoading, error, mutate } = useApi('/api/xyz');
Impact: Reduces component code by 30%, fixes data sync issues, enables optimistic updates.
Affected Files: 60+ components
1.2 Extract Reusable UI Components
src/components/ui/data-table.tsx
Used in: analytics, attendance, competitions, behavior-tracking, grade-analytics
- Sorting, filtering, pagination
- Configurable columns
- Batch actions
src/components/forms/form-builder.tsx
Used in: student entry, grade entry, assessment creation, subject management
- Schema-driven validation
- Reusable field types
- Error handling
src/components/dialogs/confirm-dialog.tsx
Used in: 12+ places (delete confirmations, cancel actions)
- Consistent styling
- Accessibility
- Custom actions
Impact: Eliminates 25+ duplicate component implementations.
1.3 Standardize API Response Format
Current inconsistency: Some routes return { data: [...] }, others return bare array
Standard format:
{
"success": true,
"data": [...],
"error": null,
"pagination": {
"total": 100,
"limit": 20,
"offset": 0
}
}
Create middleware: src/lib/api-response.ts
Impact: Simplifies error handling, enables consistent pagination, better client-side caching.
1.4 Create API Route Middleware
Problem: Every route duplicates:
const session = await getSession();
if (!session?.user?.id) return unauthorized();
await logAudit(session.user.id, action);
Solution: Higher-order middleware wrapper
// Before
export async function GET(req: Request) {
const session = await getSession();
if (!session?.user?.id) return unauthorized();
// 50+ lines of actual logic
await logAudit(...);
}
// After
export const GET = withAuth(withAudit(async (req, context) => {
// Just the business logic
const data = await db.xyz.findMany();
return apiResponse(data);
}));
Affected: All 100+ API routes
Impact: Reduces average route size by 40%, eliminates repeated auth/audit code.
Phase 2: Fix Architectural Issues (Weeks 2-3)
2.1 Consolidate Grading Logic
Current duplication: 3 implementations
src/components/grading-view.tsx— Main grading UIsrc/components/tablet-grading-view.tsx— Tablet variantsrc/components/grade-analytics-view.tsx— Analytics view
Problem: Logic inconsistencies, hard to maintain
Solution:
-
Extract grading engine →
src/lib/grading-engine.ts- Pure functions for grade computation
- Unit tested
- Reusable everywhere
-
Create UI layer →
src/components/grading/GradingForm.tsx— Input component (reusable)GradingView.tsx— Desktop view (uses GradingForm)TabletGradingView.tsx— Tablet view (uses GradingForm + responsive)GradeAnalytics.tsx— Analytics (uses grading-engine)
Impact: Single source of truth for grading logic, easier to test, consistent across UI.
2.2 Unify Assessment Creation
Current duplication: 3 implementations
assessments-view.tsx— Standard assessmentsai-tests-view.tsx— AI-generated testsexam-calendar-view.tsx— Exam scheduling + creation
Solution:
- Create
AssessmentForm.tsx— Reusable form component - Create
AssessmentType.tsx— Form variant selector (standard/AI-generated/exam) - Refactor views to use form component
2.3 Implement Single Competency Renderer
Current duplication: 4 implementations
competence-flower-view.tsx— Radar chartcompetency-grid-view.tsx— Grid viewmastery-matrix-view.tsx— Matrix view (duplicate of above)curriculum-coverage-view.tsx— Coverage view
Solution:
// New component with configurable layout
<CompetencyViewer
layout="flower" // or "grid" or "matrix" or "coverage"
competencies={competencies}
config={config}
/>
Impact: Single source of truth for competency data rendering.
2.4 Unify Calendar Implementations
Current: 3 separate calendar components
calendar-view.tsx— General calendarexam-calendar-view.tsx— Exam-specific calendarlesson-plans-view.tsx— Lesson scheduling calendar
Solution: Single calendar with event type filtering
<Calendar
events={allEvents}
eventTypeFilters={['lesson', 'exam', 'deadline']}
config={config}
/>
Phase 3: Implement Missing PRD v2 Modules (Weeks 4-6)
3.1 Module B — Digital Signage (Emergency Alerts, TV Displays)
Required tables:
SignageDisplay— Physical displaysSignageSlide— Content slidesSignagePlaylist— Rotation configEmergencyAlert— Alert system
Implementation:
- Create admin interface:
/admin/signage/displays,/admin/signage/slides - Create display client:
/signage/display/[displayId](fullscreen kiosk) - Create push notifications for emergency alerts (integrate with Module H)
- Add approval workflow for teacher-submitted slides
Safety requirement: Emergency alerts must override all displays immediately with push notification to staff.
Effort: 4–5 days
Files to create:
src/app/admin/signage/— Admin pagessrc/app/signage/display/— Display clientsrc/components/signage/— Reusable componentssrc/lib/signage-engine.ts— Rotation logic
3.2 Module H — Centralized Notifications
Required tables:
Notification— Unified notification modelNotificationPreference— Per-user settingsNotificationSubscription— Service worker subscriptions
Implementation:
- Create
Notificationmodel unified for all alert types - Implement service worker + Web Push API
- Create notification center UI:
/notifications - Add real-time delivery via WebSocket
- Refactor all modules to emit into this system instead of creating own alerts
Current alerts to consolidate:
- Exam warnings (from exam-calendar-view)
- Messages (from communication-view)
- System alerts (scattered)
- Signage emergencies (new from Module B)
Effort: 3–4 days
Files to create:
src/app/api/notifications/— Notification APIsrc/app/api/push-subscriptions/— Web Push setupsrc/components/notification-center.tsxsrc/lib/notification-engine.tssrc/lib/push-service-worker.ts
3.3 Module J — Dashboard Widget System (Customizable Home)
Current issue: Dashboard monolithic (241KB), not reusable per spec
Required tables:
DashboardWidget— Widget definitionsUserDashboardPreference— Per-user layoutWidgetData— Cached widget data (optional)
Implementation:
- Create widget registry system
- Create
Widgetwrapper component (read-only data consumer) - Create customization UI:
/dashboard/customize - Refactor
dashboard-view.tsxto use widget system - Make dashboard widgets available elsewhere (student portal, parent portal)
Widgets to create (examples):
AttendanceWidget— Pulls from canonical attendance dataUpcomingExamsWidget— Pulls from calendarGradeWidget— Pulls from grading systemRecentActivitiesWidget— Pulls from audit logWeatherWidget— Optional external data
Each widget must:
- Fetch from single canonical source (no duplication)
- Be read-only in dashboard context
- Have configurable options (hidden by user preference)
- Load independently with skeleton state
Effort: 2–3 days
Files to create:
src/components/dashboard-widgets/— Widget implementationssrc/app/dashboard/customize/— Customization pagesrc/lib/widget-registry.ts— Widget system
3.4 Module F — Exam Mode (Kiosk Lockdown + Proctoring)
Required tables:
ExamSession— Active exam sessionExamWarning— Warning logExamIncidentEvent— Incident tracking
Implementation:
- Create
ExamSessionmodel + lifecycle (started → paused → resumed → ended) - Implement fullscreen kiosk UI:
/exam/[sessionId] - Add browser-level lockdown:
- Service worker intercepts navigation
- Fullscreen API lock
- Tab/window switching detection
- Create teacher control panel:
/exam/monitor - Implement warning system (3-strike auto-pause)
- Add bathroom request flow + distress signal
- Create incident logging + parent visibility
Safety requirements:
- Bathroom requests pause only that student's session
- Distress signal triggers immediate teacher alert
- 3rd warning auto-pauses (not teacher-initiated)
- All incidents logged for audit trail
Effort: 5–6 days (complex client-side security)
Files to create:
src/app/exam/[sessionId]/— Kiosk pagesrc/app/exam/monitor/— Teacher control panelsrc/components/exam-mode/— Exam UI componentssrc/lib/exam-lockdown.ts— Kiosk logicsrc/lib/service-worker-exam.ts— Browser lockdown
Phase 4: Consolidate Duplicates (Weeks 7-8)
After Phases 1-3, apply architectural changes:
- Merge grading implementations → Single engine + UI variants
- Merge assessment creation → Unified form component
- Merge competency renderers → Configurable component
- Merge calendar implementations → Single calendar with filters
- Delete 12+ duplicate utility functions → Use shared lib
Result: Code reduction 30-40%.
Phase 5: Configuration & Compliance (Week 9)
5.1 Database Configuration System
Migrate hardcoded values to database:
Create SystemConfig table:
{
key: string (PK),
value: string | number | boolean | JSON,
description: string,
editable: boolean,
schoolId: string? (null = system-wide)
}
Migrate:
- Escalation wait period: "3 business days" →
Config["escalation.wait_days"] - Grading scales: hardcoded 1–6 → configurable per school
- Mastery levels: hardcoded 4 levels → configurable
- Report templates: hardcoded phrases → DB-driven
Effort: 2 days
5.2 Role-Based Permission UI
Implement UI-level permission checks:
// Before: Just hidden, not prevented
{userRole === 'ADMIN' && <AdminButton />}
// After: Proper permission check
<ProtectedFeature feature="admin.grading" fallback={<LockedIcon />}>
<AdminButton />
</ProtectedFeature>
Effort: 1 day
Timeline Summary
| Phase | Duration | Completion |
|---|---|---|
| Phase 1 (Quick Wins) | 1 week | Reduce duplication by 30% |
| Phase 2 (Architecture) | 2 weeks | Consolidate major duplicates |
| Phase 3 (Missing Modules) | 3 weeks | Implement B, H, J, F |
| Phase 4 (Consolidation) | 1 week | Final cleanup |
| Phase 5 (Config) | 1 week | Database config system |
| Total | ~9 weeks | Production ready |
Immediate Next Steps
- Create
use-api.tshook — Replace 60+ fetch patterns - Extract
DataTable,FormBuilder,ConfirmDialog— Eliminate 25+ duplicates - Standardize API responses — Middleware wrapper
- Start Module B (Signage) — Critical safety feature
Success Metrics
- Codebase reduced by 30% (duplication eliminated)
- All 11 PRD v2 modules implemented
- Zero memory leaks (verified with Chrome DevTools)
- All API responses standardized
- Role-based permissions enforced UI + backend
- Configuration system working
- Dashboard customization working
- Emergency alert system tested
- Exam mode kiosk tested
- Full test coverage for critical paths (>80%)