Foundation: route, recharts, sprint-dates migration, chart-colors helper (#46)

* feat(ST-1201): add Sprint start_date/end_date + claude_jobs index migration

- Sprint model: optionele start_date en end_date (DATE) voor burndown x-as
- CREATE INDEX claude_jobs(status, finished_at) voor agent-throughput-queries
- Bestaande sprints houden NULL; burndown skipt die

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(ST-1202): add lib/chart-colors.ts + vitest coverage

MD3-token-to-CSS-var mappings for STATUS, PRIORITY, VERIFY, JOB_STATUS
and SERIES_COLORS; all 5 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(ST-1203): add Insights link to NavBar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(ST-1204): move Insights NavBar link between Solo and Todo's

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(ST-1205): add sprint start_date/end_date UI + server actions

- createSprintAction + updateSprintDatesAction: Zod date validation
  with end_date >= start_date cross-check
- start-sprint-button: date inputs in create dialog
- sprint-header: date display button + edit dialog with updateSprintDatesAction
- sprint page: select start_date/end_date for SprintHeader prop
- Demo blokkade via bestaande isDemo checks
- 6 tests groen (validation + demo guard)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-05-02 15:58:15 +02:00 committed by GitHub
parent 55a1ee035c
commit ce94fb48c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 333 additions and 7 deletions

View file

@ -0,0 +1,52 @@
import { describe, it, expect } from 'vitest'
import {
STATUS_COLORS,
PRIORITY_COLORS,
VERIFY_COLORS,
JOB_STATUS_COLORS,
SERIES_COLORS,
} from '@/lib/chart-colors'
describe('chart-colors', () => {
it('STATUS_COLORS has all TaskStatus keys and non-empty values', () => {
const keys: (keyof typeof STATUS_COLORS)[] = ['TO_DO', 'IN_PROGRESS', 'REVIEW', 'DONE']
for (const key of keys) {
expect(STATUS_COLORS[key]).toBeTruthy()
expect(typeof STATUS_COLORS[key]).toBe('string')
}
})
it('PRIORITY_COLORS has keys 1-4 with non-empty values', () => {
const keys = [1, 2, 3, 4] as const
for (const key of keys) {
expect(PRIORITY_COLORS[key]).toBeTruthy()
expect(typeof PRIORITY_COLORS[key]).toBe('string')
}
})
it('VERIFY_COLORS has all VerifyResult keys and non-empty values', () => {
const keys: (keyof typeof VERIFY_COLORS)[] = ['ALIGNED', 'PARTIAL', 'EMPTY', 'DIVERGENT']
for (const key of keys) {
expect(VERIFY_COLORS[key]).toBeTruthy()
expect(typeof VERIFY_COLORS[key]).toBe('string')
}
})
it('JOB_STATUS_COLORS has all ClaudeJobStatus keys and non-empty values', () => {
const keys: (keyof typeof JOB_STATUS_COLORS)[] = [
'queued', 'claimed', 'running', 'done', 'failed', 'cancelled',
]
for (const key of keys) {
expect(JOB_STATUS_COLORS[key]).toBeTruthy()
expect(typeof JOB_STATUS_COLORS[key]).toBe('string')
}
})
it('SERIES_COLORS has 5 non-empty entries', () => {
expect(SERIES_COLORS).toHaveLength(5)
for (const color of SERIES_COLORS) {
expect(color).toBeTruthy()
expect(typeof color).toBe('string')
}
})
})