uchill/front_material/components/calendar/calendar.tsx

121 lines
3.8 KiB
TypeScript

/**
* Блок «Календарь занятий» — обёртка над LessonsCalendar.
* Используется в Dashboard и других страницах.
*/
'use client';
import React from 'react';
import { format, startOfDay } from 'date-fns';
import { LessonsCalendar } from '@/components/dashboard/LessonsCalendar';
import { LoadingSpinner } from '@/components/common/LoadingSpinner';
export interface CalendarLesson {
id: number | string;
title?: string;
start_time: string;
end_time: string;
status?: string;
client?: number;
client_name?: string;
mentor_name?: string;
subject?: string;
}
export interface CalendarProps {
/** Занятия для отображения в календаре */
lessons: CalendarLesson[];
/** Идёт загрузка занятий */
lessonsLoading?: boolean;
/** Выбранная дата (подсветка в календаре) */
selectedDate: Date;
/** Клик по ячейке дня или по слоту */
onSelectSlot?: (date: Date) => void;
/** Клик по событию (занятию) */
onSelectEvent?: (lesson: { id: string }) => void;
/** Смена видимого месяца (start/end месяца) */
onMonthChange?: (start: Date, end: Date) => void;
/** Ментор — показывает ученика; студент — показывает предмет и ментора */
isMentor?: boolean;
/** Часовой пояс пользователя (например, 'UTC+8') */
userTimezone?: string;
}
export const Calendar: React.FC<CalendarProps> = ({
lessons,
lessonsLoading = false,
selectedDate,
onSelectSlot,
onSelectEvent,
onMonthChange,
isMentor = true,
userTimezone,
}) => {
const mappedLessons = React.useMemo(
() =>
lessons.map((lesson) => {
if (isMentor && lesson.client_name) {
return {
id: String(lesson.id),
title: lesson.title || 'Занятие',
start_time: lesson.start_time,
end_time: lesson.end_time,
status: (lesson.status || 'scheduled') as 'scheduled' | 'in_progress' | 'completed' | 'cancelled',
client: {
id: String(lesson.client ?? ''),
name: lesson.client_name,
first_name: lesson.client_name.split(' ')[0] || lesson.client_name,
last_name: lesson.client_name.split(' ').slice(1).join(' ') || '',
},
};
}
const subject = lesson.subject || 'Занятие';
const mentorName = lesson.mentor_name || '';
const displayTitle = mentorName ? `${subject}${mentorName}` : subject;
return {
id: String(lesson.id),
title: displayTitle,
start_time: lesson.start_time,
end_time: lesson.end_time,
status: (lesson.status || 'scheduled') as 'scheduled' | 'in_progress' | 'completed' | 'cancelled',
client: undefined,
};
}),
[lessons, isMentor]
);
return (
<div
className="ios-glass-panel"
style={{
borderRadius: '20px',
padding: '24px',
height: '100%',
minHeight: 0,
display: 'flex',
flexDirection: 'column',
}}
>
{lessonsLoading ? (
<LoadingSpinner size="medium" />
) : (
<LessonsCalendar
lessons={mappedLessons}
selectedDate={selectedDate}
userTimezone={userTimezone}
onSelectSlot={(date) => {
try {
const d = startOfDay(date);
if (!Number.isNaN(d.getTime())) onSelectSlot?.(d);
} catch {
/* игнор невалидной даты */
}
}}
onSelectEvent={onSelectEvent}
onMonthChange={onMonthChange}
/>
)}
</div>
);
};