// ๐Ÿ‘จโ€๐Ÿซ ๊ต์‚ฌ ๋Œ€์‹œ๋ณด๋“œ. ์‹ค์‹œ๊ฐ„ ์ถœ์„ ํ™•์ธ, ํ•™์ƒ ๊ณ„์ • ๊ด€๋ฆฌ ํ™”๋ฉด์œผ๋กœ ๊ฐ€๋Š” ๋ฉ”๋‰ด๋งŒ ๋‹ด๋‹นํ•œ๋‹ค. import 'package:flutter/material.dart'; import 'device_checkout_ledger_page.dart'; import 'login_screen.dart'; import 'teacher_attendance_page.dart'; import 'teacher_student_management_page.dart'; // ========================================== // ๐Ÿ‘จโ€๐Ÿซ 4. ์„ ์ƒ๋‹˜ ๋Œ€์‹œ๋ณด๋“œ (๊ธฐ์กด 3์ดˆ ํƒ€์ด๋จธ ์™„๋ฒฝ ์œ ์ง€) // ========================================== class TeacherDashboard extends StatefulWidget { final String? teacherId; final String? teacherName; const TeacherDashboard({super.key, this.teacherId, this.teacherName}); @override State createState() => _TeacherDashboardState(); } class _TeacherDashboardState extends State { // ๐Ÿงผ [์ˆ˜์ •] ์‚ฌ์šฉํ•˜์ง€ ์•Š๋˜ _isLoading ๋ณ€์ˆ˜๋ฅผ ์‚ญ์ œํ•˜์—ฌ ๊ฒฝ๊ณ ๋ฅผ ์™„๋ฒฝํžˆ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค! @override Widget build(BuildContext context) { // ๋‹ค๋ฅธ ํ™”๋ฉด์—์„œ null์ด ๋„˜์–ด์™”์„ ๋•Œ๋ฅผ ๋Œ€๋น„ํ•œ ์•ˆ์ „๋ง ๋ฐฉํƒ„ ์ฝ”๋“œ final String displayName = widget.teacherName ?? "๊ฐ„ํŽธ์ธ์ฆ ์„ ์ƒ"; final String displayId = widget.teacherId ?? "๊ฐ„ํŽธ์ธ์ฆ"; return Scaffold( backgroundColor: Colors.grey[100], appBar: AppBar( title: const Text( '๐Ÿ‘จโ€๐Ÿซ TEACHER PORTAL', style: TextStyle(fontWeight: FontWeight.bold, letterSpacing: 1.2), ), centerTitle: true, backgroundColor: Colors.green[700], // ๊ต์‚ฌ ์ „์šฉ ๊ทธ๋ฆฐ ํ…Œ๋งˆ ์ปฌ๋Ÿฌ foregroundColor: Colors.white, elevation: 0, actions: [ IconButton( icon: const Icon(Icons.logout_rounded), onPressed: () => Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => const LoginScreen()), ), ), ], ), body: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // ๐Ÿ’ณ [์ƒ๋‹จ ๋ฐฐ๋„ˆ ๊ฐ€์ด๋“œ] StudentDashboard์™€ 100% ์ผ์น˜ํ•˜๋Š” ํ”„๋กœํ•„ ์นด๋“œ ๋ ˆ์ด์•„์›ƒ Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 28), decoration: BoxDecoration( color: Colors.green[700], borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(32), bottomRight: Radius.circular(32), ), ), child: Row( children: [ Container( padding: const EdgeInsets.all(4), decoration: const BoxDecoration( color: Colors.white, shape: BoxShape.circle, ), child: CircleAvatar( radius: 30, backgroundColor: Colors.green[50], child: Icon( Icons.admin_panel_settings_rounded, size: 32, color: Colors.green[700], ), ), ), const SizedBox(width: 18), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '$displayName ๋‹˜', style: const TextStyle( fontSize: 22, fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(height: 4), Text( '๊ต์ง์› ๋ฒˆํ˜ธ: $displayId | ๊ต์‚ฌ ๊ถŒํ•œ ํ™œ์„ฑํ™”๋จ', style: TextStyle( color: Colors.white.withValues(alpha: 0.8), fontSize: 14, ), ), ], ), ], ), ), const SizedBox(height: 32), // ๐Ÿท๏ธ [์„ธ๋กœ ๋ฐ” ํƒ€์ดํ‹€ ์ธ๋””์ผ€์ดํ„ฐ] ๊ตฌ์กฐ ์ผ์น˜ํ™” Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Row( children: [ Container( width: 4, height: 18, decoration: BoxDecoration( color: Colors.green[700], borderRadius: BorderRadius.circular(2), ), ), const SizedBox(width: 10), const Text( '์Šค๋งˆํŠธ ๊ต์‚ฌ์šฉ ๊ด€๋ฆฌ ๋ฉ”๋‰ด', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black87, ), ), ], ), ), const SizedBox(height: 16), // ๐Ÿ“Š [๊ทธ๋ฆฌ๋“œ ๋ ˆ์ด์•„์›ƒ ๋ฉ”๋‰ด] ์‹œํ›„์˜ ์นด๋“œ ์ปดํฌ๋„ŒํŠธ ์Šคํƒ€์ผ ์ ์šฉ // ๐Ÿ–ฅ๏ธ ๋ฐ์Šคํฌํ†ฑ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์นด๋“œ๊ฐ€ ์ง€๋‚˜์น˜๊ฒŒ ์ปค์ง€์ง€ ์•Š๋„๋ก ์ตœ๋Œ€ ๋„ˆ๋น„๋ฅผ ์ œํ•œํ•œ๋‹ค. Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 700), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: GridView.count( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), crossAxisCount: 2, crossAxisSpacing: 16, mainAxisSpacing: 16, childAspectRatio: 0.95, children: [ _buildModernCard( icon: Icons.assignment_turned_in_rounded, title: '์‹ค์‹œ๊ฐ„ ์ถœ์„ ํ™•์ธ', subtitle: 'ํ•™์ƒ ์ œ์ถœ ๋กœ๊ทธ ๋ชจ๋‹ˆํ„ฐ๋ง', color: Colors.blue, onTap: () => Navigator.push( context, MaterialPageRoute( builder: (context) => const TeacherAttendancePage(), ), ), ), _buildModernCard( icon: Icons.manage_accounts_rounded, title: 'ํ•™์ƒ ๊ณ„์ • ๊ด€๋ฆฌ', subtitle: '๊ณ„์ • ์ถ”๊ฐ€ ๋ฐ ๊ฐ•์ œ ๋ฆฌ์…‹', color: Colors.orange, onTap: () => Navigator.push( context, MaterialPageRoute( builder: (context) => const TeacherStudentManagementPage(), ), ), ), _buildModernCard( icon: Icons.tablet_mac_rounded, title: '์Šค๋งˆํŠธ๊ธฐ๊ธฐ ๋ฐ˜์ถœ ๋Œ€์žฅ', subtitle: 'ํŒจ๋“œ ๋ฐ˜์ถœ ์‹ ์ฒญ ์Šน์ธ/๊ฑฐ์ ˆ', color: Colors.teal, onTap: () => Navigator.push( context, MaterialPageRoute( builder: (context) => const DeviceCheckoutLedgerPage(), ), ), ), ], ), ), ), ), const SizedBox(height: 32), ], ), ), ); } // ๐Ÿ’Ž [์‹œํ›„ ๋Œ€์‹œ๋ณด๋“œ ์ „์šฉ ์นด๋“œ ์œ„์ ฏ ์ด์‹ ์™„๋ฃŒ] Widget _buildModernCard({ required IconData icon, required String title, required String subtitle, required Color color, required VoidCallback onTap, bool isActionButton = false, bool isLoading = false, }) { return InkWell( onTap: isLoading ? null : onTap, borderRadius: BorderRadius.circular(24), child: Ink( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.04), blurRadius: 16, offset: const Offset(0, 4), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: color.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(16), ), child: Icon(icon, color: color, size: 28), ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Text( title, style: const TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: Colors.black87, ), ), ), if (isLoading) const SizedBox( width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2), ) else if (isActionButton) Icon( Icons.touch_app_rounded, size: 16, color: color.withValues(alpha: 0.5), ), ], ), const SizedBox(height: 4), Text( subtitle, style: TextStyle( fontSize: 12, color: Colors.grey[500], height: 1.2, ), ), ], ), ], ), ), ); } }