eletrotupi / tcc/ commit / e2b786d

frontend: draft fix to sleep not having time

Pedro Lucas Porcellis porcellis@eletrotupi.com 1 month ago e2b786d3d7b4d089bb8eb05b23eafd24b3ab2774
Parents: 3f30f22
5 file(s) changed
  • frontend/app/(tabs)/settings.tsx +1 -1
  • frontend/hooks/useHistoryFeed.ts +4 -0
  • frontend/hooks/useSleepRecord.queries.ts +14 -0
  • frontend/lib/history/mappers.ts +8 -2
  • frontend/lib/utils/history.ts +12 -0
frontend/app/(tabs)/settings.tsx
1 1
import {
2 2
  TouchableOpacity,
3 3
  StyleSheet,
4 4
  Text,
5 5
  SectionList,
▸ 207 unchanged lines
213 213
                  color: Colors.light.text,
214 214
                  fontSize: 14,
215 215
                  fontWeight: "500" as const,
216 216
                }}
217 217
              >
218 -
                Modo Invisível
218 +
                Criptografia (EE2E)
219 219
              </Text>
220 220
            </View>
221 221

222 222
            <Ionicons name="chevron-forward" size={24} color={textColor} />
223 223
          </TouchableOpacity>
▸ 82 unchanged lines
306 306
    height: StyleSheet.hairlineWidth,
307 307
    backgroundColor: "#D1D5DB",
308 308
    marginVertical: 16,
309 309
  },
310 310
});
frontend/hooks/useHistoryFeed.ts
1 1
// hooks/useHistoryFeed.ts
2 2
import { useMemo } from "react";
3 3
import {
4 4
  mergeAndSort,
5 5
  filterByCategory,
▸ 20 unchanged lines
26 26
    const merged = mergeAndSort([
27 27
      moods.map(mapMoodToHistoryCard),
28 28
      sleepRecords.map(mapSleepToHistoryCard),
29 29
      triggers.map(mapTriggerToHistoryCard),
30 30
    ]);
31 +

32 +
    console.log("Sleep records", sleepRecords)
33 +
    console.log("Merged data", merged)
34 +

31 35
    const filtered = filterByCategory(merged, activeFilter);
32 36
    return groupByDate(filtered);
33 37
  }, [moods, sleepRecords, triggers, activeFilter]);
34 38

35 39
  // TODO: expose the isLoading here
36 40
  return grouped;
37 41
}
frontend/hooks/useSleepRecord.queries.ts
1 1
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
2 2

3 3
import { apiClient, SleepRecord, SleepRecordPayload } from "@/lib/api";
4 +
import { insightKeys } from "./useInsights.queries";
4 5

5 6
export const sleepRecordKeys = {
6 7
  all: () => ["sleep-records"] as const,
7 8
  lists: () => [...sleepRecordKeys.all(), "list"] as const,
8 9
  list: (filters?: SleepRecordFilters) =>
▸ 58 unchanged lines
67 68
      }
68 69
    },
69 70

70 71
    onSuccess: () => {
71 72
      queryClient.invalidateQueries({ queryKey: sleepRecordKeys.lists() });
73 +

74 +
      // Invalidate insights, so we can force refresh
75 +
      setTimeout(() => {
76 +
        queryClient.invalidateQueries({
77 +
          queryKey: insightKeys.byType("DAILY_ENERGY"),
78 +
        });
79 +
        queryClient.invalidateQueries({
80 +
          queryKey: insightKeys.byType("MOOD_TREND"),
81 +
        });
82 +
        queryClient.invalidateQueries({
83 +
          queryKey: insightKeys.byType("ENERGY_SLEEP_CORRELATION"),
84 +
        });
85 +
      }, 2000);
72 86
    },
73 87
  });
74 88
};
75 89

76 90
// Delete a sleep record with optimistic removal
▸ 24 unchanged lines
101 115
    onSuccess: () => {
102 116
      queryClient.invalidateQueries({ queryKey: sleepRecordKeys.lists() });
103 117
    },
104 118
  });
105 119
};
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 -
import { parse } from "date-fns";
4 +
import { parse, setHours } from "date-fns";
5 5

6 6
export function mapMoodToHistoryCard(mood: MoodEntry): HistoryCard {
7 7
  const moodLabel = getMood(mood.selectedMood);
8 8
  const components = mood.moodComponents
9 9
    .map((c) => c.component.charAt(0) + c.component.slice(1).toLowerCase())
▸ 28 unchanged lines
38 38

39 39
export function mapSleepToHistoryCard(record: SleepRecord): HistoryCard {
40 40
  const hours = Math.floor(record.average);
41 41
  const minutes = Math.round((record.average - hours) * 60);
42 42
  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
43 49

44 50
  return {
45 51
    id: `sleep-${record.id}`,
46 52
    category: "sleep",
47 -
    timestamp: record.date.toString(),
53 +
    timestamp,
48 54
    title: "Sono",
49 55
    summary: [duration, record.annotations].filter(Boolean).join(" · "),
50 56
    badge: sleepQualityBadge(record.average),
51 57
    raw: record,
52 58
  };
▸ 8 unchanged lines
61 67
    summary: [record.category, record.comment].filter(Boolean).join(" · "),
62 68
    badge: undefined,
63 69
    raw: record,
64 70
  };
65 71
}
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 +

12 20
    const key = new Date(card.timestamp).toLocaleDateString('pt-BR', {
13 21
      weekday: 'long',
14 22
      day: 'numeric',
15 23
      month: 'long',
16 24
    });
25 +

26 +
    if (card.category === 'sleep') {
27 +
      console.log("Key for this sleep card", key, card.timestamp)
28 +
    }
17 29

18 30
    // XXX: Hacky as fuck
19 31
    (acc[key] ??= []).push(card)
20 32

21 33
    return acc
▸ 5 unchanged lines
27 39
  active: HistoryCategory | 'all',
28 40
): HistoryCard[] {
29 41
  if (active === 'all') return cards
30 42
    return cards.filter(c => c.category === active)
31 43
}