チームまでは表示できた。表示と更新及びメンバー編集不可。エントリー以降も表示不可。

This commit is contained in:
2024-07-27 09:46:00 +09:00
parent c81bcef4bc
commit 08ffc42cdd
24 changed files with 17083 additions and 9 deletions

View File

@ -0,0 +1,11 @@
import 'package:get/get.dart';
import 'package:rogapp/pages/team/member_controller.dart';
import 'package:rogapp/services/api_service.dart';
class MemberBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut<ApiService>(() => ApiService());
Get.lazyPut<MemberController>(() => MemberController());
}
}

View File

@ -0,0 +1,105 @@
// lib/controllers/member_controller.dart
import 'package:get/get.dart';
import 'package:rogapp/model/user.dart';
import 'package:rogapp/services/api_service.dart';
class MemberController extends GetxController {
late final ApiService _apiService;
final int teamId = 0;
final member = Rx<User?>(null);
final email = ''.obs;
final firstname = ''.obs;
final lastname = ''.obs;
final dateOfBirth = Rx<DateTime?>(null);
@override
void onInit() async{
super.onInit();
await Get.putAsync(() => ApiService().init());
_apiService = Get.find<ApiService>();
if (Get.arguments != null && Get.arguments['member'] != null) {
member.value = Get.arguments['member'];
_initializeMemberData();
}
}
void _initializeMemberData() {
if (member.value != null) {
email.value = member.value!.email ?? '';
firstname.value = member.value!.firstname ?? '';
lastname.value = member.value!.lastname ?? '';
dateOfBirth.value = member.value!.dateOfBirth;
}
}
Future<void> createMember(int teamId) async {
try {
final newMember = await _apiService.createTeamMember(
teamId,
email.value,
firstname.value,
lastname.value,
dateOfBirth.value,
);
member.value = newMember;
} catch (e) {
print('Error creating member: $e');
}
}
Future<void> updateMember() async {
if (member.value == null) return;
int? memberId = member.value?.id;
try {
final updatedMember = await _apiService.updateTeamMember(
teamId,
memberId!,
firstname.value,
lastname.value,
dateOfBirth.value,
);
member.value = updatedMember;
} catch (e) {
print('Error updating member: $e');
}
}
Future<void> deleteMember() async {
if (member.value == null) return;
int? memberId = member.value?.id;
try {
await _apiService.deleteTeamMember(teamId,memberId!);
member.value = null;
Get.back();
} catch (e) {
print('Error deleting member: $e');
}
}
Future<void> resendInvitation() async {
if (member.value == null || member.value!.email == null) return;
int? memberId = member.value?.id;
try {
await _apiService.resendMemberInvitation(memberId!);
Get.snackbar('Success', 'Invitation resent successfully');
} catch (e) {
print('Error resending invitation: $e');
Get.snackbar('Error', 'Failed to resend invitation');
}
}
void updateEmail(String value) => email.value = value;
void updateFirstname(String value) => firstname.value = value;
void updateLastname(String value) => lastname.value = value;
void updateDateOfBirth(DateTime value) => dateOfBirth.value = value;
String getMemberStatus() {
if (member.value == null) return '';
if (member.value!.email == null) return '未登録';
if (member.value!.isActive) return '承認済';
return '招待中';
}
}

View File

@ -0,0 +1,55 @@
// lib/pages/team/member_detail_page.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:rogapp/pages/team/member_controller.dart';
class MemberDetailPage extends GetView<MemberController> {
@override
Widget build(BuildContext context) {
final mode = Get.arguments['mode'];
final member = Get.arguments['member'];
return Scaffold(
appBar: AppBar(
title: Text(mode == 'new' ? 'メンバー追加' : 'メンバー詳細'),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (mode == 'edit' && member.email != null)
Text('Email: ${member.email}'),
if (mode == 'new' || (mode == 'edit' && member.email == null))
TextField(
decoration: InputDecoration(labelText: 'Email'),
onChanged: (value) => controller.updateEmail(value),
),
TextField(
decoration: InputDecoration(labelText: ''),
onChanged: (value) => controller.updateLastname(value),
),
TextField(
decoration: InputDecoration(labelText: ''),
onChanged: (value) => controller.updateFirstname(value),
),
// 誕生日選択ウィジェットを追加
if (mode == 'edit')
Text('ステータス: ${controller.getMemberStatus()}'),
if (mode == 'edit' && controller.getMemberStatus() == '招待中')
ElevatedButton(
child: Text('招待メールを再送信'),
onPressed: () => controller.resendInvitation(),
),
if (mode == 'edit')
ElevatedButton(
child: Text('メンバーから除外'),
onPressed: () => controller.deleteMember(),
),
],
),
),
);
}
}

View File

@ -0,0 +1,11 @@
import 'package:get/get.dart';
import 'package:rogapp/pages/team/team_controller.dart';
import 'package:rogapp/services/api_service.dart';
class TeamBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut<ApiService>(() => ApiService());
Get.lazyPut<TeamController>(() => TeamController());
}
}

View File

@ -0,0 +1,117 @@
// lib/controllers/team_controller.dart
import 'package:get/get.dart';
import 'package:rogapp/model/team.dart';
import 'package:rogapp/model/category.dart';
import 'package:rogapp/model/user.dart';
import 'package:rogapp/services/api_service.dart';
class TeamController extends GetxController {
late final ApiService _apiService;
final teams = <Team>[].obs;
final categories = <NewCategory>[].obs;
final teamMembers = <User>[].obs;
final selectedCategory = Rx<NewCategory?>(null);
final currentUser = Rx<User?>(null);
final isLoading = true.obs;
final error = RxString('');
@override
void onInit() async{
super.onInit();
try {
//await Get.putAsync(() => ApiService().init());
_apiService = Get.find<ApiService>();
await Future.wait([
fetchTeams(),
fetchCategories(),
getCurrentUser(),
]);
}catch(e){
print("Team Controller error: $e");
}finally{
isLoading.value = false;
}
}
Future<void> fetchTeams() async {
try {
final fetchedTeams = await _apiService.getTeams();
teams.assignAll(fetchedTeams);
} catch (e) {
print('Error fetching teams: $e');
}
}
Future<void> fetchCategories() async {
try {
final fetchedCategories = await _apiService.getCategories();
categories.assignAll(fetchedCategories);
} catch (e) {
print('Error fetching categories: $e');
}
}
Future<void> getCurrentUser() async {
try {
final user = await _apiService.getCurrentUser();
currentUser.value = user;
} catch (e) {
print('Error getting current user: $e');
}
}
Future<void> createTeam(String teamName, int categoryId) async {
try {
final newTeam = await _apiService.createTeam(teamName, categoryId);
teams.add(newTeam);
} catch (e) {
print('Error creating team: $e');
}
}
Future<void> updateTeam(int teamId, String teamName, int categoryId) async {
try {
final updatedTeam = await _apiService.updateTeam(teamId, teamName, categoryId);
final index = teams.indexWhere((team) => team.id == teamId);
if (index != -1) {
teams[index] = updatedTeam;
}
} catch (e) {
print('Error updating team: $e');
}
}
Future<void> deleteTeam(int teamId) async {
try {
await _apiService.deleteTeam(teamId);
teams.removeWhere((team) => team.id == teamId);
} catch (e) {
print('Error deleting team: $e');
}
}
Future<void> fetchTeamMembers(int teamId) async {
try {
final members = await _apiService.getTeamMembers(teamId);
teamMembers.assignAll(members);
} catch (e) {
print('Error fetching team members: $e');
}
}
void updateTeamName(String value) {
// Update local state
}
void updateCategory(NewCategory? value) {
selectedCategory.value = value;
}
}

View File

@ -0,0 +1,69 @@
// lib/pages/team/team_detail_page.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:rogapp/pages/team/team_controller.dart';
import 'package:rogapp/routes/app_pages.dart';
import 'package:rogapp/services/api_service.dart';
class TeamDetailPage extends GetView<TeamController> {
@override
Widget build(BuildContext context) {
final mode = Get.arguments['mode'];
final team = Get.arguments['team'];
return Scaffold(
appBar: AppBar(
title: Text(mode == 'new' ? '新規チーム作成' : 'チーム詳細'),
actions: [
if (mode == 'edit')
IconButton(
icon: Icon(Icons.add),
onPressed: () => Get.toNamed(AppPages.MEMBER_DETAIL, arguments: {'mode': 'new', 'teamId': team.id}),
),
],
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
decoration: InputDecoration(labelText: 'チーム名'),
onChanged: (value) => controller.updateTeamName(value),
),
DropdownButtonFormField(
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')
Text('ゼッケン番号: ${team.zekkenNumber}'),
Obx(() {
final currentUser = controller.currentUser.value;
return Text('所有者: ${currentUser?.email ?? "未設定"}');
}),
SizedBox(height: 20),
Text('メンバーリスト', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
Expanded(
child: Obx(() => ListView.builder(
itemCount: controller.teamMembers.length,
itemBuilder: (context, index) {
final member = controller.teamMembers[index];
return ListTile(
title: Text('${member.lastname}, ${member.firstname}'),
onTap: () => Get.toNamed(AppPages.MEMBER_DETAIL, arguments: {'mode': 'edit', 'member': member}),
);
},
)),
),
],
),
),
);
}
}

View File

@ -0,0 +1,54 @@
// lib/pages/team/team_list_page.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:rogapp/pages/team/team_controller.dart';
import 'package:rogapp/routes/app_pages.dart';
import 'package:rogapp/services/api_service.dart';
class TeamListPage extends GetView<TeamController> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('チーム管理'),
actions: [
IconButton(
icon: Icon(Icons.add),
onPressed: () => Get.toNamed(AppPages.TEAM_DETAIL, arguments: {'mode': 'new'}),
),
],
),
body: FutureBuilder(
future: Get.putAsync(() => ApiService().init()),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Obx(() {
if (controller.isLoading.value) {
return Center(child: CircularProgressIndicator());
} else if (controller.error.value.isNotEmpty) {
return Center(child: Text('エラー: ${controller.error.value}'));
} else {
return ListView.builder(
itemCount: controller.teams.length,
itemBuilder: (context, index) {
final team = controller.teams[index];
return ListTile(
title: Text(team.teamName),
subtitle: Text('${team.category.categoryName} - ${team.zekkenNumber}'),
trailing: Text('メンバー: (メンバー数表示予定)'),
onTap: () => Get.toNamed(AppPages.TEAM_DETAIL, arguments: {'mode': 'edit', 'team': team}),
);
},
);
}
});
} else {
return Center(child: CircularProgressIndicator());
}
},
),
);
}
}