import { ComponentType, Fragment } from "react"; import { StyleSheet, Text, View, ViewStyle, Animated } from "react-native"; import { gameUIColors } from "../constants/gameUIColors"; export interface StatCardConfig { key: string; label: string; subtitle: string; icon: ComponentType<{ size: number; color: string }>; color: string; value: number; showBar?: boolean; pulseDelay?: number; } export interface GameUICompactStatsProps { // Stats configuration array statsConfig: StatCardConfig[]; // Total count for percentage calculations totalCount?: number; // Header configuration header?: { title: string; subtitle: string; healthPercentage?: number; healthStatus?: string; healthColor?: string; }; // Bottom bar stats bottomStats?: { label: string; value: number | string; color?: string; }[]; // Container style style?: ViewStyle; // Whether to show only active stats (value > 0) hideInactive?: boolean; } /** * Reusable compact stats display component * Shows stat cards with icons, labels, values, and optional progress bars * Used in ENV and Storage pages for metrics display */ export function GameUICompactStats({ statsConfig, totalCount, header, bottomStats, style, hideInactive = true, }: GameUICompactStatsProps) { return ( {/* Compact Header with Health */} {header && ( {header.title} {header.subtitle} {header.healthPercentage !== undefined && ( {header.healthStatus || "OPTIMAL"} )} )} {/* Health Bar */} {header?.healthPercentage !== undefined && ( SYSTEM HEALTH {header.healthPercentage}% )} {/* Compact Stats Grid */} {statsConfig.map((stat) => { const isActive = stat.value > 0; if (hideInactive && !isActive) return null; const IconComponent = stat.icon; const percentage = totalCount ? (stat.value / totalCount) * 100 : 0; return ( {stat.label} {stat.subtitle} {stat.value.toString().padStart(2, "0")} {totalCount ? ( {Math.round(percentage)}% ) : null} {stat.showBar !== false && totalCount && ( )} ); })} {/* Bottom Stats Bar */} {bottomStats && bottomStats.length > 0 && ( {bottomStats.map((stat, index) => ( {stat.label} {stat.value} {index < bottomStats.length - 1 && ( )} ))} )} ); } const styles = StyleSheet.create({ container: { backgroundColor: gameUIColors.panel, borderRadius: 12, padding: 12, marginBottom: 12, borderWidth: 1, borderColor: gameUIColors.border + "40", overflow: "hidden", position: "relative", }, // Header header: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", marginBottom: 8, paddingBottom: 8, borderBottomWidth: 1, borderBottomColor: "rgba(255, 255, 255, 0.05)", }, headerLeft: { gap: 1, }, headerRight: { alignItems: "flex-end", }, headerTitle: { fontSize: 11, fontWeight: "700", color: gameUIColors.primary, fontFamily: "monospace", letterSpacing: 1.5, }, headerSubtitle: { fontSize: 8, color: gameUIColors.secondary, fontFamily: "monospace", opacity: 0.7, }, statusIndicator: { flexDirection: "row", alignItems: "center", gap: 4, }, statusDot: { width: 5, height: 5, borderRadius: 2.5, }, statusText: { fontSize: 9, fontWeight: "600", fontFamily: "monospace", letterSpacing: 0.5, }, // Health section healthSection: { flexDirection: "row", alignItems: "center", marginBottom: 10, gap: 8, }, healthLabel: { fontSize: 8, color: gameUIColors.secondary, fontFamily: "monospace", letterSpacing: 0.5, }, healthBarWrapper: { flex: 1, }, healthBarBg: { height: 4, backgroundColor: "rgba(255, 255, 255, 0.05)", borderRadius: 2, overflow: "hidden", }, healthBarFill: { height: "100%", borderRadius: 2, }, healthPercentage: { fontSize: 11, fontWeight: "700", fontFamily: "monospace", }, // Stats grid statsGrid: { gap: 6, marginBottom: 8, }, statCard: { backgroundColor: gameUIColors.blackTint2, borderRadius: 8, borderWidth: 1, borderColor: gameUIColors.border, padding: 10, marginBottom: 4, }, cardContent: { flexDirection: "row", alignItems: "center", gap: 8, marginBottom: 4, }, cardInfo: { flex: 1, }, cardLabel: { fontSize: 11, fontWeight: "700", fontFamily: "monospace", letterSpacing: 0.5, color: gameUIColors.primary, }, cardSubtitle: { fontSize: 8, color: gameUIColors.secondary, fontFamily: "monospace", opacity: 0.7, }, statNumber: { fontSize: 16, fontWeight: "700", fontFamily: "monospace", minWidth: 28, }, valueBlock: { alignItems: "flex-end", }, percentText: { fontSize: 9, color: gameUIColors.secondary, fontFamily: "monospace", }, statBar: { height: 3, borderRadius: 1.5, overflow: "hidden", }, statBarFill: { height: "100%", borderRadius: 1.5, }, // Bottom bar bottomBar: { flexDirection: "row", alignItems: "center", paddingTop: 8, borderTopWidth: 1, borderTopColor: gameUIColors.border + "40", }, bottomStat: { flex: 1, alignItems: "center", }, bottomStatLabel: { fontSize: 7, color: gameUIColors.muted, fontFamily: "monospace", letterSpacing: 0.5, marginBottom: 1, }, bottomStatValue: { fontSize: 11, fontWeight: "700", color: gameUIColors.primary, fontFamily: "monospace", }, bottomDivider: { width: 1, height: 16, backgroundColor: gameUIColors.border + "40", }, iconBadge: { width: 24, height: 24, borderRadius: 6, borderWidth: 1, alignItems: "center", justifyContent: "center", }, });