asset tagging

main_production_asset_tracking
Sikander Saleem 5 days ago
parent 5658059543
commit e4f2089126

@ -89,7 +89,7 @@ class URLs {
static get getAssets => "$_baseUrl/Asset/GetAssets"; // get
static get getFaultDescription => "$_baseUrl/Asset/GetDefectForModelDefinition"; // get
static get getAssetById => "$_baseUrl/Asset/GetAssetById?assetId="; // get
static get assignTagToAsset => "$_baseUrl/Asset/AssignTagToAsset'"; // get
static get assignTagToAsset => "$_baseUrl/Asset/AssignTagToAsset"; // get
static get getAssetColumnsMetadata => "$_baseUrl/Asset/columns/metadata"; // get asset export columns metadata
static get saveAssetImages => "$_baseUrl/Asset/SaveAssetImages"; // get
static get getModels => "$_baseUrl/ModelDefinition/GetModelDefinitionAsset"; // get ?client=2

@ -258,17 +258,15 @@ class AssetProvider extends ChangeNotifier {
}
}
Future<List> linkAssetWithPenguinTag(int assetId, int penguinAssetTagId) async {
Future<bool> linkAssetWithPenguinTag(int assetId, int penguinAssetTagId) async {
try {
final response = await ApiManager.instance.post(URLs.assignTagToAsset, body: {"assetId": assetId, "penguinAssetTagId": penguinAssetTagId});
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body);
List list = jsonData["data"];
return list;
return true;
}
return [];
return false;
} catch (error) {
return [];
return false;
}
}
}

@ -5,6 +5,7 @@ import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/modules/asset_tracking/models/coordinates_model.dart';
import 'package:test_sa/modules/asset_tracking/models/asset_tracking_search_model.dart';
import 'package:test_sa/views/widgets/equipment/asset_tag_model.dart';
import 'models/asset_tracking_model.dart';
import 'models/floor_map_model.dart';
@ -260,19 +261,37 @@ class AssetTrackingProvider extends ChangeNotifier {
}
int assetTagPageNumber = 1;
int? totalAssetTags;
List<AssetTagModel> tagList = [];
Future<List> getPenguinAssetTags(int tagStatus) async {
bool isLoadingAssetTags = false;
void resetAssetTagData() {
tagList.clear();
assetTagPageNumber = 1;
totalAssetTags = null;
}
bool get isCanLoadMore => tagList.length < (totalAssetTags ?? 0);
Future getPenguinAssetTags() async {
if (isLoadingAssetTags) return;
try {
final response = await ApiManager.instance.get(URLs.getPenguinAssetTags + "?pageNumber=$assetTagPageNumber&tagStatus=$tagStatus");
isLoadingAssetTags = true;
notify();
final response = await ApiManager.instance.get(URLs.getPenguinAssetTags + "?pageNumber=$assetTagPageNumber&tagStatus=1");
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body);
List list = jsonData["data"];
return list;
List list = jsonData["response"]["data"];
totalAssetTags ??= jsonData["response"]["totalRows"];
tagList.addAll(list.map((item) => AssetTagModel.fromJson(item)).toList());
if (tagList.length < totalAssetTags!) {
assetTagPageNumber += 1;
}
}
return [];
} catch (error) {
return [];
}
} catch (error) {}
isLoadingAssetTags = false;
notify();
}
Future<List> linkAssetWithPenguinTag(int assetId, int penguinTagId) async {

@ -349,7 +349,7 @@ class _AssetDetailPageState extends State<AssetDetailPage> with SingleTickerProv
Row(
mainAxisSize: MainAxisSize.min,
children: [
const InfoTextLabelWidget(label: '*Asset is not associated with tag', color: AppColor.red30).flexible,
const InfoTextLabelWidget(label: '*Asset not linked with tracking tag', color: AppColor.red30).flexible,
Container(
margin: const EdgeInsets.only(left: 12, right: 12),
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
@ -359,15 +359,9 @@ class _AssetDetailPageState extends State<AssetDetailPage> with SingleTickerProv
),
child: Text(
"Link Tag",
style: AppTextStyles.bodyText2.copyWith(color: AppColor.textStyleColor(context)),
style: AppTextStyles.bodyText2.copyWith(color: AppColor.addItemButtonColor(context)),
),
).onPress(() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => AssetTagListView(),
),
);
}),
).onPress(_linkAssetTag),
],
),
] else ...[
@ -444,4 +438,14 @@ class _AssetDetailPageState extends State<AssetDetailPage> with SingleTickerProv
setState(() {});
}
}
void _linkAssetTag() async {
bool reload =
await Navigator.push(context, MaterialPageRoute(builder: (context) => AssetTagListView(assetId!, assetModel!.modelDefinition!.assetName!, assetModel!.multiAssets!.first.assetNumber!))) ??
false;
if (reload) {
assetModel = null;
setState(() {});
}
}
}

@ -1,75 +1,151 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/devices_provider.dart';
import 'package:test_sa/extensions/context_extension.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/helper/utils.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_tracking/asset_tracking_provider.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/views/widgets/dialogs/dialog.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/loaders/app_loading.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
class AssetTagListView extends StatelessWidget {
AssetTagListView({Key? key}) : super(key: key);
class AssetTagListView extends StatefulWidget {
int assetId;
String assetName;
String assetNumber;
AssetTagListView(this.assetId, this.assetName, this.assetNumber, {Key? key}) : super(key: key);
@override
_AssetTagListViewState createState() {
return _AssetTagListViewState();
}
}
class _AssetTagListViewState extends State<AssetTagListView> with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late AssetTrackingProvider assetTrackingProvider;
@override
void initState() {
super.initState();
assetTrackingProvider = Provider.of<AssetTrackingProvider>(context, listen: false);
assetTrackingProvider.resetAssetTagData();
_animationController = AnimationController(
duration: const Duration(milliseconds: 1200),
vsync: this,
);
_animationController.forward();
WidgetsBinding.instance.addPostFrameCallback((_) {
assetTrackingProvider.getPenguinAssetTags();
});
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const DefaultAppBar(title: "Available Tags"),
body: SizedBox());
appBar: const DefaultAppBar(title: "Available Tracking Tags"),
body: Consumer<AssetTrackingProvider>(builder: (context, provider, _) {
return provider.isLoadingAssetTags && provider.tagList.isEmpty
? const Center(child: ALoading())
: (provider.tagList.isEmpty && !provider.isLoading)
? NoDataFound(message: context.translation.noDataFound).center
: NotificationListener<ScrollNotification>(
onNotification: (scrollInfo) {
if (provider.isCanLoadMore && scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) {
assetTrackingProvider.getPenguinAssetTags();
}
return false;
},
child: SafeArea(
child: ListView.separated(
key: const ValueKey('asset-tag-list-view'),
padding: const EdgeInsets.all(16),
itemCount: provider.tagList.length + (provider.isLoadingAssetTags ? 1 : 0),
separatorBuilder: (listContext, itemIndex) => 12.height,
itemBuilder: (listContext, itemIndex) {
if (itemIndex == provider.tagList.length) {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: ALoading(),
);
}
final delay = itemIndex * 0.08;
final animation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: Interval(
delay.clamp(0.0, 0.7),
(delay + 0.4).clamp(0.0, 1.0),
curve: Curves.easeOut,
),
),
);
final slideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.15),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: Interval(
delay.clamp(0.0, 0.7),
(delay + 0.4).clamp(0.0, 1.0),
curve: Curves.easeOutCubic,
),
),
);
// FutureBuilder<List>(
// future: Provider.of<AssetTrackingProvider>(context, listen: false).getPenguinAssetTags(),
// builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
// if (snapshot.connectionState == ConnectionState.waiting) {
// return const Center(child: ALoading());
// } else if (snapshot.hasData) {}
//
// return SizedBox();
//
// // return ListView.separated(
// // key: const ValueKey('list_view'),
// // padding: const EdgeInsets.all(16),
// // itemCount: _searchableList.length,
// // separatorBuilder: (listContext, itemIndex) => 12.height,
// // itemBuilder: (listContext, itemIndex) {
// // // Calculate staggered animation delay
// // final delay = itemIndex * 0.08;
// // final animation = Tween<double>(begin: 0.0, end: 1.0).animate(
// // CurvedAnimation(
// // parent: _animationController,
// // curve: Interval(
// // delay.clamp(0.0, 0.7),
// // (delay + 0.4).clamp(0.0, 1.0),
// // curve: Curves.easeOut,
// // ),
// // ),
// // );
// //
// // final slideAnimation = Tween<Offset>(
// // begin: const Offset(0.0, 0.15),
// // end: Offset.zero,
// // ).animate(
// // CurvedAnimation(
// // parent: _animationController,
// // curve: Interval(
// // delay.clamp(0.0, 0.7),
// // (delay + 0.4).clamp(0.0, 1.0),
// // curve: Curves.easeOutCubic,
// // ),
// // ),
// // );
// //
// // return FadeTransition(
// // opacity: animation,
// // child: SlideTransition(
// // position: slideAnimation,
// // child: AssetItemListView(
// // device: _searchableList[itemIndex],
// // onPressed: (device) {
// // widget.fromBottomBar ? Navigator.of(context).pushNamed(AssetDetailPage.id, arguments: device.id) : Navigator.of(context).pop(device);
// // },
// // ),
// // ),
// // );
// // },
// // );
// }));
return FadeTransition(
opacity: animation,
child: SlideTransition(
position: slideAnimation,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InfoHeaderWidget(provider.tagList[itemIndex].label!),
InfoTextWidget(label: "TagID", value: provider.tagList[itemIndex].tagID, showEmptyValue: true),
InfoTextWidget(label: "Mac Address", value: provider.tagList[itemIndex].macAddress, showEmptyValue: true),
],
).toShadowContainer(context))
.onPress(() async {
bool result = await showDialog(
context: context,
builder: (_) => AAlertDialog(
title: "Confirm".addTranslation,
content: 'You are assigning\n'
'"${provider.tagList[itemIndex].label!}" -> "${widget.assetName}(${widget.assetNumber})"'
.addTranslation,
button1Text: "Assign",
),
);
if (result) {
Utils.showLoading(context);
result = await Provider.of<AssetProvider>(context, listen: false).linkAssetWithPenguinTag(widget.assetId, provider.tagList[itemIndex].id!);
Utils.hideLoading(context);
if (result) {
Navigator.pop(context, result);
}
}
}),
);
},
),
),
);
}));
}
}

@ -0,0 +1,44 @@
class AssetTagModel {
int? id;
String? tagID;
String? label;
String? macAddress;
String? type;
String? status;
String? assetName;
String? assetNumber;
AssetTagModel(
{this.id,
this.tagID,
this.label,
this.macAddress,
this.type,
this.status,
this.assetName,
this.assetNumber});
AssetTagModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
tagID = json['tagID'];
label = json['label'];
macAddress = json['macAddress'];
type = json['type'];
status = json['status'];
assetName = json['assetName'];
assetNumber = json['assetNumber'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['tagID'] = this.tagID;
data['label'] = this.label;
data['macAddress'] = this.macAddress;
data['type'] = this.type;
data['status'] = this.status;
data['assetName'] = this.assetName;
data['assetNumber'] = this.assetNumber;
return data;
}
}
Loading…
Cancel
Save