mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 09:38:02 +00:00
feat: separate active and deleted API keys display in user dashboard
- Replace single "API Keys" counter with separate "Active API Keys" and "Deleted API Keys" - Add loadApiKeysStats function to count active vs deleted keys separately - Update grid layout from lg:grid-cols-4 to lg:grid-cols-5 to accommodate new card - Add green icon for active keys and trash icon for deleted keys - Refresh API keys stats when switching to overview tab - Change default tab to 'overview' for better UX 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,7 @@
|
|||||||
? 'bg-blue-100 text-blue-700'
|
? 'bg-blue-100 text-blue-700'
|
||||||
: 'text-gray-500 hover:text-gray-700'
|
: 'text-gray-500 hover:text-gray-700'
|
||||||
]"
|
]"
|
||||||
@click="activeTab = 'overview'"
|
@click="handleTabChange('overview')"
|
||||||
>
|
>
|
||||||
Overview
|
Overview
|
||||||
</button>
|
</button>
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
? 'bg-blue-100 text-blue-700'
|
? 'bg-blue-100 text-blue-700'
|
||||||
: 'text-gray-500 hover:text-gray-700'
|
: 'text-gray-500 hover:text-gray-700'
|
||||||
]"
|
]"
|
||||||
@click="activeTab = 'api-keys'"
|
@click="handleTabChange('api-keys')"
|
||||||
>
|
>
|
||||||
API Keys
|
API Keys
|
||||||
</button>
|
</button>
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
? 'bg-blue-100 text-blue-700'
|
? 'bg-blue-100 text-blue-700'
|
||||||
: 'text-gray-500 hover:text-gray-700'
|
: 'text-gray-500 hover:text-gray-700'
|
||||||
]"
|
]"
|
||||||
@click="activeTab = 'usage'"
|
@click="handleTabChange('usage')"
|
||||||
>
|
>
|
||||||
Usage Stats
|
Usage Stats
|
||||||
</button>
|
</button>
|
||||||
@@ -84,13 +84,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Stats Cards -->
|
<!-- Stats Cards -->
|
||||||
<div class="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-4">
|
<div class="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-5">
|
||||||
<div class="overflow-hidden rounded-lg bg-white shadow">
|
<div class="overflow-hidden rounded-lg bg-white shadow">
|
||||||
<div class="p-5">
|
<div class="p-5">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="flex-shrink-0">
|
<div class="flex-shrink-0">
|
||||||
<svg
|
<svg
|
||||||
class="h-6 w-6 text-gray-400"
|
class="h-6 w-6 text-green-400"
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
@@ -105,9 +105,39 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="ml-5 w-0 flex-1">
|
<div class="ml-5 w-0 flex-1">
|
||||||
<dl>
|
<dl>
|
||||||
<dt class="truncate text-sm font-medium text-gray-500">API Keys</dt>
|
<dt class="truncate text-sm font-medium text-gray-500">Active API Keys</dt>
|
||||||
<dd class="text-lg font-medium text-gray-900">
|
<dd class="text-lg font-medium text-gray-900">
|
||||||
{{ userProfile?.apiKeyCount || 0 }}
|
{{ apiKeysStats.active }}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="overflow-hidden rounded-lg bg-white shadow">
|
||||||
|
<div class="p-5">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<svg
|
||||||
|
class="h-6 w-6 text-gray-400"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="ml-5 w-0 flex-1">
|
||||||
|
<dl>
|
||||||
|
<dt class="truncate text-sm font-medium text-gray-500">Deleted API Keys</dt>
|
||||||
|
<dd class="text-lg font-medium text-gray-900">
|
||||||
|
{{ apiKeysStats.deleted }}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
@@ -282,8 +312,9 @@ import UserUsageStats from '@/components/user/UserUsageStats.vue'
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
const activeTab = ref('api-keys')
|
const activeTab = ref('overview')
|
||||||
const userProfile = ref(null)
|
const userProfile = ref(null)
|
||||||
|
const apiKeysStats = ref({ active: 0, deleted: 0 })
|
||||||
|
|
||||||
const formatNumber = (num) => {
|
const formatNumber = (num) => {
|
||||||
if (num >= 1000000) {
|
if (num >= 1000000) {
|
||||||
@@ -305,6 +336,14 @@ const formatDate = (dateString) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleTabChange = (tab) => {
|
||||||
|
activeTab.value = tab
|
||||||
|
// Refresh API keys stats when switching to overview tab
|
||||||
|
if (tab === 'overview') {
|
||||||
|
loadApiKeysStats()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleLogout = async () => {
|
const handleLogout = async () => {
|
||||||
try {
|
try {
|
||||||
await userStore.logout()
|
await userStore.logout()
|
||||||
@@ -325,8 +364,26 @@ const loadUserProfile = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loadApiKeysStats = async () => {
|
||||||
|
try {
|
||||||
|
const allApiKeys = await userStore.getUserApiKeys(true) // Include deleted keys
|
||||||
|
const activeCount = allApiKeys.filter(
|
||||||
|
(key) => !(key.isDeleted === 'true' || key.deletedAt) && key.isActive
|
||||||
|
).length
|
||||||
|
const deletedCount = allApiKeys.filter(
|
||||||
|
(key) => key.isDeleted === 'true' || key.deletedAt
|
||||||
|
).length
|
||||||
|
|
||||||
|
apiKeysStats.value = { active: activeCount, deleted: deletedCount }
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to load API keys stats:', error)
|
||||||
|
apiKeysStats.value = { active: 0, deleted: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadUserProfile()
|
loadUserProfile()
|
||||||
|
loadApiKeysStats()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user