Files
rog_app/lib/pages/entry/entry_controller.dart
2024-09-10 08:12:33 +09:00

377 lines
12 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.

// lib/entry/entry_controller.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:gifunavi/model/entry.dart';
import 'package:gifunavi/model/event.dart';
import 'package:gifunavi/model/team.dart';
import 'package:gifunavi/model/category.dart';
import 'package:gifunavi/services/api_service.dart';
import 'package:gifunavi/pages/index/index_controller.dart';
import 'package:timezone/timezone.dart' as tz;
import '../../model/user.dart';
class EntryController extends GetxController {
late ApiService _apiService;
final entries = <Entry>[].obs;
final events = <Event>[].obs;
final teams = <Team>[].obs;
final categories = <NewCategory>[].obs;
final selectedEvent = Rx<Event?>(null);
final selectedTeam = Rx<Team?>(null);
final selectedCategory = Rx<NewCategory?>(null);
final selectedDate = Rx<DateTime?>(null);
final currentEntry = Rx<Entry?>(null);
final isLoading = true.obs;
final activeEvents = <Event>[].obs; //有効なイベントリスト
final teamMembers = <User>[].obs;
@override
void onInit() async {
super.onInit();
await initializeApiService();
await loadInitialData();
}
Future<void> initializeApiService() async {
try {
_apiService = await Get.putAsync(() => ApiService().init());
} catch (e) {
print('Error initializing ApiService: $e');
Get.snackbar('Error', 'Failed to initialize API service');
}
}
Future<void> loadInitialData() async {
try {
isLoading.value = true;
await Future.wait([
fetchEntries(),
fetchEvents(),
fetchTeams(),
fetchCategories(),
]);
updateActiveEvents(); // イベント取得後にアクティブなイベントを更新
if (Get.arguments != null && Get.arguments['entry'] != null) {
currentEntry.value = Get.arguments['entry'];
initializeEditMode(currentEntry.value!);
} else {
// 新規作成モードの場合、最初のイベントを選択
if (events.isNotEmpty) {
selectedEvent.value = activeEvents.first;
selectedDate.value = activeEvents.first.startDatetime;
}
}
} catch(e) {
print('Error initializing data: $e');
Get.snackbar('Error', 'Failed to load initial data');
} finally {
isLoading.value = false;
}
}
void updateActiveEvents() {
final now = tz.TZDateTime.now(tz.getLocation('Asia/Tokyo'));
activeEvents.assignAll(events.where((event) => event.deadlineDateTime.isAfter(now)));
}
void initializeEditMode(Entry entry) {
currentEntry.value = entry;
selectedEvent.value = entry.event;
selectedTeam.value = entry.team;
selectedCategory.value = entry.category;
selectedDate.value = entry.date;
}
void updateEvent(Event? value) {
selectedEvent.value = value;
if (value != null) {
// イベント変更時に日付を調整
if (selectedDate.value == null ||
selectedDate.value!.isBefore(value.startDatetime) ||
selectedDate.value!.isAfter(value.endDatetime)) {
selectedDate.value = value.startDatetime;
}
}
}
Future<void> fetchTeamMembers(int teamId) async {
try {
final members = await _apiService.getTeamMembers(teamId);
teamMembers.assignAll(members);
} catch (e) {
print('Error fetching team members: $e');
Get.snackbar('Error', 'Failed to fetch team members');
}
}
List<NewCategory> getFilteredCategories() {
if (selectedTeam.value == null) return [];
if (teamMembers.isEmpty) {
// ソロの場合
String baseCategory = selectedTeam.value!.members.first.female ? 'ソロ女子' : 'ソロ男子';
return categories.where((c) => c.categoryName.startsWith(baseCategory)).toList();
} else if (teamMembers.length == 1) {
// チームメンバーが1人の場合ソロ
String baseCategory = teamMembers.first.female ? 'ソロ女子' : 'ソロ男子';
return categories.where((c) => c.categoryName.startsWith(baseCategory)).toList();
} else {
// 複数人の場合
bool hasElementaryOrYounger = teamMembers.any(isElementarySchoolOrYounger);
String baseCategory = hasElementaryOrYounger ? 'ファミリー' : '一般';
return categories.where((c) => c.categoryName.startsWith(baseCategory)).toList();
}
}
bool isElementarySchoolOrYounger(User user) {
final now = DateTime.now();
final age = now.year - user.dateOfBirth!.year;
return age <= 12;
}
void updateTeam(Team? value) async {
selectedTeam.value = value;
if (value != null) {
await fetchTeamMembers(value.id);
final filteredCategories = getFilteredCategories();
if (filteredCategories.isNotEmpty) {
selectedCategory.value = filteredCategories.first;
} else {
selectedCategory.value = null;
}
} else {
teamMembers.clear();
selectedCategory.value = null;
}
}
void updateTeam_old(Team? value) {
selectedTeam.value = value;
if (value != null) {
selectedCategory.value = value.category;
}
}
//void updateTeam(Team? value) => selectedTeam.value = value;
void updateCategory(NewCategory? value) => selectedCategory.value = value;
//void updateDate(DateTime value) => selectedDate.value = value;
void updateDate(DateTime value) {
selectedDate.value = tz.TZDateTime.from(value, tz.getLocation('Asia/Tokyo'));
}
/*
void updateDate(DateTime value){
selectedDate.value = DateFormat('yyyy-MM-dd').format(value!) as DateTime?;
}
*/
void _initializeEntryData() {
if (currentEntry.value != null) {
selectedEvent.value = currentEntry.value!.event;
selectedTeam.value = currentEntry.value!.team;
selectedCategory.value = currentEntry.value!.category;
selectedDate.value = currentEntry.value!.date;
}
}
Future<void> fetchEntries() async {
try {
final fetchedEntries = await _apiService.getEntries();
entries.assignAll(fetchedEntries);
} catch (e) {
print('Error fetching entries: $e');
Get.snackbar('Error', 'Failed to fetch entries');
}
}
Future<void> fetchEvents() async {
try {
final fetchedEvents = await _apiService.getEvents();
events.assignAll(fetchedEvents.map((event) {
// end_dateの7日前を締め切りとして設定
final deadlineDateTime = event.endDatetime.subtract(const Duration(days: 7));
return Event(
id: event.id,
eventName: event.eventName,
startDatetime: event.startDatetime,
endDatetime: event.endDatetime,
deadlineDateTime: deadlineDateTime,
);
}).toList());
updateActiveEvents();
} catch (e) {
print('Error fetching events: $e');
Get.snackbar('Error', 'Failed to fetch events');
}
}
Future<void> fetchEvents_old() async {
try {
final fetchedEvents = await _apiService.getEvents();
events.assignAll(fetchedEvents);
} catch (e) {
print('Error fetching events: $e');
Get.snackbar('Error', 'Failed to fetch events');
}
}
Future<void> fetchTeams() async {
try {
final fetchedTeams = await _apiService.getTeams();
teams.assignAll(fetchedTeams);
} catch (e) {
print('Error fetching teams: $e');
Get.snackbar('Error', 'Failed to fetch team');
}
}
Future<void> fetchCategories() async {
try {
final fetchedCategories = await _apiService.getCategories();
categories.assignAll(fetchedCategories);
} catch (e) {
print('Error fetching categories: $e');
Get.snackbar('Error', 'Failed to fetch categories');
}
}
Future<void> createEntry() async {
if (selectedEvent.value == null || selectedTeam.value == null ||
selectedCategory.value == null || selectedDate.value == null) {
Get.snackbar('Error', 'Please fill all fields');
return;
}
try {
isLoading.value = true;
// Get zekken number
final updatedCategory = await _apiService.getZekkenNumber(selectedCategory.value!.id);
final zekkenNumber = updatedCategory.categoryNumber.toString();
// selectedDate.value に 9時間を加えてJSTのオフセットを適用
final jstDate = selectedDate.value!.add(const Duration(hours: 9));
final newEntry = await _apiService.createEntry(
selectedTeam.value!.id,
selectedEvent.value!.id,
selectedCategory.value!.id,
jstDate, // JSTオフセットが適用された日付を使用
zekkenNumber,
);
entries.add(newEntry);
Get.back();
} catch (e) {
print('Error creating entry: $e');
Get.snackbar('Error', '$e');
} finally {
isLoading.value = false;
}
}
Future<void> updateEntryAndRefreshMap() async {
await updateEntry();
// エントリーが正常に更新された後、マップをリフレッシュ
final indexController = Get.find<IndexController>();
final eventCode = currentEntry.value?.event.eventName ?? '';
indexController.reloadMap(eventCode);
}
bool isEntryEditable(Event event) {
return DateTime.now().isBefore(event.deadlineDateTime);
}
Future<void> updateEntry() async {
if (currentEntry.value == null) {
Get.snackbar('Error', 'No entry selected for update');
return;
}
if (!isEntryEditable(currentEntry.value!.event)) {
Get.dialog(
AlertDialog(
title: Text('エントリー変更不可'),
content: Text('締め切りを過ぎているため、エントリーの変更はできません。変更が必要な場合は事務局にお問い合わせください。'),
actions: [
TextButton(
child: Text('OK'),
onPressed: () => Get.back(),
),
],
),
);
return;
}
try {
isLoading.value = true;
final updatedEntry = await _apiService.updateEntry(
currentEntry.value!.id,
currentEntry.value!.team.id,
selectedEvent.value!.id,
selectedCategory.value!.id,
selectedDate.value!,
currentEntry.value!.zekkenNumber,
);
final index = entries.indexWhere((entry) => entry.id == updatedEntry.id);
if (index != -1) {
entries[index] = updatedEntry;
}
Get.back();
} catch (e) {
print('Error updating entry: $e');
Get.snackbar('Error', 'Failed to update entry');
} finally {
isLoading.value = false;
}
}
Future<void> updateEntryCategory(int entryId, int newCategoryId) async {
try {
//await _apiService.updateEntryCategory(entryId, newCategoryId);
final updatedEntry = await _apiService.updateEntry(
currentEntry.value!.id,
currentEntry.value!.team.id,
selectedEvent.value!.id,
newCategoryId,
currentEntry.value!.date!,
currentEntry.value!.zekkenNumber,
);
await fetchEntries();
} catch (e) {
print('Error updating entry category: $e');
Get.snackbar('エラー', 'エントリーのカテゴリ更新に失敗しました');
}
}
Future<void> deleteEntry() async {
if (currentEntry.value == null) {
Get.snackbar('Error', 'No entry selected for deletion');
return;
}
try {
isLoading.value = true;
await _apiService.deleteEntry(currentEntry.value!.id);
entries.removeWhere((entry) => entry.id == currentEntry.value!.id);
Get.back();
} catch (e) {
print('Error deleting entry: $e');
Get.snackbar('Error', 'Failed to delete entry');
} finally {
isLoading.value = false;
}
}
bool isOwner() {
// Implement logic to check if the current user is the owner of the entry
return true; // Placeholder
}
}