// Version: 1.2 - 従業員編集ダイアログ(簡易実装) import 'package:flutter/material.dart'; import '../models/employee.dart'; /// 従業員用のリッチな編集ダイアログ class EmployeeEditDialog extends StatefulWidget { final String title; final Employee? initialData; // null = 新規作成 /// 保存時のコールバック(Employee のデータを返す) final void Function(Employee)? onSave; const EmployeeEditDialog({ super.key, required this.title, this.initialData, this.onSave, }); @override State createState() => _EmployeeEditDialogState(); } class _EmployeeEditDialogState extends State { late TextEditingController nameController; late TextEditingController emailController; late TextEditingController telController; late TextEditingController departmentController; late TextEditingController roleController; @override void initState() { super.initState(); final data = widget.initialData; if (data == null) { nameController = TextEditingController(text: ''); emailController = TextEditingController(text: ''); telController = TextEditingController(text: ''); departmentController = TextEditingController(text: ''); roleController = TextEditingController(text: ''); } else { nameController = TextEditingController(text: data.name); emailController = TextEditingController(text: data.email); telController = TextEditingController(text: data.tel); departmentController = TextEditingController(text: data.department); roleController = TextEditingController(text: data.role); } } @override void dispose() { nameController.dispose(); emailController.dispose(); telController.dispose(); departmentController.dispose(); roleController.dispose(); super.dispose(); } /// リッチな入力フィールドビルダー(共通) Widget _buildRichTextField( String label, TextEditingController controller, { TextInputType? keyboard, IconData? icon, String hint = '', }) { return Padding( padding: const EdgeInsets.only(bottom: 12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 13, color: Colors.grey.shade700), ), const SizedBox(height: 4), Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( border: Border.all(color: Theme.of(context).dividerColor), borderRadius: BorderRadius.circular(8), ), child: TextField( controller: controller, keyboardType: keyboard, style: const TextStyle(fontSize: 14), decoration: InputDecoration( hintText: hint.isEmpty ? null : hint, prefixIcon: Icon(icon, size: 16, color: Theme.of(context).primaryColor), border: InputBorder.none, contentPadding: EdgeInsets.zero, ), ), ), ], ), ); } @override Widget build(BuildContext context) { return Dialog( backgroundColor: Colors.white, child: Container( constraints: const BoxConstraints(maxWidth: 420), padding: const EdgeInsets.all(16), child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // タイトル Row( children: [ Icon(Icons.person, size: 20, color: Theme.of(context).primaryColor), const SizedBox(width: 8), Expanded(child: Text( widget.title, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), )), IconButton( icon: Icon(Icons.close, color: Colors.grey), onPressed: () => Navigator.pop(context), ), ], ), const SizedBox(height: 12), // ヒントテキスト Center( child: Text( '新規作成の場合は「空白」から入力して OK を押してください', style: TextStyle(fontSize: 12, color: Colors.grey.shade500, fontStyle: FontStyle.italic), ), ), const SizedBox(height: 8), // リッチな編集フォーム Container( decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(12), border: Border.all(color: Theme.of(context).dividerColor), ), padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 基本情報セクション Text( '■ 基本情報', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Theme.of(context).primaryColor, ), ), const SizedBox(height: 8), // 名前フィールド _buildRichTextField( '氏名 *', nameController, keyboard: TextInputType.name, icon: Icons.person, hint: '山田太郎', ), // メールアドレスフィールド _buildRichTextField( 'E メール *', emailController, keyboard: TextInputType.emailAddress, icon: Icons.email, hint: 'example@company.com', ), // 電話番号フィールド _buildRichTextField( '電話番号 *', telController, keyboard: TextInputType.phone, icon: Icons.phone, hint: '03-1234-5678', ), const Divider(), // 部署情報セクション Text( '■ 部署・役職', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Theme.of(context).primaryColor, ), ), const SizedBox(height: 8), // 部門フィールド _buildRichTextField( '部署 *', departmentController, keyboard: TextInputType.text, icon: Icons.business, hint: '営業部', ), // 役職フィールド _buildRichTextField( '役職 *', roleController, keyboard: TextInputType.text, icon: Icons.badge, hint: '営業担当', ), ], ), ), const SizedBox(height: 16), // アクションボタン(Flex で配置) Row( children: [ Expanded( child: OutlinedButton( onPressed: () => Navigator.pop(context), style: OutlinedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 14), ), child: Text(' キャンセル ', textAlign: TextAlign.center, style: TextStyle(fontSize: 15)), ), ), const SizedBox(width: 8), Expanded( flex: 3, // より広いボタン child: ElevatedButton( onPressed: () { if (widget.onSave != null) { final employee = Employee( id: widget.initialData?.id ?? -1, name: nameController.text.isEmpty ? widget.initialData?.name ?? '未入力' : nameController.text, email: emailController.text.isEmpty ? widget.initialData?.email ?? '未入力' : emailController.text, tel: telController.text.isEmpty ? widget.initialData?.tel ?? '未入力' : telController.text, department: departmentController.text.isEmpty ? widget.initialData?.department ?? '未入力' : departmentController.text, role: roleController.text.isEmpty ? widget.initialData?.role ?? '未入力' : roleController.text, ); widget.onSave(employee); } }, style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 14), ), child: Text(' 保存 ', textAlign: TextAlign.center, style: TextStyle(fontSize: 15)), ), ), ], ), ], ), ), ), ); } } /// サンプル従業員選択ダイアログ(簡素版) class EmployeeChoiceDialog extends StatelessWidget { final List employees; final Function(Employee) onSelected; const EmployeeChoiceDialog({super.key, required this.employees, required this.onSelected}); @override Widget build(BuildContext context) { if (employees.isEmpty) return Dialog( child: Padding( padding: const EdgeInsets.all(32), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.search_off, size: 64, color: Colors.grey[300]), const SizedBox(height: 16), Text('検索結果がありません', style: TextStyle(color: Colors.grey, fontSize: 18)), const SizedBox(height: 8), Text('担当者データが登録されていないため\n選択できません', textAlign: TextAlign.center, style: TextStyle(color: Colors.grey.shade500)), ], ), ), ); return Dialog( child: Container( constraints: const BoxConstraints(maxWidth: 400), padding: const EdgeInsets.all(12), child: ListView.separated( shrinkWrap: true, itemCount: employees.length, separatorBuilder: (_, __) => const Divider(height: 1), itemBuilder: (ctx, index) { final employee = employees[index]; return ListTile( contentPadding: EdgeInsets.zero, leading: CircleAvatar( backgroundColor: Theme.of(context).primaryColor.withOpacity(0.1), child: Icon(Icons.person, color: Theme.of(context).primaryColor), ), title: Text( employee.name ?? '未入力', style: const TextStyle(fontWeight: FontWeight.w500), ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (employee.department.isNotEmpty) Text('部署:${employee.department}', style: const TextStyle(fontSize: 12)), if (employee.role.isNotEmpty) Text('役職:${employee.role}', style: const TextStyle(fontSize: 12)), ], ), trailing: employee.email.isNotEmpty ? Text(employee.email, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 10)) : null, onTap: () => onSelected(employee), ); }, ), ), ); } }