eletrotupi / tcc/ frontend/app/(tabs)/new/entry.tsxb4ed0dbe37bd3128e040c3ce7d1ed9784bba4951
6.5 KB | 217 lines Raw
1
import { useState, useEffect } from "react";
2
import { Link, router, useLocalSearchParams } from "expo-router";
3

4
import { View, StyleSheet, ScrollView } from "react-native";
5

6
import { Text } from "@/components/ui/Text";
7
import { SafeAreaView } from "react-native-safe-area-context";
8
import { ThemedView } from "@/components/misc/themed-view";
9
import { ScreenLayout } from "@/components/ui/ScreenLayout";
10
import { useAuth } from "@/context/AuthContext";
11
import { Grid, Col, Row, Between, Center } from "@/components/ui/LayoutHelpers";
12
import { Card } from "@/components/ui/Cards";
13
import { Button } from "@/components/ui/Button";
14
import { Input, TextArea } from "@/components/ui/Input";
15
import { Section, SectionHeader } from "@/components/ui/Sections";
16
import { Spacing, Typography, Colors } from "@/constants/theme";
17
import { ScaleSlider } from "@/components/ui/ScaleSlider";
18
import { MoodComponentCard } from "@/components/ui/MoodComponentCard";
19
import { Ionicons } from "@expo/vector-icons";
20
import { useThemeColor, useCreateMoodEntry, usePatchCareAction } from "@/hooks";
21
import { useMoodEntryStore, useCareActionLinkStore } from "@/stores";
22

23
import { MOODS, getMood } from "@/constants/moods";
24

25
import { intensityToValue } from "@/constants/mood-components";
26

27
import { apiClient } from "@/lib/api";
28

29
export default function NewMoodEntry() {
30
  const { user } = useAuth();
31
  const tintColor = useThemeColor({}, "tint");
32

33
  const { initialMood } = useLocalSearchParams();
34
  const [annotation, setAnnotation] = useState();
35
  const [stress, setStress] = useState(0);
36
  const [anxiety, setAnxiety] = useState(0);
37
  const [energy, setEnergy] = useState(0);
38

39
  const { selectedMood, setSelectedMood, components, reset } =
40
    useMoodEntryStore();
41

42
  const createMoodEntry = useCreateMoodEntry();
43
  const patchCareAction = usePatchCareAction();
44

45
  useEffect(() => {
46
    if (initialMood) setSelectedMood(getMood(initialMood));
47
  }, [initialMood]);
48

49
  useEffect(() => {
50
    return () => reset();
51
  }, []);
52

53
  const saveMoodEntry = async () => {
54
    const data = {
55
      selectedMood: selectedMood?.id.toUpperCase(),
56
      stressLevel: stress,
57
      energyLevel: energy,
58
      anxietyLevel: anxiety,
59
      moment: new Date(),
60
      annotation: annotation,
61
      moodComponents: components.map((c) => ({
62
        component: c.id.toUpperCase(),
63
        intensity: intensityToValue(c.intensity),
64
      })),
65
    };
66

67
    const result = await createMoodEntry.mutateAsync(data);
68
    const moodId = result.mood.id;
69

70
    const careActionId = useCareActionLinkStore.getState().linkMood();
71
    if (careActionId && moodId) {
72
      await patchCareAction.mutateAsync({
73
        id: String(careActionId),
74
        data: { moodId },
75
      });
76
    }
77

78
    reset();
79

80
    router.replace(`/new/post-mood?moodId=${moodId}`);
81
  };
82

83
  const editComponents = () => {
84
    router.push("/entry/mood-components");
85
  };
86

87
  return (
88
    <View>
89
      <ScrollView scrollEventThrottle={16}>
90
        <View style={styles.container}>
91
          <Center>
92
            <Text style={styles.statusPrefix} testID="text-status-prefix">
93
              Como você está se sentindo agora?
94
            </Text>
95

96
            <Text style={styles.statusText}>
97
              {selectedMood?.label || "Neutro"}
98
            </Text>
99
          </Center>
100

101
          <Card style={styles.resumeCard}>
102
            <Text style={styles.infoText}>
103
              Não existe resposta certa ou errada. Estime, de 0 a 10, como tu
104
              percebe tua energia, estresse e ansiedade neste momento. O
105
              objetivo é registrar uma impressão geral, não uma medida precisa.
106
            </Text>
107

108
            <Col gap={24}>
109
              <ScaleSlider
110
                variant="rich"
111
                label="Energia"
112
                value={energy}
113
                onValueChange={setEnergy}
114
                icon={
115
                  <Ionicons name="flower-outline" size={20} color={tintColor} />
116
                }
117
                minLabel="Baixa"
118
                maxLabel="Alta"
119
              />
120

121
              <ScaleSlider
122
                variant="rich"
123
                label="Ansiedade"
124
                value={anxiety}
125
                onValueChange={setAnxiety}
126
                icon={<Ionicons name="sad-outline" size={20} color="#FB923C" />}
127
                minLabel="Calmo"
128
                maxLabel="Ansioso"
129
              />
130

131
              <ScaleSlider
132
                variant="rich"
133
                label="Estresse"
134
                value={stress}
135
                onValueChange={setStress}
136
                icon={<Ionicons name="flame" size={20} color="#f87171" />}
137
                minLabel="Relaxado"
138
                maxLabel="Estressado"
139
              />
140
            </Col>
141
          </Card>
142

143
          <Card style={styles.annotationsCard}>
144
            <TextArea
145
              label="Notas sobre o dia"
146
              type="text"
147
              variant="darkGhost"
148
              onChangeText={(val) => setAnnotation(val)}
149
              value={annotation}
150
              minRows={4}
151
              maxRows={6}
152
              placeholder="Escreva uma nota rápida sobre o seu dia até o momento..."
153
              testID="input-notes"
154
            />
155
          </Card>
156

157
          <Section>
158
            <SectionHeader title="Também estou..." />
159
            {components.length > 0 ? (
160
              <Grid gap={2} style={{ marginTop: 8 }}>
161
                {components.map((comp) => (
162
                  <MoodComponentCard
163
                    key={comp.id}
164
                    id={comp.id}
165
                    intensity={comp.intensity}
166
                  />
167
                ))}
168
              </Grid>
169
            ) : null}
170

171
            <Button
172
              title="Adicionar estados & emoções"
173
              onPress={editComponents}
174
              textStyle={{ fontWeight: 500 }}
175
              variant="dashed"
176
              testID="button-add-mood-components"
177
            />
178
          </Section>
179

180
          <Button
181
            title="Salvar Registro"
182
            onPress={saveMoodEntry}
183
            disabled={!components.length}
184
            testID="button-save-entry"
185
          />
186
        </View>
187
      </ScrollView>
188
    </View>
189
  );
190
}
191

192
const styles = StyleSheet.create({
193
  container: {
194
    gap: 24,
195
    paddingHorizontal: Spacing.containerPadding,
196
    paddingVertical: Spacing.sectionGap,
197
  },
198
  infoText: {
199
    ...Typography.labelSm,
200
    color: Colors.light.textSecondary,
201
    marginBottom: 20,
202
    fontWeight: "400" as const,
203
  },
204
  statusText: {
205
    ...Typography.headlineXg,
206
    fontWeight: 900
207
  },
208
  statusPrefix: {
209
    ...Typography.bodyMd,
210
  },
211
  annotationsCard: {
212
    padding: Spacing.cardGap,
213
  },
214
  resumeCard: {
215
    padding: Spacing.cardGap,
216
  },
217
});