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