97 lines
3.1 KiB
TypeScript
97 lines
3.1 KiB
TypeScript
/**
|
||
* Секция карточек метрик для дашборда ментора (iOS 26).
|
||
*/
|
||
|
||
'use client';
|
||
|
||
import React from 'react';
|
||
import { MentorDashboardResponse } from '@/api/dashboard';
|
||
import { StatsGrid, type StatsGridItem } from '../ui';
|
||
|
||
const IconUsers = (
|
||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
|
||
<circle cx="9" cy="7" r="4" />
|
||
<path d="M23 21v-2a4 4 0 0 0-3-3.87" />
|
||
<path d="M16 3.13a4 4 0 0 1 0 7.75" />
|
||
</svg>
|
||
);
|
||
|
||
const IconCalendar = (
|
||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||
<rect x="3" y="4" width="18" height="18" rx="2" ry="2" />
|
||
<line x1="16" y1="2" x2="16" y2="6" />
|
||
<line x1="8" y1="2" x2="8" y2="6" />
|
||
<line x1="3" y1="10" x2="21" y2="10" />
|
||
</svg>
|
||
);
|
||
|
||
const IconRevenue = (
|
||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||
<line x1="12" y1="1" x2="12" y2="23" />
|
||
<path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6" />
|
||
</svg>
|
||
);
|
||
|
||
const IconClipboard = (
|
||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||
<polyline points="14 2 14 8 20 8" />
|
||
<line x1="16" y1="13" x2="8" y2="13" />
|
||
<line x1="16" y1="17" x2="8" y2="17" />
|
||
<polyline points="10 9 9 9 8 9" />
|
||
</svg>
|
||
);
|
||
|
||
export interface StatsSectionProps {
|
||
stats: MentorDashboardResponse | null;
|
||
loading: boolean;
|
||
}
|
||
|
||
function buildGridItems(stats: MentorDashboardResponse | null, loading: boolean): StatsGridItem[] {
|
||
const s = stats?.summary;
|
||
return [
|
||
{
|
||
title: 'Всего учеников',
|
||
value: loading ? '—' : (s?.total_clients ?? 0),
|
||
icon: IconUsers,
|
||
loading,
|
||
},
|
||
{
|
||
title: 'Завершённых занятий (месяц / всего)',
|
||
value: loading
|
||
? '—'
|
||
: `${s?.lessons_this_month ?? 0}/${s?.completed_lessons ?? 0}`,
|
||
icon: IconCalendar,
|
||
loading,
|
||
},
|
||
{
|
||
title: 'Доход (месяц / всё время)',
|
||
value: loading
|
||
? '—'
|
||
: `${s?.revenue_this_month != null ? `${Math.round(s.revenue_this_month).toLocaleString('ru-RU')} ₽` : '0 ₽'} / ${
|
||
s?.total_revenue != null ? `${Math.round(s.total_revenue).toLocaleString('ru-RU')} ₽` : '0 ₽'
|
||
}`,
|
||
icon: IconRevenue,
|
||
loading,
|
||
},
|
||
{
|
||
title: 'Заданий на проверке / всего',
|
||
value: loading
|
||
? '—'
|
||
: `${s?.pending_submissions ?? 0}/${s?.total_homeworks ?? 0}`,
|
||
icon: IconClipboard,
|
||
loading,
|
||
},
|
||
];
|
||
}
|
||
|
||
export const StatsSection: React.FC<StatsSectionProps> = ({ stats, loading }) => {
|
||
const gridItems = buildGridItems(stats, loading);
|
||
return (
|
||
<div style={{ marginBottom: 'var(--ios26-spacing-lg)' }}>
|
||
<StatsGrid items={gridItems} />
|
||
</div>
|
||
);
|
||
};
|