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