import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import 'package:superport/screens/common/theme_shadcn.dart'; import 'package:superport/screens/common/custom_widgets/form_field_wrapper.dart'; import 'package:superport/screens/company/controllers/branch_controller.dart'; import 'package:superport/utils/validators.dart'; import 'package:superport/utils/phone_utils.dart'; /// 지점 관리 화면 (입력/수정 통합) /// User/Warehouse Location 화면과 동일한 FormFieldWrapper 패턴 사용 class BranchFormScreen extends StatefulWidget { final int? branchId; // 수정 모드: 지점 ID, 생성 모드: null final String? parentCompanyName; // 수정 모드: 본사명 (표시용) const BranchFormScreen({ super.key, this.branchId, this.parentCompanyName, }); @override State createState() => _BranchFormScreenState(); } class _BranchFormScreenState extends State { late BranchController _controller; @override void initState() { super.initState(); _controller = BranchController( branchId: widget.branchId, parentCompanyName: widget.parentCompanyName, ); } @override void dispose() { _controller.dispose(); super.dispose(); } /// 지점 저장 Future _saveBranch() async { if (!_controller.formKey.currentState!.validate()) { return; } // 로딩 표시 showDialog( context: context, barrierDismissible: false, builder: (context) => const Center(child: CircularProgressIndicator()), ); try { final success = await _controller.saveBranch(); if (mounted) { Navigator.pop(context); // 로딩 다이얼로그 닫기 if (success) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(_controller.isEditMode ? '지점이 수정되었습니다.' : '지점이 등록되었습니다.'), backgroundColor: Colors.green, ), ); Navigator.pop(context, true); // 성공 시 이전 화면으로 } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(_controller.errorMessage ?? '지점 저장에 실패했습니다.'), backgroundColor: Colors.red, ), ); } } } catch (e) { if (mounted) { Navigator.pop(context); // 로딩 다이얼로그 닫기 ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('오류가 발생했습니다: $e'), backgroundColor: Colors.red, ), ); } } } @override Widget build(BuildContext context) { return ChangeNotifierProvider.value( value: _controller, child: Scaffold( appBar: AppBar( title: Text(_controller.isEditMode ? '${_controller.parentCompanyName} 지점 수정' : '지점 추가'), backgroundColor: ShadcnTheme.background, foregroundColor: ShadcnTheme.foreground, ), body: Consumer( builder: (context, controller, child) { // 로딩 상태 처리 if (controller.isLoadingHeadquarters || (controller.isEditMode && controller.isLoading && controller.originalBranch == null)) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const CircularProgressIndicator(), const SizedBox(height: 16), Text(controller.isEditMode && controller.isLoading ? '지점 정보를 불러오는 중...' : '본사 목록을 불러오는 중...'), ], ), ); } if (controller.headquartersList.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.domain_disabled, size: 64, color: Colors.grey), const SizedBox(height: 16), const Text('등록된 본사가 없습니다'), const SizedBox(height: 8), const Text('먼저 본사를 등록해주세요'), const SizedBox(height: 16), ElevatedButton( onPressed: () => controller.refreshHeadquarters(), child: const Text('새로고침'), ), ], ), ); } return Padding( padding: const EdgeInsets.all(16.0), child: Form( key: controller.formKey, child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // 본사 선택 (필수 - 수정 모드에서는 읽기 전용) FormFieldWrapper( label: "본사 선택", isRequired: true, child: controller.isEditMode ? TextFormField( initialValue: controller.parentCompanyName ?? '본사명 로딩 중...', decoration: const InputDecoration( border: OutlineInputBorder(), enabled: false, // 수정 모드에서는 비활성화 ), style: const TextStyle(color: Colors.grey), ) : DropdownButtonFormField( value: controller.selectedHeadquarterId, decoration: const InputDecoration( hintText: '본사를 선택하세요', border: OutlineInputBorder(), ), items: controller.headquartersList.map((company) { return DropdownMenuItem( value: company.id, child: Text( company.name, overflow: TextOverflow.ellipsis, ), ); }).toList(), onChanged: (value) { if (value != null) { final selectedCompany = controller.headquartersList .firstWhere((company) => company.id == value); controller.selectHeadquarters(value, selectedCompany.name); } }, validator: (value) { if (value == null) { return '본사를 선택하세요'; } return null; }, ), ), // 지점명 (필수) FormFieldWrapper( label: "지점명", isRequired: true, child: TextFormField( controller: controller.nameController, decoration: const InputDecoration( hintText: '지점명을 입력하세요', border: OutlineInputBorder(), ), validator: (value) { if (value == null || value.trim().isEmpty) { return '지점명을 입력하세요'; } if (value.trim().length < 2) { return '지점명은 2자 이상 입력하세요'; } return null; }, textInputAction: TextInputAction.next, ), ), // 주소 (선택) FormFieldWrapper( label: "주소", child: TextFormField( controller: controller.addressController, decoration: const InputDecoration( hintText: '지점 주소를 입력하세요', border: OutlineInputBorder(), ), maxLines: 2, textInputAction: TextInputAction.next, ), ), // 담당자명 (필수) FormFieldWrapper( label: "담당자명", isRequired: true, child: TextFormField( controller: controller.contactNameController, decoration: const InputDecoration( hintText: '담당자명을 입력하세요', border: OutlineInputBorder(), ), validator: (value) { if (value == null || value.trim().isEmpty) { return '담당자명을 입력하세요'; } return null; }, textInputAction: TextInputAction.next, ), ), // 담당자 직급 (선택) FormFieldWrapper( label: "담당자 직급", child: TextFormField( controller: controller.contactPositionController, decoration: const InputDecoration( hintText: '담당자 직급을 입력하세요', border: OutlineInputBorder(), ), textInputAction: TextInputAction.next, ), ), // 담당자 연락처 (필수) - Company 폼과 동일한 패턴 FormFieldWrapper( label: "담당자 연락처", isRequired: true, child: Row( children: [ // 접두사 드롭다운 (010, 02, 031 등) Container( padding: const EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(4), ), child: DropdownButton( value: controller.selectedPhonePrefix, items: controller.phonePrefixes.map((prefix) { return DropdownMenuItem( value: prefix, child: Text(prefix), ); }).toList(), onChanged: (value) { if (value != null) { controller.selectPhonePrefix(value); } }, underline: Container(), // 밑줄 제거 ), ), const SizedBox(width: 8), const Text('-', style: TextStyle(fontSize: 16)), const SizedBox(width: 8), // 전화번호 입력 (7-8자리) Expanded( child: TextFormField( controller: controller.phoneNumberController, decoration: const InputDecoration( hintText: '1234-5678', border: OutlineInputBorder(), ), keyboardType: TextInputType.phone, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, TextInputFormatter.withFunction((oldValue, newValue) { final formatted = PhoneUtils.formatPhoneNumberByPrefix( controller.selectedPhonePrefix, newValue.text, ); return TextEditingValue( text: formatted, selection: TextSelection.collapsed(offset: formatted.length), ); }), ], validator: (value) { if (value == null || value.trim().isEmpty) { return '전화번호를 입력하세요'; } final digitsOnly = value.replaceAll(RegExp(r'[^\d]'), ''); if (digitsOnly.length < 7) { return '전화번호는 7-8자리 숫자를 입력해주세요'; } return null; }, textInputAction: TextInputAction.next, ), ), ], ), ), // 담당자 이메일 (필수) FormFieldWrapper( label: "담당자 이메일", isRequired: true, child: TextFormField( controller: controller.contactEmailController, decoration: const InputDecoration( hintText: 'example@company.com', border: OutlineInputBorder(), ), keyboardType: TextInputType.emailAddress, validator: (value) { if (value == null || value.trim().isEmpty) { return '담당자 이메일을 입력하세요'; } return validateEmail(value); }, textInputAction: TextInputAction.next, ), ), // 비고 (선택) FormFieldWrapper( label: "비고", child: TextFormField( controller: controller.remarkController, decoration: const InputDecoration( hintText: '추가 정보나 메모를 입력하세요', border: OutlineInputBorder(), ), maxLines: 3, textInputAction: TextInputAction.done, ), ), const SizedBox(height: 32), // 저장 버튼 ElevatedButton( onPressed: controller.isSaving ? null : _saveBranch, style: ElevatedButton.styleFrom( backgroundColor: ShadcnTheme.primary, foregroundColor: Colors.white, minimumSize: const Size.fromHeight(48), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: controller.isSaving ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(Colors.white), strokeWidth: 2, ), ) : Text( controller.isEditMode ? '지점 수정' : '지점 등록', style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ), const SizedBox(height: 16), ], ), ), ), ); }, ), ), ); } }