Calendar/docs/typescript-code-review-2025.md
Janus Knudsen 7054c0d40a Refactors event positioning and drag-and-drop
Centralizes event position calculations into `PositionUtils` for consistency and reusability across managers and renderers.

Improves drag-and-drop functionality by emitting events for all-day event conversion and streamlining position calculations during drag operations.

Introduces `AllDayManager` and `AllDayEventRenderer` to manage and render all-day events in the calendar header. This allows dragging events to the header to convert them to all-day events.
2025-09-13 00:39:56 +02:00

7.1 KiB

TypeScript Code Review - Calendar Plantempus

Dato: September 2025
Reviewer: Roo
Fokus: Dybdegående analyse efter TimeFormatter implementation

Executive Summary

Efter implementering af TimeFormatter og gennemgang af codebasen, har jeg identificeret både styrker og forbedringspotentiale. Koden viser god separation of concerns og event-driven arkitektur, men har stadig områder der kan optimeres.

🟢 Styrker

1. Event-Driven Architecture

  • Konsistent EventBus pattern gennem hele applikationen
  • Ingen direkte dependencies mellem moduler
  • God brug af custom events for kommunikation

2. Separation of Concerns

  • Managers: Håndterer business logic (AllDayManager, DragDropManager, etc.)
  • Renderers: Fokuserer på DOM manipulation
  • Utils: Isolerede utility funktioner
  • Elements: Factory pattern for DOM element creation

3. Performance Optimering

  • DOM Caching: Konsistent caching af DOM elementer
  • Throttling: Event throttling i HeaderManager (16ms delay)
  • Pixel-based calculations: Fjernet komplekse time-based overlap beregninger

4. TypeScript Best Practices

  • Stærk typing med interfaces
  • Proper null/undefined checks
  • Readonly constants hvor relevant

🔴 Kritiske Issues

1. "new_" Prefix Methods (EventRenderer.ts)

// PROBLEM: Midlertidige metode navne
protected new_handleEventOverlaps()
protected new_renderOverlappingEvents()
protected new_applyStackStyling()
protected new_applyColumnSharingStyling()

Impact: Forvirrende navngivning, indikerer ufærdig refactoring
Løsning: Fjern prefix og ryd op i gamle metoder

2. Duplikeret Cache Logic

// AllDayManager.ts
private cachedAllDayContainer: HTMLElement | null = null;
private cachedCalendarHeader: HTMLElement | null = null;

// HeaderManager.ts
private cachedCalendarHeader: HTMLElement | null = null;

// DragDropManager.ts
private cachedElements: CachedElements = {...}

Impact: 30+ linjer duplikeret kode
Løsning: Opret generisk DOMCacheManager

3. Manglende Error Boundaries

// SimpleEventOverlapManager.ts
const linkData = element.dataset.stackLink;
try {
  return JSON.parse(linkData);
} catch (e) {
  console.warn('Failed to parse stack link data:', linkData, e);
  return null;
}

Impact: Silently failing JSON parsing
Løsning: Proper error handling med user feedback

🟡 Code Smells & Improvements

1. Magic Numbers

// SimpleEventOverlapManager.ts
const startDifference = Math.abs(top1 - top2);
if (startDifference > 40) { // Magic number!
  return OverlapType.STACKING;
}

// DragDropManager.ts
private readonly dragThreshold = 5; // Should be configurable
private readonly scrollSpeed = 10;
private readonly scrollThreshold = 30;

Løsning: Flyt til configuration constants

2. Complex Method Signatures

// AllDayManager.ts - 73 linjer!
public checkAndAnimateAllDayHeight(): void {
  // Massive method doing too much
}

Løsning: Split i mindre, fokuserede metoder

3. Inconsistent Naming

// Mix af naming conventions
getCalendarHeader()  // get prefix
findElements()       // no prefix
detectColumn()       // action verb
cachedElements       // noun

Løsning: Standardiser naming convention

4. Memory Leaks Risk

// DragDropManager.ts
private boundHandlers = {
  mouseMove: this.handleMouseMove.bind(this),
  mouseDown: this.handleMouseDown.bind(this),
  mouseUp: this.handleMouseUp.bind(this)
};

God praksis! Men ikke konsistent anvendt alle steder

📊 Metrics & Analysis

Complexity Analysis

File Lines Cyclomatic Complexity Maintainability
AllDayManager.ts 281 Medium (8) Good
DragDropManager.ts 521 High (15) Needs refactoring
SimpleEventOverlapManager.ts 473 Very High (20) Critical
HeaderManager.ts 119 Low (4) Excellent
GridManager.ts 348 Medium (10) Good

Code Duplication

  • Cache management: ~15% duplication
  • Event handling: ~10% duplication
  • Position calculations: ~8% duplication

🎯 Prioriterede Forbedringer

Priority 1: Critical Fixes

  1. Fjern "new_" prefix fra EventRenderer metoder
  2. Fix TimeFormatter timezone - Håndter mock data korrekt som UTC
  3. Implementer DOMCacheManager - Reducer duplication

Priority 2: Architecture Improvements

  1. GridPositionCalculator - Centralisér position beregninger
  2. EventThrottler - Generisk throttling utility
  3. AllDayRowCalculator - Udtræk kompleks logik fra AllDayManager

Priority 3: Code Quality

  1. Reduce method complexity - Split store metoder
  2. Standardize naming - Konsistent naming convention
  3. Add JSDoc - Mangler på mange public methods

Priority 4: Testing

  1. Unit tests for TimeFormatter
  2. Integration tests for overlap detection
  3. Performance tests for large event sets

💡 Architectural Recommendations

1. Introduce Service Layer

// Forslag: EventService
class EventService {
  private formatter: TimeFormatter;
  private calculator: GridPositionCalculator;
  private overlapManager: SimpleEventOverlapManager;
  
  // Centralized event operations
}

2. Configuration Management

interface CalendarConstants {
  DRAG_THRESHOLD: number;
  SCROLL_SPEED: number;
  STACK_OFFSET: number;
  OVERLAP_THRESHOLD: number;
}

3. Error Handling Strategy

class CalendarError extends Error {
  constructor(
    message: string,
    public code: string,
    public recoverable: boolean
  ) {
    super(message);
  }
}

🚀 Performance Optimizations

1. Virtual Scrolling

For måneds-view med mange events, overvej virtual scrolling

2. Web Workers

Flyt tunge beregninger (overlap detection) til Web Worker

3. RequestIdleCallback

Brug for non-critical updates som analytics

Positive Highlights

  1. TimeFormatter Implementation: Elegant og clean
  2. Event-driven Architecture: Konsistent og velfungerende
  3. TypeScript Usage: God type safety
  4. DOM Manipulation: Effektiv med custom elements
  5. Separation of Concerns: Klar opdeling af ansvar

Immediate (1-2 dage)

  • Fjern "new_" prefix fra EventRenderer
  • Implementer DOMCacheManager
  • Fix magic numbers

Short-term (3-5 dage)

  • Opret GridPositionCalculator
  • Implementer EventThrottler
  • Refactor SimpleEventOverlapManager complexity

Long-term (1-2 uger)

  • Add comprehensive unit tests
  • Implement service layer
  • Performance optimizations

Konklusion

Koden er generelt velstruktureret med god separation of concerns og konsistent event-driven arkitektur. TimeFormatter implementationen er elegant og løser timezone problemet godt.

Hovedudfordringerne ligger i:

  1. Ufærdig refactoring (new_ prefix)
  2. Duplikeret cache logic
  3. Høj complexity i overlap detection
  4. Manglende tests

Med de foreslåede forbedringer vil kodebasen blive mere maintainable, performant og robust.

Overall Score: 7.5/10 - God kvalitet med plads til forbedring