Team,Member, Entryの登録まで完了

This commit is contained in:
2024-07-29 08:41:28 +09:00
parent 7f8adeea01
commit 9c98d3ed53
10 changed files with 803 additions and 260 deletions

View File

@ -7,21 +7,76 @@ import 'package:rogapp/routes/app_pages.dart';
import 'package:rogapp/model/team.dart';
import 'package:rogapp/model/category.dart';
class TeamDetailPage extends GetView<TeamController> {
class TeamDetailPage extends StatefulWidget {
@override
Widget build(BuildContext context) {
final mode = Get.arguments['mode'] as String;
final team = Get.arguments['team'] as Team?;
_TeamDetailPageState createState() => _TeamDetailPageState();
}
if (mode == 'edit' && team != null) {
controller.setSelectedTeam(team);
class _TeamDetailPageState extends State<TeamDetailPage> {
late TeamController controller;
late TextEditingController _teamNameController = TextEditingController();
final RxString mode = ''.obs;
final Rx<Team?> team = Rx<Team?>(null);
Worker? _teamNameWorker;
@override
void initState() {
super.initState();
controller = Get.find<TeamController>();
_teamNameController = TextEditingController();
WidgetsBinding.instance.addPostFrameCallback((_) {
_initializeData();
});
}
void _initializeData() {
final args = Get.arguments;
if (args != null && args is Map<String, dynamic>) {
mode.value = args['mode'] as String? ?? '';
team.value = args['team'] as Team?;
if (mode.value == 'edit' && team.value != null) {
controller.setSelectedTeam(team.value!);
} else {
controller.resetForm();
}
} else {
// 引数がない場合は新規作成モードとして扱う
mode.value = 'new';
controller.resetForm();
}
_teamNameController.text = controller.teamName.value;
// Use ever instead of direct listener
_teamNameWorker = ever(controller.teamName, (String value) {
if (_teamNameController.text != value) {
_teamNameController.text = value;
}
});
}
@override
void dispose() {
_teamNameWorker?.dispose();
_teamNameController.dispose();
//controller.resetForm(); // Reset the form when leaving the page
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(mode == 'new' ? '新規チーム作成' : 'チーム詳細'),
title: Text(Get.arguments['mode'] == 'new' ? '新規チーム作成' : 'チーム詳細'),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
controller.cleanupForNavigation();
Get.back();
},
),
actions: [
IconButton(
icon: Icon(Icons.save),
@ -34,56 +89,63 @@ class TeamDetailPage extends GetView<TeamController> {
}
},
),
if (mode == 'edit')
IconButton(
icon: Icon(Icons.delete),
onPressed: () async {
try {
await controller.deleteSelectedTeam();
Get.back();
} catch (e) {
Get.snackbar('エラー', e.toString(), snackPosition: SnackPosition.BOTTOM);
}
},
),
Obx(() {
if (mode.value == 'edit') {
return IconButton(
icon: Icon(Icons.delete),
onPressed: () async {
try {
await controller.deleteSelectedTeam();
Get.back();
} catch (e) {
Get.snackbar('エラー', e.toString(), snackPosition: SnackPosition.BOTTOM);
}
},
);
} else {
return SizedBox.shrink();
}
}),
],
),
body: GetBuilder<TeamController>(
builder: (controller) {
if (controller.isLoading.value) {
return Center(child: CircularProgressIndicator());
}
body: Obx(() {
if (controller.isLoading.value) {
return Center(child: CircularProgressIndicator());
}
return SingleChildScrollView(
return SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
initialValue: controller.teamName.value,
decoration: InputDecoration(labelText: 'チーム名'),
onChanged: (value) => controller.updateTeamName(value),
),
SizedBox(height: 16),
DropdownButtonFormField<NewCategory>(
decoration: InputDecoration(labelText: 'カテゴリ'),
value: controller.selectedCategory.value,
items: controller.categories.map((category) => DropdownMenuItem(
value: category,
child: Text(category.categoryName),
)).toList(),
onChanged: (value) => controller.updateCategory(value),
),
if (mode == 'edit')
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Text('ゼッケン番号: ${controller.selectedTeam.value?.zekkenNumber ?? ""}'),
),
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
decoration: InputDecoration(labelText: 'チーム名'),
controller: _teamNameController,
onChanged: (value) => controller.updateTeamName(value),
),
SizedBox(height: 16),
DropdownButtonFormField<NewCategory>(
decoration: InputDecoration(labelText: 'カテゴリ'),
value: controller.selectedCategory.value,
items: controller.categories.map((category) => DropdownMenuItem(
value: category,
child: Text(category.categoryName),
)).toList(),
onChanged: (value) => controller.updateCategory(value),
),
if (mode.value == 'edit')
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Text('所有者: ${controller.currentUser.value?.email ?? "未設定"}'),
child: Text('ゼッケン番号: ${controller.selectedTeam.value?.zekkenNumber ?? ""}'),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Text('所有者: ${controller.currentUser.value?.email ?? "未設定"}'),
),
if (mode.value == 'edit') ...[
SizedBox(height: 24),
Text('メンバーリスト', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
SizedBox(height: 8),
@ -93,34 +155,55 @@ class TeamDetailPage extends GetView<TeamController> {
itemCount: controller.teamMembers.length,
itemBuilder: (context, index) {
final member = controller.teamMembers[index];
final isDummyEmail = member.email?.startsWith('dummy_') ?? false;
final displayName = isDummyEmail
? '${member.lastname} ${member.firstname}'
: member.isActive
? '${member.lastname} ${member.firstname}'
: '${member.email?.split('@')[0] ?? ''}(未承認)';
return ListTile(
title: Text('${member.lastname}, ${member.firstname}'),
onTap: () => Get.toNamed(
AppPages.MEMBER_DETAIL,
arguments: {'mode': 'edit', 'member': member, 'teamId': controller.selectedTeam.value?.id},
),
title: Text(displayName),
subtitle: isDummyEmail ? Text('Email未設定') : null,
onTap: () async {
final result = await Get.toNamed(
AppPages.MEMBER_DETAIL,
arguments: {'mode': 'edit', 'member': member, 'teamId': controller.selectedTeam.value?.id},
);
if (result == true) {
await controller.fetchTeamMembers(controller.selectedTeam.value!.id);
}
},
);
},
),
SizedBox(height: 16),
ElevatedButton(
child: Text('新しいメンバーを追加'),
onPressed: () => Get.toNamed(
AppPages.MEMBER_DETAIL,
arguments: {'mode': 'new', 'teamId': controller.selectedTeam.value?.id},
),
onPressed: () async {
await Get.toNamed(
AppPages.MEMBER_DETAIL,
arguments: {'mode': 'new', 'teamId': controller.selectedTeam.value?.id},
);
if (controller.selectedTeam.value != null) {
controller.fetchTeamMembers(controller.selectedTeam.value!.id);
}
},
),
],
),
],
),
);
},
),
)
);
}),
);
}
}