From d9ab6adb51dcffc4ad92949522db86bf637c0eea Mon Sep 17 00:00:00 2001 From: sihoo Date: Tue, 1 Sep 2026 08:20:47 +0900 Subject: [PATCH] =?UTF-8?q?=ED=95=99=EC=83=9D=20=EA=B3=84=EC=A0=95=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20=ED=83=80=EC=9D=BC=20=ED=81=AC=EA=B8=B0/?= =?UTF-8?q?=ED=8F=B0=ED=8A=B8=EB=A5=BC=20=EC=8B=A4=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EC=B6=9C=EC=84=9D=20=ED=99=95=EC=9D=B8=20=EB=AA=A9=EB=A1=9D?= =?UTF-8?q?=EA=B3=BC=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 계정 추가/엑셀 등록 칸과 학생 목록 타일 모두 "실시간 출석 확인" 목록의 타일 규격(220x148, 이름15/상태11.5/칩11 폰트)에 맞춰 동일한 비율로 재조정. Co-Authored-By: Claude Sonnet 5 --- lib/ui/teacher_student_management_page.dart | 72 ++++++++++++--------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/lib/ui/teacher_student_management_page.dart b/lib/ui/teacher_student_management_page.dart index 23ef52a..3dd83ca 100644 --- a/lib/ui/teacher_student_management_page.dart +++ b/lib/ui/teacher_student_management_page.dart @@ -6,6 +6,10 @@ import 'package:flutter/material.dart'; import '../function/excel_file_picker.dart'; import '../function/teacher_student_management_controller.dart'; +// 📐 "실시간 출석 확인" 목록(teacher_attendance_page.dart)의 타일 규격과 동일하게 맞춘다. +const double kAttendanceTileWidth = 220; +const double kAttendanceTileHeight = 148; + // ----------------------------------------------------------------------------- // 👥 [서브 화면 2] 학생 계정 관리 란 (추가 양식 폼 + 강제 삭제 다이얼로그 완전 내장) // ----------------------------------------------------------------------------- @@ -545,28 +549,37 @@ class _TeacherStudentManagementPageState final bool needsReset = student['device'] == '초기화 필요'; return Container( - padding: const EdgeInsets.all(8), + padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: Colors.white, - borderRadius: BorderRadius.circular(14), + borderRadius: BorderRadius.circular(20), boxShadow: [ - BoxShadow(color: Colors.black.withValues(alpha: 0.04), blurRadius: 8), + BoxShadow( + color: Colors.black.withValues(alpha: 0.03), + blurRadius: 12, + offset: const Offset(0, 4), + ), ], ), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - CircleAvatar( - radius: 20, - backgroundColor: needsReset ? Colors.red[50] : Colors.blue[50], + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: (needsReset ? Colors.red : Colors.blue).withValues( + alpha: 0.1, + ), + shape: BoxShape.circle, + ), child: Icon( needsReset ? Icons.lock_reset : Icons.person, - size: 20, + size: 18, color: needsReset ? Colors.red : Colors.blue, ), ), - const SizedBox(height: 6), + const SizedBox(height: 8), Text( '$studentName ($studentId)', textAlign: TextAlign.center, @@ -574,13 +587,13 @@ class _TeacherStudentManagementPageState overflow: TextOverflow.ellipsis, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 15), ), - const SizedBox(height: 2), + const SizedBox(height: 4), Text( needsReset ? '초기화 대기중' : '정상 등록', textAlign: TextAlign.center, style: TextStyle( - fontSize: 12, - color: needsReset ? Colors.red : Colors.grey, + fontSize: 11.5, + color: needsReset ? Colors.red[700] : Colors.grey[600], fontWeight: needsReset ? FontWeight.bold : FontWeight.normal, ), ), @@ -597,7 +610,7 @@ class _TeacherStudentManagementPageState labelPadding: const EdgeInsets.symmetric(horizontal: 6), label: Text( grade != null ? '$grade학년' : '미배정', - style: const TextStyle(fontSize: 12), + style: const TextStyle(fontSize: 11), ), onPressed: () => _showGradeMenu( chipContext, @@ -611,22 +624,22 @@ class _TeacherStudentManagementPageState icon: const Icon( Icons.lock_reset, color: Colors.purple, - size: 20, + size: 18, ), tooltip: '기기 리셋', padding: EdgeInsets.zero, - constraints: const BoxConstraints(minWidth: 30, minHeight: 30), + constraints: const BoxConstraints(minWidth: 28, minHeight: 28), onPressed: () => _confirmResetDevice(studentId, studentName), ), IconButton( icon: const Icon( Icons.delete_forever_rounded, color: Colors.redAccent, - size: 20, + size: 18, ), tooltip: '계정 영구 삭제', padding: EdgeInsets.zero, - constraints: const BoxConstraints(minWidth: 30, minHeight: 30), + constraints: const BoxConstraints(minWidth: 28, minHeight: 28), onPressed: () => _confirmDeleteStudent(studentId, studentName), ), ], @@ -656,14 +669,10 @@ class _TeacherStudentManagementPageState padding: const EdgeInsets.all(24.0), child: LayoutBuilder( builder: (context, constraints) { - // 🖥️ 웹(넓은 화면)은 계정 추가/엑셀 등록을 정사각형 2칸으로 나란히, 폰은 기존처럼 세로로 쌓는다. + // 🖥️ 웹(넓은 화면)은 계정 추가/엑셀 등록을 나란히, 폰은 기존처럼 세로로 쌓는다. + // 📐 크기/폰트 비율은 "실시간 출석 확인" 목록의 타일(220x148)과 동일하게 맞춘다. final bool isWide = constraints.maxWidth >= 800; final double listWidth = constraints.maxWidth; - // 📐 학생 목록 타일과 동일한 크기를 계정 추가/엑셀 등록 칸에도 사용한다. - final double tileSize = - ((listWidth - (isWide ? 7 : 3) * 10) / (isWide ? 8 : 4)) * - 1.5; - final double formSquareSize = tileSize; final Widget addBoxColumn = Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -671,8 +680,8 @@ class _TeacherStudentManagementPageState _sectionTitle('신규 학생 계정 추가'), const SizedBox(height: 16), SizedBox( - width: isWide ? formSquareSize : double.infinity, - height: isWide ? formSquareSize : null, + width: isWide ? kAttendanceTileWidth : double.infinity, + height: isWide ? kAttendanceTileHeight : null, child: _buildAddAccountBox(), ), ], @@ -684,8 +693,8 @@ class _TeacherStudentManagementPageState _sectionTitle('엑셀로 한번에 추가 (신입생 등)'), const SizedBox(height: 16), SizedBox( - width: isWide ? formSquareSize : double.infinity, - height: isWide ? formSquareSize : 240, + width: isWide ? kAttendanceTileWidth : double.infinity, + height: isWide ? kAttendanceTileHeight : 240, child: _buildExcelBox(), ), ], @@ -762,11 +771,12 @@ class _TeacherStudentManagementPageState shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: - SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: tileSize, - crossAxisSpacing: 10, - mainAxisSpacing: 10, - childAspectRatio: 1, + const SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: + kAttendanceTileWidth, + mainAxisExtent: kAttendanceTileHeight, + crossAxisSpacing: 12, + mainAxisSpacing: 12, ), itemCount: _controller.students.length, itemBuilder: (context, index) =>