mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
push selectAll bug, design and icons fixes
This commit is contained in:
@ -17,6 +17,7 @@ class DynamicTable extends StatefulWidget {
|
|||||||
final void Function(int, bool, dynamic)? onRowSelected;
|
final void Function(int, bool, dynamic)? onRowSelected;
|
||||||
final List<String>? initialSelectedIds;
|
final List<String>? initialSelectedIds;
|
||||||
final int uuidIndex;
|
final int uuidIndex;
|
||||||
|
final Function(dynamic selectedRows)? onSelectionChanged;
|
||||||
const DynamicTable({
|
const DynamicTable({
|
||||||
super.key,
|
super.key,
|
||||||
required this.headers,
|
required this.headers,
|
||||||
@ -32,6 +33,7 @@ class DynamicTable extends StatefulWidget {
|
|||||||
this.onRowSelected,
|
this.onRowSelected,
|
||||||
this.initialSelectedIds,
|
this.initialSelectedIds,
|
||||||
required this.uuidIndex,
|
required this.uuidIndex,
|
||||||
|
this.onSelectionChanged,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -39,7 +41,7 @@ class DynamicTable extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _DynamicTableState extends State<DynamicTable> {
|
class _DynamicTableState extends State<DynamicTable> {
|
||||||
late List<bool> _selected;
|
late List<bool> _selectedRows;
|
||||||
bool _selectAll = false;
|
bool _selectAll = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -51,47 +53,30 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
@override
|
@override
|
||||||
void didUpdateWidget(DynamicTable oldWidget) {
|
void didUpdateWidget(DynamicTable oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (oldWidget.data != widget.data) {
|
if (oldWidget.data.length != widget.data.length) {
|
||||||
_initializeSelection();
|
_initializeSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _initializeSelection() {
|
void _initializeSelection() {
|
||||||
if (widget.data.isEmpty) {
|
_selectedRows = List<bool>.filled(widget.data.length, false);
|
||||||
_selected = [];
|
|
||||||
_selectAll = false;
|
_selectAll = false;
|
||||||
} else {
|
|
||||||
_selected = List<bool>.generate(widget.data.length, (index) {
|
|
||||||
// Check if the initialSelectedIds contains the deviceUuid
|
|
||||||
// uuidIndex is the index of the column containing the deviceUuid
|
|
||||||
final deviceUuid = widget.data[index][widget.uuidIndex];
|
|
||||||
return widget.initialSelectedIds != null &&
|
|
||||||
widget.initialSelectedIds!.contains(deviceUuid);
|
|
||||||
});
|
|
||||||
_selectAll = _selected.every((element) => element == true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _toggleRowSelection(int index) {
|
|
||||||
setState(() {
|
|
||||||
_selected[index] = !_selected[index];
|
|
||||||
|
|
||||||
if (widget.onRowSelected != null) {
|
|
||||||
widget.onRowSelected!(index, _selected[index], widget.data[index]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _toggleSelectAll(bool? value) {
|
void _toggleSelectAll(bool? value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectAll = value ?? false;
|
_selectAll = value ?? false;
|
||||||
_selected = List<bool>.filled(widget.data.length, _selectAll);
|
_selectedRows = List<bool>.filled(widget.data.length, _selectAll);
|
||||||
for (int i = 0; i < widget.data.length; i++) {
|
|
||||||
if (widget.onRowSelected != null) {
|
|
||||||
widget.onRowSelected!(i, _selectAll, widget.data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
widget.onSelectionChanged?.call(_selectedRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _toggleRowSelection(int index) {
|
||||||
|
setState(() {
|
||||||
|
_selectedRows[index] = !_selectedRows[index];
|
||||||
|
_selectAll = _selectedRows.every((isSelected) => isSelected);
|
||||||
|
});
|
||||||
|
widget.onSelectionChanged?.call(_selectedRows);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -211,7 +196,7 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Checkbox(
|
child: Checkbox(
|
||||||
value: _selected[index],
|
value: _selectedRows[index],
|
||||||
onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
_toggleRowSelection(index);
|
_toggleRowSelection(index);
|
||||||
},
|
},
|
||||||
|
@ -46,6 +46,7 @@ class AcDeviceBatchControlView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
ToggleWidget(
|
ToggleWidget(
|
||||||
|
icon: Assets.ac,
|
||||||
deviceId: devicesIds.first,
|
deviceId: devicesIds.first,
|
||||||
code: 'switch',
|
code: 'switch',
|
||||||
value: state.status.acSwitch,
|
value: state.status.acSwitch,
|
||||||
|
@ -40,6 +40,7 @@ class BatchFanSpeedControl extends StatelessWidget {
|
|||||||
value == FanSpeeds.low),
|
value == FanSpeeds.low),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
Wrap(
|
Wrap(
|
||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
|
@ -43,7 +43,7 @@ class AcToggle extends StatelessWidget {
|
|||||||
child: Container(
|
child: Container(
|
||||||
color: ColorsManager.whiteColors,
|
color: ColorsManager.whiteColors,
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
icon ?? Assets.acDevice,
|
icon ?? Assets.lightPulp,
|
||||||
width: 60,
|
width: 60,
|
||||||
height: 60,
|
height: 60,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
|
@ -40,6 +40,7 @@ class FanSpeedControl extends StatelessWidget {
|
|||||||
value == FanSpeeds.low),
|
value == FanSpeeds.low),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
Wrap(
|
Wrap(
|
||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
|
@ -25,6 +25,7 @@ class DeviceManagementBloc
|
|||||||
on<SelectDevice>(_onSelectDevice);
|
on<SelectDevice>(_onSelectDevice);
|
||||||
on<ResetFilters>(_onResetFilters);
|
on<ResetFilters>(_onResetFilters);
|
||||||
on<ResetSelectedDevices>(_onResetSelectedDevices);
|
on<ResetSelectedDevices>(_onResetSelectedDevices);
|
||||||
|
on<UpdateSelection>(_onUpdateSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onFetchDevices(
|
Future<void> _onFetchDevices(
|
||||||
@ -172,6 +173,48 @@ class DeviceManagementBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onUpdateSelection(
|
||||||
|
UpdateSelection event, Emitter<DeviceManagementState> emit) {
|
||||||
|
List<AllDevicesModel> selectedDevices = [];
|
||||||
|
List<AllDevicesModel> devicesToSelectFrom = [];
|
||||||
|
|
||||||
|
if (state is DeviceManagementLoaded) {
|
||||||
|
devicesToSelectFrom = (state as DeviceManagementLoaded).devices;
|
||||||
|
} else if (state is DeviceManagementFiltered) {
|
||||||
|
devicesToSelectFrom = (state as DeviceManagementFiltered).filteredDevices;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < event.selectedRows.length; i++) {
|
||||||
|
if (event.selectedRows[i]) {
|
||||||
|
selectedDevices.add(devicesToSelectFrom[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state is DeviceManagementLoaded) {
|
||||||
|
final loadedState = state as DeviceManagementLoaded;
|
||||||
|
emit(DeviceManagementLoaded(
|
||||||
|
devices: loadedState.devices,
|
||||||
|
selectedIndex: loadedState.selectedIndex,
|
||||||
|
onlineCount: loadedState.onlineCount,
|
||||||
|
offlineCount: loadedState.offlineCount,
|
||||||
|
lowBatteryCount: loadedState.lowBatteryCount,
|
||||||
|
selectedDevice: selectedDevices,
|
||||||
|
isControlButtonEnabled: _checkIfControlButtonEnabled(selectedDevices),
|
||||||
|
));
|
||||||
|
} else if (state is DeviceManagementFiltered) {
|
||||||
|
final filteredState = state as DeviceManagementFiltered;
|
||||||
|
emit(DeviceManagementFiltered(
|
||||||
|
filteredDevices: filteredState.filteredDevices,
|
||||||
|
selectedIndex: filteredState.selectedIndex,
|
||||||
|
onlineCount: filteredState.onlineCount,
|
||||||
|
offlineCount: filteredState.offlineCount,
|
||||||
|
lowBatteryCount: filteredState.lowBatteryCount,
|
||||||
|
selectedDevice: selectedDevices,
|
||||||
|
isControlButtonEnabled: _checkIfControlButtonEnabled(selectedDevices),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool _checkIfControlButtonEnabled(List<AllDevicesModel> selectedDevices) {
|
bool _checkIfControlButtonEnabled(List<AllDevicesModel> selectedDevices) {
|
||||||
if (selectedDevices.length > 1) {
|
if (selectedDevices.length > 1) {
|
||||||
final productTypes =
|
final productTypes =
|
||||||
|
@ -54,3 +54,9 @@ class SelectDevice extends DeviceManagementEvent {
|
|||||||
class ResetFilters extends DeviceManagementEvent {}
|
class ResetFilters extends DeviceManagementEvent {}
|
||||||
|
|
||||||
class ResetSelectedDevices extends DeviceManagementEvent {}
|
class ResetSelectedDevices extends DeviceManagementEvent {}
|
||||||
|
|
||||||
|
class UpdateSelection extends DeviceManagementEvent {
|
||||||
|
final List<bool> selectedRows;
|
||||||
|
|
||||||
|
const UpdateSelection(this.selectedRows);
|
||||||
|
}
|
||||||
|
@ -120,6 +120,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
borderRadius: 9,
|
borderRadius: 9,
|
||||||
child: Text(
|
child: Text(
|
||||||
buttonLabel,
|
buttonLabel,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: isControlButtonEnabled
|
color: isControlButtonEnabled
|
||||||
@ -178,6 +179,11 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
(device.updateTime ?? 0) * 1000)),
|
(device.updateTime ?? 0) * 1000)),
|
||||||
];
|
];
|
||||||
}).toList(),
|
}).toList(),
|
||||||
|
onSelectionChanged: (selectedRows) {
|
||||||
|
context
|
||||||
|
.read<DeviceManagementBloc>()
|
||||||
|
.add(UpdateSelection(selectedRows));
|
||||||
|
},
|
||||||
initialSelectedIds: context
|
initialSelectedIds: context
|
||||||
.read<DeviceManagementBloc>()
|
.read<DeviceManagementBloc>()
|
||||||
.selectedDevices
|
.selectedDevices
|
||||||
|
@ -47,12 +47,15 @@ class ToggleWidget extends StatelessWidget {
|
|||||||
)
|
)
|
||||||
: ClipOval(
|
: ClipOval(
|
||||||
child: Container(
|
child: Container(
|
||||||
|
height: 60,
|
||||||
|
width: 60,
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
color: ColorsManager.whiteColors,
|
color: ColorsManager.whiteColors,
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
icon ?? Assets.lightPulp,
|
icon ?? Assets.lightPulp,
|
||||||
width: 60,
|
width: 35,
|
||||||
height: 60,
|
height: 35,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.contain,
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
Text(
|
Text(
|
||||||
|
@ -21,8 +21,10 @@ String formatTimeOfDayToISO(TimeOfDay time, {DateTime? currentDate}) {
|
|||||||
time.hour,
|
time.hour,
|
||||||
time.minute,
|
time.minute,
|
||||||
);
|
);
|
||||||
|
// Convert DateTime to Unix timestamp (in seconds)
|
||||||
|
final unixTimestamp = dateTime.millisecondsSinceEpoch ~/ 1000;
|
||||||
|
|
||||||
return dateTime.toUtc().toIso8601String();
|
return unixTimestamp.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
String formatIsoStringToTime(String isoString, BuildContext context) {
|
String formatIsoStringToTime(String isoString, BuildContext context) {
|
||||||
|
Reference in New Issue
Block a user