import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:carousel_slider/carousel_slider.dart'; import 'package:get/get.dart'; import 'package:wordpress/providers/api_const.dart'; import 'package:wordpress/providers/api_controller.dart'; import 'package:wordpress/utils/app_assests.dart'; import 'package:wordpress/view/all_product_screen.dart'; import 'package:wordpress/view/details_screen.dart'; import 'package:wordpress/viewmodel/cart_screen.dart'; import 'package:wordpress/viewmodel/product_home_page_model.dart'; class HomeScreen extends ConsumerStatefulWidget { const HomeScreen({super.key}); @override ConsumerState createState() => _HomeScreenState(); } class _HomeScreenState extends ConsumerState with TickerProviderStateMixin { late AnimationController _fadeController; late AnimationController _slideController; late AnimationController _scaleController; late Animation _fadeAnimation; late Animation _slideAnimation; late Animation _scaleAnimation; @override void initState() { super.initState(); // Initialize animation controllers _fadeController = AnimationController( duration: const Duration(milliseconds: 800), vsync: this, ); _slideController = AnimationController( duration: const Duration(milliseconds: 1000), vsync: this, ); _scaleController = AnimationController( duration: const Duration(milliseconds: 600), vsync: this, ); // Initialize animations _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut), ); _slideAnimation = Tween(begin: const Offset(0, 0.3), end: Offset.zero).animate( CurvedAnimation(parent: _slideController, curve: Curves.easeOutBack), ); _scaleAnimation = Tween(begin: 0.8, end: 1.0).animate( CurvedAnimation(parent: _scaleController, curve: Curves.elasticOut), ); // Start animations _startAnimations(); } void _startAnimations() async { await Future.delayed(const Duration(milliseconds: 100)); _fadeController.forward(); await Future.delayed(const Duration(milliseconds: 200)); _slideController.forward(); await Future.delayed(const Duration(milliseconds: 300)); _scaleController.forward(); } @override void dispose() { _fadeController.dispose(); _slideController.dispose(); _scaleController.dispose(); super.dispose(); } String getFullImageUrl(String url) { if (url.startsWith("http")) { return url; } return "${ConstsApi.baseUrl}$url"; } @override Widget build(BuildContext context) { final homeAsync = ref.watch(productHomePageProvider); return Scaffold( backgroundColor: Colors.grey[50], body: SafeArea( child: homeAsync.when( data: (data) { return SingleChildScrollView( physics: const BouncingScrollPhysics(), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ScaleTransition( scale: _scaleAnimation, child: _buildHeaderSection(), ), // 🎯 Section 1: Animated Banner Carousel FadeTransition( opacity: _fadeAnimation, child: _buildBannerSection(data.banners), ), const SizedBox(height: 24), // 🎯 Section 2: Animated Categories SlideTransition( position: _slideAnimation, child: _buildCategoriesSection(data.categories), ), const SizedBox(height: 24), // 🎯 Section 3: Animated Latest Products ScaleTransition( scale: _scaleAnimation, child: _buildLatestProductsSection(data.latest), ), const SizedBox(height: 20), ], ), ); }, loading: () => _buildLoadingState(), error: (err, stack) => _buildErrorState(err), ), ), ); } // 🎨 Banner Section with Animation Widget _buildBannerSection(List banners) { if (banners.isEmpty) { return const SizedBox.shrink(); } return Container( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 25), CarouselSlider( options: CarouselOptions( height: 160, autoPlay: true, enlargeCenterPage: true, viewportFraction: 0.9, autoPlayInterval: const Duration(seconds: 4), autoPlayAnimationDuration: const Duration(milliseconds: 800), autoPlayCurve: Curves.fastOutSlowIn, ), items: banners.map((banner) { final url = getFullImageUrl(banner.image); return ClipRRect( borderRadius: BorderRadius.circular(16), child: Container( color: Colors.grey[200], // fallback bg child: Image.network( url, width: double.infinity, height: 160, fit: BoxFit .fill, // fills both width & height // change to BoxFit.contain if you don’t want cropping errorBuilder: (context, error, stackTrace) => Image.network( 'https://project2022.amrithaa.com/ecomdemo/wp-content/uploads/2025/08/product1.jpg', width: double.infinity, height: 160, fit: BoxFit.cover, ), ), ), ); }).toList(), ), ], ), ); } Widget _buildHeaderSection() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Image.asset(AppAssets.logo, height: 60, width: 100), GestureDetector( onTap: () { Get.to(CartScreen()); }, child: Container( width: 40, height: 40, decoration: BoxDecoration( color: Colors.white, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 6, offset: const Offset(0, 3), ), ], ), child: Icon(Icons.shopping_cart, color: Colors.blue), ), ), ], ), ); } // 🎨 Categories Section with Animation Widget _buildCategoriesSection(List categories) { if (categories.isEmpty) { return const SizedBox.shrink(); } return Container( margin: const EdgeInsets.symmetric(horizontal: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( "Shop by Category", style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.black87, ), ), const SizedBox(height: 12), SizedBox( height: 130, child: ListView.builder( scrollDirection: Axis.horizontal, physics: const BouncingScrollPhysics(), itemCount: categories.length, itemBuilder: (context, index) { final category = categories[index]; return TweenAnimationBuilder( duration: Duration(milliseconds: 400 + (index * 100)), tween: Tween(begin: 0.0, end: 1.0), builder: (context, value, child) { return Transform.scale( scale: value, child: Container( width: 100, margin: const EdgeInsets.only(right: 12), child: Column( children: [ Container( height: 80, width: 80, decoration: BoxDecoration( color: Colors .primaries[index % Colors.primaries.length] .withOpacity(0.1), borderRadius: BorderRadius.circular(20), border: Border.all( color: Colors .primaries[index % Colors.primaries.length] .withOpacity(0.3), width: 2, ), ), child: category.image != null ? ClipRRect( borderRadius: BorderRadius.circular(18), child: Image.network( getFullImageUrl(category.image!), fit: BoxFit.cover, errorBuilder: ( context, error, stackTrace, ) => Icon( Icons.category, color: Colors.primaries[index % Colors.primaries.length], size: 30, ), ), ) : Icon( Icons.category, color: Colors.primaries[index % Colors.primaries.length], size: 30, ), ), const SizedBox(height: 8), Text( category.name, textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w500, color: Colors.black87, ), ), ], ), ), ); }, ); }, ), ), ], ), ); } // 🎨 Latest Products Section with Animation Widget _buildLatestProductsSection(List products) { if (products.isEmpty) { return const SizedBox.shrink(); } return Container( margin: const EdgeInsets.symmetric(horizontal: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( "Latest Products", style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.black87, ), ), TextButton( onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => AllProductScreen()), ); }, child: const Text( "View All", style: TextStyle( color: Colors.blue, fontWeight: FontWeight.w600, ), ), ), ], ), const SizedBox(height: 12), GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 0.75, crossAxisSpacing: 12, mainAxisSpacing: 12, ), itemCount: products.length > 6 ? 6 : products.length, itemBuilder: (context, index) { final product = products[index]; return TweenAnimationBuilder( duration: Duration(milliseconds: 500 + (index * 150)), tween: Tween(begin: 0.0, end: 1.0), builder: (context, value, child) { return Transform.translate( offset: Offset(0, 30 * (1 - value)), child: Opacity( opacity: value, child: _buildProductCard(product), ), ); }, ); }, ), ], ), ); } // 🎨 Product Card with Hover Effect Widget _buildProductCard(ProductModel product) { return GestureDetector( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => BigBasketDetailsScreen(productId: product.id), ), ); }, child: AnimatedContainer( duration: const Duration(milliseconds: 200), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.08), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Product Image Expanded( flex: 3, child: Container( decoration: const BoxDecoration( borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), child: ClipRRect( borderRadius: const BorderRadius.vertical( top: Radius.circular(16), ), child: Stack( children: [ Image.network( getFullImageUrl(product.image), width: double.infinity, height: double.infinity, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) => Container( color: Colors.grey[100], child: const Icon( Icons.image_not_supported, color: Colors.grey, size: 40, ), ), ), // Gradient overlay Positioned( bottom: 0, left: 0, right: 0, child: Container( height: 30, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.transparent, Colors.black.withOpacity(0.1), ], ), ), ), ), ], ), ), ), ), // Product Details Expanded( flex: 2, child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( product.name, maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Colors.black87, height: 1.2, ), ), const SizedBox(height: 4), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "β‚Ή${product.price}", style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.green, ), ), GestureDetector( child: Container( padding: const EdgeInsets.all(6), decoration: BoxDecoration( color: Colors.blue, borderRadius: BorderRadius.circular(8), ), child: const Icon( Icons.add_shopping_cart, color: Colors.white, size: 16, ), ), ), ], ), ], ), ), ), ], ), ), ); } // 🎨 Loading State with Animation Widget _buildLoadingState() { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ TweenAnimationBuilder( duration: const Duration(seconds: 1), tween: Tween(begin: 0.0, end: 1.0), builder: (context, value, child) { return Transform.rotate( angle: value * 2 * 3.14159, child: Container( width: 60, height: 60, decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), gradient: const LinearGradient( colors: [Colors.blue, Colors.purple], ), ), child: const Icon( Icons.shopping_bag, color: Colors.white, size: 30, ), ), ); }, ), const SizedBox(height: 16), const Text( "Loading amazing products...", style: TextStyle( fontSize: 16, color: Colors.grey, fontWeight: FontWeight.w500, ), ), ], ), ); } // 🎨 Error State Widget _buildErrorState(dynamic error) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ TweenAnimationBuilder( duration: const Duration(milliseconds: 800), tween: Tween(begin: 0.0, end: 1.0), builder: (context, value, child) { return Transform.scale( scale: value, child: Container( width: 80, height: 80, decoration: BoxDecoration( color: Colors.red.withOpacity(0.1), borderRadius: BorderRadius.circular(40), ), child: const Icon( Icons.error_outline, color: Colors.red, size: 40, ), ), ); }, ), const SizedBox(height: 16), const Text( "Oops! Something went wrong", style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, color: Colors.black87, ), ), const SizedBox(height: 8), Text( "Error: $error", textAlign: TextAlign.center, style: TextStyle(fontSize: 14, color: Colors.grey[600]), ), const SizedBox(height: 16), ElevatedButton( onPressed: () { // Retry logic ref.invalidate(productHomePageProvider); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.blue, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: const Text( "Try Again", style: TextStyle(fontWeight: FontWeight.w600), ), ), ], ), ); } } // 🎨 Additional Animation Extensions for Enhanced UI extension AnimatedWidgetExtensions on Widget { Widget fadeInUp({ Duration duration = const Duration(milliseconds: 600), Duration delay = Duration.zero, }) { return TweenAnimationBuilder( duration: duration, tween: Tween(begin: 0.0, end: 1.0), builder: (context, value, child) { return Transform.translate( offset: Offset(0, 20 * (1 - value)), child: Opacity(opacity: value, child: this), ); }, ); } Widget bounceIn({Duration duration = const Duration(milliseconds: 800)}) { return TweenAnimationBuilder( duration: duration, tween: Tween(begin: 0.0, end: 1.0), curve: Curves.elasticOut, builder: (context, value, child) { return Transform.scale(scale: value, child: this); }, ); } }