frontend: split time utilities from mood entry log and fetch it
Pedro Lucas Porcellis porcellis@eletrotupi.com · 5 months ago
5c34c8e5782048b72506e8cb8b1c65eb7af38e16 Browse filesParents
f4ff3fbChanged files
3
Additions
+50
Deletions
-94
frontend/app/(tabs)/new/index.tsx
1 1
import { useEffect, useState } from 'react';
2 2
import {
3 3
StyleSheet,
4 4
View,
5 -
Text
5 +
Text,
6 +
ActivityIndicator
6 7
} from 'react-native';
7 8
8 9
import { ThemedText } from '@/components/misc/themed-text';
9 10
import { ThemedView } from '@/components/misc/themed-view';
10 11
import { ScreenLayout } from '@/components/ui/ScreenLayout';
14 15
import { Badge } from '@/components/ui/Badge';
15 16
import { Button } from '@/components/ui/Button';
16 17
import { Section, SectionHeader } from '@/components/ui/Sections';
17 18
import { MoodSelector } from '@/components/ui/EmojiSelectors';
18 19
import { Typography, Spacing, Shadows, Colors } from '@/constants/theme';
19 -
import { useThemeColor } from '@/hooks/use-theme-color';
20 20
import { router } from 'expo-router';
21 21
import {
22 22
MoodDefinition, MOODS
23 23
} from '@/constants/moods'
24 24
25 -
const MoodEntryLog = ({ mood: MoodDefinition, moment: Date }) => {
26 -
const styles = StyleSheet.create({
27 -
card: {
28 -
flexDirection: "row",
29 -
alignItems: "center",
30 -
gap: 14,
31 -
overflow: "hidden",
32 -
padding: Spacing.cardGap
33 -
},
34 -
moodIcon: {
35 -
width: 48,
36 -
height: 48,
37 -
alignItems: "center",
38 -
justifyContent: "center",
39 -
flexShrink: 0,
40 -
},
41 -
moodIconEmoji: {
42 -
fontSize: 26,
43 -
},
44 -
// Text
45 -
moodBlock: {
46 -
flex: 1,
47 -
minWidth: 0,
48 -
},
49 -
title: {
50 -
fontSize: 15,
51 -
fontWeight: "700",
52 -
color: Colors.light.text,
53 -
letterSpacing: -0.2,
54 -
marginBottom: 3,
55 -
},
56 -
subtitle: {
57 -
fontSize: 12.5,
58 -
fontWeight: "500",
59 -
color: Colors.light.textSecondary,
60 -
letterSpacing: 0.1,
61 -
},
62 -
});
63 -
64 -
return (
65 -
<Card style={styles.card}>
66 -
<View style={styles.moodIcon}>
67 -
<Text style={styles.moodIconEmoji}>😀</Text>
68 -
</View>
25 +
import {
26 +
useThemeColor,
27 +
useMoodEntries
28 +
} from '@/hooks';
69 29
70 -
<View style={styles.moodBlock}>
71 -
<Text style={styles.title} numberOfLines={1}>
72 -
Neutro
73 -
</Text>
74 -
<ThemedText style={styles.subtitle} numberOfLines={1}>
75 -
Ontem às 10h
76 -
</ThemedText>
77 -
</View>
78 -
79 -
<Badge label="Manhã" />
80 -
</Card>
81 -
);
82 -
}
30 +
import MoodEntryLog from '@/components/ui/MoodEntryLog';
83 31
84 32
export default function New() {
85 33
const { user } = useAuth();
86 34
const [mood, setMood] = useState<string>('good');
87 -
const [isLoading, setIsLoading] = useState<boolean>(false);
35 +
const { data, isLoading } = useMoodEntries({ limit: 5 });
36 +
const recentEntries = data?.entries ?? [];
37 +
38 +
console.log("entries: ", data, recentEntries)
88 39
89 40
const initQuickRegister = () => {
90 41
// TODO: Set down on camelCase vs kebab case
91 42
router.navigate(`/new/entry?initialMood=${mood}`)
92 43
};
122 73
/>
123 74
124 75
<Button
125 76
title="Salvar Humor"
126 77
onPress={initQuickRegister}
127 -
loading={isLoading}
128 78
style={styles.quickRegisterButton}
129 79
/>
130 80
</Col>
131 81
</Card>
132 82
</Section>
143 93
</Section>
144 94
145 95
<Section>
146 96
<SectionHeader title="Registros recentes" />
147 97
148 -
<MoodEntryLog
149 -
mood="sad"
150 -
moment={new Date()}
151 -
/>
152 -
153 -
<MoodEntryLog
154 -
mood="good"
155 -
moment={new Date()}
156 -
/>
98 +
{isLoading ? (
99 +
<ActivityIndicator />
100 +
) : (
101 +
<Col gap={8}>
102 +
{recentEntries.map((entry) => (
103 +
<MoodEntryLog key={entry.id} entry={entry} />
104 +
))}
105 +
</Col>
106 +
)}
157 107
</Section>
158 108
</ScreenLayout>
159 109
)
160 110
}
161 111
178 128
marginRight: 16,
179 129
marginBottom: 16,
180 130
...Shadows.lg
181 131
}
182 132
});
frontend/components/ui/MoodEntryLog.tsx
1 1
import { format, isToday, isYesterday } from 'date-fns';
2 2
import { ptBR } from 'date-fns/locale';
3 3
import { StyleSheet, Text, View } from 'react-native';
4 +
import { router } from 'expo-router';
4 5
5 6
import { Card } from '@/components/ui/Cards';
6 7
import { Badge } from '@/components/ui/Badge';
7 8
import { getMood } from '@/constants/moods';
8 9
import { Colors, Spacing } from '@/constants/theme';
9 10
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 -
}
11 +
import { getTimeBadge, formatMoment } from '@/lib/utils/time';
33 12
34 13
interface MoodEntryLogProps {
35 14
entry: MoodEntry;
36 15
}
37 16
38 17
const MoodEntryLog = ({ entry }: MoodEntryLogProps) => {
39 18
const moment = new Date(entry.moment);
40 19
const moodDef = getMood(entry.selectedMood.toLowerCase());
41 20
const badge = getTimeBadge(moment);
42 21
22 +
const handlePress = () => router.push(`/entry/${entry.id}`);
23 +
43 24
return (
44 -
<Card style={styles.card}>
25 +
<Card style={styles.card} onPress={handlePress}>
45 26
<View style={styles.moodIcon}>
46 27
<Text style={styles.moodIconEmoji}>{moodDef?.icon ?? '😐'}</Text>
47 28
</View>
48 29
49 30
<View style={styles.moodBlock}>
101 82
letterSpacing: 0.1,
102 83
},
103 84
});
104 85
105 86
export default MoodEntryLog
/dev/null → frontend/lib/utils/time.ts
1 +
import { format, isToday, isYesterday } from 'date-fns';
2 +
import { ptBR } from 'date-fns/locale';
3 +
4 +
type TimeBadgeVariant = 'morning' | 'afternoon' | 'night' | 'latenight';
5 +
6 +
export const TIME_BADGES: Record<TimeBadgeVariant, { label: string; backgroundColor: string; color: string }> = {
7 +
morning: { label: 'Manhã', backgroundColor: '#dcfce7', color: '#16a34a' },
8 +
afternoon: { label: 'Tarde', backgroundColor: '#f1f5f9', color: '#475569' },
9 +
night: { label: 'Noite', backgroundColor: '#dbeafe', color: '#1d4ed8' },
10 +
latenight: { label: 'Madrugada', backgroundColor: '#f3e8ff', color: '#7e22ce' },
11 +
};
12 +
13 +
export const getTimeBadge = (date: Date) => {
14 +
const h = date.getHours();
15 +
if (h >= 6 && h < 12) return TIME_BADGES.morning;
16 +
if (h >= 12 && h < 18) return TIME_BADGES.afternoon;
17 +
if (h >= 18 && h < 24) return TIME_BADGES.night;
18 +
return TIME_BADGES.latenight;
19 +
}
20 +
21 +
export const formatMoment = (date: Date): string => {
22 +
if (isToday(date)) return `Hoje às ${format(date, "HH'h'mm")}`;
23 +
if (isYesterday(date)) return `Ontem às ${format(date, "HH'h'mm")}`;
24 +
return format(date, "d 'de' MMM 'às' HH'h'mm", { locale: ptBR });
25 +
}