frontend/history: fix weird offset for sleep records and use the created at
Parents:
f9e8c483 file(s) changed
- frontend/lib/history/mappers.ts +4 -6
- frontend/lib/utils/history.ts +0 -13
- frontend/lib/utils/time.ts +7 -0
frontend/lib/history/mappers.ts
1 1
import type { HistoryCard } from "@/lib/history/types";
2 2
import type { MoodEntry, SleepRecord, Trigger } from "@/lib/api";
3 3
import { getMood } from "@/constants/moods";
4 4
import { parse, setHours } from "date-fns";
5 5
▸ 29 unchanged lines
35 35
variant: "danger",
36 36
};
37 37
}
38 38
39 39
export function mapSleepToHistoryCard(record: SleepRecord): HistoryCard {
40 +
console.log("mapping...", record)
40 41
const hours = Math.floor(record.average);
41 42
const minutes = Math.round((record.average - hours) * 60);
42 43
const duration = `${hours}h ${minutes.toString().padStart(2, "0")}min`;
43 -
// Force local noon so timezone shifts can't bleed into the previous day
44 -
const dateStr = typeof record.date === 'string'
45 -
? record.date.slice(0, 10) // "2026-05-24"
46 -
: record.date.toISOString().slice(0, 10)
47 -
48 -
const timestamp = `${dateStr}T12:00:00` // local noon, no UTC funny business
44 +
const timestamp = typeof record.createdAt === 'string'
45 +
? record.createdAt
46 +
: record.createdAt.toISOString();
49 47
50 48
return {
51 49
id: `sleep-${record.id}`,
52 50
category: "sleep",
53 51
timestamp,
▸ 13 unchanged lines
67 65
summary: [record.category, record.comment].filter(Boolean).join(" · "),
68 66
badge: undefined,
69 67
raw: record,
70 68
};
71 69
}
frontend/lib/utils/history.ts
1 1
// TODO: add a barrel import here ffs
2 2
import type { HistoryCard, HistoryCategory } from '@/lib/history/types'
3 3
4 4
export function mergeAndSort(cards: HistoryCard[][]): HistoryCard[] {
5 5
return cards
▸ 1 unchanged lines
7 7
.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())
8 8
}
9 9
10 10
export function groupByDate(cards: HistoryCard[]): Record<string, HistoryCard[]> {
11 11
return cards.reduce<Record<string, HistoryCard[]>>((acc, card) => {
12 -
// If the key for this card is sleep, we have to set the hours to
13 -
// mid day since sleep records dont have a specific time
14 -
if (card.category === 'sleep') {
15 -
const date = new Date(card.timestamp)
16 -
date.setHours(12)
17 -
card.timestamp = date.toISOString()
18 -
}
19 -
20 12
const key = new Date(card.timestamp).toLocaleDateString('pt-BR', {
21 13
weekday: 'long',
22 14
day: 'numeric',
23 15
month: 'long',
24 16
});
25 17
26 -
if (card.category === 'sleep') {
27 -
console.log("Key for this sleep card", key, card.timestamp)
28 -
}
29 -
30 -
// XXX: Hacky as fuck
31 18
(acc[key] ??= []).push(card)
32 19
33 20
return acc
34 21
}, {})
35 22
}
▸ 3 unchanged lines
39 26
active: HistoryCategory | 'all',
40 27
): HistoryCard[] {
41 28
if (active === 'all') return cards
42 29
return cards.filter(c => c.category === active)
43 30
}
frontend/lib/utils/time.ts
1 1
import { format, isToday, isYesterday } from 'date-fns';
2 2
import { ptBR } from 'date-fns/locale';
3 3
4 4
type TimeBadgeVariant = 'morning' | 'afternoon' | 'night' | 'latenight';
5 5
▸ 26 unchanged lines
32 32
if (isToday(date)) return `Hoje, ${format(date, "dd/MM")}`;
33 33
if (isYesterday(date)) return `Ontem, ${format(date, "dd/MM")}`;
34 34
35 35
return format(date, "dd/MM/yyyy", { locale: ptBR });
36 36
}
37 +
38 +
// Parse a date-only string (YYYY-MM-DD or ISO UTC midnight) as local noon
39 +
// to prevent timezone offsets from shifting the calendar day
40 +
export const parseDateOnly = (dateStr: string | Date): Date => {
41 +
const iso = typeof dateStr === 'string' ? dateStr : dateStr.toISOString();
42 +
return new Date(`${iso.slice(0, 10)}T12:00:00`);
43 +
};