Implemented side tree to devices and rountines screen

This commit is contained in:
Abdullah Alassaf
2025-01-04 17:45:15 +03:00
parent 0341844ea9
commit a98f7e77a3
88 changed files with 1551 additions and 1202 deletions

View File

@ -8,6 +8,7 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_mo
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_search_filters.dart';
import 'package:syncrow_web/pages/device_managment/shared/device_batch_control_dialog.dart';
import 'package:syncrow_web/pages/device_managment/shared/device_control_dialog.dart';
import 'package:syncrow_web/pages/space_tree/view/side_spaces_view.dart';
import 'package:syncrow_web/utils/format_date_time.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
import 'package:syncrow_web/utils/style.dart';
@ -59,118 +60,143 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
final buttonLabel = (selectedDevices.length > 1) ? 'Batch Control' : 'Control';
return Column(
return Row(
children: [
Container(
padding: isLargeScreenSize(context) ? const EdgeInsets.all(30) : const EdgeInsets.all(15),
Flexible(child: SideSpacesView(
onSelectAction: (String communityId, String spaceId) {
context.read<DeviceManagementBloc>().add(FetchDevices(communityId, spaceId));
},
)),
Flexible(
flex: 3,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FilterWidget(
size: MediaQuery.of(context).size,
tabs: tabs,
selectedIndex: selectedIndex,
onTabChanged: (index) {
context.read<DeviceManagementBloc>().add(SelectedFilterChanged(index));
},
),
const SizedBox(height: 20),
const DeviceSearchFilters(),
const SizedBox(height: 12),
Container(
height: 45,
width: 125,
decoration: containerDecoration,
child: Center(
child: DefaultButton(
onPressed: isControlButtonEnabled
? () {
if (selectedDevices.length == 1) {
showDialog(
context: context,
builder: (context) => DeviceControlDialog(
device: selectedDevices.first,
),
);
} else if (selectedDevices.length > 1) {
final productTypes = selectedDevices.map((device) => device.productType).toSet();
if (productTypes.length == 1) {
showDialog(
context: context,
builder: (context) => DeviceBatchControlDialog(
devices: selectedDevices,
),
);
}
}
}
: null,
borderRadius: 9,
child: Text(
buttonLabel,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
color: isControlButtonEnabled ? Colors.white : Colors.grey,
padding: isLargeScreenSize(context)
? const EdgeInsets.all(30)
: const EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FilterWidget(
size: MediaQuery.of(context).size,
tabs: tabs,
selectedIndex: selectedIndex,
onTabChanged: (index) {
context.read<DeviceManagementBloc>().add(SelectedFilterChanged(index));
},
),
const SizedBox(height: 20),
const DeviceSearchFilters(),
const SizedBox(height: 12),
Container(
height: 45,
width: 125,
decoration: containerDecoration,
child: Center(
child: DefaultButton(
onPressed: isControlButtonEnabled
? () {
if (selectedDevices.length == 1) {
showDialog(
context: context,
builder: (context) => DeviceControlDialog(
device: selectedDevices.first,
),
);
} else if (selectedDevices.length > 1) {
final productTypes = selectedDevices
.map((device) => device.productType)
.toSet();
if (productTypes.length == 1) {
showDialog(
context: context,
builder: (context) => DeviceBatchControlDialog(
devices: selectedDevices,
),
);
}
}
}
: null,
borderRadius: 9,
child: Text(
buttonLabel,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
color: isControlButtonEnabled ? Colors.white : Colors.grey,
),
),
),
),
),
),
],
),
),
Expanded(
child: Padding(
padding: isLargeScreenSize(context)
? const EdgeInsets.all(30)
: const EdgeInsets.all(15),
child: DynamicTable(
withSelectAll: true,
cellDecoration: containerDecoration,
onRowSelected: (index, isSelected, row) {
final selectedDevice = devicesToShow[index];
context.read<DeviceManagementBloc>().add(SelectDevice(selectedDevice));
},
withCheckBox: true,
size: MediaQuery.of(context).size,
uuidIndex: 2,
headers: const [
'Device Name',
'Product Name',
'Device ID',
'Space Name',
'location',
'Battery Level',
'Installation Date and Time',
'Status',
'Last Offline Date and Time',
],
data: devicesToShow.map((device) {
final combinedSpaceNames = device.spaces != null
? device.spaces!.map((space) => space.spaceName).join(' > ') +
(device.community != null ? ' > ${device.community!.name}' : '')
: (device.community != null ? device.community!.name : '');
return [
device.name ?? '',
device.productName ?? '',
device.uuid ?? '',
(device.spaces != null && device.spaces!.isNotEmpty)
? device.spaces![0].spaceName
: '',
combinedSpaceNames,
device.batteryLevel != null ? '${device.batteryLevel}%' : '-',
formatDateTime(DateTime.fromMillisecondsSinceEpoch(
(device.createTime ?? 0) * 1000)),
device.online == true ? 'Online' : 'Offline',
formatDateTime(DateTime.fromMillisecondsSinceEpoch(
(device.updateTime ?? 0) * 1000)),
];
}).toList(),
onSelectionChanged: (selectedRows) {
context.read<DeviceManagementBloc>().add(UpdateSelection(selectedRows));
},
initialSelectedIds: context
.read<DeviceManagementBloc>()
.selectedDevices
.map((device) => device.uuid!)
.toList(),
isEmpty: devicesToShow.isEmpty,
),
),
)
],
),
),
Expanded(
child: Padding(
padding: isLargeScreenSize(context) ? const EdgeInsets.all(30) : const EdgeInsets.all(15),
child: DynamicTable(
withSelectAll: true,
cellDecoration: containerDecoration,
onRowSelected: (index, isSelected, row) {
final selectedDevice = devicesToShow[index];
context.read<DeviceManagementBloc>().add(SelectDevice(selectedDevice));
},
withCheckBox: true,
size: MediaQuery.of(context).size,
uuidIndex: 2,
headers: const [
'Device Name',
'Product Name',
'Device ID',
'Space Name',
'location',
'Battery Level',
'Installation Date and Time',
'Status',
'Last Offline Date and Time',
],
data: devicesToShow.map((device) {
final combinedSpaceNames = device.spaces != null
? device.spaces!.map((space) => space.spaceName).join(' > ') +
(device.community != null ? ' > ${device.community!.name}' : '')
: (device.community != null ? device.community!.name : '');
return [
device.name ?? '',
device.productName ?? '',
device.uuid ?? '',
(device.spaces != null && device.spaces!.isNotEmpty) ? device.spaces![0].spaceName : '',
combinedSpaceNames,
device.batteryLevel != null ? '${device.batteryLevel}%' : '-',
formatDateTime(DateTime.fromMillisecondsSinceEpoch((device.createTime ?? 0) * 1000)),
device.online == true ? 'Online' : 'Offline',
formatDateTime(DateTime.fromMillisecondsSinceEpoch((device.updateTime ?? 0) * 1000)),
];
}).toList(),
onSelectionChanged: (selectedRows) {
context.read<DeviceManagementBloc>().add(UpdateSelection(selectedRows));
},
initialSelectedIds:
context.read<DeviceManagementBloc>().selectedDevices.map((device) => device.uuid!).toList(),
isEmpty: devicesToShow.isEmpty,
),
),
)
],
);
},

View File

@ -12,8 +12,7 @@ class DeviceSearchFilters extends StatefulWidget {
State<DeviceSearchFilters> createState() => _DeviceSearchFiltersState();
}
class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
with HelperResponsiveLayout {
class _DeviceSearchFiltersState extends State<DeviceSearchFilters> with HelperResponsiveLayout {
final TextEditingController communityController = TextEditingController();
final TextEditingController unitNameController = TextEditingController();
final TextEditingController productNameController = TextEditingController();
@ -27,8 +26,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
const SizedBox(width: 20),
_buildSearchField("Space Name", unitNameController, 200),
const SizedBox(width: 20),
_buildSearchField(
"Device Name / Product Name", productNameController, 300),
_buildSearchField("Device Name / Product Name", productNameController, 300),
const SizedBox(width: 20),
_buildSearchResetButtons(),
],
@ -53,8 +51,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
);
}
Widget _buildSearchField(
String title, TextEditingController controller, double width) {
Widget _buildSearchField(String title, TextEditingController controller, double width) {
return Container(
child: StatefulTextField(
title: title,
@ -88,7 +85,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
productNameController.clear();
context.read<DeviceManagementBloc>()
..add(ResetFilters())
..add(FetchDevices());
..add(const FetchDevices('', ''));
},
);
}