map tracking added

main_production_asset_tracking
Sikander Saleem 3 weeks ago
parent 4b932099f5
commit addbe3f729

@ -632,8 +632,10 @@ class URLs {
// Asset Tracking APIs
static get getAssetsFromPenguin => "$_baseUrl/PenguinIN/GetAssetsFromPenguin";
static get getPenguinFloors => "$_baseUrl/PenguinIN/floors/";
static get getPenguinSites => "$_baseUrl/PenguinIN/sites/";
static get getPenguinBuildings => "$_baseUrl/PenguinIN/buildings/";
static get getPenguinDepartments => "$_baseUrl/PenguinIN/departments/";
static get getPenguinDepartments => "$_baseUrl/PenguinIN/departments";
static get getPenguinBuildings => "$_baseUrl/PenguinIN/buildings";
static get getPenguinFloors => "$_baseUrl/PenguinIN/floors";
}

@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import 'models/asset_tracking_model.dart';
class AssetTrackingListItemView extends StatelessWidget {
final AssetTrackingModel asset;
AssetTrackingListItemView(this.asset, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
StatusLabel(
label: (asset.location?.isLive ?? false) ? "Live" : "Not Live",
radius: 4,
textColor: AppColor.getPriorityStatusTextColor(context, (asset.location?.isLive ?? false) ? 0 : 1),
backgroundColor: AppColor.getPriorityStatusColor(context, (asset.location?.isLive ?? false) ? 0 : 1),
),
4.height,
InfoHeader16Widget(asset.label ?? ""),
InfoTextWidget(label: "Serial No", value: asset.label, showEmptyValue: true),
InfoTextWidget(label: "Type", value: asset.type?.name, showEmptyValue: true),
InfoTextWidget(label: "Status", value: asset.status?.name, showEmptyValue: true),
InfoTextWidget(label: "Department", value: asset.department?.name, showEmptyValue: true),
InfoTextWidget(
label: "Last seen",
value: asset.location?.lastSeen?.toServiceRequestDetailsFormat,
showEmptyValue: true,
showArrow: true,
arrowMsg: "View on map",
),
],
).toShadowContainer(context);
}
}

@ -18,6 +18,7 @@ import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import 'asset_tracking_item_view.dart';
import 'map_tracking_page.dart';
class AssetTrackingPage extends StatefulWidget {
@ -148,45 +149,12 @@ class _AssetTrackingPageState extends State<AssetTrackingPage> with SingleTicker
return FadeTransition(
opacity: animation,
child: SlideTransition(
position: slideAnimation,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
StatusLabel(
label: (provider.assetsList[itemIndex].location?.isLive ?? false) ? "Live" : "Not Live",
radius: 4,
textColor: AppColor.getPriorityStatusTextColor(context, (provider.assetsList[itemIndex].location?.isLive ?? false) ? 0 : 1),
backgroundColor: AppColor.getPriorityStatusColor(context, (provider.assetsList[itemIndex].location?.isLive ?? false) ? 0 : 1),
),
4.height,
InfoHeader16Widget(provider.assetsList[itemIndex].label ?? ""),
InfoTextWidget(label: "Serial No", value: provider.assetsList[itemIndex].label, showEmptyValue: true),
InfoTextWidget(label: "Type", value: provider.assetsList[itemIndex].type?.name, showEmptyValue: true),
InfoTextWidget(label: "Status", value: provider.assetsList[itemIndex].status?.name, showEmptyValue: true),
InfoTextWidget(label: "Department", value: provider.assetsList[itemIndex].department?.name, showEmptyValue: true),
InfoTextWidget(
label: "Last seen",
value: provider.assetsList[itemIndex].location?.lastSeen?.toServiceRequestDetailsFormat,
showEmptyValue: true,
showArrow: true,
arrowMsg: "View on map",
),
],
).toShadowContainer(context))
.onPress(() {
child: SlideTransition(position: slideAnimation, child: AssetTrackingListItemView(provider.assetsList[itemIndex])).onPress(() {
Navigator.push(context, MaterialPageRoute(builder: (context) => MapTrackingPage(assetTrackingData: provider.assetsList[itemIndex])));
}),
);
},
);
});
// Selector<AssetTrackingPage, bool>(
// selector: (_, myModel) => myModel, // Selects only the userName
// builder: (_, isLoading, __) {
//
// });
}
}

@ -6,6 +6,7 @@ import 'package:test_sa/controllers/api_routes/urls.dart';
import 'models/asset_tracking_model.dart';
import 'models/floor_map_model.dart';
import 'models/penguin_site_model.dart';
class AssetTrackingProvider extends ChangeNotifier {
bool isLoading = false;
@ -14,9 +15,30 @@ class AssetTrackingProvider extends ChangeNotifier {
int pageNo = 1;
List<AssetTrackingModel> assetsList = [];
List<AssetTrackingModel> assetsOnTheFloorList = [];
List<PenguinSiteModel> sitesList = [];
PenguinSiteModel? selectedSite;
List<PenguinSiteModel> buildList = [];
PenguinSiteModel? selectedBuilding;
List<PenguinSiteModel> floorList = [];
PenguinSiteModel? selectedFloor;
String get getExpansionHeader =>
(selectedBuilding == null || selectedBuilding == null || selectedFloor == null) ? "Search Floor Map" : "${selectedSite!.label} > ${selectedBuilding!.label} > ${selectedFloor!.label}";
reset() {
isLoading = false;
selectedFloor = null;
selectedBuilding = null;
selectedSite = null;
assetsList = [];
assetsOnTheFloorList = [];
notify();
}
notify() {
notifyListeners();
}
@ -40,7 +62,6 @@ class AssetTrackingProvider extends ChangeNotifier {
if (jsonData["totalRows"] <= assetsList.length) {
// nextPage = true;
}
print("assetsList:${assetsList.length}");
// if (loadMore) {
// assetInventoryResponse?.assetList?.addAll(newResponse.assetList ?? []);
// assetInventoryResponse?.totalRows = newResponse.totalRows;
@ -65,16 +86,104 @@ class AssetTrackingProvider extends ChangeNotifier {
}
}
Future getAssetsFromPenguinByFloorId(int floorId) async {
try {
assetsOnTheFloorList.clear();
final response = await ApiManager.instance.post(URLs.getAssetsFromPenguin, body: {
"floorIds": [floorId]
});
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body);
List list = jsonData["data"];
assetsOnTheFloorList.addAll(list.map((item) => AssetTrackingModel.fromJson(item)).toList());
}
notifyListeners();
} catch (error) {
notifyListeners();
}
}
Future<FloorMapModel?> getFloorMap(int floorId) async {
FloorMapModel? floorMapModel;
try {
final response = await ApiManager.instance.get(URLs.getPenguinFloors + "$floorId/maps");
final response = await ApiManager.instance.get(URLs.getPenguinFloors + "/$floorId/maps");
if (response.statusCode >= 200 && response.statusCode < 300) {
floorMapModel = FloorMapModel.fromJson(json.decode(response.body)["data"]);
final geoJsonResponse = await ApiManager.instance.get(floorMapModel.geojsonUrl!);
floorMapModel.geojsonData = json.decode(geoJsonResponse.body);
}
return floorMapModel;
} catch (error) {
return floorMapModel;
}
}
Future getPenguinSites() async {
try {
sitesList.clear();
buildList.clear();
floorList.clear();
selectedSite = null;
selectedBuilding = null;
selectedFloor = null;
final response = await ApiManager.instance.get(URLs.getPenguinSites);
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body);
List list = jsonData["data"];
sitesList.addAll(list.map((item) => PenguinSiteModel.fromJson(item)).toList());
}
notifyListeners();
} catch (error) {
notifyListeners();
}
}
Future<List<PenguinSiteModel>> getPenguinDepartments(int id) async {
List<PenguinSiteModel> sitesList = [];
try {
final response = await ApiManager.instance.get(URLs.getPenguinDepartments + "?siteId=$id");
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body);
List list = jsonData["data"];
sitesList.addAll(list.map((item) => PenguinSiteModel.fromJson(item)).toList());
}
return sitesList;
} catch (error) {
return sitesList;
}
}
Future getPenguinBuildings(int id) async {
try {
buildList.clear();
floorList.clear();
selectedBuilding = null;
selectedFloor = null;
final response = await ApiManager.instance.get(URLs.getPenguinBuildings + "?siteId=$id");
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body);
List list = jsonData["data"];
buildList.addAll(list.map((item) => PenguinSiteModel.fromJson(item)).toList());
}
notifyListeners();
} catch (error) {
notifyListeners();
}
}
Future getPenguinFloors(int id) async {
try {
floorList.clear();
selectedFloor = null;
final response = await ApiManager.instance.get(URLs.getPenguinFloors + "?buildingId=$id");
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body);
List list = jsonData["data"];
floorList.addAll(list.map((item) => PenguinSiteModel.fromJson(item)).toList());
}
notifyListeners();
} catch (error) {
notifyListeners();
}
}
}

@ -5,15 +5,20 @@ import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_geojson2/flutter_map_geojson2.dart';
import 'package:latlong2/latlong.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/helper/utils.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'asset_tracking_item_view.dart';
import 'asset_tracking_provider.dart';
import 'models/asset_tracking_model.dart';
import 'models/floor_map_model.dart';
import 'models/penguin_site_model.dart';
class MapTrackingPage extends StatefulWidget {
final AssetTrackingModel? assetTrackingData;
@ -35,6 +40,7 @@ class _MapTrackingPageState extends State<MapTrackingPage> {
FloorMapModel? floorMapModel;
Map<String, dynamic>? _geojson;
List<Marker> markers = [];
LatLngBounds? _computedBounds;
final ExpansibleController expansibleController = ExpansibleController();
@ -48,10 +54,30 @@ class _MapTrackingPageState extends State<MapTrackingPage> {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!inAppView) {
getFloorMap(widget.assetTrackingData!.location!.floor!.id!);
} else {
getPenguinSites();
}
});
}
void getPenguinSites() async {
Utils.showLoading(context);
await assetTrackingProvider.getPenguinSites();
Utils.hideLoading(context);
}
void getPenguinBuildings(int id) async {
Utils.showLoading(context);
await assetTrackingProvider.getPenguinBuildings(id);
Utils.hideLoading(context);
}
void getPenguinFloors(int id) async {
Utils.showLoading(context);
await assetTrackingProvider.getPenguinFloors(id);
Utils.hideLoading(context);
}
void getFloorMap(int id) {
Utils.showLoading(context);
assetTrackingProvider.getFloorMap(id).then((floorMap) {
@ -62,6 +88,10 @@ class _MapTrackingPageState extends State<MapTrackingPage> {
});
}
void getAssetsOnTheFloor(int id) {
assetTrackingProvider.getAssetsFromPenguinByFloorId(id);
}
void _onFloorMapLoaded(FloorMapModel? loadedFloorMap) {
floorMapModel = loadedFloorMap;
@ -133,6 +163,11 @@ class _MapTrackingPageState extends State<MapTrackingPage> {
);
}
double _dragPosition = 0.5;
late double _sheetPosition = _dragPosition;
final minChildSize = 0.25;
final maxChildSize = 1.0;
@override
Widget build(BuildContext context) {
Widget mapWidget = FlutterMap(
@ -149,6 +184,25 @@ class _MapTrackingPageState extends State<MapTrackingPage> {
styleDefaults: GeoJsonStyleDefaults.leaflet,
),
if (!inAppView) MarkerLayer(markers: markers),
Selector<AssetTrackingProvider, List<AssetTrackingModel>>(
selector: (_, myModel) => myModel.assetsOnTheFloorList,
builder: (_, assetsOnTheFloorList, __) {
return assetsOnTheFloorList.isEmpty
? const SizedBox()
: DraggableScrollableSheet(
initialChildSize: _sheetPosition,
builder: (BuildContext context, ScrollController scrollController) {
return Flexible(
child: ListView.builder(
controller: scrollController,
itemCount: assetsOnTheFloorList.length,
itemBuilder: (BuildContext context, int index) {
return AssetTrackingListItemView(assetsOnTheFloorList[index]);
},
),
);
});
}),
]
],
);
@ -168,22 +222,75 @@ class _MapTrackingPageState extends State<MapTrackingPage> {
),
child: Theme(
data: ThemeData(splashColor: Colors.transparent, hoverColor: Colors.transparent, highlightColor: Colors.transparent),
child: ExpansionTile(
shape: Border.all(color: Colors.transparent, width: 0),
collapsedShape: Border.all(color: Colors.transparent, width: 0),
controller: expansibleController,
title: const InfoTextLabelWidget(label: "Search Floor Map"),
iconColor: AppColor.icon2Color(context),
collapsedIconColor: AppColor.icon2Color(context),
dense: true,
children: <Widget>[
],
childrenPadding: EdgeInsets.all(0),
tilePadding: EdgeInsets.all(0),
),
child: Consumer<AssetTrackingProvider>(builder: (context, assetProvider, _) {
return ExpansionTile(
shape: Border.all(color: Colors.transparent, width: 0),
collapsedShape: Border.all(color: Colors.transparent, width: 0),
controller: expansibleController,
title: InfoTextLabelWidget(label: assetProvider.getExpansionHeader),
iconColor: AppColor.icon2Color(context),
collapsedIconColor: AppColor.icon2Color(context),
dense: true,
childrenPadding: const EdgeInsets.all(0),
tilePadding: const EdgeInsets.all(0),
children: <Widget>[
SingleItemDropDownMenu<PenguinSiteModel, NullableLoadingProvider>(
context: context,
title: "Select Site",
staticData: assetProvider.sitesList,
initialValue: assetProvider.selectedSite,
showShadow: false,
// backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
onSelect: (value) {
if (value != null) {
assetProvider.selectedSite = value;
getPenguinBuildings(value.id!);
}
},
),
4.height,
SingleItemDropDownMenu<PenguinSiteModel, NullableLoadingProvider>(
context: context,
title: "Select Building",
staticData: assetProvider.buildList,
initialValue: assetProvider.selectedBuilding,
showShadow: false,
enabled: assetProvider.selectedSite != null,
// backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
onSelect: (value) {
if (value != null) {
assetProvider.selectedBuilding = value;
getPenguinFloors(value.id!);
}
},
),
4.height,
SingleItemDropDownMenu<PenguinSiteModel, NullableLoadingProvider>(
context: context,
title: "Select Floor",
staticData: assetProvider.floorList,
initialValue: assetProvider.selectedFloor,
showShadow: false,
enabled: assetProvider.selectedBuilding != null,
// backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
onSelect: (value) {
if (value != null) {
assetProvider.selectedFloor = value;
expansibleController.collapse();
getFloorMap(value.id!);
getAssetsOnTheFloor(value.id!);
}
},
),
16.height,
],
);
}),
),
),
)
],
)
: Scaffold(appBar: const DefaultAppBar(title: "Live Asset Tracking"), body: mapWidget);

@ -0,0 +1,25 @@
import 'package:test_sa/models/base.dart';
class PenguinSiteModel extends Base {
int? id;
String? label;
bool? isMapped;
PenguinSiteModel({this.id, this.label}) : super(identifier: id?.toString(), name: label);
PenguinSiteModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
identifier = json['id']?.toString();
label = json['label'];
name = json['label'];
isMapped = json['isMapped'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['label'] = this.label;
data['isMapped'] = this.isMapped;
return data;
}
}
Loading…
Cancel
Save