api calendar and announcement intergrate
This commit is contained in:
parent
86a9b751ba
commit
c577c7005f
3
devtools_options.yaml
Normal file
3
devtools_options.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
28
lib/models/Announcements_Response.dart
Normal file
28
lib/models/Announcements_Response.dart
Normal file
@ -0,0 +1,28 @@
|
||||
class AnnouncementResponse {
|
||||
final String id;
|
||||
final String uniqueId;
|
||||
final List<String> sentTo;
|
||||
final String message;
|
||||
final DateTime createdAt;
|
||||
final DateTime updatedAt;
|
||||
|
||||
AnnouncementResponse({
|
||||
required this.id,
|
||||
required this.uniqueId,
|
||||
required this.sentTo,
|
||||
required this.message,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
factory AnnouncementResponse.fromJson(Map<String, dynamic> json) {
|
||||
return AnnouncementResponse(
|
||||
id: json['_id'] ?? '',
|
||||
uniqueId: json['uniqueId'] ?? '',
|
||||
sentTo: List<String>.from(json['sentTo']),
|
||||
message: json['message'] ?? '',
|
||||
createdAt: DateTime.parse(json['createdAt']),
|
||||
updatedAt: DateTime.parse(json['updatedAt']),
|
||||
);
|
||||
}
|
||||
}
|
123
lib/models/pd_rd_response_model.dart
Normal file
123
lib/models/pd_rd_response_model.dart
Normal file
@ -0,0 +1,123 @@
|
||||
class PdRdResponseModel {
|
||||
String? id;
|
||||
String? uniqueId;
|
||||
String? name;
|
||||
ShippingAddress? shippingAddress;
|
||||
Kyc? kyc;
|
||||
|
||||
String? salesCoordinator; // Nullable property for SalesCoordinator
|
||||
|
||||
PdRdResponseModel({
|
||||
this.id,
|
||||
this.uniqueId,
|
||||
this.name,
|
||||
this.kyc,
|
||||
this.shippingAddress,
|
||||
this.salesCoordinator, // Initialize SalesCoordinator
|
||||
});
|
||||
|
||||
factory PdRdResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
PdRdResponseModel(
|
||||
id: json["_id"],
|
||||
name: json["name"],
|
||||
uniqueId: json["uniqueId"],
|
||||
kyc: json["kyc"] != null ? Kyc.fromJson(json["kyc"]) : null,
|
||||
shippingAddress: json['shippingAddress'] != null
|
||||
? ShippingAddress.fromJson(json['shippingAddress'])
|
||||
: null,
|
||||
salesCoordinator: json.containsKey('salesCoordinator')
|
||||
? json['salesCoordinator']
|
||||
: null, // Handle missing field
|
||||
);
|
||||
}
|
||||
|
||||
class ShippingAddress {
|
||||
final String id;
|
||||
final String street;
|
||||
final String city;
|
||||
final String state;
|
||||
final String postalCode;
|
||||
final String country;
|
||||
final String panNumber;
|
||||
final String tradeName;
|
||||
final String gstNumber;
|
||||
final bool isDefault;
|
||||
|
||||
ShippingAddress({
|
||||
required this.id,
|
||||
required this.street,
|
||||
required this.city,
|
||||
required this.state,
|
||||
required this.postalCode,
|
||||
required this.country,
|
||||
required this.panNumber,
|
||||
required this.tradeName,
|
||||
required this.gstNumber,
|
||||
required this.isDefault,
|
||||
});
|
||||
|
||||
factory ShippingAddress.fromJson(Map<String, dynamic> json) {
|
||||
return ShippingAddress(
|
||||
id: json['_id'] ?? '',
|
||||
street: json['street'] ?? '',
|
||||
city: json['city'] ?? '',
|
||||
state: json['state'] ?? '',
|
||||
postalCode: json['postalCode'] ?? '',
|
||||
country: json['country'] ?? '',
|
||||
panNumber: json['panNumber'] ?? '',
|
||||
tradeName: json['tradeName'] ?? '',
|
||||
gstNumber: json['gstNumber'] ?? '',
|
||||
isDefault: json['isDefault'] ?? false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Kyc {
|
||||
final String id;
|
||||
final String street;
|
||||
final String city;
|
||||
final String state;
|
||||
final String postalCode;
|
||||
final String country;
|
||||
final String panNumber;
|
||||
final String tradeName;
|
||||
final String gstNumber;
|
||||
final bool isDefault;
|
||||
final String? panImgUrl; // New field for PAN image URL
|
||||
final String? aadharImgUrl; // New field for Aadhar image URL
|
||||
final String? gstImgUrl; // New field for GST image URL
|
||||
|
||||
Kyc({
|
||||
required this.id,
|
||||
required this.street,
|
||||
required this.city,
|
||||
required this.state,
|
||||
required this.postalCode,
|
||||
required this.country,
|
||||
required this.panNumber,
|
||||
required this.tradeName,
|
||||
required this.gstNumber,
|
||||
required this.isDefault,
|
||||
this.panImgUrl,
|
||||
this.aadharImgUrl,
|
||||
this.gstImgUrl,
|
||||
});
|
||||
|
||||
factory Kyc.fromJson(Map<String, dynamic> json) {
|
||||
return Kyc(
|
||||
id: json['_id'] ?? '',
|
||||
street: json['street'] ?? '',
|
||||
city: json['city'] ?? '',
|
||||
state: json['state'] ?? '',
|
||||
postalCode: json['postalCode'] ?? '',
|
||||
country: json['country'] ?? '',
|
||||
panNumber: json['panNumber'] ?? '',
|
||||
tradeName: json['trade_name'] ?? '',
|
||||
gstNumber: json['gstNumber'] ?? '',
|
||||
isDefault: json['isDefault'] ?? false,
|
||||
panImgUrl: json['pan_img']?['url'],
|
||||
aadharImgUrl: json['aadhar_img']?['url'],
|
||||
gstImgUrl: json['gst_img']?['url'],
|
||||
);
|
||||
}
|
||||
}
|
78
lib/models/task_model.dart
Normal file
78
lib/models/task_model.dart
Normal 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'],
|
||||
);
|
||||
}
|
||||
}
|
41
lib/provider/Announcement_Provider.dart
Normal file
41
lib/provider/Announcement_Provider.dart
Normal file
@ -0,0 +1,41 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../models/Announcements_Response.dart';
|
||||
import '../services/api_client.dart';
|
||||
import '../services/api_urls.dart';
|
||||
|
||||
class AnnouncementProvider extends ChangeNotifier {
|
||||
AnnouncementProvider() {
|
||||
getAnnouncements(); // Fetch announcements when the provider is initialized
|
||||
}
|
||||
|
||||
final _apiClient = ApiClient(); // Use the API client to fetch data
|
||||
List<AnnouncementResponse> announcementList = []; // List to hold announcement data
|
||||
|
||||
bool _isLoading = false; // Loading state
|
||||
|
||||
bool get isLoading => _isLoading; // Getter for loading state
|
||||
|
||||
void setLoading(bool loading) {
|
||||
_isLoading = loading;
|
||||
notifyListeners(); // Notify listeners when loading state changes
|
||||
}
|
||||
|
||||
Future<void> getAnnouncements() async {
|
||||
setLoading(true); // Set loading to true before the request
|
||||
try {
|
||||
Response response = await _apiClient.get(ApiUrls.announcementUrl); // Fetch announcements
|
||||
setLoading(false); // Set loading to false after the request completes
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> data = response.data;
|
||||
announcementList = data
|
||||
.map((item) => AnnouncementResponse.fromJson(item))
|
||||
.toList(); // Map JSON data to the announcement model
|
||||
notifyListeners(); // Notify listeners after data is updated
|
||||
}
|
||||
} catch (e) {
|
||||
setLoading(false); // Handle errors and stop loading state
|
||||
// Optionally handle errors here (e.g., log error, show message)
|
||||
}
|
||||
}
|
||||
}
|
@ -45,7 +45,7 @@ class ProductProvider extends ChangeNotifier {
|
||||
if (response.statusCode == 200) {
|
||||
productResponse = ProductResponse.fromJson(response.data);
|
||||
productList = productResponse!.products!
|
||||
.map((product) => ProductModel(sku: product.sKU!, productName: product.name!))
|
||||
.map((product) => ProductModel(sku: product.sKU!, productName: product.name!,id: product.sId!))
|
||||
.toList();
|
||||
notifyListeners(); // Notify listeners to update the UI with the product list
|
||||
}
|
||||
@ -59,6 +59,7 @@ class ProductProvider extends ChangeNotifier {
|
||||
// Send POST request to submit products
|
||||
Response response = await _apiClient.post(ApiUrls.submitProductUrl,
|
||||
data: json.encode({
|
||||
|
||||
"addedFor": distributorType.replaceAll(' ', ''),
|
||||
"addedForId": pdRdId,
|
||||
"products": selectedProducts.map((e) => e.toJson()).toList()
|
||||
@ -116,6 +117,7 @@ class ProductProvider extends ChangeNotifier {
|
||||
|
||||
// Model class for Product
|
||||
class ProductModel {
|
||||
String id; // ID of the product
|
||||
String sku; // SKU of the product
|
||||
String productName; // Name of the product
|
||||
int? sale; // Sale quantity (optional)
|
||||
@ -123,7 +125,9 @@ class ProductModel {
|
||||
|
||||
// Constructor for ProductModel
|
||||
ProductModel(
|
||||
{required this.sku,
|
||||
{
|
||||
required this.id,
|
||||
required this.sku,
|
||||
required this.productName,
|
||||
this.sale,
|
||||
this.inventory});
|
||||
@ -131,6 +135,7 @@ class ProductModel {
|
||||
// Factory method to create a ProductModel from JSON
|
||||
factory ProductModel.fromJson(Map<String, dynamic> json) {
|
||||
return ProductModel(
|
||||
id:json['_id'],
|
||||
sku: json['SKU'],
|
||||
productName: json['ProductName'],
|
||||
sale: json['Sale'],
|
||||
@ -142,6 +147,7 @@ class ProductModel {
|
||||
// Convert ProductModel to JSON format for API requests
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'_id': id,
|
||||
'SKU': sku,
|
||||
'ProductName': productName,
|
||||
'Sale': sale,
|
||||
|
61
lib/provider/task_provider.dart
Normal file
61
lib/provider/task_provider.dart
Normal file
@ -0,0 +1,61 @@
|
||||
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';
|
||||
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 = [];
|
||||
List<PdRdResponseModel> _pdList = [];
|
||||
List<PdRdResponseModel> _rdList = [];
|
||||
List<TaskModel> _taskModelList = [];
|
||||
PdRdResponseModel? _selectedDistributor;
|
||||
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;
|
||||
List<PdRdResponseModel> get pdList => _pdList;
|
||||
List<PdRdResponseModel> get rdList => _rdList;
|
||||
List<TaskModel> get taskModelList => _taskModelList;
|
||||
PdRdResponseModel? get selectedDistributor => _selectedDistributor;
|
||||
|
||||
void setLoading(bool loading) {
|
||||
_isLoading = loading;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Future<void> getAllTaskByDate(DateTime date) async {
|
||||
setLoading(true);
|
||||
try {
|
||||
final String formatedDate = DateFormat('dd/MM/yyyy').format(date);
|
||||
Response response =
|
||||
await _apiClient.get("${ApiUrls.allTaskByDate}?Date=$formatedDate");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -324,7 +324,7 @@ class _ProductBlockState extends State<ProductBlock> {
|
||||
sku: widget.product.sku,
|
||||
productName: widget.product.productName,
|
||||
sale: sale,
|
||||
inventory: inventory,
|
||||
inventory: inventory, id: widget.product.id,
|
||||
));
|
||||
} else {
|
||||
errorMessage = saleError ?? inventoryError;
|
||||
|
153
lib/screens/Announcements_Screen.dart
Normal file
153
lib/screens/Announcements_Screen.dart
Normal file
@ -0,0 +1,153 @@
|
||||
import 'package:cheminova/provider/Announcement_Provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cheminova/widgets/common_background.dart';
|
||||
import 'package:cheminova/widgets/common_drawer.dart';
|
||||
import 'package:cheminova/widgets/common_app_bar.dart';
|
||||
import 'package:cheminova/widgets/common_elevated_button.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../models/Announcements_Response.dart';
|
||||
|
||||
// Main screen that displays notifications
|
||||
class AnnouncementsScreen extends StatefulWidget {
|
||||
const AnnouncementsScreen({super.key});
|
||||
|
||||
@override
|
||||
State<AnnouncementsScreen> createState() => AnnouncementsScreenState();
|
||||
}
|
||||
|
||||
class AnnouncementsScreenState extends State<AnnouncementsScreen> {
|
||||
late AnnouncementProvider _announcementProvider;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// Initialize the NotificationProvider in the state when the screen is created
|
||||
_announcementProvider = AnnouncementProvider();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Use ChangeNotifierProvider to supply NotificationProvider to the widget tree
|
||||
return ChangeNotifierProvider(
|
||||
create: (context) => _announcementProvider,
|
||||
child: CommonBackground(
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
appBar: CommonAppBar(
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
// Pop the screen when the back button is pressed
|
||||
Navigator.pop(context);
|
||||
},
|
||||
icon: Image.asset('assets/Back_attendance.png'),
|
||||
padding: const EdgeInsets.only(right: 20),
|
||||
),
|
||||
],
|
||||
title: const Text('Announcements',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontFamily: 'Anek')),
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
),
|
||||
drawer: const CommonDrawer(),
|
||||
// Consumer listens for changes in the NotificationProvider
|
||||
body: Consumer<AnnouncementProvider>(
|
||||
builder: (context, value, child) => value.isLoading
|
||||
// Display a loading indicator if notifications are still loading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
// Show the list of notifications once loaded
|
||||
: MyListView(value: value),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Function that builds a button for a product
|
||||
Widget buildProductButton(String productName) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 15),
|
||||
child: CommonElevatedButton(
|
||||
borderRadius: 30,
|
||||
width: double.infinity,
|
||||
height: kToolbarHeight - 10,
|
||||
text: productName,
|
||||
backgroundColor: const Color(0xff004791),
|
||||
onPressed: () {
|
||||
// Log when the button is pressed
|
||||
debugPrint('$productName pressed');
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Widget that displays a list of notifications grouped by date
|
||||
class MyListView extends StatelessWidget {
|
||||
final AnnouncementProvider value;
|
||||
|
||||
const MyListView({super.key, required this.value});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Group notifications by their creation date
|
||||
Map<String, List<AnnouncementResponse>> groupedNotifications = {};
|
||||
|
||||
// Iterate over the notification list and group by formatted date
|
||||
for (var notification in value.announcementList.reversed) {
|
||||
String date = DateFormat("dd MMM yyyy").format(DateTime.parse(notification.createdAt.toString()));
|
||||
if (!groupedNotifications.containsKey(date)) {
|
||||
groupedNotifications[date] = [];
|
||||
}
|
||||
groupedNotifications[date]!.add(notification);
|
||||
}
|
||||
|
||||
// Build a ListView for grouped notifications
|
||||
return ListView.builder(
|
||||
|
||||
padding: const EdgeInsets.only(top: 15),
|
||||
itemCount: groupedNotifications.length, // Number of date groups
|
||||
itemBuilder: (context, index) {
|
||||
String date = groupedNotifications.keys.elementAt(index);
|
||||
List<AnnouncementResponse> notificationsForDate = groupedNotifications[date]!;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10, left: 10, right: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Display the date for each group of notifications
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(
|
||||
date,
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
// Display each notification in an expandable tile
|
||||
...notificationsForDate.map((item) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: ExpansionTile(
|
||||
collapsedBackgroundColor: Colors.white,
|
||||
backgroundColor: Colors.white,
|
||||
trailing: const SizedBox.shrink(), // Remove trailing icon
|
||||
title: const Text(
|
||||
"New Announcement",
|
||||
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w500),
|
||||
),
|
||||
subtitle: Text(item.message),
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -121,7 +121,7 @@ class _UpdateInventoryTaskScreenState extends State<UpdateInventoryTaskScreen> {
|
||||
distributorType: tasksList.addedFor!, // Pass distributor type
|
||||
inventoryId: tasksList.sId!, // Pass inventory ID
|
||||
tradeName: tasksList.tradeName ?? '', // Pass trader name
|
||||
pdRdId: tasksList.sId!, // Pass PD/RD ID
|
||||
pdRdId: tasksList.addedForId!, // Pass PD/RD ID
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -63,121 +63,124 @@ class _AddSalesProductScreenState extends State<AddSalesProductScreen> {
|
||||
return PopScope(
|
||||
canPop: true,
|
||||
child: CommonBackground(// Common background for the screen
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
appBar: CommonAppBar(// Custom AppBar with back button and title
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
icon: Image.asset('assets/Back_attendance.png'),
|
||||
padding: const EdgeInsets.only(right: 20),
|
||||
)
|
||||
],
|
||||
title: Text(
|
||||
'${widget.distributorType}\n${widget.tradeName}',
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontFamily: 'Anek',
|
||||
child: Form(
|
||||
key: formKey,
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
appBar: CommonAppBar(// Custom AppBar with back button and title
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
icon: Image.asset('assets/Back_attendance.png'),
|
||||
padding: const EdgeInsets.only(right: 20),
|
||||
)
|
||||
],
|
||||
title: Text(
|
||||
'${widget.distributorType}\n${widget.tradeName}',
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontFamily: 'Anek',
|
||||
),
|
||||
),
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
),
|
||||
drawer: const CommonDrawer(),
|
||||
bottomNavigationBar: Consumer<AddSalesProvider>(
|
||||
builder: (context, value, child) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Align(
|
||||
alignment: value.tasksList.isEmpty
|
||||
? Alignment.center
|
||||
: Alignment.bottomCenter,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [// Floating button to add products
|
||||
FloatingActionButton.extended(
|
||||
onPressed: () => _showProductSelectionBottomSheet(context),
|
||||
backgroundColor: Colors.white,
|
||||
icon: const Icon(Icons.add, color: Colors.black),
|
||||
label: const Text('Add Products', style: TextStyle(color: Colors.black)),
|
||||
),
|
||||
if (value.selectedProducts.isNotEmpty) ...[
|
||||
const SizedBox(height: 16.0),
|
||||
// Submit button that appears after products are selected
|
||||
CommonElevatedButton(
|
||||
borderRadius: 30,
|
||||
width: double.infinity,
|
||||
height: kToolbarHeight - 10,
|
||||
text: 'SUBMIT',
|
||||
backgroundColor: const Color(0xff004791),
|
||||
onPressed: () => _submitProducts(value),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
),
|
||||
drawer: const CommonDrawer(),
|
||||
bottomNavigationBar: Consumer<AddSalesProvider>(
|
||||
builder: (context, value, child) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Align(
|
||||
alignment: value.tasksList.isEmpty
|
||||
? Alignment.center
|
||||
: Alignment.bottomCenter,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [// Floating button to add products
|
||||
FloatingActionButton.extended(
|
||||
onPressed: () => _showProductSelectionBottomSheet(context),
|
||||
backgroundColor: Colors.white,
|
||||
icon: const Icon(Icons.add, color: Colors.black),
|
||||
label: const Text('Add Products', style: TextStyle(color: Colors.black)),
|
||||
),
|
||||
if (value.selectedProducts.isNotEmpty) ...[
|
||||
const SizedBox(height: 16.0),
|
||||
// Submit button that appears after products are selected
|
||||
CommonElevatedButton(
|
||||
borderRadius: 30,
|
||||
width: double.infinity,
|
||||
height: kToolbarHeight - 10,
|
||||
text: 'SUBMIT',
|
||||
backgroundColor: const Color(0xff004791),
|
||||
onPressed: () => _submitProducts(value),
|
||||
body: Consumer<AddSalesProvider>(// Displays the list of selected products or loading indicator
|
||||
builder: (context, value, child) {
|
||||
return Stack(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: TextFormField(// Date selection field
|
||||
controller: dateController,
|
||||
readOnly: true,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Date',
|
||||
fillColor: Colors.white,
|
||||
filled: true,
|
||||
border: InputBorder.none,
|
||||
suffixIcon: Icon(Icons.calendar_today),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Display selected products list
|
||||
if (value.selectedProducts.isNotEmpty)
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: value.selectedProducts.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ProductBlock(
|
||||
onUpdate: (updatedProduct) {
|
||||
setState(() {
|
||||
value.selectedProducts[index] = updatedProduct;
|
||||
});
|
||||
},
|
||||
onRemove: () {
|
||||
setState(() {
|
||||
value.selectedProducts.removeAt(index);
|
||||
});
|
||||
},
|
||||
product: value.selectedProducts[index],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: Consumer<AddSalesProvider>(// Displays the list of selected products or loading indicator
|
||||
builder: (context, value, child) {
|
||||
return Stack(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: TextFormField(// Date selection field
|
||||
controller: dateController,
|
||||
readOnly: true,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Date',
|
||||
fillColor: Colors.white,
|
||||
filled: true,
|
||||
border: InputBorder.none,
|
||||
suffixIcon: Icon(Icons.calendar_today),
|
||||
),
|
||||
),
|
||||
// Loading indicator
|
||||
if (value.isLoading)
|
||||
Container(
|
||||
color: Colors.black12,
|
||||
child: const Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
// Display selected products list
|
||||
if (value.selectedProducts.isNotEmpty)
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: value.selectedProducts.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ProductBlock(
|
||||
onUpdate: (updatedProduct) {
|
||||
setState(() {
|
||||
value.selectedProducts[index] = updatedProduct;
|
||||
});
|
||||
},
|
||||
onRemove: () {
|
||||
setState(() {
|
||||
value.selectedProducts.removeAt(index);
|
||||
});
|
||||
},
|
||||
product: value.selectedProducts[index],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// Loading indicator
|
||||
if (value.isLoading)
|
||||
Container(
|
||||
color: Colors.black12,
|
||||
child: const Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -1,43 +1,74 @@
|
||||
import 'package:cheminova/models/task_model.dart';
|
||||
import 'package:cheminova/provider/task_provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:table_calendar/table_calendar.dart';
|
||||
import '../widgets/common_app_bar.dart'; // Custom AppBar widget
|
||||
import '../widgets/common_background.dart'; // Custom background widget
|
||||
import '../widgets/common_drawer.dart'; // Custom drawer widget
|
||||
import '../widgets/common_app_bar.dart';
|
||||
import '../widgets/common_background.dart';
|
||||
import '../widgets/common_drawer.dart';
|
||||
|
||||
// Global variables to track the focused and selected dates in the calendar
|
||||
DateTime _focusedDay = DateTime.now();
|
||||
DateTime? _selectedDay = DateTime.now();
|
||||
DateTime _selectedDay = DateTime.now();
|
||||
|
||||
// Main Calendar screen
|
||||
class CalendarScreen extends StatelessWidget {
|
||||
class CalendarScreen extends StatefulWidget {
|
||||
const CalendarScreen({super.key});
|
||||
|
||||
@override
|
||||
State<CalendarScreen> createState() => _CalendarScreenState();
|
||||
}
|
||||
|
||||
class _CalendarScreenState extends State<CalendarScreen> {
|
||||
late TaskProvider taskProvider;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
taskProvider = TaskProvider();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CommonBackground( // Wrapper for common background styling
|
||||
child: Scaffold(
|
||||
appBar: CommonAppBar( // Custom AppBar
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context); // Go back to the previous screen
|
||||
},
|
||||
icon: Image.asset('assets/Back_attendance.png'),
|
||||
padding: const EdgeInsets.only(right: 20),
|
||||
return ChangeNotifierProvider(
|
||||
create: (context) => taskProvider,
|
||||
child: Consumer<TaskProvider>(
|
||||
builder: (context, value, child) => CommonBackground(
|
||||
child: Scaffold(
|
||||
appBar: CommonAppBar(
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
icon: Image.asset('assets/Back_attendance.png'),
|
||||
padding: const EdgeInsets.only(right: 20),
|
||||
),
|
||||
],
|
||||
title: const Text('Calendar'),
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
),
|
||||
backgroundColor: Colors.transparent,
|
||||
drawer: const CommonDrawer(),
|
||||
body: Stack(
|
||||
children: [
|
||||
Column(children: [
|
||||
const CalendarWidget(),
|
||||
TaskList(taskProvider: value)
|
||||
]),
|
||||
if (taskProvider.isLoading)
|
||||
Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withOpacity(0.2),
|
||||
),
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
title: const Text('Calendar'), // Title of the AppBar
|
||||
backgroundColor: Colors.transparent, // Transparent background for the AppBar
|
||||
elevation: 0,
|
||||
),
|
||||
backgroundColor: Colors.transparent, // Transparent background for the Scaffold
|
||||
drawer: const CommonDrawer(), // Custom drawer widget
|
||||
body: const SingleChildScrollView( // Scrollable view to accommodate the calendar and events list
|
||||
child: Column(
|
||||
children: [
|
||||
CalendarWidget(), // Calendar widget to show calendar dates
|
||||
EventsList(), // List of events associated with the selected date
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -45,7 +76,6 @@ class CalendarScreen extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
// Calendar widget that shows the calendar dates
|
||||
class CalendarWidget extends StatefulWidget {
|
||||
const CalendarWidget({super.key});
|
||||
|
||||
@ -56,117 +86,142 @@ class CalendarWidget extends StatefulWidget {
|
||||
class _CalendarWidgetState extends State<CalendarWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card( // Card UI to display the calendar inside
|
||||
margin: const EdgeInsets.all(16), // Margin around the card
|
||||
return Card(
|
||||
margin: const EdgeInsets.all(16),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16), // Padding inside the card
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start, // Align items to the left
|
||||
children: [
|
||||
const Text(
|
||||
'Calendar',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), // Calendar heading
|
||||
),
|
||||
const Text(
|
||||
'Month/Year',
|
||||
style: TextStyle(fontSize: 14, color: Colors.grey), // Display current month and year
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
TableCalendar( // TableCalendar widget to show date selection
|
||||
firstDay: DateTime.utc(1900, 5, 1), // Earliest selectable date
|
||||
lastDay: DateTime.utc(2900, 5, 1), // Latest selectable date
|
||||
focusedDay: _focusedDay, // Currently focused day
|
||||
selectedDayPredicate: (day) {
|
||||
return isSameDay(_selectedDay, day); // Highlight selected day
|
||||
},
|
||||
onDaySelected: (selectedDay, focusedDay) {
|
||||
setState(() { // Update selected and focused days
|
||||
_selectedDay = selectedDay;
|
||||
_focusedDay = focusedDay;
|
||||
});
|
||||
},
|
||||
onPageChanged: (focusedDay) {
|
||||
_focusedDay = focusedDay; // Change focused day when calendar page changes
|
||||
},
|
||||
),
|
||||
],
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: TableCalendar(
|
||||
firstDay: DateTime.utc(1900, 5, 1),
|
||||
lastDay: DateTime.utc(2900, 5, 1),
|
||||
focusedDay: _focusedDay,
|
||||
selectedDayPredicate: (day) {
|
||||
return isSameDay(_selectedDay, day);
|
||||
},
|
||||
onDaySelected: (selectedDay, focusedDay) {
|
||||
setState(() {
|
||||
_selectedDay = selectedDay;
|
||||
_focusedDay = focusedDay;
|
||||
context.read<TaskProvider>().getAllTaskByDate(_selectedDay);
|
||||
});
|
||||
},
|
||||
onPageChanged: (focusedDay) {
|
||||
_focusedDay = focusedDay;
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Widget to display a list of events
|
||||
class EventsList extends StatelessWidget {
|
||||
const EventsList({super.key});
|
||||
class TaskList extends StatefulWidget {
|
||||
final TaskProvider taskProvider;
|
||||
|
||||
const TaskList({super.key, required this.taskProvider});
|
||||
|
||||
@override
|
||||
State<TaskList> createState() => _TaskListState();
|
||||
}
|
||||
|
||||
class _TaskListState extends State<TaskList> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
widget.taskProvider.getAllTaskByDate(_selectedDay);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Card( // Card UI for the event list
|
||||
margin: EdgeInsets.all(16), // Margin around the card
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16), // Padding inside the card
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start, // Align items to the left
|
||||
children: [
|
||||
Text(
|
||||
'Events List', // Heading for the events list
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
return (widget.taskProvider.taskModelList.isEmpty)
|
||||
? Container(
|
||||
alignment: Alignment.center,
|
||||
child: const Text('No task found',
|
||||
style: TextStyle(fontSize: 20, color: Colors.white)),
|
||||
)
|
||||
: Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: widget.taskProvider.taskModelList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return _taskView(
|
||||
task: widget.taskProvider.taskModelList[index]);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
// Display individual event items
|
||||
EventItem(
|
||||
date: '10-06-2024',
|
||||
event: 'Meeting with Territory Manager',
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
EventItem(
|
||||
date: '10-06-2024',
|
||||
event: 'Sales Data Review',
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _customContainer({required Widget child}) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.white),
|
||||
color: const Color(0xffB4D1E5).withOpacity(0.8),
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Widget for displaying individual event items
|
||||
class EventItem extends StatelessWidget {
|
||||
final String date; // Event date
|
||||
final String event; // Event description
|
||||
|
||||
const EventItem({super.key, required this.date, required this.event});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(12), // Padding inside the event container
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue[50], // Light blue background for the event item
|
||||
borderRadius: BorderRadius.circular(8), // Rounded corners for the container
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start, // Align items to the left
|
||||
children: [
|
||||
Text('Date: $date'), // Display event date
|
||||
Text(
|
||||
'Event: $event', // Display event description
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
Widget _taskView({required TaskModel task}) {
|
||||
final formattedDate = DateFormat('dd/MM/yyyy').format(task.taskDueDate);
|
||||
return Column(
|
||||
children: [
|
||||
_customContainer(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Assigned to: ${task.taskAssignedTo.name}",
|
||||
style: const TextStyle(
|
||||
fontFamily: 'Anek',
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
"Task: ${task.task}",
|
||||
style: const TextStyle(
|
||||
fontFamily: 'Anek',
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
if (task.addedFor != null) ...{
|
||||
task.addedFor == 'PrincipalDistributor'
|
||||
? Text("PD: ${task.tradename}")
|
||||
: Text("RD: ${task.tradename}"),
|
||||
const SizedBox(height: 5),
|
||||
},
|
||||
Text(
|
||||
'Status: ${task.taskStatus}',
|
||||
style: const TextStyle(
|
||||
fontFamily: 'Anek',
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
if (task.note != null) ...{
|
||||
Text(
|
||||
'Note: ${task.note}',
|
||||
style: const TextStyle(
|
||||
fontFamily: 'Anek',
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
},
|
||||
Text(
|
||||
'Deadline: $formattedDate',
|
||||
style: const TextStyle(
|
||||
fontFamily: 'Anek',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
ElevatedButton( // Button to view event details
|
||||
onPressed: () {
|
||||
// Add view details functionality here
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white, // Text color
|
||||
backgroundColor: Colors.blue[800], // Button background color
|
||||
),
|
||||
child: const Text('VIEW DETAILS'), // Button label
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:cheminova/notification_services.dart';
|
||||
import 'package:cheminova/provider/home_provider.dart';
|
||||
import 'package:cheminova/screens/Announcements_Screen.dart';
|
||||
import 'package:cheminova/screens/Update_inventorytask_screen.dart';
|
||||
import 'package:cheminova/screens/calendar_screen.dart';
|
||||
import 'package:cheminova/screens/daily_tasks_screen.dart';
|
||||
@ -215,6 +216,20 @@ class _HomePageState extends State<HomePage> {
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
_buildCustomCard(
|
||||
'Announcements',
|
||||
"View Announcements",
|
||||
screenWidth,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const AnnouncementsScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
// Row containing cards for calendar and products manual
|
||||
Row(
|
||||
children: [
|
||||
|
@ -6,22 +6,27 @@ class ApiUrls {
|
||||
static const String getPdUrl = 'kyc/get-pd';
|
||||
static const String createCollectKycUrl = '${baseUrl}kyc/create';
|
||||
static const String getProfileUrl = '${baseUrl}salescoordinator/my-profile';
|
||||
static const String changePasswordUrl = '${baseUrl}salescoordinator/password/update';
|
||||
static const String forgotPasswordUrl = '${baseUrl}salescoordinator/forgot-password';
|
||||
static const String leaveAttendance = '${baseUrl}v1/markleave/salescoordinator';
|
||||
static const String changePasswordUrl =
|
||||
'${baseUrl}salescoordinator/password/update';
|
||||
static const String forgotPasswordUrl =
|
||||
'${baseUrl}salescoordinator/forgot-password';
|
||||
static const String leaveAttendance =
|
||||
'${baseUrl}v1/markleave/salescoordinator';
|
||||
static const String logOutUrl = '${baseUrl}salescoordinator/logout';
|
||||
static const String rejectedApplication = '${baseUrl}kyc/getAllrejected';
|
||||
static const String notificationUrl = '${baseUrl}/get-notification-sc';
|
||||
static const String fcmUrl = '${baseUrl}kyc/save-fcm-sc';
|
||||
static const String getProducts = '${baseUrl}product/getAll/user';
|
||||
static const String getPdRdUrl = '${baseUrl}inventory/distributors-SC/';
|
||||
static const String submitProductUrl = '${baseUrl}inventory/add-SC';
|
||||
static const String selectTaskUrl = '${baseUrl}task/tasks';
|
||||
static const String dailyTaskUrl = '${baseUrl}task/tasks/';
|
||||
static const String kycSelectTaskUrl = '${baseUrl}task/task/type/Collect KYC';
|
||||
static const String updateTaskInventoryUrl = '${baseUrl}task/update-task-status/';
|
||||
static const String getProductsManual = '${baseUrl}productmanual/getall';
|
||||
static const String salesTaskUrl = '${baseUrl}product/getAll/user/';
|
||||
static const String postSalesTaskUrl = '${baseUrl}sales/add-SC';
|
||||
static const String submitVisitUrl = '${baseUrl}visit';
|
||||
static const String rejectedApplication = '${baseUrl}kyc/getAllrejected';
|
||||
static const String notificationUrl = '${baseUrl}/get-notification-sc';
|
||||
static const String fcmUrl = '${baseUrl}kyc/save-fcm-sc';
|
||||
static const String getProducts = '${baseUrl}product/getAll/user';
|
||||
static const String getPdRdUrl = '${baseUrl}inventory/distributors-SC/';
|
||||
static const String submitProductUrl = '${baseUrl}inventory/add';
|
||||
static const String selectTaskUrl = '${baseUrl}task/tasks';
|
||||
static const String dailyTaskUrl = '${baseUrl}task/tasks/';
|
||||
static const String kycSelectTaskUrl = '${baseUrl}task/task/type/Collect KYC';
|
||||
static const String updateTaskInventoryUrl = '${baseUrl}task/update-task-status/';
|
||||
static const String getProductsManual = '${baseUrl}productmanual/getall';
|
||||
static const String salesTaskUrl = '${baseUrl}product/getAll/user/';
|
||||
static const String postSalesTaskUrl = '${baseUrl}sales/add-SC';
|
||||
static const String submitVisitUrl = '${baseUrl}visit';
|
||||
static const String allTaskByDate = '${baseUrl}task/alltask';
|
||||
static const String announcementUrl = '${baseUrl}announcement/SCs';
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user