recent activity feed

updated, now showing real data
This commit is contained in:
dimitar committed 2026-03-12 16:25:57 +01:00
1 parent 981208ab7b
commit 96db3ea3b7
3 files changed
+351 -56

No files matched your search

+131 -56
View File
@@ -9,12 +9,13 @@ import {
TouchableOpacity,
} from "react-native";
import { useUser } from "@clerk/clerk-expo";
import { useState, useCallback, useEffect, useRef } from "react";
import { useState, useCallback, useEffect, useRef, useMemo } from "react";
import { useFocusEffect } from "@react-navigation/native";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { Ionicons } from "@expo/vector-icons";
import { useTheme } from "../../contexts/ThemeContext";
import { useStatistics } from "../../contexts/StatisticsContext";
import { useFitnessGoals } from "../../contexts/FitnessGoalsContext";
import { MinimalCard } from "../../components/MinimalCard";
import { SectionHeader } from "../../components/SectionHeader";
import { IconContainer } from "../../components/IconContainer";
@@ -22,6 +23,18 @@ import { ProgressBar } from "../../components/ProgressBar";
import { TrackMealModal } from "../../components/TrackMealModal";
import { AddWaterModal } from "../../components/AddWaterModal";
import { ScanFoodModal } from "../../components/ScanFoodModal";
import {
checkInsToActivities,
completedGoalsToActivities,
newGoalsToActivities,
combineActivities,
getRecentActivities,
formatActivityTime,
formatDuration,
getActivityIcon,
getActivityEmoji,
ActivityType,
} from "../../utils/activityFeed";
const CALORIE_GOAL = 2000; // kcal
const WATER_GOAL = 2000; // ml
@@ -31,6 +44,7 @@ export default function HomeScreen() {
const { colors, typography } = useTheme();
const { refetchStatistics, forceRefresh, statistics, loading } =
useStatistics();
const { goals } = useFitnessGoals();
const [refreshing, setRefreshing] = useState(false);
const [trackMealModalVisible, setTrackMealModalVisible] = useState(false);
const [addWaterModalVisible, setAddWaterModalVisible] = useState(false);
@@ -205,6 +219,29 @@ export default function HomeScreen() {
const checkInsThisWeek = statistics?.attendance.checkInsThisWeek || 0;
const currentStreak = statistics?.attendance.currentStreak || 0;
// Combine activities from multiple sources
const recentActivities = useMemo(() => {
if (!statistics || !goals) return [];
const checkInActivities = checkInsToActivities(statistics.attendance).slice(
0,
2,
); // Only last 2 check-ins
const completedGoalActivities = completedGoalsToActivities(goals).slice(
0,
2,
); // Only last 2 completed goals
const newGoalActivities = newGoalsToActivities(goals, 7); // Last 7 days
const allActivities = combineActivities(
checkInActivities,
completedGoalActivities,
newGoalActivities,
);
return getRecentActivities(allActivities, 5); // Show top 5
}, [statistics, goals]);
// Check for midnight reset
useEffect(() => {
const checkAndResetIfNeeded = async () => {
@@ -657,72 +694,104 @@ export default function HomeScreen() {
{/* Recent Activity */}
<View style={styles.section}>
<SectionHeader
title="Recent Activity"
actionLabel="See All"
onActionPress={() => console.log("See all tapped")}
title="📊 Recent Activity"
subtitle={
recentActivities.length === 0
? "Your activity will appear here"
: `${recentActivities.length} recent activities`
}
/>
<View style={styles.activityList}>
<MinimalCard variant="default" style={styles.activityItem}>
<IconContainer
variant="colored"
backgroundColor={`${colors.primary}20`}
>
<Ionicons name="barbell" size={20} color={colors.primary} />
</IconContainer>
<View style={styles.activityInfo}>
<Text style={[typography.h3, { color: colors.textPrimary }]}>
Upper Body Power
{recentActivities.length === 0 ? (
<MinimalCard variant="default" style={{ borderRadius: 20 }}>
<View style={styles.emptyActivity}>
<Text style={{ fontSize: 64 }}>🏃</Text>
<Text
style={[
typography.bodyEmphasis,
{ color: colors.textPrimary, marginTop: 16 },
]}
>
No Recent Activity
</Text>
<Text
style={[
typography.caption,
{ color: colors.textTertiary, marginTop: 2 },
typography.body,
{
color: colors.textSecondary,
marginTop: 8,
textAlign: "center",
},
]}
>
Today, 10:00 AM
Check in at the gym or complete a goal to get started! 💪
</Text>
</View>
<Text
style={[
typography.bodyEmphasis,
{ color: colors.textSecondary },
]}
>
45m
</Text>
</MinimalCard>
) : (
<View style={styles.activityList}>
{recentActivities.map((activity) => {
const iconName = getActivityIcon(activity.type);
const emoji = getActivityEmoji(activity.type);
const timeStr = formatActivityTime(activity.timestamp);
const durationStr = formatDuration(activity.duration);
<MinimalCard variant="default" style={styles.activityItem}>
<IconContainer
variant="colored"
backgroundColor={`${colors.success}20`}
>
<Ionicons name="bicycle" size={20} color={colors.success} />
</IconContainer>
<View style={styles.activityInfo}>
<Text style={[typography.h3, { color: colors.textPrimary }]}>
Morning Cardio
</Text>
<Text
style={[
typography.caption,
{ color: colors.textTertiary, marginTop: 2 },
]}
>
Yesterday, 7:30 AM
</Text>
</View>
<Text
style={[
typography.bodyEmphasis,
{ color: colors.textSecondary },
]}
>
30m
</Text>
</MinimalCard>
</View>
// Determine color based on activity type
let iconColor = colors.primary;
if (activity.type === ActivityType.GOAL_COMPLETED) {
iconColor = colors.success;
} else if (activity.type === ActivityType.GOAL_CREATED) {
iconColor = colors.accent;
} else if (activity.type === ActivityType.GYM_CHECKIN) {
iconColor = colors.primary;
}
return (
<MinimalCard
key={activity.id}
variant="bordered"
style={styles.activityItem}
>
<IconContainer
variant="colored"
backgroundColor={`${iconColor}20`}
>
<Ionicons
name={iconName as any}
size={20}
color={iconColor}
/>
</IconContainer>
<View style={styles.activityInfo}>
<Text
style={[typography.h3, { color: colors.textPrimary }]}
>
{emoji} {activity.title}
</Text>
<Text
style={[
typography.caption,
{ color: colors.textTertiary, marginTop: 2 },
]}
>
{timeStr}
</Text>
</View>
{durationStr && (
<Text
style={[
typography.bodyEmphasis,
{ color: colors.textSecondary },
]}
>
{durationStr}
</Text>
)}
</MinimalCard>
);
})}
</View>
)}
</View>
<TrackMealModal
@@ -850,8 +919,14 @@ const styles = StyleSheet.create({
flexDirection: "row",
alignItems: "center",
gap: 12,
borderRadius: 16,
},
activityInfo: {
flex: 1,
},
emptyActivity: {
alignItems: "center",
paddingVertical: 40,
paddingHorizontal: 20,
},
});