diff --git a/lib/function/teacher_student_management_controller.dart b/lib/function/teacher_student_management_controller.dart index 38cea7d..a9e61ce 100644 --- a/lib/function/teacher_student_management_controller.dart +++ b/lib/function/teacher_student_management_controller.dart @@ -38,8 +38,42 @@ class TeacherStudentManagementController extends ChangeNotifier { List _students = []; bool _isLoadingStudents = true; + String _searchQuery = ''; + int? _gradeFilter; // null = 전체 List get students => _students; bool get isLoadingStudents => _isLoadingStudents; + String get searchQuery => _searchQuery; + int? get gradeFilter => _gradeFilter; + + /// πŸ” ν•™λ²ˆ 검색 + ν•™λ…„ ν•„ν„°λ₯Ό μ μš©ν•˜κ³ , ν•™λ…„ μ˜€λ¦„μ°¨μˆœ(1β†’2β†’3, 미배정은 맨 λ’€)으둜 + /// μ •λ ¬ν•œ λͺ©λ‘. ν™”λ©΄μ—λŠ” 이 λͺ©λ‘μ„ κ·Έλ¦°λ‹€. + List get filteredStudents { + final query = _searchQuery.trim(); + final filtered = _students.where((s) { + if (_gradeFilter != null && s['grade'] != _gradeFilter) return false; + if (query.isEmpty) return true; + return s['id'].toString().contains(query); + }).toList(); + filtered.sort((a, b) { + final ga = a['grade'] as int?; + final gb = b['grade'] as int?; + if (ga == null && gb == null) return 0; + if (ga == null) return 1; + if (gb == null) return -1; + return ga.compareTo(gb); + }); + return filtered; + } + + void setSearchQuery(String query) { + _searchQuery = query; + notifyListeners(); + } + + void setGradeFilter(int? grade) { + _gradeFilter = grade; + notifyListeners(); + } Future init() => fetchStudents(); diff --git a/lib/ui/teacher_student_management_page.dart b/lib/ui/teacher_student_management_page.dart index fab2a0d..4f49d60 100644 --- a/lib/ui/teacher_student_management_page.dart +++ b/lib/ui/teacher_student_management_page.dart @@ -358,6 +358,20 @@ class _TeacherStudentManagementPageState } // 🏷️ μ„Ήμ…˜ 제λͺ© (색 인디케이터 λ°” + ν…μŠ€νŠΈ). + Widget _gradeFilterChip(int? grade, String label) { + final bool selected = _controller.gradeFilter == grade; + return ChoiceChip( + label: Text(label), + selected: selected, + onSelected: (_) => _controller.setGradeFilter(grade), + selectedColor: AppPalette.ink, + labelStyle: TextStyle( + color: selected ? Colors.white : AppPalette.ink, + fontWeight: FontWeight.bold, + ), + ); + } + Widget _sectionTitle(String text, {Color color = AppPalette.ink}) { return Row( children: [ @@ -753,6 +767,42 @@ class _TeacherStudentManagementPageState ), ), const SizedBox(height: 12), + Row( + children: [ + Expanded( + child: TextField( + onChanged: _controller.setSearchQuery, + keyboardType: TextInputType.number, + decoration: InputDecoration( + hintText: 'ν•™λ²ˆμœΌλ‘œ 검색', + prefixIcon: const Icon( + Icons.search_rounded, + ), + filled: true, + fillColor: AppPalette.paper, + contentPadding: const EdgeInsets.symmetric( + vertical: 0, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: AppPalette.sage, + ), + ), + ), + ), + ), + const SizedBox(width: 12), + _gradeFilterChip(null, '전체'), + const SizedBox(width: 6), + _gradeFilterChip(1, '1ν•™λ…„'), + const SizedBox(width: 6), + _gradeFilterChip(2, '2ν•™λ…„'), + const SizedBox(width: 6), + _gradeFilterChip(3, '3ν•™λ…„'), + ], + ), + const SizedBox(height: 12), _controller.isLoadingStudents ? const Padding( padding: EdgeInsets.symmetric(vertical: 40), @@ -760,13 +810,19 @@ class _TeacherStudentManagementPageState child: CircularProgressIndicator(), ), ) - : _controller.students.isEmpty - ? const Padding( - padding: EdgeInsets.symmetric(vertical: 24), + : _controller.filteredStudents.isEmpty + ? Padding( + padding: const EdgeInsets.symmetric( + vertical: 24, + ), child: Center( child: Text( - 'κ°€μž…λœ 학생 계정이 μ—†μŠ΅λ‹ˆλ‹€.', - style: TextStyle(color: Colors.grey), + _controller.students.isEmpty + ? 'κ°€μž…λœ 학생 계정이 μ—†μŠ΅λ‹ˆλ‹€.' + : '검색/ν•„ν„° 쑰건에 λ§žλŠ” 학생이 μ—†μŠ΅λ‹ˆλ‹€.', + style: const TextStyle( + color: Colors.grey, + ), ), ), ) @@ -781,10 +837,11 @@ class _TeacherStudentManagementPageState crossAxisSpacing: 12, mainAxisSpacing: 12, ), - itemCount: _controller.students.length, + itemCount: + _controller.filteredStudents.length, itemBuilder: (context, index) => _buildStudentTile( - _controller.students[index], + _controller.filteredStudents[index], ), ), ],