feat: добавил эндпоинт для получения статистики админского дашборда
Backend CI / build-and-test (push) Successful in 40s
Frontend CI / build-and-check (push) Failing after 19s
🚀 Create and publish a Docker image / Detect changes in backend and frontend (push) Successful in 6s
🚀 Create and publish a Docker image / Build & publish backend image (push) Successful in 24s
🚀 Create and publish a Docker image / Build & publish frontend image (push) Successful in 27s
🚀 Create and publish a Docker image / Update stack on Portainer (push) Successful in 5s

This commit is contained in:
2026-05-28 05:09:47 +03:00
parent e8f7a64d15
commit a8d51df3f1
8 changed files with 123 additions and 23 deletions
+14 -23
View File
@@ -3,17 +3,11 @@ import { computed, onMounted, ref } from 'vue'
import GlassCard from '@/components/ui/GlassCard.vue'
import StatsWidget from '@/components/ui/StatsWidget.vue'
import StatusBadge from '@/components/ui/StatusBadge.vue'
import { lecturesApi, reviewsApi, syncApi, usersApi } from '@/api'
import type { LectureDto, SyncStatusDto, UserDto } from '@/api/types'
import { syncApi, usersApi } from '@/api'
import type { AdminDashboardStatsDto, SyncStatusDto } from '@/api/types'
const users = ref<UserDto[]>([])
const lectures = ref<LectureDto[]>([])
const pendingReviewsCount = ref(0)
const stats = ref<AdminDashboardStatsDto | null>(null)
const syncStatus = ref<SyncStatusDto | null>(null)
const enrollmentCount = computed(() =>
lectures.value.reduce((sum, lecture) => sum + lecture.enrollmentsCount, 0),
)
const syncMeta = computed(() =>
syncStatus.value?.lastSyncAt
? `Последняя синхронизация: ${new Date(syncStatus.value.lastSyncAt).toLocaleString('ru-RU')}`
@@ -21,16 +15,8 @@ const syncMeta = computed(() =>
)
onMounted(async () => {
const [usersResult, lecturesResult, reviewsResult, syncResult] = await Promise.allSettled([
usersApi.list({ PageSize: 100 }),
lecturesApi.list({ PageSize: 100 }),
reviewsApi.listPage({ Page: 1, PageSize: 1, LlmStatus: 'Pending' }),
syncApi.status(),
])
if (usersResult.status === 'fulfilled') users.value = usersResult.value
if (lecturesResult.status === 'fulfilled') lectures.value = lecturesResult.value
if (reviewsResult.status === 'fulfilled')
pendingReviewsCount.value = reviewsResult.value.totalCount
const [statsResult, syncResult] = await Promise.allSettled([usersApi.adminStats(), syncApi.status()])
if (statsResult.status === 'fulfilled') stats.value = statsResult.value
if (syncResult.status === 'fulfilled') syncStatus.value = syncResult.value
})
</script>
@@ -40,12 +26,17 @@ onMounted(async () => {
<h1 class="page-title">Дашборд администратора</h1>
<div class="stats-row">
<StatsWidget label="Пользователей" :value="users.length" icon="users" color="green" />
<StatsWidget label="Лекций" :value="lectures.length" icon="books" color="aqua" />
<StatsWidget label="Записей" :value="enrollmentCount" icon="calendar-event" color="orange" />
<StatsWidget label="Пользователей" :value="stats?.usersCount ?? 0" icon="users" color="green" />
<StatsWidget label="Лекций" :value="stats?.lecturesCount ?? 0" icon="books" color="aqua" />
<StatsWidget
label="Записей"
:value="stats?.enrollmentsCount ?? 0"
icon="calendar-event"
color="orange"
/>
<StatsWidget
label="Отзывы на проверке"
:value="pendingReviewsCount"
:value="stats?.pendingReviewsCount ?? 0"
icon="message-circle"
color="purple"
/>