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

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

6
import { Text } from "@/components/ui/Text";
7
import { Grid, Col, Center } from "@/components/ui/LayoutHelpers";
8
import { Card } from "@/components/ui/Cards";
9
import { Button } from "@/components/ui/Button";
10
import { TextArea } from "@/components/ui/Input";
11
import { Section, SectionHeader } from "@/components/ui/Sections";
12
import { Spacing, Typography, Colors } from "@/constants/theme";
13
import { ScaleSlider } from "@/components/ui/ScaleSlider";
14
import { MoodComponentCard } from "@/components/ui/MoodComponentCard";
15
import { Ionicons } from "@expo/vector-icons";
16
import { useThemeColor, useCreateMoodEntry, usePatchCareAction } from "@/hooks";
17
import { useMoodEntryStore, useCareActionLinkStore } from "@/stores";
18

19
import { getMood } from "@/constants/moods";
20

21
import { intensityToValue } from "@/constants/mood-components";
22

23
export default function NewMoodEntry() {
24
  const tintColor = useThemeColor({}, "tint");
25

26
  const { initialMood } = useLocalSearchParams<{ initialMood?: string }>();
27
  const [annotation, setAnnotation] = useState('');
28
  const [stress, setStress] = useState(0);
29
  const [anxiety, setAnxiety] = useState(0);
30
  const [energy, setEnergy] = useState(0);
31

32
  const { selectedMood, setSelectedMood, components, reset } =
33
    useMoodEntryStore();
34

35
  const createMoodEntry = useCreateMoodEntry();
36
  const patchCareAction = usePatchCareAction();
37

38
  useEffect(() => {
39
    if (initialMood) setSelectedMood(initialMood);
40
  }, [initialMood, setSelectedMood]);
41

42
  useEffect(() => {
43
    return () => reset();
44
  }, [reset]);
45

46
  const saveMoodEntry = async () => {
47
    const data = {
48
      selectedMood: (selectedMood ?? 'neutral').toUpperCase(),
49
      stressLevel: stress,
50
      energyLevel: energy,
51
      anxietyLevel: anxiety,
52
      moment: new Date(),
53
      annotation: annotation,
54
      moodComponents: components.map((c) => ({
55
        component: c.id.toUpperCase(),
56
        intensity: intensityToValue(c.intensity),
57
      })),
58
    };
59

60
    const result = await createMoodEntry.mutateAsync(data);
61
    const moodId = result.mood.id;
62

63
    const careActionId = useCareActionLinkStore.getState().linkMood();
64
    if (careActionId && moodId) {
65
      await patchCareAction.mutateAsync({
66
        id: String(careActionId),
67
        data: { moodId },
68
      });
69
    }
70

71
    reset();
72

73
    router.replace(`/new/post-mood?moodId=${moodId}`);
74
  };
75

76
  const editComponents = () => {
77
    router.push("/entry/mood-components");
78
  };
79

80
  return (
81
    <View>
82
      <ScrollView scrollEventThrottle={16}>
83
        <View style={styles.container}>
84
          <Center>
85
            <Text style={styles.statusPrefix} testID="text-status-prefix">
86
              Como você está se sentindo agora?
87
            </Text>
88

89
            <Text style={styles.statusText}>
90
              {getMood(selectedMood ?? '')?.label ?? "Neutro"}
91
            </Text>
92
          </Center>
93

94
          <Card style={styles.resumeCard}>
95
            <Text style={styles.infoText}>
96
              Não existe resposta certa ou errada. Estime, de 0 a 10, como tu
97
              percebe tua energia, estresse e ansiedade neste momento. O
98
              objetivo é registrar uma impressão geral, não uma medida precisa.
99
            </Text>
100

101
            <Col gap={24}>
102
              <ScaleSlider
103
                variant="rich"
104
                label="Energia"
105
                value={energy}
106
                onValueChange={setEnergy}
107
                icon={
108
                  <Ionicons name="flower-outline" size={20} color={tintColor} />
109
                }
110
                minLabel="Baixa"
111
                maxLabel="Alta"
112
              />
113

114
              <ScaleSlider
115
                variant="rich"
116
                label="Ansiedade"
117
                value={anxiety}
118
                onValueChange={setAnxiety}
119
                icon={<Ionicons name="sad-outline" size={20} color="#FB923C" />}
120
                minLabel="Calmo"
121
                maxLabel="Ansioso"
122
              />
123

124
              <ScaleSlider
125
                variant="rich"
126
                label="Estresse"
127
                value={stress}
128
                onValueChange={setStress}
129
                icon={<Ionicons name="flame" size={20} color="#f87171" />}
130
                minLabel="Relaxado"
131
                maxLabel="Estressado"
132
              />
133
            </Col>
134
          </Card>
135

136
          <Card style={styles.annotationsCard}>
137
            <TextArea
138
              label="Notas sobre o dia"
139
              variant="darkGhost"
140
              onChangeText={(val) => setAnnotation(val)}
141
              value={annotation}
142
              minRows={4}
143
              maxRows={6}
144
              placeholder="Escreva uma nota rápida sobre o seu dia até o momento..."
145
              testID="input-notes"
146
            />
147
          </Card>
148

149
          <Section>
150
            <SectionHeader title="Também estou..." />
151
            {components.length > 0 ? (
152
              <Grid gap={2} style={{ marginTop: 8 }}>
153
                {components.map((comp) => (
154
                  <MoodComponentCard
155
                    key={comp.id}
156
                    id={comp.id}
157
                    intensity={comp.intensity}
158
                  />
159
                ))}
160
              </Grid>
161
            ) : null}
162

163
            <Button
164
              title="Adicionar estados & emoções"
165
              onPress={editComponents}
166
              textStyle={{ fontWeight: 500 }}
167
              variant="dashed"
168
              testID="button-add-mood-components"
169
            />
170
          </Section>
171

172
          <Button
173
            title="Salvar Registro"
174
            onPress={saveMoodEntry}
175
            disabled={!components.length}
176
            testID="button-save-entry"
177
          />
178
        </View>
179
      </ScrollView>
180
    </View>
181
  );
182
}
183

184
const styles = StyleSheet.create({
185
  container: {
186
    gap: 24,
187
    paddingHorizontal: Spacing.containerPadding,
188
    paddingVertical: Spacing.sectionGap,
189
  },
190
  infoText: {
191
    ...Typography.labelSm,
192
    color: Colors.light.textSecondary,
193
    marginBottom: 20,
194
    fontWeight: "400" as const,
195
  },
196
  statusText: {
197
    ...Typography.headlineXg,
198
    fontWeight: 900
199
  },
200
  statusPrefix: {
201
    ...Typography.bodyMd,
202
  },
203
  annotationsCard: {
204
    padding: Spacing.cardGap,
205
  },
206
  resumeCard: {
207
    padding: Spacing.cardGap,
208
  },
209
});