/** * TabataGo Activity Tab * Streak, weekly sessions, program history — driven by progressStore. */ import { useMemo } from 'react' import { View, Text, StyleSheet, ScrollView } from 'react-native' import { useSafeAreaInsets } from 'react-native-safe-area-context' import { useTranslation } from 'react-i18next' import { Icon } from '@/src/shared/components/Icon' import { useProgressStore } from '@/src/shared/stores/progressStore' import { useThemeColors } from '@/src/shared/theme' import type { ThemeColors } from '@/src/shared/theme/types' import { TYPOGRAPHY } from '@/src/shared/constants/typography' import { SPACING, LAYOUT } from '@/src/shared/constants/spacing' import { RADIUS } from '@/src/shared/constants/borderRadius' import { GREEN, NAVY, TEXT, BORDER_COLORS } from '@/src/shared/constants/colors' export default function ActivityScreen() { const { t } = useTranslation() const insets = useSafeAreaInsets() const colors = useThemeColors() const styles = useMemo(() => createStyles(colors), [colors]) const history = useProgressStore(s => s.history) const streak = useProgressStore(s => s.streak) const weeklyCount = useProgressStore(s => s.getWeeklyCount()) const completedCount = useProgressStore(s => s.getCompletedCount()) const totalMinutes = useMemo( () => history.reduce((sum, s) => sum + Math.round(s.durationSeconds / 60), 0), [history], ) return ( {t('screens:tabs.progression')} {/* Streak hero */} {streak.current} {t('screens:activity.dayStreak')} {t('screens:activity.longest')}: {streak.longest} {/* Stats grid */} {/* Recent history */} {history.length > 0 && ( {t('screens:activity.recent')} {history.slice(0, 10).map((session, i) => ( {session.programId} {Math.round(session.durationSeconds / 60)} min {' · '} {new Date(session.completedAt).toLocaleDateString()} ))} )} {history.length === 0 && ( {t('screens:activity.emptyTitle')} {t('screens:activity.emptySubtitle')} )} ) } function StatCard({ icon, value, label, color }: { icon: any; value: number; label: string; color: string }) { return ( {value} {label} ) } const cardStyles = StyleSheet.create({ card: { flex: 1, alignItems: 'center', padding: SPACING[3], borderRadius: RADIUS.LG, backgroundColor: NAVY[800], borderWidth: 1, borderColor: BORDER_COLORS.DIM, gap: SPACING[1], borderCurve: 'continuous', }, value: { ...TYPOGRAPHY.TITLE_2, color: TEXT.PRIMARY, fontVariant: ['tabular-nums'] }, label: { ...TYPOGRAPHY.CAPTION_2, color: TEXT.TERTIARY, textAlign: 'center' }, }) function createStyles(colors: ThemeColors) { return StyleSheet.create({ container: { flex: 1, backgroundColor: colors.bg.base }, content: { paddingHorizontal: LAYOUT.SCREEN_PADDING }, title: { ...TYPOGRAPHY.LARGE_TITLE, color: TEXT.PRIMARY, marginBottom: SPACING[5] }, streakHero: { alignItems: 'center', paddingVertical: SPACING[6], marginBottom: SPACING[4], backgroundColor: NAVY[800], borderRadius: RADIUS.XL, borderWidth: 1, borderColor: BORDER_COLORS.DIM, gap: SPACING[1], }, streakCount: { ...TYPOGRAPHY.LARGE_TITLE, color: TEXT.PRIMARY, fontSize: 56, fontVariant: ['tabular-nums'] }, streakLabel: { ...TYPOGRAPHY.HEADLINE, color: TEXT.SECONDARY }, streakRecord: { ...TYPOGRAPHY.CAPTION_1, color: TEXT.TERTIARY, marginTop: SPACING[1] }, grid: { flexDirection: 'row', gap: SPACING[3], marginBottom: SPACING[6] }, historySection: { gap: SPACING[2] }, sectionTitle: { ...TYPOGRAPHY.CAPTION_1, color: TEXT.TERTIARY, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: SPACING[1], }, historyRow: { flexDirection: 'row', alignItems: 'center', gap: SPACING[3], padding: SPACING[3], backgroundColor: colors.surface.default.backgroundColor, borderRadius: RADIUS.MD, borderWidth: 1, borderColor: colors.surface.default.borderColor, }, historyTitle: { ...TYPOGRAPHY.SUBHEADLINE, color: TEXT.PRIMARY }, historyMeta: { ...TYPOGRAPHY.CAPTION_1, color: TEXT.TERTIARY, marginTop: 2 }, emptyState: { alignItems: 'center', marginTop: SPACING[12], gap: SPACING[2] }, emptyTitle: { ...TYPOGRAPHY.HEADLINE, color: TEXT.PRIMARY }, emptySubtitle: { ...TYPOGRAPHY.BODY, color: TEXT.TERTIARY, textAlign: 'center' }, }) }