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';
...@@ -23,6 +24,10 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -23,6 +24,10 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
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,9 +257,11 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -175,9 +257,11 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
leadID, leadID,
); );
if (data != null) { if (data != null) {
if (data.sessionExists == 1) {
if (data.error == "0") { if (data.error == "0") {
_isLoading = false; _isLoading = false;
_leadProductsList = data.leadProducts ?? []; _leadProductsList = data.leadProducts ?? [];
_quoteDetails = _quoteDetails =
data.quoteDetails ?? data.quoteDetails ??
QuoteDetails( QuoteDetails(
...@@ -189,18 +273,38 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -189,18 +273,38 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
paymentTerms: "", paymentTerms: "",
subject: "", subject: "",
); );
mailIdController.text = data.quoteDetails!.email??"-"; mailIdController.text = data.quoteDetails!.email ?? "-";
mobileController.text = data.quoteDetails!.mobile??"-"; mobileController.text = data.quoteDetails!.mobile ?? "-";
subjectsController.text = data.quoteDetails!.subject??"-"; subjectsController.text = data.quoteDetails!.subject ?? "-";
// taxesController.text = data.quoteDetails!1; // taxesController.text = data.quoteDetails!1;
// SpecialNoteController.text = data.quoteDetails; // SpecialNoteController.text = data.quoteDetails;
forController.text = data.quoteDetails!.forText??"-"; forController.text = data.quoteDetails!.forText ?? "-";
paymentTermsController.text = data.quoteDetails!.paymentTerms??"-"; 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(); notifyListeners();
} else { } else {
_isLoading = false; _isLoading = false;
notifyListeners(); notifyListeners();
} }
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LoginScreen(),
settings: RouteSettings(name: 'LoginScreen'),
),
);
}
} else { } else {
_isLoading = false; _isLoading = false;
notifyListeners(); notifyListeners();
...@@ -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,6 +379,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -268,6 +379,7 @@ 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,
...@@ -277,7 +389,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier { ...@@ -277,7 +389,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
) 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);
...@@ -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();
} }
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,6 +657,12 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -654,6 +657,12 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
), ),
), ),
Expanded( Expanded(
child: InkResponse(
onTap: () async {
editProvider.resetForm();
await editProvider.crmLeadDetailsEditProductsViewAPIFunction(context, provider.leadDetails.id!);
_showAddEditProductsSheet(context,widget.mode, "add", "");
},
child: Text( child: Text(
textAlign: TextAlign.right, textAlign: TextAlign.right,
"+ Add Product", "+ Add Product",
...@@ -664,12 +673,13 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -664,12 +673,13 @@ 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,8 +950,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -915,8 +950,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
); );
}, },
), ),
],
///Followup details ///Followup details
if (provider.followupDetails.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(
...@@ -938,7 +975,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -938,7 +975,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
var res = await Navigator.push( var res = await Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => Followupupdatescreen(), builder: (context) => Followupupdatescreen(
leadID: provider.leadDetails.id,
mode: widget.mode,
),
settings: RouteSettings( settings: RouteSettings(
name: 'Followupupdatescreen', name: 'Followupupdatescreen',
), ),
...@@ -966,7 +1006,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -966,7 +1006,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
physics: AlwaysScrollableScrollPhysics(), physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10), padding: EdgeInsets.symmetric(
vertical: 10,
horizontal: 10,
),
itemCount: provider.followupDetails.length, itemCount: provider.followupDetails.length,
itemBuilder: (context, lp) { itemBuilder: (context, lp) {
return Container( return Container(
...@@ -1023,7 +1066,8 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -1023,7 +1066,8 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
"JakartaMedium", "JakartaMedium",
fontSize: 14, fontSize: 14,
color: color:
AppColors.semi_black, AppColors
.semi_black,
), ),
), ),
Text( Text(
...@@ -1047,7 +1091,9 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -1047,7 +1091,9 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: borderRadius:
BorderRadius.circular(8), BorderRadius.circular(
8,
),
color: Color(0xFFF3FFD5), color: Color(0xFFF3FFD5),
), ),
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
...@@ -1056,13 +1102,16 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -1056,13 +1102,16 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
), ),
child: Center( child: Center(
child: Text( child: Text(
textAlign: TextAlign.right, textAlign:
TextAlign.right,
"${provider.followupDetails[lp].fstatus ?? "-"}", "${provider.followupDetails[lp].fstatus ?? "-"}",
style: TextStyle( style: TextStyle(
fontFamily: fontFamily:
"JakartaMedium", "JakartaMedium",
fontSize: 14, fontSize: 14,
color: Color(0xFF586000), color: Color(
0xFF586000,
),
), ),
), ),
), ),
...@@ -1112,7 +1161,8 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -1112,7 +1161,8 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
return Container( return Container(
padding: EdgeInsets.symmetric(vertical: 3), padding: EdgeInsets.symmetric(vertical: 3),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment:
CrossAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
child: Text( child: Text(
...@@ -1185,7 +1235,9 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -1185,7 +1235,9 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
Expanded( Expanded(
child: Text( child: Text(
textAlign: TextAlign.right, textAlign: TextAlign.right,
provider.followupDetails[lp].ffeedback == provider
.followupDetails[lp]
.ffeedback ==
"" ""
? "-" ? "-"
: provider : provider
...@@ -1208,8 +1260,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> { ...@@ -1208,8 +1260,10 @@ class _LeadDetailsByModeState extends State<LeadDetailsByMode> {
}, },
), ),
), ),
],
///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,7 +208,7 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> { ...@@ -208,7 +208,7 @@ 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',
...@@ -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,
...@@ -720,7 +924,9 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> { ...@@ -720,7 +924,9 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
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
...@@ -74,7 +74,7 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -74,7 +74,7 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
} }
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,
...@@ -185,9 +185,10 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -185,9 +185,10 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
], ],
), ),
items: items:
<String>['Active', 'Inactive', 'Suspense'] <String>['Phone', 'Visit']
.map( .map(
(value) => DropdownMenuItem<String>( (value) =>
DropdownMenuItem<String>(
value: value, value: value,
child: Text( child: Text(
value ?? '', value ?? '',
...@@ -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,15 +245,10 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -244,15 +245,10 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
], ],
), ),
items: items:
<String>[ <String>['Cold', 'Hot', 'Warm']
'Cold',
'Hot',
'Warm',
'Open',
'Closed',
]
.map( .map(
(value) => DropdownMenuItem<String>( (value) =>
DropdownMenuItem<String>(
value: value, value: value,
child: Text( child: Text(
value ?? '', value ?? '',
...@@ -303,14 +299,12 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -303,14 +299,12 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
), ),
items: items:
<String>[ <String>[
'Cold', 'Next Appointment',
'Hot', 'Update Order Status',
'Warm',
'Open',
'Closed',
] ]
.map( .map(
(value) => DropdownMenuItem<String>( (value) =>
DropdownMenuItem<String>(
value: value, value: value,
child: Text( child: Text(
value ?? '', value ?? '',
...@@ -341,12 +335,17 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -341,12 +335,17 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
), ),
), ),
SizedBox(height: 15), SizedBox(height: 15),
if (provider.nextAppointmentStatus ==
"Update Order Status") ...[
Container( Container(
padding: EdgeInsets.only(left: 10), padding: EdgeInsets.only(left: 10),
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
child: Text( child: Text(
"Next Appointment", "Update Order Status",
style: TextStyle(color: AppColors.grey_thick, fontSize: 16), style: TextStyle(
color: AppColors.grey_thick,
fontSize: 16,
),
), ),
), ),
Container( Container(
...@@ -356,6 +355,177 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -356,6 +355,177 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
), ),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10), margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5), padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
TextWidget(context, "Select Status"),
DropdownButtonHideUnderline(
child: Row(
children: [
Expanded(
child: DropdownButton2<String>(
isExpanded: true,
hint: const Row(
children: [
Expanded(
child: Text(
'Select Status',
style: TextStyle(fontSize: 14),
overflow: TextOverflow.ellipsis,
),
),
],
),
items:
<String>[
'Order Gain',
'Order Lost',
'No Requirement',
]
.map(
(value) =>
DropdownMenuItem<String>(
value: value,
child: Text(
value ?? '',
style: const TextStyle(
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
),
),
)
.toList(),
value: provider.selectOrderStatus,
onChanged: (String? newValue) {
setState(() {
provider.selectOrderStatus = newValue!;
});
},
buttonStyleData: ddtheme.buttonStyleData,
iconStyleData: ddtheme.iconStyleData,
menuItemStyleData: ddtheme.menuItemStyleData,
dropdownStyleData: ddtheme.dropdownStyleData,
),
),
],
),
),
if (provider.selectOrderStatus == "Order Gain")
...[]
else
...[
if (provider.selectOrderStatus == "Order Lost") ...[
TextWidget(context, "Select Competitor"),
DropdownButtonHideUnderline(
child: Row(
children: [
Expanded(
child: DropdownButton2<String>(
isExpanded: true,
hint: const Row(
children: [
Expanded(
child: Text(
'Select Competitor',
style: TextStyle(fontSize: 14),
overflow: TextOverflow.ellipsis,
),
),
],
),
items:
<String>[
"Mahindra",
"Kirloskar",
"Cummins",
"Ashok Leyland",
"Escorts",
"Eicher",
"Eicher Volovo",
"Ecogen",
"Crompton Greaves",
"Caterpillar",
]
.map(
(value) =>
DropdownMenuItem<String>(
value: value,
child: Text(
value ?? '',
style: const TextStyle(
fontSize: 14,
),
overflow:
TextOverflow
.ellipsis,
),
),
)
.toList(),
value: provider.selectedCompetitor,
onChanged: (String? newValue) {
setState(() {
provider.selectedCompetitor =
newValue!;
});
},
buttonStyleData: ddtheme
.buttonStyleData,
iconStyleData: ddtheme.iconStyleData,
menuItemStyleData:
ddtheme.menuItemStyleData,
dropdownStyleData:
ddtheme.dropdownStyleData,
),
),
],
),
),
] else
if (provider.selectOrderStatus ==
"No Requirement")
...[],
textControllerWidget(
context,
provider.reasonController,
"Reason",
"Reason (Description)",
provider.onReasonChanged,
TextInputType.text,
false,
null,
),
],
],
),
),
] else
...[
Container(
padding: EdgeInsets.only(left: 10),
alignment: Alignment.topLeft,
child: Text(
"Next Appointment",
style: TextStyle(
color: AppColors.grey_thick,
fontSize: 16,
),
),
),
GestureDetector(
onTap: () {
provider.showDatePickerDialog(context);
},
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
padding: EdgeInsets.symmetric(
horizontal: 10, vertical: 5),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
...@@ -369,9 +539,15 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -369,9 +539,15 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
borderRadius: BorderRadius.circular(14), borderRadius: BorderRadius.circular(14),
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10, 0), padding: const EdgeInsets.fromLTRB(
10.0,
0.0,
10,
0,
),
child: TextFormField( child: TextFormField(
controller: provider.nextAppointmentDateController, controller:
provider.nextAppointmentDateController,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
enabled: false, enabled: false,
maxLines: 1, maxLines: 1,
...@@ -411,9 +587,10 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -411,9 +587,10 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
], ],
), ),
items: items:
<String>['Active', 'Inactive', 'Suspense'] <String>['Phone', 'Visit']
.map( .map(
(value) => DropdownMenuItem<String>( (value) =>
DropdownMenuItem<String>(
value: value, value: value,
child: Text( child: Text(
value ?? '', value ?? '',
...@@ -434,19 +611,48 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -434,19 +611,48 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
}, },
buttonStyleData: ddtheme.buttonStyleData, buttonStyleData: ddtheme.buttonStyleData,
iconStyleData: ddtheme.iconStyleData, iconStyleData: ddtheme.iconStyleData,
menuItemStyleData: ddtheme.menuItemStyleData, menuItemStyleData: ddtheme
dropdownStyleData: ddtheme.dropdownStyleData, .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());
},
),
],
textControllerWidget( textControllerWidget(
context, context,
noteController, provider.noteController,
"Note", "Note",
"Write Note", "Write Note",
onNoteChanged, provider.onNoteChanged,
TextInputType.text, TextInputType.text,
false, false,
null, null,
...@@ -454,7 +660,8 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -454,7 +660,8 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
], ],
), ),
), ),
),
],
SizedBox(height: 150), SizedBox(height: 150),
], ],
), ),
...@@ -462,7 +669,20 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> { ...@@ -462,7 +669,20 @@ class _FollowupupdatescreenState extends State<Followupupdatescreen> {
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,27 +51,40 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> { ...@@ -49,27 +51,40 @@ 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),
padding: const EdgeInsets.symmetric(horizontal: 10),
child: SingleChildScrollView(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
margin: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
children: [ children: [
textControllerWidget( textControllerWidget(
context, context,
...@@ -106,10 +121,49 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> { ...@@ -106,10 +121,49 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
null, null,
), ),
errorWidget(context, provider.subjectsError), errorWidget(context, provider.subjectsError),
],
),
),
Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
margin: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
children: [
InkResponse( InkResponse(
onTap: () { onTap: () async {
provider.editAddNewRow(); 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( child: Container(
margin: const EdgeInsets.symmetric(vertical: 10), margin: const EdgeInsets.symmetric(vertical: 10),
...@@ -134,163 +188,377 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> { ...@@ -134,163 +188,377 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
), ),
), ),
), ),
if (provider.leadProductsList.isNotEmpty || if (provider.leadProductsList.isNotEmpty) ...[
provider.editProductPriceControllers.isNotEmpty) ...[ SizedBox(
ListView.builder( width: double.infinity,
itemCount: provider.editProductPriceControllers.length, height: 125,
physics: const NeverScrollableScrollPhysics(), child: ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
itemBuilder: (context, j) { scrollDirection: Axis.horizontal,
return Container( padding: EdgeInsets.symmetric(
padding: const EdgeInsets.symmetric( vertical: 15,
horizontal: 10, horizontal: 0,
vertical: 10,
),
margin: const EdgeInsets.symmetric(vertical: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
), ),
child: Column( itemCount: provider.leadProductsList.length,
crossAxisAlignment: CrossAxisAlignment.start, itemBuilder: (context, lp) {
children: [ return InkResponse(
TextWidget(context, "Product"), onTap: () async {
DropdownButtonHideUnderline( var res = await Navigator.push(
child: Row( context,
children: [ MaterialPageRoute(
Expanded( builder:
child: DropdownButton2<LeadProducts>( (
isExpanded: true, context,
hint: const Text( ) => Generatequotationaddeditproduct(
'Select Product', leadId: widget.leadId,
style: TextStyle(fontSize: 14), type: "edit",
overflow: TextOverflow.ellipsis, product:
), provider
items: .leadProductsList[lp]!,
provider.leadProductsList index: lp,
.map(
(ord) => DropdownMenuItem<
LeadProducts
>(
value: ord,
child: Text(
"(Product Name: ${ord.productName})",
style: const TextStyle(
fontSize: 14,
), ),
overflow: settings: RouteSettings(
TextOverflow name:
.ellipsis, 'Generatequotationaddeditproduct',
), ),
), ),
)
.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] = if (res != null) {
value.id?.toString() ?? ''; print("result ${res}");
provider.updateTotalAmount(j);
} }
}, },
buttonStyleData: child: Container(
ddtheme.buttonStyleData, height: 115,
iconStyleData: ddtheme.iconStyleData, width:
menuItemStyleData: MediaQuery.of(context).size.width *
ddtheme.menuItemStyleData, 0.8,
dropdownStyleData: decoration: BoxDecoration(
ddtheme.dropdownStyleData, 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",
), ),
), ),
const SizedBox(height: 10), SizedBox(width: 10),
Expanded(
flex: 6,
child: SizedBox(
child: Column(
// mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Row( Row(
children: [ children: [
Expanded( Expanded(
flex: 2, flex: 4,
child: textControllerWidget( child: Text(
context, provider
provider.editProductPriceControllers[j], .leadProductsList[lp]
"Product Price", .productName ??
"Enter Product Price", "-",
(value) => maxLines: 1,
provider.updateTotalAmount(j), overflow:
TextInputType.number, TextOverflow
false, .ellipsis,
FilteringTextInputFormatter.digitsOnly, style: TextStyle(
fontFamily:
"JakartaMedium",
fontSize: 14,
color:
AppColors
.semi_black,
), ),
), ),
],
), ),
const SizedBox(height: 10),
Row(
children: [
Expanded( Expanded(
flex: 2, flex: 2,
child: textControllerWidget( child: Text(
context, textAlign:
provider.editQuantityControllers[j], TextAlign.right,
"Quantity", "₹${provider.leadProductsList[lp].price ?? "-"}",
"Enter Quantity", style: TextStyle(
(value) => fontFamily:
provider.updateTotalAmount(j), "JakartaMedium",
TextInputType.number, fontSize: 14,
false, color:
FilteringTextInputFormatter.digitsOnly, AppColors
.semi_black,
),
), ),
), ),
], ],
), ),
const SizedBox(height: 10), Text(
Row( "x ${provider.leadProductsList[lp].qty ?? "-"}",
children: [ style: TextStyle(
Expanded( fontFamily:
flex: 2, "JakartaMedium",
child: textControllerWidget( fontSize: 14,
context, color:
provider.editTotalAmountControllers[j], AppColors.grey_semi,
"Amount", ),
"Total Amount", ),
(_) {}, SizedBox(height: 5),
TextInputType.number, DottedLine(
true, dashGapLength: 4,
FilteringTextInputFormatter.digitsOnly, dashGapColor: Colors.white,
dashColor:
AppColors.grey_semi,
dashLength: 2,
lineThickness: 0.5,
),
SizedBox(height: 5),
Text(
"₹${provider.leadProductsList[lp].prodTotalPrice ?? " - "}",
style: TextStyle(
fontFamily:
"JakartaMedium",
fontSize: 14,
color:
AppColors.semi_black,
), ),
), ),
], ],
), ),
// IconButton( ),
// icon: const Icon(Icons.delete), ),
// onPressed: provider.editProductPriceControllers.length > 1
// ? () => provider.editRemoveRow(j)
// : null,
// ),
], ],
), ),
),
); );
}, },
), ),
),
],
// if (provider.leadProductsList.isNotEmpty ||
// provider
// .editProductPriceControllers
// .isNotEmpty) ...[
// ListView.builder(
// itemCount:
// provider.editProductPriceControllers.length,
// physics: const NeverScrollableScrollPhysics(),
// shrinkWrap: true,
// itemBuilder: (context, j) {
// return Container(
// padding: const EdgeInsets.symmetric(
// horizontal: 10,
// vertical: 10,
// ),
// margin: const EdgeInsets.symmetric(
// vertical: 10,
// ),
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(20),
// ),
// child: Column(
// crossAxisAlignment:
// CrossAxisAlignment.start,
// children: [
// TextWidget(context, "Product"),
// DropdownButtonHideUnderline(
// child: Row(
// children: [
// Expanded(
// child: DropdownButton2<
// LeadProducts
// >(
// isExpanded: true,
// hint: const Text(
// 'Select Product',
// style: TextStyle(
// fontSize: 14,
// ),
// overflow:
// TextOverflow.ellipsis,
// ),
// items:
// provider.leadProductsList
// .map(
// (
// ord,
// ) => DropdownMenuItem<
// LeadProducts
// >(
// value: ord,
// child: Text(
// "(Product Name: ${ord.productName})",
// style:
// const TextStyle(
// fontSize:
// 14,
// ),
// overflow:
// TextOverflow
// .ellipsis,
// ),
// ),
// )
// .toList(),
// value:
// provider.selectedProductIds[j] !=
// null
// ? provider
// .leadProductsList
// .firstWhere(
// (ord) =>
// ord.id ==
// provider
// .selectedProductIds[j],
// orElse:
// () =>
// provider
// .leadProductsList[0],
// )
// : null,
// onChanged: (
// LeadProducts? value,
// ) {
// if (value != null) {
// provider
// .updateSelectedProductIds(
// j,
// value,
// );
// provider.selectedProductIds[j] =
// value.id?.toString() ??
// '';
// provider.updateTotalAmount(
// j,
// );
// }
// },
// buttonStyleData:
// ddtheme.buttonStyleData,
// iconStyleData:
// ddtheme.iconStyleData,
// menuItemStyleData:
// ddtheme.menuItemStyleData,
// dropdownStyleData:
// ddtheme.dropdownStyleData,
// ),
// ),
// ],
// ),
// ),
// const SizedBox(height: 10),
// Row(
// children: [
// Expanded(
// flex: 2,
// child: textControllerWidget(
// context,
// provider
// .editProductPriceControllers[j],
// "Product Price",
// "Enter Product Price",
// (value) =>
// provider.updateTotalAmount(j),
// TextInputType.number,
// false,
// FilteringTextInputFormatter
// .digitsOnly,
// ),
// ),
// ],
// ),
// const SizedBox(height: 10),
// Row(
// children: [
// Expanded(
// flex: 2,
// child: textControllerWidget(
// context,
// provider
// .editQuantityControllers[j],
// "Quantity",
// "Enter Quantity",
// (value) =>
// provider.updateTotalAmount(j),
// TextInputType.number,
// false,
// FilteringTextInputFormatter
// .digitsOnly,
// ),
// ),
// ],
// ),
// const SizedBox(height: 10),
// Row(
// children: [
// Expanded(
// flex: 2,
// child: textControllerWidget(
// context,
// provider
// .editTotalAmountControllers[j],
// "Amount",
// "Total Amount",
// (_) {},
// TextInputType.number,
// true,
// FilteringTextInputFormatter
// .digitsOnly,
// ),
// ),
// ],
// ),
// // IconButton(
// // icon: const Icon(Icons.delete),
// // onPressed: provider.editProductPriceControllers.length > 1
// // ? () => provider.editRemoveRow(j)
// // : null,
// // ),
// ],
// ),
// );
// },
// ),
// ],
], ],
),
),
Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
margin: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
children: [
textControllerWidget( textControllerWidget(
context, context,
provider.taxesController, provider.taxesController,
...@@ -341,6 +609,8 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> { ...@@ -341,6 +609,8 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> {
], ],
), ),
), ),
],
),
), ),
floatingActionButtonLocation: floatingActionButtonLocation:
...@@ -369,7 +639,8 @@ class _GeneratequotationscreenState extends State<Generatequotationscreen> { ...@@ -369,7 +639,8 @@ 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,
...@@ -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",
),
), ),
), ),
), ),
...@@ -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",
),
), ),
), ),
), ),
...@@ -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",
),
), ),
), ),
), ),
...@@ -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