eletrotupi / tcc/ frontend/app/triggers/new.tsx5f371a6dcf2b6758abddc975f2dfa25878ae17a9
6.1 KB | 213 lines Raw
1
import {
2
  View,
3
  Text,
4
  StyleSheet,
5
  KeyboardAvoidingView,
6
  ScrollView,
7
} from "react-native";
8
import { useState } from "react";
9
import { router, useLocalSearchParams } from "expo-router";
10

11
import { Card } from "@/components/ui/Cards";
12
import { TextArea } from "@/components/ui/Input";
13
import { Button } from "@/components/ui/Button";
14
import { Section, SectionHeader } from "@/components/ui/Sections";
15
import { Spacing, Typography, Colors, BorderRadius } from "@/constants/theme";
16
import { Ionicons, MaterialIcons } from "@expo/vector-icons";
17
import { useCreateTrigger, useMoodEntries } from "@/hooks";
18
import { CategoryChips, CategoryOption } from "@/components/ui/CategoryChips";
19
import { TriggerCategory } from "@/constants/triggers";
20
import { TRIGGER_CATEGORY_DEFINITIONS } from "@/constants/trigger-categories";
21
import { TimePicker } from "@/components/ui/TimePicker";
22
import { getMood } from "@/constants/moods";
23
import { LinkRow } from "@/components/ui/LinkRow";
24

25
const TRIGGER_CATEGORIES: CategoryOption<TriggerCategory>[] =
26
  TRIGGER_CATEGORY_DEFINITIONS.map((d) => ({
27
    label: d.label,
28
    value: d.id,
29
    icon: <MaterialIcons size={16} color={d.color} name={d.icon} />,
30
  }));
31

32
export default function NewTrigger() {
33
  const [moment, setMoment] = useState(new Date());
34
  const [comment, setComment] = useState("");
35
  const { category: initialCategory } = useLocalSearchParams<{ category?: string }>();
36
  const [category, setCategory] = useState(initialCategory ?? "WORK");
37
  const createTrigger = useCreateTrigger();
38
  const [linkMood, setLinkMood] = useState(false);
39
  const { data: moodEntries, isLoading: isLoadingMood } = useMoodEntries({
40
    limit: 1,
41
  });
42

43
  const latestMood = moodEntries?.entries[0] ?? null;
44
  const moodDef = latestMood
45
    ? getMood(latestMood.selectedMood.toLowerCase())
46
    : null;
47

48
  const save = async () => {
49
    const data = {
50
      moment,
51
      comment,
52
      category,
53
      ...(linkMood && latestMood ? { moodId: latestMood.id } : null),
54
    };
55

56
    await createTrigger.mutateAsync(data);
57
    router.replace("/(tabs)/actions");
58
  };
59

60
  return (
61
    <KeyboardAvoidingView behavior="height" style={styles.keyboardView}>
62
      <ScrollView scrollEventThrottle={16}>
63
        <View style={styles.container}>
64
          <View style={styles.header}>
65
            <View style={styles.innerHeaderWrapper}>
66
              <View style={[styles.headerIcon, { backgroundColor: "#FFF7ED" }]}>
67
                <Ionicons name="flash-outline" size={20} color="#EA580C" />
68
              </View>
69

70
              <View style={styles.headerTitleSubtitle}>
71
                <Text style={styles.headerTitle}>Aconteceu algo?</Text>
72
                <Text style={styles.headerSubtitle}>
73
                  Registre acontecimentos fora do padrão
74
                </Text>
75
              </View>
76
            </View>
77

78
            <Text style={styles.description}>
79
              Identificar gatilhos ajuda a entender melhor seus padrões
80
              emocionais
81
            </Text>
82
          </View>
83

84
          <Section>
85
            <SectionHeader title="Horário do Evento" />
86
            <TimePicker value={moment} onChange={setMoment} />
87
          </Section>
88

89
          <Section>
90
            <SectionHeader title="Selecionar uma categoria" />
91
            <CategoryChips
92
              options={TRIGGER_CATEGORIES}
93
              active={category}
94
              onChange={setCategory}
95
            />
96
          </Section>
97

98
          <Section>
99
            <SectionHeader title="Adicione detalhes" />
100

101
            <Card style={styles.mainCard}>
102
              <TextArea
103
                label="Comentários sobre"
104
                variant="darkGhost"
105
                onChangeText={(val) => setComment(val)}
106
                value={comment}
107
                minRows={5}
108
                maxRows={10}
109
                placeholder="Descreva o que gerou esse sentimento"
110
              />
111
            </Card>
112
          </Section>
113

114
          <Section>
115
            <SectionHeader title="Vincular registro" />
116

117
            <LinkRow
118
              icon={
119
                <View
120
                  style={[styles.iconWrap, { backgroundColor: "transparent" }]}
121
                >
122
                  <Text style={styles.moodIconEmoji}>
123
                    {moodDef?.icon ?? "😐"}
124
                  </Text>
125
                </View>
126
              }
127
              label="Humor atual"
128
              sublabel={
129
                isLoadingMood ? "..." : (moodDef?.label ?? "Nenhum registrado")
130
              }
131
              disabled={!latestMood}
132
              value={linkMood && !!latestMood}
133
              onToggle={setLinkMood}
134
            />
135

136
            <LinkRow
137
              icon={
138
                <MaterialIcons
139
                  name="psychology"
140
                  size={40}
141
                  color={Colors.light.disabled}
142
                />
143
              }
144
              label="Prática"
145
              sublabel={"Nenhuma registrada"}
146
              disabled={true}
147
              value={false}
148
              onToggle={() => {
149
                console.log("When we get that");
150
              }}
151
            />
152
          </Section>
153

154
          <Button title="Salvar Registro" onPress={save} />
155
        </View>
156
      </ScrollView>
157
    </KeyboardAvoidingView>
158
  );
159
}
160

161
const styles = StyleSheet.create({
162
  container: {
163
    gap: 24,
164
    paddingHorizontal: Spacing.containerPadding,
165
    paddingVertical: Spacing.sectionGap,
166
    marginBottom: 50,
167
  },
168
  mainCard: {
169
    padding: Spacing.cardGap,
170
  },
171
  // Header
172
  header: {},
173
  headerIcon: {
174
    paddingVertical: 15,
175
    paddingHorizontal: 14,
176
    width: 48,
177
    borderRadius: BorderRadius.md,
178
  },
179
  innerHeaderWrapper: {
180
    flex: 1,
181
    flexDirection: "row",
182
    alignItems: "center",
183
  },
184
  headerTitleSubtitle: {
185
    marginLeft: 10,
186
  },
187
  headerTitle: {
188
    ...Typography.headlineMd,
189
  },
190
  headerSubtitle: {
191
    ...Typography.bodyMd,
192
    color: Colors.light.textSecondary,
193
  },
194
  description: {
195
    ...Typography.bodyMd,
196
    color: Colors.light.textSecondary,
197
    marginTop: 20,
198
  },
199
  keyboardView: {
200
    flex: 1,
201
  },
202
  moodIconEmoji: {
203
    fontSize: 26,
204
  },
205
  iconWrap: {
206
    width: 40,
207
    height: 40,
208
    borderRadius: 20,
209
    alignItems: "center",
210
    justifyContent: "center",
211
    marginTop: 1,
212
  },
213
});