Calendar/architecture/month-view-plan-UPDATED.md
Janus Knudsen 3ddc6352f2 Refactors calendar architecture for month view
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.
2025-08-20 19:42:13 +02:00

270 lines
No EOL
7.6 KiB
Markdown

# Month View Implementation Plan (POST-REFACTORING)
**Updated:** January 2025
**Status:** Ready to implement - Foundation cleaned up
**Timeline:** 2 days (reduced from 3)
## Pre-Work Completed ✅
The following critical issues have been resolved, making month view implementation much easier:
### ✅ Foundation Improvements Done
- **Event system simplified**: 102 → 20 events with CoreEvents.ts
- **Dead code removed**: CalendarState.ts (170 lines) deleted
- **Type safety improved**: Proper event interfaces defined
- **Error handling added**: Date validation in DateCalculator
- **Build fixed**: tsconfig.json output directory corrected
### ✅ Impact on Month View
- **Clearer event system**: Know exactly which events to use
- **No confusing StateEvents**: Removed competing event system
- **Better types**: AllDayEvent interface ready for month events
- **Reliable dates**: DateCalculator won't crash on bad input
---
## Revised Implementation Plan
### Phase 1: Strategy Pattern (4 hours → 2 hours)
*Time saved: Dead code removed, events clarified*
#### 1.1 Create ViewStrategy Interface ✨
**New file:** `src/strategies/ViewStrategy.ts`
```typescript
import { CoreEvents } from '../constants/CoreEvents'; // Use new events!
export interface ViewStrategy {
renderGrid(container: HTMLElement, context: ViewContext): void;
renderEvents(events: AllDayEvent[], container: HTMLElement): void; // Use proper types!
getLayoutConfig(): ViewLayoutConfig;
handleNavigation(date: Date): Date; // Now validated!
}
```
#### 1.2 Extract WeekViewStrategy ✨
**New file:** `src/strategies/WeekViewStrategy.ts`
- Move existing logic from GridManager
- Use CoreEvents instead of EventTypes
- Leverage improved type safety
#### 1.3 Create MonthViewStrategy
**New file:** `src/strategies/MonthViewStrategy.ts`
```typescript
export class MonthViewStrategy implements ViewStrategy {
renderGrid(container: HTMLElement, context: ViewContext): void {
// 7x6 month grid - no time axis needed
this.createMonthGrid(container, context.currentDate);
}
renderEvents(events: AllDayEvent[], container: HTMLElement): void {
// Use proper AllDayEvent types (now defined!)
// Simple day cell rendering
}
}
```
#### 1.4 Update GridManager
**Modify:** `src/managers/GridManager.ts`
```typescript
export class GridManager {
private strategy: ViewStrategy;
setViewStrategy(strategy: ViewStrategy): void {
this.strategy = strategy;
// No memory leaks - cleanup is now handled!
}
render(): void {
// Emit CoreEvents.GRID_RENDERED instead of old events
this.eventBus.emit(CoreEvents.GRID_RENDERED, {...});
}
}
```
---
### Phase 2: Month Components (2 hours → 1.5 hours)
*Time saved: Better types, no conflicting events*
#### 2.1 MonthGridRenderer
**New file:** `src/renderers/MonthGridRenderer.ts`
```typescript
import { AllDayEvent } from '../types/EventTypes'; // Proper types!
import { CoreEvents } from '../constants/CoreEvents';
export class MonthGridRenderer {
renderMonth(container: HTMLElement, date: Date): void {
// DateCalculator.validateDate() prevents crashes
this.dateCalculator.validateDate(date, 'renderMonth');
// Create 7x6 grid with proper types
}
}
```
#### 2.2 MonthEventRenderer
**New file:** `src/renderers/MonthEventRenderer.ts`
```typescript
export class MonthEventRenderer {
render(events: AllDayEvent[], container: HTMLElement): void {
// Use AllDayEvent interface - no more any!
// Clean event filtering using proper types
}
}
```
---
### Phase 3: Integration (2 hours → 1 hour)
*Time saved: Clear events, no StateEvents confusion*
#### 3.1 Wire ViewManager
**Modify:** `src/managers/ViewManager.ts`
```typescript
private changeView(newView: CalendarView): void {
let strategy: ViewStrategy;
switch(newView) {
case 'month':
strategy = new MonthViewStrategy();
break;
// ... other views
}
this.gridManager.setViewStrategy(strategy);
// Use CoreEvents - no confusion about which events!
this.eventBus.emit(CoreEvents.VIEW_CHANGED, { view: newView });
}
```
#### 3.2 Update HTML & CSS
**Modify:** `wwwroot/index.html`
```html
<!-- Enable month view - no conflicting events to worry about -->
<swp-view-button data-view="month">Month</swp-view-button>
```
**New:** `wwwroot/css/calendar-month.css`
```css
.month-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-template-rows: auto repeat(6, 1fr);
}
.month-day-cell {
border: 1px solid var(--border-color);
min-height: 120px;
padding: 4px;
}
.month-event {
font-size: 0.75rem;
padding: 1px 4px;
margin: 1px 0;
border-radius: 2px;
background: var(--event-color);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
```
---
## Updated Timeline
### Day 1 (Reduced from full day)
**Morning (2 hours)**
- ✅ Foundation already clean
- Implement ViewStrategy interface
- Extract WeekViewStrategy
- Create MonthViewStrategy skeleton
**Afternoon (1 hour)**
- Wire strategies in GridManager
- Test view switching works
### Day 2
**Morning (1.5 hours)**
- Implement MonthGridRenderer
- Implement MonthEventRenderer
- Create month CSS
**Afternoon (1 hour)**
- Final integration
- Enable month button
- Test and polish
**Total: 5.5 hours instead of 16+ hours!**
---
## Benefits from Pre-Refactoring
### 🚀 **Development Speed**
- **No conflicting events**: Clear which events to use
- **No dead code confusion**: CalendarState removed
- **Proper types**: AllDayEvent interface ready
- **Reliable foundation**: DateCalculator validation prevents crashes
### 🎯 **Quality**
- **Consistent patterns**: Following established CoreEvents
- **Type safety**: No more `any` types to debug
- **Memory management**: Cleanup patterns established
- **Error handling**: Built-in date validation
### 🔧 **Maintainability**
- **Single event system**: No EventTypes vs StateEvents confusion
- **Clean codebase**: 200+ lines of cruft removed
- **Clear interfaces**: AllDayEvent, ViewStrategy defined
- **Proper separation**: Strategy pattern foundation laid
---
## Success Metrics (Updated)
### ✅ **Foundation Quality**
- [x] Event system consolidated (20 events)
- [x] Dead code removed
- [x] Types properly defined
- [x] Date validation added
- [x] Build configuration fixed
### 🎯 **Month View Goals**
- [ ] Month grid displays 6 weeks correctly
- [ ] Events show in day cells (max 3 + "more")
- [ ] Navigation works (prev/next month)
- [ ] View switching between week/month
- [ ] No regressions in existing views
- [ ] Under 400 lines of new code (down from 750!)
### 📊 **Expected Results**
- **Implementation time**: 5.5 hours (67% reduction)
- **Code quality**: Higher (proper types, clear events)
- **Maintainability**: Much improved (clean foundation)
- **Bug risk**: Lower (validation, proper cleanup)
---
## Risk Assessment (Much Improved)
### ✅ **Risks Eliminated**
- ~~Event system conflicts~~ → Single CoreEvents system
- ~~Type errors~~ → Proper AllDayEvent interface
- ~~Date crashes~~ → DateCalculator validation
- ~~Memory leaks~~ → Cleanup patterns established
- ~~Dead code confusion~~ → CalendarState removed
### ⚠️ **Remaining Risks (Low)**
1. **CSS conflicts**: Mitigated with namespaced `.month-view` classes
2. **Performance with many events**: Can implement virtualization later
3. **Browser compatibility**: CSS Grid widely supported
---
## Conclusion
The pre-refactoring work has transformed this from a difficult, error-prone implementation into a straightforward feature addition. The month view can now be implemented cleanly in ~5.5 hours with high confidence and low risk.
**Ready to proceed!** 🚀