/** * Кастомный селектор студентов с поиском и аватарами */ 'use client'; import React, { useState, useRef, useEffect } from 'react'; import { Student } from '@/api/students'; interface StudentSelectProps { students: Student[]; value: string; onChange: (value: string) => void; disabled?: boolean; required?: boolean; } export const StudentSelect: React.FC = ({ students, value, onChange, disabled = false, required = false, }) => { const [isOpen, setIsOpen] = useState(false); const [searchQuery, setSearchQuery] = useState(''); const containerRef = useRef(null); const searchInputRef = useRef(null); // Получаем выбранного студента const selectedStudent = students.find(s => String(s.id) === value); // Фильтруем студентов по поисковому запросу const filteredStudents = students.filter(student => { const fullName = `${student.user?.first_name || ''} ${student.user?.last_name || ''}`.toLowerCase(); const email = student.user?.email?.toLowerCase() || ''; const query = searchQuery.toLowerCase(); return fullName.includes(query) || email.includes(query); }); // Закрываем dropdown при клике вне компонента useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (containerRef.current && !containerRef.current.contains(event.target as Node)) { setIsOpen(false); setSearchQuery(''); } }; if (isOpen) { document.addEventListener('mousedown', handleClickOutside); // Фокусируем поле поиска при открытии setTimeout(() => searchInputRef.current?.focus(), 0); } return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, [isOpen]); const handleSelect = (studentId: string) => { onChange(studentId); setIsOpen(false); setSearchQuery(''); }; const getStudentDisplayName = (student: Student) => { const name = `${student.user?.first_name || ''} ${student.user?.last_name || ''}`.trim(); return name || student.user?.email || 'Без имени'; }; const getAvatarUrl = (student: Student) => { return student.user?.avatar || null; }; const getInitials = (student: Student) => { const firstName = student.user?.first_name || ''; const lastName = student.user?.last_name || ''; if (firstName && lastName) { return `${firstName.charAt(0)}${lastName.charAt(0)}`.toUpperCase(); } if (firstName) return firstName.charAt(0).toUpperCase(); if (lastName) return lastName.charAt(0).toUpperCase(); return student.user?.email?.charAt(0).toUpperCase() || '?'; }; return (
{/* Основная кнопка выбора */} {/* Dropdown меню */} {isOpen && (
{/* Поле поиска */}
setSearchQuery(e.target.value)} placeholder="Поиск студента..." style={{ width: '100%', padding: '8px 12px 8px 40px', fontSize: '14px', color: 'var(--md-sys-color-on-surface)', background: 'var(--md-sys-color-surface-variant)', border: 'none', borderRadius: '8px', fontFamily: 'inherit', outline: 'none', }} /> {searchQuery && ( )}
{/* Список студентов */}
{filteredStudents.length === 0 ? (
{searchQuery ? 'Студенты не найдены' : 'Нет доступных студентов'}
) : ( filteredStudents.map((student) => ( )) )}
)}
); };