From d2af8664f4f529330c5539db60a0609060f5bb9d Mon Sep 17 00:00:00 2001 From: Benjamin Sutter Date: Sun, 24 May 2026 23:12:08 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20KPI=20card=20counts=20match=20feed=20?= =?UTF-8?q?=E2=80=94=20exclusive=20buckets=20+=20filter=20reset=20on=20cli?= =?UTF-8?q?ck?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - reminderService: dueThisWeek/dueThisMonth use exclusive day ranges (1-7, 8-30) matching getHorizon() buckets; schattenmarktReadyCount counts by type=SCHATTENMARKT_RELEASE (same criteria as the feed filter) - ReminderKpiBar: clicking a horizon card resets filterType to ALL; clicking Pre-Market card resets filterHorizon to ALL — ensures the number shown on the card always equals the number of rows displayed below Co-Authored-By: Claude Sonnet 4.6 --- src/components/supply/ReminderKpiBar.tsx | 14 ++++++++++++-- src/services/reminderService.ts | 18 ++++++------------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/components/supply/ReminderKpiBar.tsx b/src/components/supply/ReminderKpiBar.tsx index 0aedb46..ca61e29 100644 --- a/src/components/supply/ReminderKpiBar.tsx +++ b/src/components/supply/ReminderKpiBar.tsx @@ -75,11 +75,21 @@ export function ReminderKpiBar() { ) function toggleHorizon(h: FilterHorizon) { - setFilterHorizon(filterHorizon === h ? 'ALL' : h) + if (filterHorizon === h) { + setFilterHorizon('ALL') + } else { + setFilterHorizon(h) + setFilterType('ALL') // clear type filter so count matches + } } function togglePreMarket() { - setFilterType(filterType === ReminderType.SCHATTENMARKT_RELEASE ? 'ALL' : ReminderType.SCHATTENMARKT_RELEASE) + if (filterType === ReminderType.SCHATTENMARKT_RELEASE) { + setFilterType('ALL') + } else { + setFilterType(ReminderType.SCHATTENMARKT_RELEASE) + setFilterHorizon('ALL') // clear horizon filter so count matches + } } if (isLoading) { diff --git a/src/services/reminderService.ts b/src/services/reminderService.ts index 8df9c12..e9d80bb 100644 --- a/src/services/reminderService.ts +++ b/src/services/reminderService.ts @@ -1,6 +1,6 @@ import { MockupReminderProvider } from '../provider/MockupReminderProvider' import type { Reminder } from '../domain/reminder' -import { ReminderPriority, ReminderStatus, ShadowMarketRisk } from '../domain/reminder' +import { ReminderPriority, ReminderStatus, ReminderType } from '../domain/reminder' const provider = MockupReminderProvider @@ -27,25 +27,19 @@ export const reminderService = { const urgentCount = active.filter(r => r.priority === ReminderPriority.URGENT).length - const endOfWeek = new Date(MOCK_TODAY) - endOfWeek.setDate(endOfWeek.getDate() + 7) + // Counts match getHorizon() in ReminderFeed — exclusive, non-overlapping buckets const dueThisWeek = active.filter(r => { const d = daysDiff(r.dueDate) - return d >= 0 && d <= 7 + return d >= 1 && d <= 7 }).length - const endOfMonth = new Date(MOCK_TODAY) - endOfMonth.setDate(endOfMonth.getDate() + 30) const dueThisMonth = active.filter(r => { const d = daysDiff(r.dueDate) - return d >= 0 && d <= 30 + return d >= 8 && d <= 30 }).length - const schattenmarktReadyCount = reminders.filter( - r => - r.status === ReminderStatus.ACTIVE && - !r.schattenmarktEnabled && - (r.shadowMarketRisk === ShadowMarketRisk.HIGH), + const schattenmarktReadyCount = active.filter( + r => r.type === ReminderType.SCHATTENMARKT_RELEASE, ).length const overdueCount = active.filter(r => daysDiff(r.dueDate) <= 0).length