h-1.flutter.4/@workspace/lib/widgets/employee_edit_dialog.dart

257 lines
No EOL
9.6 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 従業員編集ダイアログ(リッチ版)
// ※ Employee モデルに特化した編集用ダイアログ
import 'package:flutter/material.dart';
import '../models/employee.dart';
/// 従業員用のリッチな編集ダイアログ
class EmployeeEditDialog extends StatefulWidget {
final String title;
final Employee? initialData; // null = 新規作成
final void Function(Employee) onSave; // 保存コールバック
const EmployeeEditDialog({
super.key,
required this.title,
this.initialData,
required this.onSave,
});
@override
State<EmployeeEditDialog> createState() => _EmployeeEditDialogState();
}
class _EmployeeEditDialogState extends State<EmployeeEditDialog> {
late TextEditingController nameController;
late TextEditingController emailController;
late TextEditingController telController;
late TextEditingController departmentController;
late TextEditingController roleController;
@override
void initState() {
super.initState();
final data = widget.initialData;
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: e.g., '山田太郎',
),
// メールアドレスフィールド
_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: () {
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)),
),
),
],
),
],
),
),
),
);
}
}