import 'package:flutter/material.dart'; import 'package:marco/helpers/widgets/my_spacing.dart'; import 'package:marco/helpers/widgets/my_text.dart'; import 'package:marco/helpers/widgets/my_container.dart'; class MyPaginatedTable extends StatefulWidget { final String? title; final List columns; final List rows; final double columnSpacing; final double horizontalMargin; const MyPaginatedTable({ super.key, this.title, required this.columns, required this.rows, this.columnSpacing = 23, this.horizontalMargin = 35, }); @override _MyPaginatedTableState createState() => _MyPaginatedTableState(); } class _MyPaginatedTableState extends State { int _start = 0; int _rowsPerPage = 10; @override Widget build(BuildContext context) { final visibleRows = widget.rows.skip(_start).take(_rowsPerPage).toList(); final totalRows = widget.rows.length; final totalPages = (totalRows / _rowsPerPage).ceil(); final currentPage = (_start / _rowsPerPage).ceil() + 1; return Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ if (widget.title != null) Padding( padding: MySpacing.xy(8, 6), // Using standard spacing for title child: MyText.titleMedium(widget.title!, fontWeight: 600, fontSize: 20), ), if (widget.rows.isEmpty) Padding( padding: MySpacing.all(16), // Standard padding for empty state child: MyText.bodySmall('No data available'), ), if (widget.rows.isNotEmpty) LayoutBuilder( builder: (context, constraints) { final spacing = _calculateSmartSpacing(constraints.maxWidth); return SingleChildScrollView( scrollDirection: Axis.horizontal, child: MyContainer.bordered( borderColor: Colors.black.withAlpha(40), padding: EdgeInsets.zero, child: DataTable( columns: widget.columns, rows: visibleRows, columnSpacing: spacing, horizontalMargin: widget.horizontalMargin, ), ), ); }, ), MySpacing.height(8), // Standard height spacing after table PaginatedFooter( currentPage: currentPage, totalPages: totalPages, onPrevious: () { setState(() { _start = (_start - _rowsPerPage).clamp(0, totalRows - _rowsPerPage); }); }, onNext: () { setState(() { _start = (_start + _rowsPerPage).clamp(0, totalRows - _rowsPerPage); }); }, onPageSizeChanged: (newRowsPerPage) { setState(() { _rowsPerPage = newRowsPerPage; _start = 0; }); }, ), ], ); } double _calculateSmartSpacing(double maxWidth) { int columnCount = widget.columns.length; double horizontalPadding = widget.horizontalMargin * 2; double availableWidth = maxWidth - horizontalPadding; // Desired min/max column spacing const double minSpacing = 16; const double maxSpacing = 80; // Total width assuming minimal spacing double minTotalWidth = (columnCount * minSpacing) + horizontalPadding; if (minTotalWidth >= availableWidth) { // Not enough room — return minimal spacing return minSpacing; } // Fit evenly within the available width double spacing = (availableWidth / columnCount) - 40; // 40 for estimated cell content width return spacing.clamp(minSpacing, maxSpacing); } } class PaginatedFooter extends StatelessWidget { final int currentPage; final int totalPages; final VoidCallback onPrevious; final VoidCallback onNext; final Function(int) onPageSizeChanged; const PaginatedFooter({ required this.currentPage, required this.totalPages, required this.onPrevious, required this.onNext, required this.onPageSizeChanged, }); @override Widget build(BuildContext context) { return Padding( padding: MySpacing.x(16), // Standard horizontal spacing for footer child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ if (currentPage > 1) IconButton( onPressed: onPrevious, icon: Icon(Icons.chevron_left), ), Text( 'Page $currentPage of $totalPages', style: TextStyle( fontSize: 16, color: Theme.of(context).colorScheme.onBackground, ), ), SizedBox(width: 8), if (currentPage < totalPages) IconButton( onPressed: onNext, icon: Icon(Icons.chevron_right), ), SizedBox(width: 16), PopupMenuButton( icon: Icon(Icons.more_vert), onSelected: (value) { onPageSizeChanged(value); }, itemBuilder: (BuildContext context) { return [5, 10, 20, 50].map((e) { return PopupMenuItem( value: e, child: Text('$e rows per page'), ); }).toList(); }, ), ], ), ), ); } }