import { Text } from '@/aesthetics/Text'; import { font, radius, spacing, useColors } from '@/aesthetics/styles'; import { useStrings } from '@/common/hooks/useStrings'; import type { NutrientKey, Nutrition, NutritionDisplayMode, NutritionSortMode, } from '@/types/nutrition'; import { ArrowDownUp, ChevronDown } from 'lucide-react-native'; import { useMemo, useState } from 'react'; import { Pressable, StyleSheet, View, useWindowDimensions } from 'react-native'; import { NUTRIENT_META } from '@/common/constants/nutrition'; import { getNutrientsByMode, sortNutrients } from '@/see-log/utils/nutrition'; import { NutrientTile } from './NutrientTile'; type NutrientBreakdownProps = { consumed: Nutrition; targets: Nutrition; displayMode: NutritionDisplayMode; sortMode: NutritionSortMode; onChangeDisplayMode: (mode: NutritionDisplayMode) => void; onChangeSortMode: (mode: NutritionSortMode) => void; }; const GAP = spacing.xs; const TILES_PER_ROW = 3; const INITIAL_ROWS = 3; const CARD_BORDER = 2; const CONTAINER_PADDING = spacing.xl * 4 + CARD_BORDER; function TileGrid({ keys, consumed, targets, tileWidth, }: { keys: NutrientKey[]; consumed: Nutrition; targets: Nutrition; tileWidth: number; }) { return ( {keys.map(k => { const meta = NUTRIENT_META[k]; const consumedValue = consumed[k] ?? 0; const targetValue = targets[k] ?? 100; const pct = Math.min((consumedValue / targetValue) * 100, 100); return ( ); })} ); } export function NutrientBreakdown({ consumed, targets, displayMode, sortMode, onChangeDisplayMode, onChangeSortMode, }: NutrientBreakdownProps) { const c = useColors(); const strings = useStrings(); const { width: screenWidth } = useWindowDimensions(); const [expanded, setExpanded] = useState(false); const tileWidth = (screenWidth - CONTAINER_PADDING - GAP * (TILES_PER_ROW - 1)) / TILES_PER_ROW; const { level1, level2, level3 } = useMemo(() => { const byLevel = getNutrientsByMode(displayMode); return { level1: sortNutrients(byLevel.level1, sortMode, consumed, targets), level2: sortNutrients(byLevel.level2, sortMode, consumed, targets), level3: sortNutrients(byLevel.level3, sortMode, consumed, targets), }; }, [displayMode, sortMode, consumed, targets]); const isNutrientsMode = displayMode === 'nutrients'; const initialVisible = INITIAL_ROWS * TILES_PER_ROW; const hiddenCount = level1.length - initialVisible + (isNutrientsMode ? level2.length + level3.length : 0); const visibleLevel1 = expanded ? level1 : level1.slice(0, initialVisible); return ( {(['nutrients', 'usa_gov_dga'] as const).map(mode => ( onChangeDisplayMode(mode)} style={[styles.modeTab, displayMode === mode && { backgroundColor: c.surface }]} > {mode === 'nutrients' ? strings.seeLog.nutrients : strings.seeLog.nutrientBreakdown.usRealFood} ))} {strings.seeLog.nutrientBreakdown.important} onChangeSortMode(sortMode === 'default' ? 'least_filled' : 'default')} style={({ pressed }) => [ styles.sortButton, { backgroundColor: c.tagBg }, pressed && { opacity: 0.7 }, ]} > {sortMode === 'default' ? strings.seeLog.sorting.default : strings.seeLog.sorting.priority} {expanded && isNutrientsMode && level2.length > 0 && ( {strings.seeLog.nutrientBreakdown.hardToEat} )} {expanded && isNutrientsMode && level3.length > 0 && ( {strings.seeLog.nutrientBreakdown.more} )} {hiddenCount > 0 && ( setExpanded(e => !e)} style={({ pressed }) => [styles.expandButton, pressed && { opacity: 0.7 }]} > {expanded ? strings.seeLog.nutrientBreakdown.showLess : strings.seeLog.nutrientBreakdown.showMore(hiddenCount)} )} ); } const styles = StyleSheet.create({ modeTabs: { flexDirection: 'row', padding: 3, borderRadius: radius.md, marginBottom: spacing.lg, }, sectionHeaderRow: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: spacing.sm, }, modeTab: { flex: 1, paddingVertical: spacing.sm, borderRadius: radius.sm, alignItems: 'center', }, modeTabText: { fontSize: font.sm, fontWeight: '500', }, grid: { width: '100%', flexDirection: 'row', flexWrap: 'wrap', gap: GAP, }, expandButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: spacing.xs, marginTop: spacing.lg, }, expandText: { fontSize: font.sm, fontWeight: '500', }, sortButton: { flexDirection: 'row', alignItems: 'center', gap: spacing.xs, paddingHorizontal: spacing.sm, paddingVertical: spacing.sm, borderRadius: radius.md, }, sortButtonText: { fontSize: font.xs, fontWeight: '500', }, sectionHeader: { fontSize: font.md, fontWeight: '600', marginTop: spacing.lg, marginBottom: spacing.sm, }, firstSectionHeader: { marginTop: 0, marginBottom: 0, }, });