Compare commits

...

2 Commits

@ -89,6 +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 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
@ -639,6 +640,7 @@ class URLs {
static get getPenguinFloors => "$_baseUrl/PenguinIN/floors";
static get getPenguinStatus => "$_baseUrl/PenguinIN/statuses";
static get getPenguinAssetTypes => "$_baseUrl/PenguinIN/assetTypes";
static get getPenguinAssetTags => "$_baseUrl/PenguinIN/tags";
static get getPenguinTagStatusLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=3037";
static get getPenguinTagAssignmentLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=3033";

@ -257,4 +257,16 @@ class AssetProvider extends ChangeNotifier {
return false;
}
}
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) {
return true;
}
return false;
} catch (error) {
return false;
}
}
}

@ -12,6 +12,7 @@ extension WidgetExtensions on Widget {
Widget onPress(VoidCallback? onTap) => InkWell(onTap: onTap, highlightColor: Colors.transparent, splashColor: Colors.transparent, child: this);
Widget get expanded => Expanded(child: this);
Widget get flexible => Flexible(child: this);
Widget get center => Center(child: this);

@ -64,6 +64,7 @@ class AssetByIdModel {
String? modelPhoto;
String? nextPMDate;
String? lastPMDate;
int? penguinAssetTagId;
bool? hasTrainingImageData;
TrainingImageData? trainingImageData;
@ -129,6 +130,7 @@ class AssetByIdModel {
this.modelPhoto,
this.nextPMDate,
this.lastPMDate,
this.penguinAssetTagId,
this.trainingImageData,
this.hasTrainingImageData});
@ -211,6 +213,7 @@ class AssetByIdModel {
modelPhoto = json['modelPhoto'];
nextPMDate = json['nextPMDate'];
lastPMDate = json['lastPMDate'];
penguinAssetTagId = json['penguinAssetTagId'];
hasTrainingImageData = json['hasTrainingImageData'];
trainingImageData = json['trainingImageData'] != null ? TrainingImageData.fromJson(json['trainingImageData']) : null;
}

@ -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';
@ -258,4 +259,52 @@ class AssetTrackingProvider extends ChangeNotifier {
notifyListeners();
}
}
int assetTagPageNumber = 1;
int? totalAssetTags;
List<AssetTagModel> tagList = [];
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 {
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["response"]["data"];
totalAssetTags ??= jsonData["response"]["totalRows"];
tagList.addAll(list.map((item) => AssetTagModel.fromJson(item)).toList());
if (tagList.length < totalAssetTags!) {
assetTagPageNumber += 1;
}
}
} catch (error) {}
isLoadingAssetTags = false;
notify();
}
Future<List> linkAssetWithPenguinTag(int assetId, int penguinTagId) async {
try {
final response = await ApiManager.instance.get(URLs.getPenguinAssetTags);
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body);
List list = jsonData["data"];
return list;
}
return [];
} catch (error) {
return [];
}
}
}

@ -13,6 +13,7 @@ import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/widgets/equipment/asset_tag_listview.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/equipment/asset_image_upload_page.dart';
@ -216,6 +217,13 @@ class _AssetDetailPageState extends State<AssetDetailPage> with SingleTickerProv
),
);
// final assetTagAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
// CurvedAnimation(
// parent: _animationController,
// curve: const Interval(0.80, 1.0, curve: Curves.easeOut),
// ),
// );
return Column(
children: [
SingleChildScrollView(
@ -336,6 +344,35 @@ class _AssetDetailPageState extends State<AssetDetailPage> with SingleTickerProv
InfoTextWidget(label: context.translation.installationDate, value: assetModel?.installationDate?.toAssetDetailsFormat, showEmptyValue: true),
InfoTextWidget(label: context.translation.nextPmDate, value: assetModel?.nextPMDate?.toAssetDetailsFormat, showEmptyValue: true),
InfoTextWidget(label: context.translation.lastPmDate, value: assetModel?.lastPMDate?.toAssetDetailsFormat, showEmptyValue: true),
if (assetModel?.penguinAssetTagId == null && context.userProvider.isEngineer) ...[
const Divider().defaultStyle(context),
Row(
mainAxisSize: MainAxisSize.min,
children: [
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),
decoration: BoxDecoration(
color: AppColor.primary10,
borderRadius: BorderRadius.circular(35),
),
child: Text(
"Link Tag",
style: AppTextStyles.bodyText2.copyWith(color: AppColor.addItemButtonColor(context)),
),
).onPress(_linkAssetTag),
],
),
] else ...[
const Divider().defaultStyle(context),
InfoHeaderWidget("Tag Information"),
InfoTextWidget(label: "Label", value: assetModel?.installationDate?.toAssetDetailsFormat, showEmptyValue: true),
InfoTextWidget(label: "Tag ID", value: assetModel?.installationDate?.toAssetDetailsFormat, showEmptyValue: true),
InfoTextWidget(label: "MAC Address", value: assetModel?.nextPMDate?.toAssetDetailsFormat, showEmptyValue: true),
InfoTextWidget(label: "Type", value: assetModel?.lastPMDate?.toAssetDetailsFormat, showEmptyValue: true),
InfoTextWidget(label: "Status", value: assetModel?.lastPMDate?.toAssetDetailsFormat, showEmptyValue: true),
],
],
),
),
@ -401,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(() {});
}
}
}

@ -0,0 +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 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 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,
),
),
);
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