You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cloudsolutions-atoms/lib/modules/asset_tracking/asset_tracking_page.dart

260 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:provider/provider.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/modules/asset_tracking/asset_tracking_provider.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/loaders/no_data_found.dart';
import 'asset_tracking_item_view.dart';
import 'map_tracking_page.dart';
class AssetTrackingPage extends StatefulWidget {
AssetTrackingPage({Key? key}) : super(key: key);
@override
_AssetTrackingPageState createState() {
return _AssetTrackingPageState();
}
}
class _AssetTrackingPageState extends State<AssetTrackingPage> with SingleTickerProviderStateMixin {
int selectedIndex = 1;
late AnimationController _animationController;
late AssetTrackingProvider assetTrackingProvider;
@override
void initState() {
super.initState();
assetTrackingProvider = Provider.of<AssetTrackingProvider>(context, listen: false);
_animationController = AnimationController(
duration: const Duration(milliseconds: 1200),
vsync: this,
);
_animationController.forward();
WidgetsBinding.instance.addPostFrameCallback((_) {
assetTrackingProvider.reset();
getAssetsFromPenguin();
});
}
Future<void> getAssetsFromPenguin({bool loadMore = false}) async {
await assetTrackingProvider.getAssetsFromPenguin(
loadMore: loadMore,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const DefaultAppBar(title: "Live Asset Tracking"),
body: Column(
// crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: double.infinity,
child: SegmentedButton<int>(
multiSelectionEnabled: false,
emptySelectionAllowed: false,
expandedInsets: const EdgeInsets.only(left: 16, top: 8, right: 16, bottom: 8),
style: SegmentedButton.styleFrom(
side: BorderSide(color: AppColor.borderColor(context)),
textStyle: AppTextStyles.bodyText,
backgroundColor: AppColor.background(context),
foregroundColor: context.isDark ? AppColor.neutral30 : AppColor.black20,
selectedForegroundColor: AppColor.addItemButtonColor(context),
selectedBackgroundColor: AppColor.primary10,
),
segments: <ButtonSegment<int>>[
ButtonSegment<int>(
value: 1,
label: const Text("List"),
icon: Icon(Icons.list_rounded, color: AppColor.icon2Color(context)),
),
ButtonSegment<int>(
value: 2,
label: const Text("Grid"),
icon: Icon(Icons.grid_view_rounded, color: AppColor.icon2Color(context)),
),
ButtonSegment<int>(
value: 3,
label: const Text("Map"),
icon: Icon(Icons.map, color: AppColor.icon2Color(context)),
),
],
selected: <int>{selectedIndex},
onSelectionChanged: (Set<int> newSelection) {
setState(() {
selectedIndex = newSelection.first;
});
},
),
),
SafeArea(
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: selectedIndex == 1
? assetsListView()
: selectedIndex == 2
? assetsGridView()
: MapTrackingPage()
// selectedIndex == 3 ? MapTrackingPage() : assetsListView(),
),
).expanded,
],
),
);
}
Widget assetsListView() {
return Consumer<AssetTrackingProvider>(builder: (context, provider, _) {
return (provider.assetsList.isEmpty && !provider.isLoading)
? NoDataFound(message: context.translation.noDataFound).center
: NotificationListener<ScrollNotification>(
onNotification: (scrollInfo) {
if (!provider.isNextPageLoading && provider.nextPage && scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) {
getAssetsFromPenguin(loadMore: true);
}
return false;
},
child: ListView.separated(
key: const ValueKey('asset-list_view'),
padding: const EdgeInsets.all(16),
itemCount: provider.isLoading ? 6 : provider.assetsList.length + (provider.isNextPageLoading ? 1 : 0),
separatorBuilder: (listContext, itemIndex) => 12.height,
itemBuilder: (listContext, itemIndex) {
if (provider.isLoading) return const SizedBox().toAssetListShimmer(listContext, provider.isLoading);
if (itemIndex >= provider.assetsList.length) {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Center(child: CircularProgressIndicator()),
);
}
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: AssetTrackingListItemView(provider.assetsList[itemIndex])).onPress(() {
Navigator.push(context, MaterialPageRoute(builder: (context) => MapTrackingPage(assetTrackingData: provider.assetsList[itemIndex])));
}),
);
},
),
);
});
}
Widget assetsGridView() {
return Consumer<AssetTrackingProvider>(builder: (context, provider, _) {
return (provider.assetsList.isEmpty && !provider.isLoading)
? NoDataFound(message: context.translation.noDataFound).center
:
// ListView.separated(
//
// padding: const EdgeInsets.all(16),
NotificationListener<ScrollNotification>(
onNotification: (scrollInfo) {
if (!provider.isLoading &&
!provider.isNextPageLoading &&
provider.nextPage &&
scrollInfo.metrics.pixels >= (scrollInfo.metrics.maxScrollExtent - 200)) {
getAssetsFromPenguin(loadMore: true);
}
return false;
},
child: Column(
children: [
Expanded(
child: GridView.builder(
key: const ValueKey('asset-grid_view'),
padding: const EdgeInsets.all(16),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: .8,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
itemCount: provider.isLoading ? 6 : provider.assetsList.length,
// separatorBuilder: (listContext, itemIndex) => 12.height,
itemBuilder: (listContext, itemIndex) {
if (provider.isLoading) return const SizedBox().toAssetListShimmer(listContext, provider.isLoading);
// 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: AssetTrackingListItemView(provider.assetsList[itemIndex])).onPress(() {
Navigator.push(context, MaterialPageRoute(builder: (context) => MapTrackingPage(assetTrackingData: provider.assetsList[itemIndex])));
}),
);
},
),
),
if (provider.isNextPageLoading)
const Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Center(child: CircularProgressIndicator()),
),
],
),
);
});
}
}