Files
rog_app/lib/pages/index/index_page.dart
2024-09-08 18:16:51 +09:00

249 lines
9.2 KiB
Dart
Raw Permalink 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.

import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
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';
import '../permission/permission.dart';
// index_page.dartファイルの主な内容です。
// このファイルは、アプリのメインページのUIを構築し、各機能へのナビゲーションを提供しています。
// また、IndexControllerとDestinationControllerを使用して、状態管理と各種機能の実装を行っています。
//
// MapWidgetとListWidgetは、それぞれ別のファイルで定義されているウィジェットであり、マップモードとリストモードの表示を担当しています。
//
// 全体的に、index_page.dartはアプリのメインページの構造を定義し、他のコンポーネントやページへの橋渡しを行っているファイルです。
//
// 要検討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> {
final IndexController indexController = Get.find<IndexController>();
final DestinationController destinationController = Get.find<DestinationController>();
@override
void initState() {
super.initState();
_checkPermissionAndInitialize();
}
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,
);
}
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);
},
),
],
);
},
);
}else{
if(indexController.currentUser[0]["user"]["event_code"] == null) {
// イベントコードがない場合、EVENT_ENTRYページに遷移
await Get.toNamed(AppPages.EVENT_ENTRY);
// EVENT_ENTRYページから戻ってきた後に警告を表示
_showEventSelectionWarning();
}
}
}
void _showEventSelectionWarning() {
Get.dialog(
AlertDialog(
title: const Text('警告'),
content: const Text('イベントを選択してください。'),
actions: [
TextButton(
child: const Text('OK'),
onPressed: () => Get.back(),
),
],
),
);
}
// class IndexPage extends GetView<IndexController> {
// IndexPage({Key? key}) : super(key: key);
// IndexControllerとDestinationControllerのインスタンスを取得しています。
//
final LocationController locationController = Get.find<LocationController>();
// buildメソッドは、ウィジェットのUIを構築するメソッドです。
// ここでは、WillPopScopeウィジェットを使用して、端末の戻るボタンが押された際の動作を制御しています。
//
@override
Widget build(BuildContext context) {
/*
return PopScope(
canPop: false,
child: Scaffold(
*/
return Scaffold(
//
// Scaffoldウィジェットを使用して、アプリのメインページのレイアウトを構築しています。
//
drawer: DrawerPage(),
appBar: AppBar(
title: Obx(() => Text(indexController.selectedEventName.value)),
//title: Text("add_location".tr),
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)),
InkWell(
onTap: () {
Get.toNamed(AppPages.SEARCH);
},
child: Container(
height: 32,
width: 75,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(25),
),
child: const Center(
child: Icon(Icons.search),
),
),
),
//CatWidget(indexController: indexController,),
],
),
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();
}
}),
),
// マップモードとリストモードを切り替えるためのボタンです。
floatingActionButton: FloatingActionButton(
onPressed: () {
indexController.toggleMode();
},
elevation: 1.0,
//
// Obxウィジェットを使用して、indexController.mode.valueの値に基づいて、MapWidgetまたはListWidgetを表示しています。
//
child: Obx(
() => indexController.mode.value == 0
? const Image(image: AssetImage('assets/images/list2.png'))
: const Image(image: AssetImage('assets/images/map.png')),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
}