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
d2939607
Commit
d2939607
authored
Nov 21, 2025
by
Sai Srinivas
Browse files
Correction and changes
parent
a5ccb211
Changes
42
Hide whitespace changes
Inline
Side-by-side
lib/Models/financeModels/ValidateBankAccountDetailsResponse.dart
0 → 100644
View file @
d2939607
class
ValidateBankAccountDetailsResponse
{
String
?
nameAtBank
;
String
?
bankName
;
String
?
branch
;
String
?
error
;
String
?
message
;
int
?
sessionExists
;
ValidateBankAccountDetailsResponse
(
{
this
.
nameAtBank
,
this
.
bankName
,
this
.
branch
,
this
.
error
,
this
.
message
,
this
.
sessionExists
});
ValidateBankAccountDetailsResponse
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
nameAtBank
=
json
[
'name_at_bank'
];
bankName
=
json
[
'bank_name'
];
branch
=
json
[
'branch'
];
error
=
json
[
'error'
];
message
=
json
[
'message'
];
sessionExists
=
json
[
'session_exists'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'name_at_bank'
]
=
this
.
nameAtBank
;
data
[
'bank_name'
]
=
this
.
bankName
;
data
[
'branch'
]
=
this
.
branch
;
data
[
'error'
]
=
this
.
error
;
data
[
'message'
]
=
this
.
message
;
data
[
'session_exists'
]
=
this
.
sessionExists
;
return
data
;
}
}
lib/Models/financeModels/ValidateGstNumResponse.dart
0 → 100644
View file @
d2939607
class
ValidateGstNumResponse
{
String
?
legalNameOfBusiness
;
String
?
address
;
String
?
error
;
String
?
message
;
int
?
sessionExists
;
ValidateGstNumResponse
(
{
this
.
legalNameOfBusiness
,
this
.
address
,
this
.
error
,
this
.
message
,
this
.
sessionExists
});
ValidateGstNumResponse
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
legalNameOfBusiness
=
json
[
'legal_name_of_business'
];
address
=
json
[
'address'
];
error
=
json
[
'error'
];
message
=
json
[
'message'
];
sessionExists
=
json
[
'session_exists'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'legal_name_of_business'
]
=
this
.
legalNameOfBusiness
;
data
[
'address'
]
=
this
.
address
;
data
[
'error'
]
=
this
.
error
;
data
[
'message'
]
=
this
.
message
;
data
[
'session_exists'
]
=
this
.
sessionExists
;
return
data
;
}
}
lib/Models/ordersModels/commonResponse.dart
View file @
d2939607
class
CommonResponse
{
String
?
error
;
String
?
message
;
String
?
qrCode
;
String
?
qrId
;
int
?
sessionExists
;
CommonResponse
({
this
.
error
,
this
.
message
,
this
.
sessionExists
});
CommonResponse
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
error
=
json
[
'error'
];
qrCode
=
json
[
'qr_code'
];
qrId
=
json
[
'razorpay_order_id'
];
message
=
json
[
'message'
];
sessionExists
=
json
[
'session_exists'
];
}
...
...
@@ -15,6 +18,8 @@ class CommonResponse {
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
<
String
,
dynamic
>{};
data
[
'error'
]
=
error
;
data
[
'qr_code'
]
=
qrCode
;
data
[
'razorpay_order_id'
]
=
qrId
;
data
[
'message'
]
=
message
;
data
[
'session_exists'
]
=
sessionExists
;
return
data
;
...
...
lib/Notifiers/PaymentDetailsProvider.dart
View file @
d2939607
...
...
@@ -208,6 +208,7 @@ class Paymentdetailsprovider extends ChangeNotifier {
_imageName
=
null
;
_image_picked
=
0
;
resetErrors
();
notifyListeners
();
}
else
{}
}
else
{
...
...
@@ -775,6 +776,22 @@ class Paymentdetailsprovider extends ChangeNotifier {
}
}
void
resetErrors
()
{
nameError
=
null
;
designationError
=
null
;
mobError
=
null
;
altMobError
=
null
;
telError
=
null
;
emailError
=
null
;
selectContactError
=
null
;
selectPaymentError
=
null
;
selectAmountError
=
null
;
ReferenceError
=
null
;
imageError
=
null
;
notifyListeners
();
}
resetAddContect
()
{
Amountcontroller
.
clear
();
Referencecontroller
.
clear
();
...
...
lib/Notifiers/QrProvider.dart
0 → 100644
View file @
d2939607
import
'dart:async'
;
import
'package:flutter/material.dart'
;
import
'../Models/ordersModels/commonResponse.dart'
;
import
'../Utils/custom_snackbar.dart'
;
import
'../services/api_calling.dart'
;
class
QrProvider
extends
ChangeNotifier
{
CommonResponse
?
_qrResponse
;
bool
_isLoading
=
false
;
String
?
_errorMessage
;
int
_secondsLeft
=
120
;
// 2 minutes
CommonResponse
?
get
qrResponse
=>
_qrResponse
;
bool
get
isLoading
=>
_isLoading
;
String
?
get
errorMessage
=>
_errorMessage
;
int
get
secondsLeft
=>
_secondsLeft
;
Timer
?
_timer
;
/// Fetch Razorpay QR API
Future
<
void
>
fetchRazorpayQr
({
required
String
sessionId
,
required
String
empId
,
required
String
amount
,
required
String
refType
,
required
String
refId
,
})
async
{
_isLoading
=
true
;
_errorMessage
=
null
;
notifyListeners
();
try
{
final
response
=
await
ApiCalling
.
fetchRazorpayUpiQrApi
(
sessionId
,
empId
,
amount
,
refType
,
refId
,
);
if
(
response
!=
null
&&
response
.
error
==
"0"
)
{
_qrResponse
=
response
;
_startTimer
();
}
else
{
_errorMessage
=
response
?.
message
??
"Something went wrong"
;
}
}
catch
(
e
)
{
_errorMessage
=
e
.
toString
();
}
finally
{
_isLoading
=
false
;
notifyListeners
();
}
}
/// Start 2-minute countdown
void
_startTimer
()
{
_secondsLeft
=
120
;
_timer
?.
cancel
();
_timer
=
Timer
.
periodic
(
const
Duration
(
seconds:
1
),
(
timer
)
{
if
(
_secondsLeft
>
0
)
{
_secondsLeft
--;
notifyListeners
();
}
else
{
timer
.
cancel
();
}
});
}
/// Dispose timer properly
@override
void
dispose
()
{
_timer
?.
cancel
();
super
.
dispose
();
}
bool
_isPaymentUpdating
=
false
;
bool
get
isPaymentUpdating
=>
_isPaymentUpdating
;
set
isPaymentUpdating
(
bool
value
)
{
_isPaymentUpdating
=
value
;
notifyListeners
();
}
/// Fetch Razorpay QR Payment Status
Future
<
CommonResponse
?>
fetchRazorpayUpiQrStatus
({
required
BuildContext
context
,
required
String
sessionId
,
required
String
empId
,
required
String
razorpayOrderId
,
})
async
{
try
{
isPaymentUpdating
=
true
;
final
response
=
await
ApiCalling
.
fetchRazorpayUpiQrStatusApi
(
sessionId
,
empId
,
razorpayOrderId
,
);
if
(
response
!=
null
)
{
if
(
response
.
sessionExists
==
1
&&
response
.
error
==
"0"
)
{
debugPrint
(
" Payment Status:
${response.message}
"
);
}
else
{
CustomSnackBar
.
showWarning
(
context:
context
,
message:
"⚠️ Payment not yet completed or failed"
);
debugPrint
(
"⚠️ Payment not yet completed or failed"
);
}
}
else
{
debugPrint
(
"❌ Null response from Razorpay QR Status API"
);
}
return
response
;
// return here
}
catch
(
e
)
{
debugPrint
(
"❌ fetchRazorpayUpiQrStatus error:
$e
"
);
return
null
;
}
finally
{
isPaymentUpdating
=
false
;
}
}
}
lib/Notifiers/commonProvider/ValidationProvider.dart
0 → 100644
View file @
d2939607
import
'package:flutter/material.dart'
;
import
'package:generp/services/api_calling.dart'
;
import
'../../Models/financeModels/ValidateBankAccountDetailsResponse.dart'
;
import
'../../Models/financeModels/ValidateGstNumResponse.dart'
;
class
ValidationProvider
extends
ChangeNotifier
{
bool
isLoading
=
false
;
ValidateGstNumResponse
?
gstResponse
;
ValidateBankAccountDetailsResponse
?
bankResponse
;
String
?
errorMessage
;
/// Validate GST Number
/// -----------------------------
Future
<
void
>
validateGstNumber
(
String
empId
,
String
sessionId
,
String
gstNumber
)
async
{
try
{
isLoading
=
true
;
errorMessage
=
null
;
notifyListeners
();
gstResponse
=
await
ApiCalling
.
validateGstNumberApi
(
empId
,
sessionId
,
gstNumber
,
);
if
(
gstResponse
==
null
)
{
errorMessage
=
"Failed to validate GST number"
;
}
}
catch
(
e
)
{
errorMessage
=
e
.
toString
();
}
isLoading
=
false
;
notifyListeners
();
}
/// Validate Bank Account Details
/// -----------------------------
Future
<
void
>
validateBankDetails
(
String
empId
,
String
sessionId
,
String
accountNumber
)
async
{
try
{
isLoading
=
true
;
errorMessage
=
null
;
notifyListeners
();
bankResponse
=
await
ApiCalling
.
validateBankAccountDetailsApi
(
empId
,
sessionId
,
accountNumber
,
""
);
if
(
bankResponse
==
null
)
{
errorMessage
=
"Failed to validate bank account"
;
}
}
catch
(
e
)
{
errorMessage
=
e
.
toString
();
}
isLoading
=
false
;
notifyListeners
();
}
/// Reset before calling again
void
clear
()
{
gstResponse
=
null
;
bankResponse
=
null
;
errorMessage
=
null
;
notifyListeners
();
}
}
lib/Notifiers/commonProvider/accountsListProvider.dart
View file @
d2939607
// accountsListProvider.dart
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
...
...
@@ -12,6 +13,8 @@ import '../../Models/commonModels/DistrictsResponse.dart';
import
'../../Models/commonModels/SubLocationsResponse.dart'
;
import
'../../Models/commonModels/commonAccountlistResponse.dart'
;
import
'../../Models/commonModels/commonAddAccountsViewResponse.dart'
;
import
'../../Models/financeModels/ValidateBankAccountDetailsResponse.dart'
;
import
'../../Models/financeModels/ValidateGstNumResponse.dart'
;
class
Accountslistprovider
extends
ChangeNotifier
{
TextEditingController
nameController
=
TextEditingController
();
...
...
@@ -21,11 +24,11 @@ class Accountslistprovider extends ChangeNotifier {
TextEditingController
branchNameController
=
TextEditingController
();
TextEditingController
bankIfscCotroller
=
TextEditingController
();
TextEditingController
bankHolderNameController
=
TextEditingController
();
TextEditingController
gstNumberController
=
TextEditingController
();
TextEditingController
bankAcNumberController
=
TextEditingController
();
TextEditingController
bankUpiController
=
TextEditingController
();
TextEditingController
contactPersonController
=
TextEditingController
();
TextEditingController
contectPersonDesignationController
=
TextEditingController
();
TextEditingController
contectPersonDesignationController
=
TextEditingController
();
TextEditingController
contectPersonAltMobController
=
TextEditingController
();
TextEditingController
contectPersonTeleController
=
TextEditingController
();
TextEditingController
contectPersonMailController
=
TextEditingController
();
...
...
@@ -43,6 +46,7 @@ class Accountslistprovider extends ChangeNotifier {
String
?
districtError
;
String
?
localityError
;
String
?
addressError
;
String
?
gstNumberError
;
String
?
banknameError
;
String
?
bankBranchError
;
String
?
bankIFSCError
;
...
...
@@ -98,6 +102,11 @@ class Accountslistprovider extends ChangeNotifier {
notifyListeners
();
}
ValidateGstNumResponse
?
gstResponse
;
ValidateBankAccountDetailsResponse
?
bankResponse
;
String
?
errorMessage
;
States
?
_selectedState
;
Districts
?
_selectedDistricts
;
SubLocations
?
_selectedSubLocations
;
...
...
@@ -132,6 +141,12 @@ class Accountslistprovider extends ChangeNotifier {
String
?
get
selectedAccountType
=>
_selectedAccountType
;
// --- NEW: setter for isLoading so callers can do `isLoading = true;` ---
set
isLoading
(
bool
value
)
{
_isLoading
=
value
;
notifyListeners
();
}
set
selectedAccountType
(
String
?
value
)
{
_selectedAccountType
=
value
;
accountError
=
null
;
...
...
@@ -140,24 +155,24 @@ class Accountslistprovider extends ChangeNotifier {
set
selectedState
(
States
?
value
)
{
_selectedState
=
value
;
_selectedStateID
=
value
!
.
id
;
_selectedStateValue
=
value
.
name
;
_selectedStateID
=
value
?
.
id
;
_selectedStateValue
=
value
?
.
name
;
stateError
=
null
;
notifyListeners
();
}
set
selectedDistricts
(
Districts
?
value
)
{
_selectedDistricts
=
value
;
_selectedDistrictID
=
value
!
.
id
;
_selectedDistrictValue
=
value
.
district
;
_selectedDistrictID
=
value
?
.
id
;
_selectedDistrictValue
=
value
?
.
district
;
districtError
=
null
;
notifyListeners
();
}
set
selectedSubLocations
(
SubLocations
?
value
)
{
_selectedSubLocations
=
value
;
_selectedSubLocID
=
value
!
.
id
;
_selectedSubLocValue
=
value
.
subLocality
!
;
_selectedSubLocID
=
value
?
.
id
;
_selectedSubLocValue
=
value
?
.
subLocality
;
localityError
=
null
;
notifyListeners
();
}
...
...
@@ -192,6 +207,8 @@ class Accountslistprovider extends ChangeNotifier {
notifyListeners
();
}
// ---------- API / data loading ----------
Future
<
void
>
addCommonAccountViewAPI
(
context
)
async
{
try
{
var
homeProv
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
...
...
@@ -205,12 +222,15 @@ class Accountslistprovider extends ChangeNotifier {
if
(
data
!=
null
)
{
if
(
data
.
error
==
"0"
)
{
ChechkDropdownValues
();
_accountTypes
=
data
.
accountTypes
!
;
_states
=
data
.
states
!
;
_accountTypes
=
data
.
accountTypes
??
[]
;
_states
=
data
.
states
??
[]
;
notifyListeners
();
}
}
}
catch
(
e
)
{}
}
catch
(
e
)
{
// keep quiet but log in debug
if
(
kDebugMode
)
debugPrint
(
'addCommonAccountViewAPI error:
$e
'
);
}
}
Future
<
void
>
getDistrictAPI
(
context
,
stateID
)
async
{
...
...
@@ -225,11 +245,13 @@ class Accountslistprovider extends ChangeNotifier {
);
if
(
data
!=
null
)
{
if
(
data
.
error
==
"0"
)
{
_districts
=
data
.
districts
!
;
_districts
=
data
.
districts
??
[]
;
notifyListeners
();
}
}
}
catch
(
e
)
{}
}
catch
(
e
)
{
if
(
kDebugMode
)
debugPrint
(
'getDistrictAPI error:
$e
'
);
}
}
Future
<
void
>
getSubLocationAPI
(
context
,
districtID
)
async
{
...
...
@@ -244,11 +266,13 @@ class Accountslistprovider extends ChangeNotifier {
);
if
(
data
!=
null
)
{
if
(
data
.
error
==
"0"
)
{
_subLocations
=
data
.
subLocations
!
;
_subLocations
=
data
.
subLocations
??
[]
;
notifyListeners
();
}
}
}
catch
(
e
)
{}
}
catch
(
e
)
{
if
(
kDebugMode
)
debugPrint
(
'getSubLocationAPI error:
$e
'
);
}
}
Future
<
void
>
checkInputsAPI
(
context
,
type
,
value
)
async
{
...
...
@@ -272,10 +296,133 @@ class Accountslistprovider extends ChangeNotifier {
mobileError
=
data
.
message
??
""
;
}
notifyListeners
();
// toast(context, data.message);
}
}
}
catch
(
e
)
{}
}
catch
(
e
)
{
if
(
kDebugMode
)
debugPrint
(
'checkInputsAPI error:
$e
'
);
}
}
/// Validate GST Number
/// Returns true if validated successfully (and sets gstResponse). Caller can await.
Future
<
bool
>
validateGstNumber
(
String
empId
,
String
sessionId
,
String
gstNumber
)
async
{
// if empty — don't call API; clear any previous errors/responses
if
(
gstNumber
.
trim
().
isEmpty
)
{
gstResponse
=
null
;
gstNumberError
=
null
;
notifyListeners
();
return
false
;
}
try
{
isLoading
=
true
;
errorMessage
=
null
;
// call API
final
response
=
await
ApiCalling
.
validateGstNumberApi
(
empId
,
sessionId
,
gstNumber
,
);
// assign
gstResponse
=
response
;
if
(
response
==
null
)
{
gstNumberError
=
"Failed to validate GST number"
;
notifyListeners
();
return
false
;
}
// Response object expected to contain `error` and `address` and `legal_name_of_business`
if
(
response
.
error
==
"0"
)
{
gstNumberError
=
null
;
// Optionally update address or other fields in UI (UI will read gstResponse)
notifyListeners
();
return
true
;
}
else
{
// API returned invalid GST
gstNumberError
=
response
.
message
??
"Invalid GST number"
;
notifyListeners
();
return
false
;
}
}
catch
(
e
)
{
gstNumberError
=
"Error validating GST:
${e.toString()}
"
;
if
(
kDebugMode
)
debugPrint
(
'validateGstNumber error:
$e
'
);
notifyListeners
();
return
false
;
}
finally
{
isLoading
=
false
;
notifyListeners
();
}
}
/// Validate Bank Account Details
/// Returns true if validated successfully (and sets bankResponse). Caller can await.
Future
<
bool
>
validateBankDetails
(
String
empId
,
String
sessionId
,
String
accountNumber
)
async
{
// require accountNumber and IFSC to be present
final
ifsc
=
bankIfscCotroller
.
text
.
trim
();
if
(
accountNumber
.
trim
().
isEmpty
||
ifsc
.
isEmpty
)
{
// clear previous bankResponse if user cleared input
bankResponse
=
null
;
bankAcNumberError
=
null
;
bankIFSCError
=
null
;
notifyListeners
();
return
false
;
}
// basic IFSC format check (caller/UI also checks) — we trust UI but double-check
final
reg
=
RegExp
(
r'^[A-Za-z]{4}0[A-Za-z0-9]{6}$'
);
if
(!
reg
.
hasMatch
(
ifsc
))
{
bankIFSCError
=
"Invalid IFSC format"
;
notifyListeners
();
return
false
;
}
try
{
isLoading
=
true
;
errorMessage
=
null
;
// call API - pass account number and IFSC from controller (some APIs require both)
final
response
=
await
ApiCalling
.
validateBankAccountDetailsApi
(
empId
,
sessionId
,
accountNumber
,
ifsc
,
);
bankResponse
=
response
;
if
(
response
==
null
)
{
bankAcNumberError
=
"Failed to validate bank account"
;
notifyListeners
();
return
false
;
}
if
(
response
.
error
==
"0"
)
{
// success — populate fields in UI from the provider.bankResponse (UI will take the values)
bankAcNumberError
=
null
;
bankIFSCError
=
null
;
banknameError
=
null
;
bankBranchError
=
null
;
bankHolderNameError
=
null
;
notifyListeners
();
return
true
;
}
else
{
// error returned
bankAcNumberError
=
response
.
message
??
"Invalid account details"
;
notifyListeners
();
return
false
;
}
}
catch
(
e
)
{
bankAcNumberError
=
"Error validating account:
${e.toString()}
"
;
if
(
kDebugMode
)
debugPrint
(
'validateBankDetails error:
$e
'
);
notifyListeners
();
return
false
;
}
finally
{
isLoading
=
false
;
notifyListeners
();
}
}
bool
hasFilledAdditionalDetails
=
false
;
...
...
@@ -292,7 +439,6 @@ class Accountslistprovider extends ChangeNotifier {
Future
<
void
>
submitCommonAccountsAPI
(
context
,
from
)
async
{
try
{
if
(!
validatereceiptForm
(
context
))
{
// _submitClicked = false;
return
;
}
_submitClicked
=
true
;
...
...
@@ -327,14 +473,12 @@ class Accountslistprovider extends ChangeNotifier {
if
(
from
==
"Requesition"
)
{
Navigator
.
pop
(
context
,
res
);
}
else
if
(
from
==
"Dashboard"
)
{
print
(
"here"
);
Navigator
.
pushAndRemoveUntil
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
Accountslistdetails
(
accountID:
data
.
id
),
),
(
Route
<
dynamic
>
route
)
{
(
Route
<
dynamic
>
route
)
{
return
route
.
settings
.
arguments
==
'Financedashboard'
;
},
);
...
...
@@ -374,8 +518,7 @@ class Accountslistprovider extends ChangeNotifier {
nameError
=
"Please Enter a Name"
;
isValid
=
false
;
}
if
(
mobileController
.
text
.
trim
().
isNotEmpty
&&
mobileController
.
text
.
length
<
10
)
{
if
(
mobileController
.
text
.
trim
().
isNotEmpty
&&
mobileController
.
text
.
length
<
10
)
{
mobileError
=
"Mobile Number should be 10 digits"
;
isValid
=
false
;
}
...
...
@@ -398,22 +541,7 @@ class Accountslistprovider extends ChangeNotifier {
localityError
=
null
;
addressError
=
null
;
bool
isValid
=
true
;
// if (_selectedState == null || _selectedStateID!.isEmpty) {
// stateError = "Please select a State";
// isValid = false;
// }
// if (_selectedDistricts == null || _selectedDistrictID!.isEmpty) {
// districtError = "Please select a District";
// isValid = false;
// }
// if (_selectedSubLocations == null || _selectedSubLocID!.isEmpty) {
// localityError = "Please select a Locality";
// isValid = false;
// }
// if (addressController.text.trim().isEmpty) {
// addressError = "Please Enter an Address";
// isValid = false;
// }
// optional step — you commented it optional. Keep commented validations deactivated.
_submitClicked
=
false
;
notifyListeners
();
return
isValid
;
...
...
@@ -426,44 +554,8 @@ class Accountslistprovider extends ChangeNotifier {
bankHolderNameError
=
null
;
bankAcNumberError
=
null
;
upiError
=
null
;
gstNumberError
=
null
;
bool
isValid
=
true
;
// if (bankNameController.text
// .trim()
// .isEmpty) {
// banknameError = "Please Enter a Bank Name";
// isValid = false;
// }
//
// if (branchNameController.text
// .trim()
// .isEmpty) {
// bankBranchError = "Please Enter Branch Name";
// isValid = false;
// }
// if (bankIfscCotroller.text
// .trim()
// .isEmpty) {
// bankIFSCError = "Please Enter Bank IFSC";
// isValid = false;
// }
// if (bankHolderNameController.text
// .trim()
// .isEmpty) {
// bankHolderNameError = "Please Enter Account Holder Name";
// isValid = false;
// }
// if (bankAcNumberController.text
// .trim()
// .isEmpty) {
// bankAcNumberError = "Please Enter Bank Account Number";
// isValid = false;
// }
// if (bankUpiController.text
// .trim()
// .isEmpty) {
// upiError = "Please Enter UPI ID";
// isValid = false;
// }
_submitClicked
=
false
;
notifyListeners
();
return
isValid
;
...
...
@@ -471,30 +563,8 @@ class Accountslistprovider extends ChangeNotifier {
bool
validateStep4
()
{
bool
isValid
=
true
;
// if (contectPersonDesignationController.text
// .trim()
// .isEmpty) {
// desigantionError = "Please Enter Designation";
// isValid = false;
// }
// if (contectPersonAltMobController.text
// .trim()
// .isEmpty) {
// altMobError = "Please Enter Mobile Number";
// isValid = false;
// }
//
// }
// if (contectPersonTeleController.text.trim().isEmpty) {
// teleError= "Please Enter Telephone"; isValid = false;
// }
// if (contectPersonMailController.text.trim().isEmpty) {
// teleError= "Please Enter"; isValid = false;
// }
_submitClicked
=
false
;
notifyListeners
();
return
isValid
;
}
...
...
@@ -507,6 +577,7 @@ class Accountslistprovider extends ChangeNotifier {
localityError
=
null
;
addressError
=
null
;
banknameError
=
null
;
gstNumberError
=
null
;
bankBranchError
=
null
;
bankIFSCError
=
null
;
bankHolderNameError
=
null
;
...
...
@@ -535,94 +606,7 @@ class Accountslistprovider extends ChangeNotifier {
contactPersonError
=
"Please Enter Contact Person Name"
;
isValid
=
false
;
}
//
//
// if (!_isVisible && !hasFilledAdditionalDetails) {
// addMoreDetailsError = "Please Add More Details to Continue";
// isValid = false;
// }
// if(_isVisible) {
//
// if (_selectedState == null || _selectedStateID!.isEmpty) {
// stateError = "Please select a State";
// isValid = false;
// }
// if (_selectedDistricts == null || _selectedDistrictID!.isEmpty) {
// districtError = "Please select a District";
// isValid = false;
// }
// if (_selectedSubLocations == null || _selectedSubLocID!.isEmpty) {
// localityError = "Please select a Locality";
// isValid = false;
// }
// if (addressController.text.trim().isEmpty) {
// addressError = "Please Enter an Address";
// isValid = false;
// }
// if (bankNameController.text
// .trim()
// .isEmpty) {
// banknameError = "Please Enter a Bank Name";
// isValid = false;
// }
//
// if (branchNameController.text
// .trim()
// .isEmpty) {
// bankBranchError = "Please Enter Branch Name";
// isValid = false;
// }
// if (bankIfscCotroller.text
// .trim()
// .isEmpty) {
// bankIFSCError = "Please Enter Bank IFSC";
// isValid = false;
// }
// if (bankHolderNameController.text
// .trim()
// .isEmpty) {
// bankHolderNameError = "Please Enter Account Holder Name";
// isValid = false;
// }
// if (bankAcNumberController.text
// .trim()
// .isEmpty) {
// bankAcNumberError = "Please Enter Bank Account Number";
// isValid = false;
// }
// if (bankUpiController.text
// .trim()
// .isEmpty) {
// upiError = "Please Enter UPI ID";
// isValid = false;
// }
// if (contactPersonController.text
// .trim()
// .isEmpty) {
// contactPersonError = "Please Enter Contact Person Name";
// isValid = false;
// }
// if (contectPersonDesignationController.text
// .trim()
// .isEmpty) {
// desigantionError = "Please Enter Designation";
// isValid = false;
// }
// if (contectPersonAltMobController.text
// .trim()
// .isEmpty) {
// altMobError = "Please Enter Mobile Number";
// isValid = false;
// }
//
// }
// if (contectPersonTeleController.text.trim().isEmpty) {
// teleError= "Please Enter Telephone"; isValid = false;
// }
// if (contectPersonMailController.text.trim().isEmpty) {
// teleError= "Please Enter"; isValid = false;
// }
_submitClicked
=
false
;
notifyListeners
();
return
isValid
;
...
...
@@ -645,67 +629,64 @@ class Accountslistprovider extends ChangeNotifier {
void
updateBankName
(
String
value
)
{
banknameError
=
null
;
notifyListeners
();
}
/// simplified update - kept for compatibility if UI uses it
Future
<
void
>
updateGSTNumber
(
BuildContext
context
,
String
value
)
async
{
// We won't call the GST API here — UI flow calls validateGstNumber explicitly.
// This function simply clears previous error on typing.
gstNumberError
=
null
;
notifyListeners
();
}
void
updateBankBranch
(
String
value
)
{
bankBranchError
=
null
;
notifyListeners
();
}
void
updateIFSC
(
String
value
)
{
bankIFSCError
=
null
;
notifyListeners
();
}
void
updateHolder
(
String
value
)
{
bankHolderNameError
=
null
;
notifyListeners
();
}
void
updateNumber
(
String
value
)
{
bankAcNumberError
=
null
;
notifyListeners
();
}
void
updateUPI
(
String
value
)
{
upiError
=
null
;
notifyListeners
();
}
void
updateContactPerson
(
String
value
)
{
contactPersonError
=
null
;
notifyListeners
();
}
void
updateDesignation
(
String
value
)
{
desigantionError
=
null
;
notifyListeners
();
}
void
updateAltMobile
(
String
value
)
{
altMobError
=
null
;
notifyListeners
();
}
void
updateTeleMobile
(
String
value
)
{
teleError
=
null
;
notifyListeners
();
}
void
updateMail
(
String
value
)
{
mailError
=
null
;
notifyListeners
();
}
...
...
@@ -717,14 +698,11 @@ class Accountslistprovider extends ChangeNotifier {
notifyListeners
();
}
String
?
_errorMessage
;
String
?
get
errorMessage
=>
_errorMessage
;
// Common Account list provider
Future
<
void
>
commonAccountListAPIFunction
(
BuildContext
context
,
{
bool
append
=
false
,
})
async
{
BuildContext
context
,
{
bool
append
=
false
,
})
async
{
try
{
var
prov
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
...
...
@@ -747,19 +725,13 @@ class Accountslistprovider extends ChangeNotifier {
companyNameController
.
text
,
mobileNumberController
.
text
,
);
debugPrint
(
'empId:
${prov.empId}
, session:
${prov.session}
, pageNumber:
$_pageNum
'
,
);
debugPrint
(
'empId:
${prov.empId}
, session:
${prov.session}
, pageNumber:
$_pageNum
'
);
if
(
data
!=
null
&&
data
.
error
==
"0"
)
{
if
(
data
.
accountList
!=
null
)
{
if
(
append
)
{
// Append with deduplication
final
existingIds
=
_accountsList
.
map
((
e
)
=>
e
.
id
).
toSet
();
final
newItems
=
data
.
accountList
!
.
where
((
item
)
=>
!
existingIds
.
contains
(
item
.
id
))
.
toList
();
final
newItems
=
data
.
accountList
!.
where
((
item
)
=>
!
existingIds
.
contains
(
item
.
id
)).
toList
();
_accountsList
.
addAll
(
newItems
);
}
else
{
_accountsList
=
data
.
accountList
!;
...
...
@@ -779,7 +751,7 @@ class Accountslistprovider extends ChangeNotifier {
}
resetValues
()
{
p
rint
(
"rv"
);
if
(
kDebugMode
)
debugP
rint
(
"rv"
);
_selectedAccountType
=
null
;
_selectedState
=
null
;
_selectedDistricts
=
null
;
...
...
@@ -791,6 +763,10 @@ class Accountslistprovider extends ChangeNotifier {
_selectedSubLocID
=
null
;
_selectedSubLocValue
=
null
;
gstResponse
=
null
;
bankResponse
=
null
;
errorMessage
=
null
;
_isVisible
=
false
;
stateSearchController
.
clear
();
districtSearchController
.
clear
();
...
...
@@ -819,6 +795,7 @@ class Accountslistprovider extends ChangeNotifier {
localityError
=
null
;
addressError
=
null
;
banknameError
=
null
;
gstNumberError
=
null
;
bankBranchError
=
null
;
bankIFSCError
=
null
;
bankHolderNameError
=
null
;
...
...
@@ -836,21 +813,18 @@ class Accountslistprovider extends ChangeNotifier {
}
void
ChechkDropdownValues
()
{
if
(!
_accountTypes
.
contains
(
_selectedAccountType
)
&&
_selectedAccountType
!=
null
)
{
if
(!
_accountTypes
.
contains
(
_selectedAccountType
)
&&
_selectedAccountType
!=
null
)
{
_selectedAccountType
=
null
;
}
if
(!
_states
.
contains
(
_selectedState
)
&&
_selectedState
!=
null
)
{
_selectedStateID
=
null
;
_selectedStateValue
=
null
;
}
if
(!
_districts
.
contains
(
_selectedDistricts
)
&&
_selectedDistricts
!=
null
)
{
if
(!
_districts
.
contains
(
_selectedDistricts
)
&&
_selectedDistricts
!=
null
)
{
_selectedDistrictID
=
null
;
_selectedDistrictValue
=
null
;
}
if
(!
_subLocations
.
contains
(
_selectedSubLocations
)
&&
_selectedSubLocations
!=
null
)
{
if
(!
_subLocations
.
contains
(
_selectedSubLocations
)
&&
_selectedSubLocations
!=
null
)
{
_selectedSubLocID
=
null
;
_selectedSubLocValue
=
null
;
}
...
...
lib/Notifiers/crmProvider/LeadListProvider.dart
View file @
d2939607
// import 'package:flutter/cupertino.dart';
// import 'package:flutter/foundation.dart';
// import 'package:generp/Models/crmModels/GetSegmentOnTeamResponse.dart';
// import 'package:generp/Models/crmModels/GetSourceOnReferenceResponse.dart';
// import 'package:generp/Models/crmModels/LeadListViewResponse.dart';
// import 'package:generp/Models/crmModels/SubmitLeadListFilterResponse.dart';
// import 'package:provider/provider.dart';
//
// import '../../Models/crmModels/GetDistrictOnStateResponse.dart';
// import '../../Models/crmModels/GetSubLocOnDistrictResponse.dart';
// import '../../Models/crmModels/LeadListContactPopUpResponse.dart' show Contacts;
// import '../../services/api_calling.dart';
// import '../HomeScreenNotifier.dart';
//
// class Leadlistprovider extends ChangeNotifier {
// TextEditingController sLeadIDController = TextEditingController();
// TextEditingController mobileNumberController = TextEditingController();
// TextEditingController companyNameController = TextEditingController(
// text: "a",
// );
//
// bool _isLoading = true;
//
// List<Sources> _sourcesList = [];
// List<Teams> _teamsList = [];
// List<States> _statesList = [];
// List<Employees> _employeesList = [];
// List<References> _referencesList = [];
// List<Segments> _segmentsList = [];
// List<Districts> _districtsList = [];
// List<SubLocations> _subLocationsList = [];
// List<Contacts> _contactsList = [];
// List<LeadList> _crmLeadList = [];
// List<String?> _leadStatusList = [];
// List<String?> _openStatusList = [];
// List<String?> _alphabetList = [];
//
//
// Sources? _selectedSources;
// Teams? _selectedTeams;
// States? _selectedStates;
// Employees? _selectedEmployees;
// References? _selectedReferences;
// Segments? _selectedSegments;
// Districts? _selectedDistricts;
// SubLocations? _selectedSubLocations;
// Contacts? _selectedContacts;
// String? _selectedLeadStatus;
// String? _selectedOpenStatus;
// String? _selectedAlphabet;
//
// String? _selectedSourceId;
// String? _selectedSourceValue;
//
// String? _selectedTeamId;
// String? _selectedTeamValue;
//
// String? _selectedStateId;
// String? _selectedStateValue;
//
// String? _selectedEmployeeId;
// String? _selectedEmployeeValue;
//
// String? _selectedReferenceId;
// String? _selectedReferenceValue;
//
// String? _selectedSegmentId;
// String? _selectedSegmentValue;
//
// String? _selectedDistrictId;
// String? _selectedDistrictValue;
//
// String? _selectedSubLocationId;
// String? _selectedSubLocationValue;
//
// String? _selectedContactId;
// String? _selectedContactValue;
//
// bool get isLoading => _isLoading;
//
// List<Sources> get sourcesList => _sourcesList;
//
// List<Teams> get teamsList => _teamsList;
//
// List<States> get statesList => _statesList;
//
// List<Employees> get employeesList => _employeesList;
//
// List<References> get referencesList => _referencesList;
//
// List<Segments> get segmentsList => _segmentsList;
//
// List<Districts> get districtsList => _districtsList;
//
// List<SubLocations> get subLocationsList => _subLocationsList;
//
// List<Contacts> get contactsList => _contactsList;
//
// List<LeadList> get crmLeadList => _crmLeadList;
//
// List<String?> get leadStatusList => _leadStatusList;
//
// List<String?> get alphabetList => _alphabetList;
//
// List<String?> get openStatusList => _openStatusList;
//
// Sources? get selectedSource => _selectedSources;
//
// Teams? get selectedTeam => _selectedTeams;
//
// States? get selectedStates => _selectedStates;
//
// Employees? get selectedEmployee => _selectedEmployees;
//
// References? get selectedReference => _selectedReferences;
//
// Segments? get selectedSegment => _selectedSegments;
//
// Districts? get selectedDistricts => _selectedDistricts;
//
// SubLocations? get selectedSubLocations => _selectedSubLocations;
//
// Contacts? get selectedContacts => _selectedContacts;
//
// String? get selectedLeadStatus => _selectedLeadStatus;
//
// String? get selectedOpenStatus => _selectedOpenStatus;
//
// String? get selectedSourceId => _selectedSourceId;
//
// String? get selectedSourceValue => _selectedSourceValue;
//
// String? get selectedTeamId => _selectedTeamId;
//
// String? get selectedTeamValue => _selectedTeamValue;
//
// String? get selectedStateId => _selectedStateId;
//
// String? get selectedStateValue => _selectedStateValue;
//
// String? get selectedEmployeeId => _selectedEmployeeId;
//
// String? get selectedEmployeeValue => _selectedEmployeeValue;
//
// String? get selectedReferenceId => _selectedReferenceId;
//
// String? get selectedReferenceValue => _selectedReferenceValue;
//
// String? get selectedSegmentId => _selectedSegmentId;
//
// String? get selectedSegmentValue => _selectedSegmentValue;
//
// String? get selectedDistrictId => _selectedDistrictId;
//
// String? get selectedDistrictValue => _selectedDistrictValue;
//
// String? get selectedSubLocationId => _selectedSubLocationId;
//
// String? get selectedSubLocationValue => _selectedSubLocationValue;
//
// String? get selectedContactId => _selectedContactId;
//
// String? get selectedContactValue => _selectedContactValue;
//
// String? get selectedAlphabet => _selectedAlphabet;
//
// set isLoading(bool value) {
// _isLoading = value;
// notifyListeners();
// }
//
// set selectedAlphabet(String? value){
// _selectedAlphabet = value;
// notifyListeners();
// }
//
// set selectedSource(Sources? value) {
// _selectedSources = value;
// _selectedSourceId = value!.id!;
// _selectedSourceValue = value!.name!;
// notifyListeners();
// }
//
// set selectedTeam(Teams? value) {
// _selectedTeams = value;
// _selectedTeamId = value!.id!;
// _selectedTeamValue = value.name;
// notifyListeners();
// }
//
// set selectedStates(States? value) {
// _selectedStates = value;
// _selectedStateId = value!.id!;
// _selectedStateValue = value.name;
// notifyListeners();
// }
//
// set selectedEmployee(Employees? value) {
// _selectedEmployees = value;
// _selectedEmployeeId = value!.id!;
// _selectedEmployeeValue = value.name;
// notifyListeners();
// }
//
// set selectedReference(References? value) {
// _selectedReferences = value;
// _selectedReferenceId = value!.id!;
// _selectedReferenceValue = value.name;
// notifyListeners();
// }
//
// set selectedSegment(Segments? value) {
// _selectedSegments = value;
// _selectedSegmentId = value!.id!;
// _selectedSegmentValue = value.name;
// notifyListeners();
// }
//
// set selectedDistricts(Districts? value) {
// _selectedDistricts = value;
// _selectedDistrictId = value!.id!;
// _selectedDistrictValue = value.district;
// notifyListeners();
// }
//
// set selectedSubLocations(SubLocations? value) {
// _selectedSubLocations = value;
// _selectedSubLocationId = value!.id!;
// _selectedSubLocationValue = value.subLocality;
// notifyListeners();
// }
//
// set selectedContacts(Contacts? value) {
// _selectedContacts = value;
// _selectedContactId = value!.id!;
// _selectedContactValue = value.name;
// notifyListeners();
// }
//
// set selectedLeadStatus(String? value) {
// _selectedLeadStatus = value;
// notifyListeners();
// }
//
// set selectedOpenStatus(String? value) {
// _selectedOpenStatus = value;
// notifyListeners();
// }
//
// set selectedSourceId(String? value) {
// _selectedSourceId = value;
// notifyListeners();
// }
//
// set selectedSourceValue(String? value) {
// _selectedSourceValue = value;
// notifyListeners();
// }
//
// set selectedTeamId(String? value) {
// _selectedTeamId = value;
// notifyListeners();
// }
//
// set selectedTeamValue(String? value) {
// _selectedTeamValue = value;
// notifyListeners();
// }
//
// set selectedStateId(String? value) {
// _selectedStateId = value;
// notifyListeners();
// }
//
// set selectedStateValue(String? value) {
// _selectedStateValue = value;
// notifyListeners();
// }
//
// set selectedEmployeeId(String? value) {
// _selectedEmployeeId = value;
// notifyListeners();
// }
//
// set selectedEmployeeValue(String? value) {
// _selectedEmployeeValue = value;
// notifyListeners();
// }
//
// set selectedReferenceId(String? value) {
// _selectedReferenceId = value;
// notifyListeners();
// }
//
// set selectedReferenceValue(String? value) {
// _selectedReferenceValue = value;
// notifyListeners();
// }
//
// set selectedSegmentId(String? value) {
// _selectedSegmentId = value;
// notifyListeners();
// }
//
// set selectedSegmentValue(String? value) {
// _selectedSegmentValue = value;
// notifyListeners();
// }
//
// set selectedDistrictId(String? value) {
// _selectedDistrictId = value;
// notifyListeners();
// }
//
// set selectedDistrictValue(String? value) {
// _selectedDistrictValue = value;
// notifyListeners();
// }
//
// set selectedSubLocationId(String? value) {
// _selectedSubLocationId = value;
// notifyListeners();
// }
//
// set selectedSubLocationValue(String? value) {
// _selectedSubLocationValue = value;
// notifyListeners();
// }
//
// set selectedContactId(String? value) {
// _selectedContactId = value;
// notifyListeners();
// }
//
// set selectedContactValue(String? value) {
// _selectedContactValue = value;
// notifyListeners();
// }
//
// Future<void> crmLeadListViewAPIFunction(context, mode) async {
// try {
// var HomeProv = Provider.of<HomescreenNotifier>(context, listen: false);
// final data = await ApiCalling.crmLeadListViewAPI(
// HomeProv.empId,
// HomeProv.session,
// mode,
// );
// if (data != null) {
// print(data.error);
// if (data.error == "0") {
// // print("as");
// _leadStatusList = [
// "all",
// "Hot",
// "Warm",
// "Cold",
// "Order Gain",
// "Order Lost",
// ];
// _alphabetList = List.generate(26, (index) => String.fromCharCode(index + 65));
//
// _openStatusList = ["open", "Closed", "All"];
// _sourcesList = data.sources!;
// _teamsList = data.teams!;
// _statesList = data.states!;
// _employeesList = data.employees!;
// checkDropDownValues();
// // print(_leadStatusList);
// notifyListeners();
// }
// }
// } catch (e, s) {}
// }
//
// Future<void> crmLeadListSourceOnReferenceAPIFunction(
// context,
// mode,
// sourceID,
// ) async {
// try {
// var prov = Provider.of<HomescreenNotifier>(context, listen: false);
// final data = await ApiCalling.crmLeadListSourceOnReferenceAPI(
// prov.empId,
// prov.session,
// sourceID,
// );
// if (data != null) {
// if (data.error == "0") {
// _referencesList = data.references!;
// notifyListeners();
// }
// }
// } catch (e, s) {}
// }
//
// Future<void> crmLeadListSegmentOnTeamAPIFunction(
// context,
// mode,
// teamID,
// ) async {
// try {
// var prov = Provider.of<HomescreenNotifier>(context, listen: false);
// final data = await ApiCalling.crmLeadListSegmentOnTeamAPI(
// prov.empId,
// prov.session,
// teamID,
// );
// if (data != null) {
// if (data.error == "0") {
// _segmentsList = data.segments!;
// notifyListeners();
// }
// }
// } catch (e, s) {}
// }
//
// Future<void> crmLeadListDistrictsOnStateAPIFunction(
// context,
// mode,
// stateID,
// ) async {
// try {
// var prov = Provider.of<HomescreenNotifier>(context, listen: false);
// final data = await ApiCalling.crmDistrictsOnStateAPI(
// prov.empId,
// prov.session,
// stateID,
// );
// if (data != null) {
// if (data.error == "0") {
// _districtsList = data.districts!;
// notifyListeners();
// }
// }
// } catch (e, s) {}
// }
//
// Future<void> crmLeadListSubLocOnDistrictAPIFunction(
// context,
// mode,
// districtID,
// ) async {
// try {
// var prov = Provider.of<HomescreenNotifier>(context, listen: false);
// final data = await ApiCalling.crmSubLocOnDistrictAPI(
// prov.empId,
// prov.session,
// districtID,
// );
// if (data != null) {
// if (data.error == "0") {
// _subLocationsList = data.subLocations!;
// notifyListeners();
// }
// }
// } catch (e, s) {}
// }
//
// Future<void> crmLeadListContactPopUpAPIFunction(
// context,
// mode,
// accountID,
// ) async {
// try {
// var prov = Provider.of<HomescreenNotifier>(context, listen: false);
// final data = await ApiCalling.crmLeadListContactPopUpAPI(
// prov.empId,
// prov.session,
// accountID,
// );
// if (data != null) {
// if (data.error == "0") {
// _contactsList = data.contacts!;
// notifyListeners();
// }
// }
// } catch (e, s) {}
// }
//
// Future<void> crmLeadListAPIFunction(
// context,
// mode,
// leadStatus,
// openStatus,
// sourceID,
// referenceID,
// teamID,
// segmentID,
// alphabet
// ) async {
// try {
// _isLoading = true;
// _crmLeadList.clear();
// notifyListeners();
// var HomeProv = Provider.of<HomescreenNotifier>(context, listen: false);
// final data = await ApiCalling.crmLeadListFilterSubmitAPI(
// HomeProv.empId,
// HomeProv.session,
// mode,
// leadStatus,
// openStatus,
// mobileNumberController.text,
// companyNameController.text,
// sourceID,
// referenceID,
// teamID,
// segmentID,
// alphabet
// );
// if (data != null) {
// _isLoading = true;
// notifyListeners();
// if (data.error == "0") {
// _crmLeadList = data.leadList!;
// _isLoading = false;
// checkDropDownValues();
// notifyListeners();
// } else {
// _isLoading = false;
// notifyListeners();
// }
// } else {
// _isLoading = false;
// notifyListeners();
// }
// } catch (e, s) {
// _isLoading = false;
// notifyListeners();
// }
// }
//
// onChangedLeadId(value) {
// notifyListeners();
// }
//
// onChangedMobileNum(value) {
// notifyListeners();
// }
//
// onChangedCompanyName(value) {
// notifyListeners();
// }
//
// void resetForm() {
// _isLoading = false;
// sLeadIDController.clear();
// mobileNumberController.clear();
// companyNameController.clear();
// companyNameController.text = "a";
// _selectedEmployees = null;
// _selectedSources = null;
// _selectedReferences = null;
// _selectedSegments = null;
// _selectedTeams = null;
// _selectedDistricts = null;
// _selectedStates = null;
// _selectedSubLocations = null;
// _selectedLeadStatus = null;
// _selectedOpenStatus = null;
// _selectedEmployeeId = null;
// _selectedSourceId = null;
// _selectedReferenceId = null;
// _selectedTeamId = null;
// _selectedSegmentId = null;
// _selectedStateId = null;
// _selectedDistrictId = null;
// _selectedSubLocationId = null;
//
// _selectedEmployeeValue = null;
// _selectedSourceValue = null;
// _selectedReferenceValue = null;
// _selectedTeamValue = null;
// _selectedSegmentValue = null;
// _selectedDistrictValue = null;
// _selectedStateValue = null;
// _selectedSubLocationValue = null;
// checkDropDownValues();
// notifyListeners();
// }
//
// void checkDropDownValues() {
// if (!_employeesList.contains(_selectedEmployees) &&
// _selectedEmployees != null) {
// _selectedEmployeeId = null;
// _selectedEmployeeValue = null;
// }
// if (!_sourcesList.contains(_selectedSources) && _selectedSources != null) {
// _selectedSourceId = null;
// _selectedSourceValue = null;
// }
// if (!_referencesList.contains(_selectedReferences) &&
// _selectedReferences != null) {
// _selectedReferenceId = null;
// _selectedReferenceValue = null;
// }
// if (!_segmentsList.contains(_selectedSegments) &&
// _selectedSegments != null) {
// _selectedTeamId = null;
// _selectedTeamValue = null;
// }
// if (!_teamsList.contains(_selectedTeams) && _selectedTeams != null) {
// _selectedSegmentId = null;
// _selectedSegmentValue = null;
// }
// if (!_districtsList.contains(_selectedDistricts) &&
// _selectedDistricts != null) {
// _selectedDistrictId = null;
// _selectedDistrictValue = null;
// }
// if (!_statesList.contains(_selectedStates) && _selectedStates != null) {
// _selectedStateId = null;
// _selectedStateValue = null;
// }
// if (!_subLocationsList.contains(_selectedSubLocations) &&
// _selectedSubLocations != null) {
// _selectedSubLocationId = null;
// _selectedSubLocationValue = null;
// }
// notifyListeners();
// }
// }
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:generp/Models/crmModels/GetSegmentOnTeamResponse.dart'
;
...
...
@@ -697,89 +76,49 @@ class Leadlistprovider extends ChangeNotifier {
bool
get
isLoading
=>
_isLoading
;
List
<
Sources
>
get
sourcesList
=>
_sourcesList
;
List
<
Teams
>
get
teamsList
=>
_teamsList
;
List
<
States
>
get
statesList
=>
_statesList
;
List
<
Employees
>
get
employeesList
=>
_employeesList
;
List
<
References
>
get
referencesList
=>
_referencesList
;
List
<
Segments
>
get
segmentsList
=>
_segmentsList
;
List
<
Districts
>
get
districtsList
=>
_districtsList
;
List
<
SubLocations
>
get
subLocationsList
=>
_subLocationsList
;
List
<
Contacts
>
get
contactsList
=>
_contactsList
;
List
<
LeadList
>
get
crmLeadList
=>
_crmLeadList
;
List
<
String
?>
get
leadStatusList
=>
_leadStatusList
;
List
<
String
?>
get
alphabetList
=>
_alphabetList
;
List
<
String
?>
get
openStatusList
=>
_openStatusList
;
Sources
?
get
selectedSource
=>
_selectedSources
;
Teams
?
get
selectedTeam
=>
_selectedTeams
;
States
?
get
selectedStates
=>
_selectedStates
;
Employees
?
get
selectedEmployee
=>
_selectedEmployees
;
References
?
get
selectedReference
=>
_selectedReferences
;
Segments
?
get
selectedSegment
=>
_selectedSegments
;
Districts
?
get
selectedDistricts
=>
_selectedDistricts
;
SubLocations
?
get
selectedSubLocations
=>
_selectedSubLocations
;
Contacts
?
get
selectedContacts
=>
_selectedContacts
;
String
?
get
selectedLeadStatus
=>
_selectedLeadStatus
;
String
?
get
selectedOpenStatus
=>
_selectedOpenStatus
;
String
?
get
selectedSourceId
=>
_selectedSourceId
;
String
?
get
selectedSourceValue
=>
_selectedSourceValue
;
String
?
get
selectedTeamId
=>
_selectedTeamId
;
String
?
get
selectedTeamValue
=>
_selectedTeamValue
;
String
?
get
selectedStateId
=>
_selectedStateId
;
String
?
get
selectedStateValue
=>
_selectedStateValue
;
String
?
get
selectedEmployeeId
=>
_selectedEmployeeId
;
String
?
get
selectedEmployeeValue
=>
_selectedEmployeeValue
;
String
?
get
selectedReferenceId
=>
_selectedReferenceId
;
String
?
get
selectedReferenceValue
=>
_selectedReferenceValue
;
String
?
get
selectedSegmentId
=>
_selectedSegmentId
;
String
?
get
selectedSegmentValue
=>
_selectedSegmentValue
;
String
?
get
selectedDistrictId
=>
_selectedDistrictId
;
String
?
get
selectedDistrictValue
=>
_selectedDistrictValue
;
String
?
get
selectedSubLocationId
=>
_selectedSubLocationId
;
String
?
get
selectedSubLocationValue
=>
_selectedSubLocationValue
;
String
?
get
selectedContactId
=>
_selectedContactId
;
String
?
get
selectedContactValue
=>
_selectedContactValue
;
String
?
get
selectedAlphabet
=>
_selectedAlphabet
;
set
isLoading
(
bool
value
)
{
...
...
@@ -796,8 +135,9 @@ class Leadlistprovider extends ChangeNotifier {
_selectedSources
=
value
;
_selectedSourceId
=
value
?.
id
;
_selectedSourceValue
=
value
?.
name
;
print
(
'Setting selectedSource:
$value
, id:
$_selectedSourceId
, name:
$_selectedSourceValue
'
,
// debug - helpful when debugging filter problems
debugPrint
(
'Setting selectedSource: id=
$_selectedSourceId
, name=
$_selectedSourceValue
'
,
);
notifyListeners
();
}
...
...
@@ -958,6 +298,9 @@ class Leadlistprovider extends ChangeNotifier {
notifyListeners
();
}
// ---------- fetches & rehydrate selection logic ----------
// view API that returns many filter lists
Future
<
void
>
crmLeadListViewAPIFunction
(
context
,
mode
)
async
{
try
{
var
HomeProv
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
...
...
@@ -967,8 +310,8 @@ class Leadlistprovider extends ChangeNotifier {
mode
,
);
if
(
data
!=
null
)
{
p
rint
(
'crmLeadListViewAPI error:
${data.error}
, sources:
${data.sources}
'
,
debugP
rint
(
'crmLeadListViewAPI error:
${data.error}
, sources
length
:
${data.sources
?.length ?? 0
}
'
,
);
if
(
data
.
error
==
"0"
)
{
_leadStatusList
=
[
...
...
@@ -981,45 +324,69 @@ class Leadlistprovider extends ChangeNotifier {
];
_alphabetList
=
List
.
generate
(
26
,
(
index
)
=>
String
.
fromCharCode
(
index
+
65
),
(
index
)
=>
String
.
fromCharCode
(
index
+
65
),
);
_openStatusList
=
[
"open"
,
"Closed"
,
"All"
];
_sourcesList
=
data
.
sources
?.
where
((
source
)
=>
source
.
id
!=
null
&&
source
.
name
!=
null
)
.
toList
()
??
_sourcesList
=
data
.
sources
?.
where
((
source
)
=>
source
.
id
!=
null
&&
source
.
name
!=
null
)
.
toList
()
??
[];
_teamsList
=
data
.
teams
?.
where
((
team
)
=>
team
.
id
!=
null
&&
team
.
name
!=
null
)
.
toList
()
??
_teamsList
=
data
.
teams
?.
where
((
team
)
=>
team
.
id
!=
null
&&
team
.
name
!=
null
)
.
toList
()
??
[];
_statesList
=
data
.
states
?.
where
((
state
)
=>
state
.
id
!=
null
&&
state
.
name
!=
null
)
.
toList
()
??
_statesList
=
data
.
states
?.
where
((
state
)
=>
state
.
id
!=
null
&&
state
.
name
!=
null
)
.
toList
()
??
[];
_employeesList
=
data
.
employees
?.
where
(
(
employee
)
=>
employee
.
id
!=
null
&&
employee
.
name
!=
null
,
)
.
toList
()
??
_employeesList
=
data
.
employees
?.
where
(
(
employee
)
=>
employee
.
id
!=
null
&&
employee
.
name
!=
null
,
)
.
toList
()
??
[];
// --- rehydrate previously selected items by matching IDs ---
_rehydrateSelectionsAfterViewLoad
();
checkDropDownValues
();
// ensure loading flag set off
_isLoading
=
false
;
notifyListeners
();
}
else
{
// clear lists on non-zero error to avoid stale options
_sourcesList
.
clear
();
_teamsList
.
clear
();
_statesList
.
clear
();
_employeesList
.
clear
();
_isLoading
=
false
;
notifyListeners
();
}
}
else
{
// null response -> clear lists
_sourcesList
.
clear
();
_teamsList
.
clear
();
_statesList
.
clear
();
_employeesList
.
clear
();
_isLoading
=
false
;
notifyListeners
();
}
}
catch
(
e
,
s
)
{
print
(
'crmLeadListViewAPI error:
$e
, stack:
$s
'
);
debugPrint
(
'crmLeadListViewAPI error:
$e
, stack:
$s
'
);
_sourcesList
.
clear
();
_teamsList
.
clear
();
_statesList
.
clear
();
_employeesList
.
clear
();
_isLoading
=
false
;
notifyListeners
();
}
}
Future
<
void
>
crmLeadListSourceOnReferenceAPIFunction
(
context
,
mode
,
String
?
sourceID
,
)
async
{
context
,
mode
,
String
?
sourceID
,
)
async
{
try
{
var
prov
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
final
data
=
await
ApiCalling
.
crmLeadListSourceOnReferenceAPI
(
...
...
@@ -1029,27 +396,51 @@ class Leadlistprovider extends ChangeNotifier {
);
if
(
data
!=
null
)
{
if
(
data
.
error
==
"0"
)
{
_referencesList
=
data
.
references
?.
where
((
ref
)
=>
ref
.
id
!=
null
&&
ref
.
name
!=
null
)
.
toList
()
??
_referencesList
=
data
.
references
?.
where
((
ref
)
=>
ref
.
id
!=
null
&&
ref
.
name
!=
null
)
.
toList
()
??
[];
// rehydrate selectedReference if id exists
if
(
_selectedReferenceId
!=
null
)
{
final
found
=
_referencesList
.
firstWhere
(
(
r
)
=>
r
.
id
==
_selectedReferenceId
,
orElse:
()
=>
References
(
id:
_selectedReferenceId
,
name:
_selectedReferenceValue
),
);
// if found in list use that instance else leave existing selectedReference null/unchanged
if
(
_referencesList
.
any
((
r
)
=>
r
.
id
==
_selectedReferenceId
))
{
_selectedReferences
=
found
;
}
else
{
// if API returned different list, keep selectedReference null to avoid mismatch
_selectedReferences
=
null
;
_selectedReferenceId
=
null
;
_selectedReferenceValue
=
null
;
}
}
notifyListeners
();
}
else
{
_referencesList
.
clear
();
_selectedReferences
=
null
;
_selectedReferenceId
=
null
;
_selectedReferenceValue
=
null
;
notifyListeners
();
}
}
else
{
_referencesList
.
clear
();
_selectedReferences
=
null
;
_selectedReferenceId
=
null
;
_selectedReferenceValue
=
null
;
notifyListeners
();
}
}
catch
(
e
,
s
)
{
p
rint
(
'crmLeadListSourceOnReferenceAPI error:
$e
, stack:
$s
'
);
debugP
rint
(
'crmLeadListSourceOnReferenceAPI error:
$e
, stack:
$s
'
);
}
}
Future
<
void
>
crmLeadListSegmentOnTeamAPIFunction
(
context
,
mode
,
String
?
teamID
,
)
async
{
context
,
mode
,
String
?
teamID
,
)
async
{
try
{
var
prov
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
final
data
=
await
ApiCalling
.
crmLeadListSegmentOnTeamAPI
(
...
...
@@ -1059,29 +450,51 @@ class Leadlistprovider extends ChangeNotifier {
);
if
(
data
!=
null
)
{
if
(
data
.
error
==
"0"
)
{
_segmentsList
=
data
.
segments
?.
where
(
(
segment
)
=>
segment
.
id
!=
null
&&
segment
.
name
!=
null
,
)
.
toList
()
??
_segmentsList
=
data
.
segments
?.
where
(
(
segment
)
=>
segment
.
id
!=
null
&&
segment
.
name
!=
null
,
)
.
toList
()
??
[];
// rehydrate selectedSegment if id exists
if
(
_selectedSegmentId
!=
null
)
{
final
found
=
_segmentsList
.
firstWhere
(
(
s
)
=>
s
.
id
==
_selectedSegmentId
,
orElse:
()
=>
Segments
(
id:
_selectedSegmentId
,
name:
_selectedSegmentValue
),
);
if
(
_segmentsList
.
any
((
s
)
=>
s
.
id
==
_selectedSegmentId
))
{
_selectedSegments
=
found
;
}
else
{
_selectedSegments
=
null
;
_selectedSegmentId
=
null
;
_selectedSegmentValue
=
null
;
}
}
notifyListeners
();
}
else
{
_segmentsList
.
clear
();
_selectedSegments
=
null
;
_selectedSegmentId
=
null
;
_selectedSegmentValue
=
null
;
notifyListeners
();
}
}
else
{
_segmentsList
.
clear
();
_selectedSegments
=
null
;
_selectedSegmentId
=
null
;
_selectedSegmentValue
=
null
;
notifyListeners
();
}
}
catch
(
e
,
s
)
{
p
rint
(
'crmLeadListSegmentOnTeamAPI error:
$e
, stack:
$s
'
);
debugP
rint
(
'crmLeadListSegmentOnTeamAPI error:
$e
, stack:
$s
'
);
}
}
Future
<
void
>
crmLeadListDistrictsOnStateAPIFunction
(
context
,
mode
,
String
?
stateID
,
)
async
{
context
,
mode
,
String
?
stateID
,
)
async
{
try
{
var
prov
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
final
data
=
await
ApiCalling
.
crmDistrictsOnStateAPI
(
...
...
@@ -1091,30 +504,52 @@ class Leadlistprovider extends ChangeNotifier {
);
if
(
data
!=
null
)
{
if
(
data
.
error
==
"0"
)
{
_districtsList
=
data
.
districts
?.
where
(
(
district
)
=>
district
.
id
!=
null
&&
district
.
district
!=
null
,
)
.
toList
()
??
_districtsList
=
data
.
districts
?.
where
(
(
district
)
=>
district
.
id
!=
null
&&
district
.
district
!=
null
,
)
.
toList
()
??
[];
// rehydrate selection
if
(
_selectedDistrictId
!=
null
)
{
final
found
=
_districtsList
.
firstWhere
(
(
d
)
=>
d
.
id
==
_selectedDistrictId
,
orElse:
()
=>
Districts
(
id:
_selectedDistrictId
,
district:
_selectedDistrictValue
),
);
if
(
_districtsList
.
any
((
d
)
=>
d
.
id
==
_selectedDistrictId
))
{
_selectedDistricts
=
found
;
}
else
{
_selectedDistricts
=
null
;
_selectedDistrictId
=
null
;
_selectedDistrictValue
=
null
;
}
}
notifyListeners
();
}
else
{
_districtsList
.
clear
();
_selectedDistricts
=
null
;
_selectedDistrictId
=
null
;
_selectedDistrictValue
=
null
;
notifyListeners
();
}
}
else
{
_districtsList
.
clear
();
_selectedDistricts
=
null
;
_selectedDistrictId
=
null
;
_selectedDistrictValue
=
null
;
notifyListeners
();
}
}
catch
(
e
,
s
)
{
p
rint
(
'crmLeadListDistrictsOnStateAPI error:
$e
, stack:
$s
'
);
debugP
rint
(
'crmLeadListDistrictsOnStateAPI error:
$e
, stack:
$s
'
);
}
}
Future
<
void
>
crmLeadListSubLocOnDistrictAPIFunction
(
context
,
mode
,
String
?
districtID
,
)
async
{
context
,
mode
,
String
?
districtID
,
)
async
{
try
{
var
prov
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
final
data
=
await
ApiCalling
.
crmSubLocOnDistrictAPI
(
...
...
@@ -1124,29 +559,51 @@ class Leadlistprovider extends ChangeNotifier {
);
if
(
data
!=
null
)
{
if
(
data
.
error
==
"0"
)
{
_subLocationsList
=
data
.
subLocations
?.
where
(
(
subLoc
)
=>
subLoc
.
id
!=
null
&&
subLoc
.
subLocality
!=
null
,
)
.
toList
()
??
_subLocationsList
=
data
.
subLocations
?.
where
(
(
subLoc
)
=>
subLoc
.
id
!=
null
&&
subLoc
.
subLocality
!=
null
,
)
.
toList
()
??
[];
// rehydrate selection
if
(
_selectedSubLocationId
!=
null
)
{
final
found
=
_subLocationsList
.
firstWhere
(
(
s
)
=>
s
.
id
==
_selectedSubLocationId
,
orElse:
()
=>
SubLocations
(
id:
_selectedSubLocationId
,
subLocality:
_selectedSubLocationValue
),
);
if
(
_subLocationsList
.
any
((
s
)
=>
s
.
id
==
_selectedSubLocationId
))
{
_selectedSubLocations
=
found
;
}
else
{
_selectedSubLocations
=
null
;
_selectedSubLocationId
=
null
;
_selectedSubLocationValue
=
null
;
}
}
notifyListeners
();
}
else
{
_subLocationsList
.
clear
();
_selectedSubLocations
=
null
;
_selectedSubLocationId
=
null
;
_selectedSubLocationValue
=
null
;
notifyListeners
();
}
}
else
{
_subLocationsList
.
clear
();
_selectedSubLocations
=
null
;
_selectedSubLocationId
=
null
;
_selectedSubLocationValue
=
null
;
notifyListeners
();
}
}
catch
(
e
,
s
)
{
p
rint
(
'crmLeadListSubLocOnDistrictAPI error:
$e
, stack:
$s
'
);
debugP
rint
(
'crmLeadListSubLocOnDistrictAPI error:
$e
, stack:
$s
'
);
}
}
Future
<
void
>
crmLeadListContactPopUpAPIFunction
(
context
,
mode
,
String
?
accountID
,
)
async
{
context
,
mode
,
String
?
accountID
,
)
async
{
try
{
var
prov
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
final
data
=
await
ApiCalling
.
crmLeadListContactPopUpAPI
(
...
...
@@ -1156,21 +613,23 @@ class Leadlistprovider extends ChangeNotifier {
);
if
(
data
!=
null
)
{
if
(
data
.
error
==
"0"
)
{
_contactsList
=
data
.
contacts
?.
where
(
(
contact
)
=>
contact
.
id
!=
null
&&
contact
.
name
!=
null
,
)
.
toList
()
??
_contactsList
=
data
.
contacts
?.
where
(
(
contact
)
=>
contact
.
id
!=
null
&&
contact
.
name
!=
null
,
)
.
toList
()
??
[];
notifyListeners
();
}
else
{
_contactsList
.
clear
();
notifyListeners
();
}
}
else
{
_contactsList
.
clear
();
notifyListeners
();
}
}
catch
(
e
,
s
)
{
p
rint
(
'crmLeadListContactPopUpAPI error:
$e
, stack:
$s
'
);
debugP
rint
(
'crmLeadListContactPopUpAPI error:
$e
, stack:
$s
'
);
}
}
...
...
@@ -1193,17 +652,17 @@ class Leadlistprovider extends ChangeNotifier {
}
Future
<
void
>
crmLeadListAPIFunction
(
BuildContext
context
,
String
?
mode
,
String
?
leadStatus
,
String
?
openStatus
,
String
?
sourceID
,
String
?
referenceID
,
String
?
teamID
,
String
?
segmentID
,
String
?
alphabet
,
{
bool
append
=
false
,
})
async
{
BuildContext
context
,
String
?
mode
,
String
?
leadStatus
,
String
?
openStatus
,
String
?
sourceID
,
String
?
referenceID
,
String
?
teamID
,
String
?
segmentID
,
String
?
alphabet
,
{
bool
append
=
false
,
})
async
{
try
{
var
HomeProv
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
...
...
@@ -1235,27 +694,25 @@ class Leadlistprovider extends ChangeNotifier {
'empId:
${HomeProv.empId}
, session:
${HomeProv.session}
, pageNumber:
$_currentPage
'
,
);
if
(
data
!=
null
){
if
(
data
.
error
==
"0"
)
{
print
(
"Lead List Length
${data.leadList!.length}
"
);
if
(
data
!=
null
)
{
if
(
data
.
error
==
"0"
)
{
debugPrint
(
"Lead List Length
${data.leadList?.length ?? 0}
"
);
if
(
append
)
{
_crmLeadList
.
addAll
(
data
.
leadList
??
[]);
}
else
{
_crmLeadList
=
data
.
leadList
??
[];
}
if
(
data
.
leadList
!
.
length
<
15
)
{
if
(
(
data
.
leadList
?
.
length
??
0
)
<
15
)
{
_hasMoreData
=
false
;
// no more pages
}
}
else
if
(
data
.
error
==
"1"
)
{
}
else
if
(
data
.
error
==
"1"
)
{
if
(!
append
)
_errorMessage
=
"No leads found!"
;
_hasMoreData
=
false
;
}
}
else
{
}
else
{
_hasMoreData
=
false
;
}
}
catch
(
e
)
{
_errorMessage
=
"Error:
$e
"
;
}
...
...
@@ -1267,16 +724,16 @@ class Leadlistprovider extends ChangeNotifier {
/// Load next page
Future
<
void
>
loadMore
(
BuildContext
context
,
String
?
mode
,
String
?
leadStatus
,
String
?
openStatus
,
String
?
sourceID
,
String
?
referenceID
,
String
?
teamID
,
String
?
segmentID
,
String
?
alphabet
,
)
async
{
BuildContext
context
,
String
?
mode
,
String
?
leadStatus
,
String
?
openStatus
,
String
?
sourceID
,
String
?
referenceID
,
String
?
teamID
,
String
?
segmentID
,
String
?
alphabet
,
)
async
{
if
(
_isLoadingMore
||
!
_hasMoreData
)
return
;
_currentPage
++;
await
crmLeadListAPIFunction
(
...
...
@@ -1310,7 +767,6 @@ class Leadlistprovider extends ChangeNotifier {
sLeadIDController
.
clear
();
mobileNumberController
.
clear
();
companyNameController
.
clear
();
companyNameController
.
clear
();
_selectedEmployees
=
null
;
_selectedSources
=
null
;
_selectedReferences
=
null
;
...
...
@@ -1390,4 +846,60 @@ class Leadlistprovider extends ChangeNotifier {
}
notifyListeners
();
}
// --- helper to rehydrate selected instances by their IDs after lists are loaded ---
// --- helper to rehydrate selected instances by their IDs after lists are loaded ---
void
_rehydrateSelectionsAfterViewLoad
()
{
// sources
if
(
_selectedSourceId
!=
null
)
{
final
idx
=
_sourcesList
.
indexWhere
((
s
)
=>
s
.
id
==
_selectedSourceId
);
if
(
idx
!=
-
1
)
{
_selectedSources
=
_sourcesList
[
idx
];
}
else
{
_selectedSources
=
null
;
_selectedSourceId
=
null
;
_selectedSourceValue
=
null
;
}
}
// teams
if
(
_selectedTeamId
!=
null
)
{
final
idx
=
_teamsList
.
indexWhere
((
t
)
=>
t
.
id
==
_selectedTeamId
);
if
(
idx
!=
-
1
)
{
_selectedTeams
=
_teamsList
[
idx
];
}
else
{
_selectedTeams
=
null
;
_selectedTeamId
=
null
;
_selectedTeamValue
=
null
;
}
}
// employees
if
(
_selectedEmployeeId
!=
null
)
{
final
idx
=
_employeesList
.
indexWhere
((
e
)
=>
e
.
id
==
_selectedEmployeeId
);
if
(
idx
!=
-
1
)
{
_selectedEmployees
=
_employeesList
[
idx
];
}
else
{
_selectedEmployees
=
null
;
_selectedEmployeeId
=
null
;
_selectedEmployeeValue
=
null
;
}
}
// states
if
(
_selectedStateId
!=
null
)
{
final
idx
=
_statesList
.
indexWhere
((
st
)
=>
st
.
id
==
_selectedStateId
);
if
(
idx
!=
-
1
)
{
_selectedStates
=
_statesList
[
idx
];
}
else
{
_selectedStates
=
null
;
_selectedStateId
=
null
;
_selectedStateValue
=
null
;
}
}
// note: I only handled the lists you used earlier; if you need to rehydrate
// other selections (district/segment/subLocation/reference etc.) add same pattern.
}
}
lib/Notifiers/crmProvider/addNewLeadsandProspectsProvider.dart
View file @
d2939607
...
...
@@ -757,14 +757,17 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
notifyListeners
();
}
onChangeCompanyName
(
value
)
{
companynameError
=
""
;
// onChangeCompanyName(value) {
// companynameError = "";
// notifyListeners();
// }
onChangeContactPersonName
(
value
)
{
nameError
=
""
;
notifyListeners
();
}
onChangeAlternatemobile
(
value
)
{
AlternatemobileError
=
""
;
notifyListeners
();
...
...
@@ -775,22 +778,22 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
notifyListeners
();
}
Future
<
void
>
onChangeCo
ntactPerson
Name
(
BuildContext
context
,
String
value
)
async
{
nameError
=
""
;
Future
<
void
>
onChangeCo
mpany
Name
(
BuildContext
context
,
String
value
)
async
{
company
nameError
=
""
;
if
(
value
.
isEmpty
)
{
nameError
=
"Name cannot be empty"
;
company
nameError
=
"
Company
Name cannot be empty"
;
}
else
if
(
value
.
length
<
3
)
{
nameError
=
"Name must be at least 3 characters"
;
company
nameError
=
"
Company
Name must be at least 3 characters"
;
}
else
{
final
exists
=
await
checkAccountFieldExistence
(
context
,
type:
"
name
"
,
type:
"
company
"
,
typeValue:
value
,
);
if
(!
exists
)
{
nameError
=
"Name already exists"
;
company
nameError
=
"
Company
Name already exists"
;
}
else
{
nameError
=
null
;
company
nameError
=
null
;
}
}
notifyListeners
();
...
...
@@ -997,7 +1000,7 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
isValid
=
false
;
}
if
(
nameError
==
"Name already exists"
){
if
(
company
nameError
==
"
Company
Name already exists"
){
isValid
=
false
;
}
...
...
lib/Notifiers/crmProvider/editCrmAccountDetailsProvider.dart
View file @
d2939607
...
...
@@ -34,16 +34,26 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
List
<
Teams
>
get
teamsList
=>
_teamsList
;
List
<
Segments
>
get
segmentsList
=>
_segmentsList
;
Teams
?
get
selectedTeams
=>
_selectedTeams
;
Segments
?
get
selectedSegments
=>
_selectedSegments
;
// IMPORTANT: Return null if the selected object is not present in the current list.
// This prevents DropdownButton2 from receiving a value that is not part of items.
Teams
?
get
selectedTeams
{
if
(
_selectedTeams
==
null
)
return
null
;
if
(!
_teamsList
.
contains
(
_selectedTeams
))
return
null
;
return
_selectedTeams
;
}
Segments
?
get
selectedSegments
{
if
(
_selectedSegments
==
null
)
return
null
;
if
(!
_segmentsList
.
contains
(
_selectedSegments
))
return
null
;
return
_selectedSegments
;
}
AccountDetails
get
accountsDetails
=>
_accountDetails
;
String
?
get
selectedTeamId
=>
_selectedTeamId
;
String
?
get
selectedTeamValue
=>
_selectedTeamValue
;
String
?
get
selectedSegmentId
=>
_selectedSegmentId
;
String
?
get
selectedSegmentValue
=>
_selectedSegmentValue
;
set
isLoading
(
bool
value
)
{
...
...
@@ -68,15 +78,25 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
set
selectedTeams
(
Teams
?
value
)
{
_selectedTeams
=
value
;
_selectedTeamId
=
value
!.
id
!;
_selectedTeamValue
=
value
.
name
;
if
(
value
!=
null
)
{
_selectedTeamId
=
value
.
id
;
_selectedTeamValue
=
value
.
name
;
}
else
{
_selectedTeamId
=
null
;
_selectedTeamValue
=
null
;
}
notifyListeners
();
}
set
selectedSegments
(
Segments
?
value
)
{
_selectedSegments
=
value
;
_selectedSegmentId
=
value
!.
id
!;
_selectedSegmentValue
=
value
.
name
;
if
(
value
!=
null
)
{
_selectedSegmentId
=
value
.
id
;
_selectedSegmentValue
=
value
.
name
;
}
else
{
_selectedSegmentId
=
null
;
_selectedSegmentValue
=
null
;
}
notifyListeners
();
}
...
...
@@ -101,10 +121,10 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
}
Future
<
void
>
crmLeadDetailsEditAccountAPIFunction
(
context
,
leadID
,
mode
,
)
async
{
context
,
leadID
,
mode
,
)
async
{
try
{
var
HomeProv
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
final
data
=
await
ApiCalling
.
crmLeadDetailsEditAccountViewAPI
(
...
...
@@ -117,8 +137,21 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
notifyListeners
();
if
(
data
!=
null
)
{
if
(
data
.
error
==
"0"
)
{
_teamsList
=
data
.
teams
!;
_accountDetails
=
data
.
accountDetails
!;
_teamsList
=
data
.
teams
??
[];
_accountDetails
=
data
.
accountDetails
??
AccountDetails
();
// If current selected team/segment are not in the new lists, clear them
if
(
_selectedTeams
!=
null
&&
!
_teamsList
.
contains
(
_selectedTeams
))
{
_selectedTeams
=
null
;
_selectedTeamId
=
null
;
_selectedTeamValue
=
null
;
}
if
(
_selectedSegments
!=
null
&&
!
_segmentsList
.
contains
(
_selectedSegments
))
{
_selectedSegments
=
null
;
_selectedSegmentId
=
null
;
_selectedSegmentValue
=
null
;
}
_isLoading
=
false
;
notifyListeners
();
}
else
{
...
...
@@ -136,10 +169,10 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
}
Future
<
void
>
crmLeadListSegmentOnTeamAPIFunction
(
context
,
mode
,
teamID
,
)
async
{
context
,
mode
,
teamID
,
)
async
{
try
{
var
prov
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
final
data
=
await
ApiCalling
.
crmLeadListSegmentOnTeamAPI
(
...
...
@@ -149,23 +182,43 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
);
if
(
data
!=
null
)
{
if
(
data
.
error
==
"0"
)
{
_segmentsList
=
data
.
segments
!;
_segmentsList
=
data
.
segments
??
[];
// clear selectedSegments if it's not part of new list
if
(
_selectedSegments
!=
null
&&
!
_segmentsList
.
contains
(
_selectedSegments
))
{
_selectedSegments
=
null
;
_selectedSegmentId
=
null
;
_selectedSegmentValue
=
null
;
}
notifyListeners
();
}
}
}
catch
(
e
)
{}
}
// Fixed: check string emptiness properly (IDs are strings in your model)
bool
get
isFormValid
{
final
nameOk
=
editCompanyNameController
.
text
.
trim
().
isNotEmpty
;
final
teamOk
=
_selectedTeamId
!=
null
&&
_selectedTeamId
!.
isNotEmpty
;
final
segmentOk
=
_selectedSegmentId
!=
null
&&
_selectedSegmentId
!.
isNotEmpty
;
return
nameOk
&&
teamOk
&&
segmentOk
;
}
Future
<
void
>
crmLeadDetailsEditAccountSubmitAPIFunction
(
context
,
accountId
,
segmentId
,
teamId
,
)
async
{
context
,
accountId
,
segmentId
,
teamId
,
)
async
{
try
{
if
(!
validateForm
(
context
))
{
return
;
}
_isLoading
=
true
;
notifyListeners
();
var
HomeProv
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
final
data
=
await
ApiCalling
.
crmLeadDetailsEditAccountSubmitAPI
(
HomeProv
.
empId
,
...
...
@@ -175,8 +228,7 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
teamId
,
editCompanyNameController
.
text
,
);
_isLoading
=
true
;
notifyListeners
();
if
(
data
!=
null
)
{
if
(
data
.
error
==
"0"
)
{
Navigator
.
pop
(
context
,
true
);
...
...
@@ -200,19 +252,24 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
bool
validateForm
(
BuildContext
context
)
{
// Reset all errors
_companyNameError
=
null
;
_selectedTeamError
=
null
;
_selectedSegmentError
=
null
;
bool
isValid
=
true
;
if
(
_selectedTeams
==
null
||
_selectedTeamId
!.
isEmpty
)
{
_selectedTeamError
=
"Please select an account"
;
// Team checks
if
(
_selectedTeams
==
null
||
_selectedTeamId
==
null
||
_selectedTeamId
!.
isEmpty
)
{
_selectedTeamError
=
"Please select a team"
;
isValid
=
false
;
}
if
(
_selectedSegments
==
null
||
_selectedSegmentId
!.
isEmpty
)
{
_selectedSegmentError
=
"Please select an account"
;
// Segment checks
if
(
_selectedSegments
==
null
||
_selectedSegmentId
==
null
||
_selectedSegmentId
!.
isEmpty
)
{
_selectedSegmentError
=
"Please select a segment"
;
isValid
=
false
;
}
// Company name check
if
(
editCompanyNameController
.
text
.
trim
().
isEmpty
)
{
_companyNameError
=
"Please enter Company name"
;
isValid
=
false
;
...
...
@@ -223,7 +280,12 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
}
onChangedCompanyName
(
value
)
{
_companyNameError
=
""
;
// Clear the company name error when user types
if
(
value
!=
null
&&
value
.
toString
().
trim
().
isNotEmpty
)
{
_companyNameError
=
null
;
}
else
{
_companyNameError
=
"Name is required"
;
}
notifyListeners
();
}
...
...
@@ -236,11 +298,13 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
_selectedSegmentId
=
null
;
_selectedTeamValue
=
null
;
_selectedSegmentValue
=
null
;
_selectedTeamError
=
null
;
_selectedSegmentError
=
null
;
_companyNameError
=
null
;
}
void
checkDropDownValues
()
{
if
(!
_segmentsList
.
contains
(
_selectedSegments
)
&&
_selectedSegments
!=
null
)
{
if
(!
_segmentsList
.
contains
(
_selectedSegments
)
&&
_selectedSegments
!=
null
)
{
_selectedTeamId
=
null
;
_selectedTeamValue
=
null
;
}
...
...
lib/main.dart
View file @
d2939607
...
...
@@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
import
'package:flutter_local_notifications/flutter_local_notifications.dart'
;
import
'package:flutter_ringtone_player/flutter_ringtone_player.dart'
;
import
'package:generp/Models/hrmModels/leaveApplicationLIstResponse.dart'
;
import
'package:generp/Notifiers/QrProvider.dart'
;
import
'package:generp/Utils/app_colors.dart'
;
import
'package:generp/screens/AttendanceScreen.dart'
;
import
'package:generp/screens/HomeScreen.dart'
;
...
...
@@ -426,6 +427,7 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider
(
create:
(
_
)
=>
AdvanceListProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
CasualLeaveHistoryProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
ContactProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
QrProvider
()),
],
child:
Builder
(
...
...
lib/screens/commom/addCommonPayment.dart
View file @
d2939607
// addcommonpayment.dart
import
'dart:io'
;
import
'package:connectivity_plus/connectivity_plus.dart'
;
...
...
@@ -6,6 +7,7 @@ import 'package:flutter/material.dart';
import
'package:flutter/services.dart'
;
import
'package:flutter_svg/svg.dart'
;
import
'package:generp/Notifiers/commonProvider/accountsListProvider.dart'
;
import
'package:generp/Notifiers/HomeScreenNotifier.dart'
;
import
'package:generp/Utils/ShakeWidget.dart'
;
import
'package:generp/Utils/app_colors.dart'
;
import
'package:generp/Utils/commonServices.dart'
;
...
...
@@ -35,7 +37,6 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
@override
void
initState
()
{
// TODO: implement initState
super
.
initState
();
_connectivity
.
initialise
();
_connectivity
.
myStream
.
listen
((
source
)
{
...
...
@@ -47,48 +48,183 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
});
}
void
_nextStep
()
{
if
(
_formKey
.
currentState
!.
validate
())
{
if
(
_currentStep
<
3
)
{
setState
(()
{
_currentStep
+=
1
;
});
}
else
{
// Submit form data
_submitForm
();
}
@override
void
dispose
()
{
// correctly dispose focus nodes
for
(
final
fn
in
focusNodes
)
{
try
{
fn
.
dispose
();
}
catch
(
_
)
{}
}
_connectivity
.
disposeStream
();
super
.
dispose
();
}
void
_previousStep
()
{
Future
<
bool
>
onBackPressed
(
BuildContext
context
)
async
{
if
(
_currentStep
>
0
)
{
setState
(()
{
_currentStep
-=
1
;
});
setState
(()
=>
_currentStep
-=
1
);
return
false
;
}
else
{
return
true
;
}
}
void
_submitForm
()
{
print
(
'Form Submitted:'
);
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'Form submitted successfully!'
)),
);
bool
_isIfscValidFormat
(
String
ifsc
)
{
// Basic IFSC pattern: 4 letters, 0, 6 alphanumeric
final
reg
=
RegExp
(
r'^[A-Za-z]{4}0[A-Za-z0-9]{6}$'
);
return
reg
.
hasMatch
(
ifsc
.
trim
());
}
@override
void
dispose
()
{
focusNodes
.
map
((
e
)
=>
e
.
dispose
());
super
.
dispose
();
_connectivity
.
disposeStream
();
Future
<
void
>
_validateGstIfNeeded
(
Accountslistprovider
provider
)
async
{
final
gst
=
provider
.
gstNumberController
.
text
.
trim
();
if
(
gst
.
isEmpty
)
{
// nothing to validate
return
;
}
// get emp/session
final
homeProv
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
// set a small loading indicator on provider or local if needed
provider
.
isLoading
=
true
;
provider
.
gstNumberError
=
null
;
provider
.
notifyListeners
();
try
{
await
provider
.
validateGstNumber
(
homeProv
.
empId
,
homeProv
.
session
,
gst
);
// After validateGstNumber completes, provider.gstResponse should be set
if
(
provider
.
gstResponse
!=
null
&&
provider
.
gstResponse
!.
error
==
"0"
)
{
// autofill address in step 2
final
fetchedAddress
=
provider
.
gstResponse
!.
address
??
""
;
if
(
fetchedAddress
.
isNotEmpty
)
{
provider
.
addressController
.
text
=
fetchedAddress
;
}
// compare company name
final
gstName
=
(
provider
.
gstResponse
!.
legalNameOfBusiness
??
""
)
.
trim
()
.
toLowerCase
();
final
companyName
=
provider
.
nameController
.
text
.
trim
().
toLowerCase
();
if
(
gstName
.
isNotEmpty
&&
companyName
.
isNotEmpty
&&
gstName
!=
companyName
)
{
provider
.
nameError
=
"Company name doesn't match GST legal name (
${provider.gstResponse!.legalNameOfBusiness}
). Please correct."
;
}
else
{
provider
.
nameError
=
null
;
}
provider
.
gstNumberError
=
null
;
}
else
{
// API returned error or invalid gst
provider
.
gstNumberError
=
provider
.
gstResponse
?.
message
??
"Invalid GST number"
;
}
}
catch
(
e
)
{
provider
.
gstNumberError
=
"Failed to validate GST:
$e
"
;
}
finally
{
provider
.
isLoading
=
false
;
provider
.
notifyListeners
();
}
}
Future
<
bool
>
onBackPressed
(
BuildContext
context
)
async
{
if
(
_currentStep
>
0
)
{
_previousStep
();
return
false
;
Future
<
void
>
_validateBankIfNeeded
(
Accountslistprovider
provider
)
async
{
final
acc
=
provider
.
bankAcNumberController
.
text
.
trim
();
final
ifsc
=
provider
.
bankIfscCotroller
.
text
.
trim
();
// Only validate if both fields have values
if
(
acc
.
isEmpty
||
ifsc
.
isEmpty
)
{
return
;
}
// IFSC basic format check first
if
(!
_isIfscValidFormat
(
ifsc
))
{
provider
.
bankIFSCError
=
"Invalid IFSC format"
;
provider
.
notifyListeners
();
return
;
}
else
{
return
true
;
provider
.
bankIFSCError
=
null
;
}
final
homeProv
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
provider
.
isLoading
=
true
;
provider
.
notifyListeners
();
try
{
await
provider
.
validateBankDetails
(
homeProv
.
empId
,
homeProv
.
session
,
acc
);
// provider uses bankIfscCotroller.text internally
if
(
provider
.
bankResponse
!=
null
&&
provider
.
bankResponse
!.
error
==
"0"
)
{
// autofill fields
final
br
=
provider
.
bankResponse
!;
if
(
br
.
bankName
!=
null
&&
br
.
bankName
!.
isNotEmpty
)
{
provider
.
bankNameController
.
text
=
br
.
bankName
!;
}
if
(
br
.
branch
!=
null
&&
br
.
branch
!.
isNotEmpty
)
{
provider
.
branchNameController
.
text
=
br
.
branch
!;
}
if
(
br
.
nameAtBank
!=
null
&&
br
.
nameAtBank
!.
isNotEmpty
)
{
provider
.
bankHolderNameController
.
text
=
br
.
nameAtBank
!;
}
provider
.
bankAcNumberError
=
null
;
provider
.
bankIFSCError
=
null
;
}
else
{
// show error
provider
.
bankAcNumberError
=
provider
.
bankResponse
?.
message
??
"Invalid account / IFSC"
;
}
}
catch
(
e
)
{
provider
.
bankAcNumberError
=
"Failed to validate bank details:
$e
"
;
}
finally
{
provider
.
isLoading
=
false
;
provider
.
notifyListeners
();
}
}
/// Determine first step which has an error (0..3). If none returns null.
int
?
_firstErrorStep
(
Accountslistprovider
provider
)
{
// Step 0: Account Details
if
((
provider
.
accountError
?.
isNotEmpty
??
false
)
||
(
provider
.
nameError
?.
isNotEmpty
??
false
)
||
(
provider
.
mobileError
?.
isNotEmpty
??
false
)
||
(
provider
.
contactPersonError
?.
isNotEmpty
??
false
))
{
return
0
;
}
// Step 1: Address details (optional step but if errors exist, redirect)
if
((
provider
.
stateError
?.
isNotEmpty
??
false
)
||
(
provider
.
districtError
?.
isNotEmpty
??
false
)
||
(
provider
.
localityError
?.
isNotEmpty
??
false
)
||
(
provider
.
addressError
?.
isNotEmpty
??
false
))
{
return
1
;
}
// Step 2: Bank / GST related validation errors
if
((
provider
.
gstNumberError
?.
isNotEmpty
??
false
)
||
(
provider
.
bankAcNumberError
?.
isNotEmpty
??
false
)
||
(
provider
.
bankIFSCError
?.
isNotEmpty
??
false
)
||
(
provider
.
banknameError
?.
isNotEmpty
??
false
)
||
(
provider
.
bankBranchError
?.
isNotEmpty
??
false
)
||
(
provider
.
bankHolderNameError
?.
isNotEmpty
??
false
)
||
(
provider
.
upiError
?.
isNotEmpty
??
false
))
{
return
2
;
}
// Step 3: Contact Details
if
((
provider
.
desigantionError
?.
isNotEmpty
??
false
)
||
(
provider
.
altMobError
?.
isNotEmpty
??
false
)
||
(
provider
.
teleError
?.
isNotEmpty
??
false
)
||
(
provider
.
mailError
?.
isNotEmpty
??
false
))
{
return
3
;
}
return
null
;
}
@override
...
...
@@ -104,17 +240,14 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
default
:
connection
=
'Offline'
;
}
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
);
}
...
...
@@ -132,42 +265,112 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
),
backgroundColor:
AppColors
.
scaffold_bg_color
,
body:
Form
(
canPop:
_currentStep
==
0
,
key:
_formKey
,
child:
Stepper
(
margin:
EdgeInsets
.
symmetric
(
horizontal:
0
,
vertical:
0
),
type:
StepperType
.
horizontal
,
currentStep:
_currentStep
,
onStepContinue:
_nextStep
,
onStepCancel:
_previousStep
,
onStepTapped:
(
value
)
{
print
(
value
);
onStepContinue:
()
async
{
// custom continue logic:
if
(
_currentStep
==
0
)
{
// validate step1 via provider
if
(
provider
.
validateStep1
())
{
setState
(()
=>
_currentStep
=
1
);
}
else
{
// show error (provider sets errors and notifies)
provider
.
notifyListeners
();
// stay on step 0
setState
(()
=>
_currentStep
=
0
);
}
}
else
if
(
_currentStep
==
1
)
{
// Step 2 is optional; allow moving to next without forcing validation
// But if the user has entered fields and they are invalid, validate
if
(
provider
.
stateSearchController
.
text
.
trim
().
isNotEmpty
||
provider
.
districtSearchController
.
text
.
trim
().
isNotEmpty
||
provider
.
addressController
.
text
.
trim
().
isNotEmpty
)
{
if
(
provider
.
validateStep2
())
{
setState
(()
=>
_currentStep
=
2
);
}
else
{
provider
.
notifyListeners
();
}
}
else
{
// nothing filled, just move forward
setState
(()
=>
_currentStep
=
2
);
}
}
else
if
(
_currentStep
==
2
)
{
// Step 3 (bank) is optional; validate only if fields present
if
(
provider
.
gstNumberController
.
text
.
trim
().
isNotEmpty
)
{
// ensure gst validated
await
_validateGstIfNeeded
(
provider
);
}
if
(
provider
.
bankAcNumberController
.
text
.
trim
().
isNotEmpty
||
provider
.
bankIfscCotroller
.
text
.
trim
().
isNotEmpty
)
{
await
_validateBankIfNeeded
(
provider
);
}
setState
(()
{
if
(
value
==
1
&&
!
provider
.
validateStep1
())
{
return
;
// if any bank/gst errors exist, stay; else move forward
final
bankErrors
=
(
provider
.
gstNumberError
!=
null
&&
provider
.
gstNumberError
!.
isNotEmpty
)
||
(
provider
.
bankAcNumberError
!=
null
&&
provider
.
bankAcNumberError
!.
isNotEmpty
)
||
(
provider
.
bankIFSCError
!=
null
&&
provider
.
bankIFSCError
!.
isNotEmpty
);
if
(
bankErrors
)
{
provider
.
notifyListeners
();
setState
(()
=>
_currentStep
=
2
);
}
else
{
setState
(()
=>
_currentStep
=
3
);
}
if
(
value
==
2
&&
!
provider
.
validateStep2
())
{
return
;
}
else
if
(
_currentStep
==
3
)
{
// last step: same as pressing Submit in controls below
}
},
onStepCancel:
()
{
if
(
_currentStep
>
0
)
{
setState
(()
=>
_currentStep
-=
1
);
}
},
onStepTapped:
(
value
)
async
{
// allow tapping to review steps; prevent jumping forward past required failed steps
if
(
value
==
0
)
{
setState
(()
=>
_currentStep
=
0
);
}
else
if
(
value
==
1
)
{
// user wants to jump to step 1 - ensure step 0 valid
if
(
provider
.
validateStep1
())
{
setState
(()
=>
_currentStep
=
1
);
}
else
{
provider
.
notifyListeners
();
setState
(()
=>
_currentStep
=
0
);
}
if
(
value
<
_currentStep
)
{
_currentStep
=
value
;
}
else
if
(
value
>
_currentStep
)
{
_currentStep
=
value
;
}
else
if
(
value
==
2
)
{
// allow jump if step0 valid; step1 optional
if
(
provider
.
validateStep1
())
{
setState
(()
=>
_currentStep
=
2
);
}
else
{
provider
.
notifyListeners
();
setState
(()
=>
_currentStep
=
0
);
}
}
else
if
(
value
==
3
)
{
// final - require step0 valid
if
(!
provider
.
validateStep1
())
{
provider
.
notifyListeners
();
setState
(()
=>
_currentStep
=
0
);
return
;
}
});
// optional steps validated when moving forward by controls
setState
(()
=>
_currentStep
=
3
);
}
},
connectorColor:
WidgetStatePropertyAll
(
AppColors
.
app_blue
),
stepIconBuilder:
(
stepIndex
,
stepState
)
{
return
CircleAvatar
(
radius:
12
,
backgroundColor:
stepIndex
<=
_currentStep
?
AppColors
.
app_blue
:
Colors
.
grey
[
300
],
backgroundColor:
stepIndex
<=
_currentStep
?
AppColors
.
app_blue
:
Colors
.
grey
[
300
],
);
},
steps:
[
// Step 0 (Step 1 in your labels)
Step
(
label:
Text
(
"Step 1"
,
style:
TextStyle
(
fontSize:
12
)),
title:
const
Text
(
''
),
...
...
@@ -187,15 +390,8 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
),
),
Container
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
,
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
),
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
)),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
...
...
@@ -218,45 +414,20 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
),
],
),
items:
provider
.
accountTypes
.
map
(
(
act
)
=>
DropdownMenuItem
<
String
>(
value:
act
,
child:
Text
(
act
,
style:
const
TextStyle
(
fontSize:
14
,
),
overflow:
TextOverflow
.
ellipsis
,
),
),
)
.
toList
(),
// value: provider.selectedAccountType,
value:
provider
.
accountTypes
.
contains
(
provider
.
selectedAccountType
,
)
?
provider
.
selectedAccountType
:
null
,
items:
provider
.
accountTypes
.
map
((
act
)
=>
DropdownMenuItem
<
String
>(
value:
act
,
child:
Text
(
act
,
style:
const
TextStyle
(
fontSize:
14
),
overflow:
TextOverflow
.
ellipsis
),
)).
toList
(),
value:
provider
.
accountTypes
.
contains
(
provider
.
selectedAccountType
)
?
provider
.
selectedAccountType
:
null
,
onChanged:
(
value
)
{
if
(
value
!=
null
)
{
provider
.
selectedAccountType
=
value
;
print
(
"statusId:
${provider.selectedAccountType}
"
,
);
}
},
buttonStyleData:
ddtheme
.
buttonStyleData
,
iconStyleData:
ddtheme
.
iconStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
),
),
],
...
...
@@ -268,13 +439,9 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
provider
.
nameController
,
"Company Name"
,
"Enter Company Name"
,
(
p0
)
{
(
p0
)
{
provider
.
updateName
(
p0
);
provider
.
checkInputsAPI
(
context
,
"name"
,
provider
.
nameController
.
text
,
);
provider
.
checkInputsAPI
(
context
,
"name"
,
provider
.
nameController
.
text
);
},
TextInputType
.
text
,
false
,
...
...
@@ -282,6 +449,9 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
focusNodes
[
0
],
focusNodes
[
1
],
TextInputAction
.
next
,
null
,
// validator for form-level as well
// we won't add Form validator since provider handles it
),
errorWidget
(
context
,
provider
.
nameError
),
textControllerWidget
(
...
...
@@ -289,13 +459,9 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
provider
.
mobileController
,
"Mobile Number"
,
"Enter Mobile"
,
(
p0
)
{
(
p0
)
{
provider
.
updateMobile
(
p0
);
provider
.
checkInputsAPI
(
context
,
"mob1"
,
provider
.
mobileController
.
text
,
);
provider
.
checkInputsAPI
(
context
,
"mob1"
,
provider
.
mobileController
.
text
);
},
TextInputType
.
phone
,
false
,
...
...
@@ -326,6 +492,8 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
],
),
),
// Step 1 (Address / optional)
Step
(
label:
Text
(
"Step 2"
,
style:
TextStyle
(
fontSize:
12
)),
title:
const
Text
(
''
),
...
...
@@ -337,22 +505,12 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
margin:
EdgeInsets
.
only
(
bottom:
10
),
child:
Text
(
"Address Details"
,
style:
TextStyle
(
color:
AppColors
.
app_blue
,
fontSize:
16
,
fontFamily:
"JakartaMedium"
,
),
style:
TextStyle
(
color:
AppColors
.
app_blue
,
fontSize:
16
,
fontFamily:
"JakartaMedium"
),
),
),
Container
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
,
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
),
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
)),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
...
...
@@ -363,114 +521,47 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
Expanded
(
child:
DropdownButton2
<
States
>(
focusNode:
focusNodes
[
2
],
autofocus:
focusNodes
[
2
].
hasFocus
?
true
:
false
,
autofocus:
focusNodes
[
2
].
hasFocus
?
true
:
false
,
isExpanded:
true
,
hint:
Text
(
'Select State'
,
style:
TextStyle
(
fontSize:
14
),
overflow:
TextOverflow
.
ellipsis
,
),
items:
provider
.
states
.
map
(
(
states
)
=>
DropdownMenuItem
<
States
>(
value:
states
,
child:
Text
(
states
.
name
??
''
,
style:
const
TextStyle
(
fontSize:
14
,
),
overflow:
TextOverflow
.
ellipsis
,
),
),
)
.
toList
(),
value:
provider
.
states
.
contains
(
provider
.
selectedState
,
)
?
provider
.
selectedState
:
null
,
// value: provider.selectedState,
hint:
Text
(
'Select State'
,
style:
TextStyle
(
fontSize:
14
)),
items:
provider
.
states
.
map
((
states
)
=>
DropdownMenuItem
<
States
>(
value:
states
,
child:
Text
(
states
.
name
??
''
,
style:
const
TextStyle
(
fontSize:
14
),
overflow:
TextOverflow
.
ellipsis
),
)).
toList
(),
value:
provider
.
states
.
contains
(
provider
.
selectedState
)
?
provider
.
selectedState
:
null
,
onChanged:
(
States
?
value
)
{
if
(
value
!=
null
)
{
if
(
provider
.
states
.
isNotEmpty
)
{
provider
.
selectedState
=
value
;
print
(
"Selected Complaint Type:
${value.name}
, ID:
${value.id}
"
,
);
provider
.
selectedStateID
=
value
.
id
!;
print
(
"hfjkshfg
${provider.selectedStateID}
"
,
);
if
(
provider
.
selectedDistricts
!=
null
)
{
provider
.
districts
.
clear
();
// provider.selectedDistricts = null;
provider
.
selectedDistrictId
=
null
;
provider
.
selectedDistrictValue
=
null
;
}
provider
.
getDistrictAPI
(
context
,
provider
.
selectedStateID
,
);
provider
.
selectedState
=
value
;
provider
.
selectedStateID
=
value
.
id
!;
if
(
provider
.
selectedDistricts
!=
null
)
{
provider
.
districts
.
clear
();
provider
.
selectedDistrictId
=
null
;
provider
.
selectedDistrictValue
=
null
;
}
provider
.
getDistrictAPI
(
context
,
provider
.
selectedStateID
);
}
},
dropdownSearchData:
DropdownSearchData
(
searchInnerWidgetHeight:
50
,
searchController:
provider
.
stateSearchController
,
searchController:
provider
.
stateSearchController
,
searchInnerWidget:
Padding
(
padding:
const
EdgeInsets
.
all
(
8
),
child:
TextFormField
(
controller:
provider
.
stateSearchController
,
decoration:
InputDecoration
(
isDense:
true
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
8
,
),
hintText:
'Search States...'
,
border:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
8
),
),
),
controller:
provider
.
stateSearchController
,
decoration:
InputDecoration
(
isDense:
true
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
8
),
hintText:
'Search States...'
,
border:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
8
))),
),
),
searchMatchFn:
(
item
,
searchValue
)
{
return
item
.
value
?.
name
?.
toLowerCase
()
.
contains
(
searchValue
.
toLowerCase
(),
)
??
false
;
return
item
.
value
?.
name
?.
toLowerCase
().
contains
(
searchValue
.
toLowerCase
())
??
false
;
},
),
onMenuStateChange:
(
isOpen
)
{
if
(!
isOpen
)
{
provider
.
stateSearchController
.
clear
();
}
if
(!
isOpen
)
provider
.
stateSearchController
.
clear
();
},
buttonStyleData:
ddtheme
.
buttonStyleData
,
iconStyleData:
ddtheme
.
iconStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
),
),
],
...
...
@@ -485,110 +576,45 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
child:
DropdownButton2
<
Districts
>(
focusNode:
focusNodes
[
3
],
isExpanded:
true
,
hint:
Text
(
'Select District'
,
style:
TextStyle
(
fontSize:
14
),
overflow:
TextOverflow
.
ellipsis
,
),
items:
provider
.
districts
.
map
(
(
dist
)
=>
DropdownMenuItem
<
Districts
>(
value:
dist
,
child:
Text
(
dist
.
district
??
''
,
style:
const
TextStyle
(
fontSize:
14
,
),
overflow:
TextOverflow
.
ellipsis
,
),
),
)
.
toList
(),
value:
provider
.
districts
.
contains
(
provider
.
selectedDistricts
,
)
?
provider
.
selectedDistricts
:
null
,
// value: provider.selectedDistricts,
hint:
Text
(
'Select District'
,
style:
TextStyle
(
fontSize:
14
)),
items:
provider
.
districts
.
map
((
dist
)
=>
DropdownMenuItem
<
Districts
>(
value:
dist
,
child:
Text
(
dist
.
district
??
''
,
style:
const
TextStyle
(
fontSize:
14
),
overflow:
TextOverflow
.
ellipsis
),
)).
toList
(),
value:
provider
.
districts
.
contains
(
provider
.
selectedDistricts
)
?
provider
.
selectedDistricts
:
null
,
onChanged:
(
Districts
?
value
)
{
if
(
value
!=
null
)
{
if
(
provider
.
districts
.
isNotEmpty
)
{
provider
.
selectedDistricts
=
value
;
print
(
"Selected ID:
${value.id}
"
);
provider
.
selectedDistrictId
=
value
.
id
!;
provider
.
selectedDistrictValue
=
value
.
district
!;
print
(
"hfjkshfg
${provider.selectedDistrictId}
"
,
);
if
(
provider
.
selectedSubLocations
!=
null
)
{
provider
.
subLocations
.
clear
();
// provider.selectedSubLocations =
// null;
provider
.
selectedSubLocID
=
null
;
provider
.
selectedSubLocValue
=
null
;
}
provider
.
getSubLocationAPI
(
context
,
provider
.
selectedDistrictId
,
);
provider
.
selectedDistricts
=
value
;
provider
.
selectedDistrictId
=
value
.
id
!;
provider
.
selectedDistrictValue
=
value
.
district
!;
if
(
provider
.
selectedSubLocations
!=
null
)
{
provider
.
selectedSubLocID
=
null
;
provider
.
selectedSubLocValue
=
null
;
}
provider
.
getSubLocationAPI
(
context
,
provider
.
selectedDistrictId
);
}
},
dropdownSearchData:
DropdownSearchData
(
searchInnerWidgetHeight:
50
,
searchController:
provider
.
districtSearchController
,
searchController:
provider
.
districtSearchController
,
searchInnerWidget:
Padding
(
padding:
const
EdgeInsets
.
all
(
8
),
child:
TextFormField
(
controller:
provider
.
districtSearchController
,
decoration:
InputDecoration
(
isDense:
true
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
8
,
),
hintText:
'Search Districts...'
,
border:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
8
),
),
),
controller:
provider
.
districtSearchController
,
decoration:
InputDecoration
(
isDense:
true
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
8
),
hintText:
'Search Districts...'
,
border:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
8
))),
),
),
searchMatchFn:
(
item
,
searchValue
)
{
return
item
.
value
?.
district
?.
toLowerCase
()
.
contains
(
searchValue
.
toLowerCase
(),
)
??
false
;
return
item
.
value
?.
district
?.
toLowerCase
().
contains
(
searchValue
.
toLowerCase
())
??
false
;
},
),
onMenuStateChange:
(
isOpen
)
{
if
(!
isOpen
)
{
provider
.
districtSearchController
.
clear
();
}
if
(!
isOpen
)
provider
.
districtSearchController
.
clear
();
},
buttonStyleData:
ddtheme
.
buttonStyleData
,
iconStyleData:
ddtheme
.
iconStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
),
),
],
...
...
@@ -603,100 +629,40 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
child:
DropdownButton2
<
SubLocations
>(
focusNode:
focusNodes
[
4
],
isExpanded:
true
,
hint:
Text
(
'Select Sub Locality'
,
style:
TextStyle
(
fontSize:
14
),
overflow:
TextOverflow
.
ellipsis
,
),
items:
provider
.
subLocations
.
map
(
(
subloc
)
=>
DropdownMenuItem
<
SubLocations
>(
value:
subloc
,
child:
Text
(
subloc
.
subLocality
??
''
,
style:
const
TextStyle
(
fontSize:
14
,
),
overflow:
TextOverflow
.
ellipsis
,
),
),
)
.
toList
(),
// value: provider.selectedSubLocations,
value:
provider
.
subLocations
.
contains
(
provider
.
selectedSubLocations
,
)
?
provider
.
selectedSubLocations
:
null
,
hint:
Text
(
'Select Sub Locality'
,
style:
TextStyle
(
fontSize:
14
)),
items:
provider
.
subLocations
.
map
((
subloc
)
=>
DropdownMenuItem
<
SubLocations
>(
value:
subloc
,
child:
Text
(
subloc
.
subLocality
??
''
,
style:
const
TextStyle
(
fontSize:
14
),
overflow:
TextOverflow
.
ellipsis
),
)).
toList
(),
value:
provider
.
subLocations
.
contains
(
provider
.
selectedSubLocations
)
?
provider
.
selectedSubLocations
:
null
,
onChanged:
(
SubLocations
?
value
)
{
if
(
value
!=
null
)
{
if
(
provider
.
subLocations
.
isNotEmpty
)
{
provider
.
selectedSubLocations
=
value
;
print
(
"Selected ID:
${value.id}
"
);
provider
.
selectedSubLocID
=
value
.
id
!;
provider
.
selectedSubLocValue
=
value
.
subLocality
!;
print
(
"hfjkshfg
${provider.selectedSubLocID}
"
,
);
}
provider
.
selectedSubLocations
=
value
;
provider
.
selectedSubLocID
=
value
.
id
!;
provider
.
selectedSubLocValue
=
value
.
subLocality
!;
}
},
dropdownSearchData:
DropdownSearchData
(
searchInnerWidgetHeight:
50
,
searchController:
provider
.
subLocSearchController
,
searchController:
provider
.
subLocSearchController
,
searchInnerWidget:
Padding
(
padding:
const
EdgeInsets
.
all
(
8
),
child:
TextFormField
(
controller:
provider
.
subLocSearchController
,
decoration:
InputDecoration
(
isDense:
true
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
8
,
),
hintText:
'Search Sub Locality...'
,
border:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
8
),
),
),
controller:
provider
.
subLocSearchController
,
decoration:
InputDecoration
(
isDense:
true
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
8
),
hintText:
'Search Sub Locality...'
,
border:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
8
))),
),
),
searchMatchFn:
(
item
,
searchValue
)
{
return
item
.
value
?.
subLocality
?.
toLowerCase
()
.
contains
(
searchValue
.
toLowerCase
(),
)
??
false
;
return
item
.
value
?.
subLocality
?.
toLowerCase
().
contains
(
searchValue
.
toLowerCase
())
??
false
;
},
),
onMenuStateChange:
(
isOpen
)
{
if
(!
isOpen
)
{
provider
.
subLocSearchController
.
clear
();
}
if
(!
isOpen
)
provider
.
subLocSearchController
.
clear
();
},
buttonStyleData:
ddtheme
.
buttonStyleData
,
iconStyleData:
ddtheme
.
iconStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
),
),
],
...
...
@@ -723,37 +689,100 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
],
),
),
// Step 2 (Bank & GST)
Step
(
label:
Text
(
"Step 3"
,
style:
TextStyle
(
fontSize:
12
)),
title:
const
Text
(
''
),
isActive:
_currentStep
>=
1
,
isActive:
_currentStep
>=
2
,
content:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Container
(
margin:
EdgeInsets
.
only
(
bottom:
10
),
child:
Text
(
"Bank Details"
,
style:
TextStyle
(
color:
AppColors
.
app_blue
,
fontSize:
16
,
fontFamily:
"JakartaMedium"
,
),
),
child:
Text
(
"Bank Details"
,
style:
TextStyle
(
color:
AppColors
.
app_blue
,
fontSize:
16
,
fontFamily:
"JakartaMedium"
)),
),
Container
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
,
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
),
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
)),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
// GST field - if provided, validate and autofill address; compare company name
textControllerWidget
(
context
,
provider
.
gstNumberController
,
"GST Number"
,
"Enter GST Number"
,
(
val
)
async
{
// when user types, just update; validation on field submit
provider
.
gstNumberController
.
text
=
val
;
provider
.
notifyListeners
();
},
TextInputType
.
text
,
false
,
null
,
focusNodes
[
9
],
focusNodes
[
10
],
TextInputAction
.
next
,
null
,
// onEditingComplete / onFieldSubmitted, we will validate
),
// Validate GST when user leaves the field (on editing complete)
// To do that we use FocusNode
const
SizedBox
(
height:
4
),
errorWidget
(
context
,
provider
.
gstNumberError
),
// Bank Account Number
textControllerWidget
(
context
,
provider
.
bankAcNumberController
,
"Bank Account Number"
,
"Enter Bank Account Number"
,
(
p0
)
{
provider
.
updateNumber
(
p0
);
// attempt validation only when IFSC present
if
(
provider
.
bankIfscCotroller
.
text
.
trim
().
isNotEmpty
)
{
_validateBankIfNeeded
(
provider
);
}
},
TextInputType
.
number
,
false
,
FilteringTextInputFormatter
.
digitsOnly
,
focusNodes
[
10
],
focusNodes
[
11
],
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
bankAcNumberError
),
// IFSC
textControllerWidget
(
context
,
provider
.
bankIfscCotroller
,
"Bank IFSC"
,
"Enter Bank IFSC"
,
(
p0
)
{
provider
.
updateIFSC
(
p0
);
// validate IFSC format locally; if good and account present, trigger server validation
if
(
_isIfscValidFormat
(
p0
)
&&
provider
.
bankAcNumberController
.
text
.
trim
().
isNotEmpty
)
{
_validateBankIfNeeded
(
provider
);
}
else
{
if
(
p0
.
trim
().
isNotEmpty
&&
!
_isIfscValidFormat
(
p0
))
{
provider
.
bankIFSCError
=
"Invalid IFSC format"
;
provider
.
notifyListeners
();
}
else
{
provider
.
bankIFSCError
=
null
;
provider
.
notifyListeners
();
}
}
},
TextInputType
.
text
,
false
,
null
,
focusNodes
[
8
],
focusNodes
[
9
],
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
bankIFSCError
),
// Bank Name (autofill)
textControllerWidget
(
context
,
provider
.
bankNameController
,
...
...
@@ -768,6 +797,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
banknameError
),
// Branch
textControllerWidget
(
context
,
provider
.
branchNameController
,
...
...
@@ -782,20 +812,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
bankBranchError
),
textControllerWidget
(
context
,
provider
.
bankIfscCotroller
,
"Bank IFSC"
,
"Enter Bank IFSC"
,
provider
.
updateIFSC
,
TextInputType
.
text
,
false
,
null
,
focusNodes
[
8
],
focusNodes
[
9
],
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
bankIFSCError
),
// Holder
textControllerWidget
(
context
,
provider
.
bankHolderNameController
,
...
...
@@ -810,20 +827,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
bankHolderNameError
),
textControllerWidget
(
context
,
provider
.
bankAcNumberController
,
"Bank Account Number"
,
"Enter Bank Account Number"
,
provider
.
updateNumber
,
TextInputType
.
number
,
false
,
FilteringTextInputFormatter
.
digitsOnly
,
focusNodes
[
10
],
focusNodes
[
11
],
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
bankAcNumberError
),
// UPI
textControllerWidget
(
context
,
provider
.
bankUpiController
,
...
...
@@ -844,33 +848,22 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
],
),
),
// Step 3 (Contact Details)
Step
(
label:
Text
(
"Step 4"
,
style:
TextStyle
(
fontSize:
12
)),
title:
const
Text
(
''
),
isActive:
_currentStep
>=
2
,
isActive:
_currentStep
>=
3
,
content:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Container
(
margin:
EdgeInsets
.
only
(
bottom:
10
),
child:
Text
(
"Contact Details"
,
style:
TextStyle
(
color:
AppColors
.
app_blue
,
fontSize:
16
,
fontFamily:
"JakartaMedium"
,
),
),
child:
Text
(
"Contact Details"
,
style:
TextStyle
(
color:
AppColors
.
app_blue
,
fontSize:
16
,
fontFamily:
"JakartaMedium"
)),
),
Container
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
,
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
),
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
)),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
...
...
@@ -893,13 +886,9 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
provider
.
contectPersonAltMobController
,
"Alternative Mobile Number"
,
"Enter Alternative Mobile Number"
,
(
p0
)
{
(
p0
)
{
provider
.
updateAltMobile
(
p0
);
provider
.
checkInputsAPI
(
context
,
"mob2"
,
provider
.
contectPersonAltMobController
.
text
,
);
provider
.
checkInputsAPI
(
context
,
"mob2"
,
provider
.
contectPersonAltMobController
.
text
);
},
TextInputType
.
number
,
false
,
...
...
@@ -950,43 +939,54 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
children:
[
if
(
_currentStep
==
3
)
...[
InkResponse
(
onTap:
provider
.
submitClickced
?
null
:
()
{
if
(
provider
.
validateStep4
())
{
provider
.
submitClickced
=
true
;
provider
.
submitCommonAccountsAPI
(
context
,
widget
.
from
,
);
}
onTap:
provider
.
submitClickced
?
null
:
()
async
{
// Before submit final: validate all required rules:
// - Step 0 required
// - Step 3 required
// - Step 2 & Step 1 optional (but if fields present then validate)
// Also ensure gst/bank validations triggered if filled
// Trigger validations
// If GST present -> validate
if
(
provider
.
gstNumberController
.
text
.
trim
().
isNotEmpty
)
{
await
_validateGstIfNeeded
(
provider
);
}
if
(
provider
.
bankAcNumberController
.
text
.
trim
().
isNotEmpty
&&
provider
.
bankIfscCotroller
.
text
.
trim
().
isNotEmpty
)
{
await
_validateBankIfNeeded
(
provider
);
}
// Now run provider overall validation
final
ok
=
provider
.
validatereceiptForm
(
context
);
details
.
onStepContinue
;
},
if
(!
ok
)
{
// move to first error step
final
errStep
=
_firstErrorStep
(
provider
);
if
(
errStep
!=
null
)
{
setState
(()
{
_currentStep
=
errStep
;
});
}
// ensure UI updated
provider
.
notifyListeners
();
return
;
}
// All good => submit
provider
.
submitClickced
=
true
;
provider
.
notifyListeners
();
await
provider
.
submitCommonAccountsAPI
(
context
,
widget
.
from
);
},
child:
Container
(
height:
45
,
alignment:
Alignment
.
center
,
margin:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
,
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
5
,
),
decoration:
BoxDecoration
(
color:
AppColors
.
app_blue
,
borderRadius:
BorderRadius
.
circular
(
15
),
),
child:
Text
(
"Submit"
,
style:
TextStyle
(
fontSize:
15
,
fontFamily:
"JakartaMedium"
,
color:
Colors
.
white
,
),
),
margin:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
5
),
decoration:
BoxDecoration
(
color:
AppColors
.
app_blue
,
borderRadius:
BorderRadius
.
circular
(
15
)),
child:
provider
.
submitClickced
?
CircularProgressIndicator
.
adaptive
(
valueColor:
AlwaysStoppedAnimation
(
AppColors
.
white
))
:
Text
(
"Submit"
,
style:
TextStyle
(
fontSize:
15
,
fontFamily:
"JakartaMedium"
,
color:
Colors
.
white
)),
),
),
]
else
...[
...
...
@@ -996,45 +996,48 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
if
(
_currentStep
==
0
)
{
if
(
provider
.
validateStep1
())
{
_currentStep
=
1
;
}
else
{
provider
.
notifyListeners
();
_currentStep
=
0
;
}
}
else
if
(
_currentStep
==
1
)
{
if
(
provider
.
validateStep2
())
{
if
(
provider
.
stateSearchController
.
text
.
trim
().
isNotEmpty
||
provider
.
districtSearchController
.
text
.
trim
().
isNotEmpty
||
provider
.
addressController
.
text
.
trim
().
isNotEmpty
)
{
// user has filled something - validate
if
(
provider
.
validateStep2
())
{
_currentStep
=
2
;
}
else
{
provider
.
notifyListeners
();
}
}
else
{
_currentStep
=
2
;
}
}
else
if
(
_currentStep
==
2
)
{
if
(
provider
.
validateStep3
())
{
_currentStep
=
3
;
// trigger GST/Bank validate if fields present
if
(
provider
.
gstNumberController
.
text
.
trim
().
isNotEmpty
)
{
_validateGstIfNeeded
(
provider
);
}
if
(
provider
.
bankAcNumberController
.
text
.
trim
().
isNotEmpty
&&
provider
.
bankIfscCotroller
.
text
.
trim
().
isNotEmpty
)
{
_validateBankIfNeeded
(
provider
);
}
// after async validations we just try to move forward;
// if errors exist they will be shown and user stays after next tap
_currentStep
=
3
;
}
else
{
_currentStep
=
0
;
}
});
details
.
onStepContinue
;
},
child:
Container
(
height:
45
,
alignment:
Alignment
.
center
,
margin:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
,
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
5
,
),
decoration:
BoxDecoration
(
color:
AppColors
.
app_blue
,
borderRadius:
BorderRadius
.
circular
(
15
),
),
child:
Text
(
"Proceed to Next Step"
,
textAlign:
TextAlign
.
start
,
style:
TextStyle
(
fontSize:
15
,
fontFamily:
"JakartaMedium"
,
color:
Colors
.
white
,
),
),
margin:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
5
),
decoration:
BoxDecoration
(
color:
AppColors
.
app_blue
,
borderRadius:
BorderRadius
.
circular
(
15
)),
child:
Text
(
"Proceed to Next Step"
,
textAlign:
TextAlign
.
start
,
style:
TextStyle
(
fontSize:
15
,
fontFamily:
"JakartaMedium"
,
color:
Colors
.
white
)),
),
),
],
...
...
@@ -1044,24 +1047,16 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
setState
(()
{
if
(
_currentStep
==
3
)
{
_currentStep
=
2
;
}
if
(
_currentStep
==
2
)
{
}
else
if
(
_currentStep
==
2
)
{
_currentStep
=
1
;
}
else
if
(
_currentStep
==
1
)
{
_currentStep
=
0
;
}
else
{
_currentStep
=
3
;
_currentStep
=
0
;
}
});
details
.
onStepCancel
;
},
child:
Text
(
'Back'
,
style:
TextStyle
(
color:
AppColors
.
app_blue
,
fontSize:
14
,
),
),
child:
Text
(
'Back'
,
style:
TextStyle
(
color:
AppColors
.
app_blue
,
fontSize:
14
)),
),
],
],
...
...
@@ -1074,6 +1069,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
);
}
// --- Not used UI variant kept for parity with your original file ---
Widget
_scaffold1
(
BuildContext
context
)
{
return
Consumer
<
Accountslistprovider
>(
builder:
(
context
,
provider
,
child
)
{
...
...
@@ -1129,27 +1125,27 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
],
),
items:
provider
.
accountTypes
.
map
(
(
act
)
=>
DropdownMenuItem
<
String
>(
value:
act
,
child:
Text
(
act
,
style:
const
TextStyle
(
fontSize:
14
,
),
overflow:
TextOverflow
.
ellipsis
,
),
),
)
.
toList
(),
provider
.
accountTypes
.
map
(
(
act
)
=>
DropdownMenuItem
<
String
>(
value:
act
,
child:
Text
(
act
,
style:
const
TextStyle
(
fontSize:
14
,
),
overflow:
TextOverflow
.
ellipsis
,
),
),
)
.
toList
(),
// value: provider.selectedAccountType,
value:
provider
.
accountTypes
.
contains
(
provider
.
selectedAccountType
,
)
?
provider
.
selectedAccountType
:
null
,
provider
.
accountTypes
.
contains
(
provider
.
selectedAccountType
,
)
?
provider
.
selectedAccountType
:
null
,
onChanged:
(
value
)
{
if
(
value
!=
null
)
{
provider
.
selectedAccountType
=
value
;
...
...
@@ -1173,7 +1169,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
provider
.
nameController
,
"Company Name"
,
"Enter Company Name"
,
(
p0
)
{
(
p0
)
{
provider
.
updateName
(
p0
);
provider
.
checkInputsAPI
(
context
,
...
...
@@ -1194,7 +1190,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
provider
.
mobileController
,
"Mobile Number"
,
"Enter Mobile"
,
(
p0
)
{
(
p0
)
{
provider
.
updateMobile
(
p0
);
provider
.
checkInputsAPI
(
context
,
...
...
@@ -1291,9 +1287,9 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
child:
DropdownButton2
<
States
>(
focusNode:
focusNodes
[
2
],
autofocus:
focusNodes
[
2
].
hasFocus
?
true
:
false
,
focusNodes
[
2
].
hasFocus
?
true
:
false
,
isExpanded:
true
,
hint:
Text
(
'Select State'
,
...
...
@@ -1301,33 +1297,33 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
overflow:
TextOverflow
.
ellipsis
,
),
items:
provider
.
states
.
map
(
(
states
,
)
=>
DropdownMenuItem
<
States
>(
value:
states
,
child:
Text
(
states
.
name
??
''
,
style:
const
TextStyle
(
fontSize:
14
,
),
overflow:
TextOverflow
.
ellipsis
,
),
),
)
.
toList
(),
provider
.
states
.
map
(
(
states
,
)
=>
DropdownMenuItem
<
States
>(
value:
states
,
child:
Text
(
states
.
name
??
''
,
style:
const
TextStyle
(
fontSize:
14
,
),
overflow:
TextOverflow
.
ellipsis
,
),
),
)
.
toList
(),
value:
provider
.
states
.
contains
(
provider
.
selectedState
,
)
?
provider
.
selectedState
:
null
,
provider
.
states
.
contains
(
provider
.
selectedState
,
)
?
provider
.
selectedState
:
null
,
// value: provider.selectedState,
onChanged:
(
States
?
value
)
{
if
(
value
!=
null
)
{
...
...
@@ -1340,19 +1336,19 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
"Selected Complaint Type:
${value.name}
, ID:
${value.id}
"
,
);
provider
.
selectedStateID
=
value
.
id
!;
value
.
id
!;
print
(
"hfjkshfg
${provider.selectedStateID}
"
,
);
if
(
provider
.
selectedDistricts
!=
.
selectedDistricts
!=
null
)
{
provider
.
states
.
clear
();
// provider.selectedDistricts = null;
provider
.
selectedDistrictId
=
null
;
null
;
provider
.
selectedDistrictValue
=
null
;
null
;
}
provider
.
getDistrictAPI
(
...
...
@@ -1366,44 +1362,44 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
dropdownSearchData:
DropdownSearchData
(
searchInnerWidgetHeight:
50
,
searchController:
provider
.
stateSearchController
,
provider
.
stateSearchController
,
searchInnerWidget:
Padding
(
padding:
const
EdgeInsets
.
all
(
8
,
),
child:
TextFormField
(
controller:
provider
.
stateSearchController
,
provider
.
stateSearchController
,
decoration:
InputDecoration
(
isDense:
true
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
8
,
),
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
8
,
),
hintText:
'Search States...'
,
'Search States...'
,
border:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
8
,
),
BorderRadius
.
circular
(
8
,
),
),
),
),
),
searchMatchFn:
(
item
,
searchValue
,
)
{
item
,
searchValue
,
)
{
return
item
.
value
?.
name
?.
toLowerCase
()
.
contains
(
searchValue
.
toLowerCase
(),
)
??
?.
toLowerCase
()
.
contains
(
searchValue
.
toLowerCase
(),
)
??
false
;
},
),
...
...
@@ -1414,13 +1410,13 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
}
},
buttonStyleData:
ddtheme
.
buttonStyleData
,
ddtheme
.
buttonStyleData
,
iconStyleData:
ddtheme
.
iconStyleData
,
ddtheme
.
iconStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
ddtheme
.
dropdownStyleData
,
),
),
],
...
...
@@ -1441,34 +1437,34 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
overflow:
TextOverflow
.
ellipsis
,
),
items:
provider
.
districts
.
map
(
(
dist
,
)
=>
DropdownMenuItem
<
Districts
>(
value:
dist
,
child:
Text
(
dist
.
district
??
''
,
style:
const
TextStyle
(
fontSize:
14
,
),
overflow:
TextOverflow
.
ellipsis
,
),
),
)
.
toList
(),
provider
.
districts
.
map
(
(
dist
,
)
=>
DropdownMenuItem
<
Districts
>(
value:
dist
,
child:
Text
(
dist
.
district
??
''
,
style:
const
TextStyle
(
fontSize:
14
,
),
overflow:
TextOverflow
.
ellipsis
,
),
),
)
.
toList
(),
value:
provider
.
districts
.
contains
(
provider
.
selectedDistricts
,
)
?
provider
.
selectedDistricts
:
null
,
provider
.
districts
.
contains
(
provider
.
selectedDistricts
,
)
?
provider
.
selectedDistricts
:
null
,
// value: provider.selectedDistricts,
onChanged:
(
Districts
?
value
)
{
if
(
value
!=
null
)
{
...
...
@@ -1481,21 +1477,21 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
"Selected ID:
${value.id}
"
,
);
provider
.
selectedDistrictId
=
value
.
id
!;
value
.
id
!;
provider
.
selectedDistrictValue
=
value
.
district
!;
value
.
district
!;
print
(
"hfjkshfg
${provider.selectedDistrictId}
"
,
);
if
(
provider
.
selectedSubLocations
!=
.
selectedSubLocations
!=
null
)
{
// provider.selectedSubLocations =
// null;
provider
.
selectedSubLocID
=
null
;
null
;
provider
.
selectedSubLocValue
=
null
;
null
;
}
provider
.
getSubLocationAPI
(
context
,
...
...
@@ -1507,44 +1503,44 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
dropdownSearchData:
DropdownSearchData
(
searchInnerWidgetHeight:
50
,
searchController:
provider
.
districtSearchController
,
provider
.
districtSearchController
,
searchInnerWidget:
Padding
(
padding:
const
EdgeInsets
.
all
(
8
,
),
child:
TextFormField
(
controller:
provider
.
districtSearchController
,
provider
.
districtSearchController
,
decoration:
InputDecoration
(
isDense:
true
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
8
,
),
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
8
,
),
hintText:
'Search Districts...'
,
'Search Districts...'
,
border:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
8
,
),
BorderRadius
.
circular
(
8
,
),
),
),
),
),
searchMatchFn:
(
item
,
searchValue
,
)
{
item
,
searchValue
,
)
{
return
item
.
value
?.
district
?.
toLowerCase
()
.
contains
(
searchValue
.
toLowerCase
(),
)
??
?.
toLowerCase
()
.
contains
(
searchValue
.
toLowerCase
(),
)
??
false
;
},
),
...
...
@@ -1556,13 +1552,13 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
}
},
buttonStyleData:
ddtheme
.
buttonStyleData
,
ddtheme
.
buttonStyleData
,
iconStyleData:
ddtheme
.
iconStyleData
,
ddtheme
.
iconStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
ddtheme
.
dropdownStyleData
,
),
),
],
...
...
@@ -1583,37 +1579,37 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
overflow:
TextOverflow
.
ellipsis
,
),
items:
provider
.
subLocations
.
map
(
(
subloc
,
)
=>
DropdownMenuItem
<
SubLocations
>(
value:
subloc
,
child:
Text
(
subloc
.
subLocality
??
''
,
style:
const
TextStyle
(
fontSize:
14
,
),
overflow:
TextOverflow
.
ellipsis
,
),
),
)
.
toList
(),
provider
.
subLocations
.
map
(
(
subloc
,
)
=>
DropdownMenuItem
<
SubLocations
>(
value:
subloc
,
child:
Text
(
subloc
.
subLocality
??
''
,
style:
const
TextStyle
(
fontSize:
14
,
),
overflow:
TextOverflow
.
ellipsis
,
),
),
)
.
toList
(),
// value: provider.selectedSubLocations,
value:
provider
.
subLocations
.
contains
(
provider
.
selectedSubLocations
,
)
?
provider
.
selectedSubLocations
:
null
,
provider
.
subLocations
.
contains
(
provider
.
selectedSubLocations
,
)
?
provider
.
selectedSubLocations
:
null
,
onChanged:
(
SubLocations
?
value
)
{
if
(
value
!=
null
)
{
if
(
provider
...
...
@@ -1625,9 +1621,9 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
"Selected ID:
${value.id}
"
,
);
provider
.
selectedSubLocID
=
value
.
id
!;
value
.
id
!;
provider
.
selectedSubLocValue
=
value
.
subLocality
!;
value
.
subLocality
!;
print
(
"hfjkshfg
${provider.selectedSubLocID}
"
,
);
...
...
@@ -1637,44 +1633,44 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
dropdownSearchData:
DropdownSearchData
(
searchInnerWidgetHeight:
50
,
searchController:
provider
.
subLocSearchController
,
provider
.
subLocSearchController
,
searchInnerWidget:
Padding
(
padding:
const
EdgeInsets
.
all
(
8
,
),
child:
TextFormField
(
controller:
provider
.
subLocSearchController
,
provider
.
subLocSearchController
,
decoration:
InputDecoration
(
isDense:
true
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
8
,
),
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
8
,
),
hintText:
'Search Sub Locality...'
,
'Search Sub Locality...'
,
border:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
8
,
),
BorderRadius
.
circular
(
8
,
),
),
),
),
),
searchMatchFn:
(
item
,
searchValue
,
)
{
item
,
searchValue
,
)
{
return
item
.
value
?.
subLocality
?.
toLowerCase
()
.
contains
(
searchValue
.
toLowerCase
(),
)
??
?.
toLowerCase
()
.
contains
(
searchValue
.
toLowerCase
(),
)
??
false
;
},
),
...
...
@@ -1685,13 +1681,13 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
}
},
buttonStyleData:
ddtheme
.
buttonStyleData
,
ddtheme
.
buttonStyleData
,
iconStyleData:
ddtheme
.
iconStyleData
,
ddtheme
.
iconStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
ddtheme
.
dropdownStyleData
,
),
),
],
...
...
@@ -1863,7 +1859,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
provider
.
contectPersonAltMobController
,
"Alternative Mobile Number"
,
"Enter Alternative Mobile Number"
,
(
p0
)
{
(
p0
)
{
provider
.
updateAltMobile
(
p0
);
provider
.
checkInputsAPI
(
context
,
...
...
@@ -1925,12 +1921,12 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
bottomNavigationBar:
InkResponse
(
onTap:
provider
.
submitClickced
?
null
:
()
{
provider
.
submitClickced
=
true
;
provider
.
submitCommonAccountsAPI
(
context
,
widget
.
from
);
},
provider
.
submitClickced
?
null
:
()
{
provider
.
submitClickced
=
true
;
provider
.
submitCommonAccountsAPI
(
context
,
widget
.
from
);
},
child:
Container
(
height:
45
,
alignment:
Alignment
.
center
,
...
...
@@ -1941,18 +1937,18 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
borderRadius:
BorderRadius
.
circular
(
15
),
),
child:
provider
.
submitClickced
?
CircularProgressIndicator
.
adaptive
(
valueColor:
AlwaysStoppedAnimation
(
AppColors
.
white
),
)
:
Text
(
"Submit"
,
style:
TextStyle
(
fontSize:
15
,
fontFamily:
"JakartaMedium"
,
color:
Colors
.
white
,
),
),
provider
.
submitClickced
?
CircularProgressIndicator
.
adaptive
(
valueColor:
AlwaysStoppedAnimation
(
AppColors
.
white
),
)
:
Text
(
"Submit"
,
style:
TextStyle
(
fontSize:
15
,
fontFamily:
"JakartaMedium"
,
color:
Colors
.
white
,
),
),
),
),
);
...
...
lib/screens/commom/transactionDetails.dart
View file @
d2939607
...
...
@@ -103,7 +103,7 @@ class _TransactiondetailsState extends State<Transactiondetails> {
),
),
),
SizedBox
(
width:
10
),
SizedBox
(
width:
8
),
Expanded
(
flex:
3
,
child:
Container
(
...
...
@@ -117,15 +117,15 @@ class _TransactiondetailsState extends State<Transactiondetails> {
),
child:
Center
(
child:
Text
(
"₹
${details.amount ?? "-"}
"
,
"
₹
${details.amount ?? "-"}
"
,
maxLines:
2
,
overflow:
TextOverflow
.
ellipsis
,
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
1
4
,
fontSize:
1
2.8
,
color:
widget
.
type
==
"Credit
ed
"
widget
.
type
==
"Credit"
?
Color
(
0xFFEF3739
)
:
Color
(
0xFF0D9C00
),
),
...
...
@@ -359,6 +359,7 @@ class _TransactiondetailsState extends State<Transactiondetails> {
details
.
attachmentDirFilePath
??
""
,
downloadEnable:
false
,
),
),
);
...
...
lib/screens/crm/LeadListByMode.dart
View file @
d2939607
...
...
@@ -151,6 +151,11 @@ class _LeadlistbymodeState extends State<Leadlistbymode> {
InkResponse
(
onTap:
()
async
{
HapticFeedback
.
selectionClick
();
final
provider
=
Provider
.
of
<
Leadlistprovider
>(
context
,
listen:
false
);
// If lists are empty, fetch required data first (this will populate sources, teams, states, employees)
if
(
provider
.
sourcesList
.
isEmpty
||
provider
.
teamsList
.
isEmpty
||
provider
.
employeesList
.
isEmpty
)
{
await
provider
.
crmLeadListViewAPIFunction
(
context
,
widget
.
mode
);
}
_showFilterSheetNew
(
context
);
},
child:
SvgPicture
.
asset
(
...
...
@@ -158,6 +163,7 @@ class _LeadlistbymodeState extends State<Leadlistbymode> {
height:
25
,
),
),
],
),
0xFFFFFFFF
,
...
...
@@ -206,7 +212,36 @@ class _LeadlistbymodeState extends State<Leadlistbymode> {
provider
.
crmLeadList
[
index
].
leadid
,
),
),
);
).
then
((
_
)
async
{
final
provider
=
Provider
.
of
<
Leadlistprovider
>(
context
,
listen:
false
);
provider
.
resetPagination
();
if
(
widget
.
filter
!=
null
)
{
provider
.
crmLeadListAPIFunction
(
context
,
widget
.
mode
,
widget
.
filter
!.
status
,
widget
.
filter
!.
openStatus
,
""
,
""
,
""
,
""
,
""
,
);
}
else
{
provider
.
crmLeadListAPIFunction
(
context
,
widget
.
mode
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
);
}
});
},
child:
Container
(
padding:
EdgeInsets
.
symmetric
(
...
...
lib/screens/crm/addLeadsProspectsScreen.dart
View file @
d2939607
...
...
@@ -291,7 +291,7 @@ class _AddleadsprospectsscreenState extends State<Addleadsprospectsscreen> {
provider
.
companyNameController
,
"Company Name"
,
"Enter Company Name"
,
provider
.
onChangeCompanyName
,
(
value
)
=>
provider
.
onChangeCompanyName
(
context
,
value
)
,
TextInputType
.
name
,
false
,
null
,
...
...
@@ -301,21 +301,34 @@ class _AddleadsprospectsscreenState extends State<Addleadsprospectsscreen> {
),
errorWidget
(
context
,
provider
.
companynameError
),
textControllerWidget
(
context
,
provider
.
contactPersonNameController
,
"Contact Person Name"
,
"Enter Name"
,
(
value
)
=>
provider
.
onChangeContactPersonName
(
context
,
value
),
TextInputType
.
name
,
false
,
null
,
focusNodes
[
1
],
focusNodes
[
2
],
TextInputAction
.
next
,
),
//
textControllerWidget(
//
context,
//
provider.contactPersonNameController,
//
"Contact Person Name",
//
"Enter Name",
//
//
TextInputType.name,
//
false,
//
null,
//
focusNodes[1],
//
focusNodes[2],
//
TextInputAction.next,
//
),
errorWidget
(
context
,
provider
.
nameError
),
textControllerWidget
(
context
,
provider
.
contactPersonNameController
,
"Contact Person Name"
,
"Enter Name"
,
provider
.
onChangeContactPersonName
,
TextInputType
.
name
,
false
,
null
,
focusNodes
[
1
],
focusNodes
[
2
],
TextInputAction
.
next
),
errorWidget
(
context
,
provider
.
nameError
),
textControllerWidget
(
context
,
...
...
@@ -980,7 +993,7 @@ class _AddleadsprospectsscreenState extends State<Addleadsprospectsscreen> {
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
8
,
vertical:
6
,
),
decoration:
BoxDecoration
(
color:
Color
(
0xFFE6F6FF
),
...
...
@@ -1040,7 +1053,7 @@ class _AddleadsprospectsscreenState extends State<Addleadsprospectsscreen> {
color:
AppColors
.
grey_semi
,
),
),
SizedBox
(
height:
5
),
SizedBox
(
height:
2
),
DottedLine
(
dashGapLength:
4
,
dashGapColor:
Colors
.
white
,
...
...
@@ -1048,7 +1061,7 @@ class _AddleadsprospectsscreenState extends State<Addleadsprospectsscreen> {
dashLength:
2
,
lineThickness:
0.5
,
),
SizedBox
(
height:
5
),
SizedBox
(
height:
2
),
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
...
...
@@ -1062,7 +1075,7 @@ class _AddleadsprospectsscreenState extends State<Addleadsprospectsscreen> {
),
],
),
SizedBox
(
height:
5
),
SizedBox
(
height:
2
),
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
...
...
lib/screens/crm/crmDashboard.dart
View file @
d2939607
...
...
@@ -16,6 +16,7 @@ import 'package:generp/screens/crm/universalSearchScreen.dart';
import
'package:provider/provider.dart'
;
import
'package:generp/screens/screensExports.dart'
;
import
'../../Notifiers/crmProvider/LeadListProvider.dart'
;
import
'../../Notifiers/crmProvider/crmDashboardProvider.dart'
;
import
'../../Utils/app_colors.dart'
;
import
'../../Utils/commonServices.dart'
;
...
...
@@ -272,19 +273,48 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
await
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
Leadlistbymode
(
pageTitleName:
leadTitles
[
jndex
],
mode:
provider
.
allLeads
[
jndex
]
.
filter
!
.
mode
,
filter:
provider
.
allLeads
[
jndex
].
filter
!,
),
builder:
(
context
)
=>
Leadlistbymode
(
pageTitleName:
leadTitles
[
jndex
],
mode:
provider
.
allLeads
[
jndex
].
filter
!.
mode
,
filter:
provider
.
allLeads
[
jndex
].
filter
!,
),
),
);
).
then
((
_
)
async
{
// get the Leadlistprovider and reset filters + reload list
final
leadProv
=
Provider
.
of
<
Leadlistprovider
>(
context
,
listen:
false
);
// Clear selected filters
leadProv
.
resetForm
();
// Reset pagination and reload the list (same as your existing pattern)
leadProv
.
resetPagination
();
if
(
provider
.
allLeads
[
jndex
].
filter
!=
null
)
{
leadProv
.
crmLeadListAPIFunction
(
context
,
provider
.
allLeads
[
jndex
].
filter
!.
mode
,
provider
.
allLeads
[
jndex
].
filter
!.
status
,
provider
.
allLeads
[
jndex
].
filter
!.
openStatus
,
""
,
""
,
""
,
""
,
""
,
);
}
else
{
leadProv
.
crmLeadListAPIFunction
(
context
,
provider
.
allLeads
[
jndex
].
filter
!.
mode
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
);
}
});
}
}
if
(
leadTitles
[
jndex
]
==
"Pending Tasks"
)
{
...
...
lib/screens/crm/editAccountDetails.dart
View file @
d2939607
...
...
@@ -179,49 +179,45 @@ class _EditAccountDetailsState extends State<EditAccountDetails> {
),
),
SizedBox
(
height:
25
),
InkWell
(
onTap:
provider
.
isLoading
?
null
:
()
{
provider
.
isLoading
=
true
;
provider
.
crmLeadDetailsEditAccountSubmitAPIFunction
(
context
,
widget
.
accountID
,
provider
.
selectedSegmentId
,
provider
.
selectedTeamId
,
);
},
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
),
// Use ElevatedButton so we can easily disable it when invalid or loading
SizedBox
(
width:
double
.
infinity
,
child:
ElevatedButton
(
onPressed:
(
provider
.
isLoading
||
!
provider
.
isFormValid
)
?
null
:
()
{
// DO NOT set provider.isLoading here — provider will manage it.
provider
.
crmLeadDetailsEditAccountSubmitAPIFunction
(
context
,
widget
.
accountID
,
provider
.
selectedSegmentId
,
provider
.
selectedTeamId
,
);
},
style:
ElevatedButton
.
styleFrom
(
padding:
EdgeInsets
.
symmetric
(
vertical:
12.0
),
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
14.0
),
),
backgroundColor:
AppColors
.
app_blue
,
disabledBackgroundColor:
AppColors
.
app_blue
.
withOpacity
(
0.5
),
),
child:
Center
(
child:
provider
.
isLoading
?
CircularProgressIndicator
.
adaptive
(
valueColor:
AlwaysStoppedAnimation
(
AppColors
.
white
,
),
)
:
Text
(
"Submit"
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
color:
Colors
.
white
),
),
child:
provider
.
isLoading
?
SizedBox
(
height:
20
,
width:
20
,
child:
CircularProgressIndicator
.
adaptive
(
valueColor:
AlwaysStoppedAnimation
(
Colors
.
white
),
strokeWidth:
2
,
),
)
:
Text
(
"Submit"
,
style:
TextStyle
(
color:
Colors
.
white
),
),
),
),
],
),
),
...
...
lib/screens/finance/FileViewer.dart
View file @
d2939607
import
'dart:async'
;
import
'dart:io'
;
import
'package:cached_network_image/cached_network_image.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:open_filex/open_filex.dart'
;
import
'package:flutter_inappwebview/flutter_inappwebview.dart'
;
import
'package:flutter_svg/svg.dart'
;
import
'package:generp/Utils/commonWidgets.dart'
;
import
'package:path_provider/path_provider.dart'
;
import
'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'
;
import
'package:url_launcher/url_launcher.dart'
;
import
'package:flutter_pdfview/flutter_pdfview.dart'
;
...
...
@@ -17,7 +21,8 @@ import '../../Utils/app_colors.dart';
class
Fileviewer
extends
StatefulWidget
{
final
String
fileName
;
final
String
fileUrl
;
const
Fileviewer
({
super
.
key
,
required
this
.
fileName
,
required
this
.
fileUrl
});
final
bool
downloadEnable
;
// use this to show download button or not at
const
Fileviewer
({
super
.
key
,
required
this
.
fileName
,
required
this
.
fileUrl
,
required
this
.
downloadEnable
});
@override
State
<
Fileviewer
>
createState
()
=>
_FileviewerState
();
...
...
@@ -60,36 +65,70 @@ class _FileviewerState extends State<Fileviewer> {
@override
void
initState
()
{
pullToRefreshController
=
kIsWeb
?
null
:
PullToRefreshController
(
settings:
pullToRefreshSettings
,
onRefresh:
()
async
{
if
(
defaultTargetPlatform
==
TargetPlatform
.
android
)
{
webViewController
?.
reload
();
}
else
if
(
defaultTargetPlatform
==
TargetPlatform
.
iOS
)
{
webViewController
?.
loadUrl
(
urlRequest:
URLRequest
(
url:
await
webViewController
?.
getUrl
(),
),
);
}
},
);
super
.
initState
();
// Create pullToRefreshController only for non-web platforms
if
(!
kIsWeb
)
{
pullToRefreshController
=
PullToRefreshController
(
settings:
pullToRefreshSettings
,
onRefresh:
()
async
{
// Guard: don't run if widget disposed
if
(!
mounted
)
return
;
try
{
if
(
defaultTargetPlatform
==
TargetPlatform
.
android
)
{
await
webViewController
?.
reload
();
}
else
if
(
defaultTargetPlatform
==
TargetPlatform
.
iOS
)
{
final
currentUrl
=
await
webViewController
?.
getUrl
();
if
(
currentUrl
!=
null
)
{
await
webViewController
?.
loadUrl
(
urlRequest:
URLRequest
(
url:
currentUrl
),
);
}
}
}
catch
(
e
)
{
// ignore errors during refresh
}
finally
{
// ensure refresh animation stops even if reload fails
safeEndRefreshing
();
}
},
);
}
else
{
pullToRefreshController
=
null
;
}
// Initialize photo view controllers
_photoViewController
=
PhotoViewController
();
_scaleStateController
=
PhotoViewScaleStateController
();
super
.
initState
();
}
/// Safe helper to end pull-to-refresh only when mounted and controller exists.
void
safeEndRefreshing
()
{
if
(!
mounted
)
return
;
final
ctrl
=
pullToRefreshController
;
if
(
ctrl
!=
null
)
{
try
{
ctrl
.
endRefreshing
();
}
catch
(
e
)
{
// In some rare cases controller may already be disposed — ignore.
}
}
}
@override
void
dispose
()
{
// Dispose photo controllers first
_photoViewController
.
dispose
();
_scaleStateController
.
dispose
();
pullToRefreshController
?.
dispose
();
// Dispose pullToRefreshController and null it to avoid later use
try
{
pullToRefreshController
?.
dispose
();
}
catch
(
e
)
{
// ignore dispose errors
}
pullToRefreshController
=
null
;
webViewController
=
null
;
super
.
dispose
();
}
...
...
@@ -97,7 +136,50 @@ class _FileviewerState extends State<Fileviewer> {
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
resizeToAvoidBottomInset:
true
,
appBar:
appbarNew
(
context
,
"File Viewer"
,
0xFFFFFFFF
),
appBar:
AppBar
(
backgroundColor:
Color
(
0xFFFFFFFF
),
automaticallyImplyLeading:
false
,
title:
SizedBox
(
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
center
,
children:
[
InkResponse
(
onTap:
()
=>
Navigator
.
pop
(
context
,
true
),
child:
SvgPicture
.
asset
(
"assets/svg/appbar_back_button.svg"
,
height:
25
,
),
),
SizedBox
(
width:
10
),
InkResponse
(
onTap:
()
=>
Navigator
.
pop
(
context
,
true
),
child:
Text
(
"File Viewer"
,
style:
TextStyle
(
fontSize:
16
,
height:
1.1
,
fontFamily:
"JakartaSemiBold"
,
color:
AppColors
.
semi_black
,
),
),
),
Spacer
(),
/// DOWNLOAD BUTTON (NEW)
/// -----------------------------
if
(
widget
.
downloadEnable
)
IconButton
(
icon:
Icon
(
Icons
.
download_rounded
,
color:
AppColors
.
app_blue
),
onPressed:
()
async
{
await
_downloadFile
(
widget
.
fileUrl
,
widget
.
fileName
);
},
),
],
),
),
),
body:
SafeArea
(
child:
Center
(
child:
fileWidget
(
context
)
...
...
@@ -106,6 +188,190 @@ class _FileviewerState extends State<Fileviewer> {
);
}
Future
<
void
>
_downloadFile
(
String
url
,
String
fileName
)
async
{
try
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
"Downloading..."
)),
);
final
http
.
Response
response
=
await
http
.
get
(
Uri
.
parse
(
url
));
if
(
response
.
statusCode
==
200
)
{
final
bytes
=
response
.
bodyBytes
;
// Get storage directory
final
directory
=
await
getApplicationDocumentsDirectory
();
final
filePath
=
"
${directory.path}
/
$fileName
"
;
final
file
=
File
(
filePath
);
await
file
.
writeAsBytes
(
bytes
);
// Download success
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
"File downloaded successfully
\n
At this:
${directory.path}
"
)),
);
// ASK USER TO OPEN THE DOWNLOADED FILE
// -------------------------------------
showDialog
(
context:
context
,
builder:
(
context
)
{
return
Dialog
(
backgroundColor:
Colors
.
white
,
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
20
),
),
elevation:
0
,
child:
Container
(
padding:
const
EdgeInsets
.
all
(
24
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
20
),
boxShadow:
[
BoxShadow
(
color:
Colors
.
black
.
withOpacity
(
0.1
),
blurRadius:
20
,
offset:
const
Offset
(
0
,
4
),
),
],
),
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
children:
[
// Success Icon
Container
(
width:
60
,
height:
60
,
decoration:
BoxDecoration
(
color:
Colors
.
green
.
withOpacity
(
0.1
),
shape:
BoxShape
.
circle
,
),
child:
const
Icon
(
Icons
.
check_circle_rounded
,
color:
Colors
.
green
,
size:
36
,
),
),
const
SizedBox
(
height:
16
),
// Title
const
Text
(
"Download Complete"
,
style:
TextStyle
(
fontSize:
18
,
fontFamily:
"Plus Jakarta Sans"
,
fontWeight:
FontWeight
.
w700
,
color:
Colors
.
black87
,
),
),
const
SizedBox
(
height:
8
),
// Description
Text
(
"Do you want to open the file?"
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
fontSize:
14
,
fontFamily:
"Plus Jakarta Sans"
,
fontWeight:
FontWeight
.
w400
,
color:
Colors
.
grey
[
600
],
height:
1.4
,
),
),
const
SizedBox
(
height:
24
),
// Buttons Row
Row
(
children:
[
// Cancel Button
Expanded
(
child:
OutlinedButton
(
onPressed:
()
=>
Navigator
.
pop
(
context
),
style:
OutlinedButton
.
styleFrom
(
backgroundColor:
Colors
.
transparent
,
foregroundColor:
Colors
.
grey
[
600
],
side:
BorderSide
(
color:
Colors
.
grey
[
300
]!,
width:
1.5
,
),
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
12
),
),
padding:
const
EdgeInsets
.
symmetric
(
vertical:
14
),
elevation:
0
,
),
child:
Text
(
"Cancel"
,
style:
TextStyle
(
fontFamily:
"Plus Jakarta Sans"
,
fontWeight:
FontWeight
.
w600
,
fontSize:
14
,
color:
Colors
.
grey
[
700
],
),
),
),
),
const
SizedBox
(
width:
12
),
// Open Button
Expanded
(
child:
ElevatedButton
(
onPressed:
()
{
Navigator
.
pop
(
context
);
OpenFilex
.
open
(
filePath
);
},
style:
ElevatedButton
.
styleFrom
(
backgroundColor:
const
Color
(
0xFF008CDE
),
foregroundColor:
Colors
.
white
,
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
12
),
),
padding:
const
EdgeInsets
.
symmetric
(
vertical:
14
),
elevation:
0
,
shadowColor:
Colors
.
transparent
,
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
const
Icon
(
Icons
.
open_in_new
,
size:
18
),
const
SizedBox
(
width:
6
),
Text
(
"Open"
,
style:
TextStyle
(
fontFamily:
"Plus Jakarta Sans"
,
fontWeight:
FontWeight
.
w600
,
fontSize:
14
,
color:
Colors
.
white
,
),
),
],
),
),
),
],
),
],
),
),
);
},
);
}
else
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
"Failed to download file"
)),
);
}
}
catch
(
e
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
"Error:
$e
"
)),
);
}
}
Widget
fileWidget
(
BuildContext
context
)
{
final
extension
=
getFileExtension
(
widget
.
fileName
);
switch
(
extension
)
{
...
...
lib/screens/finance/PaymentRequestionListDetails.dart
View file @
d2939607
...
...
@@ -350,6 +350,7 @@ class _PaymentrequestionlistdetailsState
reqDet
.
attachmentDirFilePath
??
""
,
downloadEnable:
true
,
),
),
);
...
...
@@ -920,7 +921,7 @@ class _PaymentrequestionlistdetailsState
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
fontFamily:
"JakartaMedium"
,
fontSize:
1
4
,
fontSize:
1
3
,
color:
getTextColor
(
reqDet
.
status
),
),
),
...
...
@@ -1011,6 +1012,7 @@ class _PaymentrequestionlistdetailsState
reqDet
.
attachmentDirFilePath
??
""
,
downloadEnable:
true
,
),
),
);
...
...
@@ -1092,11 +1094,11 @@ class _PaymentrequestionlistdetailsState
decoration:
BoxDecoration
(
color:
Colors
.
white
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
alignment:
Alignment
.
bottomCenter
,
height:
8
0
,
height:
7
8
,
child:
Container
(
margin:
EdgeInsets
.
only
(
bottom:
10
),
alignment:
Alignment
.
center
,
height:
4
5
,
height:
4
2
,
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
...
...
@@ -1131,7 +1133,7 @@ class _PaymentrequestionlistdetailsState
"Reject"
,
style:
TextStyle
(
color:
AppColors
.
semi_black
,
fontSize:
1
4
,
fontSize:
1
2
,
),
),
),
...
...
@@ -1140,7 +1142,7 @@ class _PaymentrequestionlistdetailsState
),
),
),
SizedBox
(
width:
6
),
SizedBox
(
width:
4
),
if
([
"apr_lvl1"
,
...
...
@@ -1150,7 +1152,7 @@ class _PaymentrequestionlistdetailsState
SvgPicture
.
asset
(
"assets/svg/crm/vertical_line_ic.svg"
,
),
SizedBox
(
width:
6
),
SizedBox
(
width:
4
),
Expanded
(
child:
InkResponse
(
onTap:
()
{
...
...
@@ -1186,7 +1188,7 @@ class _PaymentrequestionlistdetailsState
"Approve"
,
style:
TextStyle
(
color:
AppColors
.
semi_black
,
fontSize:
1
4
,
fontSize:
1
2
,
),
),
),
...
...
@@ -1195,12 +1197,12 @@ class _PaymentrequestionlistdetailsState
),
),
),
SizedBox
(
width:
6
),
SizedBox
(
width:
4
),
]
else
if
(
widget
.
mode
==
"process"
)
...[
SvgPicture
.
asset
(
"assets/svg/crm/vertical_line_ic.svg"
,
),
SizedBox
(
width:
6
),
SizedBox
(
width:
5
),
Expanded
(
child:
InkResponse
(
onTap:
()
{
...
...
@@ -1231,13 +1233,13 @@ class _PaymentrequestionlistdetailsState
SvgPicture
.
asset
(
"assets/svg/finance/level_add_payment_ic.svg"
,
),
SizedBox
(
width:
5
),
SizedBox
(
width:
2
),
Center
(
child:
Text
(
"Add Payment"
,
style:
TextStyle
(
color:
AppColors
.
semi_black
,
fontSize:
1
4
,
fontSize:
1
2
,
),
),
),
...
...
@@ -1280,7 +1282,7 @@ class _PaymentrequestionlistdetailsState
"Edit Amount"
,
style:
TextStyle
(
color:
AppColors
.
semi_black
,
fontSize:
1
4
,
fontSize:
1
2
,
),
),
),
...
...
lib/screens/finance/financeDashboard.dart
View file @
d2939607
...
...
@@ -487,11 +487,11 @@ class _FinancedashboardState extends State<Financedashboard> {
},
child:
Container
(
padding:
EdgeInsets
.
symmetric
(
vertical:
5
,
vertical:
4.6
,
horizontal:
15
,
),
margin:
EdgeInsets
.
symmetric
(
vertical:
7
,
vertical:
5
,
horizontal:
5
,
),
decoration:
BoxDecoration
(
...
...
Prev
1
2
3
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