import 'package:flutter/material.dart'; import 'package:geojson_vi/geojson_vi.dart'; import 'package:get/get.dart'; import 'package:rogapp/model/destination.dart'; import 'package:rogapp/pages/destination/destination_controller.dart'; import 'package:rogapp/pages/index/index_controller.dart'; import 'package:rogapp/services/maxtrix_service.dart'; import 'package:rogapp/utils/const.dart'; import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_start.dart'; import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_goal.dart'; import 'package:rogapp/widgets/bottom_sheets/bottom_sheet_normal_point.dart'; class ListWidget extends StatefulWidget { const ListWidget({Key? key}) : super(key: key); @override State createState() => _ListWidgetState(); } // IndexControllerから目的地のリストを取得し、ListView.builderを使用してリストを表示します。 // 各リストアイテムは、目的地の画像、名前、カテゴリ、サブロケーションID、現在地からの距離を表示します。 // リストアイテムがタップされると、changeCurrentFeatureメソッドを呼び出して現在の目的地を更新し、 BottomSheetウィジェットを表示します。 // 主なロジック: // IndexControllerから目的地のリストを取得し、ListView.builderを使用してリストを構築します。 // getImageメソッドを使用して、目的地の画像を取得し表示します。画像が存在しない場合は、デフォルトの画像を表示します。 // matrixDistanceメソッドを使用して、現在地から目的地までの距離を計算し表示します。 // リストアイテムがタップされると、changeCurrentFeatureメソッドを呼び出して現在の目的地を更新し、showModalBottomSheetを使用してBottomSheetウィジェットを表示します。 // class _ListWidgetState extends State { final IndexController indexController = Get.find(); final DestinationController destinationController = Get.find(); Image getImage(int index) { if (indexController.locations[0].features[index]!.properties!["photos"] == null || indexController.locations[0].features[index]!.properties!["photos"] == "") { return const Image(image: AssetImage('assets/images/empty_image.png')); } else { //print("==== photo index is $index ==="); String serverUrl = ConstValues.currentServer(); GeoJSONFeature gf = indexController.locations[0].features[index]!; String photo = gf.properties!["photos"]; return Image( image: NetworkImage('$serverUrl/media/compressed/$photo'), errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { return Image.asset("assets/images/empty_image.png"); }, ); } } // 未使用? void changeCurrentFeature(GeoJSONFeature fs) { if (indexController.currentFeature.isNotEmpty) { indexController.currentFeature.clear(); } indexController.currentFeature.add(fs); } @override void initState() { super.initState(); } Destination createDestination(GeoJSONFeature feature) { final props = feature.properties; GeoJSONMultiPoint pt = feature.geometry as GeoJSONMultiPoint; return Destination( cp: props!['cp'], lat: pt.coordinates[0][1], lon: pt.coordinates[0][0], ); } Future matrixDistance(int i) async { // Create two destinations directly from indexController.locations[0].collection Destination desCurr = Destination( lat: indexController.currentLat, lon: indexController.currentLon); //Destination dest1 = createDestination(indexController.locations[0].collection[0]); Destination dest2 = createDestination(indexController.locations[0].features[i]!); // Get the distance between these two destinations final res = await MatrixService.getDestinations([desCurr, dest2]); return res["routes"][0]["legs"][0]["distance"]["text"]; //print("matrix result is ${i} : ${res["routes"][0]["legs"][0]["distance"]["text"]} "); } Future _pullRefresh() async { //print("pull to refesh"); indexController.locations[0].features.sort((a, b) => (a!.properties!['cp'] as Comparable) .compareTo(b!.properties!['cp'] as Comparable)); setState(() {}); } @override Widget build(BuildContext context) { return Obx( () => indexController.locations.isNotEmpty ? RefreshIndicator( onRefresh: _pullRefresh, child: ListView.builder( itemCount: indexController.locations[0].features.length, shrinkWrap: true, itemBuilder: (_, index) { bool isFound = false; for (Destination d in destinationController.destinations) { if (indexController.locations[0].features[index]! .properties!['location_id'] == d.location_id) { isFound = true; break; } } return Card( child: ListTile( selected: isFound, selectedTileColor: Colors.yellow.shade200, onTap: () { GeoJSONFeature gf = indexController.locations[0].features[index]!; Destination des = destinationController.festuretoDestination(gf); changeCurrentFeature(gf); Widget bottomSheet; if (des.cp == -1 || des.cp == 0) { bottomSheet = BottomSheetStart(destination: des); } else if (des.cp == -2 || des.cp == 0) { bottomSheet = BottomSheetGoal(destination: des); } else { bottomSheet = BottomSheetNormalPoint(destination: des); } showModalBottomSheet( constraints: BoxConstraints.loose( Size(Get.width, Get.height * 0.85)), isScrollControlled: true, context: context, builder: ((context) => bottomSheet ), ); }, leading: getImage(index), title: indexController.locations[0].features[index]! .properties!['location_name'] != null ? Text(indexController.locations[0].features[index]! .properties!['location_name'] .toString()) : const Text(""), subtitle: indexController.locations[0].features[index]! .properties!['category'] != null ? Text(indexController.locations[0].features[index]! .properties!['category']) : const Text(""), trailing: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ indexController.locations[0].features[index]! .properties!['sub_loc_id'] != null ? Text(indexController.locations[0] .features[index]!.properties!['sub_loc_id']) : const Text(""), SizedBox( width: 100, child: FutureBuilder( future: matrixDistance(index), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center( child: CircularProgressIndicator(), ); } if (snapshot.hasError) { return const Text("-"); } else { return Text( snapshot.data ?? '', style: const TextStyle( color: Colors.red, fontWeight: FontWeight.bold), ); } }, ), ) ], )), ); }, ), ) : const SizedBox( width: 0, height: 0, ), ); } }