Compare commits

..

1 Commits

3 changed files with 170 additions and 214 deletions

View File

@ -50,9 +50,6 @@ class _DynamicTableState extends State<DynamicTable> {
bool _selectAll = false; bool _selectAll = false;
final ScrollController _verticalScrollController = ScrollController(); final ScrollController _verticalScrollController = ScrollController();
final ScrollController _horizontalScrollController = ScrollController(); final ScrollController _horizontalScrollController = ScrollController();
static const double _fixedRowHeight = 60;
static const double _checkboxColumnWidth = 50;
static const double _settingsColumnWidth = 100;
@override @override
void initState() { void initState() {
@ -70,6 +67,7 @@ class _DynamicTableState extends State<DynamicTable> {
bool _compareListOfLists( bool _compareListOfLists(
List<List<dynamic>> oldList, List<List<dynamic>> newList) { 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; if (oldList.length != newList.length) return false;
for (int i = 0; i < oldList.length; i++) { for (int i = 0; i < oldList.length; i++) {
@ -106,130 +104,73 @@ class _DynamicTableState extends State<DynamicTable> {
context.read<DeviceManagementBloc>().add(UpdateSelection(_selectedRows)); context.read<DeviceManagementBloc>().add(UpdateSelection(_selectedRows));
} }
double get _totalTableWidth {
final hasSettings = widget.headers.contains('Settings');
final base = (widget.withCheckBox ? _checkboxColumnWidth : 0) +
(hasSettings ? _settingsColumnWidth : 0);
final regularCount = widget.headers.length - (hasSettings ? 1 : 0);
final regularWidth = (widget.size.width - base) / regularCount;
return base + regularCount * regularWidth;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
width: widget.size.width,
height: widget.size.height,
decoration: widget.cellDecoration, decoration: widget.cellDecoration,
child: ScrollConfiguration( child: Scrollbar(
behavior: const ScrollBehavior().copyWith(scrollbars: false), controller: _verticalScrollController,
thumbVisibility: true,
trackVisibility: true,
child: Scrollbar( child: Scrollbar(
//fixed the horizontal scrollbar issue
controller: _horizontalScrollController, controller: _horizontalScrollController,
thumbVisibility: true, thumbVisibility: true,
trackVisibility: true, trackVisibility: true,
notificationPredicate: (notif) => notificationPredicate: (notif) => notif.depth == 1,
notif.metrics.axis == Axis.horizontal,
child: SingleChildScrollView( child: SingleChildScrollView(
controller: _horizontalScrollController, controller: _verticalScrollController,
scrollDirection: Axis.horizontal, child: SingleChildScrollView(
child: SizedBox( controller: _horizontalScrollController,
width: _totalTableWidth, scrollDirection: Axis.horizontal,
child: Column( child: SizedBox(
children: [ width: widget.size.width,
Container( child: Column(
height: _fixedRowHeight, children: [
decoration: widget.headerDecoration ?? Container(
const BoxDecoration(color: ColorsManager.boxColor), decoration: widget.headerDecoration ??
child: Row( const BoxDecoration(
children: [ color: ColorsManager.boxColor,
if (widget.withCheckBox)
_buildSelectAllCheckbox(_checkboxColumnWidth),
for (var i = 0; i < widget.headers.length; i++)
_buildTableHeaderCell(
widget.headers[i],
widget.headers[i] == 'Settings'
? _settingsColumnWidth
: (_totalTableWidth -
(widget.withCheckBox
? _checkboxColumnWidth
: 0) -
(widget.headers.contains('Settings')
? _settingsColumnWidth
: 0)) /
(widget.headers.length -
(widget.headers.contains('Settings')
? 1
: 0)),
), ),
], child: Row(
children: [
if (widget.withCheckBox) _buildSelectAllCheckbox(),
...List.generate(widget.headers.length, (index) {
return _buildTableHeaderCell(
widget.headers[index], index);
})
//...widget.headers.map((header) => _buildTableHeaderCell(header)),
],
),
), ),
), SizedBox(
width: widget.size.width,
Expanded( child: widget.isEmpty
child: widget.isEmpty ? _buildEmptyState()
? _buildEmptyState() : Column(
: Scrollbar( children:
controller: _verticalScrollController, List.generate(widget.data.length, (rowIndex) {
thumbVisibility: true,
trackVisibility: true,
notificationPredicate: (notif) =>
notif.metrics.axis == Axis.vertical,
child: ListView.builder(
controller: _verticalScrollController,
itemCount: widget.data.length,
itemBuilder: (_, rowIndex) {
final row = widget.data[rowIndex]; final row = widget.data[rowIndex];
return SizedBox( return Row(
height: _fixedRowHeight, children: [
child: Row( if (widget.withCheckBox)
children: [ _buildRowCheckbox(
if (widget.withCheckBox) rowIndex, widget.size.height * 0.08),
_buildRowCheckbox( ...row.asMap().entries.map((entry) {
rowIndex, return _buildTableCell(
_checkboxColumnWidth, entry.value.toString(),
), widget.size.height * 0.08,
for (var colIndex = 0; rowIndex: rowIndex,
colIndex < row.length; columnIndex: entry.key,
colIndex++) );
widget.headers[colIndex] == 'Settings' }).toList(),
? buildSettingsIcon( ],
width: _settingsColumnWidth,
onTap: () => widget
.onSettingsPressed
?.call(rowIndex),
)
: _buildTableCell(
row[colIndex].toString(),
width: widget.headers[
colIndex] ==
'Settings'
? _settingsColumnWidth
: (_totalTableWidth -
(widget.withCheckBox
? _checkboxColumnWidth
: 0) -
(widget.headers
.contains(
'Settings')
? _settingsColumnWidth
: 0)) /
(widget.headers.length -
(widget.headers
.contains(
'Settings')
? 1
: 0)),
rowIndex: rowIndex,
columnIndex: colIndex,
),
],
),
); );
}, }),
), ),
), ),
), ],
], ),
), ),
), ),
), ),
@ -269,10 +210,9 @@ class _DynamicTableState extends State<DynamicTable> {
], ],
), ),
); );
Widget _buildSelectAllCheckbox() {
Widget _buildSelectAllCheckbox(double width) {
return Container( return Container(
width: width, width: 50,
decoration: const BoxDecoration( decoration: const BoxDecoration(
border: Border.symmetric( border: Border.symmetric(
vertical: BorderSide(color: ColorsManager.boxDivider), vertical: BorderSide(color: ColorsManager.boxDivider),
@ -287,11 +227,11 @@ class _DynamicTableState extends State<DynamicTable> {
); );
} }
Widget _buildRowCheckbox(int index, double width) { Widget _buildRowCheckbox(int index, double size) {
return Container( return Container(
width: width, width: 50,
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
height: _fixedRowHeight, height: size,
decoration: const BoxDecoration( decoration: const BoxDecoration(
border: Border( border: Border(
bottom: BorderSide( bottom: BorderSide(
@ -313,47 +253,50 @@ class _DynamicTableState extends State<DynamicTable> {
); );
} }
Widget _buildTableHeaderCell(String title, double width) { Widget _buildTableHeaderCell(String title, int index) {
return Container( return Expanded(
width: width, child: Container(
decoration: const BoxDecoration( decoration: const BoxDecoration(
border: Border.symmetric( border: Border.symmetric(
vertical: BorderSide(color: ColorsManager.boxDivider), vertical: BorderSide(color: ColorsManager.boxDivider),
), ),
), ),
constraints: BoxConstraints(minHeight: 40, maxHeight: _fixedRowHeight), constraints: const BoxConstraints.expand(height: 40),
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4), padding: EdgeInsets.symmetric(
child: Text( horizontal: index == widget.headers.length - 1 ? 12 : 8.0,
title, vertical: 4),
style: context.textTheme.titleSmall!.copyWith( child: Text(
color: ColorsManager.grayColor, title,
fontSize: 12, style: context.textTheme.titleSmall!.copyWith(
fontWeight: FontWeight.w400, color: ColorsManager.grayColor,
fontSize: 12,
fontWeight: FontWeight.w400,
),
maxLines: 2,
), ),
maxLines: 2,
overflow: TextOverflow.ellipsis,
), ),
), ),
); );
} }
Widget _buildTableCell(String content, Widget _buildTableCell(String content, double size,
{required double width, {required int rowIndex, required int columnIndex}) {
required int rowIndex,
required int columnIndex}) {
bool isBatteryLevel = content.endsWith('%'); bool isBatteryLevel = content.endsWith('%');
double? batteryLevel; double? batteryLevel;
if (isBatteryLevel) { if (isBatteryLevel) {
batteryLevel = double.tryParse(content.replaceAll('%', '').trim()); batteryLevel = double.tryParse(content.replaceAll('%', '').trim());
} }
bool isSettingsColumn = widget.headers[columnIndex] == 'Settings'; bool isSettingsColumn = widget.headers[columnIndex] == 'Settings';
if (isSettingsColumn) { if (isSettingsColumn) {
return buildSettingsIcon( return buildSettingsIcon(
width: width, onTap: () => widget.onSettingsPressed?.call(rowIndex)); width: 120,
height: 60,
iconSize: 40,
onTap: () => widget.onSettingsPressed?.call(rowIndex),
);
} }
Color? statusColor; Color? statusColor;
@ -377,82 +320,92 @@ class _DynamicTableState extends State<DynamicTable> {
statusColor = Colors.black; statusColor = Colors.black;
} }
return Container( return Expanded(
width: width, child: Container(
height: _fixedRowHeight, height: size,
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4), padding: const EdgeInsets.all(5.0),
decoration: const BoxDecoration( decoration: const BoxDecoration(
border: Border( border: Border(
bottom: BorderSide( bottom: BorderSide(
color: ColorsManager.boxDivider, color: ColorsManager.boxDivider,
width: 1.0, width: 1.0,
),
), ),
color: Colors.white,
), ),
color: Colors.white, alignment: Alignment.centerLeft,
), child: Text(
alignment: Alignment.centerLeft, content,
child: Text( style: TextStyle(
content, color: (batteryLevel != null && batteryLevel < 20)
style: TextStyle( ? ColorsManager.red
color: (batteryLevel != null && batteryLevel < 20) : (batteryLevel != null && batteryLevel > 20)
? ColorsManager.red ? ColorsManager.green
: (batteryLevel != null && batteryLevel > 20) : statusColor,
? ColorsManager.green fontSize: 13,
: statusColor, fontWeight: FontWeight.w400),
fontSize: 13, maxLines: 2,
fontWeight: FontWeight.w400,
), ),
maxLines: 2,
overflow: TextOverflow.ellipsis,
), ),
); );
} }
Widget buildSettingsIcon({required double width, VoidCallback? onTap}) { Widget buildSettingsIcon(
return Container( {double width = 120,
width: width, double height = 60,
height: _fixedRowHeight, double iconSize = 40,
padding: const EdgeInsets.only(left: 15, top: 10, bottom: 10), VoidCallback? onTap}) {
decoration: const BoxDecoration( return Column(
color: ColorsManager.whiteColors, children: [
border: Border( Container(
bottom: BorderSide( padding: const EdgeInsets.only(top: 10, bottom: 15, left: 10),
color: ColorsManager.boxDivider, margin: const EdgeInsets.only(right: 15),
width: 1.0, decoration: const BoxDecoration(
), color: ColorsManager.whiteColors,
), border: Border(
), bottom: BorderSide(
child: Align( color: ColorsManager.boxDivider,
alignment: Alignment.centerLeft, width: 1.0,
child: Container(
width: 50,
decoration: BoxDecoration(
color: const Color(0xFFF7F8FA),
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.17),
blurRadius: 14,
offset: const Offset(0, 4),
), ),
], ),
), ),
child: InkWell( width: width,
onTap: onTap, child: Padding(
child: Padding( padding: const EdgeInsets.only(
padding: EdgeInsets.all(8.0), right: 16.0,
child: Center( left: 17.0,
child: SvgPicture.asset( ),
Assets.settings, child: Container(
width: 40, width: 50,
height: 20, decoration: BoxDecoration(
color: ColorsManager.primaryColor, color: const Color(0xFFF7F8FA),
borderRadius: BorderRadius.circular(height / 2),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.17),
blurRadius: 14,
offset: const Offset(0, 4),
),
],
),
child: InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: SvgPicture.asset(
Assets.settings,
width: 40,
height: 22,
color: ColorsManager.primaryColor,
),
),
), ),
), ),
), ),
), ),
), ),
), ],
); );
} }
} }

View File

@ -2,11 +2,13 @@ class FailedOperation {
final bool success; final bool success;
final dynamic deviceUuid; final dynamic deviceUuid;
final dynamic error; final dynamic error;
final String deviceName;
FailedOperation({ FailedOperation({
required this.success, required this.success,
required this.deviceUuid, required this.deviceUuid,
required this.error, required this.error,
required this.deviceName,
}); });
factory FailedOperation.fromJson(Map<String, dynamic> json) { factory FailedOperation.fromJson(Map<String, dynamic> json) {
@ -14,6 +16,7 @@ class FailedOperation {
success: json['success'], success: json['success'],
deviceUuid: json['deviceUuid'], deviceUuid: json['deviceUuid'],
error: json['error'], error: json['error'],
deviceName: json['deviceName'] as String? ?? '',
); );
} }
@ -22,21 +25,22 @@ class FailedOperation {
'success': success, 'success': success,
'deviceUuid': deviceUuid, 'deviceUuid': deviceUuid,
'error': error, 'error': error,
'deviceName': deviceName,
}; };
} }
} }
class SuccessOperation { class SuccessOperation {
final bool success; final bool success;
// final Result result; // final Result result;
final String deviceUuid; final String deviceUuid;
final String deviceName;
SuccessOperation({ SuccessOperation({
required this.success, required this.success,
// required this.result, // required this.result,
required this.deviceUuid, required this.deviceUuid,
required this.deviceName,
}); });
factory SuccessOperation.fromJson(Map<String, dynamic> json) { factory SuccessOperation.fromJson(Map<String, dynamic> json) {
@ -44,6 +48,7 @@ class SuccessOperation {
success: json['success'], success: json['success'],
// result: Result.fromJson(json['result']), // result: Result.fromJson(json['result']),
deviceUuid: json['deviceUuid'], deviceUuid: json['deviceUuid'],
deviceName: json['deviceName'] as String? ?? '',
); );
} }
@ -52,6 +57,7 @@ class SuccessOperation {
'success': success, 'success': success,
// 'result': result.toJson(), // 'result': result.toJson(),
'deviceUuid': deviceUuid, 'deviceUuid': deviceUuid,
'deviceName': deviceName,
}; };
} }
} }
@ -92,8 +98,6 @@ class SuccessOperation {
// } // }
// } // }
class PasswordStatus { class PasswordStatus {
final List<SuccessOperation> successOperations; final List<SuccessOperation> successOperations;
final List<FailedOperation> failedOperations; final List<FailedOperation> failedOperations;
@ -121,4 +125,3 @@ class PasswordStatus {
}; };
} }
} }

View File

@ -63,7 +63,7 @@ class VisitorPasswordDialog extends StatelessWidget {
child: Text(visitorBloc child: Text(visitorBloc
.passwordStatus! .passwordStatus!
.failedOperations[index] .failedOperations[index]
.deviceUuid)), .deviceName)),
); );
}, },
), ),
@ -92,7 +92,7 @@ class VisitorPasswordDialog extends StatelessWidget {
child: Text(visitorBloc child: Text(visitorBloc
.passwordStatus! .passwordStatus!
.successOperations[index] .successOperations[index]
.deviceUuid)), .deviceName)),
); );
}, },
), ),