diff --git a/client/src/Utils/DataUtils.ts b/client/src/Utils/DataUtils.ts index 28fdfb7b5..3562d86ed 100644 --- a/client/src/Utils/DataUtils.ts +++ b/client/src/Utils/DataUtils.ts @@ -86,7 +86,7 @@ export const getResponseColor = ( return normalizeToHex(safe.end); }; -const MIN_HEIGHT_PCT = 8; +export const MIN_HEIGHT_PCT = 8; const CAP_PERCENTILE = 95; const percentile = (sortedValues: number[], p: number): number => { @@ -114,3 +114,24 @@ export const computeBarHeights = ( return Math.max(MIN_HEIGHT_PCT, Math.min(100, (value / cap) * 100)); }); }; + +export const computeDayBarHeights = ( + buckets: { date: string; avgResponseTime: number | null }[] +): Map => { + const values = buckets.map((bucket) => + typeof bucket.avgResponseTime === "number" && Number.isFinite(bucket.avgResponseTime) + ? Math.max(0, bucket.avgResponseTime) + : 0 + ); + + const sorted = values.slice().sort((a, b) => a - b); + const cap = percentile(sorted, CAP_PERCENTILE); + return new Map( + buckets.map((bucket, i) => [ + bucket.date, + cap <= 0 + ? MIN_HEIGHT_PCT + : Math.max(MIN_HEIGHT_PCT, Math.min(100, (values[i] / cap) * 100)), + ]) + ); +}; diff --git a/client/src/Utils/TimeUtils.ts b/client/src/Utils/TimeUtils.ts index 4112967ab..9b809e1da 100644 --- a/client/src/Utils/TimeUtils.ts +++ b/client/src/Utils/TimeUtils.ts @@ -120,3 +120,18 @@ export const formatDuration = (ms: number, verbose: boolean = false, hasSpace = } return formatted; }; + +export const enumerateDays = (days: number, timeZone: string): string[] => { + const formatter = new Intl.DateTimeFormat("en-CA", { + timeZone, + year: "numeric", + month: "2-digit", + day: "2-digit", + }); + const [year, month, day] = formatter.format(new Date()).split("-").map(Number); + const todayUtc = Date.UTC(year, month - 1, day); + const DAY_MS = 24 * 60 * 60 * 1000; + return Array.from({ length: days }, (_, i) => + new Date(todayUtc - (days - 1 - i) * DAY_MS).toISOString().slice(0, 10) + ); +};