// πŸ‘₯ κ΅μ‚¬μš© 학생 계정 관리 ν™”λ©΄ (UI μ „μš©). μ‹ κ·œ 학생 계정 μΆ”κ°€ 폼과 κ°•μ œ μ‚­μ œ λ‹€μ΄μ–Όλ‘œκ·Έλ₯Ό κ·Έλ¦°λ‹€. // μ„œλ²„ 톡신/μƒνƒœλŠ” lib/function/teacher_student_management_controller.dartκ°€ λ‹΄λ‹Ήν•œλ‹€. import 'package:flutter/material.dart'; import '../function/teacher_student_management_controller.dart'; // ----------------------------------------------------------------------------- // πŸ‘₯ [μ„œλΈŒ ν™”λ©΄ 2] 학생 계정 관리 λž€ (μΆ”κ°€ 양식 폼 + κ°•μ œ μ‚­μ œ λ‹€μ΄μ–Όλ‘œκ·Έ μ™„μ „ λ‚΄μž₯) // ----------------------------------------------------------------------------- class TeacherStudentManagementPage extends StatefulWidget { const TeacherStudentManagementPage({super.key}); @override State createState() => _TeacherStudentManagementPageState(); } class _TeacherStudentManagementPageState extends State { final TeacherStudentManagementController _controller = TeacherStudentManagementController(); final TextEditingController _addIdController = TextEditingController(); final TextEditingController _addNameController = TextEditingController(); final TextEditingController _addPwController = TextEditingController(); int? _selectedGrade; @override void dispose() { _controller.dispose(); _addIdController.dispose(); _addNameController.dispose(); _addPwController.dispose(); super.dispose(); } // βž• [학생 μΆ”κ°€ λ²„νŠΌ λ™μž‘] Future _addStudentAccount() async { final sId = _addIdController.text.trim(); final sName = _addNameController.text.trim(); final sPw = _addPwController.text.trim(); if (sId.isEmpty || sName.isEmpty || sPw.isEmpty) { ScaffoldMessenger.of( context, ).showSnackBar(const SnackBar(content: Text('⚠️ λͺ¨λ“  μž…λ ₯λž€μ„ μ±„μ›Œμ£Όμ„Έμš”.'))); return; } final (success, message) = await _controller.addStudentAccount( studentId: sId, name: sName, password: sPw, grade: _selectedGrade, ); if (!mounted) return; if (success) { _addIdController.clear(); _addNameController.clear(); _addPwController.clear(); setState(() => _selectedGrade = null); } ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text(message))); } // ❌ [학생 μ‚­μ œ λ²„νŠΌ λ™μž‘] Future _deleteStudentAccount(String studentId) async { final (_, message) = await _controller.deleteStudentAccount(studentId); if (!mounted) return; ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text(message))); } // 🚨 계정 μ‚­μ œ 확인 νŒμ—…μ°½ λͺ¨λ‹¬ void _showDeleteDialog() { final TextEditingController deleteIdController = TextEditingController(); showDialog( context: context, builder: (context) { return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(24), ), title: Row( children: [ Icon(Icons.warning_amber_rounded, color: Colors.orange[700]), const SizedBox(width: 10), const Text( '학생 계정 κ°•μ œ μ‚­μ œ', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), ), ], ), content: Column( mainAxisSize: MainAxisSize.min, children: [ const Text( '영ꡬ μ‚­μ œν•  ν•™μƒμ˜ ν•™λ²ˆμ„ μ •ν™•ν•˜κ²Œ μž…λ ₯ν•˜μ„Έμš”.', style: TextStyle(color: Colors.black54, fontSize: 13), ), const SizedBox(height: 16), TextField( controller: deleteIdController, keyboardType: TextInputType.number, decoration: InputDecoration( labelText: 'ν•™λ²ˆ μž…λ ₯', labelStyle: TextStyle(color: Colors.orange[700]), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), borderSide: BorderSide( color: Colors.orange[700]!, width: 2, ), ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(16), ), prefixIcon: const Icon(Icons.no_accounts_rounded), ), ), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('μ·¨μ†Œ', style: TextStyle(color: Colors.grey)), ), ElevatedButton( onPressed: () { final inputId = deleteIdController.text.trim(); if (inputId.isNotEmpty) { Navigator.pop(context); _deleteStudentAccount(inputId); } }, style: ElevatedButton.styleFrom( backgroundColor: Colors.orange[700], foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: const Text( 'μ‚­μ œ ν™•μ •', style: TextStyle(fontWeight: FontWeight.bold), ), ), ], ); }, ); } @override Widget build(BuildContext context) { return ListenableBuilder( listenable: _controller, builder: (context, _) { return Scaffold( backgroundColor: Colors.grey[100], appBar: AppBar( title: const Text( 'βš™οΈ 학생 톡합 관리 μ„Όν„°', style: TextStyle(fontWeight: FontWeight.bold), ), backgroundColor: Colors.orange, foregroundColor: Colors.white, elevation: 0, ), body: SingleChildScrollView( padding: const EdgeInsets.all(24.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 🏷️ 인디케이터 λ°” 1 (μΆ”κ°€ 메뉴) Row( children: [ Container( width: 4, height: 16, decoration: BoxDecoration( color: Colors.orange, borderRadius: BorderRadius.circular(2), ), ), const SizedBox(width: 8), const Text( 'μ‹ κ·œ 학생 계정 μΆ”κ°€', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), ], ), const SizedBox(height: 16), // πŸ“ 학생 μΆ”κ°€ μ»¨ν…Œμ΄λ„ˆ 폼 Container( 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, ), ], ), child: Column( children: [ TextField( controller: _addIdController, keyboardType: TextInputType.number, decoration: const InputDecoration( labelText: 'ν•™λ²ˆ', prefixIcon: Icon(Icons.badge), ), ), const SizedBox(height: 12), TextField( controller: _addNameController, decoration: const InputDecoration( labelText: '이름', prefixIcon: Icon(Icons.person), ), ), const SizedBox(height: 12), TextField( controller: _addPwController, obscureText: true, decoration: const InputDecoration( labelText: '초기 λΉ„λ°€λ²ˆν˜Έ', prefixIcon: Icon(Icons.lock), ), ), const SizedBox(height: 12), DropdownButtonFormField( initialValue: _selectedGrade, decoration: const InputDecoration( labelText: 'ν•™λ…„ (선택)', prefixIcon: Icon(Icons.class_), ), items: const [ DropdownMenuItem(value: 1, child: Text('1ν•™λ…„')), DropdownMenuItem(value: 2, child: Text('2ν•™λ…„')), DropdownMenuItem(value: 3, child: Text('3ν•™λ…„')), ], onChanged: (value) => setState(() => _selectedGrade = value), ), const SizedBox(height: 20), SizedBox( width: double.infinity, height: 50, child: ElevatedButton( onPressed: _controller.isWorking ? null : _addStudentAccount, style: ElevatedButton.styleFrom( backgroundColor: Colors.orange, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: _controller.isWorking ? const CircularProgressIndicator( color: Colors.white, ) : const Text( '학생 등둝 μ™„λ£Œ', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 15, ), ), ), ), ], ), ), const SizedBox(height: 36), // 🏷️ 인디케이터 λ°” 2 (μ‚­μ œ κΆŒν•œ μ œμ–΄λ©”λ‰΄) Row( children: [ Container( width: 4, height: 16, decoration: BoxDecoration( color: Colors.red, borderRadius: BorderRadius.circular(2), ), ), const SizedBox(width: 8), const Text( 'μœ„ν—˜ ꡬ역 (Account Reset)', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.redAccent, ), ), ], ), const SizedBox(height: 16), // 🚨 학생 μ‚­μ œ 트리거 μΉ΄λ“œ InkWell( onTap: _showDeleteDialog, borderRadius: BorderRadius.circular(24), child: Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.red[50], borderRadius: BorderRadius.circular(24), border: Border.all(color: Colors.red.shade200), ), child: const Row( children: [ Icon( Icons.delete_sweep_rounded, color: Colors.red, size: 32, ), SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '학생 계정 κ°•μ œ 원격 μ‚­μ œ', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.red, ), ), SizedBox(height: 2), Text( '인증 μ΄ˆκΈ°ν™” 및 DB 제거용', style: TextStyle( fontSize: 12, color: Colors.redAccent, ), ), ], ), ), Icon( Icons.arrow_forward_ios_rounded, color: Colors.red, size: 16, ), ], ), ), ), ], ), ), ); }, ); } }