frontend: fetch & display daily sleep insights
Parents:
e5be0014 file(s) changed
- frontend/components/ui/DailyEnergyWidget.tsx +1 -1
- frontend/components/ui/DailySleepWidget.tsx +19 -6
- frontend/hooks/useInsights.queries.ts +1 -0
- frontend/lib/api/types.ts +9 -1
frontend/components/ui/DailyEnergyWidget.tsx
1 1
import { ActivityIndicator, StyleSheet, Text, View } from "react-native";
2 2
import { Card } from "@/components/ui/Cards";
3 3
import { useInsight } from "@/hooks/useInsights.queries";
4 4
import { Ionicons } from "@expo/vector-icons";
5 5
import { Typography, Spacing, Colors, BorderRadius } from "@/constants/theme";
6 6
7 7
export const DailyEnergyWidget = () => {
8 -
const { data: insight, isLoading } = useInsight("DAILY_ENERGY", 0);
8 +
const { data: insight, isLoading } = useInsight("DAILY_ENERGY");
9 9
10 10
const metadata = insight?.metadata as {
11 11
peak: number;
12 12
trough: number;
13 13
entryCount: number;
▸ 81 unchanged lines
95 95
fontSize: 11,
96 96
fontWeight: 600,
97 97
lineHeight: 16.5,
98 98
},
99 99
});
frontend/components/ui/DailySleepWidget.tsx
1 1
import React from "react";
2 2
import { View, Text, StyleSheet, ActivityIndicator } from "react-native";
3 3
import { Card } from "./Cards";
4 4
import { Colors, Spacing, Typography } from "@/constants/theme";
5 5
import { Ionicons } from "@expo/vector-icons";
6 +
import { useInsight } from "@/hooks/useInsights.queries";
6 7
7 8
export const DailySleepWidget = () => {
8 -
//const { data: insight, isLoading } = useInsight("DAILY_ENERGY", 0);
9 -
const isLoading = false;
10 -
const insight = null;
9 +
const { data: insight, isLoading } = useInsight("DAILY_SLEEP");
10 +
11 +
const metadata = insight?.metadata as
12 +
| {
13 +
diffStr: string;
14 +
diffMinutes: number;
15 +
}
16 +
| undefined;
17 +
18 +
const diffColor = metadata?.diffMinutes
19 +
? metadata.diffMinutes < 0
20 +
? Colors.light.danger
21 +
: Colors.light.tint
22 +
: Colors.light.tint;
11 23
12 24
return (
13 25
<Card style={{ padding: Spacing.cardGap }}>
14 26
<View
15 27
style={{
▸ 14 unchanged lines
30 42
<ActivityIndicator size="small" style={{ paddingBottom: 50 }} />
31 43
</View>
32 44
) : insight ? (
33 45
<>
34 46
<Text style={{ ...Typography.headlineMd, marginBottom: 10 }}>
35 -
7h 30m
47 +
{insight.body}
36 48
</Text>
37 -
<Text style={styles.indicatorGreen}>+45min que ontem</Text>
49 +
<Text style={{ ...styles.indicatorGreen, color: diffColor }}>
50 +
{metadata?.diffStr}
51 +
</Text>
38 52
</>
39 53
) : (
40 54
<>
41 55
<Text style={styles.empty}>
42 56
Não há dados disponíveis para o dia de hoje
▸ 9 unchanged lines
52 66
container: {
53 67
flex: 1,
54 68
padding: Spacing.cardGap,
55 69
},
56 70
indicatorGreen: {
57 -
color: Colors.light.tint,
58 71
fontSize: 11,
59 72
fontWeight: 600,
60 73
lineHeight: 16.5,
61 74
},
62 75
empty: {
63 76
...Typography.labelSm,
64 77
opacity: 0.5,
65 78
},
66 79
});
frontend/hooks/useInsights.queries.ts
1 1
import { useQuery } from "@tanstack/react-query";
2 2
import { apiClient, Insight, InsightType, InsightPeriod } from "@/lib/api";
3 3
4 4
export const insightKeys = {
5 5
all: () => ["insights"] as const,
▸ 18 unchanged lines
24 24
const INSIGHT_PERIOD: Record<InsightType, InsightPeriod> = {
25 25
DAILY_ENERGY: "DAILY",
26 26
MOOD_TREND: "WEEKLY",
27 27
ENERGY_SLEEP_CORRELATION: "WEEKLY",
28 28
TRIGGER_PATTERN: "WEEKLY",
29 +
DAILY_SLEEP: "DAILY",
29 30
};
30 31
31 32
export const useInsight = (type: InsightType) => {
32 33
const period = INSIGHT_PERIOD[type];
33 34
const staleTime = INSIGHT_STALE_TIMES[period];
▸ 13 unchanged lines
47 48
queryKey: insightKeys.list(filters),
48 49
queryFn: () => apiClient.getInsights(filters).then((res) => res.insights),
49 50
staleTime: 1000 * 60 * 15,
50 51
});
51 52
};
frontend/lib/api/types.ts
1 1
export interface User {
2 2
id: number;
3 3
email: string;
4 4
firstName: string;
5 5
lastName?: string;
▸ 123 unchanged lines
129 129
// Gotta keep those in sync with the Prisma schema
130 130
export type InsightType =
131 131
| "MOOD_TREND"
132 132
| "ENERGY_SLEEP_CORRELATION"
133 133
| "TRIGGER_PATTERN"
134 -
| "DAILY_ENERGY";
134 +
| "DAILY_ENERGY"
135 +
| "DAILY_SLEEP";
135 136
136 137
export type InsightPeriod = "DAILY" | "WEEKLY" | "MONTHLY";
137 138
138 139
export type InsightMetadata =
139 140
| {
▸ 21 unchanged lines
161 162
avgEnergy: number;
162 163
dayTrend: number | null;
163 164
peak: number;
164 165
trough: number;
165 166
entryCount: number;
167 +
}
168 +
| {
169 +
type: "DAILY_SLEEP";
170 +
totalHours: number;
171 +
diffMinutes: number;
172 +
sessionCount: number;
173 +
hadNaps: boolean;
166 174
};
167 175
168 176
export type Insight = {
169 177
id: number;
170 178
type: InsightType;
▸ 23 unchanged lines
194 202
}
195 203
196 204
export interface TriggerResponse {
197 205
trigger: Trigger;
198 206
}