- Automatic browser geolocation capture on event creation - Reverse geocoding via Nominatim API for place names - Full-text search with SQLite FTS5 - Calendar view for browsing past entries - DateNavigator component for day navigation - SearchModal with Ctrl+K shortcut - QuickAddWidget with Ctrl+J shortcut - Starlight documentation site with GitHub Pages deployment - Multiple AI provider support (Groq, OpenAI, Anthropic, Ollama, LM Studio) - Multi-user registration support BREAKING: Events now include latitude/longitude/placeName fields
8.8 KiB
Calendar View Feature Research
Overview
This document outlines research and implementation ideas for adding a calendar view to DearDiary, enabling users to visualize their journaling activity across days, weeks, and months at a glance.
Current State Analysis
Existing Navigation & Data Flow
- Routes:
/(Dashboard),/today,/history,/diary,/day/:date,/journal/:date,/settings - API:
getDays()returnsArray<{ date, eventCount, hasJournal, journalTitle?, journalExcerpt? }> - History page: Currently a simple list showing all days chronologically
Key Data Points Per Day
date: ISO date string (YYYY-MM-DD)eventCount: Number of events capturedhasJournal: Whether diary page has been generatedjournalTitle: Title from AI-generated diaryjournalExcerpt: Preview text from diary content
Feature Description
1. Monthly Calendar View
Primary use case: Overview of journaling activity at a glance
- Grid layout (7 columns for weekdays)
- Each day cell shows:
- Date number
- Visual indicator(s) for presence of events/diary
- Event count (optional, on hover or expanded)
Visual Indicators
| State | Indicator |
|---|---|
| No events | Empty cell, muted styling |
| Events only (draft) | Small blue/gray dot |
| Diary generated | Small purple dot |
| Both (events + diary) | Two dots or colored dot with indicator |
| Today | Highlighted cell (border/background) |
| Selected day | Different background/border |
Event Density Visualization
- Option to show density heat map (more events = darker shade)
- Scale: 1-2 events (light), 3-5 (medium), 6+ (dark)
2. Weekly Calendar View
Primary use case: Detailed look at recent activity
- Horizontal 7-day strip
- Each day shows expanded content:
- Event count
- Mini event list (first 2-3 events)
- Diary status badge
3. Daily Mini Calendar
- Fixed position in header or sidebar
- Shows current month
- Click to navigate to specific date
- Quick navigation (prev/next month arrows)
UI Component Suggestions
Recommended Libraries
| Library | Pros | Cons |
|---|---|---|
| react-big-calendar | Full-featured, customizable, well-maintained | Requires styling, may be heavy |
| react-calendar | Lightweight, simple API, good theming | Limited customization |
| react-datepicker | Easy to integrate, accessible | More input-focused than display |
| fullcalendar-react | Enterprise-grade, many views | Complex, may be overkill |
| Custom CSS Grid | Full control, lightweight | More implementation work |
Recommendation: Custom CSS Grid + react-calendar hybrid
For DearDiary's needs, a custom implementation using CSS Grid provides:
- Full Tailwind integration (matches existing style)
- Lightweight bundle
- Complete control over visual indicators
- No dependency on heavy calendar libraries
Fallback: If ready-made needed, react-calendar is lightweight (~50KB) and sufficient for monthly view.
Tailwind CSS Implementation (Custom)
// Monthly calendar grid
<div className="grid grid-cols-7 gap-1">
{days.map(day => (
<button className={cn(
"relative p-2 rounded-lg text-center",
day.isToday && "ring-2 ring-purple-500",
day.hasEvents && "bg-slate-800",
day.hasJournal && "bg-purple-900/30"
)}>
<span>{day.dateNumber}</span>
{day.hasEvents && (
<span className="absolute bottom-1 left-1/2 -translate-x-1/2 w-1.5 h-1.5 rounded-full bg-blue-400" />
)}
</button>
))}
</div>
Integration with Existing Pages
1. Standalone Calendar Page (/calendar)
New route added to App.tsx:
- Full monthly calendar view
- Navigation to previous/next months
- Click on day navigates to
/day/:dateor/journal/:date - Toggle between month/week views
2. Integration with Dashboard
Replace or supplement "Recent Diary Pages" with mini calendar:
- Show current month
- Click date to navigate
- Compact version (fewer details per cell)
3. Integration with History Page
Replace list view with calendar as default:
- Toggle between calendar and list views
- Calendar shows activity overview
- List remains available for detailed browsing
4. Navigation Updates
Update Navbar to include calendar link:
// App.tsx Navbar
<a href="/calendar" className="text-slate-300 hover:text-white transition">Calendar</a>
5. Quick Date Navigation
Mini calendar in header (optional):
- Always visible month view
- Click date = navigate to
/day/:date
Implementation Complexity
Phase 1: Basic Monthly Calendar (Priority: High)
- Create
Calendar.tsxcomponent - Add
/calendarroute - Fetch days data for current month
- Render grid with visual indicators
- Click to navigate
Complexity: ~2-3 hours
Files: frontend/src/components/Calendar.tsx, route in App.tsx
Phase 2: Dashboard Integration (Priority: Medium)
- Add mini calendar to Dashboard
- Show current month
- Click date navigates to day
Complexity: ~1-2 hours
Phase 3: Week View (Priority: Low)
- Add week view toggle
- Horizontal 7-day strip
- Expanded content per day
Complexity: ~2-3 hours
Phase 4: Advanced Features (Priority: Low)
- Event density heat map
- Drag to select date range
- Export calendar as image
- iCal integration
Complexity: Varies
API Requirements
Current API Sufficiency
getDays() returns all days - filtering by month happens on client. For larger datasets:
Potential enhancement:
// Get days for specific month (optional optimization)
async getDaysByMonth(year: number, month: number): Promise<DayInfo[]>
Current workaround sufficient: Fetch all days, filter in React (acceptable for < 365 entries).
Accessibility Considerations
WCAG 2.1 AA Compliance
-
Keyboard Navigation
- Arrow keys to move between days
- Enter/Space to select
- Escape to close calendar
-
Screen Reader Support
aria-labelon each day cell: "March 15, 2026 - 3 events, diary generated"aria-currentfor todayrole="grid"with proper row/cell structure
-
Visual Indicators
- Don't rely solely on color
- Use icons/shapes + color
- Sufficient contrast ratios (4.5:1 minimum)
-
Focus Management
- Focus visible on calendar open
- Return focus to trigger element on close
Example ARIA Implementation
<button
aria-label={`${dateString} - ${eventCount} events${hasJournal ? ', diary generated' : ''}`}
aria-current={isToday ? 'date' : undefined}
className="..."
>
<span aria-hidden="true">{dayNumber}</span>
{hasEvents && <span className="sr-only">Has events</span>}
</button>
Mobile-Friendly Considerations
Responsive Design
-
Viewport Adaptation
- Desktop: Full monthly grid (35 cells visible)
- Tablet: Scrollable or condensed
- Mobile: Week view default, swipe between weeks
-
Touch Targets
- Minimum 44x44px tap targets
- Adequate spacing between dates
-
Interaction Patterns
- Swipe left/right for month navigation
- Tap to select, long-press for context menu
Library Considerations
If using react-big-calendar:
<Calendar
views={['month', 'week', 'day']}
defaultView="week" // Default to week on mobile
popup
selectable
style={{ height: 'auto' }}
/>
Recommended Implementation Plan
Priority 1: Calendar Page
- Create
frontend/src/components/Calendar.tsx- Monthly grid using CSS Grid
- Visual dots for event/diary status
- Click navigates to
/day/:date
- Add route
/calendarin App.tsx - Add nav link in Navbar
- Test with existing data
Priority 2: Dashboard Integration
- Add mini calendar above recent entries
- Show current month
- Highlight today, clickable dates
Priority 3: History Enhancement
- Add toggle between list/calendar views
- Calendar as default
Priority 4: Week View (Optional)
- Add view switcher
- Horizontal week strip with event previews
Summary
| Aspect | Recommendation |
|---|---|
| Implementation | Custom CSS Grid (Tailwind) |
| First placement | New /calendar page |
| View types | Monthly default, week as secondary |
| Indicators | Dots (blue=events, purple=diary) |
| Navigation | Click to /day/:date or /journal/:date |
| Accessibility | Full ARIA, keyboard nav |
| Mobile | Default to week view, touch-friendly |
Estimated Timeline
- Phase 1 (Calendar page): 2-3 hours
- Phase 2 (Dashboard): 1-2 hours
- Phase 3 (Week view): 2-3 hours
- Total: ~5-8 hours
Questions for Further Research
- Should calendar support date range selection for bulk operations?
- Export to iCal/Google Calendar desired?
- Sync with external calendars (Google, Apple)?
- Recurring event support?
- Need to show time-of-day heat map?