import { useEffect, useRef } from "react"; import { View, Text, StyleSheet, Animated, ViewStyle, TextStyle, } from "react-native"; import { CheckCircle, XCircle, AlertCircle, Clock, Info, LucideIcon, } from "../../icons"; import { gameUIColors } from "../gameUI"; export type StatusType = "success" | "error" | "warning" | "pending" | "info"; interface StatusIndicatorProps { status: StatusType; size?: "small" | "medium" | "large"; showLabel?: boolean; label?: string; showIcon?: boolean; animated?: boolean; style?: ViewStyle; labelStyle?: TextStyle; variant?: "dot" | "icon" | "badge" | "text"; } const statusConfig: Record< StatusType, { color: string; icon: LucideIcon; label: string; bgColor: string; } > = { success: { color: gameUIColors.success, icon: CheckCircle, label: "Success", bgColor: gameUIColors.success + "20", }, error: { color: gameUIColors.error, icon: XCircle, label: "Error", bgColor: gameUIColors.error + "20", }, warning: { color: gameUIColors.warning, icon: AlertCircle, label: "Warning", bgColor: gameUIColors.warning + "20", }, pending: { color: gameUIColors.warning, icon: Clock, label: "Pending", bgColor: gameUIColors.warning + "20", }, info: { color: gameUIColors.primary, icon: Info, label: "Info", bgColor: gameUIColors.primary + "20", }, }; export function StatusIndicator({ status, size = "medium", showLabel = false, label, showIcon = true, animated = false, style, labelStyle, variant = "icon", }: StatusIndicatorProps) { const pulseAnim = useRef(new Animated.Value(1)).current; const config = statusConfig[status]; const sizeConfig = { small: { iconSize: 12, fontSize: 10, dotSize: 6, padding: 4 }, medium: { iconSize: 16, fontSize: 12, dotSize: 8, padding: 6 }, large: { iconSize: 20, fontSize: 14, dotSize: 10, padding: 8 }, }; const sizes = sizeConfig[size]; const Icon = config.icon; const displayLabel = label || config.label; useEffect(() => { if (animated && status === "pending") { const animation = Animated.loop( Animated.sequence([ Animated.timing(pulseAnim, { toValue: 1.2, duration: 600, useNativeDriver: true, }), Animated.timing(pulseAnim, { toValue: 1, duration: 600, useNativeDriver: true, }), ]) ); animation.start(); return () => animation.stop(); } }, [animated, status, pulseAnim]); if (variant === "dot") { return ( ); } if (variant === "text") { return ( {displayLabel} ); } if (variant === "badge") { return ( {showIcon && } {showLabel && ( {displayLabel} )} ); } // Default icon variant return ( {showLabel && ( {displayLabel} )} ); } interface StatusDotProps { status: StatusType; size?: number; animated?: boolean; style?: ViewStyle; } StatusIndicator.Dot = function StatusDot({ status, size = 8, animated = false, style, }: StatusDotProps) { return ( ); }; interface StatusBadgeProps { status: StatusType; label?: string; size?: "small" | "medium" | "large"; showIcon?: boolean; style?: ViewStyle; } StatusIndicator.Badge = function StatusBadge({ status, label, size = "medium", showIcon = true, style, }: StatusBadgeProps) { return ( ); }; interface StatusTextProps { status: StatusType; label?: string; size?: "small" | "medium" | "large"; style?: TextStyle; } StatusIndicator.Text = function StatusText({ status, label, size = "medium", style, }: StatusTextProps) { return ( ); }; const styles = StyleSheet.create({ iconContainer: { flexDirection: "row", alignItems: "center", gap: 4, }, label: { fontWeight: "500", }, dot: { borderRadius: 100, }, text: { fontWeight: "600", }, badge: { flexDirection: "row", alignItems: "center", gap: 4, borderRadius: 4, }, badgeLabel: { fontWeight: "600", marginLeft: 4, }, });