import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../Controller/products/product_controller.dart'; import '../../Globalwidgets/textwidget.dart'; import '../../Helper/Constants/AssetConstants.dart'; import '../../Helper/Constants/Colorconstants.dart'; import '../../Helper/Logger.dart'; import '../../Model/Response/products/product_response.dart'; import '../Dashboard/Dashboardview.dart'; class ProductView extends StatelessWidget { ProductView({super.key}); final ProductController controller = Get.put(ProductController()); final FocusNode searchFocusNode = FocusNode(); @override Widget build(BuildContext context) { return GetBuilder( initState: (_) { controller.getProducts(); }, builder: (controller) { return Scaffold( appBar: AppBar( automaticallyImplyLeading: false, title: AnimatedSwitcher( duration: const Duration(milliseconds: 300), transitionBuilder: (Widget child, Animation animation) { return SizeTransition( sizeFactor: animation, axis: Axis.horizontal, child: FadeTransition(opacity: animation, child: child), ); }, child: controller.isSearchModeEnable.value ? TextField( key: const ValueKey('searchField'), focusNode: searchFocusNode, controller: controller.productSearchController, cursorColor: ColorConstants.primaryColor, decoration: const InputDecoration( hintText: 'Search Products', border: UnderlineInputBorder( borderSide: BorderSide(color: Colors.white), ), enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.white), ), focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.white, width: 2), ), isDense: false, contentPadding: EdgeInsets.zero, ), style: const TextStyle(color: Colors.black), // 🔥 FIXED HERE — USE LOCAL SEARCH onChanged: (value) { controller.applySearch(value); }, autofocus: true, ) : TextWidget( key: const ValueKey('titleText'), text: 'Products', fontWeight: FontWeight.w700, fontSize: 20, ), ), actions: [ Padding( padding: const EdgeInsets.only(right: 12), child: InkWell( onTap: () { if (controller.isSearchModeEnable.value) { controller.productSearchController.clear(); searchFocusNode.unfocus(); // 🔥 FIXED HERE — RESTORE LIST controller.applySearch(''); } else { Future.delayed(const Duration(milliseconds: 100), () { searchFocusNode.requestFocus(); }); } controller.isSearchModeEnable.value = !controller.isSearchModeEnable.value; controller.update(); }, child: Icon( controller.isSearchModeEnable.value ? Icons.cancel : Icons.search, color: ColorConstants.primaryColor, ), ), ), ], ), body: Obx(() { if (controller.isProductLoading.value) { return const Center( child: Padding( padding: EdgeInsets.only(top: 10), child: ShimmerListView(height: 100), ), ); } if (controller.product.isEmpty) { return emptyProductsWidget(); } return ListView.builder( cacheExtent: 1000, itemCount: controller.product.length, itemBuilder: (context, index) { final product = controller.product[index]; return ProductCard( key: ValueKey(product.productid), product: product, index: index, controller: controller, isLoading: controller.loadingIndices.contains(index), ); }, ); }), ); }, ); } } /// Product Card Widget class ProductCard extends StatelessWidget { final ProductData product; final int index; final ProductController controller; final bool isLoading; const ProductCard({ super.key, required this.product, required this.index, required this.controller, required this.isLoading, }); @override Widget build(BuildContext context) { final isAvailable = product.status == 'Active'; return Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0), child: Padding( padding: const EdgeInsets.only(top: 5), child: Card( elevation: 0, shadowColor: Colors.grey.shade100, color: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.only(top: 12, left: 10, right: 10), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: BorderRadius.circular(12), child: CachedNetworkImage( imageUrl: product.productimage ?? '', width: 80, height: 80, fit: BoxFit.cover, memCacheHeight: 160, memCacheWidth: 160, maxHeightDiskCache: 160, maxWidthDiskCache: 160, placeholder: (context, url) => Container( width: 80, height: 80, color: Colors.grey.shade100, child: Icon(Icons.image, color: Colors.grey.shade400, size: 40), ), errorWidget: (context, url, error) => Container( width: 80, height: 80, color: Colors.grey.shade100, child: Icon(Icons.broken_image_outlined, color: Colors.grey.shade400, size: 40), ), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ TextWidget( text: product.productname ?? 'Unknown', maxLines: 1, fontSize: 15, fontWeight: FontWeight.w700, color: isAvailable ? Colors.black87 : Colors.grey.shade600, ), const SizedBox(height: 8), Row( children: [ Icon( Icons.inventory_2_outlined, size: 16, color: Colors.grey.shade500, ), const SizedBox(width: 4), Text( "Qty: ${product.productstock ?? 0}", style: TextStyle( fontSize: 14, color: Colors.grey.shade700, fontWeight: FontWeight.w500, ), ), const Spacer(), Text( product.productcost != null ? '₹${product.productcost!.toStringAsFixed(2)}' : 'N/A', style: TextStyle( fontSize: 14, color: Colors.grey.shade700, fontWeight: FontWeight.w500, ), ), ], ), const SizedBox(height: 8), Row( children: [ Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6), decoration: BoxDecoration( color: isAvailable ? Colors.green.shade500 : Colors.red.shade400, borderRadius: BorderRadius.circular(10), ), child: Text( isAvailable ? "Active" : "Out of Stock", style: const TextStyle( fontSize: 11, color: Colors.white, fontWeight: FontWeight.w600, ), ), ), const Spacer(), AnimatedOpacity( opacity: isLoading ? 0.6 : 1.0, duration: const Duration(milliseconds: 300), child: Switch.adaptive( value: isAvailable, activeColor: Colors.green.shade500, inactiveThumbColor: Colors.grey.shade400, inactiveTrackColor: Colors.grey.shade200, onChanged: isLoading ? null : (_) => controller.toggleAvailability(index), ), ), ], ), ], ), ), ], ), ), ), ), ); } } Widget emptyProductsWidget() { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ const SizedBox(height: 10), Image.asset( AssetConstants.noProductsFound, height: 200, width: 200, fit: BoxFit.fill, ), TextWidget( text: 'No Products Found!', color: ColorConstants.blackColor, fontSize: 18, fontWeight: FontWeight.w700, maxLines: 2, textAlign: TextAlign.center, ), const SizedBox(height: 10), TextWidget( text: 'You haven’t added any products yet.', color: ColorConstants.blackColor, fontSize: 14, fontWeight: FontWeight.normal, maxLines: 2, textAlign: TextAlign.center, ), ], ), ); }