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 { ...@@ -328,6 +328,7 @@ class LeadProducts {
String? productId; String? productId;
String? qty; String? qty;
String? price; String? price;
String? prodTotalPrice;
String? date; String? date;
String? isDel; String? isDel;
String? isExists; String? isExists;
...@@ -341,6 +342,7 @@ class LeadProducts { ...@@ -341,6 +342,7 @@ class LeadProducts {
this.productId, this.productId,
this.qty, this.qty,
this.price, this.price,
this.prodTotalPrice,
this.date, this.date,
this.isDel, this.isDel,
this.isExists, this.isExists,
...@@ -354,6 +356,7 @@ class LeadProducts { ...@@ -354,6 +356,7 @@ class LeadProducts {
productId = json['product_id']; productId = json['product_id'];
qty = json['qty']; qty = json['qty'];
price = json['price']; price = json['price'];
prodTotalPrice = json['prod_total_price'];
date = json['date']; date = json['date'];
isDel = json['is_del']; isDel = json['is_del'];
isExists = json['is_exists']; isExists = json['is_exists'];
...@@ -369,6 +372,7 @@ class LeadProducts { ...@@ -369,6 +372,7 @@ class LeadProducts {
data['product_id'] = this.productId; data['product_id'] = this.productId;
data['qty'] = this.qty; data['qty'] = this.qty;
data['price'] = this.price; data['price'] = this.price;
data['prod_total_price'] = this.prodTotalPrice;
data['date'] = this.date; data['date'] = this.date;
data['is_del'] = this.isDel; data['is_del'] = this.isDel;
data['is_exists'] = this.isExists; 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 { class crmDashboardResponse {
Hotleads? hotleads; Hotleads? hotleads;
Hotleads? pendingTasks;
Hotleads? coldleads; Hotleads? coldleads;
Hotleads? warmleads; Hotleads? warmleads;
Hotleads? totalleads; Hotleads? totalleads;
Hotleads? openleads;
Hotleads? visits;
Hotleads? calls;
Hotleads? quote;
Hotleads? orderlost; Hotleads? orderlost;
Hotleads? norequirement; Hotleads? norequirement;
Hotleads? openEnquiries; Hotleads? openEnquiries;
List<NearbyLeads>? nearbyLeads;
String? error; String? error;
String? message; String? message;
int? sessionExists;
crmDashboardResponse( crmDashboardResponse(
{this.hotleads, {this.hotleads,
this.pendingTasks,
this.coldleads, this.coldleads,
this.warmleads, this.warmleads,
this.totalleads, this.totalleads,
this.openleads,
this.visits,
this.calls,
this.quote,
this.orderlost, this.orderlost,
this.norequirement, this.norequirement,
this.openEnquiries, this.openEnquiries,
this.nearbyLeads,
this.error, this.error,
this.message}); this.message,
this.sessionExists});
crmDashboardResponse.fromJson(Map<String, dynamic> json) { crmDashboardResponse.fromJson(Map<String, dynamic> json) {
hotleads = json['hotleads'] != null hotleads = json['hotleads'] != null
? new Hotleads.fromJson(json['hotleads']) ? new Hotleads.fromJson(json['hotleads'])
: null; : null;
pendingTasks = json['pending_tasks'] != null
? new Hotleads.fromJson(json['pending_tasks'])
: null;
coldleads = json['coldleads'] != null coldleads = json['coldleads'] != null
? new Hotleads.fromJson(json['coldleads']) ? new Hotleads.fromJson(json['coldleads'])
: null; : null;
...@@ -33,6 +50,13 @@ class crmDashboardResponse { ...@@ -33,6 +50,13 @@ class crmDashboardResponse {
totalleads = json['totalleads'] != null totalleads = json['totalleads'] != null
? new Hotleads.fromJson(json['totalleads']) ? new Hotleads.fromJson(json['totalleads'])
: null; : 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 orderlost = json['orderlost'] != null
? new Hotleads.fromJson(json['orderlost']) ? new Hotleads.fromJson(json['orderlost'])
: null; : null;
...@@ -42,8 +66,15 @@ class crmDashboardResponse { ...@@ -42,8 +66,15 @@ class crmDashboardResponse {
openEnquiries = json['open_enquiries'] != null openEnquiries = json['open_enquiries'] != null
? new Hotleads.fromJson(json['open_enquiries']) ? new Hotleads.fromJson(json['open_enquiries'])
: null; : null;
if (json['nearby_leads'] != null) {
nearbyLeads = <NearbyLeads>[];
json['nearby_leads'].forEach((v) {
nearbyLeads!.add(new NearbyLeads.fromJson(v));
});
}
error = json['error']; error = json['error'];
message = json['message']; message = json['message'];
sessionExists = json['session_exists'];
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
...@@ -51,6 +82,9 @@ class crmDashboardResponse { ...@@ -51,6 +82,9 @@ class crmDashboardResponse {
if (this.hotleads != null) { if (this.hotleads != null) {
data['hotleads'] = this.hotleads!.toJson(); data['hotleads'] = this.hotleads!.toJson();
} }
if (this.pendingTasks != null) {
data['pending_tasks'] = this.pendingTasks!.toJson();
}
if (this.coldleads != null) { if (this.coldleads != null) {
data['coldleads'] = this.coldleads!.toJson(); data['coldleads'] = this.coldleads!.toJson();
} }
...@@ -60,6 +94,18 @@ class crmDashboardResponse { ...@@ -60,6 +94,18 @@ class crmDashboardResponse {
if (this.totalleads != null) { if (this.totalleads != null) {
data['totalleads'] = this.totalleads!.toJson(); 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) { if (this.orderlost != null) {
data['orderlost'] = this.orderlost!.toJson(); data['orderlost'] = this.orderlost!.toJson();
} }
...@@ -69,8 +115,12 @@ class crmDashboardResponse { ...@@ -69,8 +115,12 @@ class crmDashboardResponse {
if (this.openEnquiries != null) { if (this.openEnquiries != null) {
data['open_enquiries'] = this.openEnquiries!.toJson(); 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['error'] = this.error;
data['message'] = this.message; data['message'] = this.message;
data['session_exists'] = this.sessionExists;
return data; return data;
} }
} }
...@@ -124,3 +174,116 @@ class Filter { ...@@ -124,3 +174,116 @@ class Filter {
return data; 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 { ...@@ -3,9 +3,10 @@ class crmLeadDetailsGenerateQuotationViewResponse {
List<LeadProducts>? leadProducts; List<LeadProducts>? leadProducts;
String? error; String? error;
String? message; String? message;
int? sessionExists;
crmLeadDetailsGenerateQuotationViewResponse( crmLeadDetailsGenerateQuotationViewResponse(
{this.quoteDetails, this.leadProducts, this.error, this.message}); {this.quoteDetails, this.leadProducts, this.error, this.message,this.sessionExists});
crmLeadDetailsGenerateQuotationViewResponse.fromJson( crmLeadDetailsGenerateQuotationViewResponse.fromJson(
Map<String, dynamic> json) { Map<String, dynamic> json) {
...@@ -20,6 +21,7 @@ class crmLeadDetailsGenerateQuotationViewResponse { ...@@ -20,6 +21,7 @@ class crmLeadDetailsGenerateQuotationViewResponse {
} }
error = json['error']; error = json['error'];
message = json['message']; message = json['message'];
sessionExists = json['session_exists'];
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
...@@ -33,6 +35,7 @@ class crmLeadDetailsGenerateQuotationViewResponse { ...@@ -33,6 +35,7 @@ class crmLeadDetailsGenerateQuotationViewResponse {
} }
data['error'] = this.error; data['error'] = this.error;
data['message'] = this.message; data['message'] = this.message;
data['session_exists'] = this.sessionExists;
return data; return data;
} }
} }
...@@ -84,6 +87,7 @@ class LeadProducts { ...@@ -84,6 +87,7 @@ class LeadProducts {
String? productId; String? productId;
String? qty; String? qty;
String? price; String? price;
String? prodTotalPrice;
String? date; String? date;
String? isDel; String? isDel;
String? isExists; String? isExists;
...@@ -97,6 +101,7 @@ class LeadProducts { ...@@ -97,6 +101,7 @@ class LeadProducts {
this.productId, this.productId,
this.qty, this.qty,
this.price, this.price,
this.prodTotalPrice,
this.date, this.date,
this.isDel, this.isDel,
this.isExists, this.isExists,
...@@ -110,6 +115,7 @@ class LeadProducts { ...@@ -110,6 +115,7 @@ class LeadProducts {
productId = json['product_id']; productId = json['product_id'];
qty = json['qty']; qty = json['qty'];
price = json['price']; price = json['price'];
prodTotalPrice = json['prod_total_price'];
date = json['date']; date = json['date'];
isDel = json['is_del']; isDel = json['is_del'];
isExists = json['is_exists']; isExists = json['is_exists'];
...@@ -125,6 +131,7 @@ class LeadProducts { ...@@ -125,6 +131,7 @@ class LeadProducts {
data['product_id'] = this.productId; data['product_id'] = this.productId;
data['qty'] = this.qty; data['qty'] = this.qty;
data['price'] = this.price; data['price'] = this.price;
data['prod_total_price'] = this.prodTotalPrice;
data['date'] = this.date; data['date'] = this.date;
data['is_del'] = this.isDel; data['is_del'] = this.isDel;
data['is_exists'] = this.isExists; data['is_exists'] = this.isExists;
......
...@@ -3,6 +3,9 @@ import 'package:flutter/foundation.dart'; ...@@ -3,6 +3,9 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:generp/Models/crmModels/crmDashboardResponse.dart'; import 'package:generp/Models/crmModels/crmDashboardResponse.dart';
import 'package:generp/Utils/app_colors.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:intl/intl.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
...@@ -13,37 +16,20 @@ import '../../services/api_calling.dart'; ...@@ -13,37 +16,20 @@ import '../../services/api_calling.dart';
import '../HomeScreenNotifier.dart'; import '../HomeScreenNotifier.dart';
class Crmdashboardprovider extends ChangeNotifier { class Crmdashboardprovider extends ChangeNotifier {
TextEditingController nextAppointmentDateController = TextEditingController(); String _googleApikey = "AIzaSyBGzvgMMKwPBAANTwaoRsAnrCpiWCj8wVs";
TextEditingController searchController = TextEditingController(); TextEditingController searchController = TextEditingController();
List<PagesAccessible> _accessPages = []; List<PagesAccessible> _accessPages = [];
List<PagesAccessible> get accessPages => _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<Accounts> _accountsList = [];
List<Leads> _leadsList = []; List<Leads> _leadsList = [];
List<Enquires> _enquiresList = []; List<Enquires> _enquiresList = [];
TimeOfDay _selectedTime = TimeOfDay.now();
String _formattedTime = "";
String? _selectedFollowupType; LatLng? currentLocationLatLng;
String? _selectedLeadStatus; String latlongs = "";
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;
List<Accounts> get accountsList => _accountsList; List<Accounts> get accountsList => _accountsList;
...@@ -51,24 +37,54 @@ class Crmdashboardprovider extends ChangeNotifier { ...@@ -51,24 +37,54 @@ class Crmdashboardprovider extends ChangeNotifier {
List<Enquires> get enquiresList => _enquiresList; List<Enquires> get enquiresList => _enquiresList;
List<NearbyLeads> _nearByLeads = [];
List<NearbyLeads> get nearByLeads => _nearByLeads;
Hotleads _hotleads = Hotleads(); Hotleads _hotleads = Hotleads();
Hotleads get hotleads => _hotleads; Hotleads get hotleads => _hotleads;
Hotleads _pendingTasks = Hotleads();
Hotleads get pendingTasks => _pendingTasks;
Hotleads _coldleads = Hotleads(); Hotleads _coldleads = Hotleads();
Hotleads get coldleads => _coldleads; Hotleads get coldleads => _coldleads;
Hotleads _warmleads = Hotleads(); Hotleads _warmleads = Hotleads();
Hotleads get warmleads => _warmleads; Hotleads get warmleads => _warmleads;
Hotleads _totalleads = Hotleads(); Hotleads _totalleads = Hotleads();
Hotleads get totalleads => _totalleads; 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 _orderlost = Hotleads();
Hotleads get orderlost => _orderlost; Hotleads get orderlost => _orderlost;
Hotleads _norequirement = Hotleads(); Hotleads _norequirement = Hotleads();
Hotleads get norequirement => _norequirement; Hotleads get norequirement => _norequirement;
Hotleads _openEnquiries = Hotleads(); Hotleads _openEnquiries = Hotleads();
Hotleads get openEnquiries => _openEnquiries; Hotleads get openEnquiries => _openEnquiries;
...@@ -77,25 +93,7 @@ class Crmdashboardprovider extends ChangeNotifier { ...@@ -77,25 +93,7 @@ class Crmdashboardprovider extends ChangeNotifier {
List<Hotleads> get allLeads => _allLeads; 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 { Future<void> accessPagesAPIFunction(context) async {
try { try {
...@@ -116,47 +114,82 @@ class Crmdashboardprovider extends ChangeNotifier { ...@@ -116,47 +114,82 @@ class Crmdashboardprovider extends ChangeNotifier {
} catch (e, s) {} } catch (e, s) {}
} }
Future<void> crmDashboardAPIFunction( Future<void> getCurrentLocation(context) async {
context, try {
mode, Position position = await Geolocator.getCurrentPosition(
from, desiredAccuracy: geo_location.LocationAccuracy.high,
to, );
teamemployee, currentLocationLatLng = LatLng(position.latitude, position.longitude);
) async { 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 { try {
var HomeProv = Provider.of<HomescreenNotifier>(context, listen: false); var HomeProv = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.crmDashboardAPI( final data = await ApiCalling.crmDashboardAPI(
HomeProv.empId, HomeProv.empId,
HomeProv.session, HomeProv.session,
mode, latlongs,
from,
to,
teamemployee,
); );
if (data != null) { if (data != null) {
if (data.error == "0") { if (data.error == "0") {
_hotleads = data.hotleads!; _hotleads = data.hotleads!;
_pendingTasks = data.pendingTasks!;
_coldleads = data.coldleads!; _coldleads = data.coldleads!;
_warmleads = data.warmleads!; _warmleads = data.warmleads!;
_totalleads = data.totalleads!; _totalleads = data.totalleads!;
_openleads = data.openleads!;
_visits = data.visits!;
_calls = data.calls!;
_quote = data.quote!;
_orderlost = data.orderlost!; _orderlost = data.orderlost!;
_norequirement = data.norequirement!; _norequirement = data.norequirement!;
_openEnquiries = data.openEnquiries!; _openEnquiries = data.openEnquiries!;
_allLeads = [ _allLeads = [
_openleads,
_quote,
_pendingTasks,
_visits,
_calls,
_hotleads, _hotleads,
_coldleads, _coldleads,
_warmleads, _warmleads,
_totalleads,
_orderlost,
_norequirement,
_openEnquiries,
]; ];
_nearByLeads = data.nearbyLeads!;
notifyListeners(); notifyListeners();
} }
} }
} catch (e, s) {} } 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 { Future<void> crmPendingTasksAPIFunction(context) async {
try { try {
var HomeProv = Provider.of<HomescreenNotifier>(context, listen: false); var HomeProv = Provider.of<HomescreenNotifier>(context, listen: false);
...@@ -166,7 +199,7 @@ class Crmdashboardprovider extends ChangeNotifier { ...@@ -166,7 +199,7 @@ class Crmdashboardprovider extends ChangeNotifier {
); );
if (data != null) { if (data != null) {
if (data.error == "0") { if (data.error == "0") {
_pendingTasks = data.pendingTasks!; _pendingTasksList = data.pendingTasks!;
notifyListeners(); notifyListeners();
} }
} }
...@@ -192,117 +225,4 @@ class Crmdashboardprovider extends ChangeNotifier { ...@@ -192,117 +225,4 @@ class Crmdashboardprovider extends ChangeNotifier {
} catch (e, s) {} } 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'; ...@@ -6,6 +6,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_download_manager/flutter_download_manager.dart'; import 'package:flutter_download_manager/flutter_download_manager.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:generp/Models/crmModels/crmLeadDetailsGenerateQuotationViewResponse.dart'; import 'package:generp/Models/crmModels/crmLeadDetailsGenerateQuotationViewResponse.dart';
import 'package:generp/screens/LoginScreen.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
...@@ -18,11 +19,15 @@ import '../HomeScreenNotifier.dart'; ...@@ -18,11 +19,15 @@ import '../HomeScreenNotifier.dart';
class Crmgeneratequotationprovider extends ChangeNotifier { class Crmgeneratequotationprovider extends ChangeNotifier {
final FlutterLocalNotificationsPlugin _notificationsPlugin = final FlutterLocalNotificationsPlugin _notificationsPlugin =
FlutterLocalNotificationsPlugin(); FlutterLocalNotificationsPlugin();
static const platform = MethodChannel('in.webgrid.generp/download'); static const platform = MethodChannel('in.webgrid.generp/download');
final GlobalKey webViewKey = GlobalKey(); final GlobalKey webViewKey = GlobalKey();
var dl = DownloadManager(); var dl = DownloadManager();
TextEditingController addEditProductPriceController = TextEditingController();
TextEditingController addEditQuantityController = TextEditingController();
TextEditingController addEditTotalAmountController = TextEditingController();
TextEditingController mailIdController = TextEditingController(); TextEditingController mailIdController = TextEditingController();
TextEditingController mobileController = TextEditingController(); TextEditingController mobileController = TextEditingController();
TextEditingController subjectsController = TextEditingController(); TextEditingController subjectsController = TextEditingController();
...@@ -30,7 +35,14 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -30,7 +35,14 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
TextEditingController SpecialNoteController = TextEditingController(); TextEditingController SpecialNoteController = TextEditingController();
TextEditingController forController = TextEditingController(); TextEditingController forController = TextEditingController();
TextEditingController paymentTermsController = 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? mailIdError = "";
String? mobileError = ""; String? mobileError = "";
...@@ -45,6 +57,9 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -45,6 +57,9 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
bool _isLoading = true; bool _isLoading = true;
String? _quotationFilePath; String? _quotationFilePath;
LeadProducts? _selectedLeadProducts; LeadProducts? _selectedLeadProducts;
String? _selectedAddEditLeadProductId;
String? _selectedAddEditLeadProductName;
List<TextEditingController> editProductPriceControllers = []; List<TextEditingController> editProductPriceControllers = [];
List<TextEditingController> editQuantityControllers = []; List<TextEditingController> editQuantityControllers = [];
List<TextEditingController> editTotalAmountControllers = []; List<TextEditingController> editTotalAmountControllers = [];
...@@ -58,21 +73,88 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -58,21 +73,88 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
QuoteDetails get quoteDetails => _quoteDetails; QuoteDetails get quoteDetails => _quoteDetails;
List<LeadProducts> get leadProductsList => _leadProductsList; List<LeadProducts> get leadProductsList => _leadProductsList;
set leadProductsList(List<LeadProducts> value) {
_leadProductsList = value;
notifyListeners();
}
LeadProducts? get selectedLeadProducts => _selectedLeadProducts; LeadProducts? get selectedLeadProducts => _selectedLeadProducts;
bool get isLoading => _isLoading; bool get isLoading => _isLoading;
List<String?> get selectedProductIds => _selectedProductIds; List<String?> get selectedProductIds => _selectedProductIds;
String? get selectedAddEditLeadProductId => _selectedAddEditLeadProductId;
String? get selectedAddEditLeadProductName => _selectedAddEditLeadProductName;
List<String?> get selectedValues => _selectedValues; List<String?> get selectedValues => _selectedValues;
bool get submitLoading => _submitLoading; bool get submitLoading => _submitLoading;
set selectedLeadProducts(LeadProducts? value) { set selectedLeadProducts(LeadProducts? value) {
_selectedLeadProducts = value; _selectedLeadProducts = value;
_selectedAddEditLeadProductId = value?.productId!;
_selectedAddEditLeadProductName = value?.productName;
notifyListeners(); 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) { void initializeForm(BuildContext context) {
// Clear existing controllers // Clear existing controllers
...@@ -155,7 +237,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -155,7 +237,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
"product_id": _selectedProductIds[i]!, "product_id": _selectedProductIds[i]!,
"price": editProductPriceControllers[i].text, "price": editProductPriceControllers[i].text,
"qty": editQuantityControllers[i].text, "qty": editQuantityControllers[i].text,
"net_price":editTotalAmountControllers[i].text "net_price": editTotalAmountControllers[i].text,
}; };
insertData.add(rowData); insertData.add(rowData);
} }
...@@ -175,31 +257,53 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -175,31 +257,53 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
leadID, leadID,
); );
if (data != null) { if (data != null) {
if (data.error == "0") { if (data.sessionExists == 1) {
_isLoading = false; if (data.error == "0") {
_leadProductsList = data.leadProducts ?? []; _isLoading = false;
_quoteDetails = _leadProductsList = data.leadProducts ?? [];
data.quoteDetails ??
QuoteDetails( _quoteDetails =
accountId: "", data.quoteDetails ??
email: "", QuoteDetails(
forText: "", accountId: "",
mobile: "", email: "",
name: "", forText: "",
paymentTerms: "", mobile: "",
subject: "", name: "",
); paymentTerms: "",
mailIdController.text = data.quoteDetails!.email??"-"; subject: "",
mobileController.text = data.quoteDetails!.mobile??"-"; );
subjectsController.text = data.quoteDetails!.subject??"-"; mailIdController.text = data.quoteDetails!.email ?? "-";
// taxesController.text = data.quoteDetails!1; mobileController.text = data.quoteDetails!.mobile ?? "-";
// SpecialNoteController.text = data.quoteDetails; subjectsController.text = data.quoteDetails!.subject ?? "-";
forController.text = data.quoteDetails!.forText??"-"; // taxesController.text = data.quoteDetails!1;
paymentTermsController.text = data.quoteDetails!.paymentTerms??"-"; // SpecialNoteController.text = data.quoteDetails;
notifyListeners(); 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 { } else {
_isLoading = false; Navigator.push(
notifyListeners(); context,
MaterialPageRoute(
builder: (context) => LoginScreen(),
settings: RouteSettings(name: 'LoginScreen'),
),
);
} }
} else { } else {
_isLoading = false; _isLoading = false;
...@@ -235,16 +339,22 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -235,16 +339,22 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
if (data != null) { if (data != null) {
if (data.error == "0") { if (data.error == "0") {
_quotationFilePath = data.quoteFilepath!; _quotationFilePath = data.quoteFilepath!;
if(quotation_type=="genquotedown"){ if (quotation_type == "genquotedown") {
String suggestedFilename = getUniqueFilename('quotation', 'pdf'); String suggestedFilename = getUniqueFilename('quotation', 'pdf');
String contentDisposition = 'attachment; filename="$suggestedFilename"'; String contentDisposition =
'attachment; filename="$suggestedFilename"';
// openWhatsApp(data.quoteFilepath!); // openWhatsApp(data.quoteFilepath!);
_handleDownload(context,data.quoteFilepath!,contentDisposition,'application/octet-stream',''); _handleDownload(
} context,
else if(quotation_type=="genquotewhatsappbymynum"){ data.quoteFilepath!,
contentDisposition,
'application/octet-stream',
'',
);
} else if (quotation_type == "genquotewhatsappbymynum") {
openWhatsApp(data.quoteFilepath!); openWhatsApp(data.quoteFilepath!);
} }
Navigator.pop(context,true); Navigator.pop(context, true);
toast(context, data.message); toast(context, data.message);
resetForm(); resetForm();
notifyListeners(); notifyListeners();
...@@ -260,6 +370,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -260,6 +370,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
final formattedDate = DateFormat('yyyyMMdd_HHmmss').format(now); final formattedDate = DateFormat('yyyyMMdd_HHmmss').format(now);
return '${baseName}_$formattedDate.$ext'; return '${baseName}_$formattedDate.$ext';
} }
void openWhatsApp(String path) async { void openWhatsApp(String path) async {
final Uri url = Uri.parse(path); // Example: 919876543210 final Uri url = Uri.parse(path); // Example: 919876543210
if (await canLaunchUrl(url)) { if (await canLaunchUrl(url)) {
...@@ -268,16 +379,17 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -268,16 +379,17 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
throw 'Could not launch $url'; throw 'Could not launch $url';
} }
} }
Future<void> _handleDownload( Future<void> _handleDownload(
context, context,
String url, String url,
String contentDisposition, String contentDisposition,
String mimeType, String mimeType,
String suggestedFilename, String suggestedFilename,
) async { ) async {
// Request notification permission for Android 13+ // Request notification permission for Android 13+
if (Platform.isIOS) { if (Platform.isIOS) {
_handleIOSDownload(context,url, suggestedFilename); _handleIOSDownload(context, url, suggestedFilename);
} else if (Platform.isAndroid) { } else if (Platform.isAndroid) {
if (await Permission.notification.request().isGranted) { if (await Permission.notification.request().isGranted) {
try { try {
...@@ -293,10 +405,12 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -293,10 +405,12 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
'mimeType': mimeType, 'mimeType': mimeType,
'suggestedFilename': suggestedFilename, 'suggestedFilename': suggestedFilename,
}); });
await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication); await launchUrl(
Uri.parse(url),
mode: LaunchMode.externalApplication,
);
} else if (Platform.isIOS) { } else if (Platform.isIOS) {
_handleIOSDownload(context,url, suggestedFilename); _handleIOSDownload(context, url, suggestedFilename);
} }
} catch (e) { } catch (e) {
print("Download Error $e"); print("Download Error $e");
...@@ -307,7 +421,11 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -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 { try {
// Show initial download notification // Show initial download notification
await _showDownloadNotification(0, suggestedFilename, isComplete: false); await _showDownloadNotification(0, suggestedFilename, isComplete: false);
...@@ -315,9 +433,9 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -315,9 +433,9 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
// Get the temporary directory for iOS // Get the temporary directory for iOS
final tempDir = await getTemporaryDirectory(); final tempDir = await getTemporaryDirectory();
final fileName = final fileName =
suggestedFilename.isNotEmpty suggestedFilename.isNotEmpty
? suggestedFilename ? suggestedFilename
: url.split('/').last; : url.split('/').last;
final filePath = '${tempDir.path}/$fileName'; final filePath = '${tempDir.path}/$fileName';
// Download the file using http // Download the file using http
...@@ -348,11 +466,11 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -348,11 +466,11 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
} }
Future<void> _showDownloadNotification( Future<void> _showDownloadNotification(
int progress, int progress,
String fileName, { String fileName, {
bool isComplete = false, bool isComplete = false,
bool isError = false, bool isError = false,
}) async { }) async {
final androidDetails = AndroidNotificationDetails( final androidDetails = AndroidNotificationDetails(
'download_channel', 'download_channel',
'Downloads', 'Downloads',
...@@ -378,11 +496,11 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -378,11 +496,11 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
presentBadge: true, presentBadge: true,
presentSound: isComplete || isError, presentSound: isComplete || isError,
subtitle: subtitle:
isError isError
? 'Download failed' ? 'Download failed'
: isComplete : isComplete
? 'Download complete' ? 'Download complete'
: 'Downloading...', : 'Downloading...',
threadIdentifier: 'download_thread', threadIdentifier: 'download_thread',
); );
...@@ -407,39 +525,66 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -407,39 +525,66 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
); );
} }
onChangemailId(value){ onChangemailId(value) {
mailIdError = ""; mailIdError = "";
notifyListeners(); notifyListeners();
} }
onChangemobile(value){
onChangemobile(value) {
mobileError = ""; mobileError = "";
notifyListeners(); notifyListeners();
} }
onChangesubjects(value){
onChangesubjects(value) {
subjectsError = ""; subjectsError = "";
notifyListeners(); notifyListeners();
} }
onChangetaxes(value){
onChangetaxes(value) {
taxesError = ""; taxesError = "";
notifyListeners(); notifyListeners();
} }
onChangeSpecialNote(value){
onChangeSpecialNote(value) {
SpecialNoteError = ""; SpecialNoteError = "";
notifyListeners(); notifyListeners();
} }
onChangefor(value){
onChangefor(value) {
forError = ""; forError = "";
notifyListeners(); notifyListeners();
} }
onChangepaymentTerms(value){
onChangepaymentTerms(value) {
paymentTermsError = ""; paymentTermsError = "";
notifyListeners(); 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();
}
resetForm2() {
resetForm(){
mailIdController.clear(); mailIdController.clear();
mobileController.clear(); mobileController.clear();
subjectsController.clear(); subjectsController.clear();
...@@ -460,6 +605,5 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -460,6 +605,5 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
SpecialNoteError = ""; SpecialNoteError = "";
forError = ""; forError = "";
paymentTermsError = ""; paymentTermsError = "";
} }
} }
...@@ -196,14 +196,12 @@ class crmNearbyOpenLeadsProvider extends ChangeNotifier { ...@@ -196,14 +196,12 @@ class crmNearbyOpenLeadsProvider extends ChangeNotifier {
List<Marker> markers = []; List<Marker> markers = [];
// print("Hello Nutsby!"); // 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(); Uint8List bytes = data.buffer.asUint8List();
await Future.forEach(leadsList, (leads) async { await Future.forEach(leadsList, (leads) async {
ui.Codec codec = await ui.instantiateImageCodec( ui.Codec codec = await ui.instantiateImageCodec(
bytes, bytes,
targetWidth: 75,
targetHeight: 95,
); );
ui.FrameInfo fi = await codec.getNextFrame(); ui.FrameInfo fi = await codec.getNextFrame();
Uint8List resizedBytes = Uint8List resizedBytes =
...@@ -214,9 +212,11 @@ class crmNearbyOpenLeadsProvider extends ChangeNotifier { ...@@ -214,9 +212,11 @@ class crmNearbyOpenLeadsProvider extends ChangeNotifier {
markers.add( markers.add(
Marker( Marker(
markerId: MarkerId(leads.id.toString()), markerId: MarkerId(leads.id.toString()),
position: _parseLatLng(leads.loc), position: _parseLatLng(leads.loc),
icon: BitmapDescriptor.fromBytes(resizedBytes), icon: BitmapDescriptor.fromBytes(resizedBytes),
infoWindow: InfoWindow( infoWindow: InfoWindow(
onTap:() { onTap:() {
// onMarkerTap(context, leads.id); // onMarkerTap(context, leads.id);
Navigator.push( Navigator.push(
......
...@@ -126,11 +126,17 @@ import 'package:generp/Notifiers/HomeScreenNotifier.dart'; ...@@ -126,11 +126,17 @@ import 'package:generp/Notifiers/HomeScreenNotifier.dart';
import 'package:generp/services/api_calling.dart'; import 'package:generp/services/api_calling.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../Models/crmModels/crmLeadDetailsEditProductsViewResponse.dart'; import '../../Models/crmModels/crmLeadDetailsEditProductsViewResponse.dart';
import 'crmLeadDetailsProvider.dart';
class Editproductlistprovider extends ChangeNotifier { class Editproductlistprovider extends ChangeNotifier {
TextEditingController addEditProductPriceController = TextEditingController();
TextEditingController addEditQuantityController = TextEditingController();
TextEditingController addEditTotalAmountController = TextEditingController();
List<Products> _productsList = []; List<Products> _productsList = [];
List<LeadProducts> _leadProductsList = []; List<LeadProducts> _leadProductsList = [];
Products? _selectedProducts; Products? _selectedProducts;
String? _selectedAddEditProductId;
String? _selectedAddEditProductName;
List<TextEditingController> editProductPriceControllers = []; List<TextEditingController> editProductPriceControllers = [];
List<TextEditingController> editQuantityControllers = []; List<TextEditingController> editQuantityControllers = [];
List<TextEditingController> editTotalAmountControllers = []; List<TextEditingController> editTotalAmountControllers = [];
...@@ -139,14 +145,35 @@ class Editproductlistprovider extends ChangeNotifier { ...@@ -139,14 +145,35 @@ class Editproductlistprovider extends ChangeNotifier {
bool _submitLoading = false; bool _submitLoading = false;
List<Products> get productsList => _productsList; List<Products> get productsList => _productsList;
List<LeadProducts> get leadProductsList => _leadProductsList; List<LeadProducts> get leadProductsList => _leadProductsList;
Products? get selectedProducts => _selectedProducts; Products? get selectedProducts => _selectedProducts;
String? get selectedAddEditProductId => _selectedAddEditProductId;
String? get selectedAddEditProductName => _selectedAddEditProductName;
List<String?> get selectedProductIds => _selectedProductIds; List<String?> get selectedProductIds => _selectedProductIds;
List<String?> get selectedValues => _selectedValues; List<String?> get selectedValues => _selectedValues;
bool get submitLoading => _submitLoading; bool get submitLoading => _submitLoading;
set selectedProducts(Products? value) { set selectedProducts(Products? value) {
_selectedProducts = value; _selectedProducts = value;
_selectedAddEditProductId = value!.id!;
_selectedAddEditProductName = value.name;
notifyListeners();
}
set selectedAddEditProductId(String? value) {
_selectedAddEditProductId = value;
notifyListeners();
}
set selectedAddEditProductName(String? value) {
_selectedAddEditProductName = value;
notifyListeners(); notifyListeners();
} }
...@@ -165,10 +192,20 @@ class Editproductlistprovider extends ChangeNotifier { ...@@ -165,10 +192,20 @@ class Editproductlistprovider extends ChangeNotifier {
// Initialize controllers for each lead product // Initialize controllers for each lead product
for (var product in _leadProductsList) { for (var product in _leadProductsList) {
editProductPriceControllers.add(TextEditingController(text: product.price?.toString() ?? '')); editProductPriceControllers.add(
editQuantityControllers.add(TextEditingController(text: product.qty?.toString() ?? '')); TextEditingController(text: product.price?.toString() ?? ''),
editTotalAmountControllers.add(TextEditingController( );
text: (double.parse(product.price?.toString() ?? '0') * int.parse(product.qty?.toString() ?? '0')).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); _selectedProductIds.add(product.productId);
_selectedValues.add(product.productName); _selectedValues.add(product.productName);
} }
...@@ -215,6 +252,13 @@ class Editproductlistprovider extends ChangeNotifier { ...@@ -215,6 +252,13 @@ class Editproductlistprovider extends ChangeNotifier {
notifyListeners(); 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() { List<Map<String, String>> getFormData() {
final List<Map<String, String>> insertData = []; final List<Map<String, String>> insertData = [];
for (int i = 0; i < editProductPriceControllers.length; i++) { for (int i = 0; i < editProductPriceControllers.length; i++) {
...@@ -230,10 +274,17 @@ class Editproductlistprovider extends ChangeNotifier { ...@@ -230,10 +274,17 @@ class Editproductlistprovider extends ChangeNotifier {
return insertData; return insertData;
} }
Future<void> crmLeadDetailsEditProductsViewAPIFunction(BuildContext context, String leadID) async { Future<void> crmLeadDetailsEditProductsViewAPIFunction(
BuildContext context,
String leadID,
) async {
try { try {
final prov = Provider.of<HomescreenNotifier>(context, listen: false); 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") { if (data != null && data.error == "0") {
_leadProductsList = data.leadProducts ?? []; _leadProductsList = data.leadProducts ?? [];
_productsList = data.products ?? []; _productsList = data.products ?? [];
...@@ -244,13 +295,22 @@ class Editproductlistprovider extends ChangeNotifier { ...@@ -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 { try {
final prov = Provider.of<HomescreenNotifier>(context, listen: false); 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") { if (data != null && data.error == "0") {
resetForm(); resetForm();
Navigator.pop(context,true); Navigator.pop(context, true);
notifyListeners(); notifyListeners();
} }
} catch (e, s) { } catch (e, s) {
...@@ -258,22 +318,78 @@ class Editproductlistprovider extends ChangeNotifier { ...@@ -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; submitLoading = true;
final insertedData = getFormData(); final insertedData = getFormData();
print("Form Data: $insertedData"); print("Form Data: $insertedData");
crmLeadDetailsEditProductsSubmitAPIFunction(context,insertedData,leadID); crmLeadDetailsEditProductsSubmitAPIFunction(context, insertedData, leadID);
submitLoading = false; submitLoading = false;
} }
void resetForm() { void resetForm() {
checkDropdownReset();
addEditProductPriceController.clear();
addEditQuantityController.clear();
addEditTotalAmountController.clear();
editProductPriceControllers.clear(); editProductPriceControllers.clear();
editQuantityControllers.clear(); editQuantityControllers.clear();
editTotalAmountControllers.clear(); editTotalAmountControllers.clear();
_selectedProductIds.clear(); _selectedProductIds.clear();
_selectedProducts = null;
_selectedAddEditProductId = null;
_selectedAddEditProductName = null;
_selectedValues.clear(); _selectedValues.clear();
_leadProductsList.clear(); _leadProductsList.clear();
notifyListeners(); 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 { ...@@ -414,7 +414,7 @@ class Requestionlistprovider extends ChangeNotifier {
_accounts = data.accounts ?? []; _accounts = data.accounts ?? [];
if (mode != "self") { if (mode != "self") {
_accounts = [ _accounts = [
Accounts(id: "", name: "Select"), Accounts(id: "", name: "Select Account"),
...data.accounts ?? [], ...data.accounts ?? [],
]; ];
} }
......
...@@ -220,6 +220,7 @@ class MyApp extends StatelessWidget { ...@@ -220,6 +220,7 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => Addprospectleadsprovider()), ChangeNotifierProvider(create: (_) => Addprospectleadsprovider()),
ChangeNotifierProvider(create: (_) => Editorderprovider()), ChangeNotifierProvider(create: (_) => Editorderprovider()),
ChangeNotifierProvider(create: (_) => Dispatchorderprovider()), ChangeNotifierProvider(create: (_) => Dispatchorderprovider()),
ChangeNotifierProvider(create: (_) => followUpUpdateProvider()),
], ],
child: Builder( child: Builder(
builder: (BuildContext context) { builder: (BuildContext context) {
......
...@@ -7,6 +7,7 @@ import 'package:flutter/material.dart'; ...@@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:generp/Notifiers/crmProvider/crmLeadDetailsProvider.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/commonServices.dart';
import 'package:generp/Utils/dropdownTheme.dart'; import 'package:generp/Utils/dropdownTheme.dart';
import 'package:generp/screens/crm/AppointmentDetails.dart'; import 'package:generp/screens/crm/AppointmentDetails.dart';
...@@ -18,6 +19,7 @@ import 'package:generp/screens/crm/followUpUpdateScreen.dart'; ...@@ -18,6 +19,7 @@ import 'package:generp/screens/crm/followUpUpdateScreen.dart';
import 'package:generp/screens/crm/productDetails.dart'; import 'package:generp/screens/crm/productDetails.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../Models/crmModels/crmLeadDetailsEditProductsViewResponse.dart';
import '../../Utils/app_colors.dart'; import '../../Utils/app_colors.dart';
import '../../Utils/commonWidgets.dart'; import '../../Utils/commonWidgets.dart';
import '../finance/FileViewer.dart'; import '../finance/FileViewer.dart';
...@@ -97,8 +99,8 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -97,8 +99,8 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
} }
Widget _scaffold(BuildContext context) { Widget _scaffold(BuildContext context) {
return Consumer<crmLeadDetailsProvider>( return Consumer2<crmLeadDetailsProvider, Editproductlistprovider>(
builder: (context, provider, child) { builder: (context, provider, editProvider, child) {
var leadDetails = provider.leadDetails; var leadDetails = provider.leadDetails;
var headings1 = ["Account Manager Name", "Account Created By"]; var headings1 = ["Account Manager Name", "Account Created By"];
...@@ -124,7 +126,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -124,7 +126,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
var headings4 = ["Lead Status", "Last Followup Date", "Lead Age"]; var headings4 = ["Lead Status", "Last Followup Date", "Lead Age"];
var subHeadings4 = [ var subHeadings4 = [
provider.leadDetails!.status ?? "-", provider.leadDetails!.status ?? "-",
provider.followupDetails.first!.fdate ?? "-", provider.leadDetails!.date ?? "-",
"${provider.leadDetails!.lage ?? "-"} days", "${provider.leadDetails!.lage ?? "-"} days",
]; ];
// var totalHeadings = []; // var totalHeadings = [];
...@@ -638,6 +640,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -638,6 +640,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
child: Column( child: Column(
children: [ children: [
///product details ///product details
if(provider.leadProducts.isNotEmpty)...[
Container( Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10), padding: EdgeInsets.only(left: 10, right: 10, top: 10),
child: Row( child: Row(
...@@ -654,13 +657,20 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -654,13 +657,20 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
), ),
), ),
Expanded( Expanded(
child: Text( child: InkResponse(
textAlign: TextAlign.right, onTap: () async {
"+ Add Product", editProvider.resetForm();
style: TextStyle( await editProvider.crmLeadDetailsEditProductsViewAPIFunction(context, provider.leadDetails.id!);
fontFamily: "JakartaMedium", _showAddEditProductsSheet(context,widget.mode, "add", "");
fontSize: 14, },
color: AppColors.app_blue, 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> { ...@@ -669,7 +679,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
), ),
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
height: 125, height: 130,
child: ListView.builder( child: ListView.builder(
physics: AlwaysScrollableScrollPhysics(), physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
...@@ -679,18 +689,28 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -679,18 +689,28 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
itemBuilder: (context, lp) { itemBuilder: (context, lp) {
return InkResponse( return InkResponse(
onTap: () async { onTap: () async {
var res = await Navigator.push( // var res = await Navigator.push(
context, // context,
MaterialPageRoute( // MaterialPageRoute(
builder: // builder:
(context) => EditProductsList( // (context) => EditProductsList(
leadID: provider.leadDetails.id ?? "", // 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( child: Container(
height: 125, height: 130,
width: MediaQuery.of(context).size.width * 0.95, width: MediaQuery.of(context).size.width * 0.95,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
...@@ -698,7 +718,12 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -698,7 +718,12 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
), ),
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 10, horizontal: 10,
vertical: 10, vertical: 8,
),
margin: EdgeInsets.symmetric(
horizontal: 5,
// vertical: 10,
), ),
child: Row( child: Row(
...@@ -730,6 +755,8 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -730,6 +755,8 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
.leadProducts[lp] .leadProducts[lp]
.productName ?? .productName ??
"-", "-",
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
fontFamily: "JakartaMedium", fontFamily: "JakartaMedium",
fontSize: 14, fontSize: 14,
...@@ -759,7 +786,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -759,7 +786,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
color: AppColors.grey_semi, color: AppColors.grey_semi,
), ),
), ),
SizedBox(height: 10), SizedBox(height: 5),
DottedLine( DottedLine(
dashGapLength: 4, dashGapLength: 4,
dashGapColor: Colors.white, dashGapColor: Colors.white,
...@@ -767,9 +794,9 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -767,9 +794,9 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
dashLength: 2, dashLength: 2,
lineThickness: 0.5, lineThickness: 0.5,
), ),
SizedBox(height: 10), SizedBox(height: 5),
Text( Text(
"₹${provider.leadProducts[lp].price ?? " - "}", "₹${provider.leadProducts[lp].prodTotalPrice ?? " - "}",
style: TextStyle( style: TextStyle(
fontFamily: "JakartaMedium", fontFamily: "JakartaMedium",
fontSize: 14, fontSize: 14,
...@@ -787,8 +814,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -787,8 +814,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
}, },
), ),
), ),
],
///contact details ///contact details
if(provider.contactDetails.isNotEmpty)...[
Container( Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10), padding: EdgeInsets.only(left: 10, right: 10, top: 10),
child: Row( child: Row(
...@@ -831,12 +860,18 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -831,12 +860,18 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
itemBuilder: (context, lp) { itemBuilder: (context, lp) {
return InkResponse( return InkResponse(
onTap: () async { onTap: () async {
provider.editNameController.text = provider.contactDetails[lp].name??""; provider.editNameController.text =
provider.editDesignationController.text = provider.contactDetails[lp].designation??""; provider.contactDetails[lp].name ?? "";
provider.editMobileNumberController.text = provider.contactDetails[lp].mob1??""; provider.editDesignationController.text =
provider.editAlternativeMobileController.text = provider.contactDetails[lp].mob2??""; provider.contactDetails[lp].designation ?? "";
provider.editTelephoneController.text = provider.contactDetails[lp].tel??""; provider.editMobileNumberController.text =
provider.editEmailController.text = provider.contactDetails[lp].email??""; 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); _showEditContactSheet(context, lp);
}, },
child: Container( child: Container(
...@@ -915,201 +950,273 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -915,201 +950,273 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
); );
}, },
), ),
],
///Followup details ///Followup details
Container( if (provider.followupDetails.isNotEmpty) ...[
padding: EdgeInsets.only(left: 10, right: 10, top: 10), Container(
child: Row( padding: EdgeInsets.only(left: 10, right: 10, top: 10),
children: [ child: Row(
Expanded( children: [
child: Text( Expanded(
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',
),
),
);
},
child: Text( child: Text(
textAlign: TextAlign.right, textAlign: TextAlign.left,
"+ Follow up Update", "Followup Details",
style: TextStyle( style: TextStyle(
fontFamily: "JakartaMedium", fontFamily: "JakartaMedium",
fontSize: 14, fontSize: 14,
color: AppColors.app_blue, color: AppColors.grey_thick,
), ),
), ),
), ),
), Expanded(
], child: InkResponse(
), onTap: () async {
), var res = await Navigator.push(
SizedBox( context,
width: double.infinity, MaterialPageRoute(
height: 250, builder: (context) => Followupupdatescreen(
child: ListView.builder( leadID: provider.leadDetails.id,
physics: AlwaysScrollableScrollPhysics(), mode: widget.mode,
shrinkWrap: true, ),
scrollDirection: Axis.horizontal, settings: RouteSettings(
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10), name: 'Followupupdatescreen',
itemCount: provider.followupDetails.length, ),
itemBuilder: (context, lp) { ),
return Container( );
height: 250, },
width: MediaQuery.of(context).size.width * 0.95, child: Text(
decoration: BoxDecoration( textAlign: TextAlign.right,
color: Colors.white, "+ Follow up Update",
borderRadius: BorderRadius.circular(14), style: TextStyle(
), fontFamily: "JakartaMedium",
padding: EdgeInsets.symmetric( fontSize: 14,
horizontal: 10, color: AppColors.app_blue,
vertical: 10, ),
),
),
), ),
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( child: Column(
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
flex: 1, flex: 1,
child: SvgPicture.asset( child: SvgPicture.asset(
"assets/svg/crm/followup_details_ic.svg", "assets/svg/crm/followup_details_ic.svg",
),
), ),
), SizedBox(width: 10),
SizedBox(width: 10), Expanded(
Expanded( flex: 6,
flex: 6, child: SizedBox(
child: SizedBox( child: Column(
child: Column( // mainAxisAlignment: MainAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment:
crossAxisAlignment: CrossAxisAlignment.start,
CrossAxisAlignment.start, mainAxisAlignment:
mainAxisAlignment: MainAxisAlignment.start,
MainAxisAlignment.start, children: [
children: [ Row(
Row( children: [
children: [ Expanded(
Expanded( flex: 4,
flex: 4, child: Column(
child: Column( crossAxisAlignment:
crossAxisAlignment: CrossAxisAlignment.start,
CrossAxisAlignment.start, children: [
children: [ Text(
Text( provider
provider .followupDetails[lp]
.followupDetails[lp] .ename ??
.ename ?? "-",
"-", style: TextStyle(
style: TextStyle( fontFamily:
fontFamily: "JakartaMedium",
"JakartaMedium", fontSize: 14,
fontSize: 14, color:
color: AppColors
AppColors.semi_black, .semi_black,
),
), ),
), Text(
Text( provider
provider .followupDetails[lp]
.followupDetails[lp] .fdate ??
.fdate ?? "-",
"-", style: TextStyle(
style: TextStyle( fontFamily:
fontFamily: "JakartaMedium",
"JakartaMedium", fontSize: 14,
fontSize: 14, color:
color: AppColors.grey_semi,
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( Expanded(
textAlign: TextAlign.right, flex: 2,
"${provider.followupDetails[lp].fstatus ?? "-"}", child: Container(
style: TextStyle( decoration: BoxDecoration(
fontFamily: borderRadius:
"JakartaMedium", BorderRadius.circular(
fontSize: 14, 8,
color: Color(0xFF586000), ),
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(
Container( padding: EdgeInsets.symmetric(vertical: 10),
padding: EdgeInsets.symmetric(vertical: 10), child: Row(
child: Row( children: [
children: [ Expanded(
Expanded( flex: 2,
flex: 2, child: Text(
child: Text( "Time",
"Time", style: TextStyle(
style: TextStyle( fontSize: 14,
fontSize: 14, fontFamily: "JakartaSemiBold",
fontFamily: "JakartaSemiBold", ),
), ),
), ),
), Expanded(
Expanded( flex: 7,
flex: 7, child: DottedLine(
child: DottedLine( dashGapLength: 4,
dashGapLength: 4, dashGapColor: Colors.white,
dashGapColor: Colors.white, dashColor: AppColors.grey_semi,
dashColor: AppColors.grey_semi, dashLength: 2,
dashLength: 2, lineThickness: 0.5,
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,
),
),
],
),
), ),
), Container(
...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), padding: EdgeInsets.symmetric(vertical: 3),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
...@@ -1117,7 +1224,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -1117,7 +1224,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
Expanded( Expanded(
child: Text( child: Text(
textAlign: TextAlign.left, textAlign: TextAlign.left,
heads[j], "Feedback",
style: TextStyle( style: TextStyle(
fontFamily: "JakartaRegular", fontFamily: "JakartaRegular",
fontSize: 14, fontSize: 14,
...@@ -1128,7 +1235,16 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -1128,7 +1235,16 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
Expanded( Expanded(
child: Text( child: Text(
textAlign: TextAlign.right, textAlign: TextAlign.right,
subHeads[j] == "" ? "-" : subHeads[j], provider
.followupDetails[lp]
.ffeedback ==
""
? "-"
: provider
.followupDetails[lp]
.ffeedback ??
"-",
maxLines: 2,
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: Color(0xFF818181), color: Color(0xFF818181),
...@@ -1137,79 +1253,17 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -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 ///Appointment details
if(provider.appointmentDetails.isNotEmpty)...[
Container( Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10), padding: EdgeInsets.only(left: 10, right: 10, top: 10),
child: Row( child: Row(
...@@ -1467,8 +1521,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -1467,8 +1521,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
}, },
), ),
), ),
],
///Quotation details ///Quotation details
if(provider.quotationsDetails.isNotEmpty)...[
Container( Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10), padding: EdgeInsets.only(left: 10, right: 10, top: 10),
child: Row( child: Row(
...@@ -1698,7 +1754,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -1698,7 +1754,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
}, },
), ),
), ),
],
SizedBox(height: 75), SizedBox(height: 75),
], ],
), ),
...@@ -1742,7 +1798,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -1742,7 +1798,7 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
Align( Align(
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
child: Text( child: Text(
"Add Contact", "Add Appointment",
style: TextStyle( style: TextStyle(
color: AppColors.app_blue, color: AppColors.app_blue,
fontSize: 16, fontSize: 16,
...@@ -1885,12 +1941,6 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -1885,12 +1941,6 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
child: Container( child: Container(
alignment: Alignment.center, alignment: Alignment.center,
height: 45, height: 45,
margin: EdgeInsets.only(
left: 5.0,
right: 5.0,
top: 5.0,
bottom: 5.0,
),
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColors.app_blue, //1487C9 color: AppColors.app_blue, //1487C9
borderRadius: BorderRadius.circular(14.0), borderRadius: BorderRadius.circular(14.0),
...@@ -2382,4 +2432,253 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -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'; ...@@ -18,7 +18,9 @@ import '../../Notifiers/crmProvider/crmNearbyOpenLeadsProvider.dart';
import '../../Utils/dropdownTheme.dart'; import '../../Utils/dropdownTheme.dart';
class NearbyOpenLeads extends StatefulWidget { class NearbyOpenLeads extends StatefulWidget {
const NearbyOpenLeads({super.key}); final latitude;
final longitude;
const NearbyOpenLeads({super.key, this.latitude, this.longitude});
@override @override
State<NearbyOpenLeads> createState() => _NearbyOpenLeadsState(); State<NearbyOpenLeads> createState() => _NearbyOpenLeadsState();
...@@ -121,6 +123,7 @@ class _NearbyOpenLeadsState extends State<NearbyOpenLeads> { ...@@ -121,6 +123,7 @@ class _NearbyOpenLeadsState extends State<NearbyOpenLeads> {
zoomGesturesEnabled: true, zoomGesturesEnabled: true,
zoomControlsEnabled: true, zoomControlsEnabled: true,
gestureRecognizers: { gestureRecognizers: {
Factory<OneSequenceGestureRecognizer>( Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(), () => EagerGestureRecognizer(),
), ),
...@@ -132,7 +135,9 @@ class _NearbyOpenLeadsState extends State<NearbyOpenLeads> { ...@@ -132,7 +135,9 @@ class _NearbyOpenLeadsState extends State<NearbyOpenLeads> {
), // Prioritize pinch-to-zoom ), // Prioritize pinch-to-zoom
}, },
initialCameraPosition: CameraPosition( initialCameraPosition: CameraPosition(
target: provider.startLocation, target: widget.latitude!=null||widget.longitude!=null?
LatLng(widget.latitude,widget.longitude):
provider.startLocation,
zoom: 14.0, zoom: 14.0,
), ),
markers: provider.markers.toSet(), markers: provider.markers.toSet(),
......
...@@ -198,7 +198,7 @@ class _ProspectListByModeState extends State<ProspectListByMode> { ...@@ -198,7 +198,7 @@ class _ProspectListByModeState extends State<ProspectListByMode> {
), ),
), ),
Text( Text(
crmLists[index].accman??"-", crmLists[index].mob1??"-",
maxLines: 1, maxLines: 1,
style: TextStyle( style: TextStyle(
fontFamily: "JakartaMedium", fontFamily: "JakartaMedium",
......
...@@ -5,7 +5,6 @@ import 'package:dotted_line/dotted_line.dart'; ...@@ -5,7 +5,6 @@ import 'package:dotted_line/dotted_line.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.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/pendingTasksDetails.dart';
import 'package:generp/screens/crm/pendingTasksList.dart'; import 'package:generp/screens/crm/pendingTasksList.dart';
import 'package:generp/screens/crm/universalSearchScreen.dart'; import 'package:generp/screens/crm/universalSearchScreen.dart';
...@@ -38,8 +37,9 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> { ...@@ -38,8 +37,9 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
}); });
WidgetsBinding.instance.addPostFrameCallback((timeStamp) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
var prov = Provider.of<Crmdashboardprovider>(context, listen: false); var prov = Provider.of<Crmdashboardprovider>(context, listen: false);
prov.getCurrentLocation(context);
prov.accessPagesAPIFunction(context); prov.accessPagesAPIFunction(context);
prov.crmDashboardAPIFunction(context, "executive", "", "", ""); // prov.crmDashboardAPIFunction(context);
prov.crmPendingTasksAPIFunction(context); prov.crmPendingTasksAPIFunction(context);
}); });
} }
...@@ -208,8 +208,8 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> { ...@@ -208,8 +208,8 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
'Pending Tasks', 'Pending Tasks',
'Today Visits', 'Today Visits',
'Today Calls', 'Today Calls',
'Hot Leads' 'Hot Leads',
'Cold Leads', 'Cold Leads',
'Warm Leads', 'Warm Leads',
// 'Total Leads', // 'Total Leads',
// 'Order Lost', // 'Order Lost',
...@@ -322,6 +322,8 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> { ...@@ -322,6 +322,8 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
}, },
), ),
), ),
]else...[
SizedBox(height: 10,),
], ],
// ListView.builder( // ListView.builder(
...@@ -435,6 +437,7 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> { ...@@ -435,6 +437,7 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
// ); // );
// }, // },
// ), // ),
Container( Container(
height: MediaQuery.of(context).size.height * 0.2, height: MediaQuery.of(context).size.height * 0.2,
margin: EdgeInsets.symmetric(horizontal: 10), margin: EdgeInsets.symmetric(horizontal: 10),
...@@ -638,6 +641,207 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> { ...@@ -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) ...[ if (provider.pendingTasksLists.length > 0) ...[
Align( Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
...@@ -714,13 +918,15 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> { ...@@ -714,13 +918,15 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
]; ];
return InkResponse( return InkResponse(
onTap: () async { onTap: () async {
await Navigator.push( await Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: builder:
(context) => (context) =>
Pendingtasksdetails(detailIndex: index), Pendingtasksdetails(detailIndex: index),
settings: RouteSettings(name: 'Pendingtasksdetails') settings: RouteSettings(
name: 'Pendingtasksdetails',
),
), ),
); );
}, },
......
...@@ -4,7 +4,7 @@ import 'package:connectivity_plus/connectivity_plus.dart'; ...@@ -4,7 +4,7 @@ import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.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/app_colors.dart';
import 'package:generp/Utils/commonServices.dart'; import 'package:generp/Utils/commonServices.dart';
import 'package:generp/Utils/commonWidgets.dart'; import 'package:generp/Utils/commonWidgets.dart';
...@@ -12,7 +12,9 @@ import 'package:generp/Utils/dropdownTheme.dart'; ...@@ -12,7 +12,9 @@ import 'package:generp/Utils/dropdownTheme.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class Followupupdatescreen extends StatefulWidget { class Followupupdatescreen extends StatefulWidget {
const Followupupdatescreen({super.key}); final leadID;
final mode;
const Followupupdatescreen({super.key,required this.leadID, this.mode});
@override @override
State<Followupupdatescreen> createState() => _FollowupupdatescreenState(); State<Followupupdatescreen> createState() => _FollowupupdatescreenState();
...@@ -22,12 +24,7 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -22,12 +24,7 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
Dropdowntheme ddtheme = Dropdowntheme(); Dropdowntheme ddtheme = Dropdowntheme();
Map _source = {ConnectivityResult.mobile: true}; Map _source = {ConnectivityResult.mobile: true};
final MyConnectivity _connectivity = MyConnectivity.instance; final MyConnectivity _connectivity = MyConnectivity.instance;
TextEditingController followUpFeedbackController = TextEditingController();
TextEditingController noteController = TextEditingController();
onFollowUpChanged(value) {}
onNoteChanged(value) {}
@override @override
void initState() { void initState() {
...@@ -36,7 +33,10 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -36,7 +33,10 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
_connectivity.myStream.listen((event) { _connectivity.myStream.listen((event) {
setState(() => _source = event); setState(() => _source = event);
}); });
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {}); WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
final provider = Provider.of<followUpUpdateProvider>(context);
provider.getCurrentLocation(context);
});
} }
@override @override
...@@ -61,20 +61,20 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -61,20 +61,20 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
} }
return (connection == "Online") return (connection == "Online")
? Platform.isAndroid ? Platform.isAndroid
? WillPopScope( ? WillPopScope(
onWillPop: () => onBackPressed(context), onWillPop: () => onBackPressed(context),
child: SafeArea( child: SafeArea(
top: false, top: false,
bottom: true, bottom: true,
child: _scaffold(context), child: _scaffold(context),
), ),
) )
: _scaffold(context) : _scaffold(context)
: NoNetwork(context); : NoNetwork(context);
} }
Widget _scaffold(BuildContext context) { Widget _scaffold(BuildContext context) {
return Consumer<Crmdashboardprovider>( return Consumer<followUpUpdateProvider>(
builder: (context, provider, child) { builder: (context, provider, child) {
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: true, resizeToAvoidBottomInset: true,
...@@ -154,9 +154,9 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -154,9 +154,9 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
children: [ children: [
Text( Text(
provider.selectedTime.hour.toString() + provider.selectedTime.hour.toString() +
":" + ":" +
provider.selectedTime.minute provider.selectedTime.minute
.toString() ?? .toString() ??
"Enter in Time", "Enter in Time",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.w400), style: TextStyle(fontWeight: FontWeight.w400),
...@@ -185,20 +185,21 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -185,20 +185,21 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
], ],
), ),
items: items:
<String>['Active', 'Inactive', 'Suspense'] <String>['Phone', 'Visit']
.map( .map(
(value) => DropdownMenuItem<String>( (value) =>
value: value, DropdownMenuItem<String>(
child: Text( value: value,
value ?? '', child: Text(
style: const TextStyle( value ?? '',
fontSize: 14, style: const TextStyle(
), fontSize: 14,
overflow: TextOverflow.ellipsis,
),
), ),
) overflow: TextOverflow.ellipsis,
.toList(), ),
),
)
.toList(),
value: provider.selectedFollowupType, value: provider.selectedFollowupType,
onChanged: (String? newValue) { onChanged: (String? newValue) {
setState(() { setState(() {
...@@ -216,10 +217,10 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -216,10 +217,10 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
), ),
textControllerWidget( textControllerWidget(
context, context,
followUpFeedbackController, provider.followUpFeedbackController,
"Feedback", "Feedback",
"Write Feedback", "Write Feedback",
onFollowUpChanged, provider.onFollowUpChanged,
TextInputType.text, TextInputType.text,
false, false,
null, null,
...@@ -244,26 +245,21 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -244,26 +245,21 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
], ],
), ),
items: items:
<String>[ <String>['Cold', 'Hot', 'Warm']
'Cold', .map(
'Hot', (value) =>
'Warm', DropdownMenuItem<String>(
'Open', value: value,
'Closed', child: Text(
] value ?? '',
.map( style: const TextStyle(
(value) => DropdownMenuItem<String>( fontSize: 14,
value: value,
child: Text(
value ?? '',
style: const TextStyle(
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
),
), ),
) overflow: TextOverflow.ellipsis,
.toList(), ),
),
)
.toList(),
value: provider.selectedLeadStatus, value: provider.selectedLeadStatus,
onChanged: (String? newValue) { onChanged: (String? newValue) {
setState(() { setState(() {
...@@ -302,26 +298,24 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -302,26 +298,24 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
], ],
), ),
items: items:
<String>[ <String>[
'Cold', 'Next Appointment',
'Hot', 'Update Order Status',
'Warm', ]
'Open', .map(
'Closed', (value) =>
] DropdownMenuItem<String>(
.map( value: value,
(value) => DropdownMenuItem<String>( child: Text(
value: value, value ?? '',
child: Text( style: const TextStyle(
value ?? '', fontSize: 14,
style: const TextStyle(
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
),
), ),
) overflow: TextOverflow.ellipsis,
.toList(), ),
),
)
.toList(),
value: provider.nextAppointmentStatus, value: provider.nextAppointmentStatus,
onChanged: (String? newValue) { onChanged: (String? newValue) {
setState(() { setState(() {
...@@ -341,128 +335,354 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -341,128 +335,354 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
), ),
), ),
SizedBox(height: 15), SizedBox(height: 15),
Container( if (provider.nextAppointmentStatus ==
padding: EdgeInsets.only(left: 10), "Update Order Status") ...[
alignment: Alignment.topLeft, Container(
child: Text( padding: EdgeInsets.only(left: 10),
"Next Appointment", alignment: Alignment.topLeft,
style: TextStyle(color: AppColors.grey_thick, fontSize: 16), child: Text(
), "Update Order Status",
), style: TextStyle(
Container( color: AppColors.grey_thick,
decoration: BoxDecoration( fontSize: 16,
color: Colors.white, ),
borderRadius: BorderRadius.circular(15), ),
), ),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10), Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5), decoration: BoxDecoration(
child: Column( color: Colors.white,
crossAxisAlignment: CrossAxisAlignment.start, borderRadius: BorderRadius.circular(15),
mainAxisAlignment: MainAxisAlignment.start, ),
children: [ margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
TextWidget(context, "Next Appointment Date"), padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
Container( child: Column(
height: 50, crossAxisAlignment: CrossAxisAlignment.start,
alignment: Alignment.center, mainAxisAlignment: MainAxisAlignment.start,
decoration: BoxDecoration( children: [
color: AppColors.text_field_color, TextWidget(context, "Select Status"),
borderRadius: BorderRadius.circular(14), DropdownButtonHideUnderline(
), child: Row(
child: Padding( children: [
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10, 0), Expanded(
child: TextFormField( child: DropdownButton2<String>(
controller: provider.nextAppointmentDateController, isExpanded: true,
keyboardType: TextInputType.text, hint: const Row(
enabled: false, children: [
maxLines: 1, Expanded(
readOnly: true, child: Text(
onChanged: (value) {}, 'Select Status',
decoration: InputDecoration( style: TextStyle(fontSize: 14),
hintText: "Enter Date", overflow: TextOverflow.ellipsis,
hintStyle: TextStyle( ),
fontWeight: FontWeight.w400, ),
color: Color(0xFFB4BEC0), ],
fontSize: 14, ),
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,
),
), ),
), ),
), if (provider.selectOrderStatus == "Order Gain")
TextWidget(context, "Appointment Type"), ...[]
DropdownButtonHideUnderline( else
child: Row( ...[
children: [ if (provider.selectOrderStatus == "Order Lost") ...[
Expanded( TextWidget(context, "Select Competitor"),
child: DropdownButton2<String>( DropdownButtonHideUnderline(
isExpanded: true, child: Row(
hint: const Row(
children: [ children: [
Expanded( Expanded(
child: Text( child: DropdownButton2<String>(
'Select Appointment Type', isExpanded: true,
style: TextStyle(fontSize: 14), hint: const Row(
overflow: TextOverflow.ellipsis, 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'] ] else
.map( if (provider.selectOrderStatus ==
(value) => DropdownMenuItem<String>( "No Requirement")
value: value, ...[],
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( child: Text(
value ?? '', 'Select Appointment Type',
style: const TextStyle( style: TextStyle(fontSize: 14),
fontSize: 14,
),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
), ),
) ],
.toList(), ),
value: provider.selectNextAppointmentType, items:
onChanged: (String? newValue) { <String>['Phone', 'Visit']
setState(() { .map(
provider.selectNextAppointmentType = (value) =>
newValue!; 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), SizedBox(height: 150),
], ],
), ),
), ),
floatingActionButtonLocation: floatingActionButtonLocation:
FloatingActionButtonLocation.centerFloat, FloatingActionButtonLocation.centerFloat,
floatingActionButton: InkResponse( 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( child: Container(
height: 45, height: 45,
alignment: Alignment.center, alignment: Alignment.center,
...@@ -472,7 +692,9 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -472,7 +692,9 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
color: AppColors.app_blue, color: AppColors.app_blue,
borderRadius: BorderRadius.circular(15), borderRadius: BorderRadius.circular(15),
), ),
child: Text( child:provider.submitLoading?CircularProgressIndicator.adaptive(
valueColor: AlwaysStoppedAnimation(AppColors.white),
): Text(
"Submit", "Submit",
style: TextStyle( style: TextStyle(
fontSize: 15, 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 'dart:io';
import 'package:dotted_line/dotted_line.dart';
import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:generp/Utils/dropdownTheme.dart'; import 'package:generp/Utils/dropdownTheme.dart';
import 'package:generp/screens/crm/generateQuotationAddEditProduct.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../Models/crmModels/crmLeadDetailsGenerateQuotationViewResponse.dart'; import '../../Models/crmModels/crmLeadDetailsGenerateQuotationViewResponse.dart';
...@@ -39,7 +41,7 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> { ...@@ -39,7 +41,7 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
); );
// Initialize controllers and dropdowns after API call // Initialize controllers and dropdowns after API call
provider.initializeForm(context); provider.addEditInitializeForm(context);
}); });
} }
...@@ -49,297 +51,565 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> { ...@@ -49,297 +51,565 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
builder: (context, provider, child) { builder: (context, provider, child) {
return WillPopScope( return WillPopScope(
onWillPop: () async { onWillPop: () async {
// provider.resetForm(); provider.resetForm();
return true; return true;
}, },
child: SafeArea( child: SafeArea(
top: false, top: false,
bottom: Platform.isIOS?false:true, bottom: Platform.isIOS ? false : true,
child: Scaffold( child: Scaffold(
resizeToAvoidBottomInset: true, resizeToAvoidBottomInset: true,
backgroundColor: AppColors.scaffold_bg_color, backgroundColor: AppColors.scaffold_bg_color,
appBar: appbar2( appBar: appbar2New(
context, context,
"Generate Quotation", "Generate Quotation",
provider.resetForm, provider.resetForm,
const SizedBox(width: 0), const SizedBox(width: 0),
0xFFFFFFFF,
), ),
body: Container( body: SingleChildScrollView(
decoration: BoxDecoration(color: AppColors.white), child: Column(
padding: const EdgeInsets.symmetric(horizontal: 10), crossAxisAlignment: CrossAxisAlignment.start,
child: SingleChildScrollView( children: [
child: Column( Container(
crossAxisAlignment: CrossAxisAlignment.start, padding: EdgeInsets.symmetric(
children: [ horizontal: 10,
textControllerWidget( vertical: 10,
context,
provider.mailIdController,
"Email Id",
"Enter Email Id",
provider.onChangemailId,
TextInputType.emailAddress,
false,
null,
), ),
errorWidget(context, provider.mailIdError), margin: EdgeInsets.symmetric(
horizontal: 10,
textControllerWidget( vertical: 10,
context,
provider.mobileController,
"Mobile Number",
"Enter Mobile Number",
provider.onChangemobile,
TextInputType.phone,
false,
FilteringTextInputFormatter.digitsOnly,
), ),
errorWidget(context, provider.mobileError), decoration: BoxDecoration(
color: Colors.white,
textControllerWidget( borderRadius: BorderRadius.circular(16),
context,
provider.subjectsController,
"Subject",
"Enter Subject",
provider.onChangesubjects,
TextInputType.text,
false,
null,
), ),
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( textControllerWidget(
onTap: () { context,
provider.editAddNewRow(); provider.mobileController,
}, "Mobile Number",
child: Container( "Enter Mobile Number",
margin: const EdgeInsets.symmetric(vertical: 10), provider.onChangemobile,
height: 45, TextInputType.phone,
width: MediaQuery.of(context).size.width, false,
decoration: BoxDecoration( FilteringTextInputFormatter.digitsOnly,
color: const Color(0xFFE6F6FF),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: AppColors.app_blue,
width: 0.5,
),
), ),
child: Center( errorWidget(context, provider.mobileError),
child: Text(
"+ Add Product", textControllerWidget(
style: TextStyle( context,
fontFamily: "JakartaMedium", provider.subjectsController,
color: AppColors.app_blue, "Subject",
), "Enter Subject",
), provider.onChangesubjects,
TextInputType.text,
false,
null,
), ),
), errorWidget(context, provider.subjectsError),
],
), ),
if (provider.leadProductsList.isNotEmpty || ),
provider.editProductPriceControllers.isNotEmpty) ...[ Container(
ListView.builder( padding: EdgeInsets.symmetric(
itemCount: provider.editProductPriceControllers.length, horizontal: 10,
physics: const NeverScrollableScrollPhysics(), vertical: 10,
shrinkWrap: true, ),
itemBuilder: (context, j) { margin: EdgeInsets.symmetric(
return Container( horizontal: 10,
padding: const EdgeInsets.symmetric( vertical: 10,
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), margin: const EdgeInsets.symmetric(vertical: 10),
height: 45,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: const Color(0xFFE6F6FF),
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(12),
border: Border.all(
color: AppColors.app_blue,
width: 0.5,
),
), ),
child: Column( child: Center(
crossAxisAlignment: CrossAxisAlignment.start, child: Text(
children: [ "+ Add Product",
TextWidget(context, "Product"), style: TextStyle(
DropdownButtonHideUnderline( fontFamily: "JakartaMedium",
child: Row( color: AppColors.app_blue,
children: [ ),
Expanded( ),
child: DropdownButton2<LeadProducts>( ),
isExpanded: true, ),
hint: const Text( ),
'Select Product', if (provider.leadProductsList.isNotEmpty) ...[
style: TextStyle(fontSize: 14), SizedBox(
overflow: TextOverflow.ellipsis, 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 SizedBox(width: 10),
.map( Expanded(
(ord) => DropdownMenuItem< flex: 6,
LeadProducts child: SizedBox(
>( child: Column(
value: ord, // mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Row(
children: [
Expanded(
flex: 4,
child: Text( child: Text(
"(Product Name: ${ord.productName})", provider
style: const TextStyle( .leadProductsList[lp]
fontSize: 14, .productName ??
), "-",
maxLines: 1,
overflow: overflow:
TextOverflow TextOverflow
.ellipsis, .ellipsis,
style: TextStyle(
fontFamily:
"JakartaMedium",
fontSize: 14,
color:
AppColors
.semi_black,
),
), ),
), ),
) Expanded(
.toList(), flex: 2,
value: child: Text(
provider.selectedProductIds[j] != textAlign:
null TextAlign.right,
? provider.leadProductsList "₹${provider.leadProductsList[lp].price ?? "-"}",
.firstWhere( style: TextStyle(
(ord) => fontFamily:
ord.id == "JakartaMedium",
provider fontSize: 14,
.selectedProductIds[j], color:
orElse: AppColors
() => .semi_black,
provider ),
.leadProductsList[0], ),
) ),
: null, ],
onChanged: (LeadProducts? value) { ),
if (value != null) { Text(
provider.updateSelectedProductIds( "x ${provider.leadProductsList[lp].qty ?? "-"}",
j, style: TextStyle(
value, fontFamily:
); "JakartaMedium",
provider.selectedProductIds[j] = fontSize: 14,
value.id?.toString() ?? ''; color:
provider.updateTotalAmount(j); AppColors.grey_semi,
} ),
}, ),
buttonStyleData: SizedBox(height: 5),
ddtheme.buttonStyleData, DottedLine(
iconStyleData: ddtheme.iconStyleData, dashGapLength: 4,
menuItemStyleData: dashGapColor: Colors.white,
ddtheme.menuItemStyleData, dashColor:
dropdownStyleData: AppColors.grey_semi,
ddtheme.dropdownStyleData, 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,
// ),
],
), ),
); ),
}, ],
), // if (provider.leadProductsList.isNotEmpty ||
], // provider
textControllerWidget( // .editProductPriceControllers
context, // .isNotEmpty) ...[
provider.taxesController, // ListView.builder(
"Taxes", // itemCount:
"Enter Taxes", // provider.editProductPriceControllers.length,
provider.onChangetaxes, // physics: const NeverScrollableScrollPhysics(),
TextInputType.text, // shrinkWrap: true,
false, // itemBuilder: (context, j) {
null, // 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( Container(
context, padding: EdgeInsets.symmetric(
provider.SpecialNoteController, horizontal: 10,
"Special Note", vertical: 10,
"Enter Special Note",
provider.onChangeSpecialNote,
TextInputType.text,
false,
null,
), ),
errorWidget(context, provider.SpecialNoteError), margin: EdgeInsets.symmetric(
horizontal: 10,
textControllerWidget( vertical: 10,
context,
provider.forController,
"FOR",
"Enter FOR",
provider.onChangefor,
TextInputType.text,
false,
null,
), ),
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( textControllerWidget(
context, context,
provider.paymentTermsController, provider.SpecialNoteController,
"Payment Terms", "Special Note",
"Enter Payment Terms", "Enter Special Note",
provider.onChangepaymentTerms, provider.onChangeSpecialNote,
TextInputType.text, TextInputType.text,
false, false,
null, 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> { ...@@ -369,12 +639,13 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
? null ? null
: () { : () {
//genquotedown //genquotedown
final insertedData = provider.getFormData(); final insertedData = provider.productRows;
print(insertedData);
provider provider
.crmLeadDetailsGenerateQuoteSubmitAPIFunction( .crmLeadDetailsGenerateQuoteSubmitAPIFunction(
context, context,
widget.leadId, widget.leadId,
insertedData, insertedData,
"genquotedown", "genquotedown",
); );
}, },
...@@ -400,7 +671,9 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> { ...@@ -400,7 +671,9 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
AppColors.app_blue, 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> { ...@@ -412,14 +685,14 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
? null ? null
: () { : () {
//genquotemail, //genquotemail,
final insertedData = provider.getFormData(); final insertedData = provider.getFormData();
provider provider
.crmLeadDetailsGenerateQuoteSubmitAPIFunction( .crmLeadDetailsGenerateQuoteSubmitAPIFunction(
context, context,
widget.leadId, widget.leadId,
insertedData, insertedData,
"genquotemail", "genquotemail",
); );
}, },
child: Container( child: Container(
height: 45, height: 45,
...@@ -443,7 +716,9 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> { ...@@ -443,7 +716,9 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
AppColors.app_blue, 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> { ...@@ -455,14 +730,14 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
? null ? null
: () { : () {
//genquotewhatsapp, //genquotewhatsapp,
final insertedData = provider.getFormData(); final insertedData = provider.getFormData();
provider provider
.crmLeadDetailsGenerateQuoteSubmitAPIFunction( .crmLeadDetailsGenerateQuoteSubmitAPIFunction(
context, context,
widget.leadId, widget.leadId,
insertedData, insertedData,
"genquotewhatsapp", "genquotewhatsapp",
); );
}, },
child: Container( child: Container(
height: 45, height: 45,
...@@ -486,7 +761,9 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> { ...@@ -486,7 +761,9 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
AppColors.app_blue, 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> { ...@@ -498,14 +775,14 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
? null ? null
: () { : () {
//genquotewhatsappbymynum, //genquotewhatsappbymynum,
final insertedData = provider.getFormData(); final insertedData = provider.getFormData();
provider provider
.crmLeadDetailsGenerateQuoteSubmitAPIFunction( .crmLeadDetailsGenerateQuoteSubmitAPIFunction(
context, context,
widget.leadId, widget.leadId,
insertedData, insertedData,
"genquotewhatsappbymynum", "genquotewhatsappbymynum",
); );
}, },
child: Container( child: Container(
height: 45, height: 45,
...@@ -529,7 +806,9 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> { ...@@ -529,7 +806,9 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
AppColors.app_blue, 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> { ...@@ -37,7 +37,7 @@ class _PendingtasksdetailsState extends State<Pendingtasksdetails> {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
var prov = Provider.of<Crmdashboardprovider>(context, listen: false); var prov = Provider.of<Crmdashboardprovider>(context, listen: false);
prov.accessPagesAPIFunction(context); prov.accessPagesAPIFunction(context);
prov.crmDashboardAPIFunction(context, "executive", "", "", ""); prov.crmDashboardAPIFunction(context);
prov.crmPendingTasksAPIFunction(context); prov.crmPendingTasksAPIFunction(context);
}); });
} }
...@@ -255,7 +255,9 @@ class _PendingtasksdetailsState extends State<Pendingtasksdetails> { ...@@ -255,7 +255,9 @@ class _PendingtasksdetailsState extends State<Pendingtasksdetails> {
onTap: () async { onTap: () async {
await Navigator.push( await Navigator.push(
context, context,
MaterialPageRoute(builder: (context) => Followupupdatescreen()), MaterialPageRoute(builder: (context) => Followupupdatescreen(
leadID: task.leadid,
)),
); );
}, },
child: Container( 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