task status

This commit is contained in:
kratikpal 2024-08-30 17:50:19 +05:30
parent 12af640bae
commit ec339c48ba
4 changed files with 294 additions and 142 deletions

View File

@ -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<String, dynamic> 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<String, dynamic> json) {
return TaskAssignedTo(
id: json['_id'],
name: json['name'],
mobileNumber: json['mobileNumber'],
email: json['email'],
);
}
}

View File

@ -1,4 +1,5 @@
import 'package:cheminova/models/pd_rd_response_model.dart'; 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/screens/data_submit_successfull.dart';
import 'package:cheminova/services/api_client.dart'; import 'package:cheminova/services/api_client.dart';
import 'package:cheminova/services/api_urls.dart'; import 'package:cheminova/services/api_urls.dart';
@ -15,6 +16,7 @@ class TaskProvider extends ChangeNotifier {
List<PdRdResponseModel> _salesCoordinators = []; List<PdRdResponseModel> _salesCoordinators = [];
List<PdRdResponseModel> _pdList = []; List<PdRdResponseModel> _pdList = [];
List<PdRdResponseModel> _rdList = []; List<PdRdResponseModel> _rdList = [];
List<TaskModel> _taskModelList = [];
PdRdResponseModel? _selectedDistributor; PdRdResponseModel? _selectedDistributor;
final TextEditingController _noteController = TextEditingController(); final TextEditingController _noteController = TextEditingController();
final _apiClient = ApiClient(); final _apiClient = ApiClient();
@ -28,6 +30,7 @@ class TaskProvider extends ChangeNotifier {
TextEditingController get noteController => _noteController; TextEditingController get noteController => _noteController;
List<PdRdResponseModel> get pdList => _pdList; List<PdRdResponseModel> get pdList => _pdList;
List<PdRdResponseModel> get rdList => _rdList; List<PdRdResponseModel> get rdList => _rdList;
List<TaskModel> get taskModelList => _taskModelList;
PdRdResponseModel? get selectedDistributor => _selectedDistributor; PdRdResponseModel? get selectedDistributor => _selectedDistributor;
void setLoading(bool loading) { void setLoading(bool loading) {
@ -61,6 +64,7 @@ class TaskProvider extends ChangeNotifier {
_selectedPriority = null; _selectedPriority = null;
_selectedDate = DateFormat('dd/MM/yyyy').format(DateTime.now()); _selectedDate = DateFormat('dd/MM/yyyy').format(DateTime.now());
_noteController.clear(); _noteController.clear();
_taskModelList.clear();
notifyListeners(); notifyListeners();
} }
@ -187,4 +191,59 @@ class TaskProvider extends ChangeNotifier {
setLoading(false); setLoading(false);
} }
} }
Future<void> getNewTasks() async {
setLoading(true);
clearLists();
try {
Response response = await _apiClient.get("${ApiUrls.getAllTasks}New");
if (response.statusCode == 200) {
List<TaskModel> data = (response.data['tasks'] as List)
.map((json) => TaskModel.fromJson(json))
.toList();
_taskModelList = data;
}
} catch (e) {
print("Error occurred: $e");
} finally {
setLoading(false);
}
}
Future<void> getPendingTasks() async {
setLoading(true);
clearLists();
try {
Response response = await _apiClient.get("${ApiUrls.getAllTasks}Pending");
if (response.statusCode == 200) {
List<TaskModel> data = (response.data['tasks'] as List)
.map((json) => TaskModel.fromJson(json))
.toList();
_taskModelList = data;
}
} catch (e) {
print("Error occurred: $e");
} finally {
setLoading(false);
}
}
Future<void> getCompletedTasks() async {
setLoading(true);
clearLists();
try {
Response response =
await _apiClient.get("${ApiUrls.getAllTasks}Completed");
if (response.statusCode == 200) {
List<TaskModel> data = (response.data['tasks'] as List)
.map((json) => TaskModel.fromJson(json))
.toList();
_taskModelList = data;
}
} catch (e) {
print("Error occurred: $e");
} finally {
setLoading(false);
}
}
} }

View File

@ -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_app_bar.dart';
import 'package:cheminova/widgets/common_background.dart'; import 'package:cheminova/widgets/common_background.dart';
import 'package:cheminova/widgets/common_drawer.dart'; import 'package:cheminova/widgets/common_drawer.dart';
import 'package:cheminova/widgets/common_text_form_field.dart'; import 'package:cheminova/widgets/common_text_form_field.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
class TaskManagementScreen extends StatefulWidget { class TaskManagementScreen extends StatefulWidget {
const TaskManagementScreen({super.key}); const TaskManagementScreen({super.key});
@ -13,43 +17,45 @@ class TaskManagementScreen extends StatefulWidget {
class _TaskManagementScreenState extends State<TaskManagementScreen> { class _TaskManagementScreenState extends State<TaskManagementScreen> {
final TextEditingController _searchController = TextEditingController(); final TextEditingController _searchController = TextEditingController();
final List<String> _taskList = [ List<TaskModel> _filteredTaskList = [];
'Task 1', String? _selectedChip; // State to track the selected chip
'Task 2',
'Task 3',
'Task 4',
'Task 5',
'Task 6',
'Task 7',
'Task 8',
'Task 9',
'Task 10',
];
final List<String> _filters = [
'All',
'Pending',
'Completed',
];
List<String> _filteredTaskList = [];
void _filterTaskList(String query) { void _filterTaskList(String query) {
if (query.isEmpty || query == '' || query == ' ') {
setState(() {
_filteredTaskList = context.read<TaskProvider>().taskModelList;
});
return;
}
setState(() { setState(() {
_filteredTaskList = _taskList _filteredTaskList = _filteredTaskList
.where((task) => task.toLowerCase().contains(query.toLowerCase())) .where((task) => task.taskAssignedTo.name
.toLowerCase()
.contains(query.toLowerCase()))
.toList(); .toList();
}); });
} }
Future<void> _updateTaskProvider() async {
final provider = context.read<TaskProvider>();
provider.clear();
await provider.getNewTasks();
_filteredTaskList.clear();
_filteredTaskList = provider.taskModelList;
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_filteredTaskList = _taskList; WidgetsBinding.instance.addPostFrameCallback((_) {
_updateTaskProvider();
});
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final taskProvider = context.watch<TaskProvider>();
return Scaffold( return Scaffold(
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
appBar: CommonAppBar( appBar: CommonAppBar(
@ -73,112 +79,110 @@ class _TaskManagementScreenState extends State<TaskManagementScreen> {
), ),
drawer: const CommonDrawer(), drawer: const CommonDrawer(),
body: CommonBackground( body: CommonBackground(
child: SafeArea( child: Stack(
child: SingleChildScrollView( children: [
child: Padding( SafeArea(
padding: const EdgeInsets.only(top: 20), child: SingleChildScrollView(
child: Container( child: Padding(
padding: padding: const EdgeInsets.only(top: 20),
const EdgeInsets.all(20.0).copyWith(top: 15, bottom: 30), child: Container(
margin: const EdgeInsets.symmetric(horizontal: 30.0) padding: const EdgeInsets.all(20.0)
.copyWith(bottom: 50), .copyWith(top: 15, bottom: 30),
decoration: BoxDecoration( margin: const EdgeInsets.symmetric(horizontal: 30.0)
border: Border.all(color: Colors.white), .copyWith(bottom: 50),
color: const Color(0xffB4D1E5).withOpacity(0.5), decoration: BoxDecoration(
borderRadius: BorderRadius.circular(26.0), border: Border.all(color: Colors.white),
), color: const Color(0xffB4D1E5).withOpacity(0.5),
child: Column( borderRadius: BorderRadius.circular(26.0),
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CommonTextFormField(
controller: _searchController,
onChanged: (value) => _filterTaskList(value),
title: 'Filter by Sales Coordinator:',
), ),
const SizedBox(height: 20), child: Column(
SingleChildScrollView( mainAxisSize: MainAxisSize.min,
scrollDirection: Axis.horizontal, crossAxisAlignment: CrossAxisAlignment.start,
child: Row( children: [
mainAxisAlignment: MainAxisAlignment.spaceEvenly, CommonTextFormField(
children: [ controller: _searchController,
_filterChip( onChanged: (value) => _filterTaskList(value),
title: 'All', title: 'Filter by Sales Coordinator:',
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],
), ),
), 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<TaskManagementScreen> {
return Container( return Container(
width: double.infinity, width: double.infinity,
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12.0),
// margin: const EdgeInsets.all(8),
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all(color: Colors.white), border: Border.all(color: Colors.white),
color: const Color(0xffB4D1E5).withOpacity(0.6), color: const Color(0xffB4D1E5).withOpacity(0.6),
@ -198,37 +201,39 @@ class _TaskManagementScreenState extends State<TaskManagementScreen> {
); );
} }
Widget _taskView({required String title}) { Widget _taskView({required TaskModel task}) {
final formatedDate = DateFormat('dd/MM/yyyy').format(task.taskDueDate);
return Column( return Column(
children: [ children: [
_customContainer( _customContainer(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( Text(
'Sales Coordinator: 1', "Assigned to: ${task.taskAssignedTo.name}",
style: TextStyle( style: const TextStyle(
fontFamily: 'Anek', fontFamily: 'Anek',
fontWeight: FontWeight.bold,
), ),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
Text( Text(
title, "Task: ${task.task}",
style: const TextStyle( style: const TextStyle(
fontFamily: 'Anek', fontFamily: 'Anek',
), ),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
const Text( Text(
'Status: Pending', 'Status: ${task.taskStatus}',
style: TextStyle( style: const TextStyle(
fontFamily: 'Anek', fontFamily: 'Anek',
), ),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
const Text( Text(
'Deadline: 12/12/2024', 'Deadline:$formatedDate',
style: TextStyle( style: const TextStyle(
fontFamily: 'Anek', fontFamily: 'Anek',
), ),
), ),
@ -240,14 +245,23 @@ class _TaskManagementScreenState extends State<TaskManagementScreen> {
); );
} }
Widget _filterChip({required String title, required Widget icon}) { Widget _filterChip({
return Chip( required String title,
avatar: icon, required Widget icon,
label: Text( required VoidCallback onSelected,
title, required bool isSelected,
style: const TextStyle( }) {
fontFamily: 'Anek', return GestureDetector(
onTap: onSelected,
child: Chip(
avatar: icon,
label: Text(
title,
style: const TextStyle(
fontFamily: 'Anek',
),
), ),
backgroundColor: isSelected ? Colors.blue : Colors.grey[200],
), ),
); );
} }

View File

@ -18,4 +18,5 @@ class ApiUrls {
static const String getSalesCoordinators = 'salescoordinator/getAll-TM'; static const String getSalesCoordinators = 'salescoordinator/getAll-TM';
static const String assignTask = 'task/assign-task'; static const String assignTask = 'task/assign-task';
static const String getProductsManual = 'productmanual/getall'; static const String getProductsManual = 'productmanual/getall';
static const String getAllTasks = 'task/alltasks/';
} }