# SchulOS 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:
```tsx
// 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:**
```json
{
"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:
```ts
const session = await getSession();
if (!session?.user?.id) return unauthorized();
await logAudit(session.user.id, action);
```
**Solution:** Higher-order middleware wrapper
```ts
// 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 UI
- `src/components/tablet-grading-view.tsx` — Tablet variant
- `src/components/grade-analytics-view.tsx` — Analytics view
**Problem:** Logic inconsistencies, hard to maintain
**Solution:**
1. Extract grading engine → `src/lib/grading-engine.ts`
- Pure functions for grade computation
- Unit tested
- Reusable everywhere
2. 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 assessments
- `ai-tests-view.tsx` — AI-generated tests
- `exam-calendar-view.tsx` — Exam scheduling + creation
**Solution:**
1. Create `AssessmentForm.tsx` — Reusable form component
2. Create `AssessmentType.tsx` — Form variant selector (standard/AI-generated/exam)
3. Refactor views to use form component
---
### 2.3 Implement Single Competency Renderer
**Current duplication:** 4 implementations
- `competence-flower-view.tsx` — Radar chart
- `competency-grid-view.tsx` — Grid view
- `mastery-matrix-view.tsx` — Matrix view (duplicate of above)
- `curriculum-coverage-view.tsx` — Coverage view
**Solution:**
```tsx
// New component with configurable layout
```
**Impact:** Single source of truth for competency data rendering.
---
### 2.4 Unify Calendar Implementations
**Current:** 3 separate calendar components
- `calendar-view.tsx` — General calendar
- `exam-calendar-view.tsx` — Exam-specific calendar
- `lesson-plans-view.tsx` — Lesson scheduling calendar
**Solution:** Single calendar with event type filtering
```tsx
```
---
## Phase 3: Implement Missing PRD v2 Modules (Weeks 4-6)
### 3.1 Module B — Digital Signage (Emergency Alerts, TV Displays)
**Required tables:**
- `SignageDisplay` — Physical displays
- `SignageSlide` — Content slides
- `SignagePlaylist` — Rotation config
- `EmergencyAlert` — Alert system
**Implementation:**
1. Create admin interface: `/admin/signage/displays`, `/admin/signage/slides`
2. Create display client: `/signage/display/[displayId]` (fullscreen kiosk)
3. Create push notifications for emergency alerts (integrate with Module H)
4. 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 pages
- `src/app/signage/display/` — Display client
- `src/components/signage/` — Reusable components
- `src/lib/signage-engine.ts` — Rotation logic
---
### 3.2 Module H — Centralized Notifications
**Required tables:**
- `Notification` — Unified notification model
- `NotificationPreference` — Per-user settings
- `NotificationSubscription` — Service worker subscriptions
**Implementation:**
1. Create `Notification` model unified for all alert types
2. Implement service worker + Web Push API
3. Create notification center UI: `/notifications`
4. Add real-time delivery via WebSocket
5. 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 API
- `src/app/api/push-subscriptions/` — Web Push setup
- `src/components/notification-center.tsx`
- `src/lib/notification-engine.ts`
- `src/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 definitions
- `UserDashboardPreference` — Per-user layout
- `WidgetData` — Cached widget data (optional)
**Implementation:**
1. Create widget registry system
2. Create `Widget` wrapper component (read-only data consumer)
3. Create customization UI: `/dashboard/customize`
4. Refactor `dashboard-view.tsx` to use widget system
5. Make dashboard widgets available elsewhere (student portal, parent portal)
**Widgets to create (examples):**
- `AttendanceWidget` — Pulls from canonical attendance data
- `UpcomingExamsWidget` — Pulls from calendar
- `GradeWidget` — Pulls from grading system
- `RecentActivitiesWidget` — Pulls from audit log
- `WeatherWidget` — 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 implementations
- `src/app/dashboard/customize/` — Customization page
- `src/lib/widget-registry.ts` — Widget system
---
### 3.4 Module F — Exam Mode (Kiosk Lockdown + Proctoring)
**Required tables:**
- `ExamSession` — Active exam session
- `ExamWarning` — Warning log
- `ExamIncidentEvent` — Incident tracking
**Implementation:**
1. Create `ExamSession` model + lifecycle (started → paused → resumed → ended)
2. Implement fullscreen kiosk UI: `/exam/[sessionId]`
3. Add browser-level lockdown:
- Service worker intercepts navigation
- Fullscreen API lock
- Tab/window switching detection
4. Create teacher control panel: `/exam/monitor`
5. Implement warning system (3-strike auto-pause)
6. Add bathroom request flow + distress signal
7. 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 page
- `src/app/exam/monitor/` — Teacher control panel
- `src/components/exam-mode/` — Exam UI components
- `src/lib/exam-lockdown.ts` — Kiosk logic
- `src/lib/service-worker-exam.ts` — Browser lockdown
---
## Phase 4: Consolidate Duplicates (Weeks 7-8)
After Phases 1-3, apply architectural changes:
1. **Merge grading implementations** → Single engine + UI variants
2. **Merge assessment creation** → Unified form component
3. **Merge competency renderers** → Configurable component
4. **Merge calendar implementations** → Single calendar with filters
5. **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:**
```ts
{
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:
```tsx
// Before: Just hidden, not prevented
{userRole === 'ADMIN' && }
// After: Proper permission check
}>
```
**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
1. **Create `use-api.ts` hook** — Replace 60+ fetch patterns
2. **Extract `DataTable`, `FormBuilder`, `ConfirmDialog`** — Eliminate 25+ duplicates
3. **Standardize API responses** — Middleware wrapper
4. **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%)