import 'dart:io'; import 'package:flutter/material.dart'; import 'package:kooltab2/models/product.dart'; class ProductTile extends StatelessWidget { final Product product; final bool enabled; final VoidCallback onTap; static const _tileImageSize = 280.0; const ProductTile({ super.key, required this.product, required this.enabled, required this.onTap, }); @override Widget build(BuildContext context) { final theme = Theme.of(context); final scheme = theme.colorScheme; final outOfStock = product.stockQuantity <= 0; final lowStock = product.stockQuantity > 0 && product.stockQuantity <= product.lowStockThreshold; final hasImage = product.imagePath != null && product.imagePath!.isNotEmpty; final borderColor = outOfStock ? scheme.error.withValues(alpha: 0.7) : lowStock ? Colors.amber.withValues(alpha: 0.9) : scheme.onSurface.withValues(alpha: 0.08); return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), border: Border.all( color: borderColor, width: outOfStock || lowStock ? 2 : 1, ), ), child: ClipRRect( borderRadius: BorderRadius.circular(15), child: Material( color: theme.cardTheme.color ?? scheme.surface, child: InkWell( onTap: enabled && !outOfStock ? onTap : null, child: Stack( fit: StackFit.expand, children: [ Opacity( opacity: outOfStock ? 0.35 : (enabled ? 1 : 0.4), child: hasImage ? Image.file( File(product.imagePath!), fit: BoxFit.scaleDown, cacheWidth: _tileImageSize.toInt(), errorBuilder: (context, error, stackTrace) => _noImage(scheme), ) : _noImage(scheme), ), if (hasImage) Positioned.fill( child: DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.transparent, Colors.black.withValues(alpha: 0.35), ], stops: const [0.6, 1.0], ), ), ), ), // Stock badge Positioned( top: 10, right: 10, child: _StockBadge(product: product), ), // Out of stock overlay if (outOfStock) Center( child: Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6, ), decoration: BoxDecoration( color: scheme.error.withValues(alpha: 0.9), borderRadius: BorderRadius.circular(999), ), child: Text( 'OUT OF STOCK', style: TextStyle( color: scheme.onError, fontWeight: FontWeight.w800, fontSize: 12, ), ), ), ), ], ), ), ), ), ); } Widget _noImage(ColorScheme scheme) { return Center( child: Icon( Icons.image_not_supported_outlined, size: 34, color: scheme.onSurface.withValues(alpha: 0.3), ), ); } } class _StockBadge extends StatelessWidget { final Product product; const _StockBadge({required this.product}); @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; if (product.stockQuantity <= 0) { return const SizedBox.shrink(); } final low = product.stockQuantity <= product.lowStockThreshold; return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: low ? Colors.amber.withValues(alpha: 0.9) : scheme.primary.withValues(alpha: 0.85), borderRadius: BorderRadius.circular(999), ), child: Text( '${product.stockQuantity}', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w800, color: low ? Colors.black : scheme.onPrimary, ), ), ); } }