276 lines
8.1 KiB
Dart
276 lines
8.1 KiB
Dart
// lib/controllers/member_controller.dart
|
||
|
||
import 'package:get/get.dart';
|
||
import 'package:rogapp/model/user.dart';
|
||
import 'package:rogapp/pages/team/team_controller.dart';
|
||
import 'package:rogapp/services/api_service.dart';
|
||
|
||
class MemberController extends GetxController {
|
||
late final ApiService _apiService;
|
||
|
||
final selectedMember = Rx<User?>(null);
|
||
int teamId = 0;
|
||
final member = Rx<User?>(null);
|
||
final email = ''.obs;
|
||
final firstname = ''.obs;
|
||
final lastname = ''.obs;
|
||
final female = false.obs;
|
||
final dateOfBirth = Rx<DateTime?>(null);
|
||
final isLoading = false.obs; // isLoadingプロパティを追加
|
||
final isActive = false.obs;
|
||
|
||
//MemberController(this._apiService);
|
||
|
||
@override
|
||
void onInit() {
|
||
super.onInit();
|
||
_apiService = Get.find<ApiService>();
|
||
ever(member, (_) => _initializeMemberData());
|
||
loadInitialData();
|
||
}
|
||
|
||
bool get isDummyEmail => email.value.startsWith('dummy_');
|
||
bool get isApproved => !email.value.startsWith('dummy_') && member.value?.isActive == true;
|
||
|
||
Future<void> loadInitialData() async {
|
||
try {
|
||
isLoading.value = true;
|
||
if (Get.arguments != null) {
|
||
if (Get.arguments['member'] != null) {
|
||
member.value = Get.arguments['member'];
|
||
}
|
||
if (Get.arguments['teamId'] != null) {
|
||
teamId = Get.arguments['teamId'];
|
||
}
|
||
}
|
||
// 他の必要な初期データの取得をここで行う
|
||
} catch (e) {
|
||
print('Error loading initial data: $e');
|
||
} finally {
|
||
isLoading.value = false;
|
||
}
|
||
}
|
||
|
||
|
||
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;
|
||
}
|
||
}
|
||
|
||
|
||
void setSelectedMember(User member) {
|
||
this.member.value = member;
|
||
email.value = member.email ?? '';
|
||
firstname.value = member.firstname ?? '';
|
||
lastname.value = member.lastname ?? '';
|
||
dateOfBirth.value = member.dateOfBirth;
|
||
female.value = member.female ?? false;
|
||
isActive.value = member.isActive ?? false;
|
||
}
|
||
|
||
bool _validateInputs() {
|
||
if (email.value.isNotEmpty && !isDummyEmail) {
|
||
return true; // Emailのみの場合は有効
|
||
}
|
||
if (firstname.value.isEmpty || lastname.value.isEmpty || dateOfBirth.value == null || female.value == null) {
|
||
Get.snackbar('エラー', 'Emailが空の場合、姓名と生年月日及び性別は必須です', snackPosition: SnackPosition.BOTTOM);
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
void updateFirstName(String value) {
|
||
firstname.value = value;
|
||
}
|
||
|
||
void updateLastName(String value) {
|
||
lastname.value = value;
|
||
}
|
||
|
||
|
||
Future<bool> saveMember() async {
|
||
if (!_validateInputs()) return false;
|
||
|
||
try {
|
||
isLoading.value = true;
|
||
User updatedMember;
|
||
if (member.value == null || member.value!.id == null) {
|
||
// 新規メンバー作成
|
||
updatedMember = await _apiService.createTeamMember(
|
||
teamId,
|
||
isDummyEmail ? null : email.value, // dummy_メールの場合はnullを送信
|
||
firstname.value,
|
||
lastname.value,
|
||
dateOfBirth.value,
|
||
female.value,
|
||
);
|
||
} else {
|
||
// 既存メンバー更新
|
||
updatedMember = await _apiService.updateTeamMember(
|
||
teamId,
|
||
member.value!.id!,
|
||
firstname.value,
|
||
lastname.value,
|
||
dateOfBirth.value,
|
||
female.value,
|
||
);
|
||
}
|
||
member.value = updatedMember;
|
||
Get.snackbar('成功', 'メンバーが保存されました', snackPosition: SnackPosition.BOTTOM);
|
||
return true;
|
||
} catch (e) {
|
||
print('Error saving member: $e');
|
||
Get.snackbar('エラー', 'メンバーの保存に失敗しました: ${e.toString()}', snackPosition: SnackPosition.BOTTOM);
|
||
return false;
|
||
} finally {
|
||
isLoading.value = false;
|
||
}
|
||
}
|
||
|
||
|
||
String getDisplayName() {
|
||
if (!isActive.value && !isDummyEmail) {
|
||
final displayName = email.value.split('@')[0];
|
||
return '$displayName(未承認)';
|
||
}
|
||
return '${lastname.value} ${firstname.value}'.trim();
|
||
}
|
||
|
||
Future<bool> updateMember() async {
|
||
if (member.value == null) return false;
|
||
int? memberId = member.value?.id;
|
||
try {
|
||
final updatedMember = await _apiService.updateTeamMember(
|
||
teamId,
|
||
memberId!,
|
||
firstname.value,
|
||
lastname.value,
|
||
dateOfBirth.value,
|
||
female.value,
|
||
);
|
||
member.value = updatedMember;
|
||
return true;
|
||
} catch (e) {
|
||
print('Error updating member: $e');
|
||
return false;
|
||
}
|
||
}
|
||
|
||
Future<bool> deleteMember() async {
|
||
if (member.value == null || member.value!.id == null) {
|
||
Get.snackbar('エラー', 'メンバー情報が不正です', snackPosition: SnackPosition.BOTTOM);
|
||
return false;
|
||
}
|
||
|
||
try {
|
||
isLoading.value = true;
|
||
await _apiService.deleteTeamMember(teamId, member.value!.id!);
|
||
Get.snackbar('成功', 'メンバーが削除されました', snackPosition: SnackPosition.BOTTOM);
|
||
member.value = null;
|
||
isLoading.value = false;
|
||
return true;
|
||
|
||
} catch (e) {
|
||
print('Error deleting member: $e');
|
||
Get.snackbar('エラー', 'メンバーの削除に失敗しました: ${e.toString()}', snackPosition: SnackPosition.BOTTOM);
|
||
isLoading.value = false;
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/*
|
||
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 (isDummyEmail) {
|
||
Get.snackbar('エラー', 'ダミーメールアドレスには招待メールを送信できません', snackPosition: SnackPosition.BOTTOM);
|
||
return;
|
||
}
|
||
|
||
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 '招待中';
|
||
}
|
||
|
||
int calculateAge() {
|
||
if (dateOfBirth.value == null) return 0;
|
||
final today = DateTime.now();
|
||
int age = today.year - dateOfBirth.value!.year;
|
||
if (today.month < dateOfBirth.value!.month ||
|
||
(today.month == dateOfBirth.value!.month && today.day < dateOfBirth.value!.day)) {
|
||
age--;
|
||
}
|
||
return age;
|
||
}
|
||
|
||
String calculateGrade() {
|
||
if (dateOfBirth.value == null) return '不明';
|
||
|
||
final today = DateTime.now();
|
||
final birthDate = dateOfBirth.value!;
|
||
|
||
// 今年の4月1日
|
||
final thisYearSchoolStart = DateTime(today.year, 4, 1);
|
||
|
||
// 生まれた年の翌年の4月1日(学齢期の始まり)
|
||
final schoolStartDate = DateTime(birthDate.year + 1, 4, 1);
|
||
|
||
// 学齢期の開始からの年数
|
||
int yearsFromSchoolStart = today.year - schoolStartDate.year;
|
||
|
||
// 今年の4月1日より前なら1年引く
|
||
if (today.isBefore(thisYearSchoolStart)) {
|
||
yearsFromSchoolStart--;
|
||
}
|
||
|
||
if (yearsFromSchoolStart < 7) return '未就学';
|
||
if (yearsFromSchoolStart < 13) return '小${yearsFromSchoolStart - 6}';
|
||
if (yearsFromSchoolStart < 16) return '中${yearsFromSchoolStart - 12}';
|
||
if (yearsFromSchoolStart < 19) return '高${yearsFromSchoolStart - 15}';
|
||
return '成人';
|
||
}
|
||
|
||
String getAgeAndGrade() {
|
||
final age = calculateAge();
|
||
final grade = calculateGrade();
|
||
return '$age歳/$grade';
|
||
}
|
||
|
||
bool isOver18() {
|
||
return calculateAge() >= 18;
|
||
}
|
||
} |