Prepares the calendar component for month view implementation by introducing a strategy pattern for view management, splitting configuration settings, and consolidating events into a core set. It also removes dead code and enforces type safety, improving overall code quality and maintainability. Addresses critical issues identified in the code review, laying the groundwork for efficient feature addition.
7.4 KiB
Critical Code Review - Calendar Plantempus
Date: January 2025
Reviewer: Code Analysis Assistant
Scope: Full TypeScript/JavaScript codebase
Executive Summary
This code review identifies 14+ critical issues that impact maintainability, performance, and the ability to add new features (especially month view). The codebase shows signs of rapid development without architectural planning, resulting in significant technical debt.
🚨 CRITICAL ISSUES
1. Inconsistent File Structure
Severity: High
Impact: Development confusion, build issues
Problems:
- Duplicate TypeScript/JavaScript files exist (
src/utils/PositionUtils.jsand.ts) - Mixed compiled and source code in
wwwroot/js/ - Legacy files in root directory (
calendar-*.js)
Evidence:
src/utils/PositionUtils.js (JavaScript)
src/utils/PositionUtils.ts (TypeScript)
calendar-grid-manager.js (Root legacy file)
Recommendation: Delete all .js files in src/, remove legacy root files, keep only TypeScript sources.
2. Event System Overcomplexity
Severity: Critical
Impact: Impossible to maintain, performance degradation
Problems:
- Two overlapping event systems (
EventTypes.tswith 102 events +CalendarState.ts) - Unclear separation of concerns
- Legacy events marked as "removed" but still present
Evidence:
// EventTypes.ts - 102 constants!
export const EventTypes = {
CONFIG_UPDATE: 'calendar:configupdate',
CALENDAR_TYPE_CHANGED: 'calendar:calendartypechanged',
// ... 100 more events
}
// CalendarState.ts - Another event system
export const StateEvents = {
CALENDAR_STATE_CHANGED: 'calendar:state:changed',
// ... more events
}
Recommendation: Consolidate to ~20 core events with clear ownership.
3. Missing Error Handling
Severity: High
Impact: Silent failures, poor user experience
Problems:
- No try-catch blocks in critical paths
- No error boundaries for component failures
- DateCalculator assumes all inputs are valid
Evidence:
// DateCalculator.ts - No validation
getISOWeekStart(date: Date): Date {
const monday = new Date(date); // What if date is invalid?
const currentDay = monday.getDay();
// ... continues without checks
}
Recommendation: Add comprehensive error handling and validation.
4. Memory Leak Potential
Severity: Critical
Impact: Browser performance degradation over time
Problems:
- Event listeners never cleaned up
- DOM references held indefinitely
- Multiple DateCalculator instances created
Evidence:
// ViewManager.ts - No cleanup
constructor(eventBus: IEventBus) {
this.eventBus = eventBus;
this.setupEventListeners(); // Never removed!
}
// No destroy() method exists
Recommendation: Implement proper cleanup in all managers.
5. Single Responsibility Violations
Severity: High
Impact: Unmaintainable code, difficult to test
Problems:
GridManager: Handles rendering, events, styling, positioning (311 lines!)CalendarConfig: Config, state management, and factory logic mixedNavigationRenderer: DOM manipulation and event rendering
Evidence:
// GridManager doing everything:
- subscribeToEvents()
- render()
- setupGridInteractions()
- getClickPosition()
- scrollToHour()
- minutesToTime()
Recommendation: Split into focused, single-purpose classes.
6. Dependency Injection Missing
Severity: Medium
Impact: Untestable code, tight coupling
Problems:
- Hard-coded singleton imports everywhere
calendarConfigimported directly in 15+ files- Circular dependencies through EventBus
Evidence:
import { calendarConfig } from '../core/CalendarConfig'; // Singleton
import { eventBus } from '../core/EventBus'; // Another singleton
Recommendation: Use constructor injection pattern.
7. Performance Problems
Severity: Medium
Impact: Sluggish UI, especially with many events
Problems:
document.querySelectorcalled repeatedly- No caching of DOM elements
- Full re-renders on every change
Evidence:
// Called multiple times per render:
const scrollableContent = document.querySelector('swp-scrollable-content');
Recommendation: Cache DOM queries, implement selective rendering.
8. Type Safety Issues
Severity: High
Impact: Runtime errors, hidden bugs
Problems:
anytypes used extensively- Type casting to bypass checks
- Missing interfaces for data structures
Evidence:
private allDayEvents: any[] = []; // No type safety
(header as any).dataset.today = 'true'; // Bypassing TypeScript
Recommendation: Define proper TypeScript interfaces for all data.
🔧 TECHNICAL DEBT
9. Redundant Code
- Duplicate date logic in DateCalculator and PositionUtils
- Headers rendered in multiple places
- Similar event handling patterns copy-pasted
10. Testability Issues
- No dependency injection makes mocking impossible
- Direct DOM manipulation prevents unit testing
- Global state makes tests brittle
11. Documentation Problems
- Mixed Danish/English comments
- Missing JSDoc for public APIs
- Outdated comments that don't match code
⚡ ARCHITECTURE ISSUES
12. Massive Interfaces
CalendarTypes.ts: Too many interfaces in one fileEventTypes: 102 constants is unmanageable- Manager interfaces too broad
13. Coupling Problems
- High coupling between managers
- Everything communicates via events (performance hit)
- All components depend on global config
14. Naming Inconsistency
- Mixed language conventions
- Unclear event names (
REFRESH_REQUESTEDvsCALENDAR_REFRESH_REQUESTED) swp-prefix unexplained
📊 METRICS
Code Quality Scores
- Maintainability: 3/10
- Testability: 2/10
- Performance: 5/10
- Type Safety: 4/10
- Architecture: 3/10
File Statistics
- Total TypeScript files: 24
- Total JavaScript files: 8 (should be 0)
- Average file size: ~200 lines (acceptable)
- Largest file: GridManager.ts (311 lines)
- Event types defined: 102 (should be ~20)
🎯 RECOMMENDATIONS
Immediate Actions (Week 1)
- Remove duplicate files - Clean up
.jsduplicates - Add error boundaries - Prevent cascade failures
- Fix memory leaks - Add cleanup methods
Short Term (Month 1)
- Consolidate events - Reduce to core 20 events
- Implement DI - Remove singleton dependencies
- Split mega-classes - Apply Single Responsibility
Long Term (Quarter 1)
- Add comprehensive tests - Aim for 80% coverage
- Performance optimization - Virtual scrolling, caching
- Complete documentation - JSDoc all public APIs
Impact on Month View Implementation
Without refactoring:
- 🔴 ~2000 lines of new code
- 🔴 3-4 weeks implementation
- 🔴 High bug risk
With minimal refactoring:
- ✅ ~500 lines of new code
- ✅ 1 week implementation
- ✅ Reusable components
Conclusion
The codebase requires significant refactoring to support new features efficiently. The identified issues, particularly the lack of strategy pattern and hardcoded week/day assumptions, make adding month view unnecessarily complex.
Priority: Focus on minimal refactoring that enables month view (Strategy pattern, config split, event consolidation) before attempting to add new features.