eletrotupi / tcc/ frontend/app/triggers/new.tsxc901c35af9c84b6a29e5185545ced1129f33b8f4
5.6 KB | 190 lines Raw
1
import {
2
  View,
3
  StyleSheet,
4
  KeyboardAvoidingView,
5
  ScrollView,
6
} from "react-native";
7
import { Text } from "@/components/ui/Text";
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, useLinkMoodToTrigger, usePatchCareAction } from "@/hooks";
18
import { useToast } from "@/context/ToastContext";
19
import { ApiError } from "@/lib/api";
20
import { translateError } from "@/lib/errors/translations";
21
import { useCareActionLinkStore } from "@/stores";
22
import { CategoryChips, CategoryOption } from "@/components/ui/CategoryChips";
23
import { TriggerCategory } from "@/constants/triggers";
24
import { TRIGGER_CATEGORY_DEFINITIONS } from "@/constants/trigger-categories";
25
import { TimePicker } from "@/components/ui/TimePicker";
26

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

34
export default function NewTrigger() {
35
  const [moment, setMoment] = useState(new Date());
36
  const [comment, setComment] = useState("");
37
  const { category: initialCategory, moodId: linkedMoodId } = 
38
    useLocalSearchParams<{ category?: string; moodId?: string }>();
39

40
  const [category, setCategory] = useState(initialCategory ?? "WORK");
41
  const createTrigger = useCreateTrigger();
42
  const linkMoodToTrigger = useLinkMoodToTrigger();
43
  const patchCareAction = usePatchCareAction();
44
  const { showToast } = useToast();
45

46
  const save = async () => {
47
    try {
48
      const data = { moment, comment, category };
49
      const result = await createTrigger.mutateAsync(data);
50

51
      const careActionId = useCareActionLinkStore.getState().linkTrigger();
52
      if (careActionId) {
53
        await patchCareAction.mutateAsync({
54
          id: String(careActionId),
55
          data: { triggerId: result.trigger.id },
56
        });
57
      }
58

59
      if (linkedMoodId) {
60
        await linkMoodToTrigger.mutateAsync({
61
          triggerId: String(result.trigger.id),
62
          moodId: linkedMoodId,
63
          perceivedImpact: 3,
64
        });
65
        router.back();
66
      } else {
67
        router.replace("/(tabs)/actions");
68
      }
69
    } catch (error) {
70
      showToast(
71
        error instanceof ApiError ? translateError(error) : 'Falha ao salvar o gatilho',
72
        'error',
73
      );
74
    }
75
  };
76

77
  return (
78
    <KeyboardAvoidingView behavior="height" style={styles.keyboardView}>
79
      <ScrollView scrollEventThrottle={16}>
80
        <View style={styles.container}>
81
          <View style={styles.header}>
82
            <View style={styles.innerHeaderWrapper}>
83
              <View style={[styles.headerIcon, { backgroundColor: "#FFF7ED" }]}>
84
                <Ionicons name="flash-outline" size={20} color="#EA580C" />
85
              </View>
86

87
              <View style={styles.headerTitleSubtitle}>
88
                <Text style={styles.headerTitle}>Aconteceu algo?</Text>
89
                <Text style={styles.headerSubtitle}>
90
                  Registre acontecimentos fora do padrão
91
                </Text>
92
              </View>
93
            </View>
94

95
            <Text style={styles.description}>
96
              Identificar gatilhos ajuda a entender melhor seus padrões
97
              emocionais
98
            </Text>
99
          </View>
100

101
          <Section>
102
            <SectionHeader title="Horário do Evento" />
103
            <TimePicker value={moment} onChange={setMoment} />
104
          </Section>
105

106
          <Section>
107
            <SectionHeader title="Selecionar uma categoria" />
108
            <CategoryChips
109
              options={TRIGGER_CATEGORIES}
110
              active={category}
111
              onChange={setCategory}
112
            />
113
          </Section>
114

115
          <Section>
116
            <SectionHeader title="Adicione detalhes" />
117

118
            <Card style={styles.mainCard}>
119
              <TextArea
120
                label="Comentários sobre"
121
                variant="darkGhost"
122
                onChangeText={(val) => setComment(val)}
123
                value={comment}
124
                minRows={5}
125
                maxRows={10}
126
                placeholder="Descreva o que gerou esse sentimento"
127
              />
128
            </Card>
129
          </Section>
130

131
          <Button title="Salvar Registro" onPress={save} />
132
        </View>
133
      </ScrollView>
134
    </KeyboardAvoidingView>
135
  );
136
}
137

138
const styles = StyleSheet.create({
139
  container: {
140
    gap: 24,
141
    paddingHorizontal: Spacing.containerPadding,
142
    paddingVertical: Spacing.sectionGap,
143
    marginBottom: 50,
144
  },
145
  mainCard: {
146
    padding: Spacing.cardGap,
147
  },
148
  // Header
149
  header: {},
150
  headerIcon: {
151
    paddingVertical: 15,
152
    paddingHorizontal: 14,
153
    width: 48,
154
    borderRadius: BorderRadius.md,
155
  },
156
  innerHeaderWrapper: {
157
    flex: 1,
158
    flexDirection: "row",
159
    alignItems: "center",
160
  },
161
  headerTitleSubtitle: {
162
    marginLeft: 10,
163
  },
164
  headerTitle: {
165
    ...Typography.headlineMd,
166
  },
167
  headerSubtitle: {
168
    ...Typography.bodyMd,
169
    color: Colors.light.textSecondary,
170
  },
171
  description: {
172
    ...Typography.bodyMd,
173
    color: Colors.light.textSecondary,
174
    marginTop: 20,
175
  },
176
  keyboardView: {
177
    flex: 1,
178
  },
179
  moodIconEmoji: {
180
    fontSize: 26,
181
  },
182
  iconWrap: {
183
    width: 40,
184
    height: 40,
185
    borderRadius: 20,
186
    alignItems: "center",
187
    justifyContent: "center",
188
    marginTop: 1,
189
  },
190
});