Files
rog_app/lib/widgets/bottom_sheet_new.dart
2024-03-06 15:07:14 +05:30

834 lines
37 KiB
Dart

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<BottomSheetController> {
BottomSheetNew(
{this.isAlreadyCheckedIn = false, Key? key, required this.destination})
: super(key: key);
final IndexController indexController = Get.find<IndexController>();
final DestinationController destinationController =
Get.find<DestinationController>();
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) {
print("getActionButton ${destinationController.rogainingCounted.value}");
print("getActionButton ${destinationController.distanceToStart()}");
print("getActionButton ${destination.cp}");
print("getActionButton ${DestinationController.ready_for_goal}");
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 (destinationController.isInRog.value == false &&
destination.cp == -1 &&
destinationController.rogainingCounted.value == false) {
print("counted ${destinationController.rogainingCounted.value}");
// Show confirmation dialog
Get.dialog(
AlertDialog(
title: const Text("確認"), //confirm
content: const Text(
"ロゲを開始すると、今までのロゲデータが全てクリアされます。本当に開始しますか?"), //are you sure
actions: <Widget>[
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();
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 if (destinationController.isInRog.value == true) {
//print("counted ${destinationController.rogainingCounted.value}");
// Existing logic for other conditions
if (destination.cp == -1) {
return;
}
Get.back();
await destinationController.callforCheckin(destination);
} else {
return;
}
},
child: Text(
destination.cp == -1 &&
destinationController.isInRog.value == false &&
destinationController.rogainingCounted.value == false
? "ロゲ開始"
: destinationController.isInRog.value == true &&
destination.cp == -1
? "ゲーム中"
: isAlreadyCheckedIn == true
? "ゲーム中"
: destinationController.isInRog.value == 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<bool> isDestinationCheckedIn(Destination d) async {
DatabaseHelper db = DatabaseHelper.instance;
List<Destination> 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: () 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: destination.lat, lon: destination.lon);
destinationController
.destinationMatrixFromCurrentPoint([ds, tp]);
},
//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<Widget>(
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<Widget> 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<String, dynamic> temp =
Map<String, dynamic>.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<String, dynamic> temp = Map<String, dynamic>.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,
),
),
),
),
],
);
}
}