init + api use

This commit is contained in:
Primakov Alexandr Alexandrovich
2025-11-03 17:59:08 +03:00
commit e777b57991
52 changed files with 20725 additions and 0 deletions

View File

@@ -0,0 +1,162 @@
import React from 'react'
import { Box, Heading, Grid, Text, VStack, HStack, Badge, Progress } from '@chakra-ui/react'
import { useGetSystemStatsQuery } from '../../__data__/api/api'
import { StatCard } from '../../components/StatCard'
import { LoadingSpinner } from '../../components/LoadingSpinner'
import { ErrorAlert } from '../../components/ErrorAlert'
export const DashboardPage: React.FC = () => {
const { data: stats, isLoading, error, refetch } = useGetSystemStatsQuery(undefined, {
pollingInterval: 10000, // Обновление каждые 10 секунд
})
if (isLoading) {
return <LoadingSpinner message="Загрузка статистики..." />
}
if (error || !stats) {
return <ErrorAlert message="Не удалось загрузить статистику системы" onRetry={refetch} />
}
const acceptanceRate = stats.submissions.total > 0
? ((stats.submissions.accepted / stats.submissions.total) * 100).toFixed(1)
: '0'
const rejectionRate = stats.submissions.total > 0
? ((stats.submissions.rejected / stats.submissions.total) * 100).toFixed(1)
: '0'
const queueUtilization = stats.queue.maxConcurrency > 0
? ((stats.queue.currentlyProcessing / stats.queue.maxConcurrency) * 100).toFixed(0)
: '0'
return (
<Box>
<Heading mb={6}>Dashboard</Heading>
{/* Main Stats */}
<Grid templateColumns="repeat(auto-fit, minmax(250px, 1fr))" gap={6} mb={8}>
<StatCard label="Всего пользователей" value={stats.users} colorScheme="blue" />
<StatCard label="Всего заданий" value={stats.tasks} colorScheme="teal" />
<StatCard label="Всего цепочек" value={stats.chains} colorScheme="purple" />
<StatCard label="Всего проверок" value={stats.submissions.total} colorScheme="orange" />
</Grid>
{/* Submissions Stats */}
<Box bg="white" p={6} borderRadius="lg" boxShadow="sm" borderWidth="1px" borderColor="gray.200" mb={8}>
<Heading size="md" mb={4}>
Статистика проверок
</Heading>
<Grid templateColumns="repeat(auto-fit, minmax(200px, 1fr))" gap={6}>
<VStack align="start" gap={2}>
<Text fontSize="sm" color="gray.600">
Принято
</Text>
<HStack>
<Text fontSize="2xl" fontWeight="bold" color="green.600">
{stats.submissions.accepted}
</Text>
<Badge colorPalette="green">{acceptanceRate}%</Badge>
</HStack>
</VStack>
<VStack align="start" gap={2}>
<Text fontSize="sm" color="gray.600">
Отклонено
</Text>
<HStack>
<Text fontSize="2xl" fontWeight="bold" color="red.600">
{stats.submissions.rejected}
</Text>
<Badge colorPalette="red">{rejectionRate}%</Badge>
</HStack>
</VStack>
<VStack align="start" gap={2}>
<Text fontSize="sm" color="gray.600">
Ожидают
</Text>
<Text fontSize="2xl" fontWeight="bold" color="yellow.600">
{stats.submissions.pending}
</Text>
</VStack>
<VStack align="start" gap={2}>
<Text fontSize="sm" color="gray.600">
В процессе
</Text>
<Text fontSize="2xl" fontWeight="bold" color="blue.600">
{stats.submissions.inProgress}
</Text>
</VStack>
</Grid>
</Box>
{/* Queue Stats */}
<Box bg="white" p={6} borderRadius="lg" boxShadow="sm" borderWidth="1px" borderColor="gray.200" mb={8}>
<Heading size="md" mb={4}>
Статус очереди
</Heading>
<Grid templateColumns="repeat(auto-fit, minmax(250px, 1fr))" gap={6} mb={4}>
<VStack align="start" gap={2}>
<Text fontSize="sm" color="gray.600">
В обработке
</Text>
<HStack align="baseline">
<Text fontSize="2xl" fontWeight="bold" color="teal.600">
{stats.queue.currentlyProcessing}
</Text>
<Text fontSize="sm" color="gray.500">
/ {stats.queue.maxConcurrency}
</Text>
</HStack>
</VStack>
<VStack align="start" gap={2}>
<Text fontSize="sm" color="gray.600">
Ожидают в очереди
</Text>
<Text fontSize="2xl" fontWeight="bold" color="orange.600">
{stats.queue.waiting}
</Text>
</VStack>
<VStack align="start" gap={2}>
<Text fontSize="sm" color="gray.600">
Всего в очереди
</Text>
<Text fontSize="2xl" fontWeight="bold" color="blue.600">
{stats.queue.queueLength}
</Text>
</VStack>
</Grid>
<Box>
<Text fontSize="sm" color="gray.600" mb={2}>
Загруженность очереди: {queueUtilization}%
</Text>
<Progress.Root value={Number(queueUtilization)} colorPalette="teal" size="sm" borderRadius="full">
<Progress.Track>
<Progress.Range />
</Progress.Track>
</Progress.Root>
</Box>
</Box>
{/* Average Check Time */}
<Box bg="white" p={6} borderRadius="lg" boxShadow="sm" borderWidth="1px" borderColor="gray.200">
<Heading size="md" mb={2}>
Среднее время проверки
</Heading>
<Text fontSize="3xl" fontWeight="bold" color="purple.600">
{(stats.averageCheckTimeMs / 1000).toFixed(2)} сек
</Text>
<Text fontSize="sm" color="gray.600" mt={2}>
Время от отправки решения до получения результата
</Text>
</Box>
</Box>
)
}