From ccff21987465142291f3b47292cc8dd1c8a21cf5 Mon Sep 17 00:00:00 2001 From: sihoo Date: Mon, 31 Aug 2026 01:07:38 +0900 Subject: [PATCH] =?UTF-8?q?=EC=84=A0=EC=83=9D=EB=8B=98=20=EB=8C=80?= =?UTF-8?q?=EC=8B=9C=EB=B3=B4=EB=93=9C=EC=97=90=20=ED=95=99=EB=85=84=20?= =?UTF-8?q?=ED=95=84=ED=84=B0=20=EC=B9=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 출석자/미출석자 필터처럼 학년 전체/1학년/2학년/3학년 칩을 추가해서 선택한 학년만 볼 수 있게 함. 상태 필터와 조합해서 같이 적용됨. Co-Authored-By: Claude Sonnet 5 --- .../teacher_attendance_controller.dart | 20 ++++-- lib/ui/teacher_attendance_page.dart | 64 ++++++++++++++----- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/lib/function/teacher_attendance_controller.dart b/lib/function/teacher_attendance_controller.dart index 6250aa2..b778604 100644 --- a/lib/function/teacher_attendance_controller.dart +++ b/lib/function/teacher_attendance_controller.dart @@ -26,6 +26,7 @@ class TeacherAttendanceController extends ChangeNotifier { bool _isLoading = true; bool _isRefreshing = false; // 새로고침 버튼 클릭 시 잠깐 도는 표시용 String _filterType = "ALL"; // "ALL", "CHECKED_IN", "ABSENT" + String _gradeFilter = "ALL"; // "ALL", "1", "2", "3" bool _disposed = false; // ---------------------------------------------------------------- @@ -34,6 +35,7 @@ class TeacherAttendanceController extends ChangeNotifier { bool get isLoading => _isLoading; bool get isRefreshing => _isRefreshing; String get filterType => _filterType; + String get gradeFilter => _gradeFilter; String? get attendanceTime => _attendanceTime; String? get globalPermissionUntil => _globalPermissionUntil; @@ -214,6 +216,12 @@ class TeacherAttendanceController extends ChangeNotifier { _safeNotify(); } + /// 🏫 학년 필터. "ALL"이면 전체, "1"/"2"/"3"이면 그 학년만 보이게 한다. + void setGradeFilter(String grade) { + _gradeFilter = grade; + _safeNotify(); + } + // ---------------------------------------------------------------- // 파생 로직 (출석 상태 계산) // ---------------------------------------------------------------- @@ -301,13 +309,17 @@ class TeacherAttendanceController extends ChangeNotifier { } List> get filteredStudents { - final all = combinedStudentStatus; + var result = combinedStudentStatus; if (_filterType == "CHECKED_IN") { - return all.where((s) => s['isAttendanceComplete'] == true).toList(); + result = result.where((s) => s['isAttendanceComplete'] == true).toList(); } else if (_filterType == "ABSENT") { - return all.where((s) => s['isAttendanceComplete'] == false).toList(); + result = result.where((s) => s['isAttendanceComplete'] == false).toList(); } - return all; + if (_gradeFilter != "ALL") { + final int? grade = int.tryParse(_gradeFilter); + result = result.where((s) => s['grade'] == grade).toList(); + } + return result; } /// 🏫 [학년별 카테고리] filteredStudents를 학년(1~3학년) 순서로 묶는다. diff --git a/lib/ui/teacher_attendance_page.dart b/lib/ui/teacher_attendance_page.dart index 125eb10..d15ce44 100644 --- a/lib/ui/teacher_attendance_page.dart +++ b/lib/ui/teacher_attendance_page.dart @@ -706,24 +706,56 @@ class _TeacherAttendancePageState extends State { Widget _buildFilterChips() { return Padding( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), - child: Row( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - FilterChip( - label: const Text("전체"), - selected: _controller.filterType == "ALL", - onSelected: (_) => _controller.setFilter("ALL"), + Wrap( + spacing: 8, + runSpacing: 8, + children: [ + FilterChip( + label: const Text("전체"), + selected: _controller.filterType == "ALL", + onSelected: (_) => _controller.setFilter("ALL"), + ), + FilterChip( + label: const Text("🟢 출석자"), + selected: _controller.filterType == "CHECKED_IN", + onSelected: (_) => _controller.setFilter("CHECKED_IN"), + ), + FilterChip( + label: const Text("🔴 미출석자"), + selected: _controller.filterType == "ABSENT", + onSelected: (_) => _controller.setFilter("ABSENT"), + ), + ], ), - const SizedBox(width: 8), - FilterChip( - label: const Text("🟢 출석자"), - selected: _controller.filterType == "CHECKED_IN", - onSelected: (_) => _controller.setFilter("CHECKED_IN"), - ), - const SizedBox(width: 8), - FilterChip( - label: const Text("🔴 미출석자"), - selected: _controller.filterType == "ABSENT", - onSelected: (_) => _controller.setFilter("ABSENT"), + const SizedBox(height: 8), + Wrap( + spacing: 8, + runSpacing: 8, + children: [ + ChoiceChip( + label: const Text("학년 전체"), + selected: _controller.gradeFilter == "ALL", + onSelected: (_) => _controller.setGradeFilter("ALL"), + ), + ChoiceChip( + label: const Text("1학년"), + selected: _controller.gradeFilter == "1", + onSelected: (_) => _controller.setGradeFilter("1"), + ), + ChoiceChip( + label: const Text("2학년"), + selected: _controller.gradeFilter == "2", + onSelected: (_) => _controller.setGradeFilter("2"), + ), + ChoiceChip( + label: const Text("3학년"), + selected: _controller.gradeFilter == "3", + onSelected: (_) => _controller.setGradeFilter("3"), + ), + ], ), ], ),