import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:superport/models/company_model.dart'; import 'package:superport/models/user_model.dart'; import 'package:superport/screens/common/theme_tailwind.dart'; import 'package:superport/screens/common/custom_widgets.dart'; import 'package:superport/services/mock_data_service.dart'; import 'package:superport/utils/constants.dart'; import 'package:superport/utils/validators.dart'; import 'package:flutter/services.dart'; import 'package:superport/screens/user/controllers/user_form_controller.dart'; import 'package:superport/models/user_phone_field.dart'; import 'package:superport/screens/common/widgets/company_branch_dropdown.dart'; // 사용자 등록/수정 화면 (UI만 담당, 상태/로직 분리) class UserFormScreen extends StatefulWidget { final int? userId; const UserFormScreen({super.key, this.userId}); @override State createState() => _UserFormScreenState(); } class _UserFormScreenState extends State { final TextEditingController _passwordController = TextEditingController(); final TextEditingController _confirmPasswordController = TextEditingController(); bool _showPassword = false; bool _showConfirmPassword = false; @override void dispose() { _passwordController.dispose(); _confirmPasswordController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (_) => UserFormController( dataService: MockDataService(), userId: widget.userId, ), child: Consumer( builder: (context, controller, child) { return Scaffold( appBar: AppBar( title: Text(controller.isEditMode ? '사용자 수정' : '사용자 등록'), ), body: controller.isLoading ? const Center(child: CircularProgressIndicator()) : Padding( padding: const EdgeInsets.all(16.0), child: Form( key: controller.formKey, child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 이름 _buildTextField( label: '이름', initialValue: controller.name, hintText: '사용자 이름을 입력하세요', validator: (value) => validateRequired(value, '이름'), onSaved: (value) => controller.name = value!, ), // 사용자명 (신규 등록 시만) if (!controller.isEditMode) ...[ _buildTextField( label: '사용자명', initialValue: controller.username, hintText: '로그인에 사용할 사용자명', validator: (value) { if (value == null || value.isEmpty) { return '사용자명을 입력해주세요'; } if (value.length < 3) { return '사용자명은 3자 이상이어야 합니다'; } if (controller.isUsernameAvailable == false) { return '이미 사용 중인 사용자명입니다'; } return null; }, onChanged: (value) { controller.username = value; controller.checkUsernameAvailability(value); }, onSaved: (value) => controller.username = value!, suffixIcon: controller.isCheckingUsername ? const SizedBox( width: 20, height: 20, child: Padding( padding: EdgeInsets.all(12.0), child: CircularProgressIndicator( strokeWidth: 2, ), ), ) : controller.isUsernameAvailable != null ? Icon( controller.isUsernameAvailable! ? Icons.check_circle : Icons.cancel, color: controller.isUsernameAvailable! ? Colors.green : Colors.red, ) : null, ), // 비밀번호 _buildPasswordField( label: '비밀번호', controller: _passwordController, hintText: '비밀번호를 입력하세요', obscureText: !_showPassword, onToggleVisibility: () { setState(() { _showPassword = !_showPassword; }); }, validator: (value) { if (value == null || value.isEmpty) { return '비밀번호를 입력해주세요'; } if (value.length < 6) { return '비밀번호는 6자 이상이어야 합니다'; } return null; }, onSaved: (value) => controller.password = value!, ), // 비밀번호 확인 _buildPasswordField( label: '비밀번호 확인', controller: _confirmPasswordController, hintText: '비밀번호를 다시 입력하세요', obscureText: !_showConfirmPassword, onToggleVisibility: () { setState(() { _showConfirmPassword = !_showConfirmPassword; }); }, validator: (value) { if (value == null || value.isEmpty) { return '비밀번호를 다시 입력해주세요'; } if (value != _passwordController.text) { return '비밀번호가 일치하지 않습니다'; } return null; }, ), ], // 수정 모드에서 비밀번호 변경 (선택사항) if (controller.isEditMode) ...[ ExpansionTile( title: const Text('비밀번호 변경'), children: [ _buildPasswordField( label: '새 비밀번호', controller: _passwordController, hintText: '변경할 경우만 입력하세요', obscureText: !_showPassword, onToggleVisibility: () { setState(() { _showPassword = !_showPassword; }); }, validator: (value) { if (value != null && value.isNotEmpty && value.length < 6) { return '비밀번호는 6자 이상이어야 합니다'; } return null; }, onSaved: (value) => controller.password = value ?? '', ), _buildPasswordField( label: '새 비밀번호 확인', controller: _confirmPasswordController, hintText: '비밀번호를 다시 입력하세요', obscureText: !_showConfirmPassword, onToggleVisibility: () { setState(() { _showConfirmPassword = !_showConfirmPassword; }); }, validator: (value) { if (_passwordController.text.isNotEmpty && value != _passwordController.text) { return '비밀번호가 일치하지 않습니다'; } return null; }, ), ], ), ], // 직급 _buildTextField( label: '직급', initialValue: controller.position, hintText: '직급을 입력하세요', onSaved: (value) => controller.position = value ?? '', ), // 소속 회사/지점 CompanyBranchDropdown( companies: controller.companies, selectedCompanyId: controller.companyId, selectedBranchId: controller.branchId, branches: controller.branches, onCompanyChanged: (value) { controller.companyId = value; controller.branchId = null; if (value != null) { controller.loadBranches(value); } else { controller.branches = []; } }, onBranchChanged: (value) { controller.branchId = value; }, ), // 이메일 _buildTextField( label: '이메일', initialValue: controller.email, hintText: '이메일을 입력하세요', keyboardType: TextInputType.emailAddress, validator: (value) { if (value == null || value.isEmpty) return null; return validateEmail(value); }, onSaved: (value) => controller.email = value ?? '', ), // 전화번호 _buildPhoneFieldsSection(controller), // 권한 _buildRoleRadio(controller), const SizedBox(height: 24), // 오류 메시지 표시 if (controller.error != null) Container( padding: const EdgeInsets.all(12), margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( color: Colors.red.shade50, borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.red.shade200), ), child: Row( children: [ Icon(Icons.error_outline, color: Colors.red.shade700), const SizedBox(width: 8), Expanded( child: Text( controller.error!, style: TextStyle(color: Colors.red.shade700), ), ), ], ), ), // 저장 버튼 SizedBox( width: double.infinity, child: ElevatedButton( onPressed: controller.isLoading ? null : () => _onSaveUser(controller), style: AppThemeTailwind.primaryButtonStyle, child: Padding( padding: const EdgeInsets.all(12.0), child: controller.isLoading ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ) : Text( controller.isEditMode ? '수정하기' : '등록하기', style: const TextStyle(fontSize: 16), ), ), ), ), ], ), ), ), ), ); }, ), ); } // 이름/직급/이메일 등 공통 텍스트 필드 위젯 Widget _buildTextField({ required String label, required String initialValue, required String hintText, TextInputType? keyboardType, List? inputFormatters, String? Function(String?)? validator, void Function(String?)? onSaved, void Function(String)? onChanged, Widget? suffixIcon, }) { return Padding( padding: const EdgeInsets.only(bottom: 16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, style: const TextStyle(fontWeight: FontWeight.bold)), const SizedBox(height: 4), TextFormField( initialValue: initialValue, decoration: InputDecoration( hintText: hintText, suffixIcon: suffixIcon, ), keyboardType: keyboardType, inputFormatters: inputFormatters, validator: validator, onSaved: onSaved, onChanged: onChanged, ), ], ), ); } // 비밀번호 필드 위젯 Widget _buildPasswordField({ required String label, required TextEditingController controller, required String hintText, required bool obscureText, required VoidCallback onToggleVisibility, String? Function(String?)? validator, void Function(String?)? onSaved, }) { return Padding( padding: const EdgeInsets.only(bottom: 16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, style: const TextStyle(fontWeight: FontWeight.bold)), const SizedBox(height: 4), TextFormField( controller: controller, obscureText: obscureText, decoration: InputDecoration( hintText: hintText, suffixIcon: IconButton( icon: Icon( obscureText ? Icons.visibility : Icons.visibility_off, ), onPressed: onToggleVisibility, ), ), validator: validator, onSaved: onSaved, ), ], ), ); } // 전화번호 입력 필드 섹션 위젯 (UserPhoneField 기반) Widget _buildPhoneFieldsSection(UserFormController controller) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('전화번호', style: TextStyle(fontWeight: FontWeight.bold)), const SizedBox(height: 4), ...controller.phoneFields.asMap().entries.map((entry) { final i = entry.key; final phoneField = entry.value; return Row( children: [ // 종류 드롭다운 DropdownButton( value: phoneField.type, items: controller.phoneTypes .map((type) => DropdownMenuItem(value: type, child: Text(type))) .toList(), onChanged: (value) { phoneField.type = value!; }, ), const SizedBox(width: 8), // 번호 입력 Expanded( child: TextFormField( controller: phoneField.controller, keyboardType: TextInputType.phone, decoration: const InputDecoration(hintText: '전화번호'), onSaved: (value) {}, // 값은 controller에서 직접 추출 ), ), IconButton( icon: const Icon(Icons.remove_circle, color: Colors.red), onPressed: controller.phoneFields.length > 1 ? () => controller.removePhoneField(i) : null, ), ], ); }), // 추가 버튼 Align( alignment: Alignment.centerLeft, child: TextButton.icon( onPressed: () => controller.addPhoneField(), icon: const Icon(Icons.add), label: const Text('전화번호 추가'), ), ), ], ); } // 권한(관리등급) 라디오 위젯 Widget _buildRoleRadio(UserFormController controller) { return Padding( padding: const EdgeInsets.only(bottom: 16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('권한', style: TextStyle(fontWeight: FontWeight.bold)), const SizedBox(height: 4), Row( children: [ Expanded( child: RadioListTile( title: const Text('관리자'), value: UserRoles.admin, groupValue: controller.role, onChanged: (value) { controller.role = value!; }, ), ), Expanded( child: RadioListTile( title: const Text('일반 사용자'), value: UserRoles.member, groupValue: controller.role, onChanged: (value) { controller.role = value!; }, ), ), ], ), ], ), ); } // 저장 버튼 클릭 시 사용자 저장 void _onSaveUser(UserFormController controller) async { await controller.saveUser((error) { if (error != null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(error), backgroundColor: Colors.red, ), ); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(controller.isEditMode ? '사용자 정보가 수정되었습니다' : '사용자가 등록되었습니다'), backgroundColor: Colors.green, ), ); Navigator.pop(context, true); } }); } }