refactor(frontend): comprehensive split of large view files into modular components
- Split UsersView.vue into UserCreateModal, UserEditModal, UserApiKeysModal, etc. - Split UsageView.vue into UsageStatsCards, UsageFilters, UsageTable, etc. - Split DashboardView.vue into UserDashboardStats, UserDashboardCharts, etc. - Split AccountsView.vue into AccountTableActions, AccountTableFilters, etc. - Standardized TypeScript types across new components to resolve implicit 'any' and 'never[]' errors. - Improved overall frontend maintainability and code clarity.
This commit is contained in:
81
frontend/src/components/user/profile/ProfileInfoCard.vue
Normal file
81
frontend/src/components/user/profile/ProfileInfoCard.vue
Normal file
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<div class="card overflow-hidden">
|
||||
<div
|
||||
class="border-b border-gray-100 bg-gradient-to-r from-primary-500/10 to-primary-600/5 px-6 py-5 dark:border-dark-700 dark:from-primary-500/20 dark:to-primary-600/10"
|
||||
>
|
||||
<div class="flex items-center gap-4">
|
||||
<!-- Avatar -->
|
||||
<div
|
||||
class="flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-primary-500 to-primary-600 text-2xl font-bold text-white shadow-lg shadow-primary-500/20"
|
||||
>
|
||||
{{ user?.email?.charAt(0).toUpperCase() || 'U' }}
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<h2 class="truncate text-lg font-semibold text-gray-900 dark:text-white">
|
||||
{{ user?.email }}
|
||||
</h2>
|
||||
<div class="mt-1 flex items-center gap-2">
|
||||
<span :class="['badge', user?.role === 'admin' ? 'badge-primary' : 'badge-gray']">
|
||||
{{ user?.role === 'admin' ? t('profile.administrator') : t('profile.user') }}
|
||||
</span>
|
||||
<span
|
||||
:class="['badge', user?.status === 'active' ? 'badge-success' : 'badge-danger']"
|
||||
>
|
||||
{{ user?.status }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-6 py-4">
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center gap-3 text-sm text-gray-600 dark:text-gray-400">
|
||||
<svg
|
||||
class="h-4 w-4 text-gray-400 dark:text-gray-500"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75"
|
||||
/>
|
||||
</svg>
|
||||
<span class="truncate">{{ user?.email }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="user?.username"
|
||||
class="flex items-center gap-3 text-sm text-gray-600 dark:text-gray-400"
|
||||
>
|
||||
<svg
|
||||
class="h-4 w-4 text-gray-400 dark:text-gray-500"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="truncate">{{ user.username }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type { User } from '@/types'
|
||||
|
||||
defineProps<{
|
||||
user: User | null
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
Reference in New Issue
Block a user