import 'package:cheminova/models/SalesTaskResponse.dart'; import 'package:cheminova/provider/add_sales_product_provider.dart'; import 'package:cheminova/widgets/common_app_bar.dart'; import 'package:cheminova/widgets/common_background.dart'; import 'package:cheminova/widgets/common_drawer.dart'; import 'package:cheminova/widgets/common_elevated_button.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; class AddSalesProductScreen extends StatefulWidget { // Final properties to store data passed from previous screen final String distributorType; final String tradeName; final String pdRdId; final String? inventoryId; const AddSalesProductScreen({ super.key, required this.distributorType, required this.tradeName, required this.pdRdId, this.inventoryId, }); @override State createState() => _AddSalesProductScreenState(); } class _AddSalesProductScreenState extends State { // Controllers for text fields final searchController = TextEditingController(); late AddSalesProvider salesTaskProvider; final dateController = TextEditingController(); final formKey = GlobalKey(); @override void initState() { super.initState(); // Initialize the provider and set the current date salesTaskProvider = Provider.of(context, listen: false); dateController.text = DateFormat('dd/MM/yyyy').format(DateTime.now()); WidgetsBinding.instance.addPostFrameCallback((_) { salesTaskProvider.getTask(); }); } @override void dispose() { // Dispose of the text controllers and reset the provider when the widget is removed searchController.dispose(); dateController.dispose(); if (mounted) { salesTaskProvider.resetProducts(); } super.dispose(); } @override Widget build(BuildContext context) { return PopScope( canPop: true, child: CommonBackground(// Common background for the screen child: Scaffold( backgroundColor: Colors.transparent, appBar: CommonAppBar(// Custom AppBar with back button and title actions: [ IconButton( onPressed: () => Navigator.pop(context), icon: Image.asset('assets/Back_attendance.png'), padding: const EdgeInsets.only(right: 20), ) ], title: Text( '${widget.distributorType}\n${widget.tradeName}', textAlign: TextAlign.center, style: const TextStyle( fontSize: 20, color: Colors.black, fontWeight: FontWeight.w400, fontFamily: 'Anek', ), ), backgroundColor: Colors.transparent, elevation: 0, ), drawer: const CommonDrawer(), bottomNavigationBar: Consumer( builder: (context, value, child) => Column( mainAxisSize: MainAxisSize.min, children: [ Align( alignment: value.tasksList.isEmpty ? Alignment.center : Alignment.bottomCenter, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisSize: MainAxisSize.min, children: [// Floating button to add products FloatingActionButton.extended( onPressed: () => _showProductSelectionBottomSheet(context), backgroundColor: Colors.white, icon: const Icon(Icons.add, color: Colors.black), label: const Text('Add Products', style: TextStyle(color: Colors.black)), ), if (value.selectedProducts.isNotEmpty) ...[ const SizedBox(height: 16.0), // Submit button that appears after products are selected CommonElevatedButton( borderRadius: 30, width: double.infinity, height: kToolbarHeight - 10, text: 'SUBMIT', backgroundColor: const Color(0xff004791), onPressed: () => _submitProducts(value), ), ], ], ), ), ), ], ), ), body: Consumer(// Displays the list of selected products or loading indicator builder: (context, value, child) { return Stack( children: [ Column( children: [ Padding( padding: const EdgeInsets.all(8.0), child: TextFormField(// Date selection field controller: dateController, readOnly: true, decoration: const InputDecoration( labelText: 'Date', fillColor: Colors.white, filled: true, border: InputBorder.none, suffixIcon: Icon(Icons.calendar_today), ), ), ), // Display selected products list if (value.selectedProducts.isNotEmpty) Expanded( child: ListView.builder( itemCount: value.selectedProducts.length, itemBuilder: (context, index) { return ProductBlock( onUpdate: (updatedProduct) { setState(() { value.selectedProducts[index] = updatedProduct; }); }, onRemove: () { setState(() { value.selectedProducts.removeAt(index); }); }, product: value.selectedProducts[index], ); }, ), ), ], ), // Loading indicator if (value.isLoading) Container( color: Colors.black12, child: const Center(child: CircularProgressIndicator()), ), ], ); }, ), ), ), ); } // Function to show product selection modal bottom sheet void _showProductSelectionBottomSheet(BuildContext context) { showModalBottomSheet( isScrollControlled: true, context: context, builder: (BuildContext context) { return Consumer( builder: (context, value, child) => StatefulBuilder( builder: (context, setState) { return Column( children: [ Padding( padding: const EdgeInsets.all(18.0), child: TextField( controller: searchController, decoration: const InputDecoration( labelText: 'Search by name or SKU', border: OutlineInputBorder(), prefixIcon: Icon(Icons.search), ), onChanged: (val) {// Filter product list based on search query value.filterProducts(val); setState(() {}); }, ), ), // List of products to choose from Expanded( child: ListView.builder( itemCount: searchController.text.isEmpty ? value.tasksList.length : value.searchList.length, itemBuilder: (context, index) { final data = searchController.text.isEmpty ? value.tasksList[index] : value.searchList[index]; bool isAlreadySelected = value.selectedProducts .any((selectedProduct) => selectedProduct.SKU == data.SKU); return Card( child: ListTile( title: Text( data.ProductName ?? '', style: TextStyle(color: isAlreadySelected ? Colors.grey : Colors.black), ), subtitle: Text( data.SKU ?? '', style: TextStyle(color: isAlreadySelected ? Colors.grey : Colors.black), ), onTap: isAlreadySelected ? null : () { setState(() => value.selectedProducts.add(data)); Navigator.pop(context); }, ), ); }, ), ), ], ); }, ), ); }, ).whenComplete(() => setState(() {}));// Refresh UI after modal is closed } // Function to submit selected products void _submitProducts(AddSalesProvider value) { if (formKey.currentState!.validate()) { if (value.selectedProducts.isNotEmpty && value.selectedProducts.every((product) => product.SKU!.isNotEmpty && product.ProductName!.isNotEmpty && product.SalesAmount != null && product.QuantitySold != null)) { value.submitProducts( distributorType: widget.distributorType, pdRdId: widget.pdRdId, inventoryId: widget.inventoryId, date: dateController.text.trim(), tradeName: widget.tradeName, ); } else { // Show error message if any product information is missing ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Please fill out all product details, including sale and inventory.'), ), ); } } } } // The ProductBlock class remains unchanged class ProductBlock extends StatefulWidget { final SalesProduct product; final ValueChanged onUpdate; final VoidCallback onRemove; const ProductBlock({ super.key, required this.product, required this.onUpdate, required this.onRemove, }); @override State createState() => _ProductBlockState(); } class _ProductBlockState extends State { final saleAmountController = TextEditingController(); final quantitySoldController = TextEditingController(); final commentController = TextEditingController(); String? errorMessage; @override void initState() { super.initState(); saleAmountController.text = (widget.product.SalesAmount ?? '').toString(); commentController.text = (widget.product.comments ?? '').toString(); quantitySoldController.text = (widget.product.QuantitySold ?? '').toString(); } void validateInput() { setState(() { String? quantitySoldError; String? salesAmountError; if (saleAmountController.text.isEmpty) { quantitySoldError = 'Quantity sold cannot be empty.'; } if (quantitySoldController.text.isEmpty) { salesAmountError = 'Sales amount cannot be empty.'; } errorMessage = null; if (quantitySoldError == null && salesAmountError == null) { int quantitySold = int.parse(quantitySoldController.text); int salesAmount = int.parse(saleAmountController.text); String comments = commentController.text; widget.onUpdate(SalesProduct( SKU: widget.product.SKU, ProductName: widget.product.ProductName, QuantitySold: quantitySold, SalesAmount: salesAmount, comments: comments, )); } else { errorMessage = quantitySoldError ?? salesAmountError; } }); } @override Widget build(BuildContext context) { return Card( color: Colors.white, margin: const EdgeInsets.all(8), child: Stack( children: [ Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Product: ${widget.product.ProductName}', style: const TextStyle(fontSize: 16)), Text('SKU: ${widget.product.SKU}', style: const TextStyle(fontSize: 15)), const SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ TextField( controller: saleAmountController, onTapOutside: (event) => FocusScope.of(context).unfocus(), inputFormatters: [FilteringTextInputFormatter.digitsOnly], decoration: InputDecoration( labelText: 'Sales amount', errorText: saleAmountController.text.isEmpty ? 'Sales amount cannot be empty.' : null, ), keyboardType: TextInputType.number, enabled: true, onChanged: (_) => validateInput(), ), TextField( controller: quantitySoldController, onTapOutside: (event) => FocusScope.of(context).unfocus(), inputFormatters: [FilteringTextInputFormatter.digitsOnly], decoration: InputDecoration( labelText: 'Quantity sold', errorText: quantitySoldController.text.isEmpty ? 'Quantity sold cannot be empty.' : null, ), keyboardType: TextInputType.number, enabled: true, onChanged: (_) => validateInput(), ), TextField( controller: commentController, onTapOutside: (event) => FocusScope.of(context).unfocus(), decoration: const InputDecoration( labelText: 'Comments', ), enabled: true, onChanged: (_) => validateInput(), ), ], ), ], ), ), Positioned( top: 0, right: 0, child: IconButton( icon: const Icon( Icons.delete_outlined, color: Colors.red, ), onPressed: widget.onRemove, ), ), ], ), ); } @override void dispose() { saleAmountController.dispose(); quantitySoldController.dispose(); commentController.dispose(); super.dispose(); } }