uninav/lib/components/feature_bottom_sheet.dart
2024-04-21 16:27:48 +02:00

357 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:uninav/components/colorful_chips.dart';
import 'package:uninav/controllers/map_controller.dart';
import 'package:uninav/controllers/navigation_controller.dart';
import 'package:uninav/data/geo/model.dart';
import 'package:uninav/nav/graph.dart';
import 'package:uninav/util/util.dart';
final _colorfulBoxDeco = BoxDecoration(
color: Colors.black,
border: Border.all(color: Colors.orange, width: 2),
borderRadius: BorderRadius.circular(10),
);
Future<void> showFeatureBottomSheet(
Feature feature, List<Feature>? closestFeatures) {
return Get.bottomSheet(
Theme(
data: ThemeData.light(),
child: Container(
constraints: const BoxConstraints(
// minHeight: 300,
),
width: Get.mediaQuery.size.width,
decoration: const BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30), topRight: Radius.circular(30)),
),
padding: const EdgeInsets.all(20),
child: Column(mainAxisSize: MainAxisSize.min, children: [
Center(
child: Container(
width: 50,
height: 5,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
),
),
const SizedBox(height: 10),
Text(formatFeatureTitle(feature),
style:
const TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
const SizedBox(height: 14),
if (closestFeatures != null) ...[
const Text('Did you mean:'),
Wrap(
spacing: 8,
children: closestFeatures
.map((nearFeature) => ColorfulActionChip(
label: formatFeatureTitle(nearFeature),
onPressed: () {
Get.back();
final newClosestFeatures = closestFeatures
.where((element) => element != nearFeature)
.toList();
newClosestFeatures.add(feature);
Get.find<MyMapController>().focusOnFeature(
nearFeature,
closestFeatures: newClosestFeatures);
},
))
.toList(),
),
const SizedBox(height: 14),
],
if (feature.description != null) ...[
Text(feature.description!),
const SizedBox(height: 10),
],
..._buildFeatureContent(feature),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(
child: const Row(
children: [
Icon(
Icons.share_location,
color: Colors.black,
),
SizedBox(width: 4),
Text(
"Start Navigation",
style: TextStyle(color: Colors.black),
),
],
),
onPressed: () {
print("trying to start navigation...");
final navController = Get.find<NavigationController>();
final mapController = Get.find<MyMapController>();
// make feature into graphFeature
final wrapped = wrap(
feature,
mapController.currentLevel.value,
feature.buildingName ?? "")
.first;
print("1");
Get.back();
if (navController.position.value == null) {
print("2");
Get.snackbar(
"Navigation failed!",
"Please set your position first!",
snackPosition: SnackPosition.BOTTOM,
margin: const EdgeInsets.only(
bottom: 20, left: 10, right: 10),
colorText: Colors.white,
backgroundColor: Colors.red,
duration: const Duration(seconds: 3),
);
} else {
print("3");
navController.navigate(navController.position.value!,
(feature) => feature.id == wrapped.id);
}
print("4");
},
),
],
)
]),
),
),
isScrollControlled: true,
enterBottomSheetDuration: const Duration(milliseconds: 150),
exitBottomSheetDuration: const Duration(milliseconds: 200),
);
}
List<Widget> _buildFeatureContent(Feature feature) {
return feature.type.when(
building: () => _buildBuildingContent(feature),
lectureHall: () => _buildLectureHallContent(feature),
room: (number) => _buildRoomContent(feature, number),
pcPool: (number) => _buildPcPoolContent(feature, number),
foodDrink: () => _buildFoodAndDrinkContent(feature),
door: (connects) => _buildDoorContent(feature, connects),
toilet: (toiletType) => _buildToiletContent(feature, toiletType),
stairs: (connectsLevels) => _buildStairsContent(feature, connectsLevels),
lift: (connectsLevels) => _buildLiftContent(feature, connectsLevels),
publicTransport: (busLines, tramLines) =>
_buildPublicTransportContent(feature, busLines, tramLines),
);
}
/// Builds the content for the Building feature type.
List<Widget> _buildBuildingContent(Feature feature) {
return [
Text(feature.name),
];
}
/// Builds the content for the LectureHall feature type.
List<Widget> _buildLectureHallContent(Feature feature) {
return [Text('Lecture Hall: ${feature.name}')];
}
/// Builds the content for the Room feature type.
List<Widget> _buildRoomContent(Feature feature, String roomNumber) {
return [Text('Room: ${feature.name}')];
}
List<Widget> _buildPcPoolContent(Feature feature, String roomNumber) {
return [Text('PC Pool: ${feature.name}')];
}
List<Widget> _buildFoodAndDrinkContent(Feature feature) {
return [Text('${feature.name} (Food/Drink)')];
}
/// Builds the content for the Door feature type.
List<Widget> _buildDoorContent(Feature feature, List<String> connects) {
return [
Text(
feature.name,
style: const TextStyle(fontSize: 18),
),
const SizedBox(height: 10),
if (connects.isNotEmpty) ...[
const Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: EdgeInsets.only(right: 4),
child: Text(
'Connects:',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
),
Align(
alignment: Alignment.centerLeft,
child: Wrap(
spacing: 8,
runSpacing: 4,
children: connects.map((place) {
return ColorfulChip(label: place.toString());
}).toList(),
),
),
],
];
}
/// Builds the content for the Toilet feature type.
List<Widget> _buildToiletContent(Feature feature, String toiletType) {
return [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.wc,
size: 60,
color: Colors.white,
),
Icon(
findToiletIcon(toiletType),
size: 60,
color: Colors.white,
)
],
)
];
}
/// Builds the content for the Stairs feature type.
List<Widget> _buildStairsContent(Feature feature, List<int> connectsLevels) {
return [
Text(
feature.name,
style: const TextStyle(fontSize: 18),
),
const SizedBox(height: 10),
if (connectsLevels.isNotEmpty) ...[
const Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: EdgeInsets.only(right: 4),
child: Text(
'Connects Levels:',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
),
Align(
alignment: Alignment.centerLeft,
child: Wrap(
spacing: 8,
runSpacing: 4,
children: connectsLevels.map((level) {
return ColorfulChip(label: level.toString());
}).toList(),
),
),
],
];
}
/// Builds the content for the Lift feature type.
List<Widget> _buildLiftContent(Feature feature, List<int> connectsLevels) {
return [
Text(
feature.name,
style: const TextStyle(fontSize: 18),
),
const SizedBox(height: 10),
if (connectsLevels.isNotEmpty) ...[
const Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: EdgeInsets.only(right: 4),
child: Text(
'Connects Levels:',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
),
Align(
alignment: Alignment.centerLeft,
child: Wrap(
spacing: 8,
runSpacing: 4,
children: connectsLevels.map((level) {
return ColorfulChip(label: level.toString());
}).toList(),
),
),
],
];
}
/// Builds the content for the PublicTransport feature type.
List<Widget> _buildPublicTransportContent(
Feature feature, List<String> busLines, List<String> tramLines) {
return [
Text(
feature.name,
style: const TextStyle(fontSize: 18),
),
const SizedBox(height: 10),
if (busLines.isNotEmpty) ...[
const Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: EdgeInsets.only(right: 4),
child: Text(
'Bus Lines:',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
),
Align(
alignment: Alignment.centerLeft,
child: Wrap(
spacing: 8,
runSpacing: 4,
children: busLines.map((line) {
return ColorfulChip(label: line);
}).toList(),
),
),
const SizedBox(height: 10),
],
if (tramLines.isNotEmpty) ...[
const Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: EdgeInsets.only(right: 4),
child: Text(
'Tram Lines:',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
),
Align(
alignment: Alignment.centerLeft,
child: Wrap(
spacing: 8,
runSpacing: 4,
children: tramLines.map((line) {
return ColorfulChip(label: line);
}).toList(),
),
),
],
];
}