import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import 'package:superport/models/company_model.dart'; import 'package:superport/models/address_model.dart'; import 'package:superport/screens/common/theme_shadcn.dart'; import 'package:superport/screens/common/templates/form_layout_template.dart'; import 'package:superport/screens/company/controllers/company_form_controller.dart'; import 'package:superport/utils/validators.dart'; import 'package:superport/utils/phone_utils.dart'; /// 회사 등록/수정 화면 /// User/Warehouse Location 화면과 동일한 FormFieldWrapper 패턴 사용 class CompanyFormScreen extends StatefulWidget { final Map? args; const CompanyFormScreen({Key? key, this.args}) : super(key: key); @override State createState() => _CompanyFormScreenState(); } class _CompanyFormScreenState extends State { late CompanyFormController _controller; final TextEditingController _addressController = TextEditingController(); final TextEditingController _phoneNumberController = TextEditingController(); int? companyId; bool isBranch = false; // 전화번호 관련 변수 String _selectedPhonePrefix = '010'; List _phonePrefixes = PhoneUtils.getCommonPhonePrefixes(); @override void initState() { super.initState(); // arguments 처리 final args = widget.args; if (args != null) { companyId = args['companyId']; isBranch = args['isBranch'] ?? false; } _controller = CompanyFormController( companyId: companyId, useApi: true, ); // 수정 모드일 때 데이터 로드 if (companyId != null && !isBranch) { WidgetsBinding.instance.addPostFrameCallback((_) { _controller.loadCompanyData().then((_) { if (mounted) { // 주소 필드 초기화 _addressController.text = _controller.companyAddress.toString(); // 전화번호 분리 초기화 final fullPhone = _controller.contactPhoneController.text; if (fullPhone.isNotEmpty) { _selectedPhonePrefix = PhoneUtils.extractPhonePrefix(fullPhone, _phonePrefixes); _phoneNumberController.text = PhoneUtils.extractPhoneNumberWithoutPrefix(fullPhone, _phonePrefixes); } setState(() {}); } }); }); } } @override void dispose() { _addressController.dispose(); _phoneNumberController.dispose(); _controller.dispose(); super.dispose(); } /// 회사 저장 Future _saveCompany() async { if (!_controller.formKey.currentState!.validate()) { return; } // 주소 업데이트 _controller.updateCompanyAddress( Address.fromFullAddress(_addressController.text) ); // 전화번호 합치기 final fullPhoneNumber = PhoneUtils.getFullPhoneNumber(_selectedPhonePrefix, _phoneNumberController.text); _controller.contactPhoneController.text = fullPhoneNumber; // 로딩 표시 showDialog( context: context, barrierDismissible: false, builder: (context) => const Center(child: CircularProgressIndicator()), ); try { final success = await _controller.saveCompany(); if (mounted) { Navigator.pop(context); // 로딩 다이얼로그 닫기 if (success) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(companyId != null ? '회사 정보가 수정되었습니다.' : '회사가 등록되었습니다.'), backgroundColor: Colors.green, ), ); Navigator.pop(context, true); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('회사 저장에 실패했습니다.'), 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) { final isEditMode = companyId != null; final title = isEditMode ? '회사 정보 수정' : '회사 등록'; return Scaffold( appBar: AppBar(title: Text(title)), body: Padding( padding: const EdgeInsets.all(16.0), child: Form( key: _controller.formKey, child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // 회사 유형 선택 FormFieldWrapper( label: "회사 유형", child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ CheckboxListTile( title: const Text('고객사'), value: _controller.selectedCompanyTypes.contains(CompanyType.customer), onChanged: (checked) { setState(() { _controller.toggleCompanyType(CompanyType.customer, checked ?? false); }); }, contentPadding: EdgeInsets.zero, ), CheckboxListTile( title: const Text('파트너사'), value: _controller.selectedCompanyTypes.contains(CompanyType.partner), onChanged: (checked) { setState(() { _controller.toggleCompanyType(CompanyType.partner, checked ?? false); }); }, contentPadding: EdgeInsets.zero, ), ], ), ), const SizedBox(height: 16), // 회사명 (필수) FormFieldWrapper( label: "회사명 *", 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, ), ), const SizedBox(height: 16), // 주소 (선택) FormFieldWrapper( label: "주소", child: TextFormField( controller: _addressController, decoration: const InputDecoration( hintText: '회사 주소를 입력하세요', border: OutlineInputBorder(), ), maxLines: 2, textInputAction: TextInputAction.next, ), ), const SizedBox(height: 16), // 담당자명 (필수) FormFieldWrapper( label: "담당자명 *", 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, ), ), const SizedBox(height: 16), // 담당자 직급 (선택) FormFieldWrapper( label: "담당자 직급", child: TextFormField( controller: _controller.contactPositionController, decoration: const InputDecoration( hintText: '담당자 직급을 입력하세요', border: OutlineInputBorder(), ), textInputAction: TextInputAction.next, ), ), const SizedBox(height: 16), // 담당자 연락처 (필수) - 사용자 폼과 동일한 패턴 FormFieldWrapper( label: "담당자 연락처 *", 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: _selectedPhonePrefix, items: _phonePrefixes.map((prefix) { return DropdownMenuItem( value: prefix, child: Text(prefix), ); }).toList(), onChanged: (value) { if (value != null) { setState(() { _selectedPhonePrefix = value; }); } }, underline: Container(), // 밑줄 제거 ), ), const SizedBox(width: 8), const Text('-', style: TextStyle(fontSize: 16)), const SizedBox(width: 8), // 전화번호 입력 (7-8자리) Expanded( child: TextFormField( controller: _phoneNumberController, decoration: const InputDecoration( hintText: '1234-5678', border: OutlineInputBorder(), ), keyboardType: TextInputType.phone, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, TextInputFormatter.withFunction((oldValue, newValue) { final formatted = PhoneUtils.formatPhoneNumberByPrefix( _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, ), ), ], ), ), const SizedBox(height: 16), // 담당자 이메일 (필수) FormFieldWrapper( label: "담당자 이메일 *", 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, ), ), const SizedBox(height: 16), // 비고 (선택) FormFieldWrapper( label: "비고", child: TextFormField( controller: _controller.remarkController, decoration: const InputDecoration( hintText: '추가 정보나 메모를 입력하세요', border: OutlineInputBorder(), ), maxLines: 3, textInputAction: TextInputAction.done, ), ), const SizedBox(height: 32), // 저장 버튼 ElevatedButton( onPressed: _saveCompany, style: ElevatedButton.styleFrom( backgroundColor: ShadcnTheme.primary, foregroundColor: Colors.white, minimumSize: const Size.fromHeight(48), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: Text( isEditMode ? '수정 완료' : '등록 완료', style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ), const SizedBox(height: 16), ], ), ), ), ), ); } }