eletrotupi / tcc/ commit / bcb065f

frontend: fetch & display daily sleep insights

Pedro Lucas Porcellis porcellis@eletrotupi.com 1 month ago bcb065f3b6607260c5a5caeae1a32324b723b7d7
Parents: e5be001
4 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  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
}