fix(stats): top-списки и группировка по типу на list-страницах
Refs EventHub/EventHubFrontAdmin#27 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -204,8 +204,37 @@ const CalendarListPage: React.FC = () => {
|
||||
</Card>
|
||||
</Col>
|
||||
))}
|
||||
{Object.entries(stats.calendars_by_type || {}).map(([type, count]) => (
|
||||
<Col xs={12} sm={6} md={4} key={`type-${type}`}>
|
||||
<Card>
|
||||
<Statistic title={`Тип: ${type}`} value={count} />
|
||||
</Card>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
)}
|
||||
{stats?.top_calendars_by_rating && stats.top_calendars_by_rating.length > 0 && (
|
||||
<Card title="Топ календарей по рейтингу" style={{ marginBottom: 16 }}>
|
||||
<Table
|
||||
size="small"
|
||||
pagination={false}
|
||||
rowKey="id"
|
||||
dataSource={stats.top_calendars_by_rating}
|
||||
columns={[
|
||||
{
|
||||
title: 'Название',
|
||||
dataIndex: 'title',
|
||||
key: 'title',
|
||||
render: (title: string, record) => (
|
||||
<Link to={`/calendars/${record.id}`}>{title || record.id}</Link>
|
||||
),
|
||||
},
|
||||
{ title: 'Рейтинг', dataIndex: 'rating_avg', key: 'rating_avg' },
|
||||
{ title: 'Отзывов', dataIndex: 'review_count', key: 'review_count' },
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
<Space style={{ marginBottom: 16 }} wrap>
|
||||
<Input.Search
|
||||
placeholder="Поиск"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { Table, Button, Tag, Space, Modal, Form, Select, Spin, Input, Tooltip, DatePicker, InputNumber, Card, Col, Row, Statistic } from 'antd';
|
||||
import { InfoCircleOutlined, EditOutlined, DeleteOutlined, CalendarOutlined } from '@ant-design/icons';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { useEvents, useUpdateEvent, useDeleteEvent, useEvent, useEventStats } from '../../hooks/useEvents';
|
||||
import { Event, EventListParams } from '../../types/api';
|
||||
import type { ColumnsType, SorterResult } from 'antd/es/table/interface';
|
||||
@@ -228,8 +228,37 @@ const EventListPage: React.FC = () => {
|
||||
</Card>
|
||||
</Col>
|
||||
))}
|
||||
{Object.entries(stats.events_by_type || {}).map(([type, count]) => (
|
||||
<Col xs={12} sm={6} md={4} key={`type-${type}`}>
|
||||
<Card>
|
||||
<Statistic title={`Тип: ${type}`} value={count} />
|
||||
</Card>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
)}
|
||||
{stats?.top_events_by_rating && stats.top_events_by_rating.length > 0 && (
|
||||
<Card title="Топ событий по рейтингу" style={{ marginBottom: 16 }}>
|
||||
<Table
|
||||
size="small"
|
||||
pagination={false}
|
||||
rowKey="id"
|
||||
dataSource={stats.top_events_by_rating}
|
||||
columns={[
|
||||
{
|
||||
title: 'Название',
|
||||
dataIndex: 'title',
|
||||
key: 'title',
|
||||
render: (title: string, record) => (
|
||||
<Link to={`/events/${record.id}`}>{title || record.id}</Link>
|
||||
),
|
||||
},
|
||||
{ title: 'Рейтинг', dataIndex: 'rating_avg', key: 'rating_avg' },
|
||||
{ title: 'Отзывов', dataIndex: 'review_count', key: 'review_count' },
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={data?.data}
|
||||
|
||||
@@ -219,8 +219,37 @@ const ReportListPage: React.FC = () => {
|
||||
</Card>
|
||||
</Col>
|
||||
))}
|
||||
{Object.entries(stats.reports_by_target_type || {}).map(([type, count]) => (
|
||||
<Col xs={12} sm={6} md={4} key={`type-${type}`}>
|
||||
<Card>
|
||||
<Statistic title={`Цель: ${type}`} value={count} />
|
||||
</Card>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
)}
|
||||
{stats?.top_targets_by_reports && stats.top_targets_by_reports.length > 0 && (
|
||||
<Card title="Топ целей по жалобам" style={{ marginBottom: 16 }}>
|
||||
<Table
|
||||
size="small"
|
||||
pagination={false}
|
||||
rowKey={(r) => `${r.target_type}-${r.target_id}`}
|
||||
dataSource={stats.top_targets_by_reports}
|
||||
columns={[
|
||||
{ title: 'Тип', dataIndex: 'target_type', key: 'target_type' },
|
||||
{
|
||||
title: 'ID цели',
|
||||
dataIndex: 'target_id',
|
||||
key: 'target_id',
|
||||
render: (id: string, record) => (
|
||||
<Link to={`/${record.target_type}s/${id}`}>{id}</Link>
|
||||
),
|
||||
},
|
||||
{ title: 'Жалоб', dataIndex: 'report_count', key: 'report_count' },
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={data?.data}
|
||||
|
||||
@@ -253,8 +253,37 @@ const ReviewListPage: React.FC = () => {
|
||||
</Card>
|
||||
</Col>
|
||||
))}
|
||||
{Object.entries(stats.reviews_by_target_type || {}).map(([type, count]) => (
|
||||
<Col xs={12} sm={6} md={4} key={`type-${type}`}>
|
||||
<Card>
|
||||
<Statistic title={`Цель: ${type}`} value={count} />
|
||||
</Card>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
)}
|
||||
{stats?.top_targets_by_reviews && stats.top_targets_by_reviews.length > 0 && (
|
||||
<Card title="Топ целей по отзывам" style={{ marginBottom: 16 }}>
|
||||
<Table
|
||||
size="small"
|
||||
pagination={false}
|
||||
rowKey={(r) => `${r.target_type}-${r.target_id}`}
|
||||
dataSource={stats.top_targets_by_reviews}
|
||||
columns={[
|
||||
{ title: 'Тип', dataIndex: 'target_type', key: 'target_type' },
|
||||
{
|
||||
title: 'ID цели',
|
||||
dataIndex: 'target_id',
|
||||
key: 'target_id',
|
||||
render: (id: string, record) => (
|
||||
<Link to={`/${record.target_type}s/${id}`}>{id}</Link>
|
||||
),
|
||||
},
|
||||
{ title: 'Отзывов', dataIndex: 'review_count', key: 'review_count' },
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
<Space style={{ marginBottom: 16 }}>
|
||||
<Button onClick={() => openBulkStatusModal('hidden')} disabled={selectedRowKeys.length === 0}>
|
||||
Скрыть выбранные
|
||||
|
||||
Reference in New Issue
Block a user