kimai-plugin-heatmap/.planning/milestones/v1.0-phases/04-heatmap-interaction/04-CONTEXT.md
Christopher Mühl 244c7c66fc
chore: archive v1.0 milestone
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 23:25:26 +02:00

3.1 KiB

Phase 4: Heatmap Interaction - Context

Gathered: 2026-04-08 Status: Ready for planning

## Phase Boundary

Add click-through navigation from heatmap day cells to Kimai's timesheet view, and a project filter dropdown that re-fetches and re-renders the heatmap without page reload.

## Implementation Decisions

Click Navigation

  • Clicking any day cell navigates to Kimai's timesheet list filtered by that date (/en/timesheet/?daterange=YYYY-MM-DD)
  • Empty cells (no data) are clickable too — user may want to add time for that day
  • Pointer cursor + subtle hover highlight (opacity change) on all cells as click affordance
  • If a project filter is active, preserve it in the timesheet URL (&projects[]=N)

Project Filter

  • Filter dropdown positioned next to the heatmap SVG (right side), using the spare horizontal space since the heatmap isn't full card width
  • Projects only — no activity filter (API already supports ?project=N)
  • Default state: "All Projects" selected, no filter applied
  • Selecting a project fetches from API with ?project=N, re-renders heatmap in place; color scale recalculates for filtered data

Testing Strategy

  • Vitest tests for click navigation: verify click handler sets window.location.href to correct Kimai URL pattern
  • Vitest tests for filter dropdown: verify dropdown renders, selecting fires fetch with correct query param, heatmap re-renders with new data
  • Fixture data matching existing HeatmapData shape from prior tests

Claude's Discretion

  • Exact Kimai timesheet URL format (verify against Kimai source)
  • Filter dropdown styling details (should use Tabler/Kimai form classes)
  • How to populate the project list (new API endpoint or extend existing one)

<code_context>

Existing Code Insights

Reusable Assets

  • renderHeatmap(container, data, config) in assets/src/heatmap.ts — main rendering function, can be called again with new data for filter updates
  • HeatmapData / DayEntry types in assets/src/types.ts — shared data shape
  • HeatmapController::data() already accepts ?project query parameter
  • HeatmapService::getDailyAggregation() already supports ?int $projectId parameter

Established Patterns

  • d3 selections for SVG rendering with data binding
  • Tooltip positioning via fixed-position div (mouseenter/mouseleave)
  • IIFE format with KimaiHeatmap global, kimai.initialized event for deferred init
  • Tabler CSS variables for theming (--tblr-bg-surface, --tblr-body-color, etc.)

Integration Points

  • data-url attribute on container div passes API endpoint to JS
  • Widget template at Resources/views/widget/heatmap.html.twig with Tabler card embed
  • CSS at Resources/public/heatmap.css
  • Route heatmap_data resolves to /heatmap/data

</code_context>

## Specific Ideas
  • User wants filter next to the heatmap (not in header or below) since the SVG doesn't fill the full card width — use the horizontal space to the right
## Deferred Ideas

None — discussion stayed within phase scope.