import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/cupertino.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:hum/core/constants/app_theme.dart'; import 'package:hum/views/listings/views/items/thumbnail_with_details.dart'; class HomeViewGrid extends StatefulWidget { const HomeViewGrid({super.key}); @override State createState() => _HomeViewGridState(); } class _HomeViewGridState extends State { final ScrollController _scrollController = ScrollController(); @override void dispose() { _scrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final cardRadius = 16.0; return Expanded( child: StreamBuilder( stream: FirebaseFirestore.instance.collection('items').snapshots(), builder: (context, snapshot) { if (snapshot.hasError) { return Center( child: Text( 'Error: ${snapshot.error}', style: const TextStyle(color: CupertinoColors.systemRed), ), ); } // Only show loading spinner on initial load, not on updates if (!snapshot.hasData) { return const Center(child: CupertinoActivityIndicator()); } if (snapshot.data!.docs.isEmpty) { return const Center( child: Text('No items found', style: TextStyle(color: CupertinoColors.systemGrey)), ); } final items = snapshot.data!.docs; return CustomScrollView( controller: _scrollController, cacheExtent: 1000, // Preload images 1000 pixels ahead slivers: [ const SliverPadding(padding: EdgeInsets.only(top: 120.0)), SliverPadding( padding: const EdgeInsets.all(8.0), sliver: SliverGrid( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 6.0, mainAxisSpacing: 6.0, childAspectRatio: 0.9, ), delegate: SliverChildBuilderDelegate( (context, index) { final item = items[index]; Map? itemData = item.data() as Map?; String thumbnailURL = ''; if (itemData != null) { thumbnailURL = itemData['images'][0]; } return GestureDetector( onTap: () { Navigator.of(context, rootNavigator: true).push( CupertinoPageRoute( // fullscreenDialog: true, builder: (context) => ViewListingsItem( itemID: item.id, thumbnailURL: thumbnailURL, itemData: itemData, ), ), ); }, child: Container( key: ValueKey(item.id), decoration: BoxDecoration( color: CupertinoDynamicColor.resolve(colorBarBackground, context), borderRadius: BorderRadius.circular(cardRadius), // border: Border.all(color: color, width: 2.0), ), child: Column( children: [ Stack( children: [ // LISTING IMAGE Padding( padding: const EdgeInsets.all(6.0), child: SizedBox( height: 150, width: double.infinity, child: Hero( tag: itemData?['id'], child: ClipRRect( borderRadius: BorderRadius.only( topLeft: Radius.circular(cardRadius), topRight: Radius.circular(cardRadius), bottomLeft: Radius.circular(cardRadius), bottomRight: Radius.circular(cardRadius), ), child: CachedNetworkImage( imageUrl: thumbnailURL, fit: BoxFit.cover, memCacheHeight: 600, maxHeightDiskCache: 600, fadeInDuration: Duration.zero, fadeOutDuration: Duration.zero, placeholderFadeInDuration: Duration.zero, // fadeInDuration: Duration(milliseconds: 200), placeholder: (context, url) => Center(child: CupertinoActivityIndicator()), errorWidget: (context, url, error) => Icon(CupertinoIcons.photo, size: 32), ), ), ), ), ), // CATEGORY LABEL Positioned( top: 16, left: 16, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(6), color: CupertinoColors.activeBlue.withAlpha(180), ), padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2), child: Text( 'Electronics', style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold), ), ), ), ], ), Expanded( child: Padding( padding: const EdgeInsets.only( left: 0.0, right: 8.0, top: 0.0, bottom: 0.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, spacing: 2, children: [ Text( itemData?['title'], overflow: TextOverflow.ellipsis, maxLines: 1, style: TextStyle(fontSize: 14), ), Text( '\$${itemData!['price_per_day']} / day', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: CupertinoColors.activeBlue, ), ), ], ), ), ), ], ), ), ); }, childCount: items.length, addAutomaticKeepAlives: true, addRepaintBoundaries: true, ), ), ), ], ); }, ), ); } }