import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:geojson_vi/geojson_vi.dart'; import 'package:geolocator/geolocator.dart'; import 'package:get/get.dart'; import 'package:image_picker/image_picker.dart'; import 'package:latlong2/latlong.dart'; import 'package:rogapp/main.dart'; import 'package:rogapp/model/destination.dart'; import 'package:rogapp/pages/camera/camera_page.dart'; import 'package:rogapp/pages/destination/destination_controller.dart'; import 'package:rogapp/pages/index/index_controller.dart'; import 'package:rogapp/services/external_service.dart'; import 'package:rogapp/utils/const.dart'; import 'package:rogapp/utils/database_helper.dart'; import 'package:rogapp/utils/text_util.dart'; import 'package:rogapp/widgets/bottom_sheet_controller.dart'; import 'package:rogapp/widgets/debug_widget.dart'; import 'package:url_launcher/url_launcher.dart'; class BottomSheetNew extends GetView { BottomSheetNew( {this.isAlreadyCheckedIn = false, Key? key, required this.destination}) : super(key: key); final IndexController indexController = Get.find(); final DestinationController destinationController = Get.find(); final Destination destination; final bool isAlreadyCheckedIn; Image getImage() { String serverUrl = ConstValues.currentServer(); if (indexController.rogMode == 1) { if (indexController.currentDestinationFeature.isEmpty || indexController.currentDestinationFeature[0].photos! == "") { return const Image(image: AssetImage('assets/images/empty_image.png')); } else { //print("@@@@@@@@@@@@@ rog mode -------------------- ${indexController.currentDestinationFeature[0].photos} @@@@@@@@@@@"); String photo = indexController.currentDestinationFeature[0].photos!; if (photo.contains('http')) { return Image( image: NetworkImage( indexController.currentDestinationFeature[0].photos!, ), errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { return Image.asset("assets/images/empty_image.png"); }, ); } else { return Image( image: NetworkImage( '$serverUrl/media/compressed/${indexController.currentDestinationFeature[0].photos!}', ), errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { return Image.asset("assets/images/empty_image.png"); }, ); } } } else { GeoJSONFeature gf = indexController.currentFeature[0]; print("=== photo sss ${gf.properties!["photos"]}"); if (gf.properties!["photos"] == null || gf.properties!["photos"] == "") { return const Image(image: AssetImage('assets/images/empty_image.png')); } else { String photo = gf.properties!["photos"]; if (photo.contains('http')) { return Image( image: NetworkImage( gf.properties!["photos"], ), errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { return Image.asset("assets/images/empty_image.png"); }, ); } else { String imageUrl = Uri.encodeFull( '$serverUrl/media/compressed/${gf.properties!["photos"]}'); return Image( image: NetworkImage( imageUrl, ), errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { return Image.asset("assets/images/empty_image.png"); }, ); } } } } void _launchURL(url) async { if (!await launchUrl(url)) throw 'Could not launch $url'; } bool isInDestination(String locationid) { int lid = int.parse(locationid); if (destinationController.destinations .where((element) => element.location_id == lid) .isNotEmpty) { return true; } else { return false; } } Widget getActionButton(BuildContext context, Destination destination) { Destination cdest = destinationController .festuretoDestination(indexController.currentFeature[0]); var distance = const Distance(); double distanceToDest = distance.as( LengthUnit.Meter, LatLng( destinationController.currentLat, destinationController.currentLon), LatLng(cdest.lat!, cdest.lon!)); if (destinationController.rogainingCounted.value == true && destinationController.distanceToStart() <= 500 //destination.cp == -1 && DestinationController.ready_for_goal == true) { //goal return ElevatedButton( style: ElevatedButton.styleFrom(backgroundColor: Colors.red), onPressed: destinationController.rogainingCounted.value == true && destinationController.distanceToStart() <= 500 && //destination.cp == -1 && DestinationController.ready_for_goal == true ? () async { destinationController.isAtGoal.value = true; destinationController.photos.clear(); await showModalBottomSheet( constraints: BoxConstraints.loose( ui.Size(Get.width, Get.height * 0.75)), context: Get.context!, isScrollControlled: true, builder: ((context) => CameraPage( destination: destination, ))).whenComplete(() { destinationController.skipGps = false; destinationController.chekcs = 0; destinationController.isAtGoal.value = false; }); } : null, child: const Text( "ロゲイニングを終える", style: TextStyle(color: Colors.white), )); } else if (distanceToDest <= destinationController.getForcedChckinDistance(destination)) { //start return ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Theme.of(context).colorScheme.secondary, ), onPressed: () async { // Check conditions to show confirmation dialog if (destination.cp == -1 && destinationController.isInRog.value == false && destinationController.rogainingCounted.value == false) { // Show confirmation dialog Get.dialog( AlertDialog( title: const Text("確認"), //confirm content: const Text( "ロゲを開始すると、今までのロゲデータが全てクリアされます。本当に開始しますか?"), //are you sure actions: [ TextButton( child: const Text("いいえ"), //no onPressed: () { Get.back(); // Close the dialog }, ), TextButton( child: const Text("はい"), //yes onPressed: () async { // Clear data and start game logic here destinationController.isInRog.value = true; destinationController .resetRogaining(); // Assuming you have a method to clear data destinationController.addToRogaining( destinationController.currentLat, destinationController.currentLon, destination.location_id!, ); saveGameState(); await ExternalService().startRogaining(); Get.back(); // Close the dialog and potentially navigate away }, ), ], ), barrierDismissible: false, // User must tap a button to close the dialog ); } else { // Existing logic for other conditions if (destination.cp == -1) { return; } Get.back(); await destinationController.callforCheckin(destination); } }, child: Text( destination.cp == -1 && destinationController.isInRog.value == false && destinationController.rogainingCounted.value == false ? "ロゲ開始" : destinationController.isInRog.value == true && destination.cp == -1 ? "ゲーム中" : isAlreadyCheckedIn == true ? "ゲーム中" : "チェックイン", style: TextStyle(color: Theme.of(context).colorScheme.onSecondary), ), ); } return Container(); } @override Widget build(BuildContext context) { //print("to start ${destinationController.distanceToStart()}"); destinationController.skipGps = true; // print('--- c use --- ${indexController.currentUser[0].values}'); // print('---- rog_mode ----- ${indexController.rogMode.value} -----'); // return indexController.rogMode.value == 0 // ? detailsSheet(context) // : destinationSheet(context); return detailsSheet(context); } Future isDestinationCheckedIn(Destination d) async { DatabaseHelper db = DatabaseHelper.instance; List ds = await db.getDestinationByLatLon(d.lat!, d.lon!); return ds.isNotEmpty; } // show add location details SingleChildScrollView detailsSheet(BuildContext context) { Destination cdest = destinationController .festuretoDestination(indexController.currentFeature[0]); var distance = const Distance(); double distanceToDest = distance.as( LengthUnit.Meter, LatLng( destinationController.currentLat, destinationController.currentLon), LatLng(cdest.lat!, cdest.lon!)); LogManager().addLog("Distance from current point : $distanceToDest"); LogManager().addLog( "forced distance for point : ${destinationController.getForcedChckinDistance(destination)}"); LogManager().addLog( "current point : ${destinationController.currentLat}, ${destinationController.currentLon} - ${DateTime.now().hour}:${DateTime.now().minute}:${DateTime.now().second}:${DateTime.now().microsecond}"); //LogManager().addLog("is already checked in : $isAlreadyCheckedIn"); LogManager().addLog("Checkin radius : ${destination.checkin_radious}"); LogManager().addLog("--${destination.cp}--"); return SingleChildScrollView( child: Column( children: [ Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ MaterialButton( onPressed: () { Get.back(); //indexController.makePrevious(indexController.currentFeature[0]); }, color: Colors.blue, textColor: Colors.white, padding: const EdgeInsets.all(16), shape: const CircleBorder(), child: const Icon( Icons.arrow_back_ios, //Icons.arrow_back_ios, size: 14, ), ), Expanded( child: Container( alignment: Alignment.center, child: Obx(() => Text( "${TextUtils.getDisplayTextFeture(indexController.currentFeature[0])} : ${indexController.currentFeature[0].properties!["location_name"]}", // indexController // .currentFeature[0].properties!["location_name"], style: const TextStyle( fontSize: 15.0, fontWeight: FontWeight.bold, ), )), ), ), ], ), ), Row( children: [ Expanded( child: SizedBox( height: 260.0, child: Obx(() => getImage()), )), ], ), Obx(() => Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ // Finish or Goal getActionButton(context, destination), //remove checkin isAlreadyCheckedIn == true && destination.cp != -1 ? ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.blueAccent), onPressed: () async { await destinationController .removeCheckin(destination.cp!.toInt()); destinationController .deleteDestination(destination); Get.back(); }, child: const Text( "チェックイン取消", style: TextStyle(color: Colors.white), )) //remove checkin : Container(), ], ), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Theme.of(context) .colorScheme .onPrimaryContainer), onPressed: destinationController.distanceToStart() > 500 ? () async { // print( // "dist to start ${destinationController.distanceToStart()}"); Get.back(); //print("---- go to ----"); GeoJSONMultiPoint mp = indexController .currentFeature[0] as GeoJSONMultiPoint; Position position = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy .bestForNavigation, forceAndroidLocationManager: true); //print("------- position -------- $position"); Destination ds = Destination( lat: position.latitude, lon: position.longitude); Destination tp = Destination( lat: mp.coordinates[0][1], lon: mp.coordinates[0][0]); destinationController .destinationMatrixFromCurrentPoint( [ds, tp]); } : null, //go here child: Text( "ここへ行く", style: TextStyle( color: Theme.of(context).colorScheme.onPrimary), )), const SizedBox( width: 10, ), // forced start / checkin ], ), Row( children: [ Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ indexController.currentDestinationFeature .isNotEmpty && destinationController.isInCheckin.value == true ? Container() : FutureBuilder( future: wantToGo(context), builder: (context, snapshot) { return Container( child: snapshot.data, ); }, ), indexController.currentFeature[0] .properties!["location_name"] != null && (indexController.currentFeature[0] .properties!["location_name"] as String) .isNotEmpty ? Flexible( child: Text(indexController .currentFeature[0] .properties!["location_name"])) : const SizedBox( width: 0.0, height: 0, ), ], ), ), ], ), const SizedBox( height: 8.0, ), Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ const Icon(Icons.roundabout_left), const SizedBox( width: 8.0, ), indexController.currentFeature[0] .properties!["address"] != null && (indexController.currentFeature[0] .properties!["address"] as String) .isNotEmpty ? getDetails( context, "address".tr, indexController.currentFeature[0] .properties!["address"] ?? '') : const SizedBox( width: 0.0, height: 0, ), ], ), ), Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ const Icon(Icons.phone), const SizedBox( width: 8.0, ), indexController.currentFeature[0] .properties!["phone"] != null && (indexController.currentFeature[0] .properties!["phone"] as String) .isNotEmpty ? getDetails( context, "telephone".tr, indexController.currentFeature[0] .properties!["phone"] ?? '') : const SizedBox( width: 0.0, height: 0, ), ], ), ), Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ const Icon(Icons.email), const SizedBox( width: 8.0, ), indexController.currentFeature[0] .properties!["email"] != null && (indexController.currentFeature[0] .properties!["email"] as String) .isNotEmpty ? getDetails( context, "email".tr, indexController.currentFeature[0] .properties!["email"] ?? '') : const SizedBox( width: 0.0, height: 0, ), ], ), ), Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ const Icon(Icons.language), const SizedBox( width: 8.0, ), indexController.currentFeature[0] .properties!["webcontents"] != null && (indexController.currentFeature[0] .properties!["webcontents"] as String) .isNotEmpty ? getDetails( context, "web".tr, indexController.currentFeature[0] .properties!["webcontents"] ?? '', isurl: true) : const SizedBox( width: 0.0, height: 0, ), ], ), ), Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ const SizedBox( width: 8.0, ), indexController.currentFeature[0] .properties!["remark"] != null && (indexController.currentFeature[0] .properties!["remark"] as String) .isNotEmpty ? getDetails( context, "remarks".tr, indexController.currentFeature[0] .properties!["remark"] ?? '', isurl: false) : const SizedBox( width: 0.0, height: 0, ), ], ), ), // Text('${TextUtils.getDisplayText(indexController.currentFeature[0].properties!["cp"].toString())} - id: ${TextUtils.getDisplayText(indexController.currentFeature[0].properties!["checkin_point"].toString())}'), ], ), )), const SizedBox( height: 60.0, ) ], ), ); } Future wantToGo(BuildContext context) async { bool selected = false; // print( // '---target-- ${indexController.currentFeature[0].properties!["location_id"]}----'); for (Destination d in destinationController.destinations) { //print('---- ${d.location_id.toString()} ----'); if (d.location_id == indexController.currentFeature[0].properties!["location_id"]) { selected = true; break; } } DatabaseHelper db = DatabaseHelper.instance; return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // indexController.rog_mode == 0 ? // // IconButton( // // icon: Icon(Icons.pin_drop_sharp, size: 32, color: _selected == true ? Colors.amber : Colors.blue,), // // onPressed: (){ // // if(_selected){ // // // show remove from destination // // Get.defaultDialog( // // title: "本当にこのポイントを通過順から外しますか?", // // middleText: "場所は目的地リストから削除されます", // // backgroundColor: Colors.blue.shade300, // // titleStyle: TextStyle(color: Colors.white), // // middleTextStyle: TextStyle(color: Colors.white), // // textConfirm: "はい", // // textCancel: "いいえ", // // cancelTextColor: Colors.white, // // confirmTextColor: Colors.blue, // // buttonColor: Colors.white, // // barrierDismissible: false, // // radius: 10, // // content: Column( // // children: [ // // ], // // ), // // onConfirm: (){ // // int _id = indexController.currentFeature[0].properties!["location_id"]; // // Destination? d = destinationController.destinationById(_id); // // print('--- des id is : ${d} -----'); // // if(d != null) { // // //print('--- des id is : ${d.location_id} -----'); // // destinationController.deleteDestination(d); // // Get.back(); // // Get.back(); // // Get.snackbar("追加した", "場所が削除されました"); // // } // // } // // ); // // return; // // } // // // show add to destination // // Get.defaultDialog( // // title: "この場所を登録してもよろしいですか", // // middleText: "ロケーションがロガニング リストに追加されます", // // backgroundColor: Colors.blue.shade300, // // titleStyle: TextStyle(color: Colors.white), // // middleTextStyle: TextStyle(color: Colors.white), // // textConfirm: "はい", // // textCancel: "いいえ", // // cancelTextColor: Colors.white, // // confirmTextColor: Colors.blue, // // buttonColor: Colors.white, // // barrierDismissible: false, // // radius: 10, // // content: Column( // // children: [ // // ], // // ), // // onConfirm: (){ // // GeoJsonMultiPoint mp = indexController.currentFeature[0].geometry as GeoJsonMultiPoint; // // LatLng pt = LatLng(mp.geoSerie!.geoPoints[0].latitude, mp.geoSerie!.geoPoints[0].longitude); // // print("----- want to go sub location is ---- ${indexController.currentFeature[0].properties!["sub_loc_id"]} -----"); // // Destination dest = Destination( // // name: indexController.currentFeature[0].properties!["location_name"], // // address: indexController.currentFeature[0].properties!["address"], // // phone: indexController.currentFeature[0].properties!["phone"], // // email: indexController.currentFeature[0].properties!["email"], // // webcontents: indexController.currentFeature[0].properties!["webcontents"], // // videos: indexController.currentFeature[0].properties!["videos"], // // category: indexController.currentFeature[0].properties!["category"], // // series: 1, // // lat: pt.latitude, // // lon: pt.longitude, // // sub_loc_id: indexController.currentFeature[0].properties!["sub_loc_id"], // // location_id: indexController.currentFeature[0].properties!["location_id"], // // list_order: 1, // // photos: indexController.currentFeature[0].properties!["photos"], // // checkin_radious: indexController.currentFeature[0].properties!["checkin_radius"], // // auto_checkin: indexController.currentFeature[0].properties!["auto_checkin"] == true ? 1 : 0, // // cp: indexController.currentFeature[0].properties!["cp"], // // checkin_point: indexController.currentFeature[0].properties!["checkin_point"], // // buy_point: indexController.currentFeature[0].properties!["buy_point"], // // selected: false, // // checkedin: false, // // hidden_location: indexController.currentFeature[0].properties!["hidden_location"] == true ?1 : 0 // // ); // // destinationController.addDestinations(dest); // // Get.back(); // // Get.back(); // // Get.snackbar("追加した", "場所が追加されました"); // // } // // ); // // }, // // ): // // Container(), const SizedBox( width: 8.0, ), Obx((() => indexController.rogMode.value == 1 ? ElevatedButton( onPressed: () async { Destination dest = indexController.currentDestinationFeature[0]; //print("~~~~ before checking button ~~~~"); //print("------ curent destination is ${dest!.checkedIn}-------"); destinationController.makeCheckin( dest, !dest.checkedin!, ""); }, child: indexController .currentDestinationFeature[0].checkedin == false ? const Text("チェックイン") : const Text("チェックアウト")) : Container())), ], ), ], ); } Widget getCheckin(BuildContext context) { //print("------ currentAction ----- ${indexController.currentAction}-----"); return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ indexController.currentAction[0][0]["checkin"] == false ? Column( children: [ Row( mainAxisSize: MainAxisSize.max, children: [ ElevatedButton( child: const Text("Image"), onPressed: () { final ImagePicker picker = ImagePicker(); picker .pickImage(source: ImageSource.camera) .then((value) { //print("----- image---- ${value!.path}"); }); }, ) ], ), ElevatedButton( onPressed: () { if (indexController.currentAction.isNotEmpty) { //print(indexController.currentAction[0]); indexController.currentAction[0][0]["checkin"] = true; Map temp = Map.from( indexController.currentAction[0][0]); indexController.currentAction.clear(); //print("---temp---${temp}"); indexController.currentAction.add([temp]); } }, child: Text("checkin".tr)) ], ) : ElevatedButton( onPressed: () { if (indexController.currentAction.isNotEmpty) { //print(indexController.currentAction[0]); indexController.currentAction[0][0]["checkin"] = false; Map temp = Map.from( indexController.currentAction[0][0]); indexController.currentAction.clear(); //print("---temp---${temp}"); indexController.currentAction.add([temp]); } }, child: const Icon(Icons.favorite, color: Colors.red), ) ], ) ], ); } Widget getDetails(BuildContext context, String label, String text, {bool isurl = false}) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(label), const SizedBox( width: 10.0, ), InkWell( onTap: () { if (isurl) { if (indexController.rogMode.value == 0) { _launchURL(indexController .currentFeature[0].properties!["webcontents"]); } else { indexController.currentDestinationFeature[0].webcontents; } } }, child: SizedBox( width: MediaQuery.of(context).size.width - (MediaQuery.of(context).size.width * 0.35), child: Text( text, textAlign: TextAlign.justify, style: TextStyle( color: isurl ? Colors.blue : Colors.black, ), ), ), ), ], ); } }