frontend: introduce history mappers and specific types

So the history tab will be responsible for crunching all events logged
into the system into an unifying layout, so we need to sort of map into
a unifying type, extract and calculate each of the data requirements,
etc
Pedro Lucas Porcellis porcellis@eletrotupi.com 22 days ago 4cbb518a275506db4d3fac4d5cfe87608f489f44
Parents: 7f84688
2 file(s) changed
  • frontend/lib/history/mappers.ts +53 -0
  • frontend/lib/history/types.ts +17 -0
frontend/lib/history/mappers.ts
@@ -0,0 +1,53 @@
1 + import type { HistoryCard } from '@/lib/history/types'
2 + import type { MoodEntry, SleepRecord } from '@/lib/api';
3 + import { getMood } from '@/constants/moods';
4 + import { parse } from 'date-fns';
5 +
6 + export function mapMoodToHistoryCard(mood: MoodEntry): HistoryCard {
7 + const moodLabel = getMood(mood.selectedMood) ?? mood.selectedMood
8 + const components = mood.moodComponents
9 + .map(c => c.component.charAt(0) + c.component.slice(1).toLowerCase())
10 + .join(', ')
11 +
12 + const summary = [
13 + components || null,
14 + mood.annotation || null,
15 + ].filter(Boolean).join(' · ')
16 +
17 + return {
18 + id: `mood-${mood.id}`,
19 + category: 'mood',
20 + timestamp: mood.moment,
21 + title: moodLabel,
22 + summary: summary || 'Sem detalhes',
23 + badge: undefined,
24 + raw: mood
25 + }
26 + }
27 +
28 + // Sleep Records
29 +
30 + function sleepQualityBadge(hours: number): HistoryCard['badge'] {
31 + if (hours >= 7) return { label: 'Excelente', variant: 'success' }
32 + if (hours >= 5) return { label: 'Regular', variant: 'warning' }
33 +
34 + return {
35 + label: 'Ruim', variant: 'danger'
36 + }
37 + }
38 +
39 + export function mapSleepToHistoryCard(record: SleepRecord): HistoryCard {
40 + const hours = Math.floor(record.average)
41 + const minutes = Math.round((record.average - hours) * 60)
42 + const duration = `${hours}h ${minutes.toString().padStart(2, '0')}min`
43 +
44 + return {
45 + id: `sleep-${record.id}`,
46 + category: 'sleep',
47 + timestamp: record.date,
48 + title: 'Sono',
49 + summary: [duration, record.annotations].filter(Boolean).join(' · '),
50 + badge: sleepQualityBadge(record.average),
51 + raw: record
52 + }
53 + }
frontend/lib/history/types.ts
@@ -0,0 +1,17 @@
1 + import type { MoodEntry, SleepRecord } from '@/lib/api';
2 + export type HistoryCategory = 'mood' | 'sleep' | 'trigger' | 'intervention'
3 +
4 + export type HistoryBadge = {
5 + label: string
6 + variant: 'neutral' | 'warning' | 'success' | 'danger' | 'info'
7 + }
8 +
9 + export type HistoryCard = {
10 + id: string // "<category>-<id>" to avoid collisions
11 + category: HistoryCategory
12 + timestamp: string // ISO string — used for sorting and display
13 + title: string
14 + summary: string
15 + badge?: HistoryBadge,
16 + raw: MoodEntry | SleepRecord
17 + }