eletrotupi / tcc/ commit / a2d0b31

frontend: add daily energy widget

Pedro Lucas Porcellis porcellis@eletrotupi.com · 4 months ago a2d0b31fb95ea93e87b5ebca20daa4402d0a5b99 Browse files
Parents 05053ef
Changed files
2
Additions
+133
Deletions
-45
frontend/app/(tabs)/new/index.tsx
1 1
import { useEffect, useState } from "react";
2 2
import { StyleSheet, View, Text, ActivityIndicator } from "react-native";
3 3

4 4
import { ThemedText } from "@/components/misc/themed-text";
5 5
import { ThemedView } from "@/components/misc/themed-view";
23 23
import { MoodDefinition, MOODS } from "@/constants/moods";
24 24

25 25
import { useThemeColor, useMoodEntries } from "@/hooks";
26 26

27 27
import MoodEntryLog from "@/components/ui/MoodEntryLog";
28 +
import { DailyEnergyWidget } from "@/components/ui/DailyEnergyWidget";
28 29

29 30
export default function New() {
30 31
  const { user } = useAuth();
31 32
  const [mood, setMood] = useState<string>("good");
32 33
  const { data, isLoading } = useMoodEntries({ limit: 5 });
38 39
    // TODO: Set down on camelCase vs kebab case
39 40
    router.navigate(`/new/entry?initialMood=${mood}`);
40 41
  };
41 42

42 43
  const onNotificationPress = () => {
43 -
    router.push('/notifications');
44 -
  }
44 +
    router.push("/notifications");
45 +
  };
45 46

46 47
  return (
47 48
    <ScreenLayout
48 49
      userName={user.firstName}
49 50
      userAvatar={user.avatarURL}
82 83
        </Card>
83 84
      </Section>
84 85

85 86
      {/* TODO: Check whether we gonna have to generate these on demand */}
86 87
      <Section>
87 -
        <Grid gap={4}>
88 -
          <Card style={{ padding: Spacing.cardGap }}>
89 -
            <View
90 -
              style={{
91 -
                flex: 1,
92 -
                flexDirection: "row",
93 -
                flexGrow: 0,
94 -
                paddingVertical: 10,
95 -
              }}
96 -
            >
97 -
              <Ionicons name="flash" size={20} color="#64748B" />
88 +
        <View
89 +
          style={[
90 +
            {
91 +
              flexDirection: "row",
92 +
              gap: 16,
93 +
            },
94 +
          ]}
95 +
        >
96 +
          <View style={{ flex: 1 }}>
97 +
            <DailyEnergyWidget />
98 +
          </View>
98 99

99 -
              <Text style={{ ...Typography.headlineMd, marginBottom: 10 }}>
100 -
                Energia
101 -
              </Text>
102 -
            </View>
100 +
          <View style={{ flex: 1 }}>
101 +
            <Card style={{ padding: Spacing.cardGap }}>
102 +
              <View
103 +
                style={{
104 +
                  flex: 1,
105 +
                  flexDirection: "row",
106 +
                  flexGrow: 0,
107 +
                  paddingVertical: 10,
108 +
                }}
109 +
              >
110 +
                <Ionicons name="moon" size={20} color="#64748B" />
103 111

104 -
            <Text style={{ ...Typography.headlineMd, marginBottom: 10 }}>
105 -
              Média Alta
106 -
            </Text>
107 -

108 -
            <View style={styles.lineTrack}>
109 -
              <View style={[styles.lineFill, { width: `35%` }]} />
110 -
            </View>
111 -
          </Card>
112 -

113 -
          <Card style={{ padding: Spacing.cardGap }}>
114 -
            <View
115 -
              style={{
116 -
                flex: 1,
117 -
                flexDirection: "row",
118 -
                flexGrow: 0,
119 -
                paddingVertical: 10,
120 -
              }}
121 -
            >
122 -
              <Ionicons name="moon-outline" size={20} color="#64748B" />
112 +
                <Text style={{ ...Typography.headlineMd, marginBottom: 10 }}>
113 +
                  Sono
114 +
                </Text>
115 +
              </View>
123 116

124 117
              <Text style={{ ...Typography.headlineMd, marginBottom: 10 }}>
125 -
                Sono
118 +
                7h 30m
126 119
              </Text>
127 -
            </View>
128 120

129 -
            <Text style={{ ...Typography.headlineMd, marginBottom: 10 }}>
130 -
              7h 30m
131 -
            </Text>
132 -

133 -
            <Text style={styles.indicatorGreen}>+45min que ontem</Text>
134 -
          </Card>
135 -
        </Grid>
121 +
              <Text style={styles.indicatorGreen}>+45min que ontem</Text>
122 +
            </Card>
123 +
          </View>
124 +
        </View>
136 125
      </Section>
137 126

138 127
      <Section>
139 128
        <SectionHeader title="Registros recentes" />
140 129

189 178
    fontSize: 11,
190 179
    fontWeight: 600,
191 180
    lineHeight: 16.5,
192 181
  },
193 182
});
/dev/null → frontend/components/ui/DailyEnergyWidget.tsx
1 +
import { ActivityIndicator, StyleSheet, Text, View } from "react-native";
2 +
import { Card } from "@/components/ui/Cards";
3 +
import { useInsight } from "@/hooks/useInsights.queries";
4 +
import { Ionicons } from "@expo/vector-icons";
5 +
import { Typography, Spacing, Colors, BorderRadius } from "@/constants/theme";
6 +

7 +
export const DailyEnergyWidget = () => {
8 +
  const { data: insight, isLoading } = useInsight("DAILY_ENERGY", 0);
9 +

10 +
  const metadata = insight?.metadata as {
11 +
    peak: number;
12 +
    trough: number;
13 +
    entryCount: number;
14 +
    avgEnergy: number;
15 +
  };
16 +

17 +
  const avgEnergy = metadata?.avgEnergy;
18 +
  const peak = metadata?.peak;
19 +

20 +
  const energyWidth = (avgEnergy / peak) * 100;
21 +
  const energySummary = () => {
22 +
    if (avgEnergy < 3) return "Energia baixa";
23 +
    if (avgEnergy < 5) return "Media baixa";
24 +
    if (avgEnergy < 7.5) return "Média Alta";
25 +
    return "Energia alta";
26 +
  };
27 +

28 +
  return (
29 +
    <Card style={styles.container}>
30 +
      <View
31 +
        style={{
32 +
          flex: 1,
33 +
          flexDirection: "row",
34 +
          flexGrow: 0,
35 +
          paddingVertical: 10,
36 +
        }}
37 +
      >
38 +
        <Ionicons name="flash" size={20} color="#64748B" />
39 +

40 +
        <Text style={{ ...Typography.headlineMd, marginBottom: 10 }}>
41 +
          Energia
42 +
        </Text>
43 +
      </View>
44 +

45 +
      <View style={{ flex: 1 }}>
46 +
        {isLoading ? (
47 +
          <View style={styles.empty}>
48 +
            <ActivityIndicator size="small" />
49 +
          </View>
50 +
        ) : insight ? (
51 +
          <>
52 +
            <Text style={{ ...Typography.headlineMd, marginBottom: 10 }}>
53 +
              {energySummary()}
54 +
            </Text>
55 +

56 +
            <View style={styles.lineTrack}>
57 +
              <View style={[styles.lineFill, { width: `${energyWidth}%` }]} />
58 +
            </View>
59 +
          </>
60 +
        ) : (
61 +
          <>
62 +
            <Text style={styles.empty}>
63 +
              Não há dados disponíveis para o dia de hoje
64 +
            </Text>
65 +
          </>
66 +
        )}
67 +
      </View>
68 +
    </Card>
69 +
  );
70 +
};
71 +

72 +
const styles = StyleSheet.create({
73 +
  container: {
74 +
    flex: 1,
75 +
    padding: Spacing.cardGap,
76 +
  },
77 +
  empty: {
78 +
    ...Typography.labelSm,
79 +
    opacity: 0.5,
80 +
  },
81 +
  lineTrack: {
82 +
    height: 6,
83 +
    backgroundColor: Colors.light.divider,
84 +
    borderRadius: BorderRadius.full,
85 +
    marginBottom: 4,
86 +
    overflow: "hidden",
87 +
  },
88 +
  lineFill: {
89 +
    height: "100%",
90 +
    backgroundColor: Colors.light.tint,
91 +
    borderRadius: BorderRadius.full,
92 +
  },
93 +
  indicatorGreen: {
94 +
    color: Colors.light.tint,
95 +
    fontSize: 11,
96 +
    fontWeight: 600,
97 +
    lineHeight: 16.5,
98 +
  },
99 +
});