import 'package:flutter/material.dart'; import '../modules/search/grocery_item.dart'; // ─── Grocery Card ───────────────────────────────────────────────────────────── class GroceryCard extends StatelessWidget { final GroceryItem item; final VoidCallback onToggle; const GroceryCard({super.key, required this.item, required this.onToggle}); @override Widget build(BuildContext context) { return AnimatedContainer( duration: const Duration(milliseconds: 200), decoration: BoxDecoration( color: item.inCart ? const Color(0xFFF8FDF9) : Colors.white, borderRadius: BorderRadius.circular(16), border: Border.all( color: item.inCart ? const Color(0xFF1A6B3C) : const Color(0xFFE2E8E0), width: 1.5, ), ), child: Stack( children: [ Padding( padding: const EdgeInsets.fromLTRB(12, 14, 12, 12), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(item.emoji, style: const TextStyle(fontSize: 36)), const SizedBox(height: 8), Text( item.name, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: Color(0xFF1A1F1C), height: 1.3, ), textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 6), Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 3), decoration: BoxDecoration( color: const Color(0xFFFFF3E8), borderRadius: BorderRadius.circular(20), ), child: Text( item.quantity, style: const TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: Color(0xFFF97316), ), ), ), const SizedBox(height: 10), GestureDetector( onTap: onToggle, child: AnimatedContainer( duration: const Duration(milliseconds: 200), width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 8), decoration: BoxDecoration( color: item.inCart ? const Color(0xFF1A6B3C) : const Color(0xFFE8F5EE), borderRadius: BorderRadius.circular(10), ), child: Text( item.inCart ? '✓ Added' : '+ Add to cart', textAlign: TextAlign.center, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: item.inCart ? Colors.white : const Color(0xFF1A6B3C), ), ), ), ), ], ), ), if (item.inCart) Positioned( top: 8, right: 8, child: Container( width: 20, height: 20, decoration: const BoxDecoration( color: Color(0xFF1A6B3C), shape: BoxShape.circle, ), child: const Icon(Icons.check_rounded, color: Colors.white, size: 12), ), ), ], ), ); } } // ─── Skeleton Card ──────────────────────────────────────────────────────────── class SkeletonCard extends StatefulWidget { const SkeletonCard({super.key}); @override State createState() => _SkeletonCardState(); } class _SkeletonCardState extends State with SingleTickerProviderStateMixin { late AnimationController _ctrl; late Animation _anim; @override void initState() { super.initState(); _ctrl = AnimationController( vsync: this, duration: const Duration(milliseconds: 900)) ..repeat(reverse: true); _anim = Tween(begin: 0.4, end: 1.0).animate(_ctrl); } @override void dispose() { _ctrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return FadeTransition( opacity: _anim, child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), border: Border.all(color: const Color(0xFFE2E8E0), width: 1.5), ), padding: const EdgeInsets.fromLTRB(12, 14, 12, 12), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: 48, height: 48, decoration: const BoxDecoration( color: Color(0xFFE8EDE9), shape: BoxShape.circle, ), ), const SizedBox(height: 10), _skLine(0.8), const SizedBox(height: 6), _skLine(0.6), const SizedBox(height: 10), Container( height: 32, decoration: BoxDecoration( color: const Color(0xFFE8EDE9), borderRadius: BorderRadius.circular(10), ), ), ], ), ), ); } Widget _skLine(double widthFraction) { return FractionallySizedBox( widthFactor: widthFraction, child: Container( height: 12, decoration: BoxDecoration( color: const Color(0xFFE8EDE9), borderRadius: BorderRadius.circular(6), ), ), ); } } // ─── Chip ───────────────────────────────────────────────────────────────────── class SearchChip extends StatelessWidget { final String label; final VoidCallback onTap; final bool muted; const SearchChip({ super.key, required this.label, required this.onTap, this.muted = false, }); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 7), decoration: BoxDecoration( color: muted ? const Color(0xFFEDF2F0) : Colors.white, borderRadius: BorderRadius.circular(20), border: Border.all( color: muted ? Colors.transparent : const Color(0xFFE2E8E0), width: 1.5, ), ), child: Text( label, style: TextStyle( fontSize: muted ? 12 : 13, color: muted ? const Color(0xFF6B7A72) : const Color(0xFF1A1F1C), ), ), ), ); } } // ─── Cart Bottom Sheet ──────────────────────────────────────────────────────── class CartSheet extends StatelessWidget { final List items; final void Function(GroceryItem) onRemove; const CartSheet({super.key, required this.items, required this.onRemove}); @override Widget build(BuildContext context) { return Container( decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(24)), ), padding: const EdgeInsets.fromLTRB(20, 12, 20, 32), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: 36, height: 4, decoration: BoxDecoration( color: const Color(0xFFE2E8E0), borderRadius: BorderRadius.circular(2), ), ), const SizedBox(height: 20), Row( children: [ const Text( 'Your Cart', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w700, color: Color(0xFF1A1F1C)), ), const Spacer(), Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 3), decoration: BoxDecoration( color: const Color(0xFFEDF2F0), borderRadius: BorderRadius.circular(10), ), child: Text( '${items.length} items', style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF6B7A72)), ), ), ], ), const SizedBox(height: 16), ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.45, ), child: ListView.separated( shrinkWrap: true, itemCount: items.length, separatorBuilder: (_, __) => const Divider(height: 1), itemBuilder: (_, i) { final item = items[i]; return Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: Row( children: [ Text(item.emoji, style: const TextStyle(fontSize: 28)), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(item.name, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1A1F1C))), const SizedBox(height: 2), Text(item.quantity, style: const TextStyle( fontSize: 12, color: Color(0xFFF97316), fontWeight: FontWeight.w500)), ], ), ), IconButton( icon: const Icon(Icons.delete_outline_rounded, color: Color(0xFFE24B4A), size: 20), onPressed: () => onRemove(item), ), ], ), ); }, ), ), const SizedBox(height: 16), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () { Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('🛒 Order placed successfully!'), behavior: SnackBarBehavior.floating, backgroundColor: Color(0xFF1A6B3C), ), ); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF1A6B3C), foregroundColor: Colors.white, elevation: 0, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14)), textStyle: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600), ), child: const Text('Place Order'), ), ), ], ), ); } } // ─── Section Label ──────────────────────────────────────────────────────────── class SectionLabel extends StatelessWidget { final String label; const SectionLabel(this.label, {super.key}); @override Widget build(BuildContext context) { return Text( label.toUpperCase(), style: const TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: Color(0xFF6B7A72), letterSpacing: 0.8, ), ); } }