From 3d7a5ae0c14911568d477b7bcdf48384edd69c07 Mon Sep 17 00:00:00 2001 From: Akira Date: Tue, 30 Jul 2024 02:15:04 +0900 Subject: [PATCH] Fix all features --- .../destination/destination_controller.dart | 4 +- .../destination_map/destination_map_page.dart | 2 +- lib/pages/drawer/drawer_page.dart | 44 +++--- lib/pages/entry/event_entries_binding.dart | 9 ++ lib/pages/entry/event_entries_controller.dart | 48 +++++++ lib/pages/entry/event_entries_page.dart | 23 ++++ lib/pages/index/index_controller.dart | 32 ++++- lib/routes/app_pages.dart | 10 ++ lib/routes/app_routes.dart | 2 + lib/services/api_service.dart | 37 +++++ lib/services/location_service.dart | 126 +++++++++++------- 11 files changed, 268 insertions(+), 69 deletions(-) create mode 100644 lib/pages/entry/event_entries_binding.dart create mode 100644 lib/pages/entry/event_entries_controller.dart create mode 100644 lib/pages/entry/event_entries_page.dart diff --git a/lib/pages/destination/destination_controller.dart b/lib/pages/destination/destination_controller.dart index 33884a0..85a0ca5 100644 --- a/lib/pages/destination/destination_controller.dart +++ b/lib/pages/destination/destination_controller.dart @@ -1628,7 +1628,7 @@ class DestinationController extends GetxController { // 地図のイベントリスナーを設定 indexController.mapController.mapEventStream.listen((MapEvent mapEvent) { if (mapEvent is MapEventMoveEnd) { - indexController.loadLocationsBound(); + indexController.loadLocationsBound(indexController.currentUser[0]["user"]["event_code"]); } }); @@ -1653,7 +1653,7 @@ class DestinationController extends GetxController { ); indexController.currentBound.clear(); indexController.currentBound.add(bnds); - indexController.loadLocationsBound(); + indexController.loadLocationsBound(indexController.currentUser[0]["user"]["event_code"]); centerMapToCurrentLocation(); } }); diff --git a/lib/pages/destination_map/destination_map_page.dart b/lib/pages/destination_map/destination_map_page.dart index fbd5118..660c6ca 100644 --- a/lib/pages/destination_map/destination_map_page.dart +++ b/lib/pages/destination_map/destination_map_page.dart @@ -170,7 +170,7 @@ class DestinationMapPage extends StatelessWidget { indexController.currentBound.clear(); indexController.currentBound.add(bounds); if (indexController.currentUser.isEmpty) { - indexController.loadLocationsBound(); + indexController.loadLocationsBound(indexController.currentUser[0]["user"]["event_code"]); } } }); diff --git a/lib/pages/drawer/drawer_page.dart b/lib/pages/drawer/drawer_page.dart index 04e830c..bdacdb9 100644 --- a/lib/pages/drawer/drawer_page.dart +++ b/lib/pages/drawer/drawer_page.dart @@ -79,6 +79,33 @@ class DrawerPage extends StatelessWidget { ), )), ), + + ListTile( + leading: Icon(Icons.group), + title: Text('チーム管理'), + onTap: () { + Get.back(); + Get.toNamed(AppPages.TEAM_LIST); + }, + ), + ListTile( + leading: Icon(Icons.event), + title: Text('エントリー管理'), + onTap: () { + Get.back(); + Get.toNamed(AppPages.ENTRY_LIST); + }, + ), + ListTile( + leading: Icon(Icons.event), + title: Text('イベント参加'), + onTap: () { + Get.back(); // ドロワーを閉じる + Get.toNamed(AppPages.EVENT_ENTRY); + }, + ), + + Obx(() => indexController.currentUser.isEmpty ? ListTile( leading: const Icon(Icons.login), @@ -206,22 +233,7 @@ class DrawerPage extends StatelessWidget { width: 0, height: 0, ), - ListTile( - leading: Icon(Icons.group), - title: Text('チーム管理'), - onTap: () { - Get.back(); - Get.toNamed(AppPages.TEAM_LIST); - }, - ), - ListTile( - leading: Icon(Icons.event), - title: Text('エントリー管理'), - onTap: () { - Get.back(); - Get.toNamed(AppPages.ENTRY_LIST); - }, - ), + ListTile( leading: const Icon(Icons.privacy_tip), title: Text("privacy".tr), diff --git a/lib/pages/entry/event_entries_binding.dart b/lib/pages/entry/event_entries_binding.dart new file mode 100644 index 0000000..b06049a --- /dev/null +++ b/lib/pages/entry/event_entries_binding.dart @@ -0,0 +1,9 @@ +import 'package:get/get.dart'; +import 'package:rogapp/pages/entry/event_entries_controller.dart'; + +class EventEntriesBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut(() => EventEntriesController()); + } +} diff --git a/lib/pages/entry/event_entries_controller.dart b/lib/pages/entry/event_entries_controller.dart new file mode 100644 index 0000000..78df60e --- /dev/null +++ b/lib/pages/entry/event_entries_controller.dart @@ -0,0 +1,48 @@ +import 'package:get/get.dart'; +import 'package:rogapp/model/entry.dart'; +import 'package:rogapp/pages/index/index_controller.dart'; +import 'package:rogapp/services/api_service.dart'; + +class EventEntriesController extends GetxController { + final ApiService _apiService = Get.find(); + final IndexController _indexController = Get.find(); + + final entries = [].obs; + + @override + void onInit() { + super.onInit(); + fetchEntries(); + } + + Future fetchEntries() async { + try { + final fetchedEntries = await _apiService.getEntries(); + entries.assignAll(fetchedEntries); + } catch (e) { + print('Error fetching entries: $e'); + // エラー処理を追加 + } + } + + Future joinEvent(Entry entry) async { + try { + + final userid = _indexController.currentUser[0]["user"]["id"]; + + await _apiService.updateUserInfo(userid,entry); + + _indexController.currentUser[0]["user"]["event_code"] = entry.event.eventName; + _indexController.currentUser[0]["user"]["team_name"] = entry.team.teamName; + _indexController.currentUser[0]["user"]["group"] = entry.team.category.categoryName; + _indexController.currentUser[0]["user"]["zekken_number"] = entry.team.zekkenNumber; + + Get.back(); // エントリー一覧ページを閉じる + //_indexController.isLoading.value = true; + _indexController.reloadMap(entry.event.eventName); // マップをリロード + } catch (e) { + print('Error joining event: $e'); + // エラー処理を追加 + } + } +} \ No newline at end of file diff --git a/lib/pages/entry/event_entries_page.dart b/lib/pages/entry/event_entries_page.dart new file mode 100644 index 0000000..c302ef4 --- /dev/null +++ b/lib/pages/entry/event_entries_page.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:rogapp/pages/entry/event_entries_controller.dart'; + +class EventEntriesPage extends GetView { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('イベント参加')), + body: Obx(() => ListView.builder( + itemCount: controller.entries.length, + itemBuilder: (context, index) { + final entry = controller.entries[index]; + return ListTile( + title: Text(entry.event.eventName), + subtitle: Text('${entry.category.categoryName} - ${entry.date}'), + onTap: () => controller.joinEvent(entry), + ); + }, + )), + ); + } +} \ No newline at end of file diff --git a/lib/pages/index/index_controller.dart b/lib/pages/index/index_controller.dart index baad28b..d9c4b62 100644 --- a/lib/pages/index/index_controller.dart +++ b/lib/pages/index/index_controller.dart @@ -10,6 +10,7 @@ import 'package:geolocator/geolocator.dart'; import 'package:get/get.dart'; import 'package:latlong2/latlong.dart'; import 'package:rogapp/model/destination.dart'; +import 'package:rogapp/model/entry.dart'; import 'package:rogapp/pages/destination/destination_controller.dart'; import 'package:rogapp/routes/app_pages.dart'; import 'package:rogapp/services/auth_service.dart'; @@ -59,6 +60,9 @@ class IndexController extends GetxController with WidgetsBindingObserver { String? userToken; + //late final ApiService _apiService; + final ApiService _apiService = Get.find(); + // mode = 0 is map mode, mode = 1 list mode var mode = 0.obs; @@ -79,6 +83,16 @@ class IndexController extends GetxController with WidgetsBindingObserver { final Connectivity _connectivity = Connectivity(); late StreamSubscription _connectivitySubscription; + final Rx lastUserUpdateTime = DateTime.now().obs; + + /* + void updateUserInfo(Map newUserInfo) { + currentUser.clear(); + currentUser.add(newUserInfo); + lastUserUpdateTime.value = DateTime.now(); + } + */ + void toggleMode() { if (mode.value == 0) { mode += 1; @@ -202,6 +216,7 @@ class IndexController extends GetxController with WidgetsBindingObserver { if (currentUser.isNotEmpty) { // 既にログインしている場合 await Get.putAsync(() => ApiService().init()); + //await Get.putAsync(() => ApiService().init()); // 必要に応じて追加の初期化処理 } } @@ -492,7 +507,7 @@ class IndexController extends GetxController with WidgetsBindingObserver { saveToDevice(currentUser[0]["token"]); } isLoading.value = false; - loadLocationsBound(); + loadLocationsBound( currentUser[0]["user"]["even_code"]); if (currentUser.isNotEmpty) { rogMode.value = 0; restoreGame(); @@ -577,7 +592,7 @@ class IndexController extends GetxController with WidgetsBindingObserver { // 要検討:Future.delayedを使用して非同期処理を待たずに先に進むようにしていますが、 // これによってメモリリークが発生する可能性があります。非同期処理の結果を適切に処理することを検討してください。 // - void loadLocationsBound() async { + void loadLocationsBound(String eventCode) async { if (isCustomAreaSelected.value == true) { return; } @@ -609,12 +624,13 @@ class IndexController extends GetxController with WidgetsBindingObserver { currentBound.clear(); currentBound.add(bounds); - isLoading.value = true; // ローディング状態をtrueに設定 + //isLoading.value = true; // ローディング状態をtrueに設定 //print("bounds --- (${bounds.southWest.latitude},${bounds.southWest.longitude}),(${bounds.northWest.latitude},${bounds.northWest.longitude}),(${bounds.northEast.latitude},${bounds.northEast.longitude}),(${bounds.southEast.latitude},${bounds.southEast.longitude})"); // 要検討:APIからのレスポンスがnullの場合のエラーハンドリングが不十分です。適切なエラーメッセージを表示するなどの処理を追加してください。 try { + final eventCode = currentUser[0]["user"]["event_code"]; final value = await LocationService.loadLocationsBound( bounds.southWest.latitude, bounds.southWest.longitude, @@ -624,7 +640,8 @@ class IndexController extends GetxController with WidgetsBindingObserver { bounds.northEast.longitude, bounds.southEast.latitude, bounds.southEast.longitude, - cat + cat, + eventCode ); /* if (value == null) { @@ -728,4 +745,11 @@ class IndexController extends GetxController with WidgetsBindingObserver { } return null; } + + + void reloadMap( String eventCode ) { + // マップをリロードするロジックを実装 + // 例: 現在の位置情報を再取得し、マップを更新する + loadLocationsBound( eventCode ); + } } diff --git a/lib/routes/app_pages.dart b/lib/routes/app_pages.dart index d19f12a..0dd1711 100644 --- a/lib/routes/app_pages.dart +++ b/lib/routes/app_pages.dart @@ -37,6 +37,10 @@ import 'package:rogapp/pages/entry/entry_list_page.dart'; import 'package:rogapp/pages/entry/entry_detail_page.dart'; import 'package:rogapp/pages/entry/entry_binding.dart'; +import 'package:rogapp/pages/entry/event_entries_page.dart'; +import 'package:rogapp/pages/entry/event_entries_binding.dart'; + + part 'app_routes.dart'; class AppPages { @@ -70,6 +74,7 @@ class AppPages { static const MEMBER_DETAIL = Routes.MEMBER_DETAIL; static const ENTRY_LIST = Routes.ENTRY_LIST; static const ENTRY_DETAIL = Routes.ENTRY_DETAIL; + static const EVENT_ENTRY = Routes.EVENT_ENTRIES; static final routes = [ GetPage( @@ -166,6 +171,11 @@ class AppPages { page: () => EntryDetailPage(), binding: EntryBinding(), ), + GetPage( + name: Routes.EVENT_ENTRIES, + page: () => EventEntriesPage(), + binding: EventEntriesBinding(), + ), ]; diff --git a/lib/routes/app_routes.dart b/lib/routes/app_routes.dart index e313c66..d2eece8 100644 --- a/lib/routes/app_routes.dart +++ b/lib/routes/app_routes.dart @@ -34,4 +34,6 @@ abstract class Routes { static const MEMBER_DETAIL = '/member-detail'; static const ENTRY_LIST = '/entry-list'; static const ENTRY_DETAIL = '/entry-detail'; + + static const EVENT_ENTRIES = '/event-entries'; } diff --git a/lib/services/api_service.dart b/lib/services/api_service.dart index f1bd943..ca2ccd7 100644 --- a/lib/services/api_service.dart +++ b/lib/services/api_service.dart @@ -466,6 +466,43 @@ class ApiService extends GetxService{ } } + Future updateUserInfo(int userId, Entry entry) async { + init(); + getToken(); + + final entryId = entry.id; + + DateTime? date = entry.date; + String? formattedDate; + if (date != null) { + formattedDate = DateFormat('yyyy-MM-dd').format(date); + } + + final response = await http.put( + Uri.parse('$baseUrl/userinfo/$userId/'), + headers: { + 'Authorization': 'Token $token', + 'Content-Type': 'application/json; charset=UTF-8', + }, + body: json.encode({ + 'zekken_number': entry.team.zekkenNumber, + 'event_code': entry.event.eventName, + 'group': entry.team.category.categoryName, + 'team_name': entry.team.teamName, + 'date': formattedDate, + }), + ); + if (response.statusCode == 200) { + final decodedResponse = utf8.decode(response.bodyBytes); + final updatedUserInfo = json.decode(decodedResponse); + //Get.find().updateUserInfo(updatedUserInfo); + + } else { + throw Exception('Failed to update entry'); + } + } + + Future updateEntry(int entryId, int eventId, int categoryId, DateTime date) async { init(); getToken(); diff --git a/lib/services/location_service.dart b/lib/services/location_service.dart index 07bfe04..60f069b 100644 --- a/lib/services/location_service.dart +++ b/lib/services/location_service.dart @@ -82,59 +82,93 @@ class LocationService { double lon3, double lat4, double lon4, - String cat) async { + String cat, + String event_code) async { //print("-------- in location for bound -------------"); final IndexController indexController = Get.find(); - String url = ""; - String serverUrl = ConstValues.currentServer(); - if (cat.isNotEmpty) { - if (indexController.currentUser.isNotEmpty) { - bool rog = indexController.currentUser[0]['user']['is_rogaining']; - String r = rog == true ? 'True' : 'False'; - var grp = indexController.currentUser[0]['user']['event_code']; - url = - '$serverUrl/api/inbound?rog=$r&grp=$grp&ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4&cat=$cat'; - } else { - url = - '$serverUrl/api/inbound?ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4&cat=$cat'; - } - } else { - if (indexController.currentUser.isNotEmpty) { - bool rog = indexController.currentUser[0]['user']['is_rogaining']; - String r = rog == true ? 'True' : 'False'; - var grp = indexController.currentUser[0]['user']['event_code']; - //print("-------- requested user group $grp -------------"); - url = - '$serverUrl/api/inbound?rog=$r&grp=$grp&ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4'; - } else { - url = - '$serverUrl/api/inbound?ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4'; - } - } - //print('++++++++$url'); - final response = await http.get( - Uri.parse(url), - headers: { - 'Content-Type': 'application/json; charset=UTF-8', - }, - ); + final updateTime = indexController.lastUserUpdateTime.value; - if (response.statusCode == 500) { - return null; //featuresFromGeoJson(utf8.decode(response.bodyBytes)); - } + // ユーザー情報の更新を最大5秒間待つ - if (response.statusCode == 200) { - DestinationController destinationController = - Get.find(); - GeoJSONFeatureCollection cc = - GeoJSONFeatureCollection.fromJSON(utf8.decode(response.bodyBytes)); - if (cc.features.isEmpty) { + try { + /* + // ユーザー情報の更新を最大5秒間待つ + final newUpdateTime = await indexController.lastUserUpdateTime.stream + .firstWhere( + (time) => time.isAfter(updateTime), + orElse: () => updateTime, + ).timeout(Duration(seconds: 5)); + + if (newUpdateTime == updateTime) { + print('ユーザー情報の更新がタイムアウトしました'); + // タイムアウト時の処理(例:エラー表示やリトライ) return null; - } else { - //print("---- feature got from server is ${cc.collection[0].properties} ------"); - return cc; } + */ + + /* + await indexController.lastUserUpdateTime.stream.firstWhere( + (time) => time.isAfter(updateTime), + orElse: () => updateTime, + ).timeout(Duration(seconds: 2), onTimeout: () => updateTime); + */ + + String url = ""; + String serverUrl = ConstValues.currentServer(); + if (cat.isNotEmpty) { + if (indexController.currentUser.isNotEmpty) { + bool rog = indexController.currentUser[0]['user']['is_rogaining']; + String r = rog == true ? 'True' : 'False'; + var grp = event_code; //indexController.currentUser[0]['user']['event_code']; + print("Group=$grp"); + url = + '$serverUrl/api/inbound?rog=$r&grp=$grp&ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4&cat=$cat'; + } else { + url = + '$serverUrl/api/inbound?ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4&cat=$cat'; + } + } else { + if (indexController.currentUser.isNotEmpty) { + bool rog = indexController.currentUser[0]['user']['is_rogaining']; + String r = rog == true ? 'True' : 'False'; + var grp = indexController.currentUser[0]['user']['event_code']; + print("-------- requested user group $grp -------------"); + url = + '$serverUrl/api/inbound?rog=$r&grp=$grp&ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4'; + } else { + url = + '$serverUrl/api/inbound?ln1=$lon1&la1=$lat1&ln2=$lon2&la2=$lat2&ln3=$lon3&la3=$lat3&ln4=$lon4&la4=$lat4'; + } + print('++++++++$url'); + final response = await http.get( + Uri.parse(url), + headers: { + 'Content-Type': 'application/json; charset=UTF-8', + }, + ); + + if (response.statusCode == 500) { + return null; //featuresFromGeoJson(utf8.decode(response.bodyBytes)); + } + + if (response.statusCode == 200) { + DestinationController destinationController = + Get.find(); + + GeoJSONFeatureCollection cc = + GeoJSONFeatureCollection.fromJSON(utf8.decode(response.bodyBytes)); + if (cc.features.isEmpty) { + return null; + } else { + //print("---- feature got from server is ${cc.collection[0].properties} ------"); + return cc; + } + } + } + } catch(e) { + print("Error: $e"); } + return null; }