'use client'; import { useState, useEffect } from 'react'; import { Edit, Plus, Search, X, Check, AlertCircle } from 'lucide-react'; import { updateUserCredits, setUserDailyLimit, setUserApiCosts } from '@/services/admin-credit-service'; import { setUserPlan, getUserSubscription, type SubscriptionPlan } from '@/services/subscription-service'; interface User { id: string; email: string; username: string; balance: number; total_purchased: number; total_used: number; daily_limit: number | null; google_search_cost: number; gemini_ai_cost: number; last_active?: string; } interface UserManagementClientProps { initialUsers: User[]; plans: SubscriptionPlan[]; } export default function UserManagementClient({ initialUsers, plans }: UserManagementClientProps) { const [users, setUsers] = useState(initialUsers); const [searchTerm, setSearchTerm] = useState(''); const [editingUser, setEditingUser] = useState(null); const [creditAmount, setCreditAmount] = useState(''); const [reason, setReason] = useState(''); const [dailyLimit, setDailyLimit] = useState(''); const [googleCost, setGoogleCost] = useState(''); const [geminiCost, setGeminiCost] = useState(''); const [selectedPlan, setSelectedPlan] = useState(''); const [currentPlan, setCurrentPlan] = useState(null); const [loading, setLoading] = useState(false); const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null); const filteredUsers = users.filter(user => user.email.toLowerCase().includes(searchTerm.toLowerCase()) || user.username.toLowerCase().includes(searchTerm.toLowerCase()) ); // Load user's current plan when editing useEffect(() => { if (editingUser) { getUserSubscription(editingUser.id).then(({ plan }) => { setCurrentPlan(plan); setSelectedPlan(plan?.id || ''); }); } }, [editingUser]); const handleEditUser = (user: User) => { setEditingUser(user); setCreditAmount(''); setReason(''); setDailyLimit(user.daily_limit?.toString() || ''); setGoogleCost(user.google_search_cost.toString()); setGeminiCost(user.gemini_ai_cost.toString()); setMessage(null); }; const handleUpdatePlan = async () => { if (!editingUser || !selectedPlan) { setMessage({ type: 'error', text: 'Please select a plan' }); return; } setLoading(true); setMessage(null); const result = await setUserPlan(editingUser.id, selectedPlan); if (result.success) { setMessage({ type: 'success', text: 'Plan updated successfully' }); // Reload current plan const { plan } = await getUserSubscription(editingUser.id); setCurrentPlan(plan); } else { setMessage({ type: 'error', text: result.error || 'Failed to update plan' }); } setLoading(false); }; const handleUpdateCredits = async () => { if (!editingUser || !creditAmount || !reason) { setMessage({ type: 'error', text: 'Please fill in all fields' }); return; } setLoading(true); setMessage(null); const amount = parseInt(creditAmount); const newBalance = editingUser.balance + amount; const result = await updateUserCredits(editingUser.id, newBalance, reason); if (result.success) { // Update local state setUsers(users.map(u => u.id === editingUser.id ? { ...u, balance: newBalance, total_purchased: u.total_purchased + (amount > 0 ? amount : 0) } : u )); setMessage({ type: 'success', text: `Successfully ${amount > 0 ? 'added' : 'removed'} ${Math.abs(amount)} credits` }); setCreditAmount(''); setReason(''); } else { setMessage({ type: 'error', text: result.error || 'Failed to update credits' }); } setLoading(false); }; const handleUpdateSettings = async () => { if (!editingUser) return; setLoading(true); setMessage(null); // Update daily limit if (dailyLimit !== (editingUser.daily_limit?.toString() || '')) { const limitValue = dailyLimit === '' ? null : parseInt(dailyLimit); const limitResult = await setUserDailyLimit(editingUser.id, limitValue); if (!limitResult.success) { setMessage({ type: 'error', text: 'Failed to update daily limit' }); setLoading(false); return; } } // Update API costs if (googleCost !== editingUser.google_search_cost.toString() || geminiCost !== editingUser.gemini_ai_cost.toString()) { const costsResult = await setUserApiCosts( editingUser.id, parseInt(googleCost), parseInt(geminiCost) ); if (!costsResult.success) { setMessage({ type: 'error', text: 'Failed to update API costs' }); setLoading(false); return; } } // Update local state setUsers(users.map(u => u.id === editingUser.id ? { ...u, daily_limit: dailyLimit === '' ? null : parseInt(dailyLimit), google_search_cost: parseInt(googleCost), gemini_ai_cost: parseInt(geminiCost) } : u )); setMessage({ type: 'success', text: 'Settings updated successfully' }); setLoading(false); }; return (
{/* Search Bar */}
setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-3 bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-amber-500/50" />
{/* User Table */}

Users ({filteredUsers.length})

{filteredUsers.map((user) => ( ))}
User Balance Used Daily Limit Costs Actions
{user.username}
{user.email}
{user.balance} {user.total_used} {user.daily_limit || 'Global (80)'} G:{user.google_search_cost} / AI:{user.gemini_ai_cost}
{/* Edit Modal */} {editingUser && (

Edit User

{editingUser.email}

{message && (
{message.type === 'success' ? : } {message.text}
)}
{/* Current Balance */}
Current Balance
{editingUser.balance} Credits
{/* Add/Remove Credits */}

Adjust Credits

setCreditAmount(e.target.value)} placeholder="e.g. 100 or -50" className="w-full px-4 py-2 bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-amber-500/50" />
setReason(e.target.value)} placeholder="e.g. Monthly bonus" className="w-full px-4 py-2 bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-amber-500/50" />

{/* Subscription Plan */}

Subscription Plan

{currentPlan && (
Current Plan
{currentPlan.display_name}
{currentPlan.monthly_credits} credits/month
)}

{/* Settings */}

User Settings

setDailyLimit(e.target.value)} placeholder="Global (80)" className="w-full px-4 py-2 bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-amber-500/50" />
setGoogleCost(e.target.value)} className="w-full px-4 py-2 bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-amber-500/50" />
setGeminiCost(e.target.value)} className="w-full px-4 py-2 bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-amber-500/50" />
)}
); }