assign task of KYC

This commit is contained in:
kratikpal 2024-08-23 09:11:23 +05:30
parent 7cce7db73c
commit 1436aa0131
16 changed files with 1243 additions and 479 deletions

View File

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:cheminova/provider/collect_kyc_provider.dart'; import 'package:cheminova/provider/collect_kyc_provider.dart';
import 'package:cheminova/provider/pd_rd_provider.dart'; import 'package:cheminova/provider/pd_rd_provider.dart';
import 'package:cheminova/provider/product_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/provider/user_provider.dart';
import 'package:cheminova/screens/splash_screen.dart'; import 'package:cheminova/screens/splash_screen.dart';
import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core/firebase_core.dart';
@ -100,6 +101,7 @@ Future<void> main() async {
ChangeNotifierProvider(create: (_) => UserProvider()), ChangeNotifierProvider(create: (_) => UserProvider()),
ChangeNotifierProvider(create: (_) => ProductProvider()), ChangeNotifierProvider(create: (_) => ProductProvider()),
ChangeNotifierProvider(create: (_) => PdRdProvider()), ChangeNotifierProvider(create: (_) => PdRdProvider()),
ChangeNotifierProvider(create: (_) => TaskProvider()),
], ],
child: const MyApp(), child: const MyApp(),
), ),
@ -117,12 +119,16 @@ class _MyAppState extends State<MyApp> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
// scaffoldMessengerKey: SnackBarService().scaffoldMessengerKey, // scaffoldMessengerKey: SnackBarService().scaffoldMessengerKey,
title: 'cheminova', title: 'cheminova',
theme: ThemeData( theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), colorScheme: ColorScheme.fromSeed(
useMaterial3: true), seedColor: const Color(0xff004791),
home: const SplashScreen()); ),
useMaterial3: true,
),
home: const SplashScreen(),
);
} }
} }

View File

@ -1,123 +1,127 @@
class PdRdResponseModel { class PdRdResponseModel {
String id; String? id;
String name; String? uniqueId;
String tradeName; String? name;
String address; String? tradeName;
String state; String? address;
String city; String? state;
String district; String? city;
String pincode; String? district;
String mobileNumber; String? pincode;
String principalDistributer; String? mobileNumber;
String panNumber; String? principalDistributer;
ImageModel panImg; String? panNumber;
String aadharNumber; ImageModel? panImg;
ImageModel aadharImg; String? aadharNumber;
String gstNumber; ImageModel? aadharImg;
ImageModel gstImg; String? gstNumber;
ImageModel pesticideLicenseImg; ImageModel? gstImg;
ImageModel selfieEntranceImg; ImageModel? pesticideLicenseImg;
String status; ImageModel? selfieEntranceImg;
String addedBy; String? status;
String? addedBy;
String? userType; String? userType;
List<Note> notes; List<Note>? notes;
DateTime createdAt; DateTime? createdAt;
DateTime updatedAt; DateTime? updatedAt;
int v; int? v;
PdRdResponseModel({ PdRdResponseModel({
required this.id, this.id,
required this.name, this.uniqueId,
required this.tradeName, this.name,
required this.address, this.tradeName,
required this.state, this.address,
required this.city, this.state,
required this.district, this.city,
required this.pincode, this.district,
required this.mobileNumber, this.pincode,
required this.principalDistributer, this.mobileNumber,
required this.panNumber, this.principalDistributer,
required this.panImg, this.panNumber,
required this.aadharNumber, this.panImg,
required this.aadharImg, this.aadharNumber,
required this.gstNumber, this.aadharImg,
required this.gstImg, this.gstNumber,
required this.pesticideLicenseImg, this.gstImg,
required this.selfieEntranceImg, this.pesticideLicenseImg,
required this.status, this.selfieEntranceImg,
required this.addedBy, this.status,
this.addedBy,
this.userType, this.userType,
required this.notes, this.notes,
required this.createdAt, this.createdAt,
required this.updatedAt, this.updatedAt,
required this.v, this.v,
}); });
factory PdRdResponseModel.fromJson(Map<String, dynamic> json) => factory PdRdResponseModel.fromJson(Map<String, dynamic> json) =>
PdRdResponseModel( PdRdResponseModel(
id: json["_id"], id: json["_id"],
name: json["name"], name: json["name"],
tradeName: json["trade_name"], uniqueId: json["uniqueId"],
address: json["address"], // tradeName: json["trade_name"],
state: json["state"], // address: json["address"],
city: json["city"], // state: json["state"],
district: json["district"], // city: json["city"],
pincode: json["pincode"], // district: json["district"],
mobileNumber: json["mobile_number"], // pincode: json["pincode"],
principalDistributer: json["principal_distributer"], // mobileNumber: json["mobile_number"],
panNumber: json["pan_number"], // principalDistributer: json["principal_distributer"],
panImg: ImageModel.fromJson(json["pan_img"]), // panNumber: json["pan_number"],
aadharNumber: json["aadhar_number"], // panImg: ImageModel.fromJson(json["pan_img"]),
aadharImg: ImageModel.fromJson(json["aadhar_img"]), // aadharNumber: json["aadhar_number"],
gstNumber: json["gst_number"], // aadharImg: ImageModel.fromJson(json["aadhar_img"]),
gstImg: ImageModel.fromJson(json["gst_img"]), // gstNumber: json["gst_number"],
pesticideLicenseImg: ImageModel.fromJson(json["pesticide_license_img"]), // gstImg: ImageModel.fromJson(json["gst_img"]),
selfieEntranceImg: ImageModel.fromJson(json["selfie_entrance_img"]), // pesticideLicenseImg: ImageModel.fromJson(json["pesticide_license_img"]),
status: json["status"], // selfieEntranceImg: ImageModel.fromJson(json["selfie_entrance_img"]),
addedBy: json["addedBy"], // status: json["status"],
userType: json["userType"], // addedBy: json["addedBy"],
notes: List<Note>.from(json["notes"].map((x) => Note.fromJson(x))), // userType: json["userType"],
createdAt: DateTime.parse(json["createdAt"]), // notes: List<Note>.from(json["notes"].map((x) => Note.fromJson(x))),
updatedAt: DateTime.parse(json["updatedAt"]), // createdAt: DateTime.parse(json["createdAt"]),
v: json["__v"], // updatedAt: DateTime.parse(json["updatedAt"]),
// v: json["__v"],
); );
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {
"_id": id, "_id": id,
"name": name, "name": name,
"trade_name": tradeName, "uniqueId": uniqueId,
"address": address, // "trade_name": tradeName,
"state": state, // "address": address,
"city": city, // "state": state,
"district": district, // "city": city,
"pincode": pincode, // "district": district,
"mobile_number": mobileNumber, // "pincode": pincode,
"principal_distributer": principalDistributer, // "mobile_number": mobileNumber,
"pan_number": panNumber, // "principal_distributer": principalDistributer,
"pan_img": panImg.toJson(), // "pan_number": panNumber,
"aadhar_number": aadharNumber, // "pan_img": panImg.toJson(),
"aadhar_img": aadharImg.toJson(), // "aadhar_number": aadharNumber,
"gst_number": gstNumber, // "aadhar_img": aadharImg.toJson(),
"gst_img": gstImg.toJson(), // "gst_number": gstNumber,
"pesticide_license_img": pesticideLicenseImg.toJson(), // "gst_img": gstImg.toJson(),
"selfie_entrance_img": selfieEntranceImg.toJson(), // "pesticide_license_img": pesticideLicenseImg.toJson(),
"status": status, // "selfie_entrance_img": selfieEntranceImg.toJson(),
"addedBy": addedBy, // "status": status,
"userType": userType, // "addedBy": addedBy,
"notes": List<dynamic>.from(notes.map((x) => x.toJson())), // "userType": userType,
"createdAt": createdAt.toIso8601String(), // "notes": List<dynamic>.from(notes.map((x) => x.toJson())),
"updatedAt": updatedAt.toIso8601String(), // "createdAt": createdAt.toIso8601String(),
"__v": v, // "updatedAt": updatedAt.toIso8601String(),
// "__v": v,
}; };
} }
class ImageModel { class ImageModel {
String publicId; String? publicId;
String url; String? url;
ImageModel({ ImageModel({
required this.publicId, this.publicId,
required this.url, this.url,
}); });
factory ImageModel.fromJson(Map<String, dynamic> json) => ImageModel( factory ImageModel.fromJson(Map<String, dynamic> json) => ImageModel(
@ -132,14 +136,14 @@ class ImageModel {
} }
class Note { class Note {
String message; String? message;
DateTime replyDate; DateTime? replyDate;
String id; String? id;
Note({ Note({
required this.message, this.message,
required this.replyDate, this.replyDate,
required this.id, this.id,
}); });
factory Note.fromJson(Map<String, dynamic> json) => Note( factory Note.fromJson(Map<String, dynamic> json) => Note(
@ -150,7 +154,7 @@ class Note {
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {
"message": message, "message": message,
"replyDate": replyDate.toIso8601String(), // "replyDate": replyDate.toIso8601String(),
"_id": id, "_id": id,
}; };
} }

View File

@ -8,8 +8,10 @@ class PdRdProvider extends ChangeNotifier {
bool _isLoading = false; bool _isLoading = false;
bool get isLoading => _isLoading; bool get isLoading => _isLoading;
List<PdRdResponseModel> _pdRdList = []; List<PdRdResponseModel> _pdList = [];
List<PdRdResponseModel> get pdRdList => _pdRdList; List<PdRdResponseModel> get pdList => _pdList;
List<PdRdResponseModel> _rdList = [];
List<PdRdResponseModel> get rdList => _rdList;
final _apiClient = ApiClient(); final _apiClient = ApiClient();
@ -18,16 +20,42 @@ class PdRdProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<void> getPdRd() async { void clearLists() {
_pdList.clear();
_rdList.clear();
notifyListeners();
}
Future<void> getPd() async {
setLoading(true); setLoading(true);
clearLists(); // Clear the list before fetching new data
try { try {
Response response = await _apiClient.get(ApiUrls.getPdRdUrl); Response response = await _apiClient.get(ApiUrls.getPd);
if (response.statusCode == 200) { if (response.statusCode == 200) {
// Assuming the response data is a list of PdRdResponseModel objects
List<PdRdResponseModel> data = (response.data as List) List<PdRdResponseModel> data = (response.data as List)
.map((json) => PdRdResponseModel.fromJson(json)) .map((json) => PdRdResponseModel.fromJson(json))
.toList(); .toList();
_pdRdList = data; _pdList = data;
} else {
print("Failed to load data: ${response.statusCode}");
}
} catch (e) {
print("Error occurred: $e");
} finally {
setLoading(false);
}
}
Future<void> 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<PdRdResponseModel> data = (response.data as List)
.map((json) => PdRdResponseModel.fromJson(json))
.toList();
_rdList = data;
} else { } else {
print("Failed to load data: ${response.statusCode}"); print("Failed to load data: ${response.statusCode}");
} }

View File

@ -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<PdRdResponseModel> _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<PdRdResponseModel> 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<void> getSalesCoordinators() async {
setLoading(true);
try {
Response response = await _apiClient.get(ApiUrls.getSalesCoordinators);
if (response.statusCode == 200) {
List<PdRdResponseModel> 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<void> 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);
}
}
}

View File

@ -72,7 +72,7 @@ class _AddProductsScreenState extends State<AddProductsScreen> {
), ),
], ],
title: Text( title: Text(
widget.distributor.name, widget.distributor.name!,
style: const TextStyle( style: const TextStyle(
fontSize: 20, fontSize: 20,
color: Colors.black, color: Colors.black,
@ -222,7 +222,7 @@ class _AddProductsScreenState extends State<AddProductsScreen> {
provider provider
.submitSelectedProducts( .submitSelectedProducts(
"PrincipalDistributor", "PrincipalDistributor",
widget.distributor.id) widget.distributor.id!)
.then((value) { .then((value) {
if (value) { if (value) {
Navigator.push( Navigator.push(
@ -275,27 +275,25 @@ class _ProductBlockState extends State<ProductBlock> {
setState(() { setState(() {
if (saleController.text.isNotEmpty && if (saleController.text.isNotEmpty &&
inventoryController.text.isNotEmpty) { inventoryController.text.isNotEmpty) {
// Check if the input can be parsed as an integer // Check if both inputs are valid integers
if (int.tryParse(saleController.text) == null || try {
int.tryParse(inventoryController.text) == null) {
errorMessage = 'Please enter valid integer value';
} else {
// Parse the input as integers
int sale = int.parse(saleController.text); int sale = int.parse(saleController.text);
int inventory = int.parse(inventoryController.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) { if (inventory > sale) {
errorMessage = 'Inventory should be less than or equal to sales'; errorMessage = 'Inventory should be less than or equal to sales';
} else { } else {
errorMessage = null; errorMessage = null;
} }
} catch (e) {
// Handle the case where input is not a valid integer
errorMessage = 'Please enter valid integer values for both fields';
} }
} else { } else {
errorMessage = 'Please fill in both fields'; errorMessage = null;
} }
}); });
return errorMessage == null; return errorMessage == null;
} }

View File

@ -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_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';
@ -55,39 +56,40 @@ class _AssignTaskDashBoardScreenState extends State<AssignTaskDashBoardScreen> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( // const Text(
'Assign Tasks', // 'Assign Tasks',
style: TextStyle( // style: TextStyle(
fontSize: 24, // fontSize: 24,
color: Colors.white, // color: Colors.white,
fontWeight: FontWeight.bold, // fontWeight: FontWeight.bold,
fontFamily: 'Anek', // fontFamily: 'Anek',
), // ),
), // ),
const SizedBox(height: 10), // const SizedBox(height: 10),
Row( // Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, // mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ // children: [
SizedBox( // SizedBox(
height: 200, // height: 200,
width: MediaQuery.of(context).size.width / 4.2, // width: MediaQuery.of(context).size.width / 4.2,
child: // child:
_customCard(title: "Total Tasks", subtitle: "100"), // _customCard(title: "Total Tasks", subtitle: "100"),
), // ),
SizedBox( // SizedBox(
height: 200, // height: 200,
width: MediaQuery.of(context).size.width / 4.2, // width: MediaQuery.of(context).size.width / 4.2,
child: _customCard( // child: _customCard(
title: "Tasks Pending", subtitle: "100"), // title: "Tasks Pending", subtitle: "100"),
), // ),
SizedBox( // SizedBox(
height: 200, // height: 200,
width: MediaQuery.of(context).size.width / 4.2, // width: MediaQuery.of(context).size.width / 4.2,
child: _customCard( // child: _customCard(
title: "Reports Submitted", subtitle: "100"), // title: "Reports Submitted", subtitle: "100"),
), // ),
], // ],
), // ),
const SizedBox(height: 20),
CommonElevatedButton( CommonElevatedButton(
backgroundColor: const Color(0xff004791), backgroundColor: const Color(0xff004791),
borderRadius: 30, borderRadius: 30,
@ -98,8 +100,7 @@ class _AssignTaskDashBoardScreenState extends State<AssignTaskDashBoardScreen> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => builder: (context) => const AssignTasksScreen(),
const SelectSalesCoordinatorScreen(),
), ),
); );
}, },
@ -111,7 +112,12 @@ class _AssignTaskDashBoardScreenState extends State<AssignTaskDashBoardScreen> {
width: double.infinity, width: double.infinity,
height: kToolbarHeight - 10, height: kToolbarHeight - 10,
text: 'VIEW TASK STATUS', text: 'VIEW TASK STATUS',
onPressed: () {}, onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const TaskManagementScreen(),
),
),
), ),
const SizedBox(height: 15), const SizedBox(height: 15),
CommonElevatedButton( CommonElevatedButton(

View File

@ -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_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_elevated_button.dart'; import 'package:cheminova/widgets/common_elevated_button.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:searchfield/searchfield.dart';
class AssignTasksScreen extends StatefulWidget { class AssignTasksScreen extends StatefulWidget {
const AssignTasksScreen({super.key}); const AssignTasksScreen({super.key});
@ -13,11 +17,45 @@ class AssignTasksScreen extends StatefulWidget {
} }
class _AssignTasksScreenState extends State<AssignTasksScreen> { class _AssignTasksScreenState extends State<AssignTasksScreen> {
final List<bool> _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<TaskProvider>();
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<void> _selectDate(BuildContext context) async { Future<void> _selectDate(BuildContext context) async {
final provider = context.read<TaskProvider>();
final dateSelected = await showDatePicker( final dateSelected = await showDatePicker(
context: context, context: context,
initialDate: DateTime.now(), initialDate: DateTime.now(),
@ -25,14 +63,28 @@ class _AssignTasksScreenState extends State<AssignTasksScreen> {
lastDate: DateTime(2025), lastDate: DateTime(2025),
); );
if (dateSelected != null) { if (dateSelected != null) {
setState(() { provider.setDate(DateFormat('dd/MM/yyyy').format(dateSelected));
_dateSelected = DateFormat('dd/MM/yyyy').format(dateSelected);
});
} }
} }
void _updateTaskProvider() {
final provider = context.read<TaskProvider>();
provider.clear();
provider.getSalesCoordinators();
}
@override
void initState() {
super.initState();
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(
@ -56,250 +108,338 @@ class _AssignTasksScreenState extends State<AssignTasksScreen> {
), ),
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: [
const Text(
'Assign Tasks',
style: TextStyle(
fontSize: 24,
color: Colors.white,
fontWeight: FontWeight.bold,
fontFamily: 'Anek',
),
), ),
const SizedBox(height: 20), child: Column(
Container( mainAxisSize: MainAxisSize.min,
width: double.infinity, crossAxisAlignment: CrossAxisAlignment.start,
padding: const EdgeInsets.all(12.0), children: [
margin: const EdgeInsets.only(bottom: 20), const Text(
decoration: BoxDecoration( 'Assign Tasks',
border: Border.all(color: Colors.white), style: TextStyle(
color: const Color(0xffB4D1E5).withOpacity(0.6), fontSize: 24,
borderRadius: BorderRadius.circular(16.0), color: Colors.white,
), fontWeight: FontWeight.bold,
child: const Column( fontFamily: 'Anek',
crossAxisAlignment: CrossAxisAlignment.start, ),
children: [ ),
Text( const SizedBox(height: 20),
"Sales Coordinator: Name", SearchField(
style: TextStyle( suggestionsDecoration: SuggestionDecoration(
fontSize: 16, borderRadius: const BorderRadius.only(
fontWeight: FontWeight.bold, bottomLeft: Radius.circular(8.0),
fontFamily: 'Anek', bottomRight: Radius.circular(8),
),
border: Border.all(
color: Colors.grey.withOpacity(0.5),
), ),
), ),
Text( suggestionItemDecoration: BoxDecoration(
"ID: 121", borderRadius: BorderRadius.circular(8),
style: TextStyle( shape: BoxShape.rectangle,
fontSize: 16, border: Border.all(
fontWeight: FontWeight.bold, color: Colors.transparent,
fontFamily: 'Anek', style: BorderStyle.solid,
), width: 1.0),
), ),
], searchInputDecoration: InputDecoration(
), filled: true,
), fillColor: Colors.grey.withOpacity(0.2),
Container( focusedBorder: OutlineInputBorder(
width: double.infinity, borderSide: const BorderSide(
padding: const EdgeInsets.all(12.0), color: Colors.white,
margin: const EdgeInsets.only(bottom: 20), width: 2.0,
decoration: BoxDecoration( ),
border: Border.all(color: Colors.white), borderRadius: BorderRadius.circular(8.0),
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',
), ),
), border: const OutlineInputBorder(
SizedBox( borderRadius: BorderRadius.all(
height: 35, Radius.circular(16.0),
child: CheckboxListTile( ),
value: _isChecked[0], borderSide: BorderSide(
onChanged: (value) { color: Colors.white,
setState(() { width: 2.0,
_isChecked[0] = value!;
});
},
title: const Text(
"Visit Retailers",
), ),
), ),
errorText: !_isSalesCoordinatorValid
? 'Please select a Sales Coordinator'
: null,
), ),
SizedBox( hint: 'Select Sales Coordinator',
height: 45, onSuggestionTap: (selectedItem) {
child: CheckboxListTile( if (selectedItem.item != null) {
value: _isChecked[1], taskProvider.setSelectedSalesCoordinator(
onChanged: (value) { selectedItem.item!);
setState(() { FocusScope.of(context).unfocus();
_isChecked[1] = value!; }
}); },
}, onTapOutside: (event) =>
title: const Text( FocusScope.of(context).unfocus(),
"Update Sales Data", 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( child: Column(
height: 45, crossAxisAlignment: CrossAxisAlignment.start,
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(
children: [ children: [
Checkbox(
value: _isChecked[4],
onChanged: (value) {
setState(() {
_isChecked[4] = value!;
});
},
),
const Text( const Text(
"Low", "Tasks List:",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
fontFamily: 'Anek',
),
), ),
Checkbox( SizedBox(
value: _isChecked[5], height: 35,
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
value: 'Visit Retailers',
groupValue: taskProvider.selectedTask,
onChanged: (value) {
taskProvider.setSelectedTask(value);
},
title: const Text(
"Visit Retailers",
),
),
),
SizedBox(
height: 45,
child: RadioListTile<String>(
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<String>(
contentPadding: EdgeInsets.zero,
value: 'Update Liqudation Data',
groupValue: taskProvider.selectedTask,
onChanged: (value) {
taskProvider.setSelectedTask(value);
},
title: const Text(
"Update Liqudation Data",
),
),
),
RadioListTile<String>(
contentPadding: EdgeInsets.zero,
value: 'Collect KYC',
groupValue: taskProvider.selectedTask,
onChanged: (value) { onChanged: (value) {
setState(() { taskProvider.setSelectedTask(value);
_isChecked[5] = 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( const Text(
"Medium", "Priority:",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
fontFamily: 'Anek',
),
), ),
Checkbox( Row(
value: _isChecked[6], children: [
onChanged: (value) { Radio<String>(
setState(() { value: "Low",
_isChecked[6] = value!; groupValue: taskProvider.selectedPriority,
}); onChanged: (value) {
}, taskProvider.setSelectedPriority(value!);
},
),
const Text("Low"),
Radio<String>(
value: "Medium",
groupValue: taskProvider.selectedPriority,
onChanged: (value) {
taskProvider.setSelectedPriority(value!);
},
),
const Text("Medium"),
Radio<String>(
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( 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(),
),
),
],
), ),
), ),
); );

View File

@ -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<ConfirmTaskScreen> createState() => _ConfirmTaskScreenState();
}
class _ConfirmTaskScreenState extends State<ConfirmTaskScreen> {
@override
Widget build(BuildContext context) {
final taskProvider = context.watch<TaskProvider>();
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,
);
}
}

View File

@ -14,25 +14,32 @@ class DataSubmitSuccessfullState extends State<DataSubmitSuccessfull> {
void initState() { void initState() {
super.initState(); super.initState();
Future.delayed(const Duration(seconds: 2), () { Future.delayed(const Duration(seconds: 2), () {
Navigator.pushReplacement( Navigator.of(context).pushAndRemoveUntil(
context, MaterialPageRoute(builder: (context) => const HomePage())); MaterialPageRoute(builder: (context) => const HomePage()),
(Route<dynamic> route) => false, // Remove all routes
);
}); });
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: CommonBackground( body: CommonBackground(
child: Center( child: Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Text('Data Submitted\nsuccessfully', const Text('Data Submitted\nsuccessfully',
style: TextStyle( style: TextStyle(
fontSize: 36, fontSize: 36,
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontFamily: 'Anek')), fontFamily: 'Anek')),
const SizedBox(height: 20), // Add some space between the text and the image const SizedBox(
Image.asset('assets/check_circle.png', )])))); height: 20), // Add some space between the text and the image
Image.asset(
'assets/check_circle.png',
)
]))));
} }
} }

View File

@ -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_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';
@ -79,10 +78,18 @@ class _SelectSalesCoordinatorScreenState
child: ListView.builder( child: ListView.builder(
itemCount: salesCoordinators.length, itemCount: salesCoordinators.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return _customCard( return GestureDetector(
name: salesCoordinators[index].name, onTap: () {
id: salesCoordinators[index].id, // taskProvider.setSelectedSalesCoordinator(
tasks: salesCoordinators[index].tasks, // 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( Widget _customCard(
{required String name, required String id, required int tasks}) { {required String name, required String id, required int tasks}) {
return GestureDetector( return Container(
onTap: () { width: double.infinity,
Navigator.push( padding: const EdgeInsets.all(12.0),
context, margin: const EdgeInsets.all(8),
MaterialPageRoute( decoration: BoxDecoration(
builder: (context) { border: Border.all(color: Colors.white),
return const AssignTasksScreen(); 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(
child: Container( "ID: $id",
width: double.infinity, style: const TextStyle(
padding: const EdgeInsets.all(12.0), fontFamily: 'Anek',
margin: const EdgeInsets.all(8), fontSize: 16,
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( const SizedBox(height: 5),
"ID: $id", Text(
style: const TextStyle( "Tasks: $tasks",
fontFamily: 'Anek', style: const TextStyle(
fontSize: 16, fontFamily: 'Anek',
), fontSize: 16,
), ),
const SizedBox(height: 5), ),
Text( ],
"Tasks: $tasks",
style: const TextStyle(
fontFamily: 'Anek',
fontSize: 16,
),
),
],
),
), ),
); );
} }

View File

@ -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<TaskManagementScreen> createState() => _TaskManagementScreenState();
}
class _TaskManagementScreenState extends State<TaskManagementScreen> {
final TextEditingController _searchController = TextEditingController();
final List<String> _taskList = [
'Task 1',
'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) {
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',
),
),
);
}
}

View File

@ -23,10 +23,10 @@ class _UpdateInventoryScreenState extends State<UpdateInventoryScreen> {
void initState() { void initState() {
super.initState(); super.initState();
// Fetch the PdRd data when the screen is initialized // Fetch the PdRd data when the screen is initialized
WidgetsBinding.instance.addPostFrameCallback((_) { // WidgetsBinding.instance.addPostFrameCallback((_) {
final provider = Provider.of<PdRdProvider>(context, listen: false); // final provider = Provider.of<PdRdProvider>(context, listen: false);
provider.getPdRd(); // provider.getPdRd();
}); // });
} }
@override @override
@ -65,11 +65,14 @@ class _UpdateInventoryScreenState extends State<UpdateInventoryScreen> {
text: 'SUBMIT', text: 'SUBMIT',
backgroundColor: const Color(0xff004791), backgroundColor: const Color(0xff004791),
onPressed: () { onPressed: () {
if(selectedDistributor == null || selectedDistributorType == null){ if (selectedDistributor == null ||
selectedDistributorType == null) {
ScaffoldMessenger.of(context).showSnackBar( 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( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
@ -85,22 +88,6 @@ class _UpdateInventoryScreenState extends State<UpdateInventoryScreen> {
), ),
body: Consumer<PdRdProvider>( body: Consumer<PdRdProvider>(
builder: (context, provider, child) { 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<PdRdResponseModel> principalDistributors = provider.pdRdList
.where((item) => item.userType == 'SalesCoOrdinator')
.toList();
List<PdRdResponseModel> retailerDistributors = provider.pdRdList
.where((item) => item.userType != 'SalesCoOrdinator')
.toList();
return Stack( return Stack(
children: [ children: [
Column( Column(
@ -127,6 +114,9 @@ class _UpdateInventoryScreenState extends State<UpdateInventoryScreen> {
onChanged: (value) { onChanged: (value) {
setState(() { setState(() {
selectedDistributorType = value; selectedDistributorType = value;
selectedDistributorType == 'Principal Distributor'
? provider.getPd()
: provider.getRd();
selectedDistributor = selectedDistributor =
null; // Reset distributor selection when type changes null; // Reset distributor selection when type changes
}); });
@ -148,12 +138,12 @@ class _UpdateInventoryScreenState extends State<UpdateInventoryScreen> {
value: selectedDistributor, value: selectedDistributor,
items: (selectedDistributorType == items: (selectedDistributorType ==
'Principal Distributor' 'Principal Distributor'
? principalDistributors ? provider.pdList
: retailerDistributors) : provider.rdList)
.map((PdRdResponseModel distributor) { .map((PdRdResponseModel distributor) {
return DropdownMenuItem<PdRdResponseModel>( return DropdownMenuItem<PdRdResponseModel>(
value: distributor, value: distributor,
child: Text(distributor.name), child: Text(distributor.name!),
); );
}).toList(), }).toList(),
onChanged: (value) { onChanged: (value) {
@ -170,6 +160,13 @@ class _UpdateInventoryScreenState extends State<UpdateInventoryScreen> {
), ),
], ],
), ),
if (provider.isLoading)
Container(
color: Colors.black.withOpacity(0.1),
child: const Center(
child: CircularProgressIndicator(),
),
),
], ],
); );
}, },

View File

@ -12,7 +12,9 @@ class ApiUrls {
static const String notificationUrl = '$baseUrl/get-notification-tm'; static const String notificationUrl = '$baseUrl/get-notification-tm';
static const String fcmUrl = '${baseUrl}kyc/save-fcm-tm'; static const String fcmUrl = '${baseUrl}kyc/save-fcm-tm';
static const String getProducts = '${baseUrl}product/getAll/user/'; static const String getProducts = '${baseUrl}product/getAll/user/';
static const String getPdRdUrl = static const String getPd = 'inventory/distributors-TM/RetailDistributor';
'inventory/distributors-TM/RetailDistributor'; static const String getRd = 'inventory/distributors-TM/PrincipalDistributor';
static const String submitProducts = 'inventory/add-TM'; static const String submitProducts = 'inventory/add-TM';
static const String getSalesCoordinators = 'salescoordinator/getAll-TM';
static const String assignTask = 'task/assign-task';
} }

View File

@ -13,6 +13,7 @@ class CommonTextFormField extends StatelessWidget {
final List<TextInputFormatter>? inputFormatters; final List<TextInputFormatter>? inputFormatters;
final int? maxLength; final int? maxLength;
final bool obscureText; final bool obscureText;
final void Function(String)? onChanged;
const CommonTextFormField({ const CommonTextFormField({
super.key, super.key,
@ -26,6 +27,7 @@ class CommonTextFormField extends StatelessWidget {
this.keyboardType, this.keyboardType,
this.inputFormatters, this.inputFormatters,
this.maxLength, this.maxLength,
this.onChanged,
this.obscureText = false, this.obscureText = false,
}); });
@ -45,6 +47,7 @@ class CommonTextFormField extends StatelessWidget {
readOnly: readOnly ?? false, readOnly: readOnly ?? false,
maxLines: maxLines, maxLines: maxLines,
maxLength: maxLength, maxLength: maxLength,
onChanged: onChanged,
onTapOutside: (event) => FocusScope.of(context).unfocus(), onTapOutside: (event) => FocusScope.of(context).unfocus(),
validator: validator, validator: validator,
keyboardType: keyboardType, keyboardType: keyboardType,

View File

@ -1040,6 +1040,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
searchfield:
dependency: "direct main"
description:
name: searchfield
sha256: "913bb61f42d47d82c1adb67047fff3b26dcf6a199f71ecdc9af27c506dda4b48"
url: "https://pub.dev"
source: hosted
version: "1.0.9"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:

View File

@ -50,6 +50,7 @@ dependencies:
flutter_local_notifications: ^17.2.1+2 flutter_local_notifications: ^17.2.1+2
firebase_crashlytics: ^4.0.4 firebase_crashlytics: ^4.0.4
firebase_analytics: ^11.2.1 firebase_analytics: ^11.2.1
searchfield: ^1.0.9
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: