fix: resolve relationship error in admin dashboard
- Fetched api_usage and profiles separately to avoid Supabase join errors when relationships are not explicitly defined in the schema cache. - Updated Gemini AI tracking integration to ensure all calls are recorded correctly. - Improved error handling in admin dashboard.
This commit is contained in:
@@ -29,30 +29,38 @@ export default async function AdminPage() {
|
||||
// Fetch global API stats
|
||||
const stats = await getGlobalApiStats();
|
||||
|
||||
// Fetch recent API usage
|
||||
// Fetch recent API usage without join to avoid relationship errors
|
||||
console.log('[Admin Page] Fetching recent API usage...');
|
||||
const { data: recentUsage, error: recentError } = await supabase
|
||||
const { data: recentUsageRaw, error: recentError } = await supabase
|
||||
.from('api_usage')
|
||||
.select(`
|
||||
*,
|
||||
profiles:user_id (
|
||||
username
|
||||
)
|
||||
`)
|
||||
.select('*')
|
||||
.order('created_at', { ascending: false })
|
||||
.limit(50);
|
||||
|
||||
console.log('[Admin Page] Recent usage - count:', recentUsage?.length, 'error:', recentError);
|
||||
console.log('[Admin Page] Recent usage raw - count:', recentUsageRaw?.length, 'error:', recentError);
|
||||
|
||||
// Get unique user IDs from recent usage
|
||||
const recentUserIds = Array.from(new Set(recentUsageRaw?.map(u => u.user_id) || []));
|
||||
|
||||
// Fetch profiles for these users
|
||||
const { data: recentProfiles } = recentUserIds.length > 0
|
||||
? await supabase.from('profiles').select('id, username').in('id', recentUserIds)
|
||||
: { data: [] };
|
||||
|
||||
// Combine usage with profiles
|
||||
const recentUsage = recentUsageRaw?.map(usage => ({
|
||||
...usage,
|
||||
profiles: recentProfiles?.find(p => p.id === usage.user_id) || { username: 'Unknown' }
|
||||
})) || [];
|
||||
|
||||
// Fetch per-user statistics
|
||||
const { data: userStats } = await supabase
|
||||
const { data: userStatsRaw } = await supabase
|
||||
.from('api_usage')
|
||||
.select('user_id, api_type')
|
||||
.order('created_at', { ascending: false });
|
||||
.select('user_id, api_type');
|
||||
|
||||
// Group by user
|
||||
const userStatsMap = new Map<string, { googleSearch: number; geminiAi: number; total: number }>();
|
||||
userStats?.forEach(item => {
|
||||
userStatsRaw?.forEach(item => {
|
||||
const current = userStatsMap.get(item.user_id) || { googleSearch: 0, geminiAi: 0, total: 0 };
|
||||
if (item.api_type === 'google_search') current.googleSearch++;
|
||||
if (item.api_type === 'gemini_ai') current.geminiAi++;
|
||||
@@ -66,10 +74,9 @@ export default async function AdminPage() {
|
||||
.slice(0, 10)
|
||||
.map(([userId]) => userId);
|
||||
|
||||
const { data: topUsers } = await supabase
|
||||
.from('profiles')
|
||||
.select('id, username')
|
||||
.in('id', topUserIds);
|
||||
const { data: topUsers } = topUserIds.length > 0
|
||||
? await supabase.from('profiles').select('id, username').in('id', topUserIds)
|
||||
: { data: [] };
|
||||
|
||||
const topUsersWithStats = topUsers?.map(user => ({
|
||||
...user,
|
||||
@@ -222,8 +229,8 @@ export default async function AdminPage() {
|
||||
</td>
|
||||
<td className="py-3 px-4">
|
||||
<span className={`px-2 py-1 rounded-full text-xs font-bold ${call.api_type === 'google_search'
|
||||
? 'bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400'
|
||||
: 'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-400'
|
||||
? 'bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400'
|
||||
: 'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-400'
|
||||
}`}>
|
||||
{call.api_type === 'google_search' ? 'Google Search' : 'Gemini AI'}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user