frontend: flesh a mood entry log component
Parents:
bdfa4631 file(s) changed
- frontend/components/ui/MoodEntryLog.tsx +105 -0
frontend/components/ui/MoodEntryLog.tsx
@@ -0,0 +1,105 @@
1 + import { format, isToday, isYesterday } from 'date-fns';
2 + import { ptBR } from 'date-fns/locale';
3 + import { StyleSheet, Text, View } from 'react-native';
4 +
5 + import { Card } from '@/components/ui/Cards';
6 + import { Badge } from '@/components/ui/Badge';
7 + import { getMood } from '@/constants/moods';
8 + import { Colors, Spacing } from '@/constants/theme';
9 + import { MoodEntry } from '@/lib/api';
10 +
11 + type TimeBadgeVariant = 'morning' | 'afternoon' | 'night' | 'latenight';
12 +
13 + const TIME_BADGES: Record<TimeBadgeVariant, { label: string; variant: string; }> = {
14 + morning: { label: 'Manhã', variant: 'green' },
15 + afternoon: { label: 'Tarde', variant: 'orange' },
16 + night: { label: 'Noite', variant: 'blue' },
17 + latenight: { label: 'Madrugada', variant: 'purple' },
18 + };
19 +
20 + function getTimeBadge(date: Date) {
21 + const h = date.getHours();
22 + if (h >= 6 && h < 12) return TIME_BADGES.morning;
23 + if (h >= 12 && h < 18) return TIME_BADGES.afternoon;
24 + if (h >= 18 && h < 24) return TIME_BADGES.night;
25 + return TIME_BADGES.latenight;
26 + }
27 +
28 + function formatMoment(date: Date): string {
29 + if (isToday(date)) return `Hoje às ${format(date, "HH'h'mm")}`;
30 + if (isYesterday(date)) return `Ontem às ${format(date, "HH'h'mm")}`;
31 + return format(date, "d 'de' MMM 'às' HH'h'mm", { locale: ptBR });
32 + }
33 +
34 + interface MoodEntryLogProps {
35 + entry: MoodEntry;
36 + }
37 +
38 + const MoodEntryLog = ({ entry }: MoodEntryLogProps) => {
39 + const moment = new Date(entry.moment);
40 + const moodDef = getMood(entry.selectedMood.toLowerCase());
41 + const badge = getTimeBadge(moment);
42 +
43 + return (
44 + <Card style={styles.card}>
45 + <View style={styles.moodIcon}>
46 + <Text style={styles.moodIconEmoji}>{moodDef?.icon ?? '😐'}</Text>
47 + </View>
48 +
49 + <View style={styles.moodBlock}>
50 + <Text style={styles.title} numberOfLines={1}>
51 + {moodDef?.label ?? entry.selectedMood}
52 + </Text>
53 +
54 + <Text style={styles.subtitle} numberOfLines={1}>
55 + {formatMoment(moment)}
56 + </Text>
57 + </View>
58 +
59 + <Badge
60 + label={badge.label}
61 + variant={badge.variant}
62 + />
63 + </Card>
64 + );
65 + }
66 +
67 + const styles = StyleSheet.create({
68 + card: {
69 + flexDirection: "row",
70 + alignItems: "center",
71 + gap: 14,
72 + overflow: "hidden",
73 + padding: Spacing.cardGap
74 + },
75 + moodIcon: {
76 + width: 48,
77 + height: 48,
78 + alignItems: "center",
79 + justifyContent: "center",
80 + flexShrink: 0,
81 + },
82 + moodIconEmoji: {
83 + fontSize: 26,
84 + },
85 + // Text
86 + moodBlock: {
87 + flex: 1,
88 + minWidth: 0,
89 + },
90 + title: {
91 + fontSize: 15,
92 + fontWeight: "700",
93 + color: Colors.light.text,
94 + letterSpacing: -0.2,
95 + marginBottom: 3,
96 + },
97 + subtitle: {
98 + fontSize: 12.5,
99 + fontWeight: "500",
100 + color: Colors.light.textSecondary,
101 + letterSpacing: 0.1,
102 + },
103 + });
104 +
105 + export default MoodEntryLog