import 'package:flutter/material.dart'; import 'package:tatlock_ui/shared/components/data_grid/data_grid_column.dart'; import 'package:tatlock_ui/shared/components/data_grid/data_grid_config.dart'; /// Header row for DataGrid. class DataGridHeader extends StatelessWidget { const DataGridHeader({ super.key, required this.config, required this.sortColumnIndex, required this.sortDescending, required this.onSort, this.showCheckbox = false, this.allSelected = false, this.someSelected = false, this.onSelectAll, }); final DataGridConfig config; final int? sortColumnIndex; final bool sortDescending; final void Function(int columnIndex) onSort; final bool showCheckbox; final bool allSelected; final bool someSelected; final VoidCallback? onSelectAll; @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final columns = config.visibleColumns; return Container( height: config.headerHeight, decoration: BoxDecoration( color: colorScheme.surfaceContainerHighest, border: Border( bottom: BorderSide(color: colorScheme.outlineVariant), ), ), child: Row( children: [ if (showCheckbox) SizedBox( width: 56, child: Center( child: Checkbox( value: allSelected ? true : (someSelected ? null : false), tristate: true, onChanged: (_) => onSelectAll?.call(), ), ), ), ...columns.asMap().entries.map((entry) { final index = entry.key; final column = entry.value; final isSorted = sortColumnIndex == index; return _buildHeaderCell( context, column, index, isSorted, isSorted && sortDescending, ); }), if (config.actions.isNotEmpty) const SizedBox(width: 56), // Space for actions column ], ), ); } Widget _buildHeaderCell( BuildContext context, DataGridColumn column, int index, bool isSorted, bool isDescending, ) { final colorScheme = Theme.of(context).colorScheme; final textStyle = Theme.of(context).textTheme.labelLarge?.copyWith( fontWeight: FontWeight.w600, color: colorScheme.onSurfaceVariant, ); Widget content = Row( mainAxisSize: MainAxisSize.min, children: [ Flexible( child: Text( column.header, style: textStyle, overflow: TextOverflow.ellipsis, textAlign: column.textAlign, ), ), if (column.sortable) ...[ const SizedBox(width: 4), AnimatedRotation( turns: isDescending ? 0.5 : 0, duration: const Duration(milliseconds: 200), child: Icon( isSorted ? Icons.arrow_upward : Icons.unfold_more, size: 16, color: isSorted ? colorScheme.primary : colorScheme.onSurfaceVariant.withValues(alpha: 0.5), ), ), ], ], ); if (column.sortable) { content = InkWell( onTap: () => onSort(index), child: Padding( padding: config.cellPadding, child: content, ), ); } else { content = Padding( padding: config.cellPadding, child: content, ); } return _wrapWithWidth(column.width, content); } Widget _wrapWithWidth(DataGridColumnWidth width, Widget child) { return switch (width) { GridFixedWidth(:final width) => SizedBox(width: width, child: child), GridFlexWidth(:final flex) => Expanded(flex: flex, child: child), GridFractionWidth(:final fraction) => FractionallySizedBox( widthFactor: fraction, child: child, ), }; } }