import 'dart:math'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import '../../l10n/app_localizations.dart'; import '../../models/product.dart'; import '../widgets/product_tile.dart'; class ProductGrid extends StatelessWidget { final List products; final int rows; final bool hasSelectedTab; final ValueChanged onProductTap; const ProductGrid({ super.key, required this.products, required this.rows, required this.hasSelectedTab, required this.onProductTap, }); @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; final l10n = AppLocalizations.of(context); if (products.isEmpty) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( shape: BoxShape.circle, color: scheme.onSurface.withValues(alpha: 0.05), ), child: Icon( Icons.inventory_2_outlined, size: 40, color: scheme.onSurface.withValues(alpha: 0.3), ), ), const SizedBox(height: 16), Text( l10n.noProductsYet, style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 4), Text( l10n.addFirstProduct, style: Theme.of(context).textTheme.bodyMedium, ), const SizedBox(height: 20), FilledButton.icon( onPressed: () => context.push('/admin'), icon: const Icon(Icons.admin_panel_settings_outlined), label: Text(l10n.admin), ), ], ), ); } return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.fromLTRB(20, 18, 20, 4), child: Row( children: [ Text( l10n.products, style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(width: 10), if (!hasSelectedTab) Flexible( child: Container( padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 4, ), decoration: BoxDecoration( color: scheme.onSurface.withValues(alpha: 0.06), borderRadius: BorderRadius.circular(999), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.info_outline_rounded, size: 14, color: scheme.onSurface.withValues(alpha: 0.5), ), const SizedBox(width: 4), Flexible( child: Text( l10n.selectTabToAddItems, overflow: TextOverflow.ellipsis, style: Theme.of(context).textTheme.bodySmall, ), ), ], ), ), ), ], ), ), Expanded( child: LayoutBuilder( builder: (context, constraints) { const padding = EdgeInsets.fromLTRB(16, 12, 16, 16); const spacing = 12.0; const minTileHeight = 72.0; // Exactly [rows] rows fill the height; the column count keeps // the tiles as close to square as the width allows final rowCount = rows.clamp(2, 6).toInt(); final tileHeight = max( minTileHeight, (constraints.maxHeight - padding.vertical - (rowCount - 1) * spacing) / rowCount, ); final columns = max( 1, ((constraints.maxWidth - padding.horizontal + spacing) / (tileHeight + spacing)) .round(), ); return GridView.builder( key: ValueKey('product-grid-$rowCount'), padding: padding, itemCount: products.length, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: columns, crossAxisSpacing: spacing, mainAxisSpacing: spacing, mainAxisExtent: tileHeight, ), itemBuilder: (context, index) { final product = products[index]; return ProductTile( product: product, enabled: hasSelectedTab, onTap: () => onProductTap(product), ); }, ); }, ), ), ], ); } }