frontend: rework copy text and general UX flow for mood entries
Parents:
ec834db4 file(s) changed
- frontend/app/(tabs)/new/entry.tsx +56 -61
- frontend/app/(tabs)/new/index.tsx +2 -0
- frontend/app/entry/[id].tsx +98 -65
- frontend/app/entry/mood-components.tsx +53 -54
frontend/app/(tabs)/new/entry.tsx
1 -
import { useState, useEffect } from 'react';
2 -
import {
3 -
Link, router, useLocalSearchParams
4 -
} from 'expo-router';
1 +
import { useState, useEffect } from "react";
2 +
import { Link, router, useLocalSearchParams } from "expo-router";
5 3
6 -
import {
7 -
View,
8 -
Text,
9 -
StyleSheet,
10 -
ScrollView
11 -
} from 'react-native';
4 +
import { View, Text, StyleSheet, ScrollView } from "react-native";
12 5
13 -
import { SafeAreaView } from 'react-native-safe-area-context';
14 -
import { ThemedText } from '@/components/misc/themed-text';
15 -
import { ThemedView } from '@/components/misc/themed-view';
16 -
import { ScreenLayout } from '@/components/ui/ScreenLayout';
17 -
import { useAuth } from '@/context/AuthContext';
18 -
import { Grid, Col, Row, Between, Center } from '@/components/ui/LayoutHelpers';
19 -
import { Card } from '@/components/ui/Cards';
20 -
import { Button } from '@/components/ui/Button';
21 -
import { Input, TextArea } from '@/components/ui/Input';
22 -
import { Section, SectionHeader } from '@/components/ui/Sections';
23 -
import { Spacing, Typography, Colors } from '@/constants/theme';
24 -
import { ScaleSlider } from '@/components/ui/ScaleSlider';
25 -
import { MoodComponentCard } from '@/components/ui/MoodComponentCard';
26 -
import { Ionicons } from '@expo/vector-icons';
27 -
import { useThemeColor, useCreateMoodEntry } from '@/hooks';
28 -
import {
29 -
useMoodEntryStore,
30 -
} from '@/stores';
6 +
import { SafeAreaView } from "react-native-safe-area-context";
7 +
import { ThemedText } from "@/components/misc/themed-text";
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 } from "@/hooks";
21 +
import { useMoodEntryStore } from "@/stores";
31 22
32 -
import {
33 -
MOODS,
34 -
getMood
35 -
} from '@/constants/moods';
23 +
import { MOODS, getMood } from "@/constants/moods";
36 24
37 -
import {
38 -
intensityToValue
39 -
} from '@/constants/mood-components';
25 +
import { intensityToValue } from "@/constants/mood-components";
40 26
41 -
import {
42 -
apiClient
43 -
} from '@/lib/api';
27 +
import { apiClient } from "@/lib/api";
44 28
45 29
export default function NewMoodEntry() {
46 30
const { user } = useAuth();
47 -
const tintColor = useThemeColor({}, 'tint');
31 +
const tintColor = useThemeColor({}, "tint");
48 32
49 33
const { initialMood } = useLocalSearchParams();
50 34
const [annotation, setAnnotation] = useState();
51 35
const [stress, setStress] = useState(0);
52 36
const [anxiety, setAnxiety] = useState(0);
53 37
const [energy, setEnergy] = useState(0);
54 38
55 -
const {
56 -
selectedMood,
57 -
setSelectedMood,
58 -
components,
59 -
reset
60 -
} = useMoodEntryStore();
39 +
const { selectedMood, setSelectedMood, components, reset } =
40 +
useMoodEntryStore();
61 41
62 42
const createMoodEntry = useCreateMoodEntry();
63 43
64 44
useEffect(() => {
65 45
setSelectedMood(getMood(initialMood));
▸ 11 unchanged lines
77 57
anxietyLevel: anxiety,
78 58
moment: new Date(),
79 59
annotation: annotation,
80 60
moodComponents: components.map((c) => ({
81 61
component: c.id.toUpperCase(),
82 -
intensity: intensityToValue(c.intensity)
83 -
}))
62 +
intensity: intensityToValue(c.intensity),
63 +
})),
84 64
};
85 65
86 -
await createMoodEntry.mutateAsync(data)
66 +
await createMoodEntry.mutateAsync(data);
87 67
88 68
reset();
89 -
router.replace("/")
90 -
}
69 +
router.replace("/");
70 +
};
91 71
92 72
const editComponents = () => {
93 -
router.push("/entry/mood-components")
94 -
}
73 +
router.push("/entry/mood-components");
74 +
};
95 75
96 76
return (
97 77
<View>
98 -
<ScrollView
99 -
scrollEventThrottle={16}>
78 +
<ScrollView scrollEventThrottle={16}>
100 79
<View style={styles.container}>
101 80
<Center>
102 81
<ThemedText style={styles.statusPrefix}>
103 82
Como você está se sentindo agora?
104 83
</ThemedText>
▸ 2 unchanged lines
107 86
{selectedMood?.label || "Neutro"}
108 87
</ThemedText>
109 88
</Center>
110 89
111 90
<Card style={styles.resumeCard}>
91 +
<ThemedText style={styles.infoText}>
92 +
Não existe resposta certa ou errada. Estime, de 0 a 10, como tu
93 +
percebe tua energia, estresse e ansiedade neste momento. O
94 +
objetivo é registrar uma impressão geral, não uma medida precisa.
95 +
</ThemedText>
96 +
112 97
<Col gap={24}>
113 98
<ScaleSlider
114 99
variant="rich"
115 100
label="Energia"
116 101
value={energy}
117 102
onValueChange={setEnergy}
118 -
icon={<Ionicons name="flower-outline" size={20} color={tintColor} />}
103 +
icon={
104 +
<Ionicons name="flower-outline" size={20} color={tintColor} />
105 +
}
119 106
minLabel="Baixa"
120 107
maxLabel="Alta"
121 108
/>
122 109
123 110
<ScaleSlider
▸ 30 unchanged lines
154 141
placeholder="Escreva uma nota rápida sobre o seu dia até o momento..."
155 142
/>
156 143
</Card>
157 144
158 145
<Section>
159 -
<SectionHeader title="Componentes do Humor" info="Editar" />
146 +
<SectionHeader title="Também estou..." />
160 147
{components.length > 0 ? (
161 148
<Grid gap={2} style={{ marginTop: 8 }}>
162 149
{components.map((comp) => (
163 150
<MoodComponentCard
164 151
key={comp.id}
▸ 2 unchanged lines
167 154
/>
168 155
))}
169 156
</Grid>
170 157
) : null}
171 158
172 -
<Button title="Adicionar Componentes"
159 +
<Button
160 +
title="Adicionar estados & emoções"
173 161
onPress={editComponents}
174 162
textStyle={{ fontWeight: 500 }}
175 163
variant="dashed"
176 164
/>
177 165
</Section>
178 166
179 -
<Button title="Salvar Registro"
167 +
<Button
168 +
title="Salvar Registro"
180 169
onPress={saveMoodEntry}
181 170
disabled={!components.length}
182 171
/>
183 172
</View>
184 173
</ScrollView>
▸ 5 unchanged lines
190 179
container: {
191 180
gap: 24,
192 181
paddingHorizontal: Spacing.containerPadding,
193 182
paddingVertical: Spacing.sectionGap,
194 183
},
184 +
infoText: {
185 +
...Typography.labelSm,
186 +
color: Colors.light.textSecondary,
187 +
marginBottom: 20,
188 +
fontWeight: "400" as const,
189 +
},
195 190
statusText: {
196 191
...Typography.headlineXg,
197 192
},
198 193
statusPrefix: {
199 -
...Typography.bodyMd
194 +
...Typography.bodyMd,
200 195
},
201 196
annotationsCard: {
202 -
padding: Spacing.cardGap
197 +
padding: Spacing.cardGap,
203 198
},
204 199
resumeCard: {
205 200
padding: Spacing.cardGap,
206 -
}
201 +
},
207 202
});
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";
▸ 78 unchanged lines
84 84
</Card>
85 85
</Section>
86 86
87 87
{/* TODO: Check whether we gonna have to generate these on demand */}
88 88
<Section>
89 +
<SectionHeader title="Entre hoje e ontem" />
90 +
89 91
<View
90 92
style={[
91 93
{
92 94
flexDirection: "row",
93 95
gap: 16,
▸ 64 unchanged lines
158 160
fontSize: 11,
159 161
fontWeight: 600,
160 162
lineHeight: 16.5,
161 163
},
162 164
});
frontend/app/entry/[id].tsx
1 -
import { useState, useEffect } from 'react';
2 -
import { StyleSheet, Text, View, ScrollView, Pressable, ActivityIndicator } from 'react-native';
3 -
import { useLocalSearchParams, router, Stack } from 'expo-router';
4 -
import { format } from 'date-fns';
5 -
import { ptBR } from 'date-fns/locale';
1 +
import { useState, useEffect } from "react";
2 +
import {
3 +
StyleSheet,
4 +
Text,
5 +
View,
6 +
ScrollView,
7 +
Pressable,
8 +
ActivityIndicator,
9 +
} from "react-native";
10 +
import { useLocalSearchParams, router, Stack } from "expo-router";
11 +
import { format } from "date-fns";
12 +
import { ptBR } from "date-fns/locale";
6 13
7 -
import { Card, SubtleInfoCard } from '@/components/ui/Cards';
8 -
import { Badge } from '@/components/ui/Badge';
9 -
import { Button } from '@/components/ui/Button';
10 -
import { Col, Between, Row } from '@/components/ui/LayoutHelpers';
11 -
import { Section, SectionHeader } from '@/components/ui/Sections';
12 -
import { Theme, Colors, Spacing } from '@/constants/theme';
13 -
import { getMood } from '@/constants/moods';
14 -
import { getMoodComponent, intensityLabel, intensityToValue } from '@/constants/mood-components';
15 -
import { useMoodEntry, useDeleteMoodEntry } from '@/hooks';
16 -
import { getTimeBadge, formatMoment } from '@/lib/utils/time';
17 -
import { MoodComponentCard } from '@/components/ui/MoodComponentCard';
14 +
import { Card, SubtleInfoCard } from "@/components/ui/Cards";
15 +
import { Badge } from "@/components/ui/Badge";
16 +
import { Button } from "@/components/ui/Button";
17 +
import { Col, Between, Row } from "@/components/ui/LayoutHelpers";
18 +
import { Section, SectionHeader } from "@/components/ui/Sections";
19 +
import { Theme, Colors, Spacing } from "@/constants/theme";
20 +
import { getMood } from "@/constants/moods";
21 +
import {
22 +
getMoodComponent,
23 +
intensityLabel,
24 +
intensityToValue,
25 +
} from "@/constants/mood-components";
26 +
import { useMoodEntry, useDeleteMoodEntry } from "@/hooks";
27 +
import { getTimeBadge, formatMoment } from "@/lib/utils/time";
28 +
import { MoodComponentCard } from "@/components/ui/MoodComponentCard";
18 29
19 30
export default function MoodDetailScreen() {
20 31
const { id } = useLocalSearchParams<{ id: string }>();
21 32
const { data: entry, isLoading, isError } = useMoodEntry(id);
22 33
const deleteMoodEntry = useDeleteMoodEntry();
▸ 6 unchanged lines
29 40
const createdAt = new Date(entry?.moment);
30 41
const msSinceCreation = Date.now() - createdAt.getTime();
31 42
const deletionWindowMs = 5 * 60 * 1000;
32 43
33 44
const newCanDelete = msSinceCreation < deletionWindowMs;
34 -
const newMinutesLeft = Math.max(0, Math.ceil((deletionWindowMs - msSinceCreation) / 60000));
45 +
const newMinutesLeft = Math.max(
46 +
0,
47 +
Math.ceil((deletionWindowMs - msSinceCreation) / 60000),
48 +
);
35 49
36 50
setCanDelete(newCanDelete);
37 51
setMinutesLeft(newMinutesLeft);
38 52
};
39 53
▸ 33 unchanged lines
73 87
router.back();
74 88
};
75 89
76 90
const deleteButtonMsg = () => {
77 91
const msg = "Excluir Registro";
78 -
const timeLeftStr = `(Disponível por ${minutesLeft < 1 ? '<1' : minutesLeft}:00)`;
79 -
const suffix = canDelete ? timeLeftStr : "(Expirado)"
92 +
const timeLeftStr = `(Disponível por ${minutesLeft < 1 ? "<1" : minutesLeft}:00)`;
93 +
const suffix = canDelete ? timeLeftStr : "(Expirado)";
80 94
81 -
return `${msg} ${suffix}`
82 -
}
95 +
return `${msg} ${suffix}`;
96 +
};
83 97
84 98
return (
85 99
<>
86 -
<Stack.Screen options={{ title: 'Ver detalhes' }} />
100 +
<Stack.Screen options={{ title: "Ver detalhes" }} />
87 101
88 102
<ScrollView
89 103
style={styles.container}
90 104
contentContainerStyle={styles.content}
91 105
showsVerticalScrollIndicator={false}
92 106
>
93 107
{/* Header card */}
94 108
<Card style={styles.headerCard}>
95 109
<Between>
96 -
<Row gap={12} style={{ alignItems: 'center' }}>
97 -
<Text style={styles.moodIcon}>{moodDef?.icon ?? '😐'}</Text>
110 +
<Row gap={12} style={{ alignItems: "center" }}>
111 +
<Text style={styles.moodIcon}>{moodDef?.icon ?? "😐"}</Text>
98 112
<Col gap={2}>
99 -
<Text style={styles.moodLabel}>{moodDef?.label ?? entry.selectedMood}</Text>
113 +
<Text style={styles.moodLabel}>
114 +
{moodDef?.label ?? entry.selectedMood}
115 +
</Text>
100 116
<Text style={styles.moodTime}>{formatMoment(moment)}</Text>
101 117
</Col>
102 118
</Row>
103 119
<Badge
104 120
label="Registro Ativo"
▸ 3 unchanged lines
108 124
</Between>
109 125
</Card>
110 126
111 127
{/* Core levels */}
112 128
<Section>
113 -
<SectionHeader title="Níveis" variant="subtle" />
114 -
{[
115 -
{ id: 'energy', label: 'Energia', value: entry.energyLevel },
116 -
{ id: 'stress', label: 'Estresse', value: entry.stressLevel },
117 -
{ id: 'anxiety', label: 'Ansiedade', value: entry.anxietyLevel },
118 -
].map((item, index, arr) => (
119 -
<Card key={item.id} style={{ padding: Spacing.cardGap }}>
120 -
<View key={item.label}>
121 -
<View style={styles.componentRow}>
122 -
<Text style={styles.componentLabel}>{item.label}</Text>
123 -
<Text style={styles.componentIntensityGreen}>{item.value}/10</Text>
124 -
</View>
129 +
<SectionHeader title="Níveis emocionais" variant="subtle" />
130 +
{[
131 +
{ id: "energy", label: "Energia", value: entry.energyLevel },
132 +
{ id: "stress", label: "Estresse", value: entry.stressLevel },
133 +
{ id: "anxiety", label: "Ansiedade", value: entry.anxietyLevel },
134 +
].map((item, index, arr) => (
135 +
<Card key={item.id} style={{ padding: Spacing.cardGap }}>
136 +
<View key={item.label}>
137 +
<View style={styles.componentRow}>
138 +
<Text style={styles.componentLabel}>{item.label}</Text>
139 +
<Text style={styles.componentIntensityGreen}>
140 +
{item.value}/10
141 +
</Text>
142 +
</View>
125 143
126 -
<View style={styles.progressTrack}>
127 -
<View style={[styles.progressFill, { width: `${(item.value / 10) * 100}%` }]} />
128 -
</View>
144 +
<View style={styles.progressTrack}>
145 +
<View
146 +
style={[
147 +
styles.progressFill,
148 +
{ width: `${(item.value / 10) * 100}%` },
149 +
]}
150 +
/>
129 151
</View>
130 -
</Card>
131 -
))}
152 +
</View>
153 +
</Card>
154 +
))}
132 155
</Section>
133 156
134 157
<Section>
135 -
<SectionHeader title="Componentes" variant="subtle" />
158 +
<SectionHeader title="Além disso, sinto..." variant="subtle" />
136 159
<Col gap={0}>
137 160
{entry.moodComponents.map((comp, index) => {
138 161
const def = getMoodComponent(comp.component.toLowerCase());
139 -
const numericIntensity = comp.intensity === 'LIGHT' ? 2 : comp.intensity === 'MODERATE' ? 5 : 8;
162 +
const numericIntensity =
163 +
comp.intensity === "LIGHT"
164 +
? 2
165 +
: comp.intensity === "MODERATE"
166 +
? 5
167 +
: 8;
140 168
141 169
return (
142 170
<MoodComponentCard
143 171
key={comp.id}
144 172
id={comp.component.toLowerCase()}
▸ 5 unchanged lines
150 178
</Section>
151 179
152 180
{/* Annotation / notes */}
153 181
{entry.annotation && (
154 182
<Section>
155 -
<SectionHeader title="Notas" variant="subtle" />
183 +
<SectionHeader title="Anotações" variant="subtle" />
156 184
<Card style={{ padding: Spacing.cardGap }}>
157 -
<Text style={styles.annotation}>"{entry.annotation?.trim()}"</Text>
185 +
<Text style={styles.annotation}>
186 +
"{entry.annotation?.trim()}"
187 +
</Text>
158 188
</Card>
159 189
</Section>
160 190
)}
161 191
162 192
{/* Delete */}
163 193
<View style={styles.section}>
164 194
<Text style={styles.sectionLabel}>GESTÃO DO REGISTRO</Text>
165 -
<Button variant="danger"
195 +
<Button
196 +
variant="danger"
166 197
isLoading={deleteMoodEntry.isPending}
167 198
disabled={!canDelete || deleteMoodEntry.isPending}
168 199
onPress={handleDelete}
169 -
title={deleteButtonMsg()} />
200 +
title={deleteButtonMsg()}
201 +
/>
170 202
171 -
<SubtleInfoCard style={styles.deleteInfo}
203 +
<SubtleInfoCard
204 +
style={styles.deleteInfo}
172 205
text={`
173 206
A exclusão de registros é permitida apenas nos primeiros 5 minutos
174 207
após o envio para garantir a integridade do histórico emocional.
175 -
`} />
208 +
`}
209 +
/>
176 210
</View>
177 -
178 211
</ScrollView>
179 212
</>
180 213
);
181 214
}
182 215
▸ 7 unchanged lines
190 223
gap: Spacing.sectionGap,
191 224
paddingBottom: 48,
192 225
},
193 226
centered: {
194 227
flex: 1,
195 -
justifyContent: 'center',
196 -
alignItems: 'center',
228 +
justifyContent: "center",
229 +
alignItems: "center",
197 230
gap: 12,
198 231
},
199 232
errorText: {
200 233
fontSize: 15,
201 234
color: Colors.light.textSecondary,
▸ 3 unchanged lines
205 238
paddingVertical: 10,
206 239
backgroundColor: Theme.colors.tint,
207 240
borderRadius: Theme.borderRadius.md,
208 241
},
209 242
backButtonText: {
210 -
fontWeight: '700',
243 +
fontWeight: "700",
211 244
color: Theme.colors.text,
212 245
},
213 246
214 247
// Header
215 248
headerCard: {
▸ 2 unchanged lines
218 251
moodIcon: {
219 252
fontSize: 40,
220 253
},
221 254
moodLabel: {
222 255
fontSize: 17,
223 -
fontWeight: '700',
256 +
fontWeight: "700",
224 257
color: Colors.light.text,
225 258
},
226 259
moodTime: {
227 260
fontSize: 13,
228 261
color: Colors.light.textSecondary,
▸ 3 unchanged lines
232 265
section: {
233 266
gap: 8,
234 267
},
235 268
sectionLabel: {
236 269
fontSize: 11,
237 -
fontWeight: '600',
270 +
fontWeight: "600",
238 271
letterSpacing: 0.8,
239 272
color: Colors.light.textSecondary,
240 -
textTransform: 'uppercase',
273 +
textTransform: "uppercase",
241 274
},
242 275
243 276
// Components
244 277
componentRow: {
245 -
flexDirection: 'row',
246 -
justifyContent: 'space-between',
247 -
alignItems: 'center',
278 +
flexDirection: "row",
279 +
justifyContent: "space-between",
280 +
alignItems: "center",
248 281
paddingVertical: 10,
249 282
},
250 283
componentLabel: {
251 284
fontSize: 15,
252 -
fontWeight: '700',
285 +
fontWeight: "700",
253 286
color: Colors.light.text,
254 287
},
255 288
componentIntensity: {
256 289
fontSize: 13,
257 290
color: Colors.light.textSecondary,
258 291
},
259 292
componentIntensityGreen: {
260 293
fontSize: 13,
261 -
fontWeight: '700',
294 +
fontWeight: "700",
262 295
color: Theme.colors.tint,
263 296
},
264 297
progressTrack: {
265 298
height: 6,
266 299
backgroundColor: Theme.colors.light.divider,
267 300
borderRadius: Theme.borderRadius.full,
268 301
marginBottom: 4,
269 -
overflow: 'hidden',
302 +
overflow: "hidden",
270 303
},
271 304
progressFill: {
272 -
height: '100%',
305 +
height: "100%",
273 306
backgroundColor: Theme.colors.light.tint,
274 307
borderRadius: Theme.borderRadius.full,
275 308
},
276 309
// Annotation
277 310
annotation: {
278 311
fontSize: 14,
279 312
lineHeight: 22,
280 313
color: Colors.light.textSecondary,
281 -
fontStyle: 'italic',
314 +
fontStyle: "italic",
282 315
padding: 4,
283 316
},
284 317
});
frontend/app/entry/mood-components.tsx
1 -
import React from 'react';
2 -
import {
3 -
View,
4 -
Text,
5 -
ScrollView,
6 -
Pressable,
7 -
StyleSheet,
8 -
} from 'react-native';
9 -
import { router } from 'expo-router';
10 -
import { Ionicons } from '@expo/vector-icons';
1 +
import React from "react";
2 +
import { View, Text, ScrollView, Pressable, StyleSheet } from "react-native";
3 +
import { router } from "expo-router";
4 +
import { Ionicons } from "@expo/vector-icons";
11 5
12 -
import { ScaleSlider } from '@/components/ui/ScaleSlider';
13 -
import { Row, Grid } from '@/components/ui/LayoutHelpers';
14 -
import { Section, SectionHeader } from '@/components/ui/Sections';
15 -
import { Button } from '@/components/ui/Button';
16 -
import { Card } from '@/components/ui/Cards';
17 -
import { Theme } from '@/constants/theme';
6 +
import { ScaleSlider } from "@/components/ui/ScaleSlider";
7 +
import { Row, Grid } from "@/components/ui/LayoutHelpers";
8 +
import { Section, SectionHeader } from "@/components/ui/Sections";
9 +
import { Button } from "@/components/ui/Button";
10 +
import { Card } from "@/components/ui/Cards";
11 +
import { Theme } from "@/constants/theme";
18 12
import {
19 13
MOOD_COMPONENTS,
20 14
getMoodComponent,
21 15
intensityLabel,
22 -
} from '@/constants/mood-components';
16 +
} from "@/constants/mood-components";
23 17
24 -
import {
25 -
useMoodEntryStore,
26 -
} from '@/stores/moodEntry';
18 +
import { useMoodEntryStore } from "@/stores/moodEntry";
27 19
28 20
export default function MoodComponentsScreen() {
29 21
const {
30 22
selectedMood,
31 23
components,
▸ 9 unchanged lines
41 33
router.back();
42 34
};
43 35
44 36
return (
45 37
<View style={styles.container}>
46 -
47 38
{/* Header */}
48 39
<View style={styles.header}>
49 40
<Pressable onPress={() => router.back()} hitSlop={8}>
50 41
<Ionicons name="close" size={24} color={Theme.colors.text} />
51 42
</Pressable>
52 -
<Text style={styles.headerTitle}>Editar Componentes</Text>
43 +
<Text style={styles.headerTitle}>Adicionar estados</Text>
53 44
<Pressable onPress={handleDone} hitSlop={8}>
54 45
<Text style={styles.headerAction}>Pronto</Text>
55 46
</Pressable>
56 47
</View>
57 48
58 49
<ScrollView
59 50
contentContainerStyle={styles.content}
60 51
showsVerticalScrollIndicator={false}
61 52
>
62 -
63 53
{/* Subtitle */}
64 54
{selectedMood && (
65 55
<View style={styles.subtitleBlock}>
66 -
<Text style={styles.subtitleSmall}>Baseado no seu humor selecionado</Text>
67 -
<Text style={styles.subtitleLarge}>{selectedMood.label}</Text>
56 +
<Text style={styles.subtitleSmall}>
57 +
Além do humor principal, o que melhor descreve como estou me
58 +
sentindo agora?
59 +
</Text>
68 60
</View>
69 61
)}
70 62
71 63
{/* Active components */}
72 64
{components.length > 0 && (
73 65
<Section>
74 66
<SectionHeader
75 -
title="Intensidade dos Componentes"
76 -
info={`Ativos: ${components.length}`} />
67 +
title="Intensidade"
68 +
info={`Ativos: ${components.length}`}
69 +
/>
77 70
78 71
{components.map((comp) => {
79 72
const def = getMoodComponent(comp.id);
80 73
if (!def) return null;
81 74
82 75
return (
83 76
<Card key={comp.id} style={styles.activeCard}>
84 77
{/* Card header */}
85 78
<Row style={styles.activeCardHeader}>
86 -
<View style={[styles.dot, { backgroundColor: def.color }]} />
79 +
<View
80 +
style={[styles.dot, { backgroundColor: def.color }]}
81 +
/>
87 82
<Text style={styles.activeCardLabel}>{def.label}</Text>
88 83
<Pressable
89 84
onPress={() => removeComponent(comp.id)}
90 85
hitSlop={8}
91 86
>
▸ 19 unchanged lines
111 106
style={styles.slider}
112 107
/>
113 108
</Card>
114 109
);
115 110
})}
116 -
117 111
</Section>
118 112
)}
119 113
120 114
{/* Available to add */}
121 115
{available.length > 0 && (
122 116
<Section>
123 -
<SectionHeader title="Adicionar outros" />
117 +
<SectionHeader title="Estado & Emoções" />
124 118
<Grid gap={2}>
125 119
{available.map((def) => (
126 120
<Card key={def.id} style={styles.availableItem}>
127 121
<Pressable
128 122
onPress={() => addComponent(def.id)}
129 123
style={styles.availableItemInternalWrapper}
130 124
>
131 125
<Row gap={8} style={styles.availableInner}>
132 -
<View style={[styles.dot, { backgroundColor: def.color }]} />
126 +
<View
127 +
style={[styles.dot, { backgroundColor: def.color }]}
128 +
/>
133 129
<Text style={styles.availableLabel}>{def.label}</Text>
134 130
</Row>
135 131
136 132
<Ionicons
137 133
name="add-circle-outline"
▸ 4 unchanged lines
142 138
</Card>
143 139
))}
144 140
</Grid>
145 141
</Section>
146 142
)}
143 +
144 +
<Button title="Pronto" onPress={handleDone} />
147 145
</ScrollView>
148 146
</View>
149 147
);
150 148
}
151 149
152 150
const styles = StyleSheet.create({
153 151
container: {
154 152
flex: 1,
155 153
},
156 154
header: {
157 -
flexDirection: 'row',
158 -
justifyContent: 'space-between',
159 -
alignItems: 'center',
155 +
flexDirection: "row",
156 +
justifyContent: "space-between",
157 +
alignItems: "center",
160 158
paddingHorizontal: Theme.spacing.containerPadding,
161 159
paddingVertical: 16,
162 160
borderBottomWidth: 1,
163 161
borderBottomColor: Theme.colors.light.divider,
164 162
},
165 163
headerTitle: {
166 164
fontSize: Theme.typography.bodyLg.fontSize,
167 -
fontWeight: '700',
165 +
fontWeight: "700",
168 166
color: Theme.colors.light.text,
169 167
},
170 168
headerAction: {
171 169
fontSize: Theme.typography.bodyMd.fontSize,
172 -
fontWeight: '600',
170 +
fontWeight: "600",
173 171
color: Theme.colors.light.tint,
174 172
},
175 173
content: {
176 174
padding: Theme.spacing.containerPadding,
177 175
gap: Theme.spacing.sectionGap,
178 176
paddingBottom: 120,
179 177
},
180 178
subtitleBlock: {
181 -
alignItems: 'center',
179 +
alignItems: "center",
182 180
gap: 4,
183 181
},
184 182
subtitleSmall: {
185 183
fontSize: Theme.typography.bodyMd.fontSize,
186 184
color: Theme.colors.light.textSecondary,
185 +
textAlign: "center",
187 186
},
188 187
subtitleLarge: {
189 188
fontSize: 28,
190 -
fontWeight: '700',
189 +
fontWeight: "700",
191 190
color: Theme.colors.light.text,
192 191
},
193 192
section: {
194 193
gap: Theme.spacing.cardGap,
195 194
},
196 195
sectionHeader: {
197 -
justifyContent: 'space-between',
198 -
alignItems: 'center',
196 +
justifyContent: "space-between",
197 +
alignItems: "center",
199 198
},
200 199
activeCard: {
201 200
padding: Theme.spacing.cardGap,
202 201
},
203 202
activeCardHeader: {
204 -
alignItems: 'center',
205 -
justifyContent: 'space-between',
206 -
marginBottom: 16
203 +
alignItems: "center",
204 +
justifyContent: "space-between",
205 +
marginBottom: 16,
207 206
},
208 207
activeCardLabel: {
209 208
flex: 1,
210 -
... { ...Theme.typography.bodyLg, lineHeight: 24 },
209 +
...{ ...Theme.typography.bodyLg, lineHeight: 24 },
211 210
color: Theme.colors.light.text,
212 211
marginLeft: 4,
213 212
},
214 213
dot: {
215 214
width: 12,
▸ 3 unchanged lines
219 218
},
220 219
slider: {
221 220
marginTop: 4,
222 221
},
223 222
availableItem: {
224 -
flexDirection: 'row',
225 -
justifyContent: 'space-between',
226 -
alignItems: 'center',
223 +
flexDirection: "row",
224 +
justifyContent: "space-between",
225 +
alignItems: "center",
227 226
paddingHorizontal: 12,
228 227
paddingVertical: 10,
229 228
},
230 229
availableItemInternalWrapper: {
231 -
flexDirection: 'row',
232 -
width: '100%',
233 -
justifyContent: 'space-between',
234 -
alignItems: 'center',
230 +
flexDirection: "row",
231 +
width: "100%",
232 +
justifyContent: "space-between",
233 +
alignItems: "center",
235 234
},
236 235
availableInner: {
237 -
alignItems: 'center',
236 +
alignItems: "center",
238 237
flexShrink: 1,
239 238
},
240 239
availableLabel: {
241 240
fontSize: Theme.typography.bodyMd.fontSize,
242 -
fontWeight: '500',
241 +
fontWeight: "500",
243 242
color: Theme.colors.light.text,
244 -
}
243 +
},
245 244
});