import React, { useEffect, useState } from 'react'; import { View, Pressable } from 'react-native'; import { Icon } from './Icon'; import { Text } from './Text'; import { supabase } from '~/utils/supabase'; import { useAuth } from '~/contexts/AuthContext'; import { useTheme } from '~/contexts/ThemeContext'; interface RateLimits { daily_used: number; daily_limit: number; daily_reset_at: string; hourly_used: number; hourly_limit: number; hourly_reset_at: string; active_generations: number; max_concurrent: number; total_all_time: number; } interface RateLimitIndicatorProps { compact?: boolean; onRefresh?: () => void; } export function RateLimitIndicator({ compact = false, onRefresh }: RateLimitIndicatorProps) { const { user } = useAuth(); const { theme } = useTheme(); const [limits, setLimits] = useState(null); const [loading, setLoading] = useState(true); const [expanded, setExpanded] = useState(false); const fetchLimits = async () => { if (!user) return; try { const { data, error } = await supabase.rpc('get_user_limits', { p_user_id: user.id }); if (error) throw error; setLimits(data); } catch (error) { console.error('Error fetching rate limits:', error); } finally { setLoading(false); } }; useEffect(() => { fetchLimits(); // Refresh every minute const interval = setInterval(fetchLimits, 60000); return () => clearInterval(interval); }, [user]); const formatResetTime = (resetAt: string) => { const reset = new Date(resetAt); const now = new Date(); const diff = reset.getTime() - now.getTime(); if (diff <= 0) return 'Resetting...'; const hours = Math.floor(diff / (1000 * 60 * 60)); const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); if (hours > 0) return `${hours}h ${minutes}m`; return `${minutes}m`; }; const getUsageColor = (used: number, limit: number) => { const percentage = (used / limit) * 100; if (percentage >= 90) return '#ef4444'; // red if (percentage >= 75) return '#eab308'; // yellow return '#10b981'; // green }; if (loading || !limits) return null; const dailyPercentage = Math.min(100, (limits.daily_used / limits.daily_limit) * 100); const hourlyPercentage = Math.min(100, (limits.hourly_used / limits.hourly_limit) * 100); if (compact) { return ( setExpanded(!expanded)} style={{ backgroundColor: theme.colors.surface, borderRadius: 8, padding: 8, marginBottom: 8 }} > {limits.daily_limit - limits.daily_used} daily left {expanded && ( Hourly {limits.hourly_used}/{limits.hourly_limit} ({formatResetTime(limits.hourly_reset_at)}) Active {limits.active_generations}/{limits.max_concurrent} All Time {limits.total_all_time} )} ); } return ( Usage Limits {onRefresh && ( )} {/* Daily Limit */} Daily Limit {limits.daily_used}/{limits.daily_limit} • Resets in {formatResetTime(limits.daily_reset_at)} {/* Hourly Limit */} Hourly Limit {limits.hourly_used}/{limits.hourly_limit} • Resets in {formatResetTime(limits.hourly_reset_at)} {/* Additional Stats */} {limits.active_generations} Active {limits.max_concurrent} Max Parallel {limits.total_all_time} Total ); }