Complete refactoring SFM App Source Code

This commit is contained in:
anhtunz
2024-12-15 00:59:02 +07:00
parent caa73ca43c
commit 2e27d59278
247 changed files with 18390 additions and 0 deletions

View File

@@ -0,0 +1,344 @@
// ignore_for_file: use_build_context_synchronously
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'show_direction_widget.dart';
import 'show_nearest_place.dart';
import '../../../product/constant/icon/icon_constants.dart';
import '../../../product/extention/context_extention.dart';
import '../map_bloc.dart';
import '../../../product/services/api_services.dart';
import '../../../product/services/language_services.dart';
import '../../../product/utils/device_utils.dart';
import '../../devices/device_model.dart';
onTapMarker(
BuildContext context,
Completer<GoogleMapController> controller,
MapBloc mapBloc,
LatLng myLocation,
Iterable<Device> devices,
List<String> imageAssets,
List<Marker> otherMarkers,
BitmapDescriptor hospitalIcon,
BitmapDescriptor fireStationIcon,
) {
LatLng testLocation = const LatLng(20.985453, 105.738381);
showModalBottomSheet(
context: context,
builder: (BuildContext modalBottomSheetContext) {
if (devices.length == 1) {
List<Device> devicesList = devices.toList();
final device = devicesList[0];
String deviceState = DeviceUtils.instance
.checkStateDevice(modalBottomSheetContext, device.state ?? 3);
String imgStringAsset;
if (device.state == 0) {
imgStringAsset = imageAssets[0];
} else if (device.state == 1) {
imgStringAsset = imageAssets[2];
} else {
imgStringAsset = imageAssets[1];
}
return Padding(
padding: context.paddingLow,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"${appLocalization(context).device_title}: ${device.name}",
style: context.titleLargeTextStyle,
),
],
),
SizedBox(
height: context.lowValue,
),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () async {
Navigator.pop(modalBottomSheetContext);
var destination = LatLng(
double.parse(device.settings!.latitude!),
double.parse(device.settings!.longitude!),
);
mapBloc.findTheWay(
context,
controller,
testLocation,
destination,
);
String deviceLocations = await DeviceUtils.instance
.getFullDeviceLocation(context, device.areaPath!);
String yourLocation =
appLocalization(context).map_your_location;
showDirections(
context,
controller,
otherMarkers,
mapBloc,
yourLocation,
deviceLocations,
double.parse(device.settings!.latitude!),
double.parse(device.settings!.longitude!),
);
},
style: const ButtonStyle(
backgroundColor: MaterialStatePropertyAll(Colors.blue),
foregroundColor: MaterialStatePropertyAll(Colors.white),
),
child: Row(
children: [
IconConstants.instance
.getMaterialIcon(Icons.turn_right),
Text(appLocalization(modalBottomSheetContext)
.map_show_direction),
],
),
),
SizedBox(
width: context.lowValue,
),
ElevatedButton.icon(
onPressed: () {
Navigator.pop(modalBottomSheetContext);
showNearPlacesSideSheet(
context,
double.parse(device.settings!.latitude!),
double.parse(device.settings!.longitude!),
"Bệnh viện gần nhất",
5000,
"hospital",
mapBloc,
controller,
otherMarkers,
hospitalIcon,
fireStationIcon,
);
},
style: const ButtonStyle(
backgroundColor: MaterialStatePropertyAll(Colors.pink),
foregroundColor: MaterialStatePropertyAll(Colors.white),
),
icon: IconConstants.instance
.getMaterialIcon(Icons.local_hospital),
label: Text(appLocalization(modalBottomSheetContext)
.map_nearby_hospital),
),
SizedBox(
width: context.lowValue,
),
ElevatedButton.icon(
onPressed: () {
Navigator.pop(modalBottomSheetContext);
showNearPlacesSideSheet(
context,
double.parse(device.settings!.latitude!),
double.parse(device.settings!.longitude!),
"đội pccc gần nhất",
5000,
"fire_station",
mapBloc,
controller,
otherMarkers,
hospitalIcon,
fireStationIcon,
);
},
style: const ButtonStyle(
backgroundColor: MaterialStatePropertyAll(Colors.red),
foregroundColor: MaterialStatePropertyAll(Colors.white),
),
icon: IconConstants.instance
.getMaterialIcon(Icons.fire_truck_outlined),
label: Text(appLocalization(modalBottomSheetContext)
.map_nearby_firestation),
),
],
),
),
SizedBox(height: context.lowValue),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'${appLocalization(modalBottomSheetContext).paginated_data_table_column_deviceStatus}: '),
SizedBox(
height: 25,
width: 25,
child: CircleAvatar(
minRadius: 20,
maxRadius: 20,
backgroundImage: AssetImage(imgStringAsset),
),
),
SizedBox(width: context.lowValue),
Text(
deviceState,
style: context.bodyMediumTextStyle,
),
],
),
],
),
);
// Tiếp tục xử lý mảng devices
} else if (devices.length > 1) {
DeviceSource deviceSource = DeviceSource(
DeviceUtils.instance.sortDeviceByState(devices.toList()),
modalBottomSheetContext,
controller,
mapBloc,
);
// Devices là một phần tử
return Padding(
padding: context.paddingLow,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Center(
child: Text(
appLocalization(modalBottomSheetContext)
.paginated_data_table_title,
style: context.titleLargeTextStyle,
),
),
PaginatedDataTable(
columns: [
DataColumn(
label: Center(
child: Text(
appLocalization(modalBottomSheetContext)
.input_name_device_device,
),
),
),
DataColumn(
label: Center(
child: Text(
appLocalization(modalBottomSheetContext)
.paginated_data_table_column_deviceStatus,
),
),
),
DataColumn(
label: Center(
child: Text(
appLocalization(modalBottomSheetContext)
.paginated_data_table_column_deviceBaterry,
),
),
),
DataColumn(
label: Center(
child: Text(
appLocalization(modalBottomSheetContext)
.paginated_data_table_column_deviceSignal,
),
),
),
],
source: deviceSource,
rowsPerPage: 5,
),
],
),
);
} else {
return Text(appLocalization(modalBottomSheetContext).undefine_message);
}
},
);
}
class DeviceSource extends DataTableSource {
BuildContext context;
MapBloc mapBloc;
final List<Device> devices;
final Completer<GoogleMapController> controller;
DeviceSource(this.devices, this.context, this.controller, this.mapBloc);
APIServices apiServices = APIServices();
@override
DataRow? getRow(int index) {
if (index >= devices.length) {
return null;
}
final device = devices[index];
Map<String, dynamic> sensorMap = DeviceUtils.instance
.getDeviceSensors(context, device.status?.sensors ?? []);
String deviceState =
DeviceUtils.instance.checkStateDevice(context, device.state!);
return DataRow.byIndex(
color: MaterialStatePropertyAll(
DeviceUtils.instance.getTableRowColor(device.state ?? -1),
),
index: index,
cells: [
DataCell(
Text(device.name!),
onTap: () {
mapBloc.updateCameraPosition(
controller,
double.parse(device.settings!.latitude!),
double.parse(device.settings!.longitude!),
16,
);
Navigator.pop(context);
},
),
DataCell(
Text(deviceState),
onTap: () {
mapBloc.updateCameraPosition(
controller,
double.parse(device.settings!.latitude!),
double.parse(device.settings!.longitude!),
16,
);
},
),
DataCell(
Text(sensorMap['sensorBattery'] + "%"),
onTap: () {
mapBloc.updateCameraPosition(
controller,
double.parse(device.settings!.latitude!),
double.parse(device.settings!.longitude!),
16,
);
},
),
DataCell(
Text(sensorMap['sensorCsq']),
onTap: () {
mapBloc.updateCameraPosition(
controller,
double.parse(device.settings!.latitude!),
double.parse(device.settings!.longitude!),
16,
);
},
),
],
);
}
@override
bool get isRowCountApproximate => false;
@override
int get rowCount => devices.length;
@override
int get selectedRowCount => 0;
}

View File

@@ -0,0 +1,124 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maps_launcher/maps_launcher.dart';
import 'package:sfm_app/product/constant/icon/icon_constants.dart';
import 'package:sfm_app/product/extention/context_extention.dart';
import 'package:sfm_app/product/services/language_services.dart';
import '../map_bloc.dart';
showDirections(
BuildContext context,
Completer<GoogleMapController> controller,
List<Marker> markers,
MapBloc mapBloc,
String originalName,
String destinationLocation,
double devicelat,
double devicelng,
) {
TextEditingController originController =
TextEditingController(text: originalName);
TextEditingController destinationController =
TextEditingController(text: destinationLocation);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: Colors.transparent,
// dismissDirection: DismissDirection.none,
duration: const Duration(minutes: 5),
content: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
appLocalization(context).map_show_direction,
style: context.titleLargeTextStyle,
),
Container(
alignment: Alignment.centerRight,
child: IconButton.outlined(
onPressed: () async {
await mapBloc.updateCameraPosition(
controller,
devicelat,
devicelng,
13.0,
);
List<LatLng> polylineCoordinates = [];
mapBloc.sinkPolylines.add(polylineCoordinates);
markers.clear();
if (context.mounted) {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
}
},
icon: IconConstants.instance.getMaterialIcon(Icons.close),
),
)
],
),
Row(
children: [
Text(
'${appLocalization(context).map_start}: ',
),
SizedBox(width: context.lowValue),
Expanded(
child: TextField(
controller: originController,
readOnly: true,
),
),
],
),
SizedBox(
height: context.lowValue,
),
Row(
children: [
Text(
'${appLocalization(context).map_destination}: ',
),
SizedBox(width: context.lowValue),
Expanded(
child: TextField(
controller: destinationController,
readOnly: true,
),
),
],
),
SizedBox(height: context.lowValue),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton.icon(
onPressed: () async {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
List<LatLng> polylineCoordinates = [];
mapBloc.sinkPolylines.add(polylineCoordinates);
MapsLauncher.launchCoordinates(devicelat, devicelng);
},
icon: IconConstants.instance
.getMaterialIcon(Icons.near_me_rounded),
label: Text(
appLocalization(context).map_stream,
),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.blue[300]!),
),
),
],
),
],
),
),
);
}

View File

@@ -0,0 +1,226 @@
// ignore_for_file: use_build_context_synchronously
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import '../map_bloc.dart';
import 'show_direction_widget.dart';
import '../../../product/constant/icon/icon_constants.dart';
import '../../../product/extention/context_extention.dart';
import '../../../product/services/language_services.dart';
import '../../../product/services/map_services.dart';
import '../../../product/shared/model/near_by_search_model.dart';
showNearPlacesSideSheet(
BuildContext context,
double latitude,
double longitude,
String searchKey,
int radius,
String type,
MapBloc mapBloc,
Completer<GoogleMapController> controller,
List<Marker> markers,
BitmapDescriptor hospitalIcon,
BitmapDescriptor fireStationIcon,
) async {
double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;
LatLng testLocation = LatLng(latitude, longitude);
List<PlaceDetails> placeDetails = [];
placeDetails =
await findLocation(latitude, longitude, searchKey, radius, type);
await mapBloc.updateCameraPosition(controller, latitude, longitude, 12.0);
if (placeDetails.isNotEmpty) {
for (int i = 0; i < placeDetails.length; i++) {
Marker marker = Marker(
markerId: MarkerId(placeDetails[i].result!.placeId!),
position: LatLng(placeDetails[i].result!.geometry!.location!.lat!,
placeDetails[i].result!.geometry!.location!.lng!),
infoWindow: InfoWindow(title: placeDetails[i].result!.name!),
icon:
searchKey == "Bệnh viện gần nhất" ? hospitalIcon : fireStationIcon,
);
markers.add(marker);
}
}
showModalBottomSheet(
context: context,
builder: (modalBottomSheetContext) {
return Container(
padding: context.paddingLow,
width: screenWidth,
height: screenHeight / 3,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Center(
child: Text(
'${appLocalization(modalBottomSheetContext).map_result}: ',
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
Container(
alignment: Alignment.centerRight,
child: IconButton(
onPressed: () async {
Navigator.pop(modalBottomSheetContext);
markers.clear();
await mapBloc.updateCameraPosition(
controller,
latitude,
longitude,
14.0,
);
},
icon: IconConstants.instance.getMaterialIcon(Icons.close),
),
),
],
),
if (placeDetails.isNotEmpty)
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: placeDetails.length,
itemBuilder: (BuildContext listViewContext, int index) {
final place = placeDetails[index];
return GestureDetector(
onTap: () async {
await mapBloc.updateCameraPosition(
controller,
place.result!.geometry!.location!.lat!,
place.result!.geometry!.location!.lng!,
17.0,
);
},
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: Container(
padding: listViewContext.paddingLow,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
),
width: screenWidth / 1.5,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
place.result!.name!,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
SizedBox(height: listViewContext.lowValue),
Text(
'${appLocalization(listViewContext).change_profile_address} ${place.result!.formattedAddress} '),
SizedBox(height: listViewContext.lowValue),
if (place.result?.openingHours?.openNow == null)
Text(
appLocalization(listViewContext)
.map_always_opened,
style: const TextStyle(
color: Colors.green,
),
)
else
place.result?.openingHours?.openNow ?? false
? Text(
appLocalization(listViewContext)
.map_openning,
style: const TextStyle(
color: Colors.green,
),
)
: Text(
appLocalization(listViewContext)
.map_closed,
style: const TextStyle(
color: Colors.red,
),
),
SizedBox(
height: listViewContext.lowValue,
),
Center(
child: ElevatedButton.icon(
style: const ButtonStyle(
backgroundColor:
MaterialStatePropertyAll(Colors.blue),
foregroundColor:
MaterialStatePropertyAll(Colors.white),
),
onPressed: () async {
Navigator.pop(modalBottomSheetContext);
var destination = LatLng(
place.result!.geometry!.location!.lat!,
place.result!.geometry!.location!.lng!);
mapBloc.findTheWay(context, controller,
testLocation, destination);
// findTheWay(myLocation, destination);
await mapBloc.updateCameraPosition(
controller,
place.result!.geometry!.location!.lat!,
place.result!.geometry!.location!.lng!,
13.0,
);
showDirections(
context,
controller,
markers,
mapBloc,
appLocalization(context)
.map_your_location,
place.result!.name!,
latitude,
longitude,
);
},
icon: IconConstants.instance
.getMaterialIcon(Icons.turn_right),
label: Text(appLocalization(listViewContext)
.map_show_direction),
),
),
],
),
),
),
);
},
),
)
else
Center(
child: Text(
appLocalization(modalBottomSheetContext).map_no_results,
),
),
],
),
);
},
);
}
Future<List<PlaceDetails>> findLocation(double latitude, double longitude,
String searchKey, int radius, String type) async {
MapServices mapServices = MapServices();
final nearByPlaces = await mapServices.getNearbyPlaces(
latitude, longitude, searchKey, radius, type);
return nearByPlaces.isNotEmpty ? nearByPlaces : [];
}