diff --git a/lib/models/task_model.dart b/lib/models/task_model.dart new file mode 100644 index 0000000..e55d3f8 --- /dev/null +++ b/lib/models/task_model.dart @@ -0,0 +1,78 @@ +class TaskModel { + final String id; + final String taskId; + final String task; + final String? note; + final String taskStatus; + final String? taskPriority; + final DateTime taskDueDate; + final TaskAssignedTo taskAssignedTo; + final String? taskAssignedBy; + final String? addedFor; + final String? addedForId; + final String? tradename; + final DateTime? createdAt; + final DateTime? updatedAt; + final int? version; + + TaskModel({ + required this.id, + required this.taskId, + required this.task, + this.note, + required this.taskStatus, + this.taskPriority, + required this.taskDueDate, + required this.taskAssignedTo, + this.taskAssignedBy, + this.addedFor, + this.addedForId, + this.tradename, + this.createdAt, + this.updatedAt, + this.version, + }); + + factory TaskModel.fromJson(Map json) { + return TaskModel( + id: json['_id'], + taskId: json['taskId'], + task: json['task'], + note: json['note'], + taskStatus: json['taskStatus'], + taskPriority: json['taskPriority'], + taskDueDate: DateTime.parse(json['taskDueDate']), + taskAssignedTo: TaskAssignedTo.fromJson(json['taskAssignedTo']), + taskAssignedBy: json['taskAssignedBy'], + addedFor: json['addedFor'], + addedForId: json['addedForId'], + tradename: json['tradename'], + createdAt: DateTime.parse(json['createdAt']), + updatedAt: DateTime.parse(json['updatedAt']), + version: json['__v'], + ); + } +} + +class TaskAssignedTo { + final String id; + final String name; + final String mobileNumber; + final String email; + + TaskAssignedTo({ + required this.id, + required this.name, + required this.mobileNumber, + required this.email, + }); + + factory TaskAssignedTo.fromJson(Map json) { + return TaskAssignedTo( + id: json['_id'], + name: json['name'], + mobileNumber: json['mobileNumber'], + email: json['email'], + ); + } +} diff --git a/lib/provider/task_provider.dart b/lib/provider/task_provider.dart index b682f87..15d2b67 100644 --- a/lib/provider/task_provider.dart +++ b/lib/provider/task_provider.dart @@ -1,4 +1,5 @@ import 'package:cheminova/models/pd_rd_response_model.dart'; +import 'package:cheminova/models/task_model.dart'; import 'package:cheminova/screens/data_submit_successfull.dart'; import 'package:cheminova/services/api_client.dart'; import 'package:cheminova/services/api_urls.dart'; @@ -15,6 +16,7 @@ class TaskProvider extends ChangeNotifier { List _salesCoordinators = []; List _pdList = []; List _rdList = []; + List _taskModelList = []; PdRdResponseModel? _selectedDistributor; final TextEditingController _noteController = TextEditingController(); final _apiClient = ApiClient(); @@ -28,6 +30,7 @@ class TaskProvider extends ChangeNotifier { TextEditingController get noteController => _noteController; List get pdList => _pdList; List get rdList => _rdList; + List get taskModelList => _taskModelList; PdRdResponseModel? get selectedDistributor => _selectedDistributor; void setLoading(bool loading) { @@ -61,6 +64,7 @@ class TaskProvider extends ChangeNotifier { _selectedPriority = null; _selectedDate = DateFormat('dd/MM/yyyy').format(DateTime.now()); _noteController.clear(); + _taskModelList.clear(); notifyListeners(); } @@ -187,4 +191,59 @@ class TaskProvider extends ChangeNotifier { setLoading(false); } } + + Future getNewTasks() async { + setLoading(true); + clearLists(); + try { + Response response = await _apiClient.get("${ApiUrls.getAllTasks}New"); + if (response.statusCode == 200) { + List data = (response.data['tasks'] as List) + .map((json) => TaskModel.fromJson(json)) + .toList(); + _taskModelList = data; + } + } catch (e) { + print("Error occurred: $e"); + } finally { + setLoading(false); + } + } + + Future getPendingTasks() async { + setLoading(true); + clearLists(); + try { + Response response = await _apiClient.get("${ApiUrls.getAllTasks}Pending"); + if (response.statusCode == 200) { + List data = (response.data['tasks'] as List) + .map((json) => TaskModel.fromJson(json)) + .toList(); + _taskModelList = data; + } + } catch (e) { + print("Error occurred: $e"); + } finally { + setLoading(false); + } + } + + Future getCompletedTasks() async { + setLoading(true); + clearLists(); + try { + Response response = + await _apiClient.get("${ApiUrls.getAllTasks}Completed"); + if (response.statusCode == 200) { + List data = (response.data['tasks'] as List) + .map((json) => TaskModel.fromJson(json)) + .toList(); + _taskModelList = data; + } + } catch (e) { + print("Error occurred: $e"); + } finally { + setLoading(false); + } + } } diff --git a/lib/screens/task_management_screen.dart b/lib/screens/task_management_screen.dart index 0904bd1..c475eb2 100644 --- a/lib/screens/task_management_screen.dart +++ b/lib/screens/task_management_screen.dart @@ -1,8 +1,12 @@ +import 'package:cheminova/models/task_model.dart'; +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_text_form_field.dart'; import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; class TaskManagementScreen extends StatefulWidget { const TaskManagementScreen({super.key}); @@ -13,43 +17,45 @@ class TaskManagementScreen extends StatefulWidget { 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 = []; + List _filteredTaskList = []; + String? _selectedChip; // State to track the selected chip void _filterTaskList(String query) { + if (query.isEmpty || query == '' || query == ' ') { + setState(() { + _filteredTaskList = context.read().taskModelList; + }); + return; + } setState(() { - _filteredTaskList = _taskList - .where((task) => task.toLowerCase().contains(query.toLowerCase())) + _filteredTaskList = _filteredTaskList + .where((task) => task.taskAssignedTo.name + .toLowerCase() + .contains(query.toLowerCase())) .toList(); }); } + Future _updateTaskProvider() async { + final provider = context.read(); + provider.clear(); + await provider.getNewTasks(); + _filteredTaskList.clear(); + _filteredTaskList = provider.taskModelList; + } + @override void initState() { super.initState(); - _filteredTaskList = _taskList; + WidgetsBinding.instance.addPostFrameCallback((_) { + _updateTaskProvider(); + }); } @override Widget build(BuildContext context) { + final taskProvider = context.watch(); + return Scaffold( extendBodyBehindAppBar: true, appBar: CommonAppBar( @@ -73,112 +79,110 @@ class _TaskManagementScreenState 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: [ - CommonTextFormField( - controller: _searchController, - onChanged: (value) => _filterTaskList(value), - title: 'Filter by Sales Coordinator:', + 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), - 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], + 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: 'New', + icon: const Icon(Icons.new_releases), + onSelected: () async { + setState(() { + _selectedChip = 'New'; + }); + await taskProvider.getNewTasks(); + _filteredTaskList.clear(); + _filteredTaskList = + taskProvider.taskModelList; + }, + isSelected: _selectedChip == 'New', + ), + const SizedBox(width: 5), + _filterChip( + title: 'Pending', + icon: const Icon(Icons.pending), + onSelected: () async { + setState(() { + _selectedChip = 'Pending'; + }); + await taskProvider.getPendingTasks(); + _filteredTaskList.clear(); + _filteredTaskList = + taskProvider.taskModelList; + }, + isSelected: _selectedChip == 'Pending', + ), + const SizedBox(width: 5), + _filterChip( + title: 'Completed', + icon: const Icon(Icons.done), + onSelected: () async { + setState(() { + _selectedChip = 'Completed'; + }); + await taskProvider.getCompletedTasks(); + _filteredTaskList.clear(); + _filteredTaskList = + taskProvider.taskModelList; + }, + isSelected: _selectedChip == 'Completed', + ), + ], + ), + ), + const SizedBox(height: 10), + SizedBox( + height: MediaQuery.of(context).size.height * 0.55, + child: _filteredTaskList.isEmpty + ? const Center(child: Text('No tasks found')) + : ListView.builder( + itemCount: _filteredTaskList.length, + itemBuilder: (context, index) => _taskView( + task: _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: () {}, - // ), - ], + ), ), ), ), - ), + if (taskProvider.isLoading) + Container( + color: Colors.black.withOpacity(0.1), + child: const Center( + child: CircularProgressIndicator(), + ), + ), + ], ), ), ); @@ -188,7 +192,6 @@ class _TaskManagementScreenState extends State { 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), @@ -198,37 +201,39 @@ class _TaskManagementScreenState extends State { ); } - Widget _taskView({required String title}) { + Widget _taskView({required TaskModel task}) { + final formatedDate = DateFormat('dd/MM/yyyy').format(task.taskDueDate); return Column( children: [ _customContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( - 'Sales Coordinator: 1', - style: TextStyle( + Text( + "Assigned to: ${task.taskAssignedTo.name}", + style: const TextStyle( fontFamily: 'Anek', + fontWeight: FontWeight.bold, ), ), const SizedBox(height: 10), Text( - title, + "Task: ${task.task}", style: const TextStyle( fontFamily: 'Anek', ), ), const SizedBox(height: 10), - const Text( - 'Status: Pending', - style: TextStyle( + Text( + 'Status: ${task.taskStatus}', + style: const TextStyle( fontFamily: 'Anek', ), ), const SizedBox(height: 10), - const Text( - 'Deadline: 12/12/2024', - style: TextStyle( + Text( + 'Deadline:$formatedDate', + style: const TextStyle( fontFamily: 'Anek', ), ), @@ -240,14 +245,23 @@ class _TaskManagementScreenState extends State { ); } - Widget _filterChip({required String title, required Widget icon}) { - return Chip( - avatar: icon, - label: Text( - title, - style: const TextStyle( - fontFamily: 'Anek', + Widget _filterChip({ + required String title, + required Widget icon, + required VoidCallback onSelected, + required bool isSelected, + }) { + return GestureDetector( + onTap: onSelected, + child: Chip( + avatar: icon, + label: Text( + title, + style: const TextStyle( + fontFamily: 'Anek', + ), ), + backgroundColor: isSelected ? Colors.blue : Colors.grey[200], ), ); } diff --git a/lib/services/api_urls.dart b/lib/services/api_urls.dart index e22dbd8..a150ac7 100644 --- a/lib/services/api_urls.dart +++ b/lib/services/api_urls.dart @@ -18,4 +18,5 @@ class ApiUrls { static const String getSalesCoordinators = 'salescoordinator/getAll-TM'; static const String assignTask = 'task/assign-task'; static const String getProductsManual = 'productmanual/getall'; + static const String getAllTasks = 'task/alltasks/'; }