Files
rog_app/lib/pages/index/index_page.dart

249 lines
9.2 KiB
Dart
Raw Normal View History

2022-04-17 11:45:21 +05:30
import 'package:flutter/material.dart';
2024-09-08 18:16:51 +09:00
import 'package:geolocator/geolocator.dart';
2022-04-17 11:45:21 +05:30
import 'package:get/get.dart';
import 'package:gifunavi/pages/destination/destination_controller.dart';
import 'package:gifunavi/pages/drawer/drawer_page.dart';
import 'package:gifunavi/pages/index/index_controller.dart';
import 'package:gifunavi/routes/app_pages.dart';
import 'package:gifunavi/widgets/list_widget.dart';
import 'package:gifunavi/widgets/map_widget.dart';
import 'package:gifunavi/utils/location_controller.dart';
2022-04-17 11:45:21 +05:30
2024-09-03 22:17:09 +09:00
import '../permission/permission.dart';
// index_page.dartファイルの主な内容です。
// このファイルは、アプリのメインページのUIを構築し、各機能へのナビゲーションを提供しています。
// また、IndexControllerとDestinationControllerを使用して、状態管理と各種機能の実装を行っています。
//
// MapWidgetとListWidgetは、それぞれ別のファイルで定義されているウィジェットであり、マップモードとリストモードの表示を担当しています。
//
// 全体的に、index_page.dartはアプリのメインページの構造を定義し、他のコンポーネントやページへの橋渡しを行っているファイルです。
//
2022-04-17 11:45:21 +05:30
// 要検討GPSデータの表示アイコンをタップした際のエラーハンドリングを追加することをお勧めします。
// MapWidgetとListWidgetの切り替えにObxを使用していますが、パフォーマンスを考慮して、必要な場合にのみウィジェットを再構築するようにしてください。
// DestinationControllerのisSimulationModeを使用してGPS信号の強弱をシミュレーションしていますが、本番環境では適切に実際のGPS信号を使用するようにしてください。
// IndexPageクラスは、GetView<IndexController>を継承したStatelessWidgetです。このクラスは、アプリのメインページを表すウィジェットです。
//
class IndexPage extends StatefulWidget {
const IndexPage({super.key});
@override
_IndexPageState createState() => _IndexPageState();
}
class _IndexPageState extends State<IndexPage> {
2024-09-08 18:16:51 +09:00
final IndexController indexController = Get.find<IndexController>();
final DestinationController destinationController = Get.find<DestinationController>();
@override
void initState() {
super.initState();
2024-09-08 18:16:51 +09:00
_checkPermissionAndInitialize();
}
2024-09-08 18:16:51 +09:00
Future<void> _checkPermissionAndInitialize() async {
// 位置情報の許可が得られた場合の処理
await _initializeMap();
}
Future<void> _initializeMap() async {
await indexController.loadLocations();
setState(() {}); // 状態を更新してUIを再構築
}
void _showLocationServiceDisabledOrDeniedError() {
Get.snackbar(
'エラー',
'位置情報サービスが無効か、許可されていません。設定を確認してください。',
duration: const Duration(seconds: 5),
snackPosition: SnackPosition.BOTTOM,
mainButton: TextButton(
child: const Text('設定'),
onPressed: () => Geolocator.openLocationSettings(),
),
);
}
void _showPermissionDeniedError() {
Get.snackbar(
'エラー',
'位置情報の許可が必要です。設定から許可してください。',
duration: const Duration(seconds: 5),
snackPosition: SnackPosition.BOTTOM,
);
2024-09-03 22:17:09 +09:00
}
2024-09-02 21:25:19 +09:00
void checkEventAndNavigate() async {
if (indexController.currentUser.isNotEmpty &&
indexController.currentUser[0]["user"]["event_code"] == null) {
// イベントコードがない場合、EVENT_ENTRYページに遷移
await Get.toNamed(AppPages.EVENT_ENTRY);
// EVENT_ENTRYページから戻ってきた後に警告を表示
_showEventSelectionWarning();
}
}
void checkLoginAndShowDialog() async {
if (indexController.currentUser.isEmpty) {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('ログインが必要です'),
content: const Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('1) ログインされていません。ロゲに参加するにはログインが必要です。'),
SizedBox(height: 10),
Text('2) ログイン後、個人情報入力、チーム登録、エントリー登録を行なってください。'),
SizedBox(height: 10),
Text('3) エントリー登録は場所と日にちごとに行なってください。'),
],
),
actions: [
TextButton(
child: const Text('キャンセル'),
onPressed: () {
Navigator.of(context).pop();
},
),
ElevatedButton(
child: const Text('ログイン'),
onPressed: () {
Navigator.of(context).pop();
Get.toNamed(AppPages.LOGIN);
},
),
],
);
},
);
2024-09-02 21:25:19 +09:00
}else{
if(indexController.currentUser[0]["user"]["event_code"] == null) {
// イベントコードがない場合、EVENT_ENTRYページに遷移
await Get.toNamed(AppPages.EVENT_ENTRY);
// EVENT_ENTRYページから戻ってきた後に警告を表示
_showEventSelectionWarning();
}
}
}
2024-09-02 21:25:19 +09:00
void _showEventSelectionWarning() {
Get.dialog(
AlertDialog(
2024-09-08 18:16:51 +09:00
title: const Text('警告'),
content: const Text('イベントを選択してください。'),
2024-09-02 21:25:19 +09:00
actions: [
TextButton(
2024-09-08 18:16:51 +09:00
child: const Text('OK'),
2024-09-02 21:25:19 +09:00
onPressed: () => Get.back(),
),
],
),
);
}
2024-09-08 18:16:51 +09:00
// class IndexPage extends GetView<IndexController> {
// IndexPage({Key? key}) : super(key: key);
// IndexControllerとDestinationControllerのインスタンスを取得しています。
//
final LocationController locationController = Get.find<LocationController>();
2022-04-17 11:45:21 +05:30
// buildメソッドは、ウィジェットのUIを構築するメソッドです。
// ここでは、WillPopScopeウィジェットを使用して、端末の戻るボタンが押された際の動作を制御しています。
//
2022-04-17 11:45:21 +05:30
@override
Widget build(BuildContext context) {
2024-09-08 18:16:51 +09:00
/*
return PopScope(
canPop: false,
2022-07-22 19:36:04 +05:30
child: Scaffold(
2024-09-08 18:16:51 +09:00
*/
return Scaffold(
//
// Scaffoldウィジェットを使用して、アプリのメインページのレイアウトを構築しています。
//
2023-09-03 23:37:41 +05:30
drawer: DrawerPage(),
appBar: AppBar(
title: Obx(() => Text(indexController.selectedEventName.value)),
//title: Text("add_location".tr),
2023-09-03 23:37:41 +05:30
actions: [
IconButton(
onPressed: () async {
Get.toNamed(AppPages.GPS);
},
icon: const Icon(Icons.telegram)),
IconButton(
onPressed: () {
Get.toNamed(AppPages.HISTORY);
},
icon: const Icon(Icons.history)),
IconButton(
onPressed: () {
final tk = indexController.currentUser[0]["token"];
if (tk != null) {
destinationController.fixMapBound(tk);
}
},
icon: const Icon(Icons.refresh)),
2023-09-03 23:37:41 +05:30
InkWell(
onTap: () {
Get.toNamed(AppPages.SEARCH);
2022-07-22 19:36:04 +05:30
},
2023-09-03 23:37:41 +05:30
child: Container(
height: 32,
width: 75,
decoration: BoxDecoration(
color: Colors.blue,
2023-09-03 23:37:41 +05:30
borderRadius: BorderRadius.circular(25),
2022-07-22 19:36:04 +05:30
),
2023-09-03 23:37:41 +05:30
child: const Center(
child: Icon(Icons.search),
),
),
),
//CatWidget(indexController: indexController,),
2022-07-22 19:36:04 +05:30
],
),
2024-09-08 18:16:51 +09:00
body: SafeArea(
child:Obx(() {
if (indexController.isLoadingLocations.value) {
return const Center(child: CircularProgressIndicator()); // Index Controller
} else {
return indexController.mode.value == 0
? const MapWidget()
: const ListWidget();
}
}),
),
// マップモードとリストモードを切り替えるためのボタンです。
2022-07-22 19:36:04 +05:30
floatingActionButton: FloatingActionButton(
2023-09-03 23:37:41 +05:30
onPressed: () {
2022-07-22 19:36:04 +05:30
indexController.toggleMode();
},
elevation: 1.0,
//
// Obxウィジェットを使用して、indexController.mode.valueの値に基づいて、MapWidgetまたはListWidgetを表示しています。
//
2023-09-03 23:37:41 +05:30
child: Obx(
() => indexController.mode.value == 0
2023-09-03 23:37:41 +05:30
? const Image(image: AssetImage('assets/images/list2.png'))
: const Image(image: AssetImage('assets/images/map.png')),
),
2022-07-22 19:36:04 +05:30
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
2024-09-08 18:16:51 +09:00
);
2022-04-17 11:45:21 +05:30
}
2023-09-03 23:37:41 +05:30
}