Files
rog_app/lib/widgets/bottom_sheets/bottom_sheet_base.dart

325 lines
10 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:geolocator/geolocator.dart';
import 'package:rogapp/model/destination.dart';
import 'package:rogapp/pages/index/index_controller.dart';
import 'package:rogapp/utils/const.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:rogapp/pages/destination/destination_controller.dart';
class BottomSheetBase extends StatelessWidget {
BottomSheetBase({super.key, required this.destination,this.isAlreadyCheckedIn = false});
final IndexController indexController = Get.find<IndexController>();
final DestinationController destinationController = Get.find<DestinationController>();
final bool isAlreadyCheckedIn; // すでにチェックイン済みかどうかのフラグ
final Destination destination; // 目的地オブジェクト
// そのポイントの写真を取得するメソッド
//
Image getImage() {
String serverUrl = ConstValues.currentServer();
// currentDestinationFeature(destinationそのもの)のphotoデータのチェック
// Nouffer のコードでは、indexController.rogMode によって、destination(currentDestinationFeature) かGeoJSONFeature(currentFeature)の違いで処理が分かれていた。
// しかし、現在のコードでは GeoJSONFeature gf = indexController.currentFeature[0]; は使われていない。
//
if (indexController.currentDestinationFeature[0].photos! == "") {
// 定義されていなければ、empty_image.png を選択
return const Image(image: AssetImage('assets/images/empty_image.png'));
} else {
String photo = indexController.currentDestinationFeature[0].photos!;
if (photo.contains('http')) {
// photo にhttpの文字が含まれていれば、ネットから拾ってくる。エラーならempty_image.pngを表示。
return Image(
image: NetworkImage(
indexController.currentDestinationFeature[0].photos!,
),
errorBuilder:
(BuildContext context, Object exception, StackTrace? stackTrace) {
return Image.asset("assets/images/empty_image.png");
},
);
} else {
// photo にhttpの文字が含まれていなければ、指定サーバー($serverUrl/media/compressed/*)から拾ってくる。エラーならempty_image.pngを表示。
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");
},
);
}
}
}
// URLを開くためのメソッドです。
// url_launcherパッケージを使用して、指定されたURLを開きます。
//
void _launchURL(url) async {
if (!await launchUrl(url)) throw 'Could not launch $url';
}
// 指定されたlocationidが目的地リストに含まれているかどうかを確認するメソッドです。
// destinationController.destinationsリストを走査し、locationidが一致する目的地があるかどうかを返します。
//
bool isInDestination(String locationid) {
int lid = int.parse(locationid);
if (destinationController.destinations
.where((element) => element.location_id == lid)
.isNotEmpty) {
return true;
} else {
return false;
}
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: buildWidgets(context),
),
);
}
// このメソッドはList<Widget>を返します。
List<Widget> buildWidgets(BuildContext context) {
return [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
MaterialButton(
onPressed: () {
Get.back();
},
color: Colors.blue,
textColor: Colors.white,
padding: const EdgeInsets.all(16),
shape: const CircleBorder(),
child: const Icon(Icons.arrow_back_ios, size: 14),
),
Expanded(
child: Container(
alignment: Alignment.center,
child: Obx(() => Text("${destination.sub_loc_id} : ${destination.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: getDetails(context),
)),
const SizedBox(height: 60.0),
];
}
Widget getDetails(BuildContext context) {
return Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
const Icon(Icons.roundabout_left),
const SizedBox(
width: 8.0,
),
destination.address != null && destination.address!.isNotEmpty
? getDetailsItem(
context,
"address".tr,
destination.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,
),
destination.phone != null && destination.phone!.isNotEmpty
? getDetailsItem(
context,
"telephone".tr,
destination.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,
),
destination.email != null && destination.email!.isNotEmpty
? getDetailsItem(
context,
"email".tr,
destination.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,
),
destination.webcontents != null &&
destination.webcontents!.isNotEmpty
? getDetailsItem(
context,
"web".tr,
destination.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
? getDetailsItem(
context,
"remarks".tr,
indexController.currentFeature[0]
.properties!["remark"] ??
'',
isUrl: false)
: const SizedBox(
width: 0.0,
height: 0,
),
],
),
),
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]);
// TODO: Implement "ここへ行く" functionality
},
child: Text(
"ルート",
style: TextStyle(
color: Theme.of(context).colorScheme.onPrimary,
),
),
),
const SizedBox(
width: 10,
),
],
),
],
);
}
Widget getDetailsItem(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) {
_launchURL(destination.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,
),
),
),
),
],
);
}
}