device predication inprogess
parent
8cc76265b1
commit
2ae26cc363
@ -0,0 +1,116 @@
|
||||
class PredictDeviceResponse {
|
||||
bool? success;
|
||||
String? timestamp;
|
||||
List<PredictedAsset>? predictedAsset;
|
||||
|
||||
PredictDeviceResponse({
|
||||
this.success,
|
||||
this.timestamp,
|
||||
this.predictedAsset,
|
||||
});
|
||||
|
||||
PredictDeviceResponse.fromJson(Map<String, dynamic> json) {
|
||||
success = json['success'];
|
||||
timestamp = json['timestamp'];
|
||||
|
||||
if (json['PredictedAsset'] != null) {
|
||||
predictedAsset = <PredictedAsset>[];
|
||||
|
||||
for (var item in json['PredictedAsset']) {
|
||||
predictedAsset!.add(
|
||||
PredictedAsset.fromJson(item),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'success': success,
|
||||
'timestamp': timestamp,
|
||||
'PredictedAsset':
|
||||
predictedAsset?.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class PredictedAsset {
|
||||
String? assetId;
|
||||
String? assetName;
|
||||
num? confidence;
|
||||
String? confidencePercent;
|
||||
PredictedAssetMetadata? metadata;
|
||||
|
||||
PredictedAsset({
|
||||
this.assetId,
|
||||
this.assetName,
|
||||
this.confidence,
|
||||
this.confidencePercent,
|
||||
this.metadata,
|
||||
});
|
||||
|
||||
PredictedAsset.fromJson(Map<String, dynamic> json) {
|
||||
assetId = json['assetid'];
|
||||
assetName = json['asset_name'];
|
||||
confidence = json['confidence'];
|
||||
confidencePercent = json['confidence_percent'];
|
||||
|
||||
if (json['metadata'] != null) {
|
||||
metadata = PredictedAssetMetadata.fromJson(
|
||||
json['metadata'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'assetid': assetId,
|
||||
'asset_name': assetName,
|
||||
'confidence': confidence,
|
||||
'confidence_percent': confidencePercent,
|
||||
'metadata': metadata?.toJson(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class PredictedAssetMetadata {
|
||||
String? siteId;
|
||||
String? siteName;
|
||||
String? assetName;
|
||||
String? oracleCode;
|
||||
String? assetNumber;
|
||||
String? departmentId;
|
||||
String? departmentName;
|
||||
|
||||
PredictedAssetMetadata({
|
||||
this.siteId,
|
||||
this.siteName,
|
||||
this.assetName,
|
||||
this.oracleCode,
|
||||
this.assetNumber,
|
||||
this.departmentId,
|
||||
this.departmentName,
|
||||
});
|
||||
|
||||
PredictedAssetMetadata.fromJson(Map<String, dynamic> json) {
|
||||
siteId = json['site_id'];
|
||||
siteName = json['site_name'];
|
||||
assetName = json['asset_name'];
|
||||
oracleCode = json['oracle_code'];
|
||||
assetNumber = json['asset_number'];
|
||||
departmentId = json['department_id'];
|
||||
departmentName = json['department_name'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'site_id': siteId,
|
||||
'site_name': siteName,
|
||||
'asset_name': assetName,
|
||||
'oracle_code': oracleCode,
|
||||
'asset_number': assetNumber,
|
||||
'department_id': departmentId,
|
||||
'department_name': departmentName,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/extensions/context_extension.dart';
|
||||
import 'package:test_sa/extensions/int_extensions.dart';
|
||||
import 'package:test_sa/extensions/text_extensions.dart';
|
||||
import 'package:test_sa/extensions/widget_extensions.dart';
|
||||
import 'package:test_sa/models/device/predict_device_model.dart';
|
||||
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
|
||||
|
||||
import '../../../new_views/app_style/app_color.dart';
|
||||
|
||||
class PredictDeviceItemGridView extends StatelessWidget {
|
||||
final PredictedAsset device;
|
||||
final Function(PredictedAsset) onPressed;
|
||||
|
||||
const PredictDeviceItemGridView({Key? key, required this.device, required this.onPressed}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
device.assetName!.cleanupWhitespace.capitalizeFirstOfEach,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: AppTextStyles.bodyText.copyWith(color: AppColor.textStyleColor(context)),
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
InfoTextWidget(label: context.translation.assetNumber, value: device.metadata?.assetNumber),
|
||||
InfoTextWidget(label: 'Matching Percentage', value: device.confidencePercent),
|
||||
InfoTextWidget(label: context.translation.oracleCode, value: device.metadata?.oracleCode),
|
||||
InfoTextWidget(label: context.translation.site, value: device.metadata?.siteName),
|
||||
InfoTextWidget(label: context.translation.department, value: device.metadata?.departmentName),
|
||||
],
|
||||
).expanded,
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'View Details',
|
||||
style: AppTextStyles.bodyText2.copyWith(color: AppColor.primary10),
|
||||
),
|
||||
4.width,
|
||||
const Icon(Icons.arrow_forward, color: AppColor.primary10, size: 14)
|
||||
],
|
||||
),
|
||||
],
|
||||
).expanded.onPress(() => onPressed(device)).toShadowContainer(context);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/extensions/context_extension.dart';
|
||||
import 'package:test_sa/extensions/int_extensions.dart';
|
||||
import 'package:test_sa/extensions/text_extensions.dart';
|
||||
import 'package:test_sa/extensions/widget_extensions.dart';
|
||||
import 'package:test_sa/models/device/predict_device_model.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';
|
||||
|
||||
class PredictDeviceItemView extends StatelessWidget {
|
||||
final PredictedAsset device;
|
||||
final Function(PredictedAsset) onPressed;
|
||||
final Widget? selectButton;
|
||||
final bool isSelected;
|
||||
|
||||
const PredictDeviceItemView({Key? key, required this.device, required this.onPressed, this.selectButton, this.isSelected = false}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
InfoHeaderWidget(device.assetName!.cleanupWhitespace),
|
||||
4.height,
|
||||
InfoTextWidget(label: context.translation.assetNumber, value: device.metadata?.assetNumber),
|
||||
InfoTextWidget(label: 'Matching Percentage', value: device.confidencePercent),
|
||||
InfoTextWidget(label: context.translation.oracleCode, value: device.metadata?.oracleCode),
|
||||
InfoTextWidget(label: context.translation.site, value: device.metadata?.siteName),
|
||||
InfoTextWidget(label: context.translation.department, value: device.metadata?.departmentName),
|
||||
],
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: selectButton ??
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
context.translation.viewDetails,
|
||||
style: AppTextStyles.bodyText2.copyWith(color: AppColor.primary10),
|
||||
),
|
||||
4.width,
|
||||
const Icon(Icons.arrow_forward, color: AppColor.primary10, size: 14)
|
||||
],
|
||||
))
|
||||
],
|
||||
).expanded.toShadowContainer(context, borderColor: isSelected ? AppColor.primary10 : Colors.transparent).onPress(() => onPressed(device));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,180 @@
|
||||
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/widget_extensions.dart';
|
||||
import 'package:test_sa/models/device/predict_device_model.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/views/widgets/equipment/asset_detail_page.dart';
|
||||
import 'package:test_sa/views/widgets/equipment/predict_device_item_grid_view.dart';
|
||||
import 'package:test_sa/views/widgets/equipment/predict_device_item_view.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
|
||||
|
||||
class PredictDeviceView extends StatefulWidget {
|
||||
static const String id = "/single-device-Picker";
|
||||
List<PredictedAsset> predictedAsset;
|
||||
|
||||
PredictDeviceView({Key? key, required this.predictedAsset}) : super(key: key);
|
||||
|
||||
@override
|
||||
_PredictDeviceViewState createState() => _PredictDeviceViewState();
|
||||
}
|
||||
|
||||
class _PredictDeviceViewState extends State<PredictDeviceView> with SingleTickerProviderStateMixin {
|
||||
late AssetProvider _devicesProvider;
|
||||
bool showListView = true;
|
||||
late AnimationController _animationController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_animationController = AnimationController(
|
||||
duration: const Duration(milliseconds: 1200),
|
||||
vsync: this,
|
||||
);
|
||||
_animationController.forward();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_animationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_devicesProvider = Provider.of<AssetProvider>(context);
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: DefaultAppBar(
|
||||
title: 'Predicated Devices',
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Icon(!showListView ? Icons.view_list_sharp : Icons.grid_view_outlined, color: AppColor.icon2Color(context)),
|
||||
padding: EdgeInsets.zero,
|
||||
iconSize: 20,
|
||||
visualDensity: VisualDensity.compact,
|
||||
tooltip: !showListView ? "View as List" : "View as Grid",
|
||||
onPressed: () => setState(() {
|
||||
showListView = !showListView;
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: widget.predictedAsset.isEmpty
|
||||
? NoDataFound(message: context.translation.noDeviceFound).center
|
||||
: Stack(
|
||||
children: [
|
||||
AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 500),
|
||||
child: showListView
|
||||
? ListView.separated(
|
||||
key: const ValueKey('list_view'),
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemCount: widget.predictedAsset.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: PredictDeviceItemView(
|
||||
device: widget.predictedAsset[itemIndex],
|
||||
onPressed: (device) {
|
||||
Navigator.of(context).pushNamed(AssetDetailPage.id, arguments: device.assetId);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: GridView.builder(
|
||||
key: const ValueKey('grid_view'),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: 188 / 261, crossAxisSpacing: 12, mainAxisSpacing: 12),
|
||||
itemCount: widget.predictedAsset.length,
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemBuilder: (context, index) {
|
||||
// Calculate staggered animation delay
|
||||
final delay = index * 0.08;
|
||||
final animation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||
CurvedAnimation(
|
||||
parent: _animationController,
|
||||
curve: Interval(
|
||||
delay.clamp(0.0, 0.8),
|
||||
(delay + 0.3).clamp(0.0, 1.0),
|
||||
curve: Curves.easeOut,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final slideAnimation = Tween<Offset>(
|
||||
begin: const Offset(0.0, 0.3),
|
||||
end: Offset.zero,
|
||||
).animate(
|
||||
CurvedAnimation(
|
||||
parent: _animationController,
|
||||
curve: Interval(
|
||||
delay.clamp(0.0, 0.8),
|
||||
(delay + 0.3).clamp(0.0, 1.0),
|
||||
curve: Curves.easeOutCubic,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return FadeTransition(
|
||||
opacity: animation,
|
||||
child: SlideTransition(
|
||||
position: slideAnimation,
|
||||
child: PredictDeviceItemGridView(
|
||||
device: widget.predictedAsset[index],
|
||||
onPressed: (device) {
|
||||
Navigator.of(context).pushNamed(AssetDetailPage.id, arguments: device.assetId);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
if (_devicesProvider.isLoading) Align(alignment: Alignment.bottomCenter, child: CircularProgressIndicator().paddingOnly(top: 16, bottom: 16)),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue