전체 UI 색상 통일 - 제각각이던 빨강/주황/파랑 계열을 의미별 토큰 4종으로 정리

danger/warning/success/approved(+각 Bg 버전)를 AppPalette에 추가하고,
화면마다 다르게 쓰이던 Colors.red[400/600/700]/redAccent, orange/amber
계열, blue 계열 리터럴을 전부 해당 토큰으로 교체. NFC 체크인 화면의
홀로 튀던 Colors.blueAccent도 함께 정리.
This commit is contained in:
2026-09-30 06:29:37 +00:00
parent 153c341efc
commit 9fe3e61c1c
17 changed files with 137 additions and 94 deletions
+11
View File
@@ -11,4 +11,15 @@ class AppPalette {
static const Color linen = Color(0xFFECEBE4); // 은은한 카드/배지 배경 static const Color linen = Color(0xFFECEBE4); // 은은한 카드/배지 배경
static const Color mist = Color(0xFFEEF0F2); // 페이지 배경 static const Color mist = Color(0xFFEEF0F2); // 페이지 배경
static const Color paper = Color(0xFFFAFAFF); // 카드 표면(거의 흰색) static const Color paper = Color(0xFFFAFAFF); // 카드 표면(거의 흰색)
// 🚨 경고성 색상 3종 - 예전엔 화면마다 Colors.red/red[400]/red[700]/redAccent처럼
// 제각각 써서 같은 의미인데 색이 미묘하게 달랐다. 이제 의미별로 딱 하나씩만 쓴다.
static const Color danger = Color(0xFFE13B3B); // 삭제/위반/거절/신고 등 위험/경고
static const Color dangerBg = Color(0xFFFCE9E9); // danger의 연한 배경(배지 등)
static const Color warning = Color(0xFFF08A24); // 대기중/수업중/진행중 등 주의
static const Color warningBg = Color(0xFFFDF0E1); // warning의 연한 배경
static const Color success = Color(0xFF2E9E5B); // 완료/성공(NFC 스캔 성공 등)
static const Color successBg = Color(0xFFE4F5EB); // success의 연한 배경
static const Color approved = Color(0xFF3B78C2); // 승인됨/완료 상태 표시
static const Color approvedBg = Color(0xFFE7F0FA); // approved의 연한 배경
} }
+13 -6
View File
@@ -39,7 +39,10 @@ class _AdminDashboardState extends State<AdminDashboard> {
return AlertDialog( return AlertDialog(
title: const Text( title: const Text(
'DB 초기화 경고', 'DB 초기화 경고',
style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold), style: TextStyle(
color: AppPalette.danger,
fontWeight: FontWeight.bold,
),
), ),
content: const Text( content: const Text(
'모든 학생의 출석 및 휴대폰 제출 데이터가 영구적으로 삭제됩니다.\n\n정말 초기화하시겠습니까?', '모든 학생의 출석 및 휴대폰 제출 데이터가 영구적으로 삭제됩니다.\n\n정말 초기화하시겠습니까?',
@@ -50,7 +53,9 @@ class _AdminDashboardState extends State<AdminDashboard> {
child: const Text('취소', style: TextStyle(color: Colors.grey)), child: const Text('취소', style: TextStyle(color: Colors.grey)),
), ),
ElevatedButton( ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: Colors.red), style: ElevatedButton.styleFrom(
backgroundColor: AppPalette.danger,
),
onPressed: () { onPressed: () {
Navigator.pop(dialogContext); Navigator.pop(dialogContext);
_resetDatabase(); _resetDatabase();
@@ -113,16 +118,18 @@ class _AdminDashboardState extends State<AdminDashboard> {
const SizedBox(height: 40), const SizedBox(height: 40),
_controller.isLoading _controller.isLoading
? const CircularProgressIndicator(color: Colors.red) ? const CircularProgressIndicator(
color: AppPalette.danger,
)
: SizedBox( : SizedBox(
width: double.infinity, width: double.infinity,
height: 60, height: 60,
child: ElevatedButton.icon( child: ElevatedButton.icon(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.red[50], backgroundColor: AppPalette.dangerBg,
foregroundColor: Colors.red, foregroundColor: AppPalette.danger,
side: const BorderSide( side: const BorderSide(
color: Colors.red, color: AppPalette.danger,
width: 2, width: 2,
), ),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
+1 -1
View File
@@ -140,7 +140,7 @@ class _BoardPostDetailScreenState extends State<BoardPostDetailScreen> {
), ),
TextButton( TextButton(
onPressed: () => Navigator.pop(dialogContext, true), onPressed: () => Navigator.pop(dialogContext, true),
child: const Text('삭제', style: TextStyle(color: Colors.red)), child: const Text('삭제', style: TextStyle(color: AppPalette.danger)),
), ),
], ],
), ),
+2 -2
View File
@@ -113,7 +113,7 @@ class _BoardReportScreenState extends State<BoardReportScreen> {
Text( Text(
'신고 사유: ${report['reason']}', '신고 사유: ${report['reason']}',
style: const TextStyle( style: const TextStyle(
color: Colors.redAccent, color: AppPalette.danger,
fontSize: 12.5, fontSize: 12.5,
), ),
), ),
@@ -145,7 +145,7 @@ class _BoardReportScreenState extends State<BoardReportScreen> {
Expanded( Expanded(
child: ElevatedButton( child: ElevatedButton(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.red[400], backgroundColor: AppPalette.danger,
foregroundColor: Colors.white, foregroundColor: Colors.white,
), ),
onPressed: _controller.isBusy onPressed: _controller.isBusy
+22 -19
View File
@@ -106,7 +106,7 @@ class _DeviceCheckoutLedgerPageState extends State<DeviceCheckoutLedgerPage> {
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
title: const Row( title: const Row(
children: [ children: [
Icon(Icons.warning_amber_rounded, color: Colors.orange), Icon(Icons.warning_amber_rounded, color: AppPalette.warning),
SizedBox(width: 8), SizedBox(width: 8),
Text('많은 시간요청 학생'), Text('많은 시간요청 학생'),
], ],
@@ -147,7 +147,7 @@ class _DeviceCheckoutLedgerPageState extends State<DeviceCheckoutLedgerPage> {
'${_timeRange(r['requestedStart'], r['requestedEnd'])} ' '${_timeRange(r['requestedStart'], r['requestedEnd'])} '
'(약 ${hours?.toStringAsFixed(1)}시간)', '(약 ${hours?.toStringAsFixed(1)}시간)',
style: const TextStyle( style: const TextStyle(
color: Colors.orange, color: AppPalette.warning,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 13, fontSize: 13,
), ),
@@ -172,8 +172,10 @@ class _DeviceCheckoutLedgerPageState extends State<DeviceCheckoutLedgerPage> {
_reject(r['id']); _reject(r['id']);
}, },
style: OutlinedButton.styleFrom( style: OutlinedButton.styleFrom(
foregroundColor: Colors.red, foregroundColor: AppPalette.danger,
side: const BorderSide(color: Colors.red), side: const BorderSide(
color: AppPalette.danger,
),
), ),
child: const Text('거절'), child: const Text('거절'),
), ),
@@ -224,13 +226,13 @@ class _DeviceCheckoutLedgerPageState extends State<DeviceCheckoutLedgerPage> {
({Color color, String label}) _statusInfo(String status) { ({Color color, String label}) _statusInfo(String status) {
switch (status) { switch (status) {
case 'PENDING': case 'PENDING':
return (color: Colors.orange, label: '대기중'); return (color: AppPalette.warning, label: '대기중');
case 'APPROVED': case 'APPROVED':
return (color: Colors.blue, label: '승인됨'); return (color: AppPalette.approved, label: '승인됨');
case 'RETURNED': case 'RETURNED':
return (color: Colors.grey, label: '반납완료'); return (color: Colors.grey, label: '반납완료');
case 'REJECTED': case 'REJECTED':
return (color: Colors.red, label: '거절됨'); return (color: AppPalette.danger, label: '거절됨');
default: default:
return (color: Colors.grey, label: status); return (color: Colors.grey, label: status);
} }
@@ -276,7 +278,7 @@ class _DeviceCheckoutLedgerPageState extends State<DeviceCheckoutLedgerPage> {
icon: Badge( icon: Badge(
isLabelVisible: longCount > 0, isLabelVisible: longCount > 0,
label: Text('$longCount'), label: Text('$longCount'),
backgroundColor: Colors.red, backgroundColor: AppPalette.danger,
child: const Icon(Icons.warning_amber_rounded), child: const Icon(Icons.warning_amber_rounded),
), ),
onPressed: _showLongRequestsDialog, onPressed: _showLongRequestsDialog,
@@ -297,14 +299,14 @@ class _DeviceCheckoutLedgerPageState extends State<DeviceCheckoutLedgerPage> {
vertical: 10, vertical: 10,
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.orange[100], color: AppPalette.warningBg,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.orange[400]!), border: Border.all(color: AppPalette.warning),
), ),
child: Text( child: Text(
'승인 대기 중인 요청이 $pendingCount건 있습니다.', '승인 대기 중인 요청이 $pendingCount건 있습니다.',
style: TextStyle( style: TextStyle(
color: Colors.orange[900], color: AppPalette.warning,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
@@ -340,15 +342,15 @@ class _DeviceCheckoutLedgerPageState extends State<DeviceCheckoutLedgerPage> {
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
side: isLong side: isLong
? BorderSide( ? const BorderSide(
color: Colors.red[400]!, color: AppPalette.danger,
width: 2, width: 2,
) )
: (isPending : (isPending
? BorderSide( ? const BorderSide(
color: Colors.orange[300]!, color: AppPalette.warning,
) )
: BorderSide( : const BorderSide(
color: AppPalette.sage, color: AppPalette.sage,
)), )),
), ),
@@ -419,7 +421,7 @@ class _DeviceCheckoutLedgerPageState extends State<DeviceCheckoutLedgerPage> {
Text( Text(
'${r['approvedByTeacherName']} 선생님이 허용했습니다', '${r['approvedByTeacherName']} 선생님이 허용했습니다',
style: TextStyle( style: TextStyle(
color: Colors.blue[700], color: AppPalette.approved,
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
@@ -438,9 +440,10 @@ class _DeviceCheckoutLedgerPageState extends State<DeviceCheckoutLedgerPage> {
style: style:
OutlinedButton.styleFrom( OutlinedButton.styleFrom(
foregroundColor: foregroundColor:
Colors.red, AppPalette.danger,
side: const BorderSide( side: const BorderSide(
color: Colors.red, color:
AppPalette.danger,
), ),
), ),
child: const Text('거절'), child: const Text('거절'),
+1 -1
View File
@@ -100,7 +100,7 @@ class _FriendsScreenState extends State<FriendsScreen> {
), ),
TextButton( TextButton(
onPressed: () => Navigator.pop(dialogContext, true), onPressed: () => Navigator.pop(dialogContext, true),
child: const Text('삭제', style: TextStyle(color: Colors.red)), child: const Text('삭제', style: TextStyle(color: AppPalette.danger)),
), ),
], ],
), ),
+4 -1
View File
@@ -196,7 +196,10 @@ class _GroupDetailScreenState extends State<GroupDetailScreen> {
), ),
TextButton( TextButton(
onPressed: () => Navigator.pop(dialogContext, true), onPressed: () => Navigator.pop(dialogContext, true),
child: const Text('나가기', style: TextStyle(color: Colors.red)), child: const Text(
'나가기',
style: TextStyle(color: AppPalette.danger),
),
), ),
], ],
), ),
+6 -3
View File
@@ -344,20 +344,23 @@ class _GroupListScreenState extends State<GroupListScreen> {
vertical: 1, vertical: 1,
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.red[50], color:
AppPalette.warningBg,
borderRadius: borderRadius:
BorderRadius.circular( BorderRadius.circular(
20, 20,
), ),
border: Border.all( border: Border.all(
color: Colors.red, color:
AppPalette.warning,
), ),
), ),
child: Text( child: Text(
'대기 ${g['pendingRequestCount']}', '대기 ${g['pendingRequestCount']}',
style: const TextStyle( style: const TextStyle(
fontSize: 10, fontSize: 10,
color: Colors.red, color:
AppPalette.warning,
), ),
), ),
), ),
+1 -1
View File
@@ -122,7 +122,7 @@ class _LoginScreenState extends State<LoginScreen> {
children: [ children: [
const Text( const Text(
'보안을 위해 새로운 비밀번호를 설정해 주세요.', '보안을 위해 새로운 비밀번호를 설정해 주세요.',
style: TextStyle(color: Colors.redAccent), style: TextStyle(color: AppPalette.danger),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
TextField( TextField(
+7 -4
View File
@@ -116,7 +116,7 @@ class _MainDashboardState extends State<MainDashboard> {
), ),
title: const Row( title: const Row(
children: [ children: [
Icon(Icons.warning_amber_rounded, color: Colors.redAccent), Icon(Icons.warning_amber_rounded, color: AppPalette.danger),
SizedBox(width: 10), SizedBox(width: 10),
Text( Text(
'계정 강제 삭제', '계정 강제 삭제',
@@ -142,10 +142,13 @@ class _MainDashboardState extends State<MainDashboard> {
decoration: InputDecoration( decoration: InputDecoration(
labelText: '학번 또는 교직원 번호', labelText: '학번 또는 교직원 번호',
hintText: '예: 201101 또는 T1001', hintText: '예: 201101 또는 T1001',
labelStyle: TextStyle(color: Colors.red[400]), labelStyle: const TextStyle(color: AppPalette.danger),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
borderSide: BorderSide(color: Colors.red[400]!, width: 2), borderSide: const BorderSide(
color: AppPalette.danger,
width: 2,
),
), ),
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
@@ -175,7 +178,7 @@ class _MainDashboardState extends State<MainDashboard> {
} }
}, },
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.redAccent, backgroundColor: AppPalette.danger,
foregroundColor: Colors.white, foregroundColor: Colors.white,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
+14 -11
View File
@@ -50,9 +50,9 @@ class _NfcPocketCheckInScreenState extends State<NfcPocketCheckInScreen> {
void _handleMessage(String text, WatchMessageLevel level) { void _handleMessage(String text, WatchMessageLevel level) {
final Color color = switch (level) { final Color color = switch (level) {
WatchMessageLevel.info => Colors.blueGrey, WatchMessageLevel.info => Colors.blueGrey,
WatchMessageLevel.success => Colors.green, WatchMessageLevel.success => AppPalette.success,
WatchMessageLevel.warning => Colors.orange, WatchMessageLevel.warning => AppPalette.warning,
WatchMessageLevel.error => Colors.red, WatchMessageLevel.error => AppPalette.danger,
}; };
_showSnackBar(text, color); _showSnackBar(text, color);
} }
@@ -73,10 +73,13 @@ class _NfcPocketCheckInScreenState extends State<NfcPocketCheckInScreen> {
showDialog( showDialog(
context: context, context: context,
builder: (context) => AlertDialog( builder: (context) => AlertDialog(
backgroundColor: Colors.red[50], backgroundColor: AppPalette.dangerBg,
title: const Text( title: const Text(
"무단 반출 감지", "무단 반출 감지",
style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold), style: TextStyle(
color: AppPalette.danger,
fontWeight: FontWeight.bold,
),
), ),
content: Text( content: Text(
"[${pocketNumber ?? _controller.activePocketNumber}] 주머니에서 휴대폰이 꺼내진 것으로 감지되었습니다.\n담당 선생님께 알림이 전송되었습니다.", "[${pocketNumber ?? _controller.activePocketNumber}] 주머니에서 휴대폰이 꺼내진 것으로 감지되었습니다.\n담당 선생님께 알림이 전송되었습니다.",
@@ -177,8 +180,8 @@ class _NfcPocketCheckInScreenState extends State<NfcPocketCheckInScreen> {
_controller.isProcessing ? Icons.sync : Icons.nfc, _controller.isProcessing ? Icons.sync : Icons.nfc,
size: 100, size: 100,
color: _controller.isProcessing color: _controller.isProcessing
? Colors.orange ? AppPalette.warning
: Colors.blueAccent, : AppPalette.ink,
), ),
const SizedBox(height: 30), const SizedBox(height: 30),
@@ -190,7 +193,7 @@ class _NfcPocketCheckInScreenState extends State<NfcPocketCheckInScreen> {
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: _controller.isProcessing color: _controller.isProcessing
? Colors.orange ? AppPalette.warning
: Colors.black87, : Colors.black87,
), ),
), ),
@@ -227,13 +230,13 @@ class _NfcPocketCheckInScreenState extends State<NfcPocketCheckInScreen> {
height: 160, height: 160,
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
color: Colors.greenAccent.withValues(alpha: 0.15), color: AppPalette.success.withValues(alpha: 0.15),
border: Border.all(color: Colors.greenAccent, width: 3), border: Border.all(color: AppPalette.success, width: 3),
), ),
child: const Icon( child: const Icon(
Icons.shield_rounded, Icons.shield_rounded,
size: 72, size: 72,
color: Colors.greenAccent, color: AppPalette.success,
), ),
), ),
const SizedBox(height: 40), const SizedBox(height: 40),
+2 -2
View File
@@ -40,7 +40,7 @@ class _NfcTagWriterScreenState extends State<NfcTagWriterScreen> {
AppNotice.show( AppNotice.show(
context, context,
text, text,
color: isError ? Colors.red[700] : Colors.green[700], color: isError ? AppPalette.danger : AppPalette.success,
icon: isError ? Icons.error_outline_rounded : Icons.check_circle_rounded, icon: isError ? Icons.error_outline_rounded : Icons.check_circle_rounded,
); );
} }
@@ -79,7 +79,7 @@ class _NfcTagWriterScreenState extends State<NfcTagWriterScreen> {
Icon( Icon(
isWriting ? Icons.nfc : Icons.edit_note_rounded, isWriting ? Icons.nfc : Icons.edit_note_rounded,
size: 80, size: 80,
color: isWriting ? Colors.orange : AppPalette.ink, color: isWriting ? AppPalette.warning : AppPalette.ink,
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
+3 -3
View File
@@ -144,7 +144,7 @@ class _StudyCalendarScreenState extends State<StudyCalendarScreen> {
}, },
child: const Text( child: const Text(
'삭제', '삭제',
style: TextStyle(color: Colors.red), style: TextStyle(color: AppPalette.danger),
), ),
), ),
), ),
@@ -347,7 +347,7 @@ class _StudyCalendarScreenState extends State<StudyCalendarScreen> {
size: 12, size: 12,
color: studied color: studied
? Colors.white ? Colors.white
: Colors.orange, : AppPalette.warning,
), ),
), ),
], ],
@@ -363,7 +363,7 @@ class _StudyCalendarScreenState extends State<StudyCalendarScreen> {
const SizedBox(width: 16), const SizedBox(width: 16),
_legendIcon( _legendIcon(
Icons.card_giftcard_rounded, Icons.card_giftcard_rounded,
Colors.orange, AppPalette.warning,
'이벤트', '이벤트',
), ),
], ],
+7 -4
View File
@@ -196,7 +196,10 @@ class _StudyTimerScreenState extends State<StudyTimerScreen>
const SizedBox(height: 10), const SizedBox(height: 10),
const Text( const Text(
'타이머가 멈춰있을 때만 설정을 바꿀 수 있어요.', '타이머가 멈춰있을 때만 설정을 바꿀 수 있어요.',
style: TextStyle(color: Colors.redAccent, fontSize: 12.5), style: TextStyle(
color: AppPalette.danger,
fontSize: 12.5,
),
), ),
], ],
const SizedBox(height: 18), const SizedBox(height: 18),
@@ -442,7 +445,7 @@ class _StudyTimerScreenState extends State<StudyTimerScreen>
size: 140, size: 140,
icon: Icons.stop_rounded, icon: Icons.stop_rounded,
label: '공부 종료', label: '공부 종료',
color: Colors.red[400]!, color: AppPalette.danger,
onTap: () => _runAction(_controller.stop), onTap: () => _runAction(_controller.stop),
); );
} }
@@ -453,7 +456,7 @@ class _StudyTimerScreenState extends State<StudyTimerScreen>
size: 110, size: 110,
icon: isPaused ? Icons.play_arrow_rounded : Icons.pause_rounded, icon: isPaused ? Icons.play_arrow_rounded : Icons.pause_rounded,
label: isPaused ? '재개' : '일시정지', label: isPaused ? '재개' : '일시정지',
color: isPaused ? AppPalette.ink : Colors.amber[700]!, color: isPaused ? AppPalette.ink : AppPalette.warning,
onTap: () => onTap: () =>
_runAction(isPaused ? _controller.resume : _controller.pause), _runAction(isPaused ? _controller.resume : _controller.pause),
), ),
@@ -462,7 +465,7 @@ class _StudyTimerScreenState extends State<StudyTimerScreen>
size: 110, size: 110,
icon: Icons.stop_rounded, icon: Icons.stop_rounded,
label: '공부 종료', label: '공부 종료',
color: Colors.red[400]!, color: AppPalette.danger,
onTap: () => _runAction(_controller.stop), onTap: () => _runAction(_controller.stop),
), ),
], ],
+21 -19
View File
@@ -360,8 +360,10 @@ class _TeacherAttendancePageState extends State<TeacherAttendancePage> {
final bool isPending = student['attendanceStatus'] == 'PENDING'; final bool isPending = student['attendanceStatus'] == 'PENDING';
final bool isComplete = student['attendanceStatus'] == 'COMPLETE'; final bool isComplete = student['attendanceStatus'] == 'COMPLETE';
final Color statusColor = hasViolation final Color statusColor = hasViolation
? Colors.red ? AppPalette.danger
: (isPending ? Colors.orange : (isComplete ? Colors.blue : Colors.red)); : (isPending
? AppPalette.warning
: (isComplete ? AppPalette.approved : AppPalette.danger));
final String statusLine = hasViolation final String statusLine = hasViolation
? '무단반출 (${student['violationTime']})' ? '무단반출 (${student['violationTime']})'
: (isPending : (isPending
@@ -373,10 +375,10 @@ class _TeacherAttendancePageState extends State<TeacherAttendancePage> {
return Container( return Container(
padding: const EdgeInsets.all(14), padding: const EdgeInsets.all(14),
decoration: BoxDecoration( decoration: BoxDecoration(
color: hasViolation ? Colors.red[50] : AppPalette.paper, color: hasViolation ? AppPalette.dangerBg : AppPalette.paper,
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
border: Border.all( border: Border.all(
color: hasViolation ? Colors.red[300]! : AppPalette.sage, color: hasViolation ? AppPalette.danger : AppPalette.sage,
width: hasViolation ? 1.5 : 1, width: hasViolation ? 1.5 : 1,
), ),
boxShadow: [ boxShadow: [
@@ -451,10 +453,10 @@ class _TeacherAttendancePageState extends State<TeacherAttendancePage> {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
color: hasViolation color: hasViolation
? Colors.red[700] ? AppPalette.danger
: (isPending : (isPending
? Colors.orange[800] ? AppPalette.warning
: (isComplete ? Colors.grey[600] : Colors.red[400])), : (isComplete ? Colors.grey[600] : AppPalette.danger)),
fontSize: 11.5, fontSize: 11.5,
fontWeight: hasViolation ? FontWeight.bold : FontWeight.normal, fontWeight: hasViolation ? FontWeight.bold : FontWeight.normal,
), ),
@@ -470,7 +472,7 @@ class _TeacherAttendancePageState extends State<TeacherAttendancePage> {
student['studentName'], student['studentName'],
), ),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.red[600], backgroundColor: AppPalette.danger,
foregroundColor: Colors.white, foregroundColor: Colors.white,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
), ),
@@ -781,18 +783,18 @@ class _TeacherAttendancePageState extends State<TeacherAttendancePage> {
final bool isPending = student['attendanceStatus'] == 'PENDING'; final bool isPending = student['attendanceStatus'] == 'PENDING';
final bool isComplete = student['attendanceStatus'] == 'COMPLETE'; final bool isComplete = student['attendanceStatus'] == 'COMPLETE';
final Color background = hasViolation final Color background = hasViolation
? Colors.red[50]! ? AppPalette.dangerBg
: isComplete : isComplete
? Colors.blue[50]! ? AppPalette.approvedBg
: isPending : isPending
? Colors.orange[50]! ? AppPalette.warningBg
: AppPalette.paper; : AppPalette.paper;
final Color border = hasViolation final Color border = hasViolation
? Colors.red[300]! ? AppPalette.danger
: isComplete : isComplete
? Colors.blue[200]! ? AppPalette.approved
: isPending : isPending
? Colors.orange[200]! ? AppPalette.warning
: AppPalette.sage; : AppPalette.sage;
return InkWell( return InkWell(
@@ -828,7 +830,7 @@ class _TeacherAttendancePageState extends State<TeacherAttendancePage> {
'무단반출', '무단반출',
style: TextStyle( style: TextStyle(
fontSize: 7.5, fontSize: 7.5,
color: Colors.red[700], color: AppPalette.danger,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
@@ -849,19 +851,19 @@ class _TeacherAttendancePageState extends State<TeacherAttendancePage> {
margin: const EdgeInsets.fromLTRB(16, 8, 16, 0), margin: const EdgeInsets.fromLTRB(16, 8, 16, 0),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.amber[100], color: AppPalette.warningBg,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.amber[400]!), border: Border.all(color: AppPalette.warning),
), ),
child: Row( child: Row(
children: [ children: [
Icon(Icons.lock_open_rounded, color: Colors.amber[800], size: 20), Icon(Icons.lock_open_rounded, color: AppPalette.warning, size: 20),
const SizedBox(width: 8), const SizedBox(width: 8),
Expanded( Expanded(
child: Text( child: Text(
'지금 전체 반출 허용 중입니다 ($until 까지) — 이 시간 동안은 무단반출 경고가 뜨지 않아요.', '지금 전체 반출 허용 중입니다 ($until 까지) — 이 시간 동안은 무단반출 경고가 뜨지 않아요.',
style: TextStyle( style: TextStyle(
color: Colors.amber[900], color: AppPalette.warning,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 12.5, fontSize: 12.5,
), ),
+8 -4
View File
@@ -376,7 +376,7 @@ class _TeacherCallScreenState extends State<TeacherCallScreen> {
final location = t['location'] ?? '교무실'; final location = t['location'] ?? '교무실';
final isSelected = _selectedTeacherId == t['teacherId']; final isSelected = _selectedTeacherId == t['teacherId'];
final inClass = _controller.isInClassNow(name); final inClass = _controller.isInClassNow(name);
final statusColor = inClass ? Colors.orange : AppPalette.ink; final statusColor = inClass ? AppPalette.warning : AppPalette.ink;
return GestureDetector( return GestureDetector(
onTap: () => setState(() { onTap: () => setState(() {
@@ -428,17 +428,21 @@ class _TeacherCallScreenState extends State<TeacherCallScreen> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: isSelected color: isSelected
? Colors.white.withValues(alpha: 0.15) ? Colors.white.withValues(alpha: 0.15)
: Colors.orange[50], : AppPalette.warningBg,
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
border: Border.all( border: Border.all(
color: isSelected ? Colors.white54 : Colors.orange, color: isSelected
? Colors.white54
: AppPalette.warning,
), ),
), ),
child: Text( child: Text(
'수업중', '수업중',
style: TextStyle( style: TextStyle(
fontSize: 9, fontSize: 9,
color: isSelected ? Colors.white : Colors.orange, color: isSelected
? Colors.white
: AppPalette.warning,
), ),
), ),
), ),
+14 -13
View File
@@ -223,7 +223,10 @@ class _TeacherStudentManagementPageState
child: SingleChildScrollView( child: SingleChildScrollView(
child: Text( child: Text(
result.failures.join('\n'), result.failures.join('\n'),
style: const TextStyle(fontSize: 12, color: Colors.red), style: const TextStyle(
fontSize: 12,
color: AppPalette.danger,
),
), ),
), ),
), ),
@@ -321,7 +324,7 @@ class _TeacherStudentManagementPageState
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
title: Row( title: Row(
children: [ children: [
Icon(Icons.warning_amber_rounded, color: Colors.red[700]), Icon(Icons.warning_amber_rounded, color: AppPalette.danger),
const SizedBox(width: 10), const SizedBox(width: 10),
const Text( const Text(
'계정 완전 삭제', '계정 완전 삭제',
@@ -339,7 +342,7 @@ class _TeacherStudentManagementPageState
), ),
ElevatedButton( ElevatedButton(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.red[600], backgroundColor: AppPalette.danger,
foregroundColor: Colors.white, foregroundColor: Colors.white,
), ),
onPressed: () async { onPressed: () async {
@@ -519,10 +522,10 @@ class _TeacherStudentManagementPageState
height: double.infinity, height: double.infinity,
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
color: _isDragging ? Colors.orange[50] : AppPalette.paper, color: _isDragging ? AppPalette.warningBg : AppPalette.paper,
borderRadius: BorderRadius.circular(24), borderRadius: BorderRadius.circular(24),
border: Border.all( border: Border.all(
color: _isDragging ? Colors.orange : AppPalette.sage, color: _isDragging ? AppPalette.warning : AppPalette.sage,
width: _isDragging ? 2 : 1, width: _isDragging ? 2 : 1,
), ),
), ),
@@ -532,7 +535,7 @@ class _TeacherStudentManagementPageState
Icon( Icon(
Icons.upload_file_rounded, Icons.upload_file_rounded,
size: 40, size: 40,
color: _isDragging ? Colors.orange : AppPalette.sage, color: _isDragging ? AppPalette.warning : AppPalette.sage,
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
Text( Text(
@@ -540,7 +543,7 @@ class _TeacherStudentManagementPageState
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: _isDragging ? Colors.orange[800] : AppPalette.ink, color: _isDragging ? AppPalette.warning : AppPalette.ink,
), ),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
@@ -584,15 +587,13 @@ class _TeacherStudentManagementPageState
Container( Container(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: needsReset color: needsReset ? AppPalette.dangerBg : AppPalette.linen,
? Colors.red.withValues(alpha: 0.1)
: AppPalette.linen,
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
child: Icon( child: Icon(
needsReset ? Icons.lock_reset : Icons.person, needsReset ? Icons.lock_reset : Icons.person,
size: 18, size: 18,
color: needsReset ? Colors.red : AppPalette.ink, color: needsReset ? AppPalette.danger : AppPalette.ink,
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
@@ -609,7 +610,7 @@ class _TeacherStudentManagementPageState
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 11.5, fontSize: 11.5,
color: needsReset ? Colors.red[700] : Colors.grey[600], color: needsReset ? AppPalette.danger : Colors.grey[600],
fontWeight: needsReset ? FontWeight.bold : FontWeight.normal, fontWeight: needsReset ? FontWeight.bold : FontWeight.normal,
), ),
), ),
@@ -650,7 +651,7 @@ class _TeacherStudentManagementPageState
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons.delete_forever_rounded, Icons.delete_forever_rounded,
color: Colors.redAccent, color: AppPalette.danger,
size: 18, size: 18,
), ),
tooltip: '계정 영구 삭제', tooltip: '계정 영구 삭제',