From 9089b9032ee1139f7e09925424aca6d818a2fbeb Mon Sep 17 00:00:00 2001 From: sihoo Date: Fri, 4 Sep 2026 22:31:03 +0900 Subject: [PATCH] =?UTF-8?q?UI=20=EB=AC=B8=EA=B5=AC=20=EC=9D=B4=EB=AA=A8?= =?UTF-8?q?=ED=8B=B0=EC=BD=98=20=EC=A0=9C=EA=B1=B0=20+=20=EA=B3=84?= =?UTF-8?q?=EC=A0=95=20=EA=B0=95=EC=A0=9C=20=EC=82=AD=EC=A0=9C=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EC=BD=98=20=EA=B2=80=EC=A0=95=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 화면 타이틀, 스낵바/다이얼로그 메시지, 백그라운드 알림 문구 등 사용자에게 노출되는 텍스트에서 이모티콘을 전부 제거 (코드 주석은 대상 아님). 아이콘 위젯은 그대로 유지. main_dashboard.dart의 "계정 강제 삭제" 타일 아이콘 색상도 빨간색 대신 다른 타일과 동일한 검정(AppPalette.ink)으로 통일. Co-Authored-By: Claude Sonnet 5 --- lib/function/admin_controller.dart | 6 +-- lib/function/device_checkout_controller.dart | 6 +-- .../device_checkout_ledger_controller.dart | 6 +-- lib/function/login_controller.dart | 23 ++++---- .../nfc_pocket_checkin_controller.dart | 54 ++++++++++--------- lib/function/nfc_tag_writer_controller.dart | 18 +++---- .../student_dashboard_controller.dart | 6 +-- .../teacher_attendance_controller.dart | 10 ++-- lib/function/teacher_register_controller.dart | 6 +-- ...teacher_student_management_controller.dart | 24 ++++----- lib/pocket_watch_service.dart | 16 +++--- lib/screens/change_password_screen.dart | 8 +-- lib/ui/admin_dashboard.dart | 4 +- lib/ui/device_checkout_ledger_page.dart | 21 ++++---- lib/ui/device_checkout_request_screen.dart | 4 +- lib/ui/login_screen.dart | 24 ++++----- lib/ui/main_dashboard.dart | 18 +++---- lib/ui/nfc_poccket_checkin_screen.dart | 17 +++--- lib/ui/nfc_tag_writer_screen.dart | 2 +- lib/ui/teacher_attendance_page.dart | 20 +++---- lib/ui/teacher_register_screen.dart | 6 +-- lib/ui/teacher_student_management_page.dart | 18 +++---- 22 files changed, 157 insertions(+), 160 deletions(-) diff --git a/lib/function/admin_controller.dart b/lib/function/admin_controller.dart index d3b8fe3..2d83114 100644 --- a/lib/function/admin_controller.dart +++ b/lib/function/admin_controller.dart @@ -17,12 +17,12 @@ class AdminController extends ChangeNotifier { try { final response = await http.get(url); if (response.statusCode == 200) { - return '💥 DB가 깔끔하게 초기화되었습니다! (출석 번호 1번부터 시작)'; + return 'DB가 깔끔하게 초기화되었습니다! (출석 번호 1번부터 시작)'; } else { - return '❌ 초기화 실패: 서버 권한 오류 (${response.statusCode})'; + return '초기화 실패: 서버 권한 오류 (${response.statusCode})'; } } catch (e) { - return '❌ 네트워크 에러: 서버와 연결할 수 없습니다.'; + return '네트워크 에러: 서버와 연결할 수 없습니다.'; } finally { _isLoading = false; notifyListeners(); diff --git a/lib/function/device_checkout_controller.dart b/lib/function/device_checkout_controller.dart index 19de90b..5c7859f 100644 --- a/lib/function/device_checkout_controller.dart +++ b/lib/function/device_checkout_controller.dart @@ -34,12 +34,12 @@ class DeviceCheckoutController extends ChangeNotifier { ); final result = jsonDecode(utf8.decode(response.bodyBytes)); if (response.statusCode == 200 && result['status'] == 'success') { - return (true, '✅ ${result['message'] ?? '요청이 접수되었습니다.'}'); + return (true, '${result['message'] ?? '요청이 접수되었습니다.'}'); } else { - return (false, '❌ ${result['message'] ?? '요청 실패'}'); + return (false, '${result['message'] ?? '요청 실패'}'); } } catch (e) { - return (false, '🚨 네트워크 에러: $e'); + return (false, '네트워크 에러: $e'); } finally { _isSubmitting = false; notifyListeners(); diff --git a/lib/function/device_checkout_ledger_controller.dart b/lib/function/device_checkout_ledger_controller.dart index d66237a..46b11d7 100644 --- a/lib/function/device_checkout_ledger_controller.dart +++ b/lib/function/device_checkout_ledger_controller.dart @@ -87,11 +87,11 @@ class DeviceCheckoutLedgerController extends ChangeNotifier { final result = jsonDecode(utf8.decode(response.bodyBytes)); if (response.statusCode == 200 && result['status'] == 'success') { await fetchAll(); - return (true, '✅ ${result['message'] ?? '처리되었습니다.'}'); + return (true, '${result['message'] ?? '처리되었습니다.'}'); } - return (false, '❌ ${result['message'] ?? '처리 실패'}'); + return (false, '${result['message'] ?? '처리 실패'}'); } catch (e) { - return (false, '🚨 네트워크 에러: $e'); + return (false, '네트워크 에러: $e'); } finally { _isWorking = false; _safeNotify(); diff --git a/lib/function/login_controller.dart b/lib/function/login_controller.dart index 5dab246..9e95b97 100644 --- a/lib/function/login_controller.dart +++ b/lib/function/login_controller.dart @@ -17,13 +17,11 @@ class LoginResult { final bool isDeviceMatched; final String? errorMessage; - const LoginResult.masterSuccess({ - required this.studentId, - required this.name, - }) : outcome = LoginOutcome.masterSuccess, - role = null, - isDeviceMatched = true, - errorMessage = null; + const LoginResult.masterSuccess({required this.studentId, required this.name}) + : outcome = LoginOutcome.masterSuccess, + role = null, + isDeviceMatched = true, + errorMessage = null; const LoginResult.needsPasswordChange({ required this.studentId, @@ -55,16 +53,13 @@ class LoginController extends ChangeNotifier { Future login(String id, String password) async { if (id.isEmpty || password.isEmpty) { - return const LoginResult.error('⚠️ 학번과 비밀번호를 모두 입력해 주세요.'); + return const LoginResult.error('학번과 비밀번호를 모두 입력해 주세요.'); } // 🔥 [개발자 마스터 계정] if (id == "2061") { if (password == "happy9642!") { - return const LoginResult.masterSuccess( - studentId: "2061", - name: "훗춧가룻", - ); + return const LoginResult.masterSuccess(studentId: "2061", name: "훗춧가룻"); } else { return const LoginResult.error('개발자 계정의 마스터 비밀번호가 올바르지 않습니다.'); } @@ -200,9 +195,9 @@ class LoginController extends ChangeNotifier { final resData = jsonDecode(utf8.decode(response.bodyBytes)); if (response.statusCode == 200 && resData['status'] == 'success') { - return (true, '✅ 비밀번호가 변경되었습니다!'); + return (true, '비밀번호가 변경되었습니다!'); } else { - return (false, '❌ 실패: ${resData['message']}'); + return (false, '실패: ${resData['message']}'); } } catch (e) { return (false, '서버 에러 발생: $e'); diff --git a/lib/function/nfc_pocket_checkin_controller.dart b/lib/function/nfc_pocket_checkin_controller.dart index 06407c0..9ff036a 100644 --- a/lib/function/nfc_pocket_checkin_controller.dart +++ b/lib/function/nfc_pocket_checkin_controller.dart @@ -17,8 +17,12 @@ import '../config.dart' show baseUrl; // 🛡️ iOS 근접센서 감시용 네이티브 채널 (ios/Runner/ProximityMonitorPlugin.swift 참고). // 조도 센서 API가 없는 iOS에서, 통화 중 화면이 꺼지는 것과 같은 원리인 // 근접센서로 "주머니 안/밖" 상태 변화를 감지해 대체한다. -const MethodChannel _proximityMethodChannel = MethodChannel('proximity_monitor'); -const EventChannel _proximityEventChannel = EventChannel('proximity_monitor/events'); +const MethodChannel _proximityMethodChannel = MethodChannel( + 'proximity_monitor', +); +const EventChannel _proximityEventChannel = EventChannel( + 'proximity_monitor/events', +); enum WatchMessageLevel { info, success, warning, error } @@ -78,22 +82,22 @@ class NfcPocketCheckinController extends ChangeNotifier { // 화면이 열려있는 동안은 실시간으로 위반 알림을 받아 팝업을 띄운다. // 무단 반출이 한 번 감지되면 "신뢰된 감시 세션"은 끝난 것으로 보고, // 다음 태깅은 체크아웃이 아니라 새 출석(재출석)으로 처리되도록 감시 상태를 해제한다. - _violationSub = FlutterBackgroundService().on('violation_detected').listen(( - event, - ) { - _isWatching = false; - notifyListeners(); - onViolationDetected(event?['pocketNumber']?.toString()); - }); + _violationSub = FlutterBackgroundService() + .on('violation_detected') + .listen((event) { + _isWatching = false; + notifyListeners(); + onViolationDetected(event?['pocketNumber']?.toString()); + }); // 🏫 하교 처리 등으로 반출이 허용된 상태에서 폰을 꺼내면, 위반이 아니라 정상 회수로 처리된다. _checkedOutSub = FlutterBackgroundService().on('checked_out').listen(( event, ) { _isWatching = false; _activePocketNumber = null; - _statusMessage = "✅ 폰을 회수했습니다. 수고하셨습니다!"; + _statusMessage = "폰을 회수했습니다. 수고하셨습니다!"; notifyListeners(); - onMessage("✅ 폰이 정상적으로 회수되었습니다.", WatchMessageLevel.success); + onMessage("폰이 정상적으로 회수되었습니다.", WatchMessageLevel.success); }); } } @@ -117,7 +121,7 @@ class NfcPocketCheckinController extends ChangeNotifier { void _startNfcSession() async { bool isAvailable = await NfcManager.instance.isAvailable(); if (!isAvailable) { - _statusMessage = "❌ 이 스마트폰은 NFC 기능이 꺼져있거나 지원되지 않습니다."; + _statusMessage = "이 스마트폰은 NFC 기능이 꺼져있거나 지원되지 않습니다."; notifyListeners(); return; } @@ -134,7 +138,7 @@ class NfcPocketCheckinController extends ChangeNotifier { } _isProcessing = true; - _statusMessage = "⏳ 태그 인식 완료! 서버에 출석 전송 중..."; + _statusMessage = "태그 인식 완료! 서버에 출석 전송 중..."; notifyListeners(); try { @@ -163,7 +167,7 @@ class NfcPocketCheckinController extends ChangeNotifier { tagUid: _getTagUid(tag), ); } catch (e) { - onMessage("❌ 태그 읽기 실패: $e", WatchMessageLevel.error); + onMessage("태그 읽기 실패: $e", WatchMessageLevel.error); } finally { // 3초 후 연타 방지 해제 (쿨다운) await Future.delayed(const Duration(seconds: 3)); @@ -216,16 +220,16 @@ class NfcPocketCheckinController extends ChangeNotifier { onMessage("ℹ️ 이 기기는 백그라운드 감시를 지원하지 않습니다.", WatchMessageLevel.info); } } else { - onMessage("⚠️ 출석 실패: ${result['message']}", WatchMessageLevel.warning); + onMessage("출석 실패: ${result['message']}", WatchMessageLevel.warning); } } else { onMessage( - "🚨 서버 에러 (코드: ${response.statusCode})", + "서버 에러 (코드: ${response.statusCode})", WatchMessageLevel.error, ); } } catch (e) { - onMessage("❌ 서버 연결 실패: $e", WatchMessageLevel.error); + onMessage("서버 연결 실패: $e", WatchMessageLevel.error); } } @@ -255,7 +259,7 @@ class NfcPocketCheckinController extends ChangeNotifier { _isWatching = true; _activePocketNumber = pocketNumber; - _statusMessage = "🛡️ 백그라운드에서 감시 중입니다. 화면을 꺼도 계속 감시돼요."; + _statusMessage = "백그라운드에서 감시 중입니다. 화면을 꺼도 계속 감시돼요."; notifyListeners(); } @@ -268,9 +272,9 @@ class NfcPocketCheckinController extends ChangeNotifier { } _isWatching = false; _activePocketNumber = null; - _statusMessage = "✅ 폰을 회수했습니다. 감시가 종료되었습니다."; + _statusMessage = "폰을 회수했습니다. 감시가 종료되었습니다."; notifyListeners(); - onMessage("✅ 감시가 종료되었습니다. 수고하셨습니다!", WatchMessageLevel.success); + onMessage("감시가 종료되었습니다. 수고하셨습니다!", WatchMessageLevel.success); } // ----------------------------------------------------------------------- @@ -291,13 +295,13 @@ class NfcPocketCheckinController extends ChangeNotifier { _activePocketNumber = pocketNumber; _isWatching = true; - _statusMessage = "📥 주머니에 넣는 중..."; + _statusMessage = "주머니에 넣는 중..."; notifyListeners(); try { await _proximityMethodChannel.invokeMethod('start'); } catch (e) { - onMessage("❌ 근접센서 감시 시작 실패: $e", WatchMessageLevel.error); + onMessage("근접센서 감시 시작 실패: $e", WatchMessageLevel.error); _isWatching = false; _isIosProximityWatch = false; notifyListeners(); @@ -307,7 +311,7 @@ class NfcPocketCheckinController extends ChangeNotifier { // 학생이 폰을 주머니에 넣을 시간을 준 뒤, 그 시점 상태를 기준값으로 삼는다. await Future.delayed(const Duration(seconds: 4)); - _statusMessage = "🛡️ 감시 중입니다. 화면을 잠그지 말고 주머니에 넣어주세요."; + _statusMessage = "감시 중입니다. 화면을 잠그지 말고 주머니에 넣어주세요."; notifyListeners(); _proximitySub = _proximityEventChannel.receiveBroadcastStream().listen(( @@ -359,9 +363,9 @@ class NfcPocketCheckinController extends ChangeNotifier { if (isPermitted) { _activePocketNumber = null; - _statusMessage = "✅ 폰을 회수했습니다. 수고하셨습니다!"; + _statusMessage = "폰을 회수했습니다. 수고하셨습니다!"; notifyListeners(); - onMessage("✅ 폰이 정상적으로 회수되었습니다.", WatchMessageLevel.success); + onMessage("폰이 정상적으로 회수되었습니다.", WatchMessageLevel.success); return; } diff --git a/lib/function/nfc_tag_writer_controller.dart b/lib/function/nfc_tag_writer_controller.dart index bef4605..106ab85 100644 --- a/lib/function/nfc_tag_writer_controller.dart +++ b/lib/function/nfc_tag_writer_controller.dart @@ -37,19 +37,19 @@ class NfcTagWriterController extends ChangeNotifier { Future startWriteSession(String number) async { if (number.isEmpty) { - onMessage("⚠️ 주머니 번호를 입력해주세요.", true); + onMessage("주머니 번호를 입력해주세요.", true); return; } final String pocketLabel = "POCKET_$number"; bool isAvailable = await NfcManager.instance.isAvailable(); if (!isAvailable) { - onMessage("❌ NFC가 꺼져있거나 지원되지 않습니다.", true); + onMessage("NFC가 꺼져있거나 지원되지 않습니다.", true); return; } _isWriting = true; - _statusMessage = "📡 [$pocketLabel] 쓸 준비 완료! 스티커에 폰 뒷면을 대주세요."; + _statusMessage = "[$pocketLabel] 쓸 준비 완료! 스티커에 폰 뒷면을 대주세요."; notifyListeners(); NfcManager.instance.startSession( @@ -58,11 +58,11 @@ class NfcTagWriterController extends ChangeNotifier { try { final ndef = Ndef.from(tag); if (ndef == null) { - onMessage("❌ 이 태그는 NDEF 쓰기를 지원하지 않는 종류입니다.", true); + onMessage("이 태그는 NDEF 쓰기를 지원하지 않는 종류입니다.", true); return; } if (!ndef.isWritable) { - onMessage("❌ 이 태그는 쓰기 잠금(read-only) 상태입니다.", true); + onMessage("이 태그는 쓰기 잠금(read-only) 상태입니다.", true); return; } @@ -78,8 +78,8 @@ class NfcTagWriterController extends ChangeNotifier { onMessage( tagUid != null - ? "✅ [$pocketLabel] 쓰기 + UID 등록 성공!" - : "⚠️ [$pocketLabel] 쓰기는 성공했지만 UID를 못 읽어 등록은 안 됐습니다.", + ? "[$pocketLabel] 쓰기 + UID 등록 성공!" + : "[$pocketLabel] 쓰기는 성공했지만 UID를 못 읽어 등록은 안 됐습니다.", tagUid == null, ); // 다음 스티커를 연달아 쓰기 편하도록 번호를 자동으로 1 올려준다. @@ -88,7 +88,7 @@ class NfcTagWriterController extends ChangeNotifier { _statusMessage = "다음 번호를 확인하고 '쓰기 시작'을 다시 눌러주세요."; notifyListeners(); } catch (e) { - onMessage("❌ 쓰기 실패: $e", true); + onMessage("쓰기 실패: $e", true); } finally { await NfcManager.instance.stopSession(); _isWriting = false; @@ -117,7 +117,7 @@ class NfcTagWriterController extends ChangeNotifier { body: jsonEncode({"tagUid": tagUid, "pocketNumber": pocketLabel}), ); } catch (e) { - onMessage("❌ 서버에 UID 등록 실패: $e", true); + onMessage("서버에 UID 등록 실패: $e", true); } } diff --git a/lib/function/student_dashboard_controller.dart b/lib/function/student_dashboard_controller.dart index 7971bce..04eb5e3 100644 --- a/lib/function/student_dashboard_controller.dart +++ b/lib/function/student_dashboard_controller.dart @@ -18,13 +18,13 @@ class StudentDashboardController extends ChangeNotifier { final response = await http.delete(url); if (response.statusCode == 200) { final responseData = jsonDecode(response.body); - return (true, '✅ ${responseData['message']}'); + return (true, '${responseData['message']}'); } else { final errorData = jsonDecode(response.body); - return (false, '❌ 삭제 실패: ${errorData['detail'] ?? '알 수 없는 오류'}'); + return (false, '삭제 실패: ${errorData['detail'] ?? '알 수 없는 오류'}'); } } catch (e) { - return (false, '❌ 서버와 연결할 수 없습니다. (네트워크 에러)'); + return (false, '서버와 연결할 수 없습니다. (네트워크 에러)'); } finally { _isLoading = false; notifyListeners(); diff --git a/lib/function/teacher_attendance_controller.dart b/lib/function/teacher_attendance_controller.dart index b778604..b4609c3 100644 --- a/lib/function/teacher_attendance_controller.dart +++ b/lib/function/teacher_attendance_controller.dart @@ -145,7 +145,7 @@ class TeacherAttendanceController extends ChangeNotifier { await fetchAll(); return result['message'] ?? '하교 처리되었습니다.'; } catch (e) { - return '❌ 하교 처리 실패: $e'; + return '하교 처리 실패: $e'; } } @@ -161,7 +161,7 @@ class TeacherAttendanceController extends ChangeNotifier { await fetchAll(); return result['message'] ?? '처리되었습니다.'; } catch (e) { - return '❌ 반출 허용 실패: $e'; + return '반출 허용 실패: $e'; } } @@ -177,7 +177,7 @@ class TeacherAttendanceController extends ChangeNotifier { await fetchAll(); return result['message'] ?? '처리되었습니다.'; } catch (e) { - return '❌ 설정 실패: $e'; + return '설정 실패: $e'; } } @@ -193,7 +193,7 @@ class TeacherAttendanceController extends ChangeNotifier { await fetchAll(); return result['message'] ?? '처리되었습니다.'; } catch (e) { - return '❌ 출석시간 설정 실패: $e'; + return '출석시간 설정 실패: $e'; } } @@ -207,7 +207,7 @@ class TeacherAttendanceController extends ChangeNotifier { await fetchAll(); return result['message'] ?? '처리되었습니다.'; } catch (e) { - return '❌ 초기화 실패: $e'; + return '초기화 실패: $e'; } } diff --git a/lib/function/teacher_register_controller.dart b/lib/function/teacher_register_controller.dart index d8be488..8accf01 100644 --- a/lib/function/teacher_register_controller.dart +++ b/lib/function/teacher_register_controller.dart @@ -36,13 +36,13 @@ class TeacherRegisterController extends ChangeNotifier { final res = jsonDecode(response.body); if (response.statusCode == 200 && res['status'] == 'success') { - return (true, '✅ ${res['message']}'); + return (true, '${res['message']}'); } else { String errorMsg = res['detail'] ?? res['message'] ?? '회원가입에 실패했습니다.'; - return (false, '❌ $errorMsg'); + return (false, errorMsg); } } catch (e) { - return (false, '❌ 서버와 통신에 실패했습니다.'); + return (false, '서버와 통신에 실패했습니다.'); } finally { _isLoading = false; notifyListeners(); diff --git a/lib/function/teacher_student_management_controller.dart b/lib/function/teacher_student_management_controller.dart index 988af49..deac7e9 100644 --- a/lib/function/teacher_student_management_controller.dart +++ b/lib/function/teacher_student_management_controller.dart @@ -76,11 +76,11 @@ class TeacherStudentManagementController extends ChangeNotifier { ); if (response.statusCode == 200) { await fetchStudents(); - return (true, '✅ $studentName 학생 기기 초기화 완료! (비밀번호도 1234로 초기화됨)'); + return (true, '$studentName 학생 기기 초기화 완료! (비밀번호도 1234로 초기화됨)'); } - return (false, '❌ 초기화 통신 실패'); + return (false, '초기화 통신 실패'); } catch (e) { - return (false, '❌ 초기화 통신 실패: $e'); + return (false, '초기화 통신 실패: $e'); } finally { _isWorking = false; notifyListeners(); @@ -211,12 +211,12 @@ class TeacherStudentManagementController extends ChangeNotifier { final result = jsonDecode(utf8.decode(response.bodyBytes)); if (response.statusCode == 200 && result['status'] == 'success') { - return (true, '✅ ${result['message'] ?? '계정이 생성되었습니다.'}'); + return (true, '${result['message'] ?? '계정이 생성되었습니다.'}'); } else { - return (false, '❌ 생성 실패: ${result['message'] ?? '오류 발생'}'); + return (false, '생성 실패: ${result['message'] ?? '오류 발생'}'); } } catch (e) { - return (false, '🚨 네트워크 에러: $e'); + return (false, '네트워크 에러: $e'); } } @@ -238,12 +238,12 @@ class TeacherStudentManagementController extends ChangeNotifier { if (response.statusCode == 200 && result['status'] == 'success') { await fetchStudents(); - return (true, '✅ ${result['message'] ?? '학년이 지정되었습니다.'}'); + return (true, '${result['message'] ?? '학년이 지정되었습니다.'}'); } else { - return (false, '❌ 지정 실패: ${result['message'] ?? '오류 발생'}'); + return (false, '지정 실패: ${result['message'] ?? '오류 발생'}'); } } catch (e) { - return (false, '🚨 네트워크 에러: $e'); + return (false, '네트워크 에러: $e'); } finally { _isWorking = false; notifyListeners(); @@ -266,12 +266,12 @@ class TeacherStudentManagementController extends ChangeNotifier { if (response.statusCode == 200) { final resData = jsonDecode(utf8.decode(response.bodyBytes)); await fetchStudents(); - return (true, '✅ ${resData['message']}'); + return (true, '${resData['message']}'); } else { - return (false, '❌ 삭제 실패하였습니다.'); + return (false, '삭제 실패하였습니다.'); } } catch (e) { - return (false, '❌ 서버 에러 발생'); + return (false, '서버 에러 발생'); } finally { _isWorking = false; notifyListeners(); diff --git a/lib/pocket_watch_service.dart b/lib/pocket_watch_service.dart index 679b074..713014e 100644 --- a/lib/pocket_watch_service.dart +++ b/lib/pocket_watch_service.dart @@ -44,7 +44,7 @@ Future initializePocketWatchService() async { autoStartOnBoot: false, isForegroundMode: true, notificationChannelId: pocketWatchNotificationChannelId, - initialNotificationTitle: '🛡️ 주머니 감시 대기 중', + initialNotificationTitle: '주머니 감시 대기 중', initialNotificationContent: '출석 태깅을 기다리는 중입니다.', foregroundServiceNotificationId: pocketWatchNotificationId, foregroundServiceTypes: [AndroidForegroundType.specialUse], @@ -88,7 +88,7 @@ void onPocketWatchServiceStart(ServiceInstance service) { Future reportViolation() async { // 진동 3연타로 강하게 경고 (백그라운드 서비스에서는 HapticFeedback이 아닌 vibration 패키지를 써야 동작함) Vibration.vibrate(pattern: [0, 400, 150, 400, 150, 400]); - updateNotification("🚨 무단 반출 감지!", "[$pocketNumber] 주머니에서 폰이 감지되지 않습니다."); + updateNotification("무단 반출 감지!", "[$pocketNumber] 주머니에서 폰이 감지되지 않습니다."); service.invoke('violation_detected', { "pocketNumber": pocketNumber, "timestamp": DateTime.now().toIso8601String(), @@ -128,7 +128,7 @@ void onPocketWatchServiceStart(ServiceInstance service) { } if (isPermitted) { - updateNotification("✅ 폰 회수 완료", "[$pocketNumber] 주머니에서 정상적으로 회수되었습니다."); + updateNotification("폰 회수 완료", "[$pocketNumber] 주머니에서 정상적으로 회수되었습니다."); service.invoke('checked_out', {"pocketNumber": pocketNumber}); service.stopSelf(); } else { @@ -145,7 +145,7 @@ void onPocketWatchServiceStart(ServiceInstance service) { baselineLux = calibrationSamples.reduce((a, b) => a + b) ~/ calibrationSamples.length; - updateNotification("🛡️ 감시 중", "[$pocketNumber] 폰이 주머니 안에 있는지 감시 중"); + updateNotification("감시 중", "[$pocketNumber] 폰이 주머니 안에 있는지 감시 중"); } return; } @@ -163,22 +163,22 @@ void onPocketWatchServiceStart(ServiceInstance service) { baselineLux = null; violated = false; - updateNotification("📥 주머니에 넣는 중...", "잠시 후 감시가 시작됩니다."); + updateNotification("주머니에 넣는 중...", "잠시 후 감시가 시작됩니다."); await Future.delayed(_placePhoneDelay); - updateNotification("🔎 밝기 측정 중...", "주머니 속 밝기를 기준값으로 설정하는 중입니다."); + updateNotification("밝기 측정 중...", "주머니 속 밝기를 기준값으로 설정하는 중입니다."); try { await Light().requestAuthorization(); lightSub = Light().lightSensorStream.listen( onLightReading, onError: (Object error) { - updateNotification("❌ 조도 센서 오류", "$error"); + updateNotification("조도 센서 오류", "$error"); }, ); } catch (e) { - updateNotification("❌ 조도 센서 시작 실패", "$e"); + updateNotification("조도 센서 시작 실패", "$e"); } } diff --git a/lib/screens/change_password_screen.dart b/lib/screens/change_password_screen.dart index ce9360d..1528d70 100644 --- a/lib/screens/change_password_screen.dart +++ b/lib/screens/change_password_screen.dart @@ -22,7 +22,7 @@ class _ChangePasswordScreenState extends State { String newPw = _pwController.text.trim(); if (newPw.isEmpty || newPw == "1234") { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('⚠️ 초기 비밀번호와 다른 안전한 비밀번호를 입력하세요.')), + const SnackBar(content: Text('초기 비밀번호와 다른 안전한 비밀번호를 입력하세요.')), ); return; } @@ -38,7 +38,7 @@ class _ChangePasswordScreenState extends State { final res = jsonDecode(response.body); if (response.statusCode == 200 && res['status'] == 'success') { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('🔒 비밀번호 변경 완료! 다시 로그인해 주세요.')), + const SnackBar(content: Text('비밀번호 변경 완료! 다시 로그인해 주세요.')), ); // 비밀번호를 바꿨으니 다시 로그인 화면으로 강제 이동 Navigator.pushReplacement( @@ -49,7 +49,7 @@ class _ChangePasswordScreenState extends State { } catch (e) { ScaffoldMessenger.of( context, - ).showSnackBar(const SnackBar(content: Text('❌ 통신 실패'))); + ).showSnackBar(const SnackBar(content: Text('통신 실패'))); } finally { setState(() => _isLoading = false); } @@ -65,7 +65,7 @@ class _ChangePasswordScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( - '🔒 보안을 위해\n비밀번호를 변경해 주세요', + '보안을 위해\n비밀번호를 변경해 주세요', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, diff --git a/lib/ui/admin_dashboard.dart b/lib/ui/admin_dashboard.dart index 0c99bcf..2eba821 100644 --- a/lib/ui/admin_dashboard.dart +++ b/lib/ui/admin_dashboard.dart @@ -38,7 +38,7 @@ class _AdminDashboardState extends State { builder: (BuildContext dialogContext) { return AlertDialog( title: const Text( - '⚠️ DB 초기화 경고', + 'DB 초기화 경고', style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold), ), content: const Text( @@ -74,7 +74,7 @@ class _AdminDashboardState extends State { return Scaffold( backgroundColor: AppPalette.mist, appBar: AppBar( - title: const Text('🛠️ 관리자 시스템'), + title: const Text('관리자 시스템'), backgroundColor: AppPalette.ink, foregroundColor: AppPalette.paper, actions: [ diff --git a/lib/ui/device_checkout_ledger_page.dart b/lib/ui/device_checkout_ledger_page.dart index 387d61f..0c4a65e 100644 --- a/lib/ui/device_checkout_ledger_page.dart +++ b/lib/ui/device_checkout_ledger_page.dart @@ -63,13 +63,13 @@ class _DeviceCheckoutLedgerPageState extends State { ({Color color, String label}) _statusInfo(String status) { switch (status) { case 'PENDING': - return (color: Colors.orange, label: '⏳ 대기중'); + return (color: Colors.orange, label: '대기중'); case 'APPROVED': - return (color: Colors.blue, label: '✅ 승인됨'); + return (color: Colors.blue, label: '승인됨'); case 'RETURNED': - return (color: Colors.grey, label: '↩️ 반납완료'); + return (color: Colors.grey, label: '반납완료'); case 'REJECTED': - return (color: Colors.red, label: '🚫 거절됨'); + return (color: Colors.red, label: '거절됨'); default: return (color: Colors.grey, label: status); } @@ -95,7 +95,7 @@ class _DeviceCheckoutLedgerPageState extends State { backgroundColor: AppPalette.mist, appBar: AppBar( title: const Text( - '📱 스마트기기 반출 대장', + '스마트기기 반출 대장', style: TextStyle(fontWeight: FontWeight.bold), ), backgroundColor: AppPalette.ink, @@ -127,7 +127,7 @@ class _DeviceCheckoutLedgerPageState extends State { border: Border.all(color: Colors.orange[400]!), ), child: Text( - '⏳ 승인 대기 중인 요청이 $pendingCount건 있습니다.', + '승인 대기 중인 요청이 $pendingCount건 있습니다.', style: TextStyle( color: Colors.orange[900], fontWeight: FontWeight.bold, @@ -207,7 +207,10 @@ class _DeviceCheckoutLedgerPageState extends State { ), const SizedBox(height: 6), Text( - '⏰ ${_timeRange(r['requestedStart'], r['requestedEnd'])}', + _timeRange( + r['requestedStart'], + r['requestedEnd'], + ), style: TextStyle( color: Colors.grey[700], fontSize: 13, @@ -215,7 +218,7 @@ class _DeviceCheckoutLedgerPageState extends State { ), const SizedBox(height: 2), Text( - '📝 ${r['purpose']}', + r['purpose'], style: TextStyle( color: Colors.grey[700], fontSize: 13, @@ -226,7 +229,7 @@ class _DeviceCheckoutLedgerPageState extends State { null) ...[ const SizedBox(height: 2), Text( - '👤 ${r['approvedByTeacherName']} 선생님이 허용했습니다', + '${r['approvedByTeacherName']} 선생님이 허용했습니다', style: TextStyle( color: Colors.blue[700], fontSize: 12, diff --git a/lib/ui/device_checkout_request_screen.dart b/lib/ui/device_checkout_request_screen.dart index fd32257..734be69 100644 --- a/lib/ui/device_checkout_request_screen.dart +++ b/lib/ui/device_checkout_request_screen.dart @@ -58,7 +58,7 @@ class _DeviceCheckoutRequestScreenState final purpose = _purposeController.text.trim(); if (_startTime == null || _endTime == null || purpose.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('⚠️ 시작/종료 시각과 사용 목적을 모두 입력해주세요.')), + const SnackBar(content: Text('시작/종료 시각과 사용 목적을 모두 입력해주세요.')), ); return; } @@ -86,7 +86,7 @@ class _DeviceCheckoutRequestScreenState backgroundColor: AppPalette.mist, appBar: AppBar( title: const Text( - '📱 스마트기기 반출 신청', + '스마트기기 반출 신청', style: TextStyle(fontWeight: FontWeight.bold), ), backgroundColor: AppPalette.ink, diff --git a/lib/ui/login_screen.dart b/lib/ui/login_screen.dart index d2cf4fc..bc39ae7 100644 --- a/lib/ui/login_screen.dart +++ b/lib/ui/login_screen.dart @@ -43,9 +43,9 @@ class _LoginScreenState extends State { _showErrorDialog(result.errorMessage!); break; case LoginOutcome.masterSuccess: - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('👑 개발자 최고 권한으로 로그인되었습니다.')), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(const SnackBar(content: Text('개발자 최고 권한으로 로그인되었습니다.'))); Navigator.pushReplacement( context, MaterialPageRoute( @@ -69,7 +69,7 @@ class _LoginScreenState extends State { case LoginOutcome.success: ScaffoldMessenger.of( context, - ).showSnackBar(SnackBar(content: Text('✅ ${result.name}님 환영합니다!'))); + ).showSnackBar(SnackBar(content: Text('${result.name}님 환영합니다!'))); _navigateBasedOnRole( result.role!, result.studentId!, @@ -99,7 +99,7 @@ class _LoginScreenState extends State { builder: (context, setDialogState) { return AlertDialog( title: const Text( - '🔒 초기 비밀번호 변경', + '초기 비밀번호 변경', style: TextStyle(fontWeight: FontWeight.bold), ), content: Column( @@ -136,9 +136,7 @@ class _LoginScreenState extends State { String newPassword = newPwController.text.trim(); if (newPassword.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('⚠️ 새 비밀번호를 입력해 주세요.'), - ), + const SnackBar(content: Text('새 비밀번호를 입력해 주세요.')), ); return; } @@ -204,7 +202,7 @@ class _LoginScreenState extends State { context: context, builder: (ctx) => AlertDialog( title: const Text( - '⚠️ 인증 실패', + '인증 실패', style: TextStyle(fontWeight: FontWeight.bold), ), content: Text(message), @@ -229,7 +227,7 @@ class _LoginScreenState extends State { barrierDismissible: false, builder: (BuildContext dialogContext) { return AlertDialog( - title: Text('🔒 $title 권한 인증 (기존 방식)'), + title: Text('$title 권한 인증 (기존 방식)'), content: TextField( controller: passwordController, obscureText: true, @@ -244,7 +242,7 @@ class _LoginScreenState extends State { ); } else { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('❌ 비밀번호가 올바르지 않습니다.')), + const SnackBar(content: Text('비밀번호가 올바르지 않습니다.')), ); } }, @@ -268,7 +266,7 @@ class _LoginScreenState extends State { ); } else { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('❌ 비밀번호가 올바르지 않습니다.')), + const SnackBar(content: Text('비밀번호가 올바르지 않습니다.')), ); } }, @@ -365,7 +363,7 @@ class _LoginScreenState extends State { ), ), child: const Text( - '👨‍🏫 선생님이신가요? 교사 회원가입 하기', + '선생님이신가요? 교사 회원가입 하기', style: TextStyle( color: AppPalette.ink, fontWeight: FontWeight.bold, diff --git a/lib/ui/main_dashboard.dart b/lib/ui/main_dashboard.dart index cba8cec..621b0cd 100644 --- a/lib/ui/main_dashboard.dart +++ b/lib/ui/main_dashboard.dart @@ -165,28 +165,28 @@ class _MainDashboardState extends State { ({String title, String subtitle, Color color, IconData icon}) _theme() { if (_isDeveloper) { return ( - title: '👑 MASTER CONTROL', + title: 'MASTER CONTROL', subtitle: '최고 관리 권한 활성화됨', color: AppPalette.ink, icon: Icons.admin_panel_settings_rounded, ); } else if (widget.role == 'admin') { return ( - title: '🛠️ ADMIN CONTROL', + title: 'ADMIN CONTROL', subtitle: '시스템 관리자 권한 활성화됨', color: AppPalette.ink, icon: Icons.admin_panel_settings_rounded, ); } else if (widget.role == 'teacher') { return ( - title: '👨‍🏫 TEACHER PORTAL', + title: 'TEACHER PORTAL', subtitle: '교직원 번호: $_displayId | 교사 권한 활성화됨', color: AppPalette.ink, icon: Icons.admin_panel_settings_rounded, ); } return ( - title: '🎓 STUDENT PORTAL', + title: 'STUDENT PORTAL', subtitle: '학번: $_displayId | 인증 완료', color: AppPalette.ink, icon: Icons.school_rounded, @@ -334,7 +334,7 @@ class _MainDashboardState extends State { title: 'NFC 태그', subtitle: widget.isDeviceMatched ? '출석 및 폰 수거 완료' - : '⚠️ 본인 인증 기기 전용', + : '본인 인증 기기 전용', color: widget.isDeviceMatched ? AppPalette.ink : AppPalette.sage, @@ -346,7 +346,7 @@ class _MainDashboardState extends State { ).showSnackBar( const SnackBar( content: Text( - '🚨 대리 출석 방지를 위해 등록된 본인 스마트폰에서만 출석 가능합니다.', + '대리 출석 방지를 위해 등록된 본인 스마트폰에서만 출석 가능합니다.', ), ), ); @@ -363,9 +363,7 @@ class _MainDashboardState extends State { onTap: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( - content: Text( - '🍔 실시간 학교 상황 페이지로 이동합니다.', - ), + content: Text('실시간 학교 상황 페이지로 이동합니다.'), ), ); }, @@ -455,7 +453,7 @@ class _MainDashboardState extends State { icon: Icons.delete_sweep_rounded, title: '계정 강제 삭제', subtitle: '학생 및 교사 DB 삭제', - color: Colors.red[600]!, + color: AppPalette.ink, onTap: () => _showDeleteUserDialog(context), ), if (_isAdmin) diff --git a/lib/ui/nfc_poccket_checkin_screen.dart b/lib/ui/nfc_poccket_checkin_screen.dart index 645e039..d541f1c 100644 --- a/lib/ui/nfc_poccket_checkin_screen.dart +++ b/lib/ui/nfc_poccket_checkin_screen.dart @@ -72,7 +72,7 @@ class _NfcPocketCheckInScreenState extends State { builder: (context) => AlertDialog( backgroundColor: Colors.red[50], title: const Text( - "🚨 무단 반출 감지", + "무단 반출 감지", style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold), ), content: Text( @@ -98,7 +98,7 @@ class _NfcPocketCheckInScreenState extends State { context: context, barrierDismissible: false, builder: (context) => AlertDialog( - title: const Text("🛡️ 감시 모드 켜기 전에"), + title: const Text("감시 모드 켜기 전에"), content: const Text( "iOS는 화면을 잠그면 감시가 끊겨요. 아래 순서로 '가이드 접근'을 먼저 켜주세요.\n\n" "1. 사이드(또는 홈) 버튼 3번 빠르게 누르기\n" @@ -127,9 +127,9 @@ class _NfcPocketCheckInScreenState extends State { showDialog( context: context, builder: (context) => AlertDialog( - title: const Text("🎉 자습실 출석 완료!"), + title: const Text("자습실 출석 완료!"), content: Text( - "${widget.studentName} 학생!\n[$pocketNumber] 주머니 출석이 확인되었습니다.\n\n폰을 주머니에 쏙 넣고 자습에 집중해 주세요! ✏️", + "${widget.studentName} 학생!\n[$pocketNumber] 주머니 출석이 확인되었습니다.\n\n폰을 주머니에 쏙 넣고 자습에 집중해 주세요!", ), actions: [ TextButton( @@ -161,7 +161,10 @@ class _NfcPocketCheckInScreenState extends State { appBar: AppBar( title: const Text( "자습실 NFC 출석체크", - style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), ), backgroundColor: const Color.fromARGB(255, 48, 48, 52), ), @@ -258,8 +261,8 @@ class _NfcPocketCheckInScreenState extends State { const SizedBox(height: 8), Text( !kIsWeb && Platform.isIOS - ? "🔒 가이드 접근을 켠 채로 화면만 잠기도록 두세요.\n(임의로 앱을 나가면 감시가 끊깁니다)\n감시를 끝내려면 가이드 접근을 먼저 끄고 다시 태깅하세요." - : "📴 화면을 꺼도 감시는 계속됩니다.\n알림바에서 상태를 확인할 수 있어요.\n(폰을 꺼내 다시 태깅하면 반출 처리됩니다)", + ? "가이드 접근을 켠 채로 화면만 잠기도록 두세요.\n(임의로 앱을 나가면 감시가 끊깁니다)\n감시를 끝내려면 가이드 접근을 먼저 끄고 다시 태깅하세요." + : "화면을 꺼도 감시는 계속됩니다.\n알림바에서 상태를 확인할 수 있어요.\n(폰을 꺼내 다시 태깅하면 반출 처리됩니다)", textAlign: TextAlign.center, style: const TextStyle(color: Colors.white38, fontSize: 13), ), diff --git a/lib/ui/nfc_tag_writer_screen.dart b/lib/ui/nfc_tag_writer_screen.dart index 6b8b5ee..2146ae6 100644 --- a/lib/ui/nfc_tag_writer_screen.dart +++ b/lib/ui/nfc_tag_writer_screen.dart @@ -50,7 +50,7 @@ class _NfcTagWriterScreenState extends State { final bool isWriting = _controller.isWriting; return Scaffold( appBar: AppBar( - title: const Text("🏷️ NFC 주머니 태그 쓰기"), + title: const Text("NFC 주머니 태그 쓰기"), backgroundColor: Colors.deepPurple, foregroundColor: Colors.white, ), diff --git a/lib/ui/teacher_attendance_page.dart b/lib/ui/teacher_attendance_page.dart index 44f7046..d014188 100644 --- a/lib/ui/teacher_attendance_page.dart +++ b/lib/ui/teacher_attendance_page.dart @@ -63,7 +63,7 @@ class _TeacherAttendancePageState extends State { showDialog( context: context, builder: (context) => AlertDialog( - title: const Text('🧪 테스트용 허용시간 초기화'), + title: const Text('테스트용 허용시간 초기화'), content: const Text( '하교 처리나 반출 허용 시간 설정으로 켜져 있는 모든 허용 시간대를 지금 즉시 해제합니다.\n' '(무단반출 감지 테스트할 때만 사용하세요)', @@ -126,7 +126,7 @@ class _TeacherAttendancePageState extends State { showDialog( context: context, builder: (context) => AlertDialog( - title: const Text('⏰ 전체 학생 반출 허용 시간 설정'), + title: const Text('전체 학생 반출 허용 시간 설정'), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -169,7 +169,7 @@ class _TeacherAttendancePageState extends State { showDialog( context: context, builder: (context) => AlertDialog( - title: const Text('🏫 하교 처리'), + title: const Text('하교 처리'), content: const Text( '지금부터 모든 학생의 반출이 자동으로 허용되며, 더 이상 무단반출 경고가 뜨지 않습니다.\n하교 처리하시겠습니까?', ), @@ -206,7 +206,7 @@ class _TeacherAttendancePageState extends State { backgroundColor: AppPalette.mist, appBar: AppBar( title: const Text( - '📋 실시간 출석 현황', + '실시간 출석 현황', style: TextStyle(fontWeight: FontWeight.bold), ), backgroundColor: AppPalette.ink, @@ -261,7 +261,7 @@ class _TeacherAttendancePageState extends State { Icons.bug_report_outlined, color: Colors.white70, ), - tooltip: '🧪 테스트용: 허용시간 초기화', + tooltip: '테스트용: 허용시간 초기화', ), const SizedBox(width: 8), ], @@ -387,9 +387,9 @@ class _TeacherAttendancePageState extends State { ? Colors.red : (isPending ? Colors.orange : (isComplete ? Colors.blue : Colors.red)); final String statusLine = hasViolation - ? '🚨 무단반출 (${student['violationTime']})' + ? '무단반출 (${student['violationTime']})' : (isPending - ? '⏳ 미완료 (${student['checkInTime']})' + ? '미완료 (${student['checkInTime']})' : (isComplete ? '${student['checkInTime']}' : (student['hasEverCheckedIn'] == true ? '미제출' : '미등록'))); @@ -691,7 +691,7 @@ class _TeacherAttendancePageState extends State { const SizedBox(width: 8), Expanded( child: Text( - '🔓 지금 전체 반출 허용 중입니다 ($until 까지) — 이 시간 동안은 무단반출 경고가 뜨지 않아요.', + '지금 전체 반출 허용 중입니다 ($until 까지) — 이 시간 동안은 무단반출 경고가 뜨지 않아요.', style: TextStyle( color: Colors.amber[900], fontWeight: FontWeight.bold, @@ -721,12 +721,12 @@ class _TeacherAttendancePageState extends State { onSelected: (_) => _controller.setFilter("ALL"), ), FilterChip( - label: const Text("🟢 출석자"), + label: const Text("출석자"), selected: _controller.filterType == "CHECKED_IN", onSelected: (_) => _controller.setFilter("CHECKED_IN"), ), FilterChip( - label: const Text("🔴 미출석자"), + label: const Text("미출석자"), selected: _controller.filterType == "ABSENT", onSelected: (_) => _controller.setFilter("ABSENT"), ), diff --git a/lib/ui/teacher_register_screen.dart b/lib/ui/teacher_register_screen.dart index f66a649..28432e3 100644 --- a/lib/ui/teacher_register_screen.dart +++ b/lib/ui/teacher_register_screen.dart @@ -36,7 +36,7 @@ class _TeacherRegisterScreenState extends State { if (id.isEmpty || pw.isEmpty || name.isEmpty || secret.isEmpty) { ScaffoldMessenger.of( context, - ).showSnackBar(const SnackBar(content: Text('⚠️ 모든 빈칸을 입력해 주세요.'))); + ).showSnackBar(const SnackBar(content: Text('모든 빈칸을 입력해 주세요.'))); return; } @@ -72,7 +72,7 @@ class _TeacherRegisterScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( - '👨‍🏫 교직원 전용 인증', + '교직원 전용 인증', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), const SizedBox(height: 4), @@ -85,7 +85,7 @@ class _TeacherRegisterScreenState extends State { controller: _secretController, obscureText: true, decoration: const InputDecoration( - labelText: '🔑 교사 인증 비밀코드 입력', + labelText: '교사 인증 비밀코드 입력', border: OutlineInputBorder(), ), ), diff --git a/lib/ui/teacher_student_management_page.dart b/lib/ui/teacher_student_management_page.dart index 86b8ed1..784f74f 100644 --- a/lib/ui/teacher_student_management_page.dart +++ b/lib/ui/teacher_student_management_page.dart @@ -53,7 +53,7 @@ class _TeacherStudentManagementPageState if (sId.isEmpty || sName.isEmpty) { ScaffoldMessenger.of( context, - ).showSnackBar(const SnackBar(content: Text('⚠️ 모든 입력란을 채워주세요.'))); + ).showSnackBar(const SnackBar(content: Text('모든 입력란을 채워주세요.'))); return; } @@ -91,15 +91,13 @@ class _TeacherStudentManagementPageState if (!mounted) return; ScaffoldMessenger.of( context, - ).showSnackBar(SnackBar(content: Text('❌ 엑셀 파일을 읽는 데 실패했습니다: $e'))); + ).showSnackBar(SnackBar(content: Text('엑셀 파일을 읽는 데 실패했습니다: $e'))); return; } if (rows.isEmpty) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('⚠️ 유효한 학생 데이터를 찾지 못했습니다. (1행은 머리글로 건너뜁니다)'), - ), + const SnackBar(content: Text('유효한 학생 데이터를 찾지 못했습니다. (1행은 머리글로 건너뜁니다)')), ); return; } @@ -112,7 +110,7 @@ class _TeacherStudentManagementPageState context: context, builder: (context) => AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), - title: Text('📄 ${rows.length}명 확인됨'), + title: Text('${rows.length}명 확인됨'), content: SizedBox( width: 400, child: Column( @@ -209,9 +207,7 @@ class _TeacherStudentManagementPageState context: context, builder: (context) => AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), - title: Text( - result.failures.isEmpty ? '✅ 일괄 등록 완료' : '⚠️ 일괄 등록 완료 (일부 실패)', - ), + title: Text(result.failures.isEmpty ? '일괄 등록 완료' : '일괄 등록 완료 (일부 실패)'), content: SizedBox( width: 400, child: Column( @@ -295,7 +291,7 @@ class _TeacherStudentManagementPageState context: context, builder: (ctx) => AlertDialog( title: const Text( - '⚠️ 기기 등록 초기화', + '기기 등록 초기화', style: TextStyle(fontWeight: FontWeight.bold, color: AppPalette.ink), ), content: Text('$studentName 학생의 스마트폰 기기 등록과 비밀번호(1234)를 초기화하시겠습니까?'), @@ -676,7 +672,7 @@ class _TeacherStudentManagementPageState backgroundColor: AppPalette.mist, appBar: AppBar( title: const Text( - '⚙️ 학생 통합 관리 센터', + '학생 통합 관리 센터', style: TextStyle(fontWeight: FontWeight.bold), ), backgroundColor: AppPalette.ink,