/** * Секция «Ближайшие занятия» для дашборда ментора (iOS 26). */ 'use client'; import React, { useMemo, useState } from 'react'; import { MentorDashboardResponse } from '@/api/dashboard'; import { Panel, SectionHeader, FlipCard } from '../ui'; import { LoadingSpinner } from '@/components/common/LoadingSpinner'; import { getLesson, type Lesson } from '@/api/schedule'; export interface UpcomingLessonsSectionProps { data: MentorDashboardResponse | null; loading: boolean; } const formatDateTime = (dateTimeStr: string | null): string => { if (!dateTimeStr) return '—'; try { const date = new Date(dateTimeStr); if (isNaN(date.getTime())) return '—'; const today = new Date(); const tomorrow = new Date(today); tomorrow.setDate(tomorrow.getDate() + 1); const isToday = date.toDateString() === today.toDateString(); const isTomorrow = date.toDateString() === tomorrow.toDateString(); const timeStr = date.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit', }); if (isToday) { return `Сегодня, ${timeStr}`; } else if (isTomorrow) { return `Завтра, ${timeStr}`; } else { return date.toLocaleDateString('ru-RU', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit', }); } } catch { return '—'; } }; export const UpcomingLessonsSection: React.FC = ({ data, loading, }) => { const lessons = data?.upcoming_lessons?.slice(0, 4) || []; const [flipped, setFlipped] = useState(false); const [selectedLessonId, setSelectedLessonId] = useState(null); const [details, setDetails] = useState(null); const [loadingDetails, setLoadingDetails] = useState(false); const selectedPreview = useMemo( () => lessons.find((l) => l.id === selectedLessonId) || null, [lessons, selectedLessonId], ); const formatFullDateTime = (dateTimeStr: string | null): string => { if (!dateTimeStr) return '—'; try { const date = new Date(dateTimeStr); if (isNaN(date.getTime())) return '—'; return date.toLocaleString('ru-RU', { day: 'numeric', month: 'long', year: 'numeric', hour: '2-digit', minute: '2-digit', }); } catch { return '—'; } }; const openLessonDetails = async (lessonId: string) => { setSelectedLessonId(lessonId); setFlipped(true); setLoadingDetails(true); setDetails(null); try { const full = await getLesson(lessonId); setDetails(full); } catch (error) { console.error('Ошибка загрузки занятия:', error); } finally { setLoadingDetails(false); } }; return ( { // если пользователь кликнул по "пустому месту" в карточке — не хотим случайно закрывать, // но оставим стандартное поведение: переворот по клику на сам контейнер FlipCard. setFlipped(v); }} front={ {loading && !data ? ( ) : lessons.length === 0 ? (
Нет запланированных занятий
) : (
e.stopPropagation()} > {lessons.map((lesson) => { const client = lesson.client as any; const fullName = client?.first_name || client?.last_name ? `${client.first_name ?? ''} ${client.last_name ?? ''}`.trim() : client?.name || 'Студент'; return ( ); })}
)}
} back={ { e.stopPropagation(); setFlipped(false); }} className="ios26-back-button" > Назад } />
e.stopPropagation()}> {loadingDetails ? (
Загрузка...
) : details ? (

{details.title || selectedPreview?.title || 'Занятие'}

{details.subject && (

Предмет: {details.subject}

)}

Начало: {formatFullDateTime(details.start_time)}

Окончание: {formatFullDateTime(details.end_time)}

{details.description && (

{details.description}

)} {details.mentor_notes && (

Заметки: {details.mentor_notes}

)}
) : (
Не удалось загрузить детали
)}
} /> ); };