'use client';
import { useState, useEffect, useCallback } from 'react';
import Box from '@mui/material/Box';
import Card from '@mui/material/Card';
import Stack from '@mui/material/Stack';
import Divider from '@mui/material/Divider';
import Avatar from '@mui/material/Avatar';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';
import CircularProgress from '@mui/material/CircularProgress';
import LinearProgress from '@mui/material/LinearProgress';
import { useTheme } from '@mui/material/styles';
import { paths } from 'src/routes/paths';
import { useRouter } from 'src/routes/hooks';
import { fDateTime } from 'src/utils/format-time';
import { getClientDashboard, getChildDashboard } from 'src/utils/dashboard-api';
import { createLiveKitRoom } from 'src/utils/livekit-api';
import { DashboardContent } from 'src/layouts/dashboard';
import { useAuthContext } from 'src/auth/hooks';
import { CONFIG } from 'src/config-global';
import { varAlpha } from 'src/theme/styles';
import { Iconify } from 'src/components/iconify';
import { CourseWidgetSummary } from '../../course/course-widget-summary';
import { CourseProgress } from '../../course/course-progress';
import { CourseMyAccount } from '../../course/course-my-account';
// ----------------------------------------------------------------------
const formatDateTime = (str) => {
if (!str) return '—';
try {
const date = new Date(str);
if (isNaN(date.getTime())) return '—';
const today = new Date();
const tomorrow = new Date(today);
tomorrow.setDate(today.getDate() + 1);
const time = date.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' });
if (date.toDateString() === today.toDateString()) return `Сегодня, ${time}`;
if (date.toDateString() === tomorrow.toDateString()) return `Завтра, ${time}`;
return date.toLocaleDateString('ru-RU', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' });
} catch {
return '—';
}
};
// ----------------------------------------------------------------------
function LessonItem({ lesson }) {
const router = useRouter();
const [joining, setJoining] = useState(false);
const mentorName = lesson.mentor
? `${lesson.mentor.first_name || ''} ${lesson.mentor.last_name || ''}`.trim() || 'Ментор'
: 'Ментор';
const now = new Date();
const startTime = new Date(lesson.start_time);
const diffMin = (startTime - now) / 60000;
const canJoin = diffMin < 11 && diffMin > -90;
const handleJoin = async () => {
try {
setJoining(true);
const res = await createLiveKitRoom(lesson.id);
const token = res?.access_token || res?.token;
router.push(`${paths.dashboard.prejoin}?token=${encodeURIComponent(token)}&lesson_id=${lesson.id}`);
} catch (err) {
console.error('Join error:', err);
setJoining(false);
}
};
return (
{mentorName[0]?.toUpperCase()}
{lesson.title || lesson.subject || 'Занятие'}
{mentorName}
{canJoin ? (
}
sx={{ flexShrink: 0, minWidth: 110 }}
>
{joining ? '...' : 'Подключиться'}
) : (
{formatDateTime(lesson.start_time)}
)}
);
}
// ----------------------------------------------------------------------
function HomeworkItem({ homework }) {
const statusColor = {
pending: 'warning',
submitted: 'info',
reviewed: 'success',
completed: 'success',
}[homework.status] || 'default';
return (
{homework.title}
{homework.subject || 'Предмет не указан'}
{homework.grade != null && (
{homework.grade}/5
)}
);
}
// ----------------------------------------------------------------------
export function OverviewClientView({ childId, childName }) {
const theme = useTheme();
const { user } = useAuthContext();
const [stats, setStats] = useState(null);
const [loading, setLoading] = useState(true);
const fetchData = useCallback(
async (signal) => {
try {
setLoading(true);
const data = childId
? await getChildDashboard(childId, { signal })
: await getClientDashboard({ signal });
if (!signal?.aborted) setStats(data);
} catch (err) {
if (err?.name === 'AbortError' || err?.name === 'CanceledError') return;
console.error('Client dashboard error:', err);
} finally {
if (!signal?.aborted) setLoading(false);
}
},
[childId]
);
useEffect(() => {
const controller = new AbortController();
fetchData(controller.signal);
return () => controller.abort();
}, [fetchData]);
// Периодическое обновление каждые 60 сек — кнопка «Подключиться» появляется автоматически
useEffect(() => {
const id = setInterval(() => {
const controller = new AbortController();
fetchData(controller.signal);
return () => controller.abort();
}, 60_000);
return () => clearInterval(id);
}, [fetchData]);
const displayName = childName || user?.first_name || 'Студент';
const completionPct =
stats?.total_lessons > 0
? Math.round((stats.completed_lessons / stats.total_lessons) * 100)
: 0;
if (loading && !stats) {
return (
);
}
return (
{/* LEFT */}
{/* Stat widgets */}
{/* Progress bar */}
Прогресс занятий
{completionPct}%
Пройдено: {stats?.completed_lessons || 0}
Всего: {stats?.total_lessons || 0}
{/* Upcoming lessons + homework */}
{/* Upcoming lessons */}
Ближайшие занятия
{loading ? (
) : stats?.upcoming_lessons?.length > 0 ? (
{stats.upcoming_lessons.slice(0, 4).map((lesson) => (
))}
) : (
Нет запланированных занятий
)}
{/* Homework */}
Домашние задания
{loading ? (
) : stats?.recent_homework?.length > 0 ? (
{stats.recent_homework.slice(0, 4).map((hw) => (
))}
) : (
Нет домашних заданий
)}
{/* RIGHT sidebar */}
{/* Next lesson highlight */}
{stats?.next_lesson && (
Следующее занятие
{stats.next_lesson.title || 'Занятие'}
{formatDateTime(stats.next_lesson.start_time)}
{stats.next_lesson.mentor && (
{(stats.next_lesson.mentor.first_name || 'М')[0]}
{`${stats.next_lesson.mentor.first_name || ''} ${stats.next_lesson.mentor.last_name || ''}`.trim()}
)}
)}
);
}