import 'dart:async'; import 'package:data_table_2/data_table_2.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'add_new_device_widget.dart'; import 'delete_device_widget.dart'; import 'device_model.dart'; import '../../product/shared/shared_pie_chart.dart'; import '../../bloc/devices_manager_bloc.dart'; import '../../product/base/bloc/base_bloc.dart'; import '../../product/constant/enums/app_route_enums.dart'; import '../../product/constant/enums/role_enums.dart'; import '../../product/constant/icon/icon_constants.dart'; import '../../product/extension/context_extension.dart'; import '../../product/services/api_services.dart'; import '../../product/services/language_services.dart'; import '../../product/utils/device_utils.dart'; class DevicesManagerScreen extends StatefulWidget { const DevicesManagerScreen({super.key}); @override State createState() => _DevicesManagerScreenState(); } class _DevicesManagerScreenState extends State { late DevicesManagerBloc devicesManagerBloc; String role = "Undefine"; APIServices apiServices = APIServices(); List devices = []; Timer? getAllDevicesTimer; List tags = []; int tagIndex = -2; @override void initState() { super.initState(); devicesManagerBloc = BlocProvider.of(context); getUserRole(); const duration = Duration(seconds: 10); getAllDevicesTimer = Timer.periodic( duration, (Timer t) => devicesManagerBloc.getDeviceByState(tagIndex), ); } @override void dispose() { getAllDevicesTimer?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( // backgroundColor: Colors.grey.withValues(alpha: 0.6), body: StreamBuilder>( stream: devicesManagerBloc.streamTagStates, builder: (context, tagSnapshot) { return SafeArea( child: StreamBuilder>( stream: devicesManagerBloc.streamAllDevices, initialData: devices, builder: (context, allDeviceSnapshot) { if (allDeviceSnapshot.data?.isEmpty ?? devices.isEmpty) { devicesManagerBloc .getDeviceByState(tagSnapshot.data?[0] ?? -2); return const Center(child: CircularProgressIndicator()); } else { if (tagSnapshot.data!.isNotEmpty) { tagIndex = tagSnapshot.data![0]; devicesManagerBloc.sinkTagStates.add([tagIndex]); } return SingleChildScrollView( child: Column( children: [ if (tagSnapshot.hasData && tagSnapshot.data!.isNotEmpty && tagSnapshot.data![0] != -2) TagState( state: tagSnapshot.data![0], devicesManagerBloc: devicesManagerBloc, ), SizedBox(height: context.lowValue), StreamBuilder( stream: devicesManagerBloc.streamUserRole, initialData: role, builder: (context, roleSnapshot) { return SizedBox( height: context.dynamicHeight(0.4), child: CardTheme( color: Theme.of(context).colorScheme.onPrimary, shadowColor: Theme.of(context).colorScheme.onPrimary, child: PaginatedDataTable2( headingRowHeight: 30, columnSpacing: 30, horizontalMargin: 10, fixedLeftColumns: 1, autoRowsToHeight: true, renderEmptyRowsInTheEnd: false, dragStartBehavior: DragStartBehavior.down, minWidth: 950, header: Center( child: Text( appLocalization(context) .paginated_data_table_title, style: context.headlineMediumTextStyle, ), ), columns: [ if (roleSnapshot.data == RoleEnums.ADMIN.name || roleSnapshot.data == RoleEnums.USER.name) DataColumn( label: Text(appLocalization(context) .paginated_data_table_column_deviceName), ), DataColumn( label: Text(appLocalization(context) .paginated_data_table_column_deviceStatus), ), DataColumn( label: Text(appLocalization(context) .paginated_data_table_column_deviceBaterry), ), DataColumn( label: Text(appLocalization(context) .paginated_data_table_column_deviceSignal), ), DataColumn( label: Text(appLocalization(context) .paginated_data_table_column_deviceTemperature), ), DataColumn( label: Text(appLocalization(context) .paginated_data_table_column_deviceHump), ), DataColumn( label: Text(appLocalization(context) .paginated_data_table_column_devicePower), ), DataColumn( label: Text(appLocalization(context) .paginated_data_table_column_action), ), ], onPageChanged: (int pageIndex) { // log('Chuyen page: $pageIndex'); }, // rowsPerPage: // (allDeviceSnapshot.data?.length ?? 1) < 6 // ? (allDeviceSnapshot.data?.length ?? // 0) // : 5, actions: [ if (roleSnapshot.data == RoleEnums.USER.name || roleSnapshot.data == RoleEnums.ADMIN.name) IconButton( style: ButtonStyle( backgroundColor: WidgetStateProperty.all( Colors.green), iconColor: WidgetStateProperty.all( Colors.white, ), ), onPressed: () { ScaffoldMessenger.of(context) .clearSnackBars(); addNewDevice(context, roleSnapshot.data ?? role); }, icon: IconConstants.instance .getMaterialIcon(Icons.add)) ], source: DeviceSource( devices: allDeviceSnapshot.data ?? devices, context: context, devicesBloc: devicesManagerBloc, role: role, ), ), ), ); }, ), SizedBox(height: context.lowValue), Text( appLocalization(context).overview_message, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), StreamBuilder>>( stream: devicesManagerBloc.streamDeviceByState, builder: (context, devicesByStateSnapshot) { if (devicesByStateSnapshot.data == null) { devicesManagerBloc.getDeviceByState( tagSnapshot.data?[0] ?? -2); return const Center( child: CircularProgressIndicator()); } else { return SharedPieChart( deviceByState: devicesByStateSnapshot.data ?? {}, devicesManagerBloc: devicesManagerBloc, ); } }, ), ], ), ); } }, ), ); }), ); } void getUserRole() async { role = await apiServices.getUserRole(); devicesManagerBloc.sinkUserRole.add(role); } } class DeviceSource extends DataTableSource { String role; APIServices apiServices = APIServices(); List devices; final DevicesManagerBloc devicesBloc; final BuildContext context; DeviceSource({ required this.devices, required this.context, required this.devicesBloc, required this.role, }); @override DataRow? getRow(int index) { if (index >= devices.length) { return null; } final device = devices[index]; Map sensorMap = DeviceUtils.instance .getDeviceSensors(context, device.status?.sensors ?? []); String deviceState = DeviceUtils.instance.checkStateDevice(context, device.state!); return DataRow.byIndex( // color: WidgetStateProperty.all(rowColor), index: index, cells: [ if (role == RoleEnums.USER.name || role == RoleEnums.ADMIN.name) DataCell( Text(device.name!, style: TextStyle( color: DeviceUtils.instance .getTableRowColor(device.state!))), onTap: () { context.pushNamed(AppRoutes.DEVICE_DETAIL.name, pathParameters: {'thingID': device.thingId!}); }), DataCell( Text(deviceState, style: TextStyle( color: DeviceUtils.instance .getTableRowColor(device.state!))), onTap: () { context.pushNamed(AppRoutes.DEVICE_DETAIL.name, pathParameters: {'thingID': device.thingId!}); }), DataCell( Text(sensorMap['sensorBattery'] + "%", style: TextStyle( color: DeviceUtils.instance.getTableRowColor(device.state!))), onTap: () => context.pushNamed(AppRoutes.DEVICE_DETAIL.name, pathParameters: {'thingID': device.thingId!}), ), DataCell( Text(sensorMap['sensorCsq'], style: TextStyle( color: DeviceUtils.instance.getTableRowColor(device.state!))), ), DataCell( Text("${sensorMap['sensorTemp']}°C", style: TextStyle( color: DeviceUtils.instance.getTableRowColor(device.state!))), ), DataCell( Text("${sensorMap['sensorHum']}%", style: TextStyle( color: DeviceUtils.instance.getTableRowColor(device.state!))), ), DataCell( Text("${sensorMap['sensorVolt']}V", style: TextStyle( color: DeviceUtils.instance.getTableRowColor(device.state!))), ), DataCell( Center( child: Row( children: [ IconButton( hoverColor: Colors.black, onPressed: () { context.pushNamed(AppRoutes.DEVICE_UPDATE.name, pathParameters: {'thingID': device.thingId!}); }, icon: const Icon(Icons.build, color: Colors.blue)), IconButton( onPressed: () async { handleDeleteDevice(context,devicesBloc, device.extId!, role); }, icon: const Icon(Icons.delete, color: Colors.red)), ], ), ), ), ], ); } @override int get rowCount => devices.length; @override bool get isRowCountApproximate => false; @override int get selectedRowCount => 0; } class TagState extends StatelessWidget { const TagState({ super.key, required this.state, required this.devicesManagerBloc, }); final int state; final DevicesManagerBloc devicesManagerBloc; @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.all(context.lowValue), height: context.mediumValue, width: context.dynamicWidth(0.35), decoration: BoxDecoration( color: DeviceUtils.instance.getTableRowColor(state), borderRadius: BorderRadius.circular(context.mediumValue), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( DeviceUtils.instance.checkStateDevice(context, state), style: const TextStyle(color: Colors.white), ), GestureDetector( onTap: () { devicesManagerBloc.getDeviceByState(-2); }, child: const Icon( Icons.close, size: 20, ), ), ], ), ); } }