Fixed design issues

This commit is contained in:
Abdullah Alassaf
2024-10-08 01:56:09 +03:00
parent d05328e998
commit 813f2f2693
7 changed files with 114 additions and 98 deletions

View File

@ -53,11 +53,26 @@ class _DynamicTableState extends State<DynamicTable> {
@override @override
void didUpdateWidget(DynamicTable oldWidget) { void didUpdateWidget(DynamicTable oldWidget) {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (oldWidget.data.length != widget.data.length) { if (!_compareListOfLists(oldWidget.data, widget.data)) {
_initializeSelection(); _initializeSelection();
} }
} }
bool _compareListOfLists(List<List<dynamic>> oldList, List<List<dynamic>> newList) {
// Check if the old and new lists are the same
if (oldList.length != newList.length) return false;
for (int i = 0; i < oldList.length; i++) {
if (oldList[i].length != newList[i].length) return false;
for (int j = 0; j < oldList[i].length; j++) {
if (oldList[i][j] != newList[i][j]) return false;
}
}
return true;
}
void _initializeSelection() { void _initializeSelection() {
_selectedRows = List<bool>.filled(widget.data.length, false); _selectedRows = List<bool>.filled(widget.data.length, false);
_selectAll = false; _selectAll = false;
@ -90,13 +105,11 @@ class _DynamicTableState extends State<DynamicTable> {
child: Column( child: Column(
children: [ children: [
Container( Container(
decoration: widget.headerDecoration ?? decoration: widget.headerDecoration ?? BoxDecoration(color: Colors.grey[200]),
BoxDecoration(color: Colors.grey[200]),
child: Row( child: Row(
children: [ children: [
if (widget.withCheckBox) _buildSelectAllCheckbox(), if (widget.withCheckBox) _buildSelectAllCheckbox(),
...widget.headers ...widget.headers.map((header) => _buildTableHeaderCell(header)),
.map((header) => _buildTableHeaderCell(header)),
], ],
), ),
), ),
@ -123,8 +136,7 @@ class _DynamicTableState extends State<DynamicTable> {
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.bodySmall! .bodySmall!
.copyWith( .copyWith(color: ColorsManager.grayColor),
color: ColorsManager.grayColor),
) )
], ],
), ),
@ -144,11 +156,9 @@ class _DynamicTableState extends State<DynamicTable> {
return Row( return Row(
children: [ children: [
if (widget.withCheckBox) if (widget.withCheckBox)
_buildRowCheckbox( _buildRowCheckbox(index, widget.size.height * 0.10),
index, widget.size.height * 0.10), ...row.map((cell) =>
...row.map((cell) => _buildTableCell( _buildTableCell(cell.toString(), widget.size.height * 0.10)),
cell.toString(),
widget.size.height * 0.10)),
], ],
); );
}, },
@ -173,9 +183,7 @@ class _DynamicTableState extends State<DynamicTable> {
), ),
child: Checkbox( child: Checkbox(
value: _selectAll, value: _selectAll,
onChanged: widget.withSelectAll && widget.data.isNotEmpty onChanged: widget.withSelectAll && widget.data.isNotEmpty ? _toggleSelectAll : null,
? _toggleSelectAll
: null,
), ),
); );
} }

View File

@ -2,20 +2,21 @@ import 'package:flutter/material.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
class StatefulTextField extends StatefulWidget { class StatefulTextField extends StatefulWidget {
const StatefulTextField({ const StatefulTextField(
super.key, {super.key,
required this.title, required this.title,
this.hintText = 'Please enter', this.hintText = 'Please enter',
required this.width, required this.width,
this.elevation = 0, this.elevation = 0,
required this.controller, required this.controller,
}); this.onSubmitted});
final String title; final String title;
final String hintText; final String hintText;
final double width; final double width;
final double elevation; final double elevation;
final TextEditingController controller; final TextEditingController controller;
final Function? onSubmitted;
@override @override
State<StatefulTextField> createState() => _StatefulTextFieldState(); State<StatefulTextField> createState() => _StatefulTextFieldState();
@ -30,25 +31,26 @@ class _StatefulTextFieldState extends State<StatefulTextField> {
hintText: widget.hintText, hintText: widget.hintText,
width: widget.width, width: widget.width,
elevation: widget.elevation, elevation: widget.elevation,
); onSubmittedFun: widget.onSubmitted);
} }
} }
class CustomTextField extends StatelessWidget { class CustomTextField extends StatelessWidget {
const CustomTextField({ const CustomTextField(
super.key, {super.key,
required this.title, required this.title,
required this.controller, required this.controller,
this.hintText = 'Please enter', this.hintText = 'Please enter',
required this.width, required this.width,
this.elevation = 0, this.elevation = 0,
}); this.onSubmittedFun});
final String title; final String title;
final TextEditingController controller; final TextEditingController controller;
final String hintText; final String hintText;
final double width; final double width;
final double elevation; final double elevation;
final Function? onSubmittedFun;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -81,10 +83,12 @@ class CustomTextField extends StatelessWidget {
decoration: InputDecoration( decoration: InputDecoration(
hintText: hintText, hintText: hintText,
hintStyle: const TextStyle(fontSize: 12), hintStyle: const TextStyle(fontSize: 12),
contentPadding: contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
border: InputBorder.none, border: InputBorder.none,
), ),
onFieldSubmitted: (_) {
onSubmittedFun!();
},
), ),
), ),
), ),

View File

@ -37,8 +37,8 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
offlineCount = state.offlineCount; offlineCount = state.offlineCount;
lowBatteryCount = state.lowBatteryCount; lowBatteryCount = state.lowBatteryCount;
isControlButtonEnabled = state.isControlButtonEnabled; isControlButtonEnabled = state.isControlButtonEnabled;
selectedDevices = state.selectedDevice ?? selectedDevices =
context.read<DeviceManagementBloc>().selectedDevices; state.selectedDevice ?? context.read<DeviceManagementBloc>().selectedDevices;
} else if (state is DeviceManagementFiltered) { } else if (state is DeviceManagementFiltered) {
devicesToShow = state.filteredDevices; devicesToShow = state.filteredDevices;
selectedIndex = state.selectedIndex; selectedIndex = state.selectedIndex;
@ -46,8 +46,8 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
offlineCount = state.offlineCount; offlineCount = state.offlineCount;
lowBatteryCount = state.lowBatteryCount; lowBatteryCount = state.lowBatteryCount;
isControlButtonEnabled = state.isControlButtonEnabled; isControlButtonEnabled = state.isControlButtonEnabled;
selectedDevices = state.selectedDevice ?? selectedDevices =
context.read<DeviceManagementBloc>().selectedDevices; state.selectedDevice ?? context.read<DeviceManagementBloc>().selectedDevices;
} else if (state is DeviceManagementInitial) { } else if (state is DeviceManagementInitial) {
devicesToShow = []; devicesToShow = [];
selectedIndex = 0; selectedIndex = 0;
@ -61,15 +61,13 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
'Low Battery ($lowBatteryCount)', 'Low Battery ($lowBatteryCount)',
]; ];
final buttonLabel = final buttonLabel = (selectedDevices.length > 1) ? 'Batch Control' : 'Control';
(selectedDevices.length > 1) ? 'Batch Control' : 'Control';
return Column( return Column(
children: [ children: [
Container( Container(
padding: isLargeScreenSize(context) padding:
? const EdgeInsets.all(30) isLargeScreenSize(context) ? const EdgeInsets.all(30) : const EdgeInsets.all(15),
: const EdgeInsets.all(15),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -78,9 +76,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
tabs: tabs, tabs: tabs,
selectedIndex: selectedIndex, selectedIndex: selectedIndex,
onTabChanged: (index) { onTabChanged: (index) {
context context.read<DeviceManagementBloc>().add(SelectedFilterChanged(index));
.read<DeviceManagementBloc>()
.add(SelectedFilterChanged(index));
}, },
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
@ -102,14 +98,12 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
), ),
); );
} else if (selectedDevices.length > 1) { } else if (selectedDevices.length > 1) {
final productTypes = selectedDevices final productTypes =
.map((device) => device.productType) selectedDevices.map((device) => device.productType).toSet();
.toSet();
if (productTypes.length == 1) { if (productTypes.length == 1) {
showDialog( showDialog(
context: context, context: context,
builder: (context) => builder: (context) => DeviceBatchControlDialog(
DeviceBatchControlDialog(
devices: selectedDevices, devices: selectedDevices,
), ),
); );
@ -123,9 +117,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
color: isControlButtonEnabled color: isControlButtonEnabled ? Colors.white : Colors.grey,
? Colors.white
: Colors.grey,
), ),
), ),
), ),
@ -144,9 +136,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
cellDecoration: containerDecoration, cellDecoration: containerDecoration,
onRowSelected: (index, isSelected, row) { onRowSelected: (index, isSelected, row) {
final selectedDevice = devicesToShow[index]; final selectedDevice = devicesToShow[index];
context context.read<DeviceManagementBloc>().add(SelectDevice(selectedDevice));
.read<DeviceManagementBloc>()
.add(SelectDevice(selectedDevice));
}, },
withCheckBox: true, withCheckBox: true,
size: context.screenSize, size: context.screenSize,
@ -169,20 +159,16 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
device.uuid ?? '', device.uuid ?? '',
device.unit?.name ?? '', device.unit?.name ?? '',
device.room?.name ?? '', device.room?.name ?? '',
device.batteryLevel != null device.batteryLevel != null ? '${device.batteryLevel}%' : '-',
? '${device.batteryLevel}%' formatDateTime(
: '-', DateTime.fromMillisecondsSinceEpoch((device.createTime ?? 0) * 1000)),
formatDateTime(DateTime.fromMillisecondsSinceEpoch(
(device.createTime ?? 0) * 1000)),
device.online == true ? 'Online' : 'Offline', device.online == true ? 'Online' : 'Offline',
formatDateTime(DateTime.fromMillisecondsSinceEpoch( formatDateTime(
(device.updateTime ?? 0) * 1000)), DateTime.fromMillisecondsSinceEpoch((device.updateTime ?? 0) * 1000)),
]; ];
}).toList(), }).toList(),
onSelectionChanged: (selectedRows) { onSelectionChanged: (selectedRows) {
context context.read<DeviceManagementBloc>().add(UpdateSelection(selectedRows));
.read<DeviceManagementBloc>()
.add(UpdateSelection(selectedRows));
}, },
initialSelectedIds: context initialSelectedIds: context
.read<DeviceManagementBloc>() .read<DeviceManagementBloc>()

View File

@ -12,8 +12,7 @@ class DeviceSearchFilters extends StatefulWidget {
State<DeviceSearchFilters> createState() => _DeviceSearchFiltersState(); State<DeviceSearchFilters> createState() => _DeviceSearchFiltersState();
} }
class _DeviceSearchFiltersState extends State<DeviceSearchFilters> class _DeviceSearchFiltersState extends State<DeviceSearchFilters> with HelperResponsiveLayout {
with HelperResponsiveLayout {
final TextEditingController communityController = TextEditingController(); final TextEditingController communityController = TextEditingController();
final TextEditingController unitNameController = TextEditingController(); final TextEditingController unitNameController = TextEditingController();
final TextEditingController productNameController = TextEditingController(); final TextEditingController productNameController = TextEditingController();
@ -35,8 +34,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
const SizedBox(width: 20), const SizedBox(width: 20),
_buildSearchField("Unit Name", unitNameController, 200), _buildSearchField("Unit Name", unitNameController, 200),
const SizedBox(width: 20), const SizedBox(width: 20),
_buildSearchField( _buildSearchField("Device Name / Product Name", productNameController, 300),
"Device Name / Product Name", productNameController, 300),
const SizedBox(width: 20), const SizedBox(width: 20),
_buildSearchResetButtons(), _buildSearchResetButtons(),
], ],
@ -45,22 +43,34 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
spacing: 20, spacing: 20,
runSpacing: 10, runSpacing: 10,
children: [ children: [
_buildSearchField("Community", communityController, 200), _buildSearchField(
"Community",
communityController,
200,
),
_buildSearchField("Unit Name", unitNameController, 200), _buildSearchField("Unit Name", unitNameController, 200),
_buildSearchField( _buildSearchField(
"Device Name / Product Name", productNameController, 300), "Device Name / Product Name",
productNameController,
300,
),
_buildSearchResetButtons(), _buildSearchResetButtons(),
], ],
); );
} }
Widget _buildSearchField( Widget _buildSearchField(String title, TextEditingController controller, double width) {
String title, TextEditingController controller, double width) {
return StatefulTextField( return StatefulTextField(
title: title, title: title,
width: width, width: width,
elevation: 2, elevation: 2,
controller: controller, controller: controller,
onSubmitted: () {
context.read<DeviceManagementBloc>().add(SearchDevices(
productName: productNameController.text,
unitName: unitNameController.text,
));
},
); );
} }

View File

@ -7,8 +7,7 @@ import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
class FirmwareUpdateWidget extends StatefulWidget { class FirmwareUpdateWidget extends StatefulWidget {
const FirmwareUpdateWidget( const FirmwareUpdateWidget({super.key, required this.deviceId, required this.version});
{super.key, required this.deviceId, required this.version});
final String deviceId; final String deviceId;
final int version; final int version;
@ -33,6 +32,8 @@ class _FirmwareUpdateWidgetState extends State<FirmwareUpdateWidget> {
? Column( ? Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [ children: [
Text( Text(
'Firmware Update', 'Firmware Update',
@ -47,7 +48,8 @@ class _FirmwareUpdateWidgetState extends State<FirmwareUpdateWidget> {
color: ColorsManager.grayColor, color: ColorsManager.grayColor,
), ),
), ),
const SizedBox(height: 16), ],
),
Row( Row(
children: [ children: [
Flexible( Flexible(

View File

@ -11,7 +11,14 @@ class DeviceControlsContainer extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
color: ColorsManager.greyColor.withOpacity(0.2), color: ColorsManager.greyColor.withOpacity(0.2),
border: Border.all(color: ColorsManager.boxDivider), // border: Border.all(color: ColorsManager.boxDivider),
// boxShadow: <BoxShadow>[
// BoxShadow(
// color: ColorsManager.blackColor.withOpacity(0.05),
// blurRadius: 6.0,
// offset: const Offset(0, 5),
// spreadRadius: 0)
// ],
), ),
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
child: child, child: child,

View File

@ -5,8 +5,7 @@ abstract class ColorsManager {
static const Color switchOffColor = Color(0x7F8D99AE); static const Color switchOffColor = Color(0x7F8D99AE);
static const Color primaryColor = Color(0xFF0030CB); //023DFE static const Color primaryColor = Color(0xFF0030CB); //023DFE
static const Color secondaryTextColor = Color(0xFF848484); static const Color secondaryTextColor = Color(0xFF848484);
static Color primaryColorWithOpacity = static Color primaryColorWithOpacity = const Color(0xFF023DFE).withOpacity(0.6);
const Color(0xFF023DFE).withOpacity(0.6);
static const Color whiteColors = Colors.white; static const Color whiteColors = Colors.white;
static const Color secondaryColor = Color(0xFF023DFE); static const Color secondaryColor = Color(0xFF023DFE);
static const Color onSecondaryColor = Color(0xFF023DFE); static const Color onSecondaryColor = Color(0xFF023DFE);