From 6599d9a05ce3a17173db32be05819a35e7cfdfcf Mon Sep 17 00:00:00 2001 From: Vaibhav Date: Tue, 13 Aug 2024 18:57:01 +0530 Subject: [PATCH] Change UI (UID screen) & Add Product --- lib/screens/Add_products_screen.dart | 284 +++++++++++++++++++++++ lib/screens/update_inventory_screen.dart | 167 ++++++++----- 2 files changed, 393 insertions(+), 58 deletions(-) create mode 100644 lib/screens/Add_products_screen.dart diff --git a/lib/screens/Add_products_screen.dart b/lib/screens/Add_products_screen.dart new file mode 100644 index 0000000..6b8b41e --- /dev/null +++ b/lib/screens/Add_products_screen.dart @@ -0,0 +1,284 @@ +import 'package:flutter/material.dart'; +import 'package:cheminova/widgets/common_background.dart'; +import 'package:cheminova/widgets/common_app_bar.dart'; +import 'package:cheminova/widgets/common_drawer.dart'; +import 'package:cheminova/widgets/common_elevated_button.dart'; +import 'package:cheminova/screens/data_submit_successfull.dart'; + +class AddProductsScreen extends StatefulWidget { + const AddProductsScreen({super.key}); + + @override + State createState() => _AddProductsScreenState(); +} + +class _AddProductsScreenState extends State { + final List products = [ + Product(name: 'Product A', sku: 'SKU001', isPurchased: true), + Product(name: 'Product B', sku: 'SKU002', isPurchased: true), + Product(name: 'Product C', sku: 'SKU003', isPurchased: false), + ]; + + List selectedProducts = []; + List filteredProducts = []; + final searchController = TextEditingController(); + + @override + void initState() { + super.initState(); + filteredProducts = products; + } + + void filterProducts(String query) { + setState(() { + filteredProducts = products.where((product) { + final productNameLower = product.name.toLowerCase(); + final productSkuLower = product.sku.toLowerCase(); + final searchLower = query.toLowerCase(); + + return productNameLower.contains(searchLower) || + productSkuLower.contains(searchLower); + }).toList(); + }); + } + + @override + Widget build(BuildContext context) { + return CommonBackground( + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: CommonAppBar( + actions: [ + IconButton( + onPressed: () { + Navigator.pop(context); + }, + icon: Image.asset('assets/Back_attendance.png'), + padding: const EdgeInsets.only(right: 20), + ), + ], + title: const Text('Add Products', + style: TextStyle( + fontSize: 20, + color: Colors.black, + fontWeight: FontWeight.w400, + fontFamily: 'Anek')), + backgroundColor: Colors.transparent, + elevation: 0, + ), + drawer: const CommonDrawer(), + body: Stack( + children: [ + Column( + children: [ + if (selectedProducts.isNotEmpty) + Expanded( + child: ListView.builder( + itemCount: selectedProducts.length, + itemBuilder: (context, index) { + return ProductBlock(product: selectedProducts[index]); + }, + ), + ), + ], + ), + Align( + alignment: selectedProducts.isEmpty ? Alignment.center : Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FloatingActionButton.extended( + onPressed: () { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return StatefulBuilder( + builder: (context, setState) { + return Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: searchController, + decoration: const InputDecoration( + labelText: 'Search by name or SKU', + border: OutlineInputBorder(), + prefixIcon: Icon(Icons.search), + ), + onChanged: (value) { + filterProducts(value); + setState(() {}); + }, + ), + ), + Expanded( + child: ListView.builder( + itemCount: filteredProducts.length, + itemBuilder: (context, index) { + bool isAlreadySelected = selectedProducts.contains(filteredProducts[index]); + return ListTile( + title: Text( + filteredProducts[index].name, + style: TextStyle( + color: isAlreadySelected ? Colors.grey : Colors.black, + ), + ), + subtitle: Text( + filteredProducts[index].sku, + style: TextStyle( + color: isAlreadySelected ? Colors.grey : Colors.black, + ), + ), + onTap: isAlreadySelected + ? null + : () { + setState(() { + selectedProducts.add(filteredProducts[index]); + }); + Navigator.pop(context); + }, + ); + }, + ), + ), + ], + ); + }, + ); + }, + ).whenComplete(() { + setState(() {}); + }); + }, + backgroundColor: Colors.white, + icon: const Icon(Icons.add, color: Colors.black), + label: const Text( + 'Add Products', + style: TextStyle(color: Colors.black), + ), + ), + if (selectedProducts.isNotEmpty) ...[ + const SizedBox(height: 16.0), + CommonElevatedButton( + borderRadius: 30, + width: double.infinity, + height: kToolbarHeight - 10, + text: 'SUBMIT', + backgroundColor: const Color(0xff004791), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const DataSubmitSuccessfull(), + ), + ); + }, + ), + ], + ], + ), + ), + ), + ], + ), + ), + ); + } +} + +class Product { + final String name; + final String sku; + final bool isPurchased; + int? sale; + int? inventory; + + Product({ + required this.name, + required this.sku, + required this.isPurchased, + this.sale, + this.inventory, + }); +} + +class ProductBlock extends StatefulWidget { + final Product product; + + const ProductBlock({super.key, required this.product}); + + @override + _ProductBlockState createState() => _ProductBlockState(); +} + +class _ProductBlockState extends State { + final saleController = TextEditingController(); + final inventoryController = TextEditingController(); + String? errorMessage; + + @override + void initState() { + super.initState(); + saleController.text = widget.product.sale?.toString() ?? ''; + inventoryController.text = widget.product.inventory?.toString() ?? ''; + } + + void validateInput() { + setState(() { + if (saleController.text.isNotEmpty && inventoryController.text.isNotEmpty) { + int sale = int.parse(saleController.text); + int inventory = int.parse(inventoryController.text); + if (inventory > sale) { + errorMessage = 'Inventory should be less than or equal to sales'; + } else { + errorMessage = null; + } + } else { + errorMessage = null; + } + }); + } + + @override + Widget build(BuildContext context) { + return Card( + color: !widget.product.isPurchased ? Colors.white54 : Colors.white, + margin: const EdgeInsets.all(8), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Product: ${widget.product.name}', style: const TextStyle(fontSize: 16)), + Text('SKU: ${widget.product.sku}', style: const TextStyle(fontSize: 15)), + const SizedBox(height: 8), + TextField( + controller: saleController, + decoration: const InputDecoration(labelText: 'Sale'), + keyboardType: TextInputType.number, + enabled: widget.product.isPurchased, + onChanged: (_) => validateInput(), + ), + TextField( + controller: inventoryController, + decoration: const InputDecoration(labelText: 'Inventory'), + keyboardType: TextInputType.number, + enabled: widget.product.isPurchased, + onChanged: (_) => validateInput(), + ), + if (errorMessage != null) + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text( + errorMessage!, + style: const TextStyle(color: Colors.red), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/update_inventory_screen.dart b/lib/screens/update_inventory_screen.dart index 379fea9..62b2be9 100644 --- a/lib/screens/update_inventory_screen.dart +++ b/lib/screens/update_inventory_screen.dart @@ -1,3 +1,4 @@ +import 'package:cheminova/screens/Add_products_screen.dart'; import 'package:flutter/material.dart'; import 'package:cheminova/widgets/common_background.dart'; import 'package:cheminova/widgets/common_app_bar.dart'; @@ -13,14 +14,19 @@ class UpdateInventoryScreen extends StatefulWidget { } class _UpdateInventoryScreenState extends State { - final searchController = TextEditingController(); - List products = [ + final List products = [ Product(name: 'Product A', sku: 'SKU001', isPurchased: true), Product(name: 'Product B', sku: 'SKU002', isPurchased: true), Product(name: 'Product C', sku: 'SKU003', isPurchased: false), ]; + List selectedProducts = []; List filteredProducts = []; + final List principalDistributors = ['vaibhav', 'sonu', 'monu']; + final List retailerDistributors = ['shivam', 'vivek']; + String? selectedDistributorType; + String? selectedDistributor; + final searchController = TextEditingController(); @override void initState() { @@ -30,10 +36,14 @@ class _UpdateInventoryScreenState extends State { void filterProducts(String query) { setState(() { - filteredProducts = products - .where((product) => - product.name.toLowerCase().contains(query.toLowerCase())) - .toList(); + filteredProducts = products.where((product) { + final productNameLower = product.name.toLowerCase(); + final productSkuLower = product.sku.toLowerCase(); + final searchLower = query.toLowerCase(); + + return productNameLower.contains(searchLower) || + productSkuLower.contains(searchLower); + }).toList(); }); } @@ -62,47 +72,97 @@ class _UpdateInventoryScreenState extends State { elevation: 0, ), drawer: const CommonDrawer(), - body: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: TextField( - controller: searchController, - decoration: const InputDecoration( - fillColor: Colors.white, - filled: true, - labelText: 'Search', - suffixIcon: Icon(Icons.search), - border: OutlineInputBorder(), + bottomNavigationBar: Padding( + padding: const EdgeInsets.all(16.0), + child: CommonElevatedButton( + borderRadius: 30, + width: double.infinity, + height: kToolbarHeight - 10, + text: 'SUBMIT', + backgroundColor: const Color(0xff004791), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const AddProductsScreen(), ), - onChanged: filterProducts, - ), - ), - Expanded( - child: ListView.builder( - itemCount: filteredProducts.length, - itemBuilder: (context, index) { - return ProductBlock(product: filteredProducts[index]); - }, - ), - ), - Padding( - padding: const EdgeInsets.all(16.0), - child: CommonElevatedButton( - borderRadius: 30, - width: double.infinity, - height: kToolbarHeight - 10, - text: 'SUBMIT', - backgroundColor: const Color(0xff004791), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const DataSubmitSuccessfull(), + ); + }, + ), + ), + body: Stack( + children: [ + Column( + children: [ + // Dropdown for selecting distributor type + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 25), + child: DropdownButtonFormField( + decoration: const InputDecoration( + labelText: 'Select Distributor Type', + fillColor: Colors.white, + filled: true, + border: OutlineInputBorder(), ), - ); - }, - ), + value: selectedDistributorType, + items: ['Principal Distributor', 'Retailer Distributor'].map((String type) { + return DropdownMenuItem( + value: type, + child: Text(type), + ); + }).toList(), + onChanged: (value) { + setState(() { + selectedDistributorType = value; + selectedDistributor = null; // Reset distributor selection when type changes + }); + }, + ), + ), + // Dropdown for selecting distributor name based on type + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 25), + child: DropdownButtonFormField( + decoration: const InputDecoration( + labelText: 'Select Distributor Name', + fillColor: Colors.white, + filled: true, + border: OutlineInputBorder(), + ), + value: selectedDistributor, + items: (selectedDistributorType == 'Principal Distributor' + ? principalDistributors + : retailerDistributors) + .map((String distributor) { + return DropdownMenuItem( + value: distributor, + child: Text(distributor), + ); + }).toList(), + onChanged: (value) { + setState(() { + selectedDistributor = value; + }); + }, + // Disable the dropdown if no distributor type is selected + isExpanded: true, + isDense: true, + iconSize: 24, + hint: Text( + 'Please select a ${selectedDistributorType ?? "Distributor Type"} first'), + ), + ), + // Show the selected products + if (selectedProducts.isNotEmpty) + Expanded( + child: ListView.builder( + itemCount: selectedProducts.length, + itemBuilder: (context, index) { + return ProductBlock(product: selectedProducts[index]); + }, + ), + ), + ], ), ], ), @@ -117,7 +177,6 @@ class Product { final bool isPurchased; int? sale; int? inventory; - String? liquidation; Product({ required this.name, @@ -125,7 +184,6 @@ class Product { required this.isPurchased, this.sale, this.inventory, - this.liquidation, }); } @@ -141,7 +199,6 @@ class ProductBlock extends StatefulWidget { class _ProductBlockState extends State { final saleController = TextEditingController(); final inventoryController = TextEditingController(); - final liquidationController = TextEditingController(); String? errorMessage; @override @@ -149,7 +206,6 @@ class _ProductBlockState extends State { super.initState(); saleController.text = widget.product.sale?.toString() ?? ''; inventoryController.text = widget.product.inventory?.toString() ?? ''; - liquidationController.text = widget.product.liquidation ?? ''; } void validateInput() { @@ -171,15 +227,15 @@ class _ProductBlockState extends State { @override Widget build(BuildContext context) { return Card( - color: !widget.product.isPurchased?Colors.white54:Colors.white, + color: !widget.product.isPurchased ? Colors.white54 : Colors.white, margin: const EdgeInsets.all(8), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Product: ${widget.product.name}',style: TextStyle(fontSize: 16),), - Text('SKU: ${widget.product.sku}',style: TextStyle(fontSize: 15),), + Text('Product: ${widget.product.name}', style: const TextStyle(fontSize: 16)), + Text('SKU: ${widget.product.sku}', style: const TextStyle(fontSize: 15)), const SizedBox(height: 8), TextField( controller: saleController, @@ -195,11 +251,6 @@ class _ProductBlockState extends State { enabled: widget.product.isPurchased, onChanged: (_) => validateInput(), ), - // TextField( - // controller: liquidationController, - // decoration: const InputDecoration(labelText: 'Liquidation'), - // enabled: widget.product.isPurchased, - // ), if (errorMessage != null) Padding( padding: const EdgeInsets.only(top: 8.0), @@ -213,4 +264,4 @@ class _ProductBlockState extends State { ), ); } -} \ No newline at end of file +}