/** * Диалог создания занятия в Material Design 3 */ 'use client'; import React, { useState, useEffect } from 'react'; import { loadComponent } from '@/lib/material-components'; import { createLesson } from '@/api/schedule'; import { getStudents, Student } from '@/api/students'; import { getSubjects, getMentorSubjects, createMentorSubject, Subject, MentorSubject } from '@/api/subjects'; import { getCurrentUser, User } from '@/api/auth'; import { format } from 'date-fns'; interface CreateLessonDialogProps { open: boolean; onClose: () => void; onSuccess: () => void; defaultDate?: Date; } interface LessonFormData { client: string; title: string; subject_id?: number; mentor_subject_id?: number; subject_name?: string; description: string; start_date: string; // YYYY-MM-DD start_time: string; // HH:mm duration: number; price?: number; is_recurring: boolean; } export const CreateLessonDialog: React.FC = ({ open, onClose, onSuccess, defaultDate, }) => { const [componentsLoaded, setComponentsLoaded] = useState(false); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [students, setStudents] = useState([]); const [subjects, setSubjects] = useState([]); const [mentorSubjects, setMentorSubjects] = useState([]); const [currentUser, setCurrentUser] = useState(null); const [selectedSubjectId, setSelectedSubjectId] = useState(null); const [selectedMentorSubjectId, setSelectedMentorSubjectId] = useState(null); const [customSubjectName, setCustomSubjectName] = useState(''); const [formData, setFormData] = useState({ client: '', title: '', description: '', start_date: '', start_time: '', duration: 60, price: undefined, is_recurring: false, }); useEffect(() => { if (open) { loadComponents(); loadData(); } }, [open]); useEffect(() => { if (open && defaultDate) { const start = new Date(defaultDate); const formatDate = (date: Date) => { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; }; const formatTime = (date: Date) => { const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); return `${hours}:${minutes}`; }; setFormData(prev => ({ ...prev, start_date: formatDate(start), start_time: formatTime(start), })); } }, [open, defaultDate]); const loadComponents = async () => { try { await Promise.all([ loadComponent('dialog'), loadComponent('filled-button'), loadComponent('text-button'), loadComponent('outlined-field'), loadComponent('select'), loadComponent('switch'), loadComponent('icon'), ]); setComponentsLoaded(true); } catch (error) { console.error('[CreateLessonDialog] Ошибка загрузки компонентов:', error); } }; const loadData = async () => { try { const [studentsData, subjectsData, mentorSubjectsData, userData] = await Promise.all([ getStudents({ page_size: 100 }), getSubjects(), getMentorSubjects(), getCurrentUser(), ]); const studentsList = Array.isArray(studentsData) ? studentsData : (studentsData.results || []); setStudents(studentsList); setSubjects(Array.isArray(subjectsData) ? subjectsData : []); setMentorSubjects(Array.isArray(mentorSubjectsData) ? mentorSubjectsData : []); setCurrentUser(userData); } catch (error) { console.error('[CreateLessonDialog] Ошибка загрузки данных:', error); setError('Ошибка загрузки данных'); } }; const generateTitle = (student: Student | null, subjectName: string): string => { if (!student || !subjectName || !currentUser) return ''; const mentorName = `${currentUser.last_name} ${currentUser.first_name?.charAt(0) || ''}.`.trim(); const studentName = `${student.user?.last_name || ''} ${student.user?.first_name?.charAt(0) || ''}.`.trim(); return `${mentorName} ${studentName} ${subjectName}`.trim(); }; const getSubjectName = (): string => { if (selectedSubjectId) { const subject = subjects.find(s => s.id === selectedSubjectId); return subject?.name || ''; } if (selectedMentorSubjectId) { const subject = mentorSubjects.find(s => s.id === selectedMentorSubjectId); return subject?.name || ''; } return customSubjectName || ''; }; // Автогенерация названия useEffect(() => { if (formData.client && getSubjectName() && currentUser) { const selectedStudent = students.find(s => String(s.id) === formData.client); if (selectedStudent) { const subjectName = getSubjectName(); const generatedTitle = generateTitle(selectedStudent, subjectName); setFormData(prev => ({ ...prev, title: generatedTitle })); } } }, [formData.client, selectedSubjectId, selectedMentorSubjectId, customSubjectName, students, currentUser, subjects, mentorSubjects]); const handleSubjectChange = async (value: string | number | null, isCustom: boolean, customName?: string) => { if (isCustom && customName) { setSelectedSubjectId(null); setSelectedMentorSubjectId(null); setCustomSubjectName(customName); } else if (value) { const subject = subjects.find(s => s.id === value); const mentorSubject = mentorSubjects.find(s => s.id === value); if (subject) { setSelectedSubjectId(subject.id); setSelectedMentorSubjectId(null); setCustomSubjectName(''); } else if (mentorSubject) { setSelectedSubjectId(null); setSelectedMentorSubjectId(mentorSubject.id); setCustomSubjectName(''); } } else { setSelectedSubjectId(null); setSelectedMentorSubjectId(null); setCustomSubjectName(''); } }; const handleCustomSubjectCreate = async (name: string): Promise => { const newSubject = await createMentorSubject(name); setMentorSubjects(prev => [...prev, newSubject]); setSelectedMentorSubjectId(newSubject.id); setCustomSubjectName(''); }; const handleDateChange = (value: string) => { setFormData(prev => ({ ...prev, start_date: value, })); }; const handleTimeChange = (value: string) => { setFormData(prev => ({ ...prev, start_time: value, })); }; const handleDurationChange = (value: number) => { setFormData(prev => ({ ...prev, duration: value, })); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); setError(null); try { if (!formData.client) { setError('Выберите ученика'); setLoading(false); return; } if (!selectedSubjectId && !selectedMentorSubjectId && !customSubjectName) { setError('Выберите или введите предмет'); setLoading(false); return; } if (!formData.start_date || !formData.start_time) { setError('Укажите дату и время начала'); setLoading(false); return; } if (!formData.price || formData.price <= 0) { setError('Укажите стоимость занятия'); setLoading(false); return; } // Объединяем дату и время в ISO строку const startUtc = new Date(`${formData.start_date}T${formData.start_time}`).toISOString(); const payload: any = { client: formData.client, title: formData.title || generateTitle( students.find(s => String(s.id) === formData.client) || null, getSubjectName() ), description: formData.description, start_time: startUtc, duration: formData.duration, price: formData.price, is_recurring: formData.is_recurring, }; if (selectedSubjectId) { payload.subject_id = selectedSubjectId; } else if (selectedMentorSubjectId) { payload.mentor_subject_id = selectedMentorSubjectId; } else if (customSubjectName) { payload.subject_name = customSubjectName; } await createLesson(payload); // Сброс формы setFormData({ client: '', title: '', description: '', start_date: '', start_time: '', duration: 60, price: undefined, is_recurring: false, }); setSelectedSubjectId(null); setSelectedMentorSubjectId(null); setCustomSubjectName(''); onSuccess(); onClose(); } catch (err: any) { console.error('[CreateLessonDialog] Ошибка создания занятия:', err); if (err.response?.data) { const fieldErrors = Object.entries(err.response.data) .map(([key, value]) => `${key}: ${Array.isArray(value) ? value.join(', ') : value}`) .join('\n'); setError(fieldErrors); } else { setError(err.message || 'Ошибка создания занятия'); } } finally { setLoading(false); } }; const handleClose = () => { if (!loading) { setFormData({ client: '', title: '', description: '', start_date: '', start_time: '', duration: 60, price: undefined, is_recurring: false, }); setSelectedSubjectId(null); setSelectedMentorSubjectId(null); setCustomSubjectName(''); setError(null); onClose(); } }; if (!open || !componentsLoaded) return null; return ( <>
Создать занятие
{ e.preventDefault(); handleSubmit(e); }} style={{ display: 'flex', flexDirection: 'column', gap: '20px', minWidth: '500px', maxWidth: '600px' }}> {error && (
{error}
)} {/* Ученик */}
{/* Предмет */}
{ setCustomSubjectName(e.target.value); if (e.target.value) { handleSubjectChange(null, true, e.target.value); } else { handleSubjectChange(null, false); } }} placeholder="Название предмета" disabled={loading} style={{ border: 'none', outline: 'none', background: 'transparent', width: '100%', fontSize: '16px', color: 'var(--md-sys-color-on-surface)', }} />
{/* Название */}
setFormData(prev => ({ ...prev, title: e.target.value }))} placeholder="Автоматически генерируется" disabled={loading} style={{ border: 'none', outline: 'none', background: 'transparent', width: '100%', fontSize: '16px', color: 'var(--md-sys-color-on-surface)', }} />
{/* Описание */}