diff --git a/lib/main.dart b/lib/main.dart index 5724c7b..57a848e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:cheminova/provider/collect_kyc_provider.dart'; import 'package:cheminova/provider/pd_rd_provider.dart'; import 'package:cheminova/provider/product_provider.dart'; +import 'package:cheminova/provider/task_provider.dart'; import 'package:cheminova/provider/user_provider.dart'; import 'package:cheminova/screens/splash_screen.dart'; import 'package:firebase_core/firebase_core.dart'; @@ -100,6 +101,7 @@ Future main() async { ChangeNotifierProvider(create: (_) => UserProvider()), ChangeNotifierProvider(create: (_) => ProductProvider()), ChangeNotifierProvider(create: (_) => PdRdProvider()), + ChangeNotifierProvider(create: (_) => TaskProvider()), ], child: const MyApp(), ), @@ -117,12 +119,16 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { return MaterialApp( - debugShowCheckedModeBanner: false, - // scaffoldMessengerKey: SnackBarService().scaffoldMessengerKey, - title: 'cheminova', - theme: ThemeData( - colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), - useMaterial3: true), - home: const SplashScreen()); + debugShowCheckedModeBanner: false, + // scaffoldMessengerKey: SnackBarService().scaffoldMessengerKey, + title: 'cheminova', + theme: ThemeData( + colorScheme: ColorScheme.fromSeed( + seedColor: const Color(0xff004791), + ), + useMaterial3: true, + ), + home: const SplashScreen(), + ); } } diff --git a/lib/models/pd_rd_response_model.dart b/lib/models/pd_rd_response_model.dart index 41f5ec1..227c4c6 100644 --- a/lib/models/pd_rd_response_model.dart +++ b/lib/models/pd_rd_response_model.dart @@ -1,123 +1,127 @@ class PdRdResponseModel { - String id; - String name; - String tradeName; - String address; - String state; - String city; - String district; - String pincode; - String mobileNumber; - String principalDistributer; - String panNumber; - ImageModel panImg; - String aadharNumber; - ImageModel aadharImg; - String gstNumber; - ImageModel gstImg; - ImageModel pesticideLicenseImg; - ImageModel selfieEntranceImg; - String status; - String addedBy; + String? id; + String? uniqueId; + String? name; + String? tradeName; + String? address; + String? state; + String? city; + String? district; + String? pincode; + String? mobileNumber; + String? principalDistributer; + String? panNumber; + ImageModel? panImg; + String? aadharNumber; + ImageModel? aadharImg; + String? gstNumber; + ImageModel? gstImg; + ImageModel? pesticideLicenseImg; + ImageModel? selfieEntranceImg; + String? status; + String? addedBy; String? userType; - List notes; - DateTime createdAt; - DateTime updatedAt; - int v; + List? notes; + DateTime? createdAt; + DateTime? updatedAt; + int? v; PdRdResponseModel({ - required this.id, - required this.name, - required this.tradeName, - required this.address, - required this.state, - required this.city, - required this.district, - required this.pincode, - required this.mobileNumber, - required this.principalDistributer, - required this.panNumber, - required this.panImg, - required this.aadharNumber, - required this.aadharImg, - required this.gstNumber, - required this.gstImg, - required this.pesticideLicenseImg, - required this.selfieEntranceImg, - required this.status, - required this.addedBy, + this.id, + this.uniqueId, + this.name, + this.tradeName, + this.address, + this.state, + this.city, + this.district, + this.pincode, + this.mobileNumber, + this.principalDistributer, + this.panNumber, + this.panImg, + this.aadharNumber, + this.aadharImg, + this.gstNumber, + this.gstImg, + this.pesticideLicenseImg, + this.selfieEntranceImg, + this.status, + this.addedBy, this.userType, - required this.notes, - required this.createdAt, - required this.updatedAt, - required this.v, + this.notes, + this.createdAt, + this.updatedAt, + this.v, }); factory PdRdResponseModel.fromJson(Map json) => PdRdResponseModel( id: json["_id"], name: json["name"], - tradeName: json["trade_name"], - address: json["address"], - state: json["state"], - city: json["city"], - district: json["district"], - pincode: json["pincode"], - mobileNumber: json["mobile_number"], - principalDistributer: json["principal_distributer"], - panNumber: json["pan_number"], - panImg: ImageModel.fromJson(json["pan_img"]), - aadharNumber: json["aadhar_number"], - aadharImg: ImageModel.fromJson(json["aadhar_img"]), - gstNumber: json["gst_number"], - gstImg: ImageModel.fromJson(json["gst_img"]), - pesticideLicenseImg: ImageModel.fromJson(json["pesticide_license_img"]), - selfieEntranceImg: ImageModel.fromJson(json["selfie_entrance_img"]), - status: json["status"], - addedBy: json["addedBy"], - userType: json["userType"], - notes: List.from(json["notes"].map((x) => Note.fromJson(x))), - createdAt: DateTime.parse(json["createdAt"]), - updatedAt: DateTime.parse(json["updatedAt"]), - v: json["__v"], + uniqueId: json["uniqueId"], + // tradeName: json["trade_name"], + // address: json["address"], + // state: json["state"], + // city: json["city"], + // district: json["district"], + // pincode: json["pincode"], + // mobileNumber: json["mobile_number"], + // principalDistributer: json["principal_distributer"], + // panNumber: json["pan_number"], + // panImg: ImageModel.fromJson(json["pan_img"]), + // aadharNumber: json["aadhar_number"], + // aadharImg: ImageModel.fromJson(json["aadhar_img"]), + // gstNumber: json["gst_number"], + // gstImg: ImageModel.fromJson(json["gst_img"]), + // pesticideLicenseImg: ImageModel.fromJson(json["pesticide_license_img"]), + // selfieEntranceImg: ImageModel.fromJson(json["selfie_entrance_img"]), + // status: json["status"], + // addedBy: json["addedBy"], + // userType: json["userType"], + // notes: List.from(json["notes"].map((x) => Note.fromJson(x))), + // createdAt: DateTime.parse(json["createdAt"]), + // updatedAt: DateTime.parse(json["updatedAt"]), + // v: json["__v"], ); Map toJson() => { "_id": id, "name": name, - "trade_name": tradeName, - "address": address, - "state": state, - "city": city, - "district": district, - "pincode": pincode, - "mobile_number": mobileNumber, - "principal_distributer": principalDistributer, - "pan_number": panNumber, - "pan_img": panImg.toJson(), - "aadhar_number": aadharNumber, - "aadhar_img": aadharImg.toJson(), - "gst_number": gstNumber, - "gst_img": gstImg.toJson(), - "pesticide_license_img": pesticideLicenseImg.toJson(), - "selfie_entrance_img": selfieEntranceImg.toJson(), - "status": status, - "addedBy": addedBy, - "userType": userType, - "notes": List.from(notes.map((x) => x.toJson())), - "createdAt": createdAt.toIso8601String(), - "updatedAt": updatedAt.toIso8601String(), - "__v": v, + "uniqueId": uniqueId, + // "trade_name": tradeName, + // "address": address, + // "state": state, + // "city": city, + // "district": district, + // "pincode": pincode, + // "mobile_number": mobileNumber, + // "principal_distributer": principalDistributer, + // "pan_number": panNumber, + // "pan_img": panImg.toJson(), + // "aadhar_number": aadharNumber, + // "aadhar_img": aadharImg.toJson(), + // "gst_number": gstNumber, + // "gst_img": gstImg.toJson(), + // "pesticide_license_img": pesticideLicenseImg.toJson(), + // "selfie_entrance_img": selfieEntranceImg.toJson(), + // "status": status, + // "addedBy": addedBy, + // "userType": userType, + // "notes": List.from(notes.map((x) => x.toJson())), + // "createdAt": createdAt.toIso8601String(), + // "updatedAt": updatedAt.toIso8601String(), + // "__v": v, }; } class ImageModel { - String publicId; - String url; + String? publicId; + String? url; ImageModel({ - required this.publicId, - required this.url, + this.publicId, + this.url, }); factory ImageModel.fromJson(Map json) => ImageModel( @@ -132,14 +136,14 @@ class ImageModel { } class Note { - String message; - DateTime replyDate; - String id; + String? message; + DateTime? replyDate; + String? id; Note({ - required this.message, - required this.replyDate, - required this.id, + this.message, + this.replyDate, + this.id, }); factory Note.fromJson(Map json) => Note( @@ -150,7 +154,7 @@ class Note { Map toJson() => { "message": message, - "replyDate": replyDate.toIso8601String(), + // "replyDate": replyDate.toIso8601String(), "_id": id, }; } diff --git a/lib/provider/pd_rd_provider.dart b/lib/provider/pd_rd_provider.dart index 1abfb66..1854814 100644 --- a/lib/provider/pd_rd_provider.dart +++ b/lib/provider/pd_rd_provider.dart @@ -8,8 +8,10 @@ class PdRdProvider extends ChangeNotifier { bool _isLoading = false; bool get isLoading => _isLoading; - List _pdRdList = []; - List get pdRdList => _pdRdList; + List _pdList = []; + List get pdList => _pdList; + List _rdList = []; + List get rdList => _rdList; final _apiClient = ApiClient(); @@ -18,16 +20,42 @@ class PdRdProvider extends ChangeNotifier { notifyListeners(); } - Future getPdRd() async { + void clearLists() { + _pdList.clear(); + _rdList.clear(); + notifyListeners(); + } + + Future getPd() async { setLoading(true); + clearLists(); // Clear the list before fetching new data try { - Response response = await _apiClient.get(ApiUrls.getPdRdUrl); + Response response = await _apiClient.get(ApiUrls.getPd); if (response.statusCode == 200) { - // Assuming the response data is a list of PdRdResponseModel objects List data = (response.data as List) .map((json) => PdRdResponseModel.fromJson(json)) .toList(); - _pdRdList = data; + _pdList = data; + } else { + print("Failed to load data: ${response.statusCode}"); + } + } catch (e) { + print("Error occurred: $e"); + } finally { + setLoading(false); + } + } + + Future getRd() async { + setLoading(true); + clearLists(); // Clear the list before fetching new data + try { + Response response = await _apiClient.get(ApiUrls.getRd); + if (response.statusCode == 200) { + List data = (response.data as List) + .map((json) => PdRdResponseModel.fromJson(json)) + .toList(); + _rdList = data; } else { print("Failed to load data: ${response.statusCode}"); } diff --git a/lib/provider/task_provider.dart b/lib/provider/task_provider.dart new file mode 100644 index 0000000..aafbc97 --- /dev/null +++ b/lib/provider/task_provider.dart @@ -0,0 +1,111 @@ +import 'package:cheminova/models/pd_rd_response_model.dart'; +import 'package:cheminova/screens/data_submit_successfull.dart'; +import 'package:cheminova/services/api_client.dart'; +import 'package:cheminova/services/api_urls.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +class TaskProvider extends ChangeNotifier { + bool _isLoading = false; + PdRdResponseModel? _selectedSalesCoordinator; + String? _selectedTask; + String? _selectedPriority; + String _selectedDate = DateFormat('dd/MM/yyyy').format(DateTime.now()); + List _salesCoordinators = []; + final TextEditingController _noteController = TextEditingController(); + final _apiClient = ApiClient(); + + bool get isLoading => _isLoading; + PdRdResponseModel? get selectedSalesCoordinator => _selectedSalesCoordinator; + String? get selectedTask => _selectedTask; + String? get selectedPriority => _selectedPriority; + String get selectedDate => _selectedDate; + List get salesCoordinators => _salesCoordinators; + TextEditingController get noteController => _noteController; + + void setLoading(bool loading) { + _isLoading = loading; + notifyListeners(); + } + + void setSelectedSalesCoordinator(PdRdResponseModel coordinator) { + _selectedSalesCoordinator = coordinator; + notifyListeners(); + } + + void setSelectedTask(String? task) { + _selectedTask = task; + notifyListeners(); + } + + void setSelectedPriority(String priority) { + _selectedPriority = priority; + notifyListeners(); + } + + void setDate(String date) { + _selectedDate = date; + notifyListeners(); + } + + void clear(){ + _selectedSalesCoordinator = null; + _selectedTask = null; + _selectedPriority = null; + _selectedDate = DateFormat('dd/MM/yyyy').format(DateTime.now()); + _noteController.clear(); + notifyListeners(); + } + + Future getSalesCoordinators() async { + setLoading(true); + try { + Response response = await _apiClient.get(ApiUrls.getSalesCoordinators); + if (response.statusCode == 200) { + List data = + (response.data['salesCoOrinators'] as List) + .map((json) => PdRdResponseModel.fromJson(json)) + .toList(); + _salesCoordinators = data; + } else { + print("Failed to load data: ${response.statusCode}"); + } + } catch (e) { + print("Error occurred: $e"); + setLoading(false); + } finally { + setLoading(false); + } + } + + Future assignTask(BuildContext context) async { + setLoading(true); + try { + Response response = await _apiClient.post( + ApiUrls.assignTask, + data: { + 'taskAssignedTo': _selectedSalesCoordinator!.id, + 'task': _selectedTask, + 'taskPriority': _selectedPriority, + 'taskDueDate': _selectedDate, + 'note': _noteController.text, + }, + ); + if (response.statusCode == 201) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const DataSubmitSuccessfull(), + ), + ); + } else { + print("Failed to assign task: ${response.statusCode}"); + } + } catch (e) { + print("Error occurred: $e"); + } finally { + setLoading(false); + } + } +} diff --git a/lib/screens/add_products_screen.dart b/lib/screens/add_products_screen.dart index 6877c4f..f94df2e 100644 --- a/lib/screens/add_products_screen.dart +++ b/lib/screens/add_products_screen.dart @@ -72,7 +72,7 @@ class _AddProductsScreenState extends State { ), ], title: Text( - widget.distributor.name, + widget.distributor.name!, style: const TextStyle( fontSize: 20, color: Colors.black, @@ -222,7 +222,7 @@ class _AddProductsScreenState extends State { provider .submitSelectedProducts( "PrincipalDistributor", - widget.distributor.id) + widget.distributor.id!) .then((value) { if (value) { Navigator.push( @@ -275,27 +275,25 @@ class _ProductBlockState extends State { setState(() { if (saleController.text.isNotEmpty && inventoryController.text.isNotEmpty) { - // Check if the input can be parsed as an integer - if (int.tryParse(saleController.text) == null || - int.tryParse(inventoryController.text) == null) { - errorMessage = 'Please enter valid integer value'; - } else { - // Parse the input as integers + // Check if both inputs are valid integers + try { int sale = int.parse(saleController.text); int inventory = int.parse(inventoryController.text); - // Validate if inventory is less than or equal to sales + // Validation: inventory should be less than or equal to sales if (inventory > sale) { errorMessage = 'Inventory should be less than or equal to sales'; } else { errorMessage = null; } + } catch (e) { + // Handle the case where input is not a valid integer + errorMessage = 'Please enter valid integer values for both fields'; } } else { - errorMessage = 'Please fill in both fields'; + errorMessage = null; } }); - return errorMessage == null; } diff --git a/lib/screens/assign_task_dash_board_screen.dart b/lib/screens/assign_task_dash_board_screen.dart index 0ab4584..0556208 100644 --- a/lib/screens/assign_task_dash_board_screen.dart +++ b/lib/screens/assign_task_dash_board_screen.dart @@ -1,4 +1,5 @@ -import 'package:cheminova/screens/select_sales_coordinator_screen.dart'; +import 'package:cheminova/screens/assign_tasks_screen.dart'; +import 'package:cheminova/screens/task_management_screen.dart'; import 'package:cheminova/widgets/common_app_bar.dart'; import 'package:cheminova/widgets/common_background.dart'; import 'package:cheminova/widgets/common_drawer.dart'; @@ -55,39 +56,40 @@ class _AssignTaskDashBoardScreenState extends State { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( - 'Assign Tasks', - style: TextStyle( - fontSize: 24, - color: Colors.white, - fontWeight: FontWeight.bold, - fontFamily: 'Anek', - ), - ), - const SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - SizedBox( - height: 200, - width: MediaQuery.of(context).size.width / 4.2, - child: - _customCard(title: "Total Tasks", subtitle: "100"), - ), - SizedBox( - height: 200, - width: MediaQuery.of(context).size.width / 4.2, - child: _customCard( - title: "Tasks Pending", subtitle: "100"), - ), - SizedBox( - height: 200, - width: MediaQuery.of(context).size.width / 4.2, - child: _customCard( - title: "Reports Submitted", subtitle: "100"), - ), - ], - ), + // const Text( + // 'Assign Tasks', + // style: TextStyle( + // fontSize: 24, + // color: Colors.white, + // fontWeight: FontWeight.bold, + // fontFamily: 'Anek', + // ), + // ), + // const SizedBox(height: 10), + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceEvenly, + // children: [ + // SizedBox( + // height: 200, + // width: MediaQuery.of(context).size.width / 4.2, + // child: + // _customCard(title: "Total Tasks", subtitle: "100"), + // ), + // SizedBox( + // height: 200, + // width: MediaQuery.of(context).size.width / 4.2, + // child: _customCard( + // title: "Tasks Pending", subtitle: "100"), + // ), + // SizedBox( + // height: 200, + // width: MediaQuery.of(context).size.width / 4.2, + // child: _customCard( + // title: "Reports Submitted", subtitle: "100"), + // ), + // ], + // ), + const SizedBox(height: 20), CommonElevatedButton( backgroundColor: const Color(0xff004791), borderRadius: 30, @@ -98,8 +100,7 @@ class _AssignTaskDashBoardScreenState extends State { Navigator.push( context, MaterialPageRoute( - builder: (context) => - const SelectSalesCoordinatorScreen(), + builder: (context) => const AssignTasksScreen(), ), ); }, @@ -111,7 +112,12 @@ class _AssignTaskDashBoardScreenState extends State { width: double.infinity, height: kToolbarHeight - 10, text: 'VIEW TASK STATUS', - onPressed: () {}, + onPressed: () => Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const TaskManagementScreen(), + ), + ), ), const SizedBox(height: 15), CommonElevatedButton( diff --git a/lib/screens/assign_tasks_screen.dart b/lib/screens/assign_tasks_screen.dart index ef1b72f..63adb7d 100644 --- a/lib/screens/assign_tasks_screen.dart +++ b/lib/screens/assign_tasks_screen.dart @@ -1,9 +1,13 @@ +import 'package:cheminova/provider/task_provider.dart'; +import 'package:cheminova/screens/confirm_task_screen.dart'; +import 'package:provider/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:intl/intl.dart'; +import 'package:searchfield/searchfield.dart'; class AssignTasksScreen extends StatefulWidget { const AssignTasksScreen({super.key}); @@ -13,11 +17,45 @@ class AssignTasksScreen extends StatefulWidget { } class _AssignTasksScreenState extends State { - final List _isChecked = List.generate(8, (_) => false); + bool _isSalesCoordinatorValid = true; + bool _isTaskValid = true; + bool _isPriorityValid = true; + bool _isNotesValid = true; - String _dateSelected = DateFormat('dd/MM/yyyy').format(DateTime.now()); + void _validateAndSubmit() { + final taskProvider = context.read(); + setState(() { + // Validate Sales Coordinator + _isSalesCoordinatorValid = taskProvider.selectedSalesCoordinator != null; + + // Validate Task + _isTaskValid = taskProvider.selectedTask != null && + taskProvider.selectedTask!.isNotEmpty; + + // Validate Priority + _isPriorityValid = taskProvider.selectedPriority != null && + taskProvider.selectedPriority!.isNotEmpty; + + // Validate Notes + if (taskProvider.selectedTask == 'Collect KYC' && + taskProvider.noteController.text.isEmpty) { + _isNotesValid = false; + } + }); + + // If all fields are valid, proceed to the next screen + if (_isSalesCoordinatorValid && _isTaskValid && _isPriorityValid) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const ConfirmTaskScreen(), + ), + ); + } + } Future _selectDate(BuildContext context) async { + final provider = context.read(); final dateSelected = await showDatePicker( context: context, initialDate: DateTime.now(), @@ -25,14 +63,28 @@ class _AssignTasksScreenState extends State { lastDate: DateTime(2025), ); if (dateSelected != null) { - setState(() { - _dateSelected = DateFormat('dd/MM/yyyy').format(dateSelected); - }); + provider.setDate(DateFormat('dd/MM/yyyy').format(dateSelected)); } } + void _updateTaskProvider() { + final provider = context.read(); + provider.clear(); + provider.getSalesCoordinators(); + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + _updateTaskProvider(); + }); + } + @override Widget build(BuildContext context) { + final taskProvider = context.watch(); + return Scaffold( extendBodyBehindAppBar: true, appBar: CommonAppBar( @@ -56,250 +108,338 @@ class _AssignTasksScreenState extends State { ), drawer: const CommonDrawer(), body: CommonBackground( - child: SafeArea( - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.only(top: 20), - child: Container( - padding: - const EdgeInsets.all(20.0).copyWith(top: 15, bottom: 30), - margin: const EdgeInsets.symmetric(horizontal: 30.0) - .copyWith(bottom: 50), - decoration: BoxDecoration( - border: Border.all(color: Colors.white), - color: const Color(0xffB4D1E5).withOpacity(0.5), - borderRadius: BorderRadius.circular(26.0), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Assign Tasks', - style: TextStyle( - fontSize: 24, - color: Colors.white, - fontWeight: FontWeight.bold, - fontFamily: 'Anek', - ), + child: Stack( + children: [ + SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.only(top: 20), + child: Container( + padding: const EdgeInsets.all(20.0) + .copyWith(top: 15, bottom: 30), + margin: const EdgeInsets.symmetric(horizontal: 30.0) + .copyWith(bottom: 50), + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + color: const Color(0xffB4D1E5).withOpacity(0.5), + borderRadius: BorderRadius.circular(26.0), ), - const SizedBox(height: 20), - Container( - width: double.infinity, - padding: const EdgeInsets.all(12.0), - margin: const EdgeInsets.only(bottom: 20), - decoration: BoxDecoration( - border: Border.all(color: Colors.white), - color: const Color(0xffB4D1E5).withOpacity(0.6), - borderRadius: BorderRadius.circular(16.0), - ), - child: const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Sales Coordinator: Name", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - fontFamily: 'Anek', + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Assign Tasks', + style: TextStyle( + fontSize: 24, + color: Colors.white, + fontWeight: FontWeight.bold, + fontFamily: 'Anek', + ), + ), + const SizedBox(height: 20), + SearchField( + suggestionsDecoration: SuggestionDecoration( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(8.0), + bottomRight: Radius.circular(8), + ), + border: Border.all( + color: Colors.grey.withOpacity(0.5), ), ), - Text( - "ID: 121", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - fontFamily: 'Anek', - ), + suggestionItemDecoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + shape: BoxShape.rectangle, + border: Border.all( + color: Colors.transparent, + style: BorderStyle.solid, + width: 1.0), ), - ], - ), - ), - Container( - width: double.infinity, - padding: const EdgeInsets.all(12.0), - margin: const EdgeInsets.only(bottom: 20), - decoration: BoxDecoration( - border: Border.all(color: Colors.white), - color: const Color(0xffB4D1E5).withOpacity(0.6), - borderRadius: BorderRadius.circular(16.0), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "Tasks List:", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - fontFamily: 'Anek', + searchInputDecoration: InputDecoration( + filled: true, + fillColor: Colors.grey.withOpacity(0.2), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: Colors.white, + width: 2.0, + ), + borderRadius: BorderRadius.circular(8.0), ), - ), - SizedBox( - height: 35, - child: CheckboxListTile( - value: _isChecked[0], - onChanged: (value) { - setState(() { - _isChecked[0] = value!; - }); - }, - title: const Text( - "Visit Retailers", + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(16.0), + ), + borderSide: BorderSide( + color: Colors.white, + width: 2.0, ), ), + errorText: !_isSalesCoordinatorValid + ? 'Please select a Sales Coordinator' + : null, ), - SizedBox( - height: 45, - child: CheckboxListTile( - value: _isChecked[1], - onChanged: (value) { - setState(() { - _isChecked[1] = value!; - }); - }, - title: const Text( - "Update Sales Data", - ), - ), + hint: 'Select Sales Coordinator', + onSuggestionTap: (selectedItem) { + if (selectedItem.item != null) { + taskProvider.setSelectedSalesCoordinator( + selectedItem.item!); + FocusScope.of(context).unfocus(); + } + }, + onTapOutside: (event) => + FocusScope.of(context).unfocus(), + marginColor: Colors.grey.shade300, + suggestions: taskProvider.salesCoordinators + .map( + (e) => SearchFieldListItem( + e.name!, + item: e, + child: Text(e.name!), + ), + ) + .toList(), + ), + const SizedBox(height: 20), + Container( + width: double.infinity, + padding: const EdgeInsets.all(12.0), + margin: const EdgeInsets.only(bottom: 20), + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + color: const Color(0xffB4D1E5).withOpacity(0.6), + borderRadius: BorderRadius.circular(16.0), ), - SizedBox( - height: 45, - child: CheckboxListTile( - value: _isChecked[2], - onChanged: (value) { - setState(() { - _isChecked[2] = value!; - }); - }, - title: const Text( - "Update Liqudation Data", - ), - ), - ), - CheckboxListTile( - value: _isChecked[3], - onChanged: (value) { - setState(() { - _isChecked[3] = value!; - }); - }, - title: const Text( - "Collect KYC", - ), - ), - ], - ), - ), - Container( - width: double.infinity, - padding: const EdgeInsets.all(12.0), - margin: const EdgeInsets.only(bottom: 20), - decoration: BoxDecoration( - border: Border.all(color: Colors.white), - color: const Color(0xffB4D1E5).withOpacity(0.6), - borderRadius: BorderRadius.circular(16.0), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "Priority:", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - fontFamily: 'Anek', - ), - ), - Row( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Checkbox( - value: _isChecked[4], - onChanged: (value) { - setState(() { - _isChecked[4] = value!; - }); - }, - ), const Text( - "Low", + "Tasks List:", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + fontFamily: 'Anek', + ), ), - Checkbox( - value: _isChecked[5], + SizedBox( + height: 35, + child: RadioListTile( + contentPadding: EdgeInsets.zero, + value: 'Visit Retailers', + groupValue: taskProvider.selectedTask, + onChanged: (value) { + taskProvider.setSelectedTask(value); + }, + title: const Text( + "Visit Retailers", + ), + ), + ), + SizedBox( + height: 45, + child: RadioListTile( + contentPadding: EdgeInsets.zero, + value: 'Update Sales Data', + groupValue: taskProvider.selectedTask, + onChanged: (value) { + taskProvider.setSelectedTask(value); + }, + title: const Text( + "Update Sales Data", + ), + ), + ), + SizedBox( + height: 45, + child: RadioListTile( + contentPadding: EdgeInsets.zero, + value: 'Update Liqudation Data', + groupValue: taskProvider.selectedTask, + onChanged: (value) { + taskProvider.setSelectedTask(value); + }, + title: const Text( + "Update Liqudation Data", + ), + ), + ), + RadioListTile( + contentPadding: EdgeInsets.zero, + value: 'Collect KYC', + groupValue: taskProvider.selectedTask, onChanged: (value) { - setState(() { - _isChecked[5] = value!; - }); + taskProvider.setSelectedTask(value); }, + title: const Text( + "Collect KYC", + ), ), + if (!_isTaskValid && + (taskProvider.selectedTask?.isEmpty ?? true)) + const Padding( + padding: + EdgeInsets.symmetric(horizontal: 16.0), + child: Text( + 'Please select a task', + style: TextStyle( + color: Colors.red, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ), + if (taskProvider.selectedTask == 'Collect KYC') ...{ + Container( + height: 150, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16.0), + ), + child: TextFormField( + controller: taskProvider.noteController, + expands: true, + maxLines: null, + minLines: null, + decoration: InputDecoration( + contentPadding: const EdgeInsets.symmetric( + vertical: 14.0, + horizontal: 16.0, + ), + border: InputBorder.none, + labelText: 'Note', + hintText: 'Enter your note', + errorText: !_isNotesValid + ? 'Please enter a note' + : null, + ), + ), + ), + const SizedBox( + height: 20, + ) + }, + Container( + width: double.infinity, + padding: const EdgeInsets.all(12.0), + margin: const EdgeInsets.only(bottom: 20), + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + color: const Color(0xffB4D1E5).withOpacity(0.6), + borderRadius: BorderRadius.circular(16.0), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ const Text( - "Medium", + "Priority:", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + fontFamily: 'Anek', + ), ), - Checkbox( - value: _isChecked[6], - onChanged: (value) { - setState(() { - _isChecked[6] = value!; - }); - }, + Row( + children: [ + Radio( + value: "Low", + groupValue: taskProvider.selectedPriority, + onChanged: (value) { + taskProvider.setSelectedPriority(value!); + }, + ), + const Text("Low"), + Radio( + value: "Medium", + groupValue: taskProvider.selectedPriority, + onChanged: (value) { + taskProvider.setSelectedPriority(value!); + }, + ), + const Text("Medium"), + Radio( + value: "High", + groupValue: taskProvider.selectedPriority, + onChanged: (value) { + taskProvider.setSelectedPriority(value!); + }, + ), + const Text("High"), + ], ), + if (!_isPriorityValid && + (taskProvider.selectedPriority?.isEmpty ?? + true)) + const Padding( + padding: + EdgeInsets.symmetric(horizontal: 16.0), + child: Text( + 'Please select a priority', + style: TextStyle(color: Colors.red), + ), + ), + ], + ), + ), + Container( + width: double.infinity, + padding: const EdgeInsets.all(12.0), + margin: const EdgeInsets.only(bottom: 20), + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + color: const Color(0xffB4D1E5).withOpacity(0.6), + borderRadius: BorderRadius.circular(16.0), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ const Text( - "High", + "Due Date:", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + fontFamily: 'Anek', + ), + ), + Row( + children: [ + Text( + taskProvider.selectedDate, + ), + IconButton( + onPressed: () { + _selectDate(context); + }, + icon: const Icon(Icons.calendar_month), + ), + ], ), ], ), - ], - ), + ), + CommonElevatedButton( + backgroundColor: const Color(0xff004791), + borderRadius: 30, + width: double.infinity, + height: kToolbarHeight - 10, + text: 'CONFIRM', + onPressed: _validateAndSubmit, + ), + ], ), - Container( - width: double.infinity, - padding: const EdgeInsets.all(12.0), - margin: const EdgeInsets.only(bottom: 20), - decoration: BoxDecoration( - border: Border.all(color: Colors.white), - color: const Color(0xffB4D1E5).withOpacity(0.6), - borderRadius: BorderRadius.circular(16.0), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "Due Date:", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - fontFamily: 'Anek', - ), - ), - Row( - children: [ - Text( - _dateSelected, - ), - IconButton( - onPressed: () { - _selectDate(context); - }, - icon: const Icon(Icons.calendar_month), - ), - ], - ), - ], - ), - ), - CommonElevatedButton( - backgroundColor: const Color(0xff004791), - borderRadius: 30, - width: double.infinity, - height: kToolbarHeight - 10, - text: 'CONFIRM', - onPressed: () {}, - ), - ], + ), ), ), ), - ), + if (taskProvider.isLoading) + Container( + color: Colors.black.withOpacity(0.1), + child: const Center( + child: CircularProgressIndicator(), + ), + ), + ], ), ), ); diff --git a/lib/screens/confirm_task_screen.dart b/lib/screens/confirm_task_screen.dart new file mode 100644 index 0000000..9c3b58a --- /dev/null +++ b/lib/screens/confirm_task_screen.dart @@ -0,0 +1,204 @@ +import 'package:cheminova/provider/task_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:provider/provider.dart'; + +class ConfirmTaskScreen extends StatefulWidget { + const ConfirmTaskScreen({super.key}); + + @override + State createState() => _ConfirmTaskScreenState(); +} + +class _ConfirmTaskScreenState extends State { + @override + Widget build(BuildContext context) { + final taskProvider = context.watch(); + + return Scaffold( + extendBodyBehindAppBar: true, + appBar: CommonAppBar( + backgroundColor: Colors.transparent, + elevation: 0, + actions: [ + IconButton( + onPressed: () { + Navigator.pop(context); + }, + icon: Image.asset('assets/Back_attendance.png'), + padding: const EdgeInsets.only(right: 20), + ), + ], + title: const Center( + child: Text( + 'Confirm Task', + style: TextStyle(color: Colors.black87, fontSize: 20), + ), + ), + ), + drawer: const CommonDrawer(), + body: CommonBackground( + child: SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.only(top: 20), + child: Container( + padding: + const EdgeInsets.all(20.0).copyWith(top: 15, bottom: 30), + margin: const EdgeInsets.symmetric(horizontal: 30.0) + .copyWith(bottom: 50), + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + color: const Color(0xffB4D1E5).withOpacity(0.5), + borderRadius: BorderRadius.circular(26.0), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Confirm Task', + style: TextStyle( + fontSize: 24, + color: Colors.white, + fontWeight: FontWeight.bold, + fontFamily: 'Anek', + ), + ), + const SizedBox(height: 20), + _customContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Sales Coordinator:', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + fontFamily: 'Anek', + ), + ), + Text( + taskProvider.selectedSalesCoordinator!.name!, + style: const TextStyle( + fontSize: 16, + fontFamily: 'Anek', + ), + ), + Text( + 'ID: ${taskProvider.selectedSalesCoordinator!.uniqueId!}', + style: const TextStyle( + fontSize: 16, + fontFamily: 'Anek', + ), + ), + ], + ), + ), + const SizedBox(height: 20), + const Text( + 'Tasks:', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + fontFamily: 'Anek', + ), + ), + const SizedBox(height: 10), + _customContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Task: ${taskProvider.selectedTask!}', + style: const TextStyle( + fontFamily: 'Anek', + ), + ), + const SizedBox(height: 10), + Text( + 'Priority: ${taskProvider.selectedPriority!}', + style: const TextStyle( + fontFamily: 'Anek', + ), + ), + const SizedBox(height: 10), + Text( + 'Deadline: ${taskProvider.selectedDate}', + style: const TextStyle( + fontFamily: 'Anek', + ), + ), + ], + ), + ), + const SizedBox(height: 20), + if (taskProvider.selectedTask == 'Collect KYC') + _customContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Note:', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + fontFamily: 'Anek', + ), + ), + Text( + taskProvider.noteController.text, + style: const TextStyle( + fontSize: 16, + fontFamily: 'Anek', + ), + ), + ], + ), + ), + const SizedBox(height: 20), + CommonElevatedButton( + isLoading: taskProvider.isLoading, + backgroundColor: const Color(0xff004791), + borderRadius: 30, + width: double.infinity, + height: kToolbarHeight - 10, + text: 'CONFIRM', + onPressed: () => taskProvider.assignTask(context), + ), + const SizedBox(height: 20), + CommonElevatedButton( + backgroundColor: const Color(0xff00784C), + borderRadius: 30, + width: double.infinity, + height: kToolbarHeight - 10, + text: 'EDIT', + onPressed: () => Navigator.pop(context), + ), + ], + ), + ), + ), + ), + ), + ), + ); + } + + Widget _customContainer({required Widget child}) { + return Container( + width: double.infinity, + padding: const EdgeInsets.all(12.0), + // margin: const EdgeInsets.all(8), + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + color: const Color(0xffB4D1E5).withOpacity(0.6), + borderRadius: BorderRadius.circular(16.0), + ), + child: child, + ); + } +} diff --git a/lib/screens/data_submit_successfull.dart b/lib/screens/data_submit_successfull.dart index 4e7dc44..88861b2 100644 --- a/lib/screens/data_submit_successfull.dart +++ b/lib/screens/data_submit_successfull.dart @@ -14,25 +14,32 @@ class DataSubmitSuccessfullState extends State { void initState() { super.initState(); Future.delayed(const Duration(seconds: 2), () { - Navigator.pushReplacement( - context, MaterialPageRoute(builder: (context) => const HomePage())); + Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute(builder: (context) => const HomePage()), + (Route route) => false, // Remove all routes + ); }); } + @override Widget build(BuildContext context) { - return Scaffold( + return Scaffold( body: CommonBackground( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Text('Data Submitted\nsuccessfully', - style: TextStyle( - fontSize: 36, - color: Colors.white, - fontWeight: FontWeight.w400, - fontFamily: 'Anek')), - const SizedBox(height: 20), // Add some space between the text and the image - Image.asset('assets/check_circle.png', )])))); + const Text('Data Submitted\nsuccessfully', + style: TextStyle( + fontSize: 36, + color: Colors.white, + fontWeight: FontWeight.w400, + fontFamily: 'Anek')), + const SizedBox( + height: 20), // Add some space between the text and the image + Image.asset( + 'assets/check_circle.png', + ) + ])))); } } diff --git a/lib/screens/select_sales_coordinator_screen.dart b/lib/screens/select_sales_coordinator_screen.dart index 3ea5f51..3d4e0e4 100644 --- a/lib/screens/select_sales_coordinator_screen.dart +++ b/lib/screens/select_sales_coordinator_screen.dart @@ -1,4 +1,3 @@ -import 'package:cheminova/screens/assign_tasks_screen.dart'; import 'package:cheminova/widgets/common_app_bar.dart'; import 'package:cheminova/widgets/common_background.dart'; import 'package:cheminova/widgets/common_drawer.dart'; @@ -79,10 +78,18 @@ class _SelectSalesCoordinatorScreenState child: ListView.builder( itemCount: salesCoordinators.length, itemBuilder: (context, index) { - return _customCard( - name: salesCoordinators[index].name, - id: salesCoordinators[index].id, - tasks: salesCoordinators[index].tasks, + return GestureDetector( + onTap: () { + // taskProvider.setSelectedSalesCoordinator( + // salesCoordinators[index], + // ); + // Navigator.pop(context); + }, + child: _customCard( + name: salesCoordinators[index].name, + id: salesCoordinators[index].id, + tasks: salesCoordinators[index].tasks, + ), ); }, ), @@ -98,55 +105,43 @@ class _SelectSalesCoordinatorScreenState Widget _customCard( {required String name, required String id, required int tasks}) { - return GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) { - return const AssignTasksScreen(); - }, + return Container( + width: double.infinity, + padding: const EdgeInsets.all(12.0), + margin: const EdgeInsets.all(8), + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + color: const Color(0xffB4D1E5).withOpacity(0.6), + borderRadius: BorderRadius.circular(16.0), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: const TextStyle( + fontFamily: 'Anek', + fontSize: 16, + ), ), - ); - }, - child: Container( - width: double.infinity, - padding: const EdgeInsets.all(12.0), - margin: const EdgeInsets.all(8), - decoration: BoxDecoration( - border: Border.all(color: Colors.white), - color: const Color(0xffB4D1E5).withOpacity(0.6), - borderRadius: BorderRadius.circular(16.0), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: const TextStyle( - fontFamily: 'Anek', - fontSize: 16, - ), + const SizedBox(height: 5), + Text( + "ID: $id", + style: const TextStyle( + fontFamily: 'Anek', + fontSize: 16, ), - const SizedBox(height: 5), - Text( - "ID: $id", - style: const TextStyle( - fontFamily: 'Anek', - fontSize: 16, - ), + ), + const SizedBox(height: 5), + Text( + "Tasks: $tasks", + style: const TextStyle( + fontFamily: 'Anek', + fontSize: 16, ), - const SizedBox(height: 5), - Text( - "Tasks: $tasks", - style: const TextStyle( - fontFamily: 'Anek', - fontSize: 16, - ), - ), - ], - ), + ), + ], ), ); } diff --git a/lib/screens/task_management_screen.dart b/lib/screens/task_management_screen.dart new file mode 100644 index 0000000..0904bd1 --- /dev/null +++ b/lib/screens/task_management_screen.dart @@ -0,0 +1,254 @@ +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_text_form_field.dart'; +import 'package:flutter/material.dart'; + +class TaskManagementScreen extends StatefulWidget { + const TaskManagementScreen({super.key}); + + @override + State createState() => _TaskManagementScreenState(); +} + +class _TaskManagementScreenState extends State { + final TextEditingController _searchController = TextEditingController(); + final List _taskList = [ + 'Task 1', + 'Task 2', + 'Task 3', + 'Task 4', + 'Task 5', + 'Task 6', + 'Task 7', + 'Task 8', + 'Task 9', + 'Task 10', + ]; + + final List _filters = [ + 'All', + 'Pending', + 'Completed', + ]; + + List _filteredTaskList = []; + + void _filterTaskList(String query) { + setState(() { + _filteredTaskList = _taskList + .where((task) => task.toLowerCase().contains(query.toLowerCase())) + .toList(); + }); + } + + @override + void initState() { + super.initState(); + _filteredTaskList = _taskList; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: CommonAppBar( + backgroundColor: Colors.transparent, + elevation: 0, + actions: [ + IconButton( + onPressed: () { + Navigator.pop(context); + }, + icon: Image.asset('assets/Back_attendance.png'), + padding: const EdgeInsets.only(right: 20), + ), + ], + title: const Center( + child: Text( + 'Task Management', + style: TextStyle(color: Colors.black87, fontSize: 20), + ), + ), + ), + drawer: const CommonDrawer(), + body: CommonBackground( + child: SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.only(top: 20), + child: Container( + padding: + const EdgeInsets.all(20.0).copyWith(top: 15, bottom: 30), + margin: const EdgeInsets.symmetric(horizontal: 30.0) + .copyWith(bottom: 50), + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + color: const Color(0xffB4D1E5).withOpacity(0.5), + borderRadius: BorderRadius.circular(26.0), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CommonTextFormField( + controller: _searchController, + onChanged: (value) => _filterTaskList(value), + title: 'Filter by Sales Coordinator:', + ), + const SizedBox(height: 20), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _filterChip( + title: 'All', + icon: const Icon(Icons.all_inclusive), + ), + const SizedBox(width: 5), + _filterChip( + title: 'Pending', + icon: const Icon(Icons.pending), + ), + const SizedBox(width: 5), + _filterChip( + title: 'Completed', + icon: const Icon(Icons.done), + ), + ], + ), + ), + const Text( + 'Tasks:', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + fontFamily: 'Anek', + ), + ), + const SizedBox(height: 10), + SizedBox( + height: MediaQuery.of(context).size.height * 0.55, + child: ListView.builder( + itemCount: _filteredTaskList.length, + itemBuilder: (context, index) => _taskView( + title: _filteredTaskList[index], + ), + ), + ), + // CommonElevatedButton( + // backgroundColor: const Color(0xff004791), + // borderRadius: 30, + // width: double.infinity, + // height: kToolbarHeight - 10, + // text: 'EDIT', + // onPressed: () => Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => const AssignTasksScreen(), + // ), + // ), + // ), + // const SizedBox(height: 20), + // CommonElevatedButton( + // backgroundColor: const Color(0xff00784C), + // borderRadius: 30, + // width: double.infinity, + // height: kToolbarHeight - 10, + // text: 'REASSIGN', + // onPressed: () => Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => + // const SelectSalesCoordinatorScreen(), + // ), + // ), + // ), + // const SizedBox(height: 20), + // CommonElevatedButton( + // backgroundColor: const Color(0xff00784C), + // borderRadius: 30, + // width: double.infinity, + // height: kToolbarHeight - 10, + // text: 'MARK AS COMPLETED', + // onPressed: () {}, + // ), + ], + ), + ), + ), + ), + ), + ), + ); + } + + Widget _customContainer({required Widget child}) { + return Container( + width: double.infinity, + padding: const EdgeInsets.all(12.0), + // margin: const EdgeInsets.all(8), + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + color: const Color(0xffB4D1E5).withOpacity(0.6), + borderRadius: BorderRadius.circular(16.0), + ), + child: child, + ); + } + + Widget _taskView({required String title}) { + return Column( + children: [ + _customContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Sales Coordinator: 1', + style: TextStyle( + fontFamily: 'Anek', + ), + ), + const SizedBox(height: 10), + Text( + title, + style: const TextStyle( + fontFamily: 'Anek', + ), + ), + const SizedBox(height: 10), + const Text( + 'Status: Pending', + style: TextStyle( + fontFamily: 'Anek', + ), + ), + const SizedBox(height: 10), + const Text( + 'Deadline: 12/12/2024', + style: TextStyle( + fontFamily: 'Anek', + ), + ), + ], + ), + ), + const SizedBox(height: 10), + ], + ); + } + + Widget _filterChip({required String title, required Widget icon}) { + return Chip( + avatar: icon, + label: Text( + title, + style: const TextStyle( + fontFamily: 'Anek', + ), + ), + ); + } +} diff --git a/lib/screens/update_inventory_screen.dart b/lib/screens/update_inventory_screen.dart index 386c53a..81edc7b 100644 --- a/lib/screens/update_inventory_screen.dart +++ b/lib/screens/update_inventory_screen.dart @@ -23,10 +23,10 @@ class _UpdateInventoryScreenState extends State { void initState() { super.initState(); // Fetch the PdRd data when the screen is initialized - WidgetsBinding.instance.addPostFrameCallback((_) { - final provider = Provider.of(context, listen: false); - provider.getPdRd(); - }); + // WidgetsBinding.instance.addPostFrameCallback((_) { + // final provider = Provider.of(context, listen: false); + // provider.getPdRd(); + // }); } @override @@ -65,11 +65,14 @@ class _UpdateInventoryScreenState extends State { text: 'SUBMIT', backgroundColor: const Color(0xff004791), onPressed: () { - if(selectedDistributor == null || selectedDistributorType == null){ + if (selectedDistributor == null || + selectedDistributorType == null) { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('Please select distributor type and distributor')), + const SnackBar( + content: Text( + 'Please select distributor type and distributor')), ); - }else{ + } else { Navigator.push( context, MaterialPageRoute( @@ -85,22 +88,6 @@ class _UpdateInventoryScreenState extends State { ), body: Consumer( builder: (context, provider, child) { - if (provider.isLoading) { - return const Center(child: CircularProgressIndicator()); - } - - if (provider.pdRdList.isEmpty) { - return const Center(child: Text('No distributors available.')); - } - - List principalDistributors = provider.pdRdList - .where((item) => item.userType == 'SalesCoOrdinator') - .toList(); - - List retailerDistributors = provider.pdRdList - .where((item) => item.userType != 'SalesCoOrdinator') - .toList(); - return Stack( children: [ Column( @@ -127,6 +114,9 @@ class _UpdateInventoryScreenState extends State { onChanged: (value) { setState(() { selectedDistributorType = value; + selectedDistributorType == 'Principal Distributor' + ? provider.getPd() + : provider.getRd(); selectedDistributor = null; // Reset distributor selection when type changes }); @@ -148,12 +138,12 @@ class _UpdateInventoryScreenState extends State { value: selectedDistributor, items: (selectedDistributorType == 'Principal Distributor' - ? principalDistributors - : retailerDistributors) + ? provider.pdList + : provider.rdList) .map((PdRdResponseModel distributor) { return DropdownMenuItem( value: distributor, - child: Text(distributor.name), + child: Text(distributor.name!), ); }).toList(), onChanged: (value) { @@ -170,6 +160,13 @@ class _UpdateInventoryScreenState extends State { ), ], ), + if (provider.isLoading) + Container( + color: Colors.black.withOpacity(0.1), + child: const Center( + child: CircularProgressIndicator(), + ), + ), ], ); }, diff --git a/lib/services/api_urls.dart b/lib/services/api_urls.dart index d216f5e..8a50745 100644 --- a/lib/services/api_urls.dart +++ b/lib/services/api_urls.dart @@ -12,7 +12,9 @@ class ApiUrls { static const String notificationUrl = '$baseUrl/get-notification-tm'; static const String fcmUrl = '${baseUrl}kyc/save-fcm-tm'; static const String getProducts = '${baseUrl}product/getAll/user/'; - static const String getPdRdUrl = - 'inventory/distributors-TM/RetailDistributor'; + static const String getPd = 'inventory/distributors-TM/RetailDistributor'; + static const String getRd = 'inventory/distributors-TM/PrincipalDistributor'; static const String submitProducts = 'inventory/add-TM'; + static const String getSalesCoordinators = 'salescoordinator/getAll-TM'; + static const String assignTask = 'task/assign-task'; } diff --git a/lib/widgets/common_text_form_field.dart b/lib/widgets/common_text_form_field.dart index f21e149..284ef30 100644 --- a/lib/widgets/common_text_form_field.dart +++ b/lib/widgets/common_text_form_field.dart @@ -13,6 +13,7 @@ class CommonTextFormField extends StatelessWidget { final List? inputFormatters; final int? maxLength; final bool obscureText; + final void Function(String)? onChanged; const CommonTextFormField({ super.key, @@ -26,6 +27,7 @@ class CommonTextFormField extends StatelessWidget { this.keyboardType, this.inputFormatters, this.maxLength, + this.onChanged, this.obscureText = false, }); @@ -45,6 +47,7 @@ class CommonTextFormField extends StatelessWidget { readOnly: readOnly ?? false, maxLines: maxLines, maxLength: maxLength, + onChanged: onChanged, onTapOutside: (event) => FocusScope.of(context).unfocus(), validator: validator, keyboardType: keyboardType, diff --git a/pubspec.lock b/pubspec.lock index a6d5ad8..8fa01e5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1040,6 +1040,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + searchfield: + dependency: "direct main" + description: + name: searchfield + sha256: "913bb61f42d47d82c1adb67047fff3b26dcf6a199f71ecdc9af27c506dda4b48" + url: "https://pub.dev" + source: hosted + version: "1.0.9" shelf: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8a50ba8..22d64cc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -50,6 +50,7 @@ dependencies: flutter_local_notifications: ^17.2.1+2 firebase_crashlytics: ^4.0.4 firebase_analytics: ^11.2.1 + searchfield: ^1.0.9 dev_dependencies: flutter_test: