import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/devices_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_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/tm_module/device_transfer/device_filter_screen.dart'; import 'package:test_sa/modules/tm_module/device_transfer/device_search_screen.dart'; import 'package:test_sa/modules/export_module/pages/export_form_view.dart'; import 'package:test_sa/modules/export_module/models/export_module_type.dart'; import 'package:test_sa/views/widgets/equipment/asset_detail_page.dart'; import 'package:test_sa/views/widgets/equipment/asset_item_gridview.dart'; import 'package:test_sa/views/widgets/equipment/asset_item_listview.dart'; import 'package:test_sa/views/widgets/loaders/lazy_loading.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; import 'package:test_sa/views/widgets/qr/scan_qr.dart'; import '../../../models/device/asset.dart'; import '../../../models/device/asset_search.dart'; import '../../../new_views/app_style/app_color.dart'; import '../../../new_views/app_style/app_text_style.dart'; class MyAssetsPage extends StatefulWidget { static const String id = "/single-device-Picker"; final bool fromBottomBar; const MyAssetsPage({Key? key, this.fromBottomBar = false}) : super(key: key); @override _MyAssetsPageState createState() => _MyAssetsPageState(); } class _MyAssetsPageState extends State { late AssetProvider _devicesProvider; late UserProvider _userProvider; late SettingProvider _settingProvider; final List _searchableList = []; final List _initList = []; final bool _firstTime = true; DeviceSearch? _searchAsset; bool showListView = true; TextEditingController numberController = TextEditingController(); TextEditingController snController = TextEditingController(); _getDevice(String result, {bool isQr = false}) async { _devicesProvider.reset(); await _devicesProvider.getAssets(search: DeviceSearch(assetNo: result, assetSerialNumber: ""), isQr: isQr); _searchableList.clear(); _searchableList.addAll(_devicesProvider.devices); } @override void initState() { super.initState(); } @override void dispose() { numberController.dispose(); snController.dispose(); _devicesProvider.reset(); super.dispose(); } @override Widget build(BuildContext context) { _devicesProvider = Provider.of(context); _userProvider = Provider.of(context); _settingProvider = Provider.of(context); if (_firstTime) { _searchableList.clear(); _searchableList.addAll(_devicesProvider.devices); _initList.addAll(_devicesProvider.devices); } return Scaffold( resizeToAvoidBottomInset: false, appBar: AppBar( automaticallyImplyLeading: false, titleSpacing: 0, title: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ if (!widget.fromBottomBar) const Icon(Icons.arrow_back_ios).onPress(() { Navigator.of(context).pop(); }), Container( height: 40.toScreenHeight, padding: const EdgeInsets.only(left: 16, right: 8), alignment: Alignment.center, decoration: ShapeDecoration( color: AppColor.dropDownBackground(context), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(6), side: BorderSide(color: AppColor.borderColor(context)), ), ), child: Row( children: [ Icon(Icons.search, color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, size: 19), 8.width, Text( context.translation.search, style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), ).expanded, ], ), ).onPress(() async { final result = await Navigator.push(context, MaterialPageRoute(builder: (context) => const DeviceSearchScreen())); if (result != null) { _searchAsset = result; } _searchableList.clear(); _searchableList.addAll(_devicesProvider.devices); }).expanded, 16.width, Icon(Icons.grid_view_outlined, color: AppColor.icon2Color(context)).onPress(() => setState(() { showListView = !showListView; })), IconButton( icon: "download".toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)), padding: EdgeInsets.zero, onPressed: () async { await Navigator.push( context, CupertinoPageRoute( builder: (context) => ExportFormView( searchModel: _searchAsset, moduleType: ExportModuleType.asset, pageNo: _devicesProvider.pageItemNumber, pageSize: _devicesProvider.devices.length ~/ _devicesProvider.pageItemNumber + 1, ), ), ); }, ), IconButton( icon: "filter".toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)), padding: EdgeInsets.zero, onPressed: () async { final result = await Navigator.push(context, CupertinoPageRoute(builder: (context) => DeviceFilterScreen(data: _searchAsset))); if (result != null) { _searchAsset = result; } _searchableList.clear(); _searchableList.addAll(_devicesProvider.devices); }, ), ], ).paddingOnly(start: 16, end: 16), ), body: SafeArea( child: LoadingManager( isLoading: false, stateCode: _devicesProvider.stateCode, isFailedLoading: _devicesProvider.devices == null, onRefresh: () async { _devicesProvider.reset(); await _devicesProvider.getAssets(search: _searchAsset); }, child: Column( children: [ if (!_filterIsEmpty()) _buildActiveFiltersChips(), Expanded( child: _searchableList.isEmpty ? NoDataFound(message: context.translation.noDeviceFound).center : LazyLoading( nextPage: _devicesProvider.nextPage, onLazyLoad: () async { await _devicesProvider.getAssets( // user: _userProvider.user!, // host: _settingProvider.host!, // hospitalId: _userProvider.user!.clientId!, search: _searchAsset, // serialNumber: snController.text, // number: numberController.text, ); }, child: Stack( children: [ AnimatedSwitcher( duration: const Duration(milliseconds: 500), child: showListView ? ListView.separated( padding: const EdgeInsets.all(16), itemCount: _searchableList.length, separatorBuilder: (listContext, itemIndex) => 12.height, itemBuilder: (listContext, itemIndex) { return AssetItemListView( device: _searchableList[itemIndex], onPressed: (device) { widget.fromBottomBar ? Navigator.of(context).pushNamed(AssetDetailPage.id, arguments: device.id) : Navigator.of(context).pop(device); // Navigator.of(context).pushNamed(AssetDetailPage.id, arguments: device.id); }, ); }, ) : GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: 188 / 261, crossAxisSpacing: 12, mainAxisSpacing: 12), itemCount: _searchableList.length, padding: const EdgeInsets.all(16), itemBuilder: (context, index) { return AssetItemGridView( device: _searchableList[index], onPressed: (device) { widget.fromBottomBar ? Navigator.of(context).pushNamed(AssetDetailPage.id, arguments: device.id) : Navigator.of(context).pop(device); }, ); }, ), ), if (_devicesProvider.isLoading) Align(alignment: Alignment.bottomCenter, child: CircularProgressIndicator().paddingOnly(top: 16, bottom: 16)), ], ), )), ], ), ), ), floatingActionButton: FloatingActionButton( heroTag: "some tag 2", child: "qr".toSvgAsset(height: 32, fit: BoxFit.fitHeight, color: Theme.of(context).scaffoldBackgroundColor), onPressed: () async { String? result = await Navigator.of(context).push( MaterialPageRoute(builder: (_) => const ScanQr()), ) as String?; if (result != null) _getDevice(result, isQr: true); }, ), ); } bool _filterIsEmpty() { if (_searchAsset == null) return true; if ((_searchAsset!.assetName?.isNotEmpty ?? false) || (_searchAsset!.assetNo?.isNotEmpty ?? false) || (_searchAsset!.assetSerialNumber?.isNotEmpty ?? false) || (_searchAsset!.model?.isNotEmpty ?? false) || (_searchAsset!.supplier?.isNotEmpty ?? false) || (_searchAsset!.site?.isNotEmpty ?? false) || (_searchAsset!.manufacturer?.isNotEmpty ?? false) || (_searchAsset!.modelDefinition?.isNotEmpty ?? false) || (_searchAsset!.departments?.isNotEmpty ?? false) || (_searchAsset!.sites?.isNotEmpty ?? false) || (_searchAsset!.assetStatus != null) || (_searchAsset!.supplyDateFrom != null) || (_searchAsset!.supplyDateTo != null)) { return false; } return true; } Widget _buildActiveFiltersChips() { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( color: AppColor.background(context), border: Border( bottom: BorderSide(color: AppColor.borderColor(context), width: 1), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Active Filters', style: AppTextStyles.tinyFont2.copyWith( color: AppColor.labelTextStyleColor(context), fontWeight: FontWeight.w600, ), ), Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, spacing: 16, children: [ SizedBox( height: 40.toScreenHeight, child: ListView.separated( scrollDirection: Axis.horizontal, padding: const EdgeInsets.only(top: 8, right: 0, left: 0, bottom: 0), itemBuilder: (cxt, index) => _getActiveFilterChips()[index], separatorBuilder: (cxt, index) => 8.width, itemCount: _getActiveFilterChips().length, ), ).expanded, TextButton( onPressed: _clearAllFilters, style: TextButton.styleFrom( padding: EdgeInsets.zero, tapTargetSize: MaterialTapTargetSize.shrinkWrap, ), child: Text( 'Clear Filters', style: AppTextStyles.tinyFont.copyWith( color: AppColor.primary10, fontWeight: FontWeight.w500, ), ), ), ], ) ], ), ); } List _getActiveFilterChips() { List chips = []; // Asset Name if (_searchAsset?.assetName?.isNotEmpty ?? false) { chips.add(_buildFilterChip( label: '${context.translation.assetName}: ${_searchAsset!.assetName}', onDelete: () { setState(() { _searchAsset!.assetName = null; _refreshWithFilters(); }); }, )); } // Asset Number if (_searchAsset?.assetNo?.isNotEmpty ?? false) { chips.add(_buildFilterChip( label: '${context.translation.assetNumber}: ${_searchAsset!.assetNo}', onDelete: () { setState(() { _searchAsset!.assetNo = null; _refreshWithFilters(); }); }, )); } // Serial Number if (_searchAsset?.assetSerialNumber?.isNotEmpty ?? false) { chips.add(_buildFilterChip( label: '${context.translation.snNumber}: ${_searchAsset!.assetSerialNumber}', onDelete: () { setState(() { _searchAsset!.assetSerialNumber = null; _refreshWithFilters(); }); }, )); } // Model if (_searchAsset?.model?.isNotEmpty ?? false) { chips.add(_buildFilterChip( label: '${context.translation.model}: ${_searchAsset!.model}', onDelete: () { setState(() { _searchAsset!.model = null; _refreshWithFilters(); }); }, )); } // Supplier if (_searchAsset?.supplier?.isNotEmpty ?? false) { chips.add(_buildFilterChip( label: '${context.translation.supplier}: ${_searchAsset!.supplier}', onDelete: () { setState(() { _searchAsset!.supplier = null; _refreshWithFilters(); }); }, )); } // Site (single) if (_searchAsset?.site?.isNotEmpty ?? false) { chips.add(_buildFilterChip( label: '${context.translation.site}: ${_searchAsset!.site}', onDelete: () { setState(() { _searchAsset!.site = null; _refreshWithFilters(); }); }, )); } // Manufacturer if (_searchAsset?.manufacturer?.isNotEmpty ?? false) { chips.add(_buildFilterChip( label: '${context.translation.manufacture}: ${_searchAsset!.manufacturer}', onDelete: () { setState(() { _searchAsset!.manufacturer = null; _refreshWithFilters(); }); }, )); } // Model Definition if (_searchAsset?.modelDefinition?.isNotEmpty ?? false) { chips.add(_buildFilterChip( label: '${context.translation.md}: ${_searchAsset!.modelDefinition}', onDelete: () { setState(() { _searchAsset!.modelDefinition = null; _refreshWithFilters(); }); }, )); } // Asset Status (Commissioning Status) if (_searchAsset?.assetStatus != null) { chips.add(_buildFilterChip( label: 'Status: ${_searchAsset!.assetStatus!.name ?? 'Unknown'}', onDelete: () { setState(() { _searchAsset!.assetStatus = null; _refreshWithFilters(); }); }, )); } // Departments (multiple) if (_searchAsset?.departments?.isNotEmpty ?? false) { for (var dept in _searchAsset!.departments!) { chips.add(_buildFilterChip( label: '${context.translation.byDepartment}: $dept', onDelete: () { setState(() { _searchAsset!.departments!.remove(dept); _refreshWithFilters(); }); }, )); } } // Sites (multiple) if (_searchAsset?.sites?.isNotEmpty ?? false) { for (var site in _searchAsset!.sites!) { chips.add(_buildFilterChip( label: '${context.translation.bySite}: $site', onDelete: () { setState(() { _searchAsset!.sites!.remove(site); _refreshWithFilters(); }); }, )); } } // Date Range if (_searchAsset?.supplyDateFrom != null || _searchAsset?.supplyDateTo != null) { String dateLabel = 'Supply Date: '; if (_searchAsset!.supplyDateFrom != null && _searchAsset!.supplyDateTo != null) { dateLabel += '${_formatDate(_searchAsset!.supplyDateFrom!)} - ${_formatDate(_searchAsset!.supplyDateTo!)}'; } else if (_searchAsset!.supplyDateFrom != null) { dateLabel += 'From ${_formatDate(_searchAsset!.supplyDateFrom!)}'; } else if (_searchAsset!.supplyDateTo != null) { dateLabel += 'To ${_formatDate(_searchAsset!.supplyDateTo!)}'; } chips.add(_buildFilterChip( label: dateLabel, onDelete: () { setState(() { _searchAsset!.supplyDateFrom = null; _searchAsset!.supplyDateTo = null; _refreshWithFilters(); }); }, )); } return chips; } Widget _buildFilterChip({required String label, required VoidCallback onDelete}) { return Theme( data: Theme.of(context).copyWith( splashColor: Colors.transparent, highlightColor: Colors.transparent, ), child: Chip( backgroundColor: AppColor.backgroundTabBarColor(context), side: BorderSide(color: AppColor.border2Color(context)), label: Text(label), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30.0), ), labelStyle: AppTextStyles.tinyFont2.copyWith( color: AppColor.labelTextStyleColor(context), ), deleteIconColor: AppColor.icon2Color(context), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, onDeleted: onDelete, ), ); } String _formatDate(String dateString) { try { final date = DateTime.parse(dateString); return '${date.day}/${date.month}/${date.year}'; } catch (e) { return dateString; } } void _clearAllFilters() { setState(() { _searchAsset?.assetName = null; _searchAsset?.assetNo = null; _searchAsset?.assetSerialNumber = null; _searchAsset?.model = null; _searchAsset?.supplier = null; _searchAsset?.site = null; _searchAsset?.manufacturer = null; _searchAsset?.modelDefinition = null; _searchAsset?.assetStatus = null; _searchAsset?.departments?.clear(); _searchAsset?.sites?.clear(); _searchAsset?.supplyDateFrom = null; _searchAsset?.supplyDateTo = null; _searchAsset = null; _refreshWithFilters(); }); } void _refreshWithFilters() { _devicesProvider.reset(); _devicesProvider.getAssets(search: _searchAsset); _searchableList.clear(); _searchableList.addAll(_devicesProvider.devices); } }