Files
rog_app/lib/pages/entry/entry_controller.dart

381 lines
12 KiB
Dart
Raw Permalink Normal View History

// 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';
2024-09-08 21:18:45 +09:00
import 'package:gifunavi/pages/index/index_controller.dart';
import 'package:timezone/timezone.dart' as tz;
2024-09-10 08:12:33 +09:00
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;
2024-09-08 21:18:45 +09:00
final activeEvents = <Event>[].obs; //有効なイベントリスト
2024-09-10 08:12:33 +09:00
final teamMembers = <User>[].obs;
2024-09-10 16:16:04 +09:00
final hasError = false.obs;
final errorMessage = "".obs;
2024-09-10 08:12:33 +09:00
@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');
2024-09-10 16:16:04 +09:00
Get.snackbar('Error', 'APIサービスの初期化に失敗しました');
}
}
Future<void> loadInitialData() async {
try {
isLoading.value = true;
await Future.wait([
fetchEntries(),
fetchEvents(),
fetchTeams(),
fetchCategories(),
]);
2024-09-08 21:18:45 +09:00
updateActiveEvents(); // イベント取得後にアクティブなイベントを更新
if (Get.arguments != null && Get.arguments['entry'] != null) {
currentEntry.value = Get.arguments['entry'];
initializeEditMode(currentEntry.value!);
} else {
// 新規作成モードの場合、最初のイベントを選択
2024-09-10 16:16:04 +09:00
if (activeEvents.isNotEmpty) {
2024-09-08 21:18:45 +09:00
selectedEvent.value = activeEvents.first;
selectedDate.value = activeEvents.first.startDatetime;
}
}
} catch(e) {
print('Error initializing data: $e');
2024-09-10 16:16:04 +09:00
// エラー状態を設定
hasError.value = true;
Get.snackbar('Error', '初期データの読み込みに失敗しました');
} finally {
isLoading.value = false;
}
}
2024-09-08 21:18:45 +09:00
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;
}
}
}
2024-09-10 08:12:33 +09:00
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;
}
}
2024-09-10 08:12:33 +09:00
//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());
2024-09-08 21:18:45 +09:00
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();
2024-09-02 21:25:19 +09:00
// 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,
2024-09-02 21:25:19 +09:00
jstDate, // JSTオフセットが適用された日付を使用
zekkenNumber,
);
entries.add(newEntry);
Get.back();
} catch (e) {
print('Error creating entry: $e');
2024-09-02 21:25:19 +09:00
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
}
}