Commit b38d986d authored by Sai Srinivas's avatar Sai Srinivas
Browse files

23-07-2025 By Sai Srinivas

CRM Lead Details, Generate Quotation & Followup and Prospect List.
parent c0252747
......@@ -328,6 +328,7 @@ class LeadProducts {
String? productId;
String? qty;
String? price;
String? prodTotalPrice;
String? date;
String? isDel;
String? isExists;
......@@ -341,6 +342,7 @@ class LeadProducts {
this.productId,
this.qty,
this.price,
this.prodTotalPrice,
this.date,
this.isDel,
this.isExists,
......@@ -354,6 +356,7 @@ class LeadProducts {
productId = json['product_id'];
qty = json['qty'];
price = json['price'];
prodTotalPrice = json['prod_total_price'];
date = json['date'];
isDel = json['is_del'];
isExists = json['is_exists'];
......@@ -369,6 +372,7 @@ class LeadProducts {
data['product_id'] = this.productId;
data['qty'] = this.qty;
data['price'] = this.price;
data['prod_total_price'] = this.prodTotalPrice;
data['date'] = this.date;
data['is_del'] = this.isDel;
data['is_exists'] = this.isExists;
......
class crmAddFollowUpResponse {
String? redirectTo;
String? error;
String? message;
int? sessionExists;
crmAddFollowUpResponse(
{this.redirectTo, this.error, this.message, this.sessionExists});
crmAddFollowUpResponse.fromJson(Map<String, dynamic> json) {
redirectTo = json['redirect_to'];
error = json['error'];
message = json['message'];
sessionExists = json['session_exists'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['redirect_to'] = this.redirectTo;
data['error'] = this.error;
data['message'] = this.message;
data['session_exists'] = this.sessionExists;
return data;
}
}
class crmDashboardResponse {
Hotleads? hotleads;
Hotleads? pendingTasks;
Hotleads? coldleads;
Hotleads? warmleads;
Hotleads? totalleads;
Hotleads? openleads;
Hotleads? visits;
Hotleads? calls;
Hotleads? quote;
Hotleads? orderlost;
Hotleads? norequirement;
Hotleads? openEnquiries;
List<NearbyLeads>? nearbyLeads;
String? error;
String? message;
int? sessionExists;
crmDashboardResponse(
{this.hotleads,
this.pendingTasks,
this.coldleads,
this.warmleads,
this.totalleads,
this.openleads,
this.visits,
this.calls,
this.quote,
this.orderlost,
this.norequirement,
this.openEnquiries,
this.nearbyLeads,
this.error,
this.message});
this.message,
this.sessionExists});
crmDashboardResponse.fromJson(Map<String, dynamic> json) {
hotleads = json['hotleads'] != null
? new Hotleads.fromJson(json['hotleads'])
: null;
pendingTasks = json['pending_tasks'] != null
? new Hotleads.fromJson(json['pending_tasks'])
: null;
coldleads = json['coldleads'] != null
? new Hotleads.fromJson(json['coldleads'])
: null;
......@@ -33,6 +50,13 @@ class crmDashboardResponse {
totalleads = json['totalleads'] != null
? new Hotleads.fromJson(json['totalleads'])
: null;
openleads = json['openleads'] != null
? new Hotleads.fromJson(json['openleads'])
: null;
visits =
json['visits'] != null ? new Hotleads.fromJson(json['visits']) : null;
calls = json['calls'] != null ? new Hotleads.fromJson(json['calls']) : null;
quote = json['quote'] != null ? new Hotleads.fromJson(json['quote']) : null;
orderlost = json['orderlost'] != null
? new Hotleads.fromJson(json['orderlost'])
: null;
......@@ -42,8 +66,15 @@ class crmDashboardResponse {
openEnquiries = json['open_enquiries'] != null
? new Hotleads.fromJson(json['open_enquiries'])
: null;
if (json['nearby_leads'] != null) {
nearbyLeads = <NearbyLeads>[];
json['nearby_leads'].forEach((v) {
nearbyLeads!.add(new NearbyLeads.fromJson(v));
});
}
error = json['error'];
message = json['message'];
sessionExists = json['session_exists'];
}
Map<String, dynamic> toJson() {
......@@ -51,6 +82,9 @@ class crmDashboardResponse {
if (this.hotleads != null) {
data['hotleads'] = this.hotleads!.toJson();
}
if (this.pendingTasks != null) {
data['pending_tasks'] = this.pendingTasks!.toJson();
}
if (this.coldleads != null) {
data['coldleads'] = this.coldleads!.toJson();
}
......@@ -60,6 +94,18 @@ class crmDashboardResponse {
if (this.totalleads != null) {
data['totalleads'] = this.totalleads!.toJson();
}
if (this.openleads != null) {
data['openleads'] = this.openleads!.toJson();
}
if (this.visits != null) {
data['visits'] = this.visits!.toJson();
}
if (this.calls != null) {
data['calls'] = this.calls!.toJson();
}
if (this.quote != null) {
data['quote'] = this.quote!.toJson();
}
if (this.orderlost != null) {
data['orderlost'] = this.orderlost!.toJson();
}
......@@ -69,8 +115,12 @@ class crmDashboardResponse {
if (this.openEnquiries != null) {
data['open_enquiries'] = this.openEnquiries!.toJson();
}
if (this.nearbyLeads != null) {
data['nearby_leads'] = this.nearbyLeads!.map((v) => v.toJson()).toList();
}
data['error'] = this.error;
data['message'] = this.message;
data['session_exists'] = this.sessionExists;
return data;
}
}
......@@ -124,3 +174,116 @@ class Filter {
return data;
}
}
class NearbyLeads {
String? id;
String? ownerId;
String? accId;
String? accManagerId;
String? status;
String? openStatus;
String? date;
String? closeDate;
String? closereason;
String? competitor;
String? orderGainId;
String? loc;
String? isExists;
String? createdDatetime;
String? updatedDatetime;
String? followupFunction;
String? name;
String? product;
String? contName;
String? address;
String? mob1;
String? mob2;
String? tel;
String? email;
String? distance;
NearbyLeads(
{this.id,
this.ownerId,
this.accId,
this.accManagerId,
this.status,
this.openStatus,
this.date,
this.closeDate,
this.closereason,
this.competitor,
this.orderGainId,
this.loc,
this.isExists,
this.createdDatetime,
this.updatedDatetime,
this.followupFunction,
this.name,
this.product,
this.contName,
this.address,
this.mob1,
this.mob2,
this.tel,
this.email,
this.distance});
NearbyLeads.fromJson(Map<String, dynamic> json) {
id = json['id'];
ownerId = json['owner_id'];
accId = json['acc_id'];
accManagerId = json['acc_manager_id'];
status = json['status'];
openStatus = json['open_status'];
date = json['date'];
closeDate = json['close_date'];
closereason = json['closereason'];
competitor = json['competitor'];
orderGainId = json['order_gain_id'];
loc = json['loc'];
isExists = json['is_exists'];
createdDatetime = json['created_datetime'];
updatedDatetime = json['updated_datetime'];
followupFunction = json['followup_function'];
name = json['name'];
product = json['product'];
contName = json['cont_name'];
address = json['address'];
mob1 = json['mob1'];
mob2 = json['mob2'];
tel = json['tel'];
email = json['email'];
distance = json['distance'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['owner_id'] = this.ownerId;
data['acc_id'] = this.accId;
data['acc_manager_id'] = this.accManagerId;
data['status'] = this.status;
data['open_status'] = this.openStatus;
data['date'] = this.date;
data['close_date'] = this.closeDate;
data['closereason'] = this.closereason;
data['competitor'] = this.competitor;
data['order_gain_id'] = this.orderGainId;
data['loc'] = this.loc;
data['is_exists'] = this.isExists;
data['created_datetime'] = this.createdDatetime;
data['updated_datetime'] = this.updatedDatetime;
data['followup_function'] = this.followupFunction;
data['name'] = this.name;
data['product'] = this.product;
data['cont_name'] = this.contName;
data['address'] = this.address;
data['mob1'] = this.mob1;
data['mob2'] = this.mob2;
data['tel'] = this.tel;
data['email'] = this.email;
data['distance'] = this.distance;
return data;
}
}
......@@ -3,9 +3,10 @@ class crmLeadDetailsGenerateQuotationViewResponse {
List<LeadProducts>? leadProducts;
String? error;
String? message;
int? sessionExists;
crmLeadDetailsGenerateQuotationViewResponse(
{this.quoteDetails, this.leadProducts, this.error, this.message});
{this.quoteDetails, this.leadProducts, this.error, this.message,this.sessionExists});
crmLeadDetailsGenerateQuotationViewResponse.fromJson(
Map<String, dynamic> json) {
......@@ -20,6 +21,7 @@ class crmLeadDetailsGenerateQuotationViewResponse {
}
error = json['error'];
message = json['message'];
sessionExists = json['session_exists'];
}
Map<String, dynamic> toJson() {
......@@ -33,6 +35,7 @@ class crmLeadDetailsGenerateQuotationViewResponse {
}
data['error'] = this.error;
data['message'] = this.message;
data['session_exists'] = this.sessionExists;
return data;
}
}
......@@ -84,6 +87,7 @@ class LeadProducts {
String? productId;
String? qty;
String? price;
String? prodTotalPrice;
String? date;
String? isDel;
String? isExists;
......@@ -97,6 +101,7 @@ class LeadProducts {
this.productId,
this.qty,
this.price,
this.prodTotalPrice,
this.date,
this.isDel,
this.isExists,
......@@ -110,6 +115,7 @@ class LeadProducts {
productId = json['product_id'];
qty = json['qty'];
price = json['price'];
prodTotalPrice = json['prod_total_price'];
date = json['date'];
isDel = json['is_del'];
isExists = json['is_exists'];
......@@ -125,6 +131,7 @@ class LeadProducts {
data['product_id'] = this.productId;
data['qty'] = this.qty;
data['price'] = this.price;
data['prod_total_price'] = this.prodTotalPrice;
data['date'] = this.date;
data['is_del'] = this.isDel;
data['is_exists'] = this.isExists;
......
......@@ -3,6 +3,9 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:generp/Models/crmModels/crmDashboardResponse.dart';
import 'package:generp/Utils/app_colors.dart';
import 'package:geolocator/geolocator.dart';
import 'package:geolocator/geolocator.dart' as geo_location;
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
......@@ -13,37 +16,20 @@ import '../../services/api_calling.dart';
import '../HomeScreenNotifier.dart';
class Crmdashboardprovider extends ChangeNotifier {
TextEditingController nextAppointmentDateController = TextEditingController();
String _googleApikey = "AIzaSyBGzvgMMKwPBAANTwaoRsAnrCpiWCj8wVs";
TextEditingController searchController = TextEditingController();
List<PagesAccessible> _accessPages = [];
List<PagesAccessible> get accessPages => _accessPages;
List<PendingTasks> _pendingTasks = [];
List<PendingTasks> _pendingTasksList = [];
List<PendingTasks> get pendingTasksLists => _pendingTasks;
List<PendingTasks> get pendingTasksLists => _pendingTasksList;
List<Accounts> _accountsList = [];
List<Leads> _leadsList = [];
List<Enquires> _enquiresList = [];
TimeOfDay _selectedTime = TimeOfDay.now();
String _formattedTime = "";
String? _selectedFollowupType;
String? _selectedLeadStatus;
String? _nextAppointmentStatus;
String? _selectNextAppointmentType;
DateTime? _date;
String? _formattedDate;
String? _dateError;
TimeOfDay get selectedTime => _selectedTime;
String get formattedTime => _formattedTime;
String? get selectedFollowupType => _selectedFollowupType;
String? get selectedLeadStatus => _selectedLeadStatus;
String? get nextAppointmentStatus => _nextAppointmentStatus;
String? get selectNextAppointmentType => _selectNextAppointmentType;
LatLng? currentLocationLatLng;
String latlongs = "";
List<Accounts> get accountsList => _accountsList;
......@@ -51,24 +37,54 @@ class Crmdashboardprovider extends ChangeNotifier {
List<Enquires> get enquiresList => _enquiresList;
List<NearbyLeads> _nearByLeads = [];
List<NearbyLeads> get nearByLeads => _nearByLeads;
Hotleads _hotleads = Hotleads();
Hotleads get hotleads => _hotleads;
Hotleads _pendingTasks = Hotleads();
Hotleads get pendingTasks => _pendingTasks;
Hotleads _coldleads = Hotleads();
Hotleads get coldleads => _coldleads;
Hotleads _warmleads = Hotleads();
Hotleads get warmleads => _warmleads;
Hotleads _totalleads = Hotleads();
Hotleads get totalleads => _totalleads;
Hotleads _openleads = Hotleads();
Hotleads get openleads => _openleads;
Hotleads _visits = Hotleads();
Hotleads get visits => _visits;
Hotleads _calls = Hotleads();
Hotleads get calls => _calls;
Hotleads _quote = Hotleads();
Hotleads get quote => _quote;
Hotleads _orderlost = Hotleads();
Hotleads get orderlost => _orderlost;
Hotleads _norequirement = Hotleads();
Hotleads get norequirement => _norequirement;
Hotleads _openEnquiries = Hotleads();
Hotleads get openEnquiries => _openEnquiries;
......@@ -77,25 +93,7 @@ class Crmdashboardprovider extends ChangeNotifier {
List<Hotleads> get allLeads => _allLeads;
set selectedFollowupType(String? value){
_selectedFollowupType = value;
notifyListeners();
}
set selectedLeadStatus(String? value){
_selectedLeadStatus = value;
notifyListeners();
}
set nextAppointmentStatus(String? value){
_nextAppointmentStatus = value;
notifyListeners();
}
set selectNextAppointmentType(String? value){
_selectNextAppointmentType = value;
notifyListeners();
}
Future<void> accessPagesAPIFunction(context) async {
try {
......@@ -116,47 +114,82 @@ class Crmdashboardprovider extends ChangeNotifier {
} catch (e, s) {}
}
Future<void> crmDashboardAPIFunction(
context,
mode,
from,
to,
teamemployee,
) async {
Future<void> getCurrentLocation(context) async {
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: geo_location.LocationAccuracy.high,
);
currentLocationLatLng = LatLng(position.latitude, position.longitude);
print("Current Loc: ${currentLocationLatLng}");
latlongs = '${position.latitude},${position.longitude}';
print("latlongs : ${latlongs}");
notifyListeners();
crmDashboardAPIFunction(context);
} catch (e) {
print("Error getting current location: $e");
}
}
Future<void> crmDashboardAPIFunction(context) async {
try {
var HomeProv = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.crmDashboardAPI(
HomeProv.empId,
HomeProv.session,
mode,
from,
to,
teamemployee,
latlongs,
);
if (data != null) {
if (data.error == "0") {
_hotleads = data.hotleads!;
_pendingTasks = data.pendingTasks!;
_coldleads = data.coldleads!;
_warmleads = data.warmleads!;
_totalleads = data.totalleads!;
_openleads = data.openleads!;
_visits = data.visits!;
_calls = data.calls!;
_quote = data.quote!;
_orderlost = data.orderlost!;
_norequirement = data.norequirement!;
_openEnquiries = data.openEnquiries!;
_allLeads = [
_openleads,
_quote,
_pendingTasks,
_visits,
_calls,
_hotleads,
_coldleads,
_warmleads,
_totalleads,
_orderlost,
_norequirement,
_openEnquiries,
];
_nearByLeads = data.nearbyLeads!;
notifyListeners();
}
}
} catch (e, s) {}
}
String getStaticMapUrl(double lat, double lng) {
const apiKey = 'YOUR_GOOGLE_MAPS_API_KEY';
const zoom = 15;
const size = '400x400';
return 'https://maps.googleapis.com/maps/api/staticmap?center=$lat,$lng&zoom=$zoom&size=$size&key=$_googleApikey';
}
String getSimpleOSMImage(double lat, double lng) {
final zoom = 15;
//https://maps.googleapis.com/maps/api/staticmap?center=15.4919328,80.0492584&zoom=15&size=400x400
return 'https://static-maps.yandex.ru/1.x/?ll=$lng,$lat&z=$zoom&size=400,400&l=map&pt=$lng,$lat,pm2rdm';
}
({double lat, double lng}) parseLocation(String loc) {
final parts = loc.split(',');
return (
lat: double.parse(parts[0].trim()),
lng: double.parse(parts[1].trim()),
);
}
Future<void> crmPendingTasksAPIFunction(context) async {
try {
var HomeProv = Provider.of<HomescreenNotifier>(context, listen: false);
......@@ -166,7 +199,7 @@ class Crmdashboardprovider extends ChangeNotifier {
);
if (data != null) {
if (data.error == "0") {
_pendingTasks = data.pendingTasks!;
_pendingTasksList = data.pendingTasks!;
notifyListeners();
}
}
......@@ -192,117 +225,4 @@ class Crmdashboardprovider extends ChangeNotifier {
} catch (e, s) {}
}
set formattedDate(String? value) {
_formattedDate = value;
nextAppointmentDateController.text = _formattedDate!;
_dateError = null;
notifyListeners();
}
set dateError(value){
_dateError = value;
notifyListeners();
}
void setDate(DateTime newDate) {
_date = newDate;
_formattedDate = DateFormat('yyyy-MM-dd').format(newDate);
nextAppointmentDateController.text = _formattedDate!;
_dateError = null;
notifyListeners();
}
Future<void> selectTime(BuildContext context) async {
final TimeOfDay? picked = await showTimePicker(
context: context,
initialTime: _selectedTime,
);
if (picked != null && picked != _selectedTime) _selectedTime = picked;
_formattedTime =
_selectedTime.hour.toString() + ":" + _selectedTime.minute.toString();
notifyListeners();
}
String formatTime(int hour, int minute) {
String period = (hour >= 12) ? 'pm' : 'am';
if (hour == 0) {
hour = 12;
} else if (hour > 12) {
hour -= 12;
}
String formattedHour = (hour < 10) ? '0$hour' : '$hour';
String formattedMinute = (minute < 10) ? '0$minute' : '$minute';
print("formattedTime: $formattedHour:$formattedMinute $period");
return '$formattedHour:$formattedMinute $period';
}
void showDatePickerDialog(BuildContext context) {
showCupertinoModalPopup<void>(
context: context,
builder:
(BuildContext context) => Container(
height: 216,
padding: const EdgeInsets.only(top: 6.0),
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
color: CupertinoColors.systemBackground.resolveFrom(context),
child: SafeArea(
top: false,
child: Column(
children: [
Expanded(
flex: 1,
child: SizedBox(
height: 40,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CupertinoButton(
child: Text(
'Cancel',
style: TextStyle(fontFamily: "JakartaMedium",color: AppColors.app_blue),
),
onPressed: () {
Navigator.pop(context);
},
),
CupertinoButton(
child: Text(
'Done',
style: TextStyle(fontFamily: "JakartaMedium",color: AppColors.app_blue),
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
),
Expanded(
flex: 3,
child: CupertinoDatePicker(
dateOrder: DatePickerDateOrder.dmy,
initialDateTime: _date ?? DateTime.now(),
mode: CupertinoDatePickerMode.date,
use24hFormat: true,
showDayOfWeek: true,
onDateTimeChanged: (DateTime newDate) {
setDate(newDate);
},
),
),
],
),
),
),
);
}
}
......@@ -6,6 +6,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_download_manager/flutter_download_manager.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:generp/Models/crmModels/crmLeadDetailsGenerateQuotationViewResponse.dart';
import 'package:generp/screens/LoginScreen.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'package:path_provider/path_provider.dart';
......@@ -18,11 +19,15 @@ import '../HomeScreenNotifier.dart';
class Crmgeneratequotationprovider extends ChangeNotifier {
final FlutterLocalNotificationsPlugin _notificationsPlugin =
FlutterLocalNotificationsPlugin();
FlutterLocalNotificationsPlugin();
static const platform = MethodChannel('in.webgrid.generp/download');
final GlobalKey webViewKey = GlobalKey();
var dl = DownloadManager();
TextEditingController addEditProductPriceController = TextEditingController();
TextEditingController addEditQuantityController = TextEditingController();
TextEditingController addEditTotalAmountController = TextEditingController();
TextEditingController mailIdController = TextEditingController();
TextEditingController mobileController = TextEditingController();
TextEditingController subjectsController = TextEditingController();
......@@ -30,7 +35,14 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
TextEditingController SpecialNoteController = TextEditingController();
TextEditingController forController = TextEditingController();
TextEditingController paymentTermsController = TextEditingController();
List<Map<String, dynamic>> _productRows = []; // For backend
List<Map<String, dynamic>> get productRows => _productRows;
set productRows(value) {
_productRows = value;
notifyListeners();
}
String? mailIdError = "";
String? mobileError = "";
......@@ -45,6 +57,9 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
bool _isLoading = true;
String? _quotationFilePath;
LeadProducts? _selectedLeadProducts;
String? _selectedAddEditLeadProductId;
String? _selectedAddEditLeadProductName;
List<TextEditingController> editProductPriceControllers = [];
List<TextEditingController> editQuantityControllers = [];
List<TextEditingController> editTotalAmountControllers = [];
......@@ -58,21 +73,88 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
QuoteDetails get quoteDetails => _quoteDetails;
List<LeadProducts> get leadProductsList => _leadProductsList;
set leadProductsList(List<LeadProducts> value) {
_leadProductsList = value;
notifyListeners();
}
LeadProducts? get selectedLeadProducts => _selectedLeadProducts;
bool get isLoading => _isLoading;
List<String?> get selectedProductIds => _selectedProductIds;
String? get selectedAddEditLeadProductId => _selectedAddEditLeadProductId;
String? get selectedAddEditLeadProductName => _selectedAddEditLeadProductName;
List<String?> get selectedValues => _selectedValues;
bool get submitLoading => _submitLoading;
set selectedLeadProducts(LeadProducts? value) {
_selectedLeadProducts = value;
_selectedAddEditLeadProductId = value?.productId!;
_selectedAddEditLeadProductName = value?.productName;
notifyListeners();
}
set selectedAddEditLeadProductId(String? value) {
_selectedAddEditLeadProductId = value;
notifyListeners();
}
set selectedAddEditLeadProductName(String? value) {
_selectedAddEditLeadProductName = value;
notifyListeners();
}
set submitLoading(bool value) {
_submitLoading = value;
notifyListeners();
}
void addEditUpdateTotalAmount(value) {
final price = double.tryParse(addEditProductPriceController.text) ?? 0;
final qty = int.tryParse(addEditQuantityController.text) ?? 0;
addEditTotalAmountController.text = (price * qty).toString();
notifyListeners();
}
void editProduct(int index, LeadProducts updatedProduct) {
if (index >= 0 && index < leadProductsList.length) {
leadProductsList[index] = updatedProduct;
_productRows[index] = {
"product_id": updatedProduct.productId!,
"price": updatedProduct.price,
"qty": updatedProduct.qty,
"net_price": updatedProduct.prodTotalPrice,
};
notifyListeners();
}
}
void addEditInitializeForm(BuildContext context) {
addEditProductPriceController.clear();
addEditQuantityController.clear();
addEditTotalAmountController.clear();
selectedLeadProducts = null;
selectedAddEditLeadProductId = null;
selectedAddEditLeadProductName = null;
notifyListeners();
}
void preFillFormForEdit(LeadProducts product) {
selectedLeadProducts = product;
selectedAddEditLeadProductId = product.id;
selectedAddEditLeadProductName = product.productName;
addEditProductPriceController.text = product.price?.toString() ?? '';
addEditQuantityController.text = product.qty?.toString() ?? '';
addEditTotalAmountController.text =
product.prodTotalPrice?.toString() ?? '';
notifyListeners();
}
void initializeForm(BuildContext context) {
// Clear existing controllers
......@@ -155,7 +237,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
"product_id": _selectedProductIds[i]!,
"price": editProductPriceControllers[i].text,
"qty": editQuantityControllers[i].text,
"net_price":editTotalAmountControllers[i].text
"net_price": editTotalAmountControllers[i].text,
};
insertData.add(rowData);
}
......@@ -175,31 +257,53 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
leadID,
);
if (data != null) {
if (data.error == "0") {
_isLoading = false;
_leadProductsList = data.leadProducts ?? [];
_quoteDetails =
data.quoteDetails ??
QuoteDetails(
accountId: "",
email: "",
forText: "",
mobile: "",
name: "",
paymentTerms: "",
subject: "",
);
mailIdController.text = data.quoteDetails!.email??"-";
mobileController.text = data.quoteDetails!.mobile??"-";
subjectsController.text = data.quoteDetails!.subject??"-";
// taxesController.text = data.quoteDetails!1;
// SpecialNoteController.text = data.quoteDetails;
forController.text = data.quoteDetails!.forText??"-";
paymentTermsController.text = data.quoteDetails!.paymentTerms??"-";
notifyListeners();
if (data.sessionExists == 1) {
if (data.error == "0") {
_isLoading = false;
_leadProductsList = data.leadProducts ?? [];
_quoteDetails =
data.quoteDetails ??
QuoteDetails(
accountId: "",
email: "",
forText: "",
mobile: "",
name: "",
paymentTerms: "",
subject: "",
);
mailIdController.text = data.quoteDetails!.email ?? "-";
mobileController.text = data.quoteDetails!.mobile ?? "-";
subjectsController.text = data.quoteDetails!.subject ?? "-";
// taxesController.text = data.quoteDetails!1;
// SpecialNoteController.text = data.quoteDetails;
forController.text = data.quoteDetails!.forText ?? "-";
paymentTermsController.text =
data.quoteDetails!.paymentTerms ?? "-";
for (var product in data.leadProducts!) {
_productRows.add({
"product_id": product.productId!,
"price": product.price,
"qty": product.qty,
"net_price": product.prodTotalPrice,
});
}
print("_productRows : ${_productRows}");
notifyListeners();
} else {
_isLoading = false;
notifyListeners();
}
} else {
_isLoading = false;
notifyListeners();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LoginScreen(),
settings: RouteSettings(name: 'LoginScreen'),
),
);
}
} else {
_isLoading = false;
......@@ -235,16 +339,22 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
if (data != null) {
if (data.error == "0") {
_quotationFilePath = data.quoteFilepath!;
if(quotation_type=="genquotedown"){
if (quotation_type == "genquotedown") {
String suggestedFilename = getUniqueFilename('quotation', 'pdf');
String contentDisposition = 'attachment; filename="$suggestedFilename"';
String contentDisposition =
'attachment; filename="$suggestedFilename"';
// openWhatsApp(data.quoteFilepath!);
_handleDownload(context,data.quoteFilepath!,contentDisposition,'application/octet-stream','');
}
else if(quotation_type=="genquotewhatsappbymynum"){
_handleDownload(
context,
data.quoteFilepath!,
contentDisposition,
'application/octet-stream',
'',
);
} else if (quotation_type == "genquotewhatsappbymynum") {
openWhatsApp(data.quoteFilepath!);
}
Navigator.pop(context,true);
Navigator.pop(context, true);
toast(context, data.message);
resetForm();
notifyListeners();
......@@ -260,6 +370,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
final formattedDate = DateFormat('yyyyMMdd_HHmmss').format(now);
return '${baseName}_$formattedDate.$ext';
}
void openWhatsApp(String path) async {
final Uri url = Uri.parse(path); // Example: 919876543210
if (await canLaunchUrl(url)) {
......@@ -268,16 +379,17 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
throw 'Could not launch $url';
}
}
Future<void> _handleDownload(
context,
String url,
String contentDisposition,
String mimeType,
String suggestedFilename,
) async {
context,
String url,
String contentDisposition,
String mimeType,
String suggestedFilename,
) async {
// Request notification permission for Android 13+
if (Platform.isIOS) {
_handleIOSDownload(context,url, suggestedFilename);
_handleIOSDownload(context, url, suggestedFilename);
} else if (Platform.isAndroid) {
if (await Permission.notification.request().isGranted) {
try {
......@@ -293,10 +405,12 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
'mimeType': mimeType,
'suggestedFilename': suggestedFilename,
});
await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
await launchUrl(
Uri.parse(url),
mode: LaunchMode.externalApplication,
);
} else if (Platform.isIOS) {
_handleIOSDownload(context,url, suggestedFilename);
_handleIOSDownload(context, url, suggestedFilename);
}
} catch (e) {
print("Download Error $e");
......@@ -307,7 +421,11 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
}
}
Future<void> _handleIOSDownload(context,String url, String suggestedFilename) async {
Future<void> _handleIOSDownload(
context,
String url,
String suggestedFilename,
) async {
try {
// Show initial download notification
await _showDownloadNotification(0, suggestedFilename, isComplete: false);
......@@ -315,9 +433,9 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
// Get the temporary directory for iOS
final tempDir = await getTemporaryDirectory();
final fileName =
suggestedFilename.isNotEmpty
? suggestedFilename
: url.split('/').last;
suggestedFilename.isNotEmpty
? suggestedFilename
: url.split('/').last;
final filePath = '${tempDir.path}/$fileName';
// Download the file using http
......@@ -348,11 +466,11 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
}
Future<void> _showDownloadNotification(
int progress,
String fileName, {
bool isComplete = false,
bool isError = false,
}) async {
int progress,
String fileName, {
bool isComplete = false,
bool isError = false,
}) async {
final androidDetails = AndroidNotificationDetails(
'download_channel',
'Downloads',
......@@ -378,11 +496,11 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
presentBadge: true,
presentSound: isComplete || isError,
subtitle:
isError
? 'Download failed'
: isComplete
? 'Download complete'
: 'Downloading...',
isError
? 'Download failed'
: isComplete
? 'Download complete'
: 'Downloading...',
threadIdentifier: 'download_thread',
);
......@@ -407,39 +525,66 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
);
}
onChangemailId(value){
onChangemailId(value) {
mailIdError = "";
notifyListeners();
}
onChangemobile(value){
onChangemobile(value) {
mobileError = "";
notifyListeners();
}
onChangesubjects(value){
onChangesubjects(value) {
subjectsError = "";
notifyListeners();
}
onChangetaxes(value){
onChangetaxes(value) {
taxesError = "";
notifyListeners();
}
onChangeSpecialNote(value){
onChangeSpecialNote(value) {
SpecialNoteError = "";
notifyListeners();
}
onChangefor(value){
onChangefor(value) {
forError = "";
notifyListeners();
}
onChangepaymentTerms(value){
onChangepaymentTerms(value) {
paymentTermsError = "";
notifyListeners();
}
void resetForm() {
checkDropdownReset();
_productRows.clear();
addEditProductPriceController.clear();
addEditQuantityController.clear();
addEditTotalAmountController.clear();
editProductPriceControllers.clear();
editQuantityControllers.clear();
editTotalAmountControllers.clear();
_selectedLeadProducts = null;
_selectedAddEditLeadProductId = null;
_selectedAddEditLeadProductName = null;
notifyListeners();
}
void checkDropdownReset() {
if (!_leadProductsList.contains(_selectedLeadProducts) &&
_selectedLeadProducts != null) {
_selectedAddEditLeadProductId = null;
_selectedAddEditLeadProductName = null;
}
notifyListeners();
}
resetForm(){
resetForm2() {
mailIdController.clear();
mobileController.clear();
subjectsController.clear();
......@@ -460,6 +605,5 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
SpecialNoteError = "";
forError = "";
paymentTermsError = "";
}
}
......@@ -196,14 +196,12 @@ class crmNearbyOpenLeadsProvider extends ChangeNotifier {
List<Marker> markers = [];
// print("Hello Nutsby!");
ByteData data = await rootBundle.load("assets/images/dg_set.png");
ByteData data = await rootBundle.load("assets/images/leads_ic.png");
Uint8List bytes = data.buffer.asUint8List();
await Future.forEach(leadsList, (leads) async {
ui.Codec codec = await ui.instantiateImageCodec(
bytes,
targetWidth: 75,
targetHeight: 95,
);
ui.FrameInfo fi = await codec.getNextFrame();
Uint8List resizedBytes =
......@@ -214,9 +212,11 @@ class crmNearbyOpenLeadsProvider extends ChangeNotifier {
markers.add(
Marker(
markerId: MarkerId(leads.id.toString()),
position: _parseLatLng(leads.loc),
icon: BitmapDescriptor.fromBytes(resizedBytes),
infoWindow: InfoWindow(
onTap:() {
// onMarkerTap(context, leads.id);
Navigator.push(
......
......@@ -126,11 +126,17 @@ import 'package:generp/Notifiers/HomeScreenNotifier.dart';
import 'package:generp/services/api_calling.dart';
import 'package:provider/provider.dart';
import '../../Models/crmModels/crmLeadDetailsEditProductsViewResponse.dart';
import 'crmLeadDetailsProvider.dart';
class Editproductlistprovider extends ChangeNotifier {
TextEditingController addEditProductPriceController = TextEditingController();
TextEditingController addEditQuantityController = TextEditingController();
TextEditingController addEditTotalAmountController = TextEditingController();
List<Products> _productsList = [];
List<LeadProducts> _leadProductsList = [];
Products? _selectedProducts;
String? _selectedAddEditProductId;
String? _selectedAddEditProductName;
List<TextEditingController> editProductPriceControllers = [];
List<TextEditingController> editQuantityControllers = [];
List<TextEditingController> editTotalAmountControllers = [];
......@@ -139,14 +145,35 @@ class Editproductlistprovider extends ChangeNotifier {
bool _submitLoading = false;
List<Products> get productsList => _productsList;
List<LeadProducts> get leadProductsList => _leadProductsList;
Products? get selectedProducts => _selectedProducts;
String? get selectedAddEditProductId => _selectedAddEditProductId;
String? get selectedAddEditProductName => _selectedAddEditProductName;
List<String?> get selectedProductIds => _selectedProductIds;
List<String?> get selectedValues => _selectedValues;
bool get submitLoading => _submitLoading;
set selectedProducts(Products? value) {
_selectedProducts = value;
_selectedAddEditProductId = value!.id!;
_selectedAddEditProductName = value.name;
notifyListeners();
}
set selectedAddEditProductId(String? value) {
_selectedAddEditProductId = value;
notifyListeners();
}
set selectedAddEditProductName(String? value) {
_selectedAddEditProductName = value;
notifyListeners();
}
......@@ -165,10 +192,20 @@ class Editproductlistprovider extends ChangeNotifier {
// Initialize controllers for each lead product
for (var product in _leadProductsList) {
editProductPriceControllers.add(TextEditingController(text: product.price?.toString() ?? ''));
editQuantityControllers.add(TextEditingController(text: product.qty?.toString() ?? ''));
editTotalAmountControllers.add(TextEditingController(
text: (double.parse(product.price?.toString() ?? '0') * int.parse(product.qty?.toString() ?? '0')).toString()));
editProductPriceControllers.add(
TextEditingController(text: product.price?.toString() ?? ''),
);
editQuantityControllers.add(
TextEditingController(text: product.qty?.toString() ?? ''),
);
editTotalAmountControllers.add(
TextEditingController(
text:
(double.parse(product.price?.toString() ?? '0') *
int.parse(product.qty?.toString() ?? '0'))
.toString(),
),
);
_selectedProductIds.add(product.productId);
_selectedValues.add(product.productName);
}
......@@ -215,6 +252,13 @@ class Editproductlistprovider extends ChangeNotifier {
notifyListeners();
}
void addEditUpdateTotalAmount() {
final price = double.tryParse(addEditProductPriceController.text) ?? 0;
final qty = int.tryParse(addEditQuantityController.text) ?? 0;
addEditTotalAmountController.text = (price * qty).toString();
notifyListeners();
}
List<Map<String, String>> getFormData() {
final List<Map<String, String>> insertData = [];
for (int i = 0; i < editProductPriceControllers.length; i++) {
......@@ -230,10 +274,17 @@ class Editproductlistprovider extends ChangeNotifier {
return insertData;
}
Future<void> crmLeadDetailsEditProductsViewAPIFunction(BuildContext context, String leadID) async {
Future<void> crmLeadDetailsEditProductsViewAPIFunction(
BuildContext context,
String leadID,
) async {
try {
final prov = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.crmLeadDetailsEditProductsViewAPI(prov.empId, prov.session, leadID);
final data = await ApiCalling.crmLeadDetailsEditProductsViewAPI(
prov.empId,
prov.session,
leadID,
);
if (data != null && data.error == "0") {
_leadProductsList = data.leadProducts ?? [];
_productsList = data.products ?? [];
......@@ -244,13 +295,22 @@ class Editproductlistprovider extends ChangeNotifier {
}
}
Future<void> crmLeadDetailsEditProductsSubmitAPIFunction(BuildContext context,products, String leadID) async {
Future<void> crmLeadDetailsEditProductsSubmitAPIFunction(
BuildContext context,
products,
String leadID,
) async {
try {
final prov = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.crmLeadDetailsEditProductsSubmitAPI(prov.empId, prov.session,products, leadID);
final data = await ApiCalling.crmLeadDetailsEditProductsSubmitAPI(
prov.empId,
prov.session,
products,
leadID,
);
if (data != null && data.error == "0") {
resetForm();
Navigator.pop(context,true);
Navigator.pop(context, true);
notifyListeners();
}
} catch (e, s) {
......@@ -258,22 +318,78 @@ class Editproductlistprovider extends ChangeNotifier {
}
}
void submitForm(BuildContext context,leadID) async {
Future<void> crmLeadDetailsAddEditProductsSubmitAPIFunction(
BuildContext context,
mode,
String leadID,
type,
leadProductId,
productId,
) async {
try {
_submitLoading = true;
notifyListeners();
final prov = Provider.of<HomescreenNotifier>(context, listen: false);
final prov2 = Provider.of<crmLeadDetailsProvider>(context, listen: false);
final data = await ApiCalling.crmLeadDetailsAddEditProductsAPI(
prov.empId,
prov.session,
leadID,
type,
leadProductId,
productId,
addEditQuantityController.text,
addEditTotalAmountController.text,
);
if (data != null && data.error == "0") {
_submitLoading = false;
resetForm();
Navigator.pop(context, true);
prov2.crmLeadDetailsAPIFunction(context, leadID, mode);
notifyListeners();
}else{
_submitLoading = false;
notifyListeners();
}
} catch (e, s) {
_submitLoading = false;
notifyListeners();
print("Error: $e, Stack: $s");
}
}
void submitForm(BuildContext context, leadID) async {
submitLoading = true;
final insertedData = getFormData();
print("Form Data: $insertedData");
crmLeadDetailsEditProductsSubmitAPIFunction(context,insertedData,leadID);
crmLeadDetailsEditProductsSubmitAPIFunction(context, insertedData, leadID);
submitLoading = false;
}
void resetForm() {
checkDropdownReset();
addEditProductPriceController.clear();
addEditQuantityController.clear();
addEditTotalAmountController.clear();
editProductPriceControllers.clear();
editQuantityControllers.clear();
editTotalAmountControllers.clear();
_selectedProductIds.clear();
_selectedProducts = null;
_selectedAddEditProductId = null;
_selectedAddEditProductName = null;
_selectedValues.clear();
_leadProductsList.clear();
notifyListeners();
}
}
\ No newline at end of file
void checkDropdownReset(){
if(!_productsList.contains(_selectedProducts)&&_selectedProducts!=null){
_selectedAddEditProductId = null;
_selectedAddEditProductName = null;
}
notifyListeners();
}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:generp/Notifiers/HomeScreenNotifier.dart';
import 'package:generp/Utils/app_colors.dart';
import 'package:geolocator/geolocator.dart';
import 'package:geolocator/geolocator.dart' as geo_location;
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import '../../services/api_calling.dart';
import 'crmLeadDetailsProvider.dart';
class followUpUpdateProvider extends ChangeNotifier {
bool _submitLoading = false;
TextEditingController nextAppointmentDateController = TextEditingController();
TextEditingController followUpFeedbackController = TextEditingController();
TextEditingController noteController = TextEditingController();
TextEditingController reasonController = TextEditingController();
TimeOfDay _selectedTime = TimeOfDay.now();
String _formattedTime = "";
String? _selectedFollowupType;
String? _selectedLeadStatus;
String? _nextAppointmentStatus;
String? _selectNextAppointmentType;
String? _selectOrderStatus;
String? _selectedCompetitor;
LatLng? currentLocationLatLng;
String? latlongs;
DateTime? _date;
String? _formattedDate;
String? _dateError;
bool get submitLoading => _submitLoading;
TimeOfDay get selectedTime => _selectedTime;
String get formattedTime => _formattedTime;
String? get selectedFollowupType => _selectedFollowupType;
String? get selectedLeadStatus => _selectedLeadStatus;
String? get nextAppointmentStatus => _nextAppointmentStatus;
String? get selectNextAppointmentType => _selectNextAppointmentType;
String? get selectOrderStatus => _selectOrderStatus;
String? get selectedCompetitor => _selectedCompetitor;
set submitLoading(bool value){
_submitLoading = value;
notifyListeners();
}
set selectedFollowupType(String? value) {
_selectedFollowupType = value;
notifyListeners();
}
set selectedLeadStatus(String? value) {
_selectedLeadStatus = value;
notifyListeners();
}
set nextAppointmentStatus(String? value) {
_nextAppointmentStatus = value;
notifyListeners();
}
set selectNextAppointmentType(String? value) {
_selectNextAppointmentType = value;
notifyListeners();
}
set selectOrderStatus(String? value) {
_selectOrderStatus = value;
notifyListeners();
}
set selectedCompetitor(String? value) {
_selectedCompetitor = value;
notifyListeners();
}
bool _checked = false;
var _smsSent = "0";
bool get checked => _checked;
get smsSent => _smsSent;
set smsSent(value) {
_smsSent = value;
notifyListeners();
}
set checked(value) {
_checked = value;
notifyListeners();
}
set formattedDate(String? value) {
_formattedDate = value;
nextAppointmentDateController.text = _formattedDate!;
_dateError = null;
notifyListeners();
}
set dateError(value) {
_dateError = value;
notifyListeners();
}
Future<void> getCurrentLocation(context) async {
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: geo_location.LocationAccuracy.high,
);
currentLocationLatLng = LatLng(position.latitude, position.longitude);
print("Current Loc: ${currentLocationLatLng}");
latlongs = '${position.latitude},${position.longitude}';
print("latlongs : ${latlongs}");
notifyListeners();
} catch (e) {
print("Error getting current location: $e");
}
}
Future<void> crmAddFollowUpAPIFunction(
BuildContext context,
nextAppointmentStatus,
orderStatus,
leadID,
followupType,
competitor,
leadStatus,
appointmentType,
sms,
[mode]
) async {
try {
_submitLoading = true;
notifyListeners();
final prov = Provider.of<HomescreenNotifier>(context, listen: false);
final prov2 = Provider.of<crmLeadDetailsProvider>(context, listen: false);
final data = await ApiCalling.crmLeadDetailsAddFollowUpAPI(
prov.session,
prov.empId,
nextAppointmentStatus,
orderStatus,
leadID,
followUpFeedbackController.text,
followupType,
_selectedTime.hour.toString() + ":" + _selectedTime.minute.toString(),
latlongs,
competitor,
reasonController.text,
leadStatus,
nextAppointmentDateController.text,
appointmentType,
sms,
noteController.text,
);
if (data != null && data.error == "0") {
_submitLoading = false;
resetForm();
Navigator.pop(context);
if(mode.isNotEmpty){
prov2.crmLeadDetailsAPIFunction(context, leadID, mode);
}
notifyListeners();
} else {
_submitLoading = false;
notifyListeners();
}
} catch (e, s) {
_submitLoading = false;
notifyListeners();
print("Error: $e, Stack: $s");
}
}
void setDate(DateTime newDate) {
_date = newDate;
_formattedDate = DateFormat('yyyy-MM-dd').format(newDate);
nextAppointmentDateController.text = _formattedDate!;
_dateError = null;
notifyListeners();
}
Future<void> selectTime(BuildContext context) async {
final TimeOfDay? picked = await showTimePicker(
context: context,
initialTime: _selectedTime,
);
if (picked != null && picked != _selectedTime) _selectedTime = picked;
_formattedTime =
_selectedTime.hour.toString() + ":" + _selectedTime.minute.toString();
notifyListeners();
}
String formatTime(int hour, int minute) {
String period = (hour >= 12) ? 'pm' : 'am';
if (hour == 0) {
hour = 12;
} else if (hour > 12) {
hour -= 12;
}
String formattedHour = (hour < 10) ? '0$hour' : '$hour';
String formattedMinute = (minute < 10) ? '0$minute' : '$minute';
print("formattedTime: $formattedHour:$formattedMinute $period");
return '$formattedHour:$formattedMinute $period';
}
void showDatePickerDialog(BuildContext context) {
showCupertinoModalPopup<void>(
context: context,
builder:
(BuildContext context) => Container(
height: 216,
padding: const EdgeInsets.only(top: 6.0),
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
color: CupertinoColors.systemBackground.resolveFrom(context),
child: SafeArea(
top: false,
child: Column(
children: [
Expanded(
flex: 1,
child: SizedBox(
height: 40,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CupertinoButton(
child: Text(
'Cancel',
style: TextStyle(
fontFamily: "JakartaMedium",
color: AppColors.app_blue,
),
),
onPressed: () {
Navigator.pop(context);
},
),
CupertinoButton(
child: Text(
'Done',
style: TextStyle(
fontFamily: "JakartaMedium",
color: AppColors.app_blue,
),
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
),
Expanded(
flex: 3,
child: CupertinoDatePicker(
dateOrder: DatePickerDateOrder.dmy,
initialDateTime: _date ?? DateTime.now(),
mode: CupertinoDatePickerMode.date,
use24hFormat: true,
showDayOfWeek: true,
onDateTimeChanged: (DateTime newDate) {
setDate(newDate);
},
),
),
],
),
),
),
);
}
onFollowUpChanged(value) {}
onNoteChanged(value) {}
onReasonChanged(value) {}
void resetForm(){
nextAppointmentDateController.clear();
followUpFeedbackController.clear();
noteController.clear();
reasonController.clear();
_selectedFollowupType = null;
_selectedLeadStatus = null;
_nextAppointmentStatus = null;
_selectNextAppointmentType = null;
_selectOrderStatus = null;
_selectedCompetitor = null;
notifyListeners();
}
}
......@@ -414,7 +414,7 @@ class Requestionlistprovider extends ChangeNotifier {
_accounts = data.accounts ?? [];
if (mode != "self") {
_accounts = [
Accounts(id: "", name: "Select"),
Accounts(id: "", name: "Select Account"),
...data.accounts ?? [],
];
}
......
......@@ -220,6 +220,7 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => Addprospectleadsprovider()),
ChangeNotifierProvider(create: (_) => Editorderprovider()),
ChangeNotifierProvider(create: (_) => Dispatchorderprovider()),
ChangeNotifierProvider(create: (_) => followUpUpdateProvider()),
],
child: Builder(
builder: (BuildContext context) {
......
......@@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:generp/Notifiers/crmProvider/crmLeadDetailsProvider.dart';
import 'package:generp/Notifiers/crmProvider/editProductListProvider.dart';
import 'package:generp/Utils/commonServices.dart';
import 'package:generp/Utils/dropdownTheme.dart';
import 'package:generp/screens/crm/AppointmentDetails.dart';
......@@ -18,6 +19,7 @@ import 'package:generp/screens/crm/followUpUpdateScreen.dart';
import 'package:generp/screens/crm/productDetails.dart';
import 'package:provider/provider.dart';
import '../../Models/crmModels/crmLeadDetailsEditProductsViewResponse.dart';
import '../../Utils/app_colors.dart';
import '../../Utils/commonWidgets.dart';
import '../finance/FileViewer.dart';
......@@ -97,8 +99,8 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
}
Widget _scaffold(BuildContext context) {
return Consumer<crmLeadDetailsProvider>(
builder: (context, provider, child) {
return Consumer2<crmLeadDetailsProvider, Editproductlistprovider>(
builder: (context, provider, editProvider, child) {
var leadDetails = provider.leadDetails;
var headings1 = ["Account Manager Name", "Account Created By"];
......@@ -124,7 +126,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
var headings4 = ["Lead Status", "Last Followup Date", "Lead Age"];
var subHeadings4 = [
provider.leadDetails!.status ?? "-",
provider.followupDetails.first!.fdate ?? "-",
provider.leadDetails!.date ?? "-",
"${provider.leadDetails!.lage ?? "-"} days",
];
// var totalHeadings = [];
......@@ -638,6 +640,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
child: Column(
children: [
///product details
if(provider.leadProducts.isNotEmpty)...[
Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10),
child: Row(
......@@ -654,13 +657,20 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
),
),
Expanded(
child: Text(
textAlign: TextAlign.right,
"+ Add Product",
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.app_blue,
child: InkResponse(
onTap: () async {
editProvider.resetForm();
await editProvider.crmLeadDetailsEditProductsViewAPIFunction(context, provider.leadDetails.id!);
_showAddEditProductsSheet(context,widget.mode, "add", "");
},
child: Text(
textAlign: TextAlign.right,
"+ Add Product",
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.app_blue,
),
),
),
),
......@@ -669,7 +679,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
),
SizedBox(
width: double.infinity,
height: 125,
height: 130,
child: ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
......@@ -679,18 +689,28 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
itemBuilder: (context, lp) {
return InkResponse(
onTap: () async {
var res = await Navigator.push(
context,
MaterialPageRoute(
builder:
(context) => EditProductsList(
leadID: provider.leadDetails.id ?? "",
),
),
// var res = await Navigator.push(
// context,
// MaterialPageRoute(
// builder:
// (context) => EditProductsList(
// leadID: provider.leadDetails.id ?? "",
// ),
// ),
// );
await editProvider.crmLeadDetailsEditProductsViewAPIFunction(context, provider.leadDetails.id!);
editProvider.addEditProductPriceController.text = provider.leadProducts[lp].price!;
editProvider.addEditQuantityController.text = provider.leadProducts[lp].qty!;
editProvider.addEditTotalAmountController.text = provider.leadProducts[lp].prodTotalPrice!;
editProvider.selectedProducts = editProvider.productsList.firstWhere(
(product) => product.id == provider.leadProducts[lp].productId
);
editProvider.selectedAddEditProductId = provider.leadProducts[lp].productId!;
editProvider.selectedAddEditProductName = provider.leadProducts[lp].productName!;
_showAddEditProductsSheet(context,widget.mode, "edit", provider.leadProducts[lp].id);
},
child: Container(
height: 125,
height: 130,
width: MediaQuery.of(context).size.width * 0.95,
decoration: BoxDecoration(
color: Colors.white,
......@@ -698,7 +718,12 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
),
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
vertical: 8,
),
margin: EdgeInsets.symmetric(
horizontal: 5,
// vertical: 10,
),
child: Row(
......@@ -730,6 +755,8 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
.leadProducts[lp]
.productName ??
"-",
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
......@@ -759,7 +786,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
color: AppColors.grey_semi,
),
),
SizedBox(height: 10),
SizedBox(height: 5),
DottedLine(
dashGapLength: 4,
dashGapColor: Colors.white,
......@@ -767,9 +794,9 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
dashLength: 2,
lineThickness: 0.5,
),
SizedBox(height: 10),
SizedBox(height: 5),
Text(
"₹${provider.leadProducts[lp].price ?? " - "}",
"₹${provider.leadProducts[lp].prodTotalPrice ?? " - "}",
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
......@@ -787,8 +814,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
},
),
),
],
///contact details
if(provider.contactDetails.isNotEmpty)...[
Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10),
child: Row(
......@@ -831,12 +860,18 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
itemBuilder: (context, lp) {
return InkResponse(
onTap: () async {
provider.editNameController.text = provider.contactDetails[lp].name??"";
provider.editDesignationController.text = provider.contactDetails[lp].designation??"";
provider.editMobileNumberController.text = provider.contactDetails[lp].mob1??"";
provider.editAlternativeMobileController.text = provider.contactDetails[lp].mob2??"";
provider.editTelephoneController.text = provider.contactDetails[lp].tel??"";
provider.editEmailController.text = provider.contactDetails[lp].email??"";
provider.editNameController.text =
provider.contactDetails[lp].name ?? "";
provider.editDesignationController.text =
provider.contactDetails[lp].designation ?? "";
provider.editMobileNumberController.text =
provider.contactDetails[lp].mob1 ?? "";
provider.editAlternativeMobileController.text =
provider.contactDetails[lp].mob2 ?? "";
provider.editTelephoneController.text =
provider.contactDetails[lp].tel ?? "";
provider.editEmailController.text =
provider.contactDetails[lp].email ?? "";
_showEditContactSheet(context, lp);
},
child: Container(
......@@ -915,201 +950,273 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
);
},
),
],
///Followup details
Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10),
child: Row(
children: [
Expanded(
child: Text(
textAlign: TextAlign.left,
"Followup Details",
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.grey_thick,
),
),
),
Expanded(
child: InkResponse(
onTap: () async {
var res = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Followupupdatescreen(),
settings: RouteSettings(
name: 'Followupupdatescreen',
),
),
);
},
if (provider.followupDetails.isNotEmpty) ...[
Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10),
child: Row(
children: [
Expanded(
child: Text(
textAlign: TextAlign.right,
"+ Follow up Update",
textAlign: TextAlign.left,
"Followup Details",
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.app_blue,
color: AppColors.grey_thick,
),
),
),
),
],
),
),
SizedBox(
width: double.infinity,
height: 250,
child: ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
itemCount: provider.followupDetails.length,
itemBuilder: (context, lp) {
return Container(
height: 250,
width: MediaQuery.of(context).size.width * 0.95,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(14),
),
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
Expanded(
child: InkResponse(
onTap: () async {
var res = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Followupupdatescreen(
leadID: provider.leadDetails.id,
mode: widget.mode,
),
settings: RouteSettings(
name: 'Followupupdatescreen',
),
),
);
},
child: Text(
textAlign: TextAlign.right,
"+ Follow up Update",
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.app_blue,
),
),
),
),
margin: EdgeInsets.symmetric(horizontal: 5),
],
),
),
SizedBox(
width: double.infinity,
height: 250,
child: ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(
vertical: 10,
horizontal: 10,
),
itemCount: provider.followupDetails.length,
itemBuilder: (context, lp) {
return Container(
height: 250,
width: MediaQuery.of(context).size.width * 0.95,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(14),
),
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
margin: EdgeInsets.symmetric(horizontal: 5),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 1,
child: SvgPicture.asset(
"assets/svg/crm/followup_details_ic.svg",
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 1,
child: SvgPicture.asset(
"assets/svg/crm/followup_details_ic.svg",
),
),
),
SizedBox(width: 10),
Expanded(
flex: 6,
child: SizedBox(
child: Column(
// mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Row(
children: [
Expanded(
flex: 4,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
provider
.followupDetails[lp]
.ename ??
"-",
style: TextStyle(
fontFamily:
"JakartaMedium",
fontSize: 14,
color:
AppColors.semi_black,
SizedBox(width: 10),
Expanded(
flex: 6,
child: SizedBox(
child: Column(
// mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Row(
children: [
Expanded(
flex: 4,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
provider
.followupDetails[lp]
.ename ??
"-",
style: TextStyle(
fontFamily:
"JakartaMedium",
fontSize: 14,
color:
AppColors
.semi_black,
),
),
),
Text(
provider
.followupDetails[lp]
.fdate ??
"-",
style: TextStyle(
fontFamily:
"JakartaMedium",
fontSize: 14,
color:
AppColors.grey_semi,
Text(
provider
.followupDetails[lp]
.fdate ??
"-",
style: TextStyle(
fontFamily:
"JakartaMedium",
fontSize: 14,
color:
AppColors.grey_semi,
),
),
),
],
),
),
Expanded(
flex: 2,
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(8),
color: Color(0xFFF3FFD5),
),
padding: EdgeInsets.symmetric(
horizontal: 5,
vertical: 10,
],
),
child: Center(
child: Text(
textAlign: TextAlign.right,
"${provider.followupDetails[lp].fstatus ?? "-"}",
style: TextStyle(
fontFamily:
"JakartaMedium",
fontSize: 14,
color: Color(0xFF586000),
),
Expanded(
flex: 2,
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(
8,
),
color: Color(0xFFF3FFD5),
),
padding: EdgeInsets.symmetric(
horizontal: 5,
vertical: 10,
),
child: Center(
child: Text(
textAlign:
TextAlign.right,
"${provider.followupDetails[lp].fstatus ?? "-"}",
style: TextStyle(
fontFamily:
"JakartaMedium",
fontSize: 14,
color: Color(
0xFF586000,
),
),
),
),
),
),
),
],
),
],
],
),
],
),
),
),
),
],
),
Container(
padding: EdgeInsets.symmetric(vertical: 10),
child: Row(
children: [
Expanded(
flex: 2,
child: Text(
"Time",
style: TextStyle(
fontSize: 14,
fontFamily: "JakartaSemiBold",
],
),
Container(
padding: EdgeInsets.symmetric(vertical: 10),
child: Row(
children: [
Expanded(
flex: 2,
child: Text(
"Time",
style: TextStyle(
fontSize: 14,
fontFamily: "JakartaSemiBold",
),
),
),
),
Expanded(
flex: 7,
child: DottedLine(
dashGapLength: 4,
dashGapColor: Colors.white,
dashColor: AppColors.grey_semi,
dashLength: 2,
lineThickness: 0.5,
Expanded(
flex: 7,
child: DottedLine(
dashGapLength: 4,
dashGapColor: Colors.white,
dashColor: AppColors.grey_semi,
dashLength: 2,
lineThickness: 0.5,
),
),
],
),
),
...List.generate(2, (j) {
final heads = ["In Time", "Out Time"];
final subHeads = [
provider.followupDetails[lp].finTime ?? "-",
provider.followupDetails[lp].foutTime ?? "-",
];
return Container(
padding: EdgeInsets.symmetric(vertical: 3),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Expanded(
child: Text(
textAlign: TextAlign.left,
heads[j],
style: TextStyle(
fontFamily: "JakartaRegular",
fontSize: 14,
color: AppColors.semi_black,
),
),
),
Expanded(
child: Text(
textAlign: TextAlign.right,
subHeads[j] == "" ? "-" : subHeads[j],
style: TextStyle(
fontSize: 14,
color: Color(0xFF818181),
),
),
),
],
),
],
);
}),
Container(
padding: EdgeInsets.symmetric(vertical: 10),
child: Row(
children: [
Expanded(
flex: 2,
child: Text(
"Remarks",
style: TextStyle(
fontSize: 14,
fontFamily: "JakartaSemiBold",
),
),
),
Expanded(
flex: 7,
child: DottedLine(
dashGapLength: 4,
dashGapColor: Colors.white,
dashColor: AppColors.grey_semi,
dashLength: 2,
lineThickness: 0.5,
),
),
],
),
),
),
...List.generate(2, (j) {
final heads = ["In Time", "Out Time"];
final subHeads = [
provider.followupDetails[lp].finTime ?? "-",
provider.followupDetails[lp].foutTime ?? "-",
];
return Container(
Container(
padding: EdgeInsets.symmetric(vertical: 3),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
......@@ -1117,7 +1224,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
Expanded(
child: Text(
textAlign: TextAlign.left,
heads[j],
"Feedback",
style: TextStyle(
fontFamily: "JakartaRegular",
fontSize: 14,
......@@ -1128,7 +1235,16 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
Expanded(
child: Text(
textAlign: TextAlign.right,
subHeads[j] == "" ? "-" : subHeads[j],
provider
.followupDetails[lp]
.ffeedback ==
""
? "-"
: provider
.followupDetails[lp]
.ffeedback ??
"-",
maxLines: 2,
style: TextStyle(
fontSize: 14,
color: Color(0xFF818181),
......@@ -1137,79 +1253,17 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
),
],
),
);
}),
Container(
padding: EdgeInsets.symmetric(vertical: 10),
child: Row(
children: [
Expanded(
flex: 2,
child: Text(
"Remarks",
style: TextStyle(
fontSize: 14,
fontFamily: "JakartaSemiBold",
),
),
),
Expanded(
flex: 7,
child: DottedLine(
dashGapLength: 4,
dashGapColor: Colors.white,
dashColor: AppColors.grey_semi,
dashLength: 2,
lineThickness: 0.5,
),
),
],
),
),
Container(
padding: EdgeInsets.symmetric(vertical: 3),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Text(
textAlign: TextAlign.left,
"Feedback",
style: TextStyle(
fontFamily: "JakartaRegular",
fontSize: 14,
color: AppColors.semi_black,
),
),
),
Expanded(
child: Text(
textAlign: TextAlign.right,
provider.followupDetails[lp].ffeedback ==
""
? "-"
: provider
.followupDetails[lp]
.ffeedback ??
"-",
maxLines: 2,
style: TextStyle(
fontSize: 14,
color: Color(0xFF818181),
),
),
),
],
),
),
],
),
);
},
],
),
);
},
),
),
),
],
///Appointment details
if(provider.appointmentDetails.isNotEmpty)...[
Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10),
child: Row(
......@@ -1467,8 +1521,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
},
),
),
],
///Quotation details
if(provider.quotationsDetails.isNotEmpty)...[
Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10),
child: Row(
......@@ -1698,7 +1754,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
},
),
),
],
SizedBox(height: 75),
],
),
......@@ -1742,7 +1798,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
Align(
alignment: Alignment.topLeft,
child: Text(
"Add Contact",
"Add Appointment",
style: TextStyle(
color: AppColors.app_blue,
fontSize: 16,
......@@ -1885,12 +1941,6 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
child: Container(
alignment: Alignment.center,
height: 45,
margin: EdgeInsets.only(
left: 5.0,
right: 5.0,
top: 5.0,
bottom: 5.0,
),
decoration: BoxDecoration(
color: AppColors.app_blue, //1487C9
borderRadius: BorderRadius.circular(14.0),
......@@ -2382,4 +2432,253 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
},
);
}
Future<void> _showAddEditProductsSheet(
BuildContext context,
mode,
type,
leadProductId,
) {
return showModalBottomSheet(
useSafeArea: true,
isDismissible: true,
isScrollControlled: true,
showDragHandle: true,
backgroundColor: Colors.white,
enableDrag: true,
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return SafeArea(
child: Consumer2<crmLeadDetailsProvider, Editproductlistprovider>(
builder: (context, provider, editProvider, child) {
final price =
double.tryParse(
editProvider.addEditProductPriceController.text,
) ??
0;
final qty =
int.tryParse(
editProvider.addEditQuantityController.text,
) ??
0;
editProvider.addEditTotalAmountController.text =
(price * qty).toString();
return Container(
margin: EdgeInsets.only(
bottom: 15,
left: 15,
right: 15,
top: 10,
),
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
type == "add" ? "Add Product" : "Edit Product",
style: TextStyle(
fontSize: 14,
color: AppColors.app_blue,
fontFamily: "JakartaMedium",
),
),
SizedBox(height: 10,),
TextWidget(context, "Product"),
DropdownButtonHideUnderline(
child: Row(
children: [
Expanded(
child: DropdownButton2<Products>(
isExpanded: true,
hint: const Text(
'Select Product',
style: TextStyle(fontSize: 14),
overflow: TextOverflow.ellipsis,
),
items:
editProvider.productsList
.map(
(
ord,
) => DropdownMenuItem<Products>(
value: ord,
child: Text(
"(Product Name: ${ord.name})",
style: const TextStyle(
fontSize: 14,
),
overflow:
TextOverflow.ellipsis,
),
),
)
.toList(),
// value: editProvider.selectedAddEditProductId != null
// ? editProvider.productsList.firstWhere(
// (ord) => ord.id == editProvider.selectedProductIds,
// orElse: () => editProvider.productsList[0],
// )
// : null,
value: editProvider.selectedProducts,
onChanged: (Products? value) {
if (value != null) {
editProvider.selectedProducts = value;
editProvider.selectedAddEditProductId =
value.id;
editProvider
.selectedAddEditProductName =
value.name;
// editProvider.updateSelectedProductIds(j, value);
// editProvider.selectedProductIds[j] =
// value.id?.toString() ?? '';
// editProvider.updateTotalAmount(j);
}
},
buttonStyleData: ddtheme.buttonStyleData,
iconStyleData: ddtheme.iconStyleData,
menuItemStyleData:
ddtheme.menuItemStyleData,
dropdownStyleData:
ddtheme.dropdownStyleData,
),
),
],
),
),
const SizedBox(height: 10),
Row(
children: [
Expanded(
flex: 2,
child: textControllerWidget(
context,
editProvider.addEditProductPriceController,
"Product Price",
"Enter Product Price",
(value) =>
editProvider.addEditUpdateTotalAmount,
TextInputType.number,
false,
null,
),
),
],
),
const SizedBox(height: 10),
Row(
children: [
Expanded(
flex: 2,
child: textControllerWidget(
context,
editProvider.addEditQuantityController,
"Quantity",
"Enter Quantity",
(value) =>
editProvider.addEditUpdateTotalAmount,
TextInputType.number,
false,
FilteringTextInputFormatter.digitsOnly,
),
),
],
),
errorWidget(
context,
"Note: Submit Quantity as Zero (0) to delete Product",
),
const SizedBox(height: 10),
Row(
children: [
Expanded(
flex: 2,
child: textControllerWidget(
context,
editProvider.addEditTotalAmountController,
"Amount",
"Total Amount",
(_) {},
TextInputType.number,
true,
FilteringTextInputFormatter.digitsOnly,
),
),
],
),
// IconButton(
// icon: const Icon(Icons.delete),
// onPressed: editProvider.editProductPriceControllers.length > 1
// ? () => editProvider.editRemoveRow(j)
// : null,
// ),
InkResponse(
onTap:
editProvider.submitLoading
? null
: () {
editProvider
.crmLeadDetailsAddEditProductsSubmitAPIFunction(
context,
mode,
provider.leadDetails.id!,
type,
leadProductId,
editProvider
.selectedAddEditProductId,
);
},
child: Container(
height: 45,
alignment: Alignment.center,
margin: const EdgeInsets.symmetric(
horizontal: 0,
vertical: 15,
),
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 5,
),
decoration: BoxDecoration(
color: AppColors.app_blue,
borderRadius: BorderRadius.circular(15),
),
child:
editProvider.submitLoading
? CircularProgressIndicator.adaptive(
valueColor:
AlwaysStoppedAnimation<Color>(
AppColors.white,
),
)
: const Text(
"Submit",
style: TextStyle(
fontSize: 15,
fontFamily: "JakartaMedium",
color: Colors.white,
),
),
),
),
],
),
),
);
},
),
);
},
);
},
).whenComplete(() {
Provider.of<crmLeadDetailsProvider>(context).crmLeadDetailsAPIFunction(context, widget.leadId, widget.mode);
Provider.of<Editproductlistprovider>(context).resetForm();
},);
}
}
......@@ -18,7 +18,9 @@ import '../../Notifiers/crmProvider/crmNearbyOpenLeadsProvider.dart';
import '../../Utils/dropdownTheme.dart';
class NearbyOpenLeads extends StatefulWidget {
const NearbyOpenLeads({super.key});
final latitude;
final longitude;
const NearbyOpenLeads({super.key, this.latitude, this.longitude});
@override
State<NearbyOpenLeads> createState() => _NearbyOpenLeadsState();
......@@ -121,6 +123,7 @@ class _NearbyOpenLeadsState extends State<NearbyOpenLeads> {
zoomGesturesEnabled: true,
zoomControlsEnabled: true,
gestureRecognizers: {
Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(),
),
......@@ -132,7 +135,9 @@ class _NearbyOpenLeadsState extends State<NearbyOpenLeads> {
), // Prioritize pinch-to-zoom
},
initialCameraPosition: CameraPosition(
target: provider.startLocation,
target: widget.latitude!=null||widget.longitude!=null?
LatLng(widget.latitude,widget.longitude):
provider.startLocation,
zoom: 14.0,
),
markers: provider.markers.toSet(),
......
......@@ -198,7 +198,7 @@ class _ProspectListByModeState extends State<ProspectListByMode> {
),
),
Text(
crmLists[index].accman??"-",
crmLists[index].mob1??"-",
maxLines: 1,
style: TextStyle(
fontFamily: "JakartaMedium",
......
......@@ -5,7 +5,6 @@ import 'package:dotted_line/dotted_line.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:generp/Models/crmModels/crmPendingTasksResponse.dart';
import 'package:generp/screens/crm/pendingTasksDetails.dart';
import 'package:generp/screens/crm/pendingTasksList.dart';
import 'package:generp/screens/crm/universalSearchScreen.dart';
......@@ -38,8 +37,9 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
});
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
var prov = Provider.of<Crmdashboardprovider>(context, listen: false);
prov.getCurrentLocation(context);
prov.accessPagesAPIFunction(context);
prov.crmDashboardAPIFunction(context, "executive", "", "", "");
// prov.crmDashboardAPIFunction(context);
prov.crmPendingTasksAPIFunction(context);
});
}
......@@ -208,8 +208,8 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
'Pending Tasks',
'Today Visits',
'Today Calls',
'Hot Leads'
'Cold Leads',
'Hot Leads',
'Cold Leads',
'Warm Leads',
// 'Total Leads',
// 'Order Lost',
......@@ -322,6 +322,8 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
},
),
),
]else...[
SizedBox(height: 10,),
],
// ListView.builder(
......@@ -435,6 +437,7 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
// );
// },
// ),
Container(
height: MediaQuery.of(context).size.height * 0.2,
margin: EdgeInsets.symmetric(horizontal: 10),
......@@ -638,6 +641,207 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
),
),
if (provider.nearByLeads.isNotEmpty) ...[
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: EdgeInsets.only(left: 15, top: 10, right: 15),
child: Row(
children: [
Text(
"NearBy Leads",
style: TextStyle(
fontSize: 16,
color: AppColors.grey_semi,
),
),
Spacer(),
InkResponse(
onTap: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NearbyOpenLeads(),
settings: RouteSettings(
name: "NearbyOpenLeads",
),
),
);
},
child: SizedBox(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"View All",
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.app_blue,
),
),
SizedBox(width: 5),
SvgPicture.asset(
"assets/svg/next_button.svg",
),
],
),
),
),
],
),
),
),
SizedBox(
width: double.infinity,
height: 150,
child: ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(
vertical: 10,
horizontal: 10,
),
itemCount: provider.nearByLeads.length,
itemBuilder: (context, index) {
final lead = provider.nearByLeads[index];
final location = provider.parseLocation(lead.loc!);
final latitude = location.lat;
final longitude = location.lng;
return InkResponse(
onTap: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NearbyOpenLeads(
latitude:latitude,
longitude:longitude
),
settings: RouteSettings(
name: "NearbyOpenLeads",
),
),
);
},
child: Container(
alignment: Alignment.center,
height: 150,
width: MediaQuery.of(context).size.width * 0.8,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(14),
),
margin: EdgeInsets.symmetric(
horizontal: 5,
vertical: 5,
),
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 15,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Column(
crossAxisAlignment:CrossAxisAlignment.start,
children: [
Text(
provider.nearByLeads[index].name ?? "-",
maxLines: 1,
style: TextStyle(
fontSize: 14,
color: AppColors.semi_black,
fontFamily: "JakartaMedium"
),
),
Text(
provider.nearByLeads[index].product ??
"-",
maxLines: 2,
style: TextStyle(
fontSize: 14,
color: AppColors.grey_semi,
fontFamily: "JakartaMedium"
),
),
],
),
),
SizedBox(width: 10,),
Expanded(
child: ClipRRect(
borderRadius:BorderRadius.circular(16),
child: Image.network(
provider.getSimpleOSMImage(latitude, longitude),
width: 400,
height: 400,
fit: BoxFit.cover,
),
),
),
],
),
),
);
},
),
),
]else...[
SizedBox(height: 10,),
InkResponse(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NearbyOpenLeads(),
),
);
},
child: Container(
height: 60,
margin: EdgeInsets.symmetric(horizontal: 10, vertical: 0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
child: Row(
children: [
Expanded(
flex: 1,
child: Container(
height: 35,
width: 35,
padding: EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Color(0xFFEDF8FF),
shape: BoxShape.circle,
),
child: SvgPicture.asset(
"assets/svg/find_generator.svg",
),
),
),
Expanded(
flex: 4,
child: Text(
"Find Nearby Generators",
style: TextStyle(
fontSize: 14,
color: AppColors.app_blue,
),
),
),
],
),
),
),
],
if (provider.pendingTasksLists.length > 0) ...[
Align(
alignment: Alignment.centerLeft,
......@@ -714,13 +918,15 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
];
return InkResponse(
onTap: () async {
await Navigator.push(
await Navigator.push(
context,
MaterialPageRoute(
builder:
(context) =>
Pendingtasksdetails(detailIndex: index),
settings: RouteSettings(name: 'Pendingtasksdetails')
settings: RouteSettings(
name: 'Pendingtasksdetails',
),
),
);
},
......
......@@ -4,7 +4,7 @@ import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:generp/Notifiers/crmProvider/crmDashboardProvider.dart';
import 'package:generp/Notifiers/crmProvider/followUpUpdateProvider.dart';
import 'package:generp/Utils/app_colors.dart';
import 'package:generp/Utils/commonServices.dart';
import 'package:generp/Utils/commonWidgets.dart';
......@@ -12,7 +12,9 @@ import 'package:generp/Utils/dropdownTheme.dart';
import 'package:provider/provider.dart';
class Followupupdatescreen extends StatefulWidget {
const Followupupdatescreen({super.key});
final leadID;
final mode;
const Followupupdatescreen({super.key,required this.leadID, this.mode});
@override
State<Followupupdatescreen> createState() => _FollowupupdatescreenState();
......@@ -22,12 +24,7 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
Dropdowntheme ddtheme = Dropdowntheme();
Map _source = {ConnectivityResult.mobile: true};
final MyConnectivity _connectivity = MyConnectivity.instance;
TextEditingController followUpFeedbackController = TextEditingController();
TextEditingController noteController = TextEditingController();
onFollowUpChanged(value) {}
onNoteChanged(value) {}
@override
void initState() {
......@@ -36,7 +33,10 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
_connectivity.myStream.listen((event) {
setState(() => _source = event);
});
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {});
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
final provider = Provider.of<followUpUpdateProvider>(context);
provider.getCurrentLocation(context);
});
}
@override
......@@ -61,20 +61,20 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
}
return (connection == "Online")
? Platform.isAndroid
? WillPopScope(
onWillPop: () => onBackPressed(context),
child: SafeArea(
top: false,
bottom: true,
child: _scaffold(context),
),
)
: _scaffold(context)
? WillPopScope(
onWillPop: () => onBackPressed(context),
child: SafeArea(
top: false,
bottom: true,
child: _scaffold(context),
),
)
: _scaffold(context)
: NoNetwork(context);
}
Widget _scaffold(BuildContext context) {
return Consumer<Crmdashboardprovider>(
return Consumer<followUpUpdateProvider>(
builder: (context, provider, child) {
return Scaffold(
resizeToAvoidBottomInset: true,
......@@ -154,9 +154,9 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
children: [
Text(
provider.selectedTime.hour.toString() +
":" +
provider.selectedTime.minute
.toString() ??
":" +
provider.selectedTime.minute
.toString() ??
"Enter in Time",
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.w400),
......@@ -185,20 +185,21 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
],
),
items:
<String>['Active', 'Inactive', 'Suspense']
.map(
(value) => DropdownMenuItem<String>(
value: value,
child: Text(
value ?? '',
style: const TextStyle(
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
),
<String>['Phone', 'Visit']
.map(
(value) =>
DropdownMenuItem<String>(
value: value,
child: Text(
value ?? '',
style: const TextStyle(
fontSize: 14,
),
)
.toList(),
overflow: TextOverflow.ellipsis,
),
),
)
.toList(),
value: provider.selectedFollowupType,
onChanged: (String? newValue) {
setState(() {
......@@ -216,10 +217,10 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
),
textControllerWidget(
context,
followUpFeedbackController,
provider.followUpFeedbackController,
"Feedback",
"Write Feedback",
onFollowUpChanged,
provider.onFollowUpChanged,
TextInputType.text,
false,
null,
......@@ -244,26 +245,21 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
],
),
items:
<String>[
'Cold',
'Hot',
'Warm',
'Open',
'Closed',
]
.map(
(value) => DropdownMenuItem<String>(
value: value,
child: Text(
value ?? '',
style: const TextStyle(
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
),
<String>['Cold', 'Hot', 'Warm']
.map(
(value) =>
DropdownMenuItem<String>(
value: value,
child: Text(
value ?? '',
style: const TextStyle(
fontSize: 14,
),
)
.toList(),
overflow: TextOverflow.ellipsis,
),
),
)
.toList(),
value: provider.selectedLeadStatus,
onChanged: (String? newValue) {
setState(() {
......@@ -302,26 +298,24 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
],
),
items:
<String>[
'Cold',
'Hot',
'Warm',
'Open',
'Closed',
]
.map(
(value) => DropdownMenuItem<String>(
value: value,
child: Text(
value ?? '',
style: const TextStyle(
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
),
<String>[
'Next Appointment',
'Update Order Status',
]
.map(
(value) =>
DropdownMenuItem<String>(
value: value,
child: Text(
value ?? '',
style: const TextStyle(
fontSize: 14,
),
)
.toList(),
overflow: TextOverflow.ellipsis,
),
),
)
.toList(),
value: provider.nextAppointmentStatus,
onChanged: (String? newValue) {
setState(() {
......@@ -341,128 +335,354 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
),
),
SizedBox(height: 15),
Container(
padding: EdgeInsets.only(left: 10),
alignment: Alignment.topLeft,
child: Text(
"Next Appointment",
style: TextStyle(color: AppColors.grey_thick, fontSize: 16),
),
),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
if (provider.nextAppointmentStatus ==
"Update Order Status") ...[
Container(
padding: EdgeInsets.only(left: 10),
alignment: Alignment.topLeft,
child: Text(
"Update Order Status",
style: TextStyle(
color: AppColors.grey_thick,
fontSize: 16,
),
),
),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
TextWidget(context, "Next Appointment Date"),
Container(
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: AppColors.text_field_color,
borderRadius: BorderRadius.circular(14),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10, 0),
child: TextFormField(
controller: provider.nextAppointmentDateController,
keyboardType: TextInputType.text,
enabled: false,
maxLines: 1,
readOnly: true,
onChanged: (value) {},
decoration: InputDecoration(
hintText: "Enter Date",
hintStyle: TextStyle(
fontWeight: FontWeight.w400,
color: Color(0xFFB4BEC0),
fontSize: 14,
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
TextWidget(context, "Select Status"),
DropdownButtonHideUnderline(
child: Row(
children: [
Expanded(
child: DropdownButton2<String>(
isExpanded: true,
hint: const Row(
children: [
Expanded(
child: Text(
'Select Status',
style: TextStyle(fontSize: 14),
overflow: TextOverflow.ellipsis,
),
),
],
),
items:
<String>[
'Order Gain',
'Order Lost',
'No Requirement',
]
.map(
(value) =>
DropdownMenuItem<String>(
value: value,
child: Text(
value ?? '',
style: const TextStyle(
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
),
),
)
.toList(),
value: provider.selectOrderStatus,
onChanged: (String? newValue) {
setState(() {
provider.selectOrderStatus = newValue!;
});
},
buttonStyleData: ddtheme.buttonStyleData,
iconStyleData: ddtheme.iconStyleData,
menuItemStyleData: ddtheme.menuItemStyleData,
dropdownStyleData: ddtheme.dropdownStyleData,
),
),
enabledBorder: InputBorder.none,
disabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
),
],
),
),
),
TextWidget(context, "Appointment Type"),
DropdownButtonHideUnderline(
child: Row(
children: [
Expanded(
child: DropdownButton2<String>(
isExpanded: true,
hint: const Row(
if (provider.selectOrderStatus == "Order Gain")
...[]
else
...[
if (provider.selectOrderStatus == "Order Lost") ...[
TextWidget(context, "Select Competitor"),
DropdownButtonHideUnderline(
child: Row(
children: [
Expanded(
child: Text(
'Select Appointment Type',
style: TextStyle(fontSize: 14),
overflow: TextOverflow.ellipsis,
child: DropdownButton2<String>(
isExpanded: true,
hint: const Row(
children: [
Expanded(
child: Text(
'Select Competitor',
style: TextStyle(fontSize: 14),
overflow: TextOverflow.ellipsis,
),
),
],
),
items:
<String>[
"Mahindra",
"Kirloskar",
"Cummins",
"Ashok Leyland",
"Escorts",
"Eicher",
"Eicher Volovo",
"Ecogen",
"Crompton Greaves",
"Caterpillar",
]
.map(
(value) =>
DropdownMenuItem<String>(
value: value,
child: Text(
value ?? '',
style: const TextStyle(
fontSize: 14,
),
overflow:
TextOverflow
.ellipsis,
),
),
)
.toList(),
value: provider.selectedCompetitor,
onChanged: (String? newValue) {
setState(() {
provider.selectedCompetitor =
newValue!;
});
},
buttonStyleData: ddtheme
.buttonStyleData,
iconStyleData: ddtheme.iconStyleData,
menuItemStyleData:
ddtheme.menuItemStyleData,
dropdownStyleData:
ddtheme.dropdownStyleData,
),
),
],
),
items:
<String>['Active', 'Inactive', 'Suspense']
.map(
(value) => DropdownMenuItem<String>(
value: value,
),
] else
if (provider.selectOrderStatus ==
"No Requirement")
...[],
textControllerWidget(
context,
provider.reasonController,
"Reason",
"Reason (Description)",
provider.onReasonChanged,
TextInputType.text,
false,
null,
),
],
],
),
),
] else
...[
Container(
padding: EdgeInsets.only(left: 10),
alignment: Alignment.topLeft,
child: Text(
"Next Appointment",
style: TextStyle(
color: AppColors.grey_thick,
fontSize: 16,
),
),
),
GestureDetector(
onTap: () {
provider.showDatePickerDialog(context);
},
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
padding: EdgeInsets.symmetric(
horizontal: 10, vertical: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
TextWidget(context, "Next Appointment Date"),
Container(
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: AppColors.text_field_color,
borderRadius: BorderRadius.circular(14),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(
10.0,
0.0,
10,
0,
),
child: TextFormField(
controller:
provider.nextAppointmentDateController,
keyboardType: TextInputType.text,
enabled: false,
maxLines: 1,
readOnly: true,
onChanged: (value) {},
decoration: InputDecoration(
hintText: "Enter Date",
hintStyle: TextStyle(
fontWeight: FontWeight.w400,
color: Color(0xFFB4BEC0),
fontSize: 14,
),
enabledBorder: InputBorder.none,
disabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
),
),
),
),
TextWidget(context, "Appointment Type"),
DropdownButtonHideUnderline(
child: Row(
children: [
Expanded(
child: DropdownButton2<String>(
isExpanded: true,
hint: const Row(
children: [
Expanded(
child: Text(
value ?? '',
style: const TextStyle(
fontSize: 14,
),
'Select Appointment Type',
style: TextStyle(fontSize: 14),
overflow: TextOverflow.ellipsis,
),
),
)
.toList(),
value: provider.selectNextAppointmentType,
onChanged: (String? newValue) {
setState(() {
provider.selectNextAppointmentType =
newValue!;
});
],
),
items:
<String>['Phone', 'Visit']
.map(
(value) =>
DropdownMenuItem<String>(
value: value,
child: Text(
value ?? '',
style: const TextStyle(
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
),
),
)
.toList(),
value: provider.selectNextAppointmentType,
onChanged: (String? newValue) {
setState(() {
provider.selectNextAppointmentType =
newValue!;
});
},
buttonStyleData: ddtheme.buttonStyleData,
iconStyleData: ddtheme.iconStyleData,
menuItemStyleData: ddtheme
.menuItemStyleData,
dropdownStyleData: ddtheme
.dropdownStyleData,
),
),
],
),
),
if (provider.selectNextAppointmentType ==
"Visit") ...[
CheckboxListTile(
checkboxShape: CircleBorder(),
controlAffinity: ListTileControlAffinity.leading,
value: provider.checked,
contentPadding: EdgeInsets.symmetric(
horizontal: 0),
title: Text(
"Send SMS reminder to Customer",
style: TextStyle(
fontSize: 14,
fontFamily: "JakartaRegular",
),
),
onChanged: (value) {
provider.checked = !provider.checked;
if (value == true) {
provider.smsSent = "1";
} else {
provider.smsSent = "0";
}
print(provider.smsSent +
provider.checked.toString());
},
buttonStyleData: ddtheme.buttonStyleData,
iconStyleData: ddtheme.iconStyleData,
menuItemStyleData: ddtheme.menuItemStyleData,
dropdownStyleData: ddtheme.dropdownStyleData,
),
],
textControllerWidget(
context,
provider.noteController,
"Note",
"Write Note",
provider.onNoteChanged,
TextInputType.text,
false,
null,
),
],
),
),
textControllerWidget(
context,
noteController,
"Note",
"Write Note",
onNoteChanged,
TextInputType.text,
false,
null,
),
],
),
),
),
],
SizedBox(height: 150),
],
),
),
floatingActionButtonLocation:
FloatingActionButtonLocation.centerFloat,
FloatingActionButtonLocation.centerFloat,
floatingActionButton: InkResponse(
onTap: () {},
onTap:provider.submitLoading?null: () {
provider.submitLoading = true;
provider.crmAddFollowUpAPIFunction(
context,
provider.nextAppointmentStatus,
provider.selectOrderStatus,
widget.leadID,
provider.selectedFollowupType,
provider.selectedCompetitor,
provider.selectedLeadStatus,
provider.selectNextAppointmentType,
provider.smsSent,
widget.mode);
},
child: Container(
height: 45,
alignment: Alignment.center,
......@@ -472,7 +692,9 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
color: AppColors.app_blue,
borderRadius: BorderRadius.circular(15),
),
child: Text(
child:provider.submitLoading?CircularProgressIndicator.adaptive(
valueColor: AlwaysStoppedAnimation(AppColors.white),
): Text(
"Submit",
style: TextStyle(
fontSize: 15,
......
import 'dart:io';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import '../../Models/crmModels/crmLeadDetailsGenerateQuotationViewResponse.dart';
import '../../Notifiers/crmProvider/crmGenerateQuotationProvider.dart';
import '../../Notifiers/crmProvider/crmLeadDetailsProvider.dart';
import '../../Utils/app_colors.dart';
import '../../Utils/commonServices.dart';
import '../../Utils/commonWidgets.dart';
import '../../Utils/dropdownTheme.dart';
class Generatequotationaddeditproduct extends StatefulWidget {
final leadId;
final type;
final product;
final index;
const Generatequotationaddeditproduct({
super.key,
required this.leadId,
this.type,
this.product,
this.index,
});
@override
State<Generatequotationaddeditproduct> createState() =>
_GeneratequotationaddeditproductState();
}
class _GeneratequotationaddeditproductState
extends State<Generatequotationaddeditproduct> {
Map _source = {ConnectivityResult.mobile: true};
final MyConnectivity _connectivity = MyConnectivity.instance;
Dropdowntheme ddtheme = Dropdowntheme();
@override
void initState() {
// TODO: implement initState
super.initState();
_connectivity.initialise();
_connectivity.myStream.listen((source) {
setState(() => _source = source);
});
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
final provider = Provider.of<Crmgeneratequotationprovider>(
context,
listen: false,
);
provider.crmLeadDetailsGenerateQuoteViewAPIFunction(
context,
widget.leadId,
);
// provider.resetForm();
if (widget.type == "add") {
// Initialize controllers and dropdowns after API call
provider.addEditInitializeForm(context);
} else {
provider.preFillFormForEdit(widget.product);
}
});
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_connectivity.disposeStream();
}
@override
Widget build(BuildContext context) {
switch (_source.keys.toList()[0]) {
case ConnectivityResult.mobile:
connection = 'Online';
break;
case ConnectivityResult.wifi:
connection = 'Online';
break;
case ConnectivityResult.none:
default:
connection = 'Offline';
}
return (connection == "Online")
? Platform.isAndroid
? WillPopScope(
onWillPop: () => onBackPressed(context),
child: SafeArea(
top: false,
bottom: true,
child: _scaffold(context),
),
)
: _scaffold(context)
: NoNetwork(context);
}
Widget _scaffold(BuildContext context) {
return Consumer<Crmgeneratequotationprovider>(
builder: (context, provider, child) {
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: appbarNew(context, "Generate Quotation", 0xFFFFFFFF),
backgroundColor: AppColors.scaffold_bg_color,
body: SingleChildScrollView(
child: Column(
children: [
Container(
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
margin: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextWidget(context, "Product"),
DropdownButtonHideUnderline(
child: Row(
children: [
Expanded(
child: DropdownButton2<LeadProducts>(
isExpanded: true,
hint: const Text(
'Select Product',
style: TextStyle(fontSize: 14),
overflow: TextOverflow.ellipsis,
),
items:
provider.leadProductsList
.map(
(
ord,
) => DropdownMenuItem<LeadProducts>(
value: ord,
child: Text(
"(Product Name: ${ord.productName})",
style: const TextStyle(
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
),
),
)
.toList(),
// provider.selectedOrderIds[index] != null?
// provider
// .orderList
// .firstWhere(
// (product) =>
// product
// .orderId ==
// provider
// .selectedOrderIds[index],
// )
value:
provider.selectedLeadProducts != null
? provider.leadProductsList.firstWhere(
(element) =>
element.id ==
provider
.selectedAddEditLeadProductId,
)
: null,
onChanged: (LeadProducts? value) {
if (value != null) {
provider.selectedLeadProducts = value;
provider.selectedAddEditLeadProductId =
value!.productId!;
provider.selectedAddEditLeadProductName =
value.productName;
}
},
buttonStyleData: ddtheme.buttonStyleData,
iconStyleData: ddtheme.iconStyleData,
menuItemStyleData: ddtheme.menuItemStyleData,
dropdownStyleData: ddtheme.dropdownStyleData,
),
),
],
),
),
const SizedBox(height: 10),
textControllerWidget(
context,
provider.addEditProductPriceController,
"Product Price",
"Enter Product Price",
provider.addEditUpdateTotalAmount,
TextInputType.number,
false,
FilteringTextInputFormatter.digitsOnly,
),
const SizedBox(height: 10),
textControllerWidget(
context,
provider.addEditQuantityController,
"Quantity",
"Enter Quantity",
provider.addEditUpdateTotalAmount,
TextInputType.number,
false,
FilteringTextInputFormatter.digitsOnly,
),
const SizedBox(height: 10),
Row(
children: [
Expanded(
flex: 2,
child: textControllerWidget(
context,
provider.addEditTotalAmountController,
"Amount",
"Total Amount",
(_) {},
TextInputType.number,
true,
FilteringTextInputFormatter.digitsOnly,
),
),
],
),
// IconButton(
// icon: const Icon(Icons.delete),
// onPressed: provider.editProductPriceControllers.length > 1
// ? () => provider.editRemoveRow(j)
// : null,
// ),
],
),
),
],
),
),
floatingActionButtonLocation:
FloatingActionButtonLocation.centerFloat,
floatingActionButton: InkWell(
onTap: () {
if (provider.selectedLeadProducts != null) {
var newProduct;
if (widget.type == "add") {
newProduct = LeadProducts(
id: provider.selectedAddEditLeadProductId,
productName: provider.selectedAddEditLeadProductName,
price: provider.addEditProductPriceController.text,
qty: provider.addEditQuantityController.text,
prodTotalPrice: provider.addEditTotalAmountController.text,
);
provider.leadProductsList.add(newProduct);
provider.productRows.add({
"product_id": provider.selectedAddEditLeadProductId!,
"price": provider.addEditProductPriceController.text,
"qty": provider.addEditQuantityController.text,
"net_price": provider.addEditTotalAmountController.text,
});
Navigator.pop(context, newProduct);
} else {
final updatedProduct = LeadProducts(
id: provider.selectedAddEditLeadProductId,
productName: provider.selectedAddEditLeadProductName,
price: provider.addEditProductPriceController.text,
qty: provider.addEditQuantityController.text,
prodTotalPrice: provider.addEditTotalAmountController.text,
);
provider.editProduct(widget.index!, updatedProduct);
Navigator.pop(context, updatedProduct);
}
// if (widget.index != null) {
// // Editing existing product
// provider.editProduct(widget.index!, newProduct);
// } else {
// // Adding new product
// provider.addProduct(newProduct);
// }
}
},
child: Container(
alignment: Alignment.center,
height: 45,
decoration: BoxDecoration(
color: AppColors.app_blue, //1487C9
borderRadius: BorderRadius.circular(14.0),
),
margin: EdgeInsets.symmetric(horizontal: 10),
child: Center(
child: Text(
"Submit",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
),
),
),
);
},
);
}
}
import 'dart:io';
import 'package:dotted_line/dotted_line.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:generp/Utils/dropdownTheme.dart';
import 'package:generp/screens/crm/generateQuotationAddEditProduct.dart';
import 'package:provider/provider.dart';
import '../../Models/crmModels/crmLeadDetailsGenerateQuotationViewResponse.dart';
......@@ -39,7 +41,7 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
);
// Initialize controllers and dropdowns after API call
provider.initializeForm(context);
provider.addEditInitializeForm(context);
});
}
......@@ -49,297 +51,565 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
builder: (context, provider, child) {
return WillPopScope(
onWillPop: () async {
// provider.resetForm();
provider.resetForm();
return true;
},
child: SafeArea(
top: false,
bottom: Platform.isIOS?false:true,
bottom: Platform.isIOS ? false : true,
child: Scaffold(
resizeToAvoidBottomInset: true,
backgroundColor: AppColors.scaffold_bg_color,
appBar: appbar2(
appBar: appbar2New(
context,
"Generate Quotation",
provider.resetForm,
const SizedBox(width: 0),
0xFFFFFFFF,
),
body: Container(
decoration: BoxDecoration(color: AppColors.white),
padding: const EdgeInsets.symmetric(horizontal: 10),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
textControllerWidget(
context,
provider.mailIdController,
"Email Id",
"Enter Email Id",
provider.onChangemailId,
TextInputType.emailAddress,
false,
null,
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
errorWidget(context, provider.mailIdError),
textControllerWidget(
context,
provider.mobileController,
"Mobile Number",
"Enter Mobile Number",
provider.onChangemobile,
TextInputType.phone,
false,
FilteringTextInputFormatter.digitsOnly,
margin: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
errorWidget(context, provider.mobileError),
textControllerWidget(
context,
provider.subjectsController,
"Subject",
"Enter Subject",
provider.onChangesubjects,
TextInputType.text,
false,
null,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
errorWidget(context, provider.subjectsError),
child: Column(
children: [
textControllerWidget(
context,
provider.mailIdController,
"Email Id",
"Enter Email Id",
provider.onChangemailId,
TextInputType.emailAddress,
false,
null,
),
errorWidget(context, provider.mailIdError),
InkResponse(
onTap: () {
provider.editAddNewRow();
},
child: Container(
margin: const EdgeInsets.symmetric(vertical: 10),
height: 45,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: const Color(0xFFE6F6FF),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: AppColors.app_blue,
width: 0.5,
),
textControllerWidget(
context,
provider.mobileController,
"Mobile Number",
"Enter Mobile Number",
provider.onChangemobile,
TextInputType.phone,
false,
FilteringTextInputFormatter.digitsOnly,
),
child: Center(
child: Text(
"+ Add Product",
style: TextStyle(
fontFamily: "JakartaMedium",
color: AppColors.app_blue,
),
),
errorWidget(context, provider.mobileError),
textControllerWidget(
context,
provider.subjectsController,
"Subject",
"Enter Subject",
provider.onChangesubjects,
TextInputType.text,
false,
null,
),
),
errorWidget(context, provider.subjectsError),
],
),
if (provider.leadProductsList.isNotEmpty ||
provider.editProductPriceControllers.isNotEmpty) ...[
ListView.builder(
itemCount: provider.editProductPriceControllers.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, j) {
return Container(
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
),
Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
margin: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
children: [
InkResponse(
onTap: () async {
var res = await Navigator.push(
context,
MaterialPageRoute(
builder:
(context) =>
Generatequotationaddeditproduct(
leadId: widget.leadId,
type: "add",
),
settings: RouteSettings(
name: 'Generatequotationaddeditproduct',
),
),
);
if (res != null) {
print("result ${res}");
// provider
// .crmLeadDetailsGenerateQuoteViewAPIFunction(
// context,
// widget.leadId,
// );
}
},
child: Container(
margin: const EdgeInsets.symmetric(vertical: 10),
height: 45,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
color: const Color(0xFFE6F6FF),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: AppColors.app_blue,
width: 0.5,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextWidget(context, "Product"),
DropdownButtonHideUnderline(
child: Row(
children: [
Expanded(
child: DropdownButton2<LeadProducts>(
isExpanded: true,
hint: const Text(
'Select Product',
style: TextStyle(fontSize: 14),
overflow: TextOverflow.ellipsis,
child: Center(
child: Text(
"+ Add Product",
style: TextStyle(
fontFamily: "JakartaMedium",
color: AppColors.app_blue,
),
),
),
),
),
if (provider.leadProductsList.isNotEmpty) ...[
SizedBox(
width: double.infinity,
height: 125,
child: ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(
vertical: 15,
horizontal: 0,
),
itemCount: provider.leadProductsList.length,
itemBuilder: (context, lp) {
return InkResponse(
onTap: () async {
var res = await Navigator.push(
context,
MaterialPageRoute(
builder:
(
context,
) => Generatequotationaddeditproduct(
leadId: widget.leadId,
type: "edit",
product:
provider
.leadProductsList[lp]!,
index: lp,
),
settings: RouteSettings(
name:
'Generatequotationaddeditproduct',
),
),
);
if (res != null) {
print("result ${res}");
}
},
child: Container(
height: 115,
width:
MediaQuery.of(context).size.width *
0.8,
decoration: BoxDecoration(
color: Color(0xFFE6F6FF),
borderRadius: BorderRadius.circular(14),
),
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 8,
),
margin: EdgeInsets.symmetric(
horizontal: 5,
// vertical: 10,
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Expanded(
flex: 1,
child: SvgPicture.asset(
"assets/svg/crm/product_details_ic.svg",
),
items:
provider.leadProductsList
.map(
(ord) => DropdownMenuItem<
LeadProducts
>(
value: ord,
),
SizedBox(width: 10),
Expanded(
flex: 6,
child: SizedBox(
child: Column(
// mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Row(
children: [
Expanded(
flex: 4,
child: Text(
"(Product Name: ${ord.productName})",
style: const TextStyle(
fontSize: 14,
),
provider
.leadProductsList[lp]
.productName ??
"-",
maxLines: 1,
overflow:
TextOverflow
.ellipsis,
style: TextStyle(
fontFamily:
"JakartaMedium",
fontSize: 14,
color:
AppColors
.semi_black,
),
),
),
)
.toList(),
value:
provider.selectedProductIds[j] !=
null
? provider.leadProductsList
.firstWhere(
(ord) =>
ord.id ==
provider
.selectedProductIds[j],
orElse:
() =>
provider
.leadProductsList[0],
)
: null,
onChanged: (LeadProducts? value) {
if (value != null) {
provider.updateSelectedProductIds(
j,
value,
);
provider.selectedProductIds[j] =
value.id?.toString() ?? '';
provider.updateTotalAmount(j);
}
},
buttonStyleData:
ddtheme.buttonStyleData,
iconStyleData: ddtheme.iconStyleData,
menuItemStyleData:
ddtheme.menuItemStyleData,
dropdownStyleData:
ddtheme.dropdownStyleData,
Expanded(
flex: 2,
child: Text(
textAlign:
TextAlign.right,
"₹${provider.leadProductsList[lp].price ?? "-"}",
style: TextStyle(
fontFamily:
"JakartaMedium",
fontSize: 14,
color:
AppColors
.semi_black,
),
),
),
],
),
Text(
"x ${provider.leadProductsList[lp].qty ?? "-"}",
style: TextStyle(
fontFamily:
"JakartaMedium",
fontSize: 14,
color:
AppColors.grey_semi,
),
),
SizedBox(height: 5),
DottedLine(
dashGapLength: 4,
dashGapColor: Colors.white,
dashColor:
AppColors.grey_semi,
dashLength: 2,
lineThickness: 0.5,
),
SizedBox(height: 5),
Text(
"₹${provider.leadProductsList[lp].prodTotalPrice ?? " - "}",
style: TextStyle(
fontFamily:
"JakartaMedium",
fontSize: 14,
color:
AppColors.semi_black,
),
),
],
),
),
),
),
],
),
),
const SizedBox(height: 10),
Row(
children: [
Expanded(
flex: 2,
child: textControllerWidget(
context,
provider.editProductPriceControllers[j],
"Product Price",
"Enter Product Price",
(value) =>
provider.updateTotalAmount(j),
TextInputType.number,
false,
FilteringTextInputFormatter.digitsOnly,
),
),
],
),
const SizedBox(height: 10),
Row(
children: [
Expanded(
flex: 2,
child: textControllerWidget(
context,
provider.editQuantityControllers[j],
"Quantity",
"Enter Quantity",
(value) =>
provider.updateTotalAmount(j),
TextInputType.number,
false,
FilteringTextInputFormatter.digitsOnly,
),
],
),
],
),
const SizedBox(height: 10),
Row(
children: [
Expanded(
flex: 2,
child: textControllerWidget(
context,
provider.editTotalAmountControllers[j],
"Amount",
"Total Amount",
(_) {},
TextInputType.number,
true,
FilteringTextInputFormatter.digitsOnly,
),
),
],
),
// IconButton(
// icon: const Icon(Icons.delete),
// onPressed: provider.editProductPriceControllers.length > 1
// ? () => provider.editRemoveRow(j)
// : null,
// ),
],
),
);
},
),
);
},
),
],
textControllerWidget(
context,
provider.taxesController,
"Taxes",
"Enter Taxes",
provider.onChangetaxes,
TextInputType.text,
false,
null,
),
],
// if (provider.leadProductsList.isNotEmpty ||
// provider
// .editProductPriceControllers
// .isNotEmpty) ...[
// ListView.builder(
// itemCount:
// provider.editProductPriceControllers.length,
// physics: const NeverScrollableScrollPhysics(),
// shrinkWrap: true,
// itemBuilder: (context, j) {
// return Container(
// padding: const EdgeInsets.symmetric(
// horizontal: 10,
// vertical: 10,
// ),
// margin: const EdgeInsets.symmetric(
// vertical: 10,
// ),
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(20),
// ),
// child: Column(
// crossAxisAlignment:
// CrossAxisAlignment.start,
// children: [
// TextWidget(context, "Product"),
// DropdownButtonHideUnderline(
// child: Row(
// children: [
// Expanded(
// child: DropdownButton2<
// LeadProducts
// >(
// isExpanded: true,
// hint: const Text(
// 'Select Product',
// style: TextStyle(
// fontSize: 14,
// ),
// overflow:
// TextOverflow.ellipsis,
// ),
// items:
// provider.leadProductsList
// .map(
// (
// ord,
// ) => DropdownMenuItem<
// LeadProducts
// >(
// value: ord,
// child: Text(
// "(Product Name: ${ord.productName})",
// style:
// const TextStyle(
// fontSize:
// 14,
// ),
// overflow:
// TextOverflow
// .ellipsis,
// ),
// ),
// )
// .toList(),
// value:
// provider.selectedProductIds[j] !=
// null
// ? provider
// .leadProductsList
// .firstWhere(
// (ord) =>
// ord.id ==
// provider
// .selectedProductIds[j],
// orElse:
// () =>
// provider
// .leadProductsList[0],
// )
// : null,
// onChanged: (
// LeadProducts? value,
// ) {
// if (value != null) {
// provider
// .updateSelectedProductIds(
// j,
// value,
// );
// provider.selectedProductIds[j] =
// value.id?.toString() ??
// '';
// provider.updateTotalAmount(
// j,
// );
// }
// },
// buttonStyleData:
// ddtheme.buttonStyleData,
// iconStyleData:
// ddtheme.iconStyleData,
// menuItemStyleData:
// ddtheme.menuItemStyleData,
// dropdownStyleData:
// ddtheme.dropdownStyleData,
// ),
// ),
// ],
// ),
// ),
// const SizedBox(height: 10),
// Row(
// children: [
// Expanded(
// flex: 2,
// child: textControllerWidget(
// context,
// provider
// .editProductPriceControllers[j],
// "Product Price",
// "Enter Product Price",
// (value) =>
// provider.updateTotalAmount(j),
// TextInputType.number,
// false,
// FilteringTextInputFormatter
// .digitsOnly,
// ),
// ),
// ],
// ),
// const SizedBox(height: 10),
// Row(
// children: [
// Expanded(
// flex: 2,
// child: textControllerWidget(
// context,
// provider
// .editQuantityControllers[j],
// "Quantity",
// "Enter Quantity",
// (value) =>
// provider.updateTotalAmount(j),
// TextInputType.number,
// false,
// FilteringTextInputFormatter
// .digitsOnly,
// ),
// ),
// ],
// ),
// const SizedBox(height: 10),
// Row(
// children: [
// Expanded(
// flex: 2,
// child: textControllerWidget(
// context,
// provider
// .editTotalAmountControllers[j],
// "Amount",
// "Total Amount",
// (_) {},
// TextInputType.number,
// true,
// FilteringTextInputFormatter
// .digitsOnly,
// ),
// ),
// ],
// ),
// // IconButton(
// // icon: const Icon(Icons.delete),
// // onPressed: provider.editProductPriceControllers.length > 1
// // ? () => provider.editRemoveRow(j)
// // : null,
// // ),
// ],
// ),
// );
// },
// ),
// ],
],
),
errorWidget(context, provider.taxesError),
),
textControllerWidget(
context,
provider.SpecialNoteController,
"Special Note",
"Enter Special Note",
provider.onChangeSpecialNote,
TextInputType.text,
false,
null,
Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
errorWidget(context, provider.SpecialNoteError),
textControllerWidget(
context,
provider.forController,
"FOR",
"Enter FOR",
provider.onChangefor,
TextInputType.text,
false,
null,
margin: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
errorWidget(context, provider.forError),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
children: [
textControllerWidget(
context,
provider.taxesController,
"Taxes",
"Enter Taxes",
provider.onChangetaxes,
TextInputType.text,
false,
null,
),
errorWidget(context, provider.taxesError),
textControllerWidget(
context,
provider.paymentTermsController,
"Payment Terms",
"Enter Payment Terms",
provider.onChangepaymentTerms,
TextInputType.text,
false,
null,
textControllerWidget(
context,
provider.SpecialNoteController,
"Special Note",
"Enter Special Note",
provider.onChangeSpecialNote,
TextInputType.text,
false,
null,
),
errorWidget(context, provider.SpecialNoteError),
textControllerWidget(
context,
provider.forController,
"FOR",
"Enter FOR",
provider.onChangefor,
TextInputType.text,
false,
null,
),
errorWidget(context, provider.forError),
textControllerWidget(
context,
provider.paymentTermsController,
"Payment Terms",
"Enter Payment Terms",
provider.onChangepaymentTerms,
TextInputType.text,
false,
null,
),
errorWidget(context, provider.paymentTermsError),
],
),
errorWidget(context, provider.paymentTermsError),
],
),
),
],
),
),
......@@ -369,12 +639,13 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
? null
: () {
//genquotedown
final insertedData = provider.getFormData();
final insertedData = provider.productRows;
print(insertedData);
provider
.crmLeadDetailsGenerateQuoteSubmitAPIFunction(
context,
widget.leadId,
insertedData,
insertedData,
"genquotedown",
);
},
......@@ -400,7 +671,9 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
AppColors.app_blue,
),
)
: SvgPicture.asset("assets/svg/download_quote.svg"),
: SvgPicture.asset(
"assets/svg/download_quote.svg",
),
),
),
),
......@@ -412,14 +685,14 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
? null
: () {
//genquotemail,
final insertedData = provider.getFormData();
provider
.crmLeadDetailsGenerateQuoteSubmitAPIFunction(
context,
widget.leadId,
insertedData,
"genquotemail",
);
final insertedData = provider.getFormData();
provider
.crmLeadDetailsGenerateQuoteSubmitAPIFunction(
context,
widget.leadId,
insertedData,
"genquotemail",
);
},
child: Container(
height: 45,
......@@ -443,7 +716,9 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
AppColors.app_blue,
),
)
: SvgPicture.asset("assets/svg/mail_quote.svg")
: SvgPicture.asset(
"assets/svg/mail_quote.svg",
),
),
),
),
......@@ -455,14 +730,14 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
? null
: () {
//genquotewhatsapp,
final insertedData = provider.getFormData();
provider
.crmLeadDetailsGenerateQuoteSubmitAPIFunction(
context,
widget.leadId,
insertedData,
"genquotewhatsapp",
);
final insertedData = provider.getFormData();
provider
.crmLeadDetailsGenerateQuoteSubmitAPIFunction(
context,
widget.leadId,
insertedData,
"genquotewhatsapp",
);
},
child: Container(
height: 45,
......@@ -486,7 +761,9 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
AppColors.app_blue,
),
)
: SvgPicture.asset("assets/svg/whatsapp_quote.svg")
: SvgPicture.asset(
"assets/svg/whatsapp_quote.svg",
),
),
),
),
......@@ -498,14 +775,14 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
? null
: () {
//genquotewhatsappbymynum,
final insertedData = provider.getFormData();
provider
.crmLeadDetailsGenerateQuoteSubmitAPIFunction(
context,
widget.leadId,
insertedData,
"genquotewhatsappbymynum",
);
final insertedData = provider.getFormData();
provider
.crmLeadDetailsGenerateQuoteSubmitAPIFunction(
context,
widget.leadId,
insertedData,
"genquotewhatsappbymynum",
);
},
child: Container(
height: 45,
......@@ -529,7 +806,9 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
AppColors.app_blue,
),
)
:SvgPicture.asset("assets/svg/whatsapp_quote_self.svg")
: SvgPicture.asset(
"assets/svg/whatsapp_quote_self.svg",
),
),
),
),
......
......@@ -37,7 +37,7 @@ class _PendingtasksdetailsState extends State<Pendingtasksdetails> {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
var prov = Provider.of<Crmdashboardprovider>(context, listen: false);
prov.accessPagesAPIFunction(context);
prov.crmDashboardAPIFunction(context, "executive", "", "", "");
prov.crmDashboardAPIFunction(context);
prov.crmPendingTasksAPIFunction(context);
});
}
......@@ -255,7 +255,9 @@ class _PendingtasksdetailsState extends State<Pendingtasksdetails> {
onTap: () async {
await Navigator.push(
context,
MaterialPageRoute(builder: (context) => Followupupdatescreen()),
MaterialPageRoute(builder: (context) => Followupupdatescreen(
leadID: task.leadid,
)),
);
},
child: Container(
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment