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
7ba7402c
Commit
7ba7402c
authored
Nov 21, 2025
by
Sai Srinivas
Committed by
Sai Srinivas
Nov 28, 2025
Browse files
Edit form and some fixes added
parent
d2939607
Changes
40
Hide whitespace changes
Inline
Side-by-side
lib/main.dart
View file @
7ba7402c
...
@@ -428,7 +428,8 @@ class MyApp extends StatelessWidget {
...
@@ -428,7 +428,8 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider
(
create:
(
_
)
=>
CasualLeaveHistoryProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
CasualLeaveHistoryProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
ContactProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
ContactProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
QrProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
QrProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
CrmNearByGeneratorsProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
EditCommonAccountProvider
()),
],
],
child:
Builder
(
child:
Builder
(
builder:
(
BuildContext
context
)
{
builder:
(
BuildContext
context
)
{
...
...
lib/screens/commom/accountsList.dart
View file @
7ba7402c
...
@@ -117,8 +117,18 @@ class _AccountslistState extends State<Accountslist> {
...
@@ -117,8 +117,18 @@ class _AccountslistState extends State<Accountslist> {
return
(
connection
==
"Online"
)
return
(
connection
==
"Online"
)
?
Platform
.
isAndroid
?
Platform
.
isAndroid
?
WillPopScope
(
?
WillPopScope
(
onWillPop:
()
=>
onBackPressed
(
context
),
onWillPop:
()
async
{
child:
SafeArea
(
onBackPressed
(
context
);
_refreshList
(
context
);
final
provider
=
Provider
.
of
<
Accountslistprovider
>(
context
,
listen:
false
);
provider
.
resetValues
();
provider
.
commonAccountListAPIFunction
(
context
);
// Return true or false depending on whether you want to allow the pop
return
true
;
// allow the back navigation
// return false; // prevent back navigation
},
child:
SafeArea
(
top:
false
,
top:
false
,
bottom:
true
,
bottom:
true
,
child:
_scaffold
(
context
),
child:
_scaffold
(
context
),
...
...
lib/screens/commom/accountsListDetails.dart
View file @
7ba7402c
...
@@ -8,11 +8,13 @@ import 'package:generp/Notifiers/commonProvider/accountDetailsProvider.dart';
...
@@ -8,11 +8,13 @@ import 'package:generp/Notifiers/commonProvider/accountDetailsProvider.dart';
import
'package:generp/Utils/app_colors.dart'
;
import
'package:generp/Utils/app_colors.dart'
;
import
'package:generp/Utils/commonServices.dart'
;
import
'package:generp/Utils/commonServices.dart'
;
import
'package:generp/Utils/commonWidgets.dart'
;
import
'package:generp/Utils/commonWidgets.dart'
;
import
'package:generp/screens/commom/editCommonAccount.dart'
;
import
'package:generp/screens/commom/transactionDetails.dart'
;
import
'package:generp/screens/commom/transactionDetails.dart'
;
import
'package:generp/screens/finance/submitPaymentRequestionListsByMode.dart'
;
import
'package:generp/screens/finance/submitPaymentRequestionListsByMode.dart'
;
import
'package:provider/provider.dart'
;
import
'package:provider/provider.dart'
;
import
'../../Models/commonModels/commonAccountdetailsResponse.dart'
;
import
'../../Models/commonModels/commonAccountdetailsResponse.dart'
;
import
'addCommonPayment.dart'
;
class
Accountslistdetails
extends
StatefulWidget
{
class
Accountslistdetails
extends
StatefulWidget
{
final
accountID
;
final
accountID
;
...
@@ -131,733 +133,762 @@ class _AccountslistdetailsState extends State<Accountslistdetails> {
...
@@ -131,733 +133,762 @@ class _AccountslistdetailsState extends State<Accountslistdetails> {
),
),
resizeToAvoidBottomInset:
true
,
resizeToAvoidBottomInset:
true
,
backgroundColor:
AppColors
.
scaffold_bg_color
,
backgroundColor:
AppColors
.
scaffold_bg_color
,
body:
SizedBox
(
body:
Builder
(
builder:
(
context
){
child:
SingleChildScrollView
(
if
(
provider
.
isLoading
)
{
child:
Column
(
return
const
Center
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
child:
CircularProgressIndicator
(
color:
Colors
.
blue
),
children:
[
);
Card
(
}
shape:
RoundedRectangleBorder
(
return
SizedBox
(
borderRadius:
BorderRadius
.
only
(
child:
SingleChildScrollView
(
bottomLeft:
Radius
.
circular
(
30
),
child:
Column
(
bottomRight:
Radius
.
circular
(
30
),
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Card
(
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
only
(
bottomLeft:
Radius
.
circular
(
30
),
bottomRight:
Radius
.
circular
(
30
),
),
),
),
),
elevation:
2
,
elevation:
2
,
child:
Column
(
child:
Column
(
children:
[
children:
[
Container
(
Container
(
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
Colors
.
white
,
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
vertical
(
borderRadius:
BorderRadius
.
vertical
(
bottom:
Radius
.
circular
(
30
),
bottom:
Radius
.
circular
(
30
),
),
),
// margin: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
padding:
EdgeInsets
.
symmetric
(
vertical:
10
,
horizontal:
10
,
),
child:
Column
(
children:
[
Row
(
children:
[
Expanded
(
flex:
1
,
child:
SizedBox
(
height:
50
,
width:
35
,
child:
SvgPicture
.
asset
(
"assets/svg/crm/lead_details_ic.svg"
,
),
),
),
SizedBox
(
width:
10
),
Expanded
(
flex:
5
,
child:
SizedBox
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
provider
.
accountDetails
.
name
??
"-"
,
style:
TextStyle
(
fontFamily:
"JakartaMedium"
,
fontSize:
14
,
color:
AppColors
.
semi_black
,
),
),
Text
(
provider
.
accountDetails
.
type
??
"-"
,
style:
TextStyle
(
fontFamily:
"JakartaMedium"
,
fontSize:
14
,
color:
AppColors
.
grey_semi
,
),
),
],
),
),
),
SizedBox
(
width:
10
),
],
),
),
Visibility
(
),
visible:
// margin: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
provider
.
showMoreDetails
?
true
:
false
,
padding:
EdgeInsets
.
symmetric
(
child:
Column
(
vertical:
10
,
horizontal:
10
,
),
child:
Column
(
children:
[
Row
(
children:
[
children:
[
Container
(
Expanded
(
padding:
EdgeInsets
.
symmetric
(
flex:
1
,
vertical:
4
,
child:
SizedBox
(
height:
50
,
width:
35
,
child:
SvgPicture
.
asset
(
"assets/svg/crm/lead_details_ic.svg"
,
),
),
),
child:
Row
(
),
children:
[
SizedBox
(
width:
10
),
Expanded
(
Expanded
(
flex:
3
,
flex:
5
,
child:
Text
(
child:
SizedBox
(
"Bank Details"
,
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
provider
.
accountDetails
.
name
??
"-"
,
style:
TextStyle
(
style:
TextStyle
(
fontFamily:
"JakartaMedium"
,
fontSize:
14
,
fontSize:
14
,
fontFamily:
"JakartaSemiBold"
,
color:
AppColors
.
semi_black
,
),
),
),
),
),
Text
(
Expanded
(
provider
.
accountDetails
.
type
??
"-"
,
flex:
6
,
style:
TextStyle
(
child:
DottedLine
(
fontFamily:
"JakartaMedium"
,
dashGapLength:
4
,
fontSize:
14
,
dashGapColor:
Colors
.
white
,
color:
AppColors
.
grey_semi
,
dashColor:
AppColors
.
grey_semi
,
),
dashLength:
2
,
lineThickness:
0.5
,
),
),
],
),
),
),
SizedBox
(
width:
2
),
Expanded
(
flex:
1
,
child:
InkResponse
(
onTap:
()
{
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
EditCommonAccountScreen
(
accountID:
widget
.
accountID
,))
).
then
((
_
)
async
{
var
prov
=
Provider
.
of
<
Accountdetailsprovider
>(
context
,
listen:
false
);
await
prov
.
accountdetailsAPIFunction
(
context
,
widget
.
accountID
);
});
},
child:
SizedBox
(
height:
25
,
width:
25
,
child:
SvgPicture
.
asset
(
"assets/svg/crm_contact_edit.svg"
,
),
),
]
,
)
,
),
),
),
),
...
List
.
generate
(
subHeadings1
.
length
,
(
j
)
{
],
return
Container
(
),
Visibility
(
visible:
provider
.
showMoreDetails
?
true
:
false
,
child:
Column
(
children:
[
Container
(
padding:
EdgeInsets
.
symmetric
(
padding:
EdgeInsets
.
symmetric
(
vertical:
7
,
vertical:
4
,
),
),
child:
Row
(
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
children:
[
Expanded
(
Expanded
(
flex:
3
,
child:
Text
(
child:
Text
(
headings1
[
j
]
,
"Bank Details"
,
style:
TextStyle
(
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
fontSize:
14
,
color:
AppColors
.
semi_black
,
fontFamily:
"JakartaSemiBold"
,
),
),
),
),
),
),
Expanded
(
Expanded
(
child:
Text
(
flex:
6
,
subHeadings1
[
j
]
==
""
child:
DottedLine
(
?
"-"
dashGapLength:
4
,
:
subHeadings1
[
j
],
dashGapColor:
Colors
.
white
,
style:
TextStyle
(
dashColor:
AppColors
.
grey_semi
,
fontSize:
14
,
dashLength:
2
,
color:
Color
(
0xFF818181
),
lineThickness:
0.5
,
),
),
),
),
),
],
],
),
),
);
}),
Container
(
padding:
EdgeInsets
.
symmetric
(
vertical:
4
,
),
),
child:
Row
(
...
List
.
generate
(
subHeadings1
.
length
,
(
j
)
{
children:
[
return
Container
(
Expanded
(
padding:
EdgeInsets
.
symmetric
(
flex:
3
,
vertical:
7
,
child:
Text
(
"Address Details"
,
style:
TextStyle
(
fontSize:
14
,
fontFamily:
"JakartaSemiBold"
,
),
),
),
),
Expanded
(
child:
Row
(
flex:
6
,
crossAxisAlignment:
child:
DottedLine
(
CrossAxisAlignment
.
start
,
dashGapLength:
4
,
children:
[
dashGapColor:
Colors
.
white
,
Expanded
(
dashColor:
AppColors
.
grey_semi
,
child:
Text
(
dashLength:
2
,
headings1
[
j
],
lineThickness:
0.5
,
style:
TextStyle
(
),
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
color:
AppColors
.
semi_black
,
),
),
),
Expanded
(
child:
Text
(
subHeadings1
[
j
]
==
""
?
"-"
:
subHeadings1
[
j
],
style:
TextStyle
(
fontSize:
14
,
color:
Color
(
0xFF818181
),
),
),
),
],
),
),
],
);
),
}),
),
Container
(
...
List
.
generate
(
subHeadings2
.
length
,
(
j
)
{
return
Container
(
padding:
EdgeInsets
.
symmetric
(
padding:
EdgeInsets
.
symmetric
(
vertical:
7
,
vertical:
4
,
),
),
child:
Row
(
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
children:
[
Expanded
(
Expanded
(
flex:
3
,
child:
Text
(
child:
Text
(
headings2
[
j
]
,
"Address Details"
,
style:
TextStyle
(
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
fontSize:
14
,
color:
AppColors
.
semi_black
,
fontFamily:
"JakartaSemiBold"
,
),
),
),
),
),
),
Expanded
(
Expanded
(
child:
Text
(
flex:
6
,
subHeadings2
[
j
]
==
""
child:
DottedLine
(
?
"-"
dashGapLength:
4
,
:
subHeadings2
[
j
],
dashGapColor:
Colors
.
white
,
style:
TextStyle
(
dashColor:
AppColors
.
grey_semi
,
fontSize:
14
,
dashLength:
2
,
color:
Color
(
0xFF818181
),
lineThickness:
0.5
,
),
),
),
),
),
],
],
),
),
);
}),
Container
(
padding:
EdgeInsets
.
symmetric
(
vertical:
4
,
),
),
child:
Row
(
...
List
.
generate
(
subHeadings2
.
length
,
(
j
)
{
children:
[
return
Container
(
Expanded
(
padding:
EdgeInsets
.
symmetric
(
flex:
3
,
vertical:
7
,
child:
Text
(
"More Details"
,
style:
TextStyle
(
fontSize:
14
,
fontFamily:
"JakartaSemiBold"
,
),
),
),
),
Expanded
(
child:
Row
(
flex:
6
,
crossAxisAlignment:
child:
DottedLine
(
CrossAxisAlignment
.
start
,
dashGapLength:
4
,
children:
[
dashGapColor:
Colors
.
white
,
Expanded
(
dashColor:
AppColors
.
grey_semi
,
child:
Text
(
dashLength:
2
,
headings2
[
j
],
lineThickness:
0.5
,
style:
TextStyle
(
),
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
color:
AppColors
.
semi_black
,
),
),
),
Expanded
(
child:
Text
(
subHeadings2
[
j
]
==
""
?
"-"
:
subHeadings2
[
j
],
style:
TextStyle
(
fontSize:
14
,
color:
Color
(
0xFF818181
),
),
),
),
],
),
),
],
);
),
}),
),
Container
(
...
List
.
generate
(
subHeadings3
.
length
,
(
j
)
{
return
Container
(
padding:
EdgeInsets
.
symmetric
(
padding:
EdgeInsets
.
symmetric
(
vertical:
7
,
vertical:
4
,
),
),
child:
Row
(
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
children:
[
Expanded
(
Expanded
(
flex:
3
,
child:
Text
(
child:
Text
(
headings3
[
j
]
,
"More Details"
,
style:
TextStyle
(
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
fontSize:
14
,
color:
AppColors
.
semi_black
,
fontFamily:
"JakartaSemiBold"
,
),
),
),
),
),
),
Expanded
(
Expanded
(
child:
Text
(
flex:
6
,
subHeadings3
[
j
]
==
""
child:
DottedLine
(
?
"-"
dashGapLength:
4
,
:
subHeadings3
[
j
],
dashGapColor:
Colors
.
white
,
style:
TextStyle
(
dashColor:
AppColors
.
grey_semi
,
fontSize:
14
,
dashLength:
2
,
color:
Color
(
0xFF818181
),
lineThickness:
0.5
,
),
),
),
),
),
],
],
),
),
);
),
}),
...
List
.
generate
(
subHeadings3
.
length
,
(
j
)
{
],
return
Container
(
padding:
EdgeInsets
.
symmetric
(
vertical:
7
,
),
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Expanded
(
child:
Text
(
headings3
[
j
],
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
color:
AppColors
.
semi_black
,
),
),
),
Expanded
(
child:
Text
(
subHeadings3
[
j
]
==
""
?
"-"
:
subHeadings3
[
j
],
style:
TextStyle
(
fontSize:
14
,
color:
Color
(
0xFF818181
),
),
),
),
],
),
);
}),
],
),
),
),
),
InkResponse
(
InkResponse
(
onTap:
()
async
{
onTap:
()
async
{
provider
.
showMoreDetails
=
provider
.
showMoreDetails
=
!
provider
.
showMoreDetails
;
!
provider
.
showMoreDetails
;
},
},
child:
Container
(
child:
Container
(
padding:
EdgeInsets
.
symmetric
(
vertical:
5
),
padding:
EdgeInsets
.
symmetric
(
vertical:
5
),
child:
Row
(
child:
Row
(
crossAxisAlignment:
crossAxisAlignment:
CrossAxisAlignment
.
center
,
CrossAxisAlignment
.
center
,
mainAxisAlignment:
MainAxisAlignment
.
center
,
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
children:
[
Text
(
Text
(
provider
.
showMoreDetails
provider
.
showMoreDetails
?
"Hide Details"
?
"Hide Details"
:
"View Details"
,
:
"View Details"
,
style:
TextStyle
(
style:
TextStyle
(
fontFamily:
"JakartaMedium"
,
fontFamily:
"JakartaMedium"
,
fontSize:
14
,
fontSize:
14
,
color:
AppColors
.
app_blue
,
color:
AppColors
.
app_blue
,
),
),
),
),
Transform
.
flip
(
Transform
.
flip
(
flip
Y:
flipY:
provider
.
showMoreDetails
provider
.
showMoreDetails
?
true
?
true
:
false
,
:
false
,
child:
SvgPicture
.
asset
(
child:
SvgPicture
.
asset
(
"assets/svg/arrow_dropdown.svg"
,
"assets/svg/arrow_dropdown.svg"
,
height:
25
,
height
:
2
5
,
width
:
2
0
,
width:
20
,
color:
AppColors
.
app_blue
,
color:
AppColors
.
app_blue
,
)
,
),
),
)
,
]
,
]
,
)
,
),
),
),
),
)
,
]
,
]
,
)
,
),
),
)
,
]
,
]
,
)
,
),
),
),
Container
(
Container
(
margin:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
margin:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
Colors
.
white
,
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
),
borderRadius:
BorderRadius
.
circular
(
16
),
),
),
child:
Column
(
child:
Column
(
children:
[
children:
[
Container
(
Container
(
padding:
EdgeInsets
.
symmetric
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
horizontal:
10
,
vertical:
15
,
vertical:
15
,
),
),
margin:
EdgeInsets
.
symmetric
(
margin:
EdgeInsets
.
symmetric
(
horizontal:
10
,
horizontal:
10
,
vertical:
15
,
vertical:
15
,
),
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
Color
(
0xFFEDF7FF
),
color:
Color
(
0xFFEDF7FF
),
borderRadius:
BorderRadius
.
circular
(
16
),
borderRadius:
BorderRadius
.
circular
(
16
),
),
),
child:
Column
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
center
,
crossAxisAlignment:
CrossAxisAlignment
.
center
,
children:
[
children:
[
Row
(
Row
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
children:
[
Text
(
Text
(
provider
.
balanceDetails
.
balance
??
"-"
,
provider
.
balanceDetails
.
balance
??
"-"
,
style:
TextStyle
(
fontSize:
20
,
fontFamily:
"JakartaMedium"
,
color:
AppColors
.
app_blue
,
),
),
],
),
Container
(
padding:
EdgeInsets
.
only
(
top:
5
),
child:
Text
(
"Total Balance"
,
maxLines:
1
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
20
,
fontSize:
14
,
fontFamily:
"Jakarta
Medium
"
,
fontFamily:
"Jakarta
Regular
"
,
color:
AppColors
.
app_blue
,
color:
AppColors
.
semi_black
,
),
),
),
),
],
),
Container
(
padding:
EdgeInsets
.
only
(
top:
5
),
child:
Text
(
"Total Balance"
,
maxLines:
1
,
style:
TextStyle
(
fontSize:
14
,
fontFamily:
"JakartaRegular"
,
color:
AppColors
.
semi_black
,
),
),
),
)
,
]
,
]
,
)
,
),
),
),
Row
(
Row
(
children:
[
children:
[
...
List
.
generate
(
2
,
(
jj
)
{
...
List
.
generate
(
2
,
(
jj
)
{
final
texts
=
[
"Credited"
,
"Debited"
];
final
texts
=
[
"Credited"
,
"Debited"
];
final
heads
=
[
final
heads
=
[
provider
.
balanceDetails
.
totalCredit
??
"-"
,
provider
.
balanceDetails
.
totalCredit
??
"-"
,
provider
.
balanceDetails
.
totalDebit
??
"-"
,
provider
.
balanceDetails
.
totalDebit
??
"-"
,
];
];
final
svgs
=
[
final
svgs
=
[
"assets/svg/finance/cred_debit_ic.svg"
,
"assets/svg/finance/cred_debit_ic.svg"
,
"assets/svg/finance/deb_credit_ic.svg"
,
"assets/svg/finance/deb_credit_ic.svg"
,
];
];
return
Expanded
(
return
Expanded
(
child:
Container
(
child:
Container
(
padding:
EdgeInsets
.
symmetric
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
horizontal:
10
,
vertical:
15
,
vertical:
15
,
),
),
margin:
EdgeInsets
.
symmetric
(
margin:
EdgeInsets
.
symmetric
(
horizontal:
10
,
horizontal:
10
,
vertical:
15
,
vertical:
15
,
),
decoration:
BoxDecoration
(
color:
texts
[
jj
]
==
"Credited"
?
Color
(
0xFFFFEFEF
)
:
Color
(
0xFFE7FFE5
),
borderRadius:
BorderRadius
.
circular
(
16
),
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
heads
[
jj
]
??
"-"
,
maxLines:
2
,
style:
TextStyle
(
fontSize:
20
,
color:
texts
[
jj
]
==
"Credited"
?
Color
(
0xFFEF3739
)
:
Color
(
0xFF0D9C00
),
fontFamily:
"JakartaMedium"
,
),
),
Container
(
padding:
EdgeInsets
.
only
(
top:
5
),
child:
Row
(
children:
[
Expanded
(
flex:
3
,
child:
Text
(
texts
[
jj
]
??
"-"
,
maxLines:
1
,
style:
TextStyle
(
fontSize:
14
,
fontFamily:
"JakartaRegular"
,
color:
AppColors
.
semi_black
,
),
),
),
Expanded
(
flex:
1
,
child:
SvgPicture
.
asset
(
svgs
[
jj
]),
),
],
),
),
],
),
),
),
decoration:
BoxDecoration
(
);
color:
}),
texts
[
jj
]
==
"Credited"
],
?
Color
(
0xFFFFEFEF
)
),
:
Color
(
0xFFE7FFE5
),
],
borderRadius:
BorderRadius
.
circular
(
16
),
),
),
ListView
.
builder
(
physics:
NeverScrollableScrollPhysics
(),
shrinkWrap:
true
,
itemCount:
provider
.
ledgerList
.
length
,
itemBuilder:
(
context
,
index
)
{
double
runningBalance
=
0
;
int
currentIndex
=
provider
.
ledgerList
.
indexOf
(
provider
.
ledgerList
[
index
],
);
for
(
var
i
=
0
;
i
<=
currentIndex
;
i
++)
{
var
ledgerItem
=
provider
.
ledgerList
[
i
];
double
credit
=
double
.
tryParse
(
ledgerItem
.
creditAmount
.
toString
(),
)
??
0
;
double
debit
=
double
.
tryParse
(
ledgerItem
.
debitAmount
.
toString
(),
)
??
0
;
runningBalance
+=
(
debit
-
credit
);
}
return
InkResponse
(
onTap:
()
async
{
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
Transactiondetails
(
paymentID:
provider
.
ledgerList
[
index
].
refId
,
type:
provider
.
ledgerList
[
index
].
type
,
description:
provider
.
ledgerList
[
index
].
description
,
),
),
);
},
child:
Container
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
,
),
margin:
EdgeInsets
.
symmetric
(
vertical:
5
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
),
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Expanded
(
flex:
1
,
child:
SizedBox
(
child:
provider
.
ledgerList
[
index
].
type
==
"Credit"
?
SvgPicture
.
asset
(
"assets/svg/finance/debited_filled_ic.svg"
,
height:
45
,
width:
45
,
fit:
BoxFit
.
contain
,
)
:
SvgPicture
.
asset
(
"assets/svg/finance/credited_filled_ic.svg"
,
height:
45
,
width:
45
,
fit:
BoxFit
.
contain
,
),
),
),
child:
Column
(
),
crossAxisAlignment:
SizedBox
(
width:
10
),
CrossAxisAlignment
.
start
,
Expanded
(
children:
[
flex:
8
,
Text
(
child:
SizedBox
(
heads
[
jj
]
??
"-"
,
child:
Column
(
maxLines:
2
,
children:
[
style:
TextStyle
(
Row
(
fontSize:
20
,
crossAxisAlignment:
color:
CrossAxisAlignment
.
start
,
texts
[
jj
]
==
"Credited"
?
Color
(
0xFFEF3739
)
:
Color
(
0xFF0D9C00
),
fontFamily:
"JakartaMedium"
,
),
),
Container
(
padding:
EdgeInsets
.
only
(
top:
5
),
child:
Row
(
children:
[
children:
[
Expanded
(
flex:
5
,
child:
SizedBox
(
child:
Text
(
provider
.
ledgerList
[
index
]
.
description
??
"-"
,
maxLines:
2
,
overflow:
TextOverflow
.
ellipsis
,
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
),
),
),
),
Spacer
(),
Expanded
(
Expanded
(
flex:
3
,
flex:
3
,
child:
Text
(
child:
SizedBox
(
texts
[
jj
]
??
"-"
,
child:
RichText
(
maxLines:
1
,
maxLines:
1
,
style:
TextStyle
(
textAlign:
TextAlign
.
right
,
fontSize:
14
,
overflow:
TextOverflow
.
ellipsis
,
fontFamily:
"JakartaRegular"
,
text:
TextSpan
(
color:
AppColors
.
semi_black
,
children:
[
TextSpan
(
text:
provider
.
ledgerList
[
index
]
.
type
==
"Credit"
?
"-"
:
"+"
,
style:
TextStyle
(
color:
provider
.
ledgerList
[
index
]
.
type
==
"Credit"
?
Color
(
0xFFEF3739
,
)
:
Color
(
0xFF0D9C00
,
),
fontSize:
14
,
fontFamily:
"JakartaRegular"
,
),
),
TextSpan
(
text:
"₹
${provider.ledgerList[index].type == "Credit" ? "${provider.ledgerList[index].creditAmount}
"
:
"
${provider.ledgerList[index].debitAmount}
"
}
",
style: TextStyle(
color:
provider
.ledgerList[index]
.type ==
"
Credit
"
? Color(
0xFFEF3739,
)
: Color(
0xFF0D9C00,
),
fontSize: 14,
fontFamily:
"
JakartaRegular
",
),
),
],
),
),
),
),
),
),
),
],
),
SizedBox(height: 7),
Row(
children: [
Expanded(
Expanded(
flex:
1
,
flex: 5,
child:
SvgPicture
.
asset
(
svgs
[
jj
]),
child: SizedBox(
child: Text(
provider
.ledgerList[index]
.date ??
"
-
",
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontFamily: "
JakartaRegular
",
color: AppColors.grey_semi,
fontSize: 12,
),
),
),
),
),
Spacer(),
// Expanded(
// flex: 3,
// child: SizedBox(
// child: RichText(
// maxLines: 1,
// textAlign: TextAlign.right,
// overflow: TextOverflow.ellipsis,
// text: TextSpan(
// children: [
// TextSpan(
// text: "
Bal:
",
// style: TextStyle(
// color:
// AppColors
// .semi_black,
// fontSize: 12,
// fontFamily:
// "
JakartaRegular
",
// ),
// ),
// TextSpan(
// text: "
₹
$runningBalance
",
// style: TextStyle(
// color:
// AppColors.grey_semi,
// fontSize: 12,
// fontFamily:
// "
JakartaMedium
",
// ),
// ),
// ],
// ),
// ),
// ),
// ),
],
],
),
),
)
,
]
,
]
,
)
,
),
),
),
),
);
],
}
),
),
]
,
)
,
)
,
)
;
]
,
}
,
),
),
),
if ([
"
Vendor
",
ListView
.
builder
(
"
Customer
",
physics:
NeverScrollableScrollPhysics
(),
].contains(provider.accountDetails.type)) ...[
shrinkWrap:
true
,
InkWell(
itemCount:
provider
.
ledgerList
.
length
,
onTap: () {
itemBuilder:
(
context
,
index
)
{
double
runningBalance
=
0
;
int
currentIndex
=
provider
.
ledgerList
.
indexOf
(
provider
.
ledgerList
[
index
],
);
for
(
var
i
=
0
;
i
<=
currentIndex
;
i
++)
{
var
ledgerItem
=
provider
.
ledgerList
[
i
];
double
credit
=
double
.
tryParse
(
ledgerItem
.
creditAmount
.
toString
(),
)
??
0
;
double
debit
=
double
.
tryParse
(
ledgerItem
.
debitAmount
.
toString
(),
)
??
0
;
runningBalance
+=
(
debit
-
credit
);
}
return
InkResponse
(
onTap:
()
async
{
Navigator.push(
Navigator.push(
context,
context,
MaterialPageRoute(
MaterialPageRoute(
builder:
builder:
(
context
)
=>
Transactiondetails
(
(context) => Submitpaymentrequestionlistsbymode(
paymentID:
provider
.
ledgerList
[
index
].
refId
,
mode: "
other
",
type:
provider
.
ledgerList
[
index
].
type
,
pageTitleName: "
Add
Payment
Request
(
Other
)
",
description:
accountId: provider.accountDetails.id!,
provider
.
ledgerList
[
index
].
description
,
),
),
),
),
);
);
},
},
child: Container(
child: Container(
padding:
EdgeInsets
.
symmetric
(
alignment: Alignment.center,
horizontal:
10
,
height: 45,
vertical:
10
,
margin: EdgeInsets.only(
left: 5.0,
right: 5.0,
top: 5.0,
bottom: 5.0,
),
),
margin:
EdgeInsets
.
symmetric
(
vertical:
5
),
decoration: BoxDecoration(
decoration: BoxDecoration(
color:
Colors
.
white
,
color:
App
Colors.
app_blue, //1487C9
borderRadius:
BorderRadius
.
circular
(
1
6
),
borderRadius: BorderRadius.circular(1
5.0
),
),
),
child:
Row
(
child: Center(
mainAxisAlignment:
MainAxisAlignment
.
start
,
child: Text(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
"
Add
Payment
Request
(
Other
)
",
children:
[
textAlign: TextAlign.center,
Expanded
(
style: TextStyle(
flex:
1
,
color: Colors.white,
child:
SizedBox
(
fontFamily: "
JakartaMedium
",
child:
fontSize: 15,
provider
.
ledgerList
[
index
].
type
==
"Credit"
?
SvgPicture
.
asset
(
"assets/svg/finance/debited_filled_ic.svg"
,
height:
45
,
width:
45
,
fit:
BoxFit
.
contain
,
)
:
SvgPicture
.
asset
(
"assets/svg/finance/credited_filled_ic.svg"
,
height:
45
,
width:
45
,
fit:
BoxFit
.
contain
,
),
),
),
SizedBox
(
width:
10
),
Expanded
(
flex:
8
,
child:
SizedBox
(
child:
Column
(
children:
[
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Expanded
(
flex:
5
,
child:
SizedBox
(
child:
Text
(
provider
.
ledgerList
[
index
]
.
description
??
"-"
,
maxLines:
2
,
overflow:
TextOverflow
.
ellipsis
,
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
),
),
),
),
Spacer
(),
Expanded
(
flex:
3
,
child:
SizedBox
(
child:
RichText
(
maxLines:
1
,
textAlign:
TextAlign
.
right
,
overflow:
TextOverflow
.
ellipsis
,
text:
TextSpan
(
children:
[
TextSpan
(
text:
provider
.
ledgerList
[
index
]
.
type
==
"Credit"
?
"-"
:
"+"
,
style:
TextStyle
(
color:
provider
.
ledgerList
[
index
]
.
type
==
"Credit"
?
Color
(
0xFFEF3739
,
)
:
Color
(
0xFF0D9C00
,
),
fontSize:
14
,
fontFamily:
"JakartaRegular"
,
),
),
TextSpan
(
text:
"₹
${provider.ledgerList[index].type == "Credit" ? "${provider.ledgerList[index].creditAmount}
"
:
"
${provider.ledgerList[index].debitAmount}
"
}
",
style: TextStyle(
color:
provider
.ledgerList[index]
.type ==
"
Credit
"
? Color(
0xFFEF3739,
)
: Color(
0xFF0D9C00,
),
fontSize: 14,
fontFamily:
"
JakartaRegular
",
),
),
],
),
),
),
),
],
),
SizedBox(height: 7),
Row(
children: [
Expanded(
flex: 5,
child: SizedBox(
child: Text(
provider
.ledgerList[index]
.date ??
"
-
",
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontFamily: "
JakartaRegular
",
color: AppColors.grey_semi,
fontSize: 12,
),
),
),
),
Spacer(),
Expanded(
flex: 3,
child: SizedBox(
child: RichText(
maxLines: 1,
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
text: TextSpan(
children: [
TextSpan(
text: "
Bal:
",
style: TextStyle(
color:
AppColors
.semi_black,
fontSize: 12,
fontFamily:
"
JakartaRegular
",
),
),
TextSpan(
text: "
₹
$runningBalance
",
style: TextStyle(
color:
AppColors.grey_semi,
fontSize: 12,
fontFamily:
"
JakartaMedium
",
),
),
],
),
),
),
),
],
),
],
),
),
),
),
],
),
),
);
},
),
if ([
"
Vendor
",
"
Customer
",
].contains(provider.accountDetails.type)) ...[
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder:
(context) => Submitpaymentrequestionlistsbymode(
mode: "
other
",
pageTitleName: "
Add
Payment
Request
(
Other
)
",
accountId: provider.accountDetails.id!,
),
),
);
},
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(15.0),
),
child: Center(
child: Text(
"
Add
Payment
Request
(
Other
)
",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontFamily: "
JakartaMedium
",
fontSize: 15,
),
),
),
),
),
),
),
),
)
,
]
,
],
],
]
,
)
,
),
),
),
);
),
}
)
);
);
},
},
);
);
...
...
lib/screens/commom/addCommonPayment.dart
View file @
7ba7402c
...
@@ -31,7 +31,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
...
@@ -31,7 +31,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
Dropdowntheme
ddtheme
=
Dropdowntheme
();
Dropdowntheme
ddtheme
=
Dropdowntheme
();
int
_currentStep
=
0
;
int
_currentStep
=
0
;
final
_formKey
=
GlobalKey
<
FormState
>();
final
_formKey
=
GlobalKey
<
FormState
>();
List
<
FocusNode
>
focusNodes
=
List
.
generate
(
2
0
,
(
index
)
=>
FocusNode
());
final
List
<
FocusNode
>
focusNodes
=
List
.
generate
(
3
0
,
(
index
)
=>
FocusNode
());
Map
_source
=
{
ConnectivityResult
.
mobile
:
true
};
Map
_source
=
{
ConnectivityResult
.
mobile
:
true
};
final
MyConnectivity
_connectivity
=
MyConnectivity
.
instance
;
final
MyConnectivity
_connectivity
=
MyConnectivity
.
instance
;
...
@@ -274,7 +274,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
...
@@ -274,7 +274,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
// custom continue logic:
// custom continue logic:
if
(
_currentStep
==
0
)
{
if
(
_currentStep
==
0
)
{
// validate step1 via provider
// validate step1 via provider
if
(
provider
.
validateStep1
())
{
if
(
provider
.
validateStep1
(
context
))
{
setState
(()
=>
_currentStep
=
1
);
setState
(()
=>
_currentStep
=
1
);
}
else
{
}
else
{
// show error (provider sets errors and notifies)
// show error (provider sets errors and notifies)
...
@@ -337,7 +337,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
...
@@ -337,7 +337,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
setState
(()
=>
_currentStep
=
0
);
setState
(()
=>
_currentStep
=
0
);
}
else
if
(
value
==
1
)
{
}
else
if
(
value
==
1
)
{
// user wants to jump to step 1 - ensure step 0 valid
// user wants to jump to step 1 - ensure step 0 valid
if
(
provider
.
validateStep1
())
{
if
(
provider
.
validateStep1
(
context
))
{
setState
(()
=>
_currentStep
=
1
);
setState
(()
=>
_currentStep
=
1
);
}
else
{
}
else
{
provider
.
notifyListeners
();
provider
.
notifyListeners
();
...
@@ -345,7 +345,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
...
@@ -345,7 +345,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
}
}
}
else
if
(
value
==
2
)
{
}
else
if
(
value
==
2
)
{
// allow jump if step0 valid; step1 optional
// allow jump if step0 valid; step1 optional
if
(
provider
.
validateStep1
())
{
if
(
provider
.
validateStep1
(
context
))
{
setState
(()
=>
_currentStep
=
2
);
setState
(()
=>
_currentStep
=
2
);
}
else
{
}
else
{
provider
.
notifyListeners
();
provider
.
notifyListeners
();
...
@@ -353,7 +353,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
...
@@ -353,7 +353,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
}
}
}
else
if
(
value
==
3
)
{
}
else
if
(
value
==
3
)
{
// final - require step0 valid
// final - require step0 valid
if
(!
provider
.
validateStep1
())
{
if
(!
provider
.
validateStep1
(
context
))
{
provider
.
notifyListeners
();
provider
.
notifyListeners
();
setState
(()
=>
_currentStep
=
0
);
setState
(()
=>
_currentStep
=
0
);
return
;
return
;
...
@@ -440,9 +440,12 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
...
@@ -440,9 +440,12 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
"Company Name"
,
"Company Name"
,
"Enter Company Name"
,
"Enter Company Name"
,
(
p0
)
{
(
p0
)
{
provider
.
updateName
(
p0
);
provider
.
updateName
(
p0
);
provider
.
checkInputsAPI
(
context
,
"name"
,
provider
.
nameController
.
text
);
provider
.
checkInputsAPI
(
context
,
"name"
,
provider
.
nameController
.
text
);
},
// Recompare with GST response if exists
provider
.
recheckNameWithGst
();
},
TextInputType
.
text
,
TextInputType
.
text
,
false
,
false
,
null
,
null
,
...
@@ -708,52 +711,120 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
...
@@ -708,52 +711,120 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
child:
Column
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
children:
[
// GST field - if provided, validate and autofill address; compare company name
// GST field (unique focus node 9). Only one GST widget here.
textControllerWidget
(
Text
(
"GST Number"
),
context
,
const
SizedBox
(
height:
6
),
provider
.
gstNumberController
,
TextFormField
(
"GST Number"
,
controller:
provider
.
gstNumberController
,
"Enter GST Number"
,
focusNode:
focusNodes
[
9
],
(
val
)
async
{
textInputAction:
TextInputAction
.
done
,
// when user types, just update; validation on field submit
keyboardType:
TextInputType
.
text
,
provider
.
gstNumberController
.
text
=
val
;
style:
TextStyle
(
provider
.
notifyListeners
();
height:
1.2
,
color:
Colors
.
black87
,
backgroundColor:
AppColors
.
text_field_color
,
),
decoration:
InputDecoration
(
hintText:
"Enter GST Number"
,
filled:
true
,
hintStyle:
TextStyle
(
height:
1.2
,
backgroundColor:
AppColors
.
text_field_color
,
color:
AppColors
.
grey_semi
,
),
fillColor:
AppColors
.
text_field_color
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
14
,
vertical:
14
),
enabledBorder:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
16
),
borderSide:
BorderSide
.
none
,
),
focusedBorder:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
16
),
borderSide:
BorderSide
.
none
,
),
errorBorder:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
16
),
borderSide:
BorderSide
.
none
,
),
focusedErrorBorder:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
16
),
borderSide:
BorderSide
.
none
,
),
),
onChanged:
(
value
)
{
// only clear GST error when user edits
provider
.
updateGSTNumber
(
value
);
final
trimmed
=
value
.
trim
();
if
(
trimmed
.
isEmpty
)
{
// user cleared GST -> clear response + errors
provider
.
gstResponse
=
null
;
provider
.
gstNumberError
=
null
;
provider
.
nameError
=
null
;
// also clear mismatch error, if any
provider
.
notifyListeners
();
return
;
}
// OPTIONAL: auto-validate once full 15-char GST typed
if
(
trimmed
.
length
==
15
)
{
provider
.
checkAndApplyGst
(
context
,
trimmed
);
}
},
onFieldSubmitted:
(
value
)
async
{
final
trimmed
=
value
.
trim
();
if
(
trimmed
.
isNotEmpty
)
{
await
provider
.
checkAndApplyGst
(
context
,
trimmed
);
}
// move focus to Bank Account Number
FocusScope
.
of
(
context
).
requestFocus
(
focusNodes
[
10
]);
},
},
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
),
const
SizedBox
(
height:
4
),
errorWidget
(
context
,
provider
.
gstNumberError
),
errorWidget
(
context
,
provider
.
gstNumberError
),
// Bank Account Number
const
SizedBox
(
height:
4
),
// errorWidget(context, provider.gstNumberError),
// Bank Account Number (use same style as other fields)
textControllerWidget
(
textControllerWidget
(
context
,
context
,
provider
.
bankAcNumberController
,
provider
.
bankAcNumberController
,
"Bank Account Number"
,
"Bank Account Number"
,
"Enter Bank Account Number"
,
"Enter Bank Account Number"
,
(
p0
)
{
(
p0
)
{
// update provider value and trigger bank validation if IFSC already present
provider
.
updateNumber
(
p0
);
provider
.
updateNumber
(
p0
);
//
attempt validation only when
IFSC
p
re
sent
//
If account entered but IFSC empty -> provider will set
IFSC re
quired error via checkAndApplyBank
if
(
provider
.
bankIfscCotroller
.
text
.
trim
().
isNotEmpty
)
{
if
(
provider
.
bankIfscCotroller
.
text
.
trim
().
isNotEmpty
)
{
_validateBankIfNeeded
(
provider
);
// validate once IFSC is present
provider
.
checkAndApplyBank
(
context
,
p0
.
trim
());
}
else
{
// If account present but IFSC empty, show IFSC required error
if
(
p0
.
trim
().
isNotEmpty
)
{
provider
.
bankIFSCError
=
"IFSC is required when account number is entered"
;
provider
.
notifyListeners
();
}
else
{
provider
.
bankIFSCError
=
null
;
provider
.
notifyListeners
();
}
}
}
},
},
TextInputType
.
number
,
TextInputType
.
number
,
false
,
false
,
FilteringTextInputFormatter
.
digitsOnly
,
FilteringTextInputFormatter
.
digitsOnly
,
focusNodes
[
10
],
focusNodes
[
10
],
// bank account unique
focusNodes
[
11
],
focusNodes
[
8
],
// move to IFSC next
TextInputAction
.
next
,
TextInputAction
.
next
,
),
),
const
SizedBox
(
height:
4
),
errorWidget
(
context
,
provider
.
bankAcNumberError
),
errorWidget
(
context
,
provider
.
bankAcNumberError
),
// IFSC
// Bank IFSC
textControllerWidget
(
textControllerWidget
(
context
,
context
,
provider
.
bankIfscCotroller
,
provider
.
bankIfscCotroller
,
...
@@ -761,28 +832,46 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
...
@@ -761,28 +832,46 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
"Enter Bank IFSC"
,
"Enter Bank IFSC"
,
(
p0
)
{
(
p0
)
{
provider
.
updateIFSC
(
p0
);
provider
.
updateIFSC
(
p0
);
//
validate
IFSC format
locally; if good and account present, trigger server validation
//
local
IFSC format
check
if
(
_isIfscValidFormat
(
p0
)
&&
provider
.
bankAcNumberController
.
text
.
trim
().
isNotEmpty
)
{
final
reg
=
RegExp
(
r'^[A-Za-z]{4}0[A-Za-z0-9]{6}$'
);
_validateBankIfNeeded
(
provider
);
if
(
p0
.
trim
().
isEmpty
)
{
}
else
{
// if account exists and IFSC empty -> show required error
if
(
p
0
.
trim
().
isNotEmpty
&&
!
_isIfscValidFormat
(
p0
)
)
{
if
(
p
rovider
.
bankAcNumberController
.
text
.
trim
().
isNotEmpty
)
{
provider
.
bankIFSCError
=
"I
nvalid IFSC format
"
;
provider
.
bankIFSCError
=
"I
FSC is required when account number is entered
"
;
provider
.
notifyListeners
();
provider
.
notifyListeners
();
}
else
{
}
else
{
provider
.
bankIFSCError
=
null
;
provider
.
bankIFSCError
=
null
;
provider
.
notifyListeners
();
provider
.
notifyListeners
();
}
}
return
;
}
if
(!
reg
.
hasMatch
(
p0
.
trim
()))
{
provider
.
bankIFSCError
=
"Invalid IFSC format"
;
provider
.
notifyListeners
();
return
;
}
else
{
provider
.
bankIFSCError
=
null
;
provider
.
notifyListeners
();
}
// if acc and IFSC both present and valid -> call bank API
if
(
provider
.
bankAcNumberController
.
text
.
trim
().
isNotEmpty
)
{
provider
.
checkAndApplyBank
(
context
,
provider
.
bankAcNumberController
.
text
.
trim
());
}
}
},
},
TextInputType
.
text
,
TextInputType
.
text
,
false
,
false
,
null
,
null
,
focusNodes
[
8
],
focusNodes
[
8
],
// unique IFSC focus
focusNodes
[
9
],
focusNodes
[
11
],
// next focus after IFSC (holder / or UPI)
TextInputAction
.
next
,
TextInputAction
.
next
,
),
),
const
SizedBox
(
height:
4
),
errorWidget
(
context
,
provider
.
bankIFSCError
),
errorWidget
(
context
,
provider
.
bankIFSCError
),
// Bank Name (autofill)
const
SizedBox
(
height:
8
),
// Bank Name (autofill by API) (unique focus node 6)
textControllerWidget
(
textControllerWidget
(
context
,
context
,
provider
.
bankNameController
,
provider
.
bankNameController
,
...
@@ -797,7 +886,10 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
...
@@ -797,7 +886,10 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
TextInputAction
.
next
,
TextInputAction
.
next
,
),
),
errorWidget
(
context
,
provider
.
banknameError
),
errorWidget
(
context
,
provider
.
banknameError
),
// Branch
const
SizedBox
(
height:
8
),
// Branch (unique focus node 7)
textControllerWidget
(
textControllerWidget
(
context
,
context
,
provider
.
branchNameController
,
provider
.
branchNameController
,
...
@@ -808,11 +900,14 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
...
@@ -808,11 +900,14 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
false
,
false
,
null
,
null
,
focusNodes
[
7
],
focusNodes
[
7
],
focusNodes
[
8
],
focusNodes
[
11
],
TextInputAction
.
next
,
TextInputAction
.
next
,
),
),
errorWidget
(
context
,
provider
.
bankBranchError
),
errorWidget
(
context
,
provider
.
bankBranchError
),
// Holder
const
SizedBox
(
height:
8
),
// Bank Holder Name (unique focus node 11) — previously incorrectly used 9
textControllerWidget
(
textControllerWidget
(
context
,
context
,
provider
.
bankHolderNameController
,
provider
.
bankHolderNameController
,
...
@@ -822,26 +917,30 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
...
@@ -822,26 +917,30 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
TextInputType
.
text
,
TextInputType
.
text
,
false
,
false
,
null
,
null
,
focusNodes
[
9
],
focusNodes
[
11
],
// <-- corrected unique index
focusNodes
[
10
],
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
bankHolderNameError
),
// UPI
textControllerWidget
(
context
,
provider
.
bankUpiController
,
"Bank UPI ID"
,
"Enter Bank UPI ID"
,
provider
.
updateUPI
,
TextInputType
.
text
,
false
,
null
,
focusNodes
[
11
],
focusNodes
[
12
],
focusNodes
[
12
],
TextInputAction
.
next
,
TextInputAction
.
next
,
),
),
errorWidget
(
context
,
provider
.
upiError
),
errorWidget
(
context
,
provider
.
bankHolderNameError
),
const
SizedBox
(
height:
8
),
// Bank UPI (unique focus node 12)
// Bank UPI (use different focus nodes than Contact Person)
textControllerWidget
(
context
,
provider
.
bankUpiController
,
"Bank UPI ID"
,
"Enter Bank UPI ID"
,
provider
.
updateUPI
,
TextInputType
.
text
,
false
,
null
,
focusNodes
[
17
],
//
focusNodes
[
18
],
// next focus
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
upiError
),
],
],
),
),
),
),
...
@@ -973,6 +1072,23 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
...
@@ -973,6 +1072,23 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
return
;
return
;
}
}
if
(
provider
.
validateStep1
(
context
))
{
// move to first error step
final
errStep
=
_firstErrorStep
(
provider
);
if
(
errStep
!=
null
)
{
setState
(()
{
_currentStep
=
errStep
;
});
}
else
{
provider
.
submitClickced
=
true
;
provider
.
notifyListeners
();
await
provider
.
submitCommonAccountsAPI
(
context
,
widget
.
from
);
}
// ensure UI updated
provider
.
notifyListeners
();
return
;
}
// All good => submit
// All good => submit
provider
.
submitClickced
=
true
;
provider
.
submitClickced
=
true
;
provider
.
notifyListeners
();
provider
.
notifyListeners
();
...
@@ -994,7 +1110,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
...
@@ -994,7 +1110,7 @@ class _AddcommonpaymentState extends State<Addcommonpayment> {
onTap:
()
{
onTap:
()
{
setState
(()
{
setState
(()
{
if
(
_currentStep
==
0
)
{
if
(
_currentStep
==
0
)
{
if
(
provider
.
validateStep1
())
{
if
(
provider
.
validateStep1
(
context
))
{
_currentStep
=
1
;
_currentStep
=
1
;
}
else
{
}
else
{
provider
.
notifyListeners
();
provider
.
notifyListeners
();
...
...
lib/screens/commom/editCommonAccount.dart
0 → 100644
View file @
7ba7402c
// edit_common_account_screen.dart
import
'dart:async'
;
import
'package:dropdown_button2/dropdown_button2.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:provider/provider.dart'
;
import
'package:generp/Notifiers/HomeScreenNotifier.dart'
;
import
'package:generp/Notifiers/commonProvider/editCommonAccountProvider.dart'
;
import
'package:generp/Utils/app_colors.dart'
;
import
'package:generp/Utils/commonWidgets.dart'
;
import
'package:generp/Utils/dropdownTheme.dart'
;
import
'../../Models/commonModels/DistrictsResponse.dart'
;
import
'../../Models/commonModels/SubLocationsResponse.dart'
;
import
'../../Models/commonModels/commonAddAccountsViewResponse.dart'
;
class
EditCommonAccountScreen
extends
StatefulWidget
{
final
String
accountID
;
const
EditCommonAccountScreen
({
super
.
key
,
required
this
.
accountID
});
@override
State
<
EditCommonAccountScreen
>
createState
()
=>
_EditCommonAccountScreenState
();
}
class
_EditCommonAccountScreenState
extends
State
<
EditCommonAccountScreen
>
{
Timer
?
_nameDebounce
;
Timer
?
_gstDebounce
;
final
_formKey
=
GlobalKey
<
FormState
>();
// Focus nodes
late
List
<
FocusNode
>
focusNodes
;
static
const
int
FN_ACCOUNT
=
0
;
static
const
int
FN_NAME
=
1
;
static
const
int
FN_NAME_NEXT
=
2
;
static
const
int
FN_MOBILE
=
3
;
static
const
int
FN_CONTACT
=
4
;
static
const
int
FN_GST
=
5
;
static
const
int
FN_STATE
=
6
;
static
const
int
FN_DISTRICT
=
7
;
static
const
int
FN_SUBLOC
=
8
;
static
const
int
FN_ADDRESS
=
9
;
static
const
int
FN_BANK_ACC
=
10
;
static
const
int
FN_IFSC
=
11
;
static
const
int
FN_BANK_NAME
=
12
;
static
const
int
FN_BANK_BRANCH
=
13
;
static
const
int
FN_BANK_HOLDER
=
14
;
static
const
int
FN_UPI
=
15
;
static
const
int
FN_CONTACT_DESIG
=
16
;
static
const
int
FN_CONTACT_ALTMOB
=
17
;
static
const
int
FN_CONTACT_TELE
=
18
;
static
const
int
FN_CONTACT_MAIL
=
19
;
int
_currentStep
=
0
;
final
Dropdowntheme
ddtheme
=
Dropdowntheme
();
@override
void
initState
()
{
super
.
initState
();
// create enough focus nodes (0..19)
focusNodes
=
List
.
generate
(
20
,
(
_
)
=>
FocusNode
());
WidgetsBinding
.
instance
.
addPostFrameCallback
((
_
)
{
final
prov
=
Provider
.
of
<
EditCommonAccountProvider
>(
context
,
listen:
false
);
// ensure only once: reset then load
prov
.
resetValues
();
prov
.
loadAccountDetailsForEdit
(
context
,
widget
.
accountID
);
});
}
@override
void
dispose
()
{
for
(
final
fn
in
focusNodes
)
{
try
{
fn
.
dispose
();
}
catch
(
_
)
{}
}
_nameDebounce
?.
cancel
();
_gstDebounce
?.
cancel
();
// reset provider values when leaving screen to avoid stale state
final
prov
=
Provider
.
of
<
EditCommonAccountProvider
>(
context
,
listen:
false
);
prov
.
resetValues
();
super
.
dispose
();
}
// small helper to check IFSC simple pattern
bool
_isIfscValidFormat
(
String
ifsc
)
{
final
reg
=
RegExp
(
r'^[A-Za-z]{4}0[A-Za-z0-9]{6}$'
);
return
reg
.
hasMatch
(
ifsc
.
trim
());
}
bool
_isGstValidFormat
(
String
gst
)
{
gst
=
gst
.
trim
().
toUpperCase
();
final
reg
=
RegExp
(
r'^[0-3][0-9][A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$'
);
return
reg
.
hasMatch
(
gst
);
}
Future
<
void
>
_validateGstIfNeeded
(
EditCommonAccountProvider
provider
)
async
{
final
gst
=
provider
.
gstNumberController
.
text
.
trim
();
if
(!
_isGstValidFormat
(
gst
))
{
provider
.
gstNumberError
=
"Invalid GST format"
;
provider
.
notifyListeners
();
return
;
}
if
(
gst
.
isEmpty
)
return
;
final
homeProv
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
provider
.
isLoading
=
true
;
await
provider
.
validateGstNumber
(
homeProv
.
empId
,
homeProv
.
session
,
gst
);
provider
.
isLoading
=
false
;
}
Future
<
void
>
_validateBankIfNeeded
(
EditCommonAccountProvider
provider
)
async
{
final
acc
=
provider
.
bankAcNumberController
.
text
.
trim
();
final
ifsc
=
provider
.
bankIfscCotroller
.
text
.
trim
();
final
accList
=
provider
.
detailsListResponse
?.
accountList
!.
first
;
if
(
acc
.
isEmpty
&&
ifsc
.
isEmpty
)
return
;
if
(
acc
.
isNotEmpty
&&
ifsc
.
isEmpty
)
{
provider
.
bankIFSCError
=
"IFSC is required when account number is entered"
;
provider
.
notifyListeners
();
return
;
}
if
(
acc
.
isEmpty
&&
ifsc
.
isEmpty
)
{
provider
.
bankNameController
.
text
=
accList
?.
bankName
??
""
;
provider
.
branchNameController
.
text
=
accList
?.
bankBranchName
??
""
;
provider
.
bankHolderNameController
.
text
=
accList
?.
bankAccountHolderName
??
""
;
provider
.
notifyListeners
();
return
;
}
if
(!
_isIfscValidFormat
(
ifsc
))
{
provider
.
bankIFSCError
=
"Invalid IFSC format"
;
provider
.
notifyListeners
();
return
;
}
final
homeProv
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
provider
.
isLoading
=
true
;
await
provider
.
validateBankDetails
(
homeProv
.
empId
,
homeProv
.
session
,
acc
);
provider
.
isLoading
=
false
;
// If validateBankDetails succeeded provider.bankResponse will be set and UI autofills
if
(
provider
.
bankResponse
!=
null
&&
provider
.
bankResponse
!.
error
==
"0"
)
{
provider
.
bankNameController
.
text
=
provider
.
bankResponse
!.
bankName
??
provider
.
bankNameController
.
text
;
provider
.
branchNameController
.
text
=
provider
.
bankResponse
!.
branch
??
provider
.
branchNameController
.
text
;
provider
.
bankHolderNameController
.
text
=
provider
.
bankResponse
!.
nameAtBank
??
provider
.
bankHolderNameController
.
text
;
provider
.
notifyListeners
();
}
}
int
?
_firstErrorStep
(
EditCommonAccountProvider
p
)
{
if
((
p
.
accountError
?.
isNotEmpty
??
false
)
||
(
p
.
nameError
?.
isNotEmpty
??
false
)
||
(
p
.
mobileError
?.
isNotEmpty
??
false
)
||
(
p
.
contactPersonError
?.
isNotEmpty
??
false
))
{
return
0
;
}
if
((
p
.
stateError
?.
isNotEmpty
??
false
)
||
(
p
.
districtError
?.
isNotEmpty
??
false
)
||
(
p
.
localityError
?.
isNotEmpty
??
false
)
||
(
p
.
addressError
?.
isNotEmpty
??
false
))
{
return
1
;
}
if
((
p
.
gstNumberError
?.
isNotEmpty
??
false
)
||
(
p
.
bankAcNumberError
?.
isNotEmpty
??
false
)
||
(
p
.
bankIFSCError
?.
isNotEmpty
??
false
)
||
(
p
.
banknameError
?.
isNotEmpty
??
false
)
||
(
p
.
bankBranchError
?.
isNotEmpty
??
false
)
||
(
p
.
bankHolderNameError
?.
isNotEmpty
??
false
)
||
(
p
.
upiError
?.
isNotEmpty
??
false
))
{
return
2
;
}
if
((
p
.
desigantionError
?.
isNotEmpty
??
false
)
||
(
p
.
altMobError
?.
isNotEmpty
??
false
)
||
(
p
.
teleError
?.
isNotEmpty
??
false
)
||
(
p
.
mailError
?.
isNotEmpty
??
false
))
{
return
3
;
}
return
null
;
}
@override
Widget
build
(
BuildContext
context
)
{
return
Consumer
<
EditCommonAccountProvider
>(
builder:
(
context
,
provider
,
child
)
{
return
Scaffold
(
appBar:
appbar2New
(
context
,
"Edit Account"
,
provider
.
resetValues
,
const
SizedBox
.
shrink
(),
0xFFFFFFFF
),
backgroundColor:
AppColors
.
scaffold_bg_color
,
body:
Form
(
key:
_formKey
,
child:
Stepper
(
type:
StepperType
.
horizontal
,
currentStep:
_currentStep
,
onStepContinue:
()
async
{
// custom continue logic same as your flow
if
(
_currentStep
==
0
)
{
provider
.
validateStep
();
if
(
provider
.
gstNumberController
.
text
.
trim
().
isNotEmpty
)
{
await
_validateGstIfNeeded
(
provider
);
}
if
(
provider
.
validateStep1
(
context
))
{
setState
(()
=>
_currentStep
=
1
);
}
else
{
provider
.
notifyListeners
();
setState
(()
=>
_currentStep
=
0
);
}
}
else
if
(
_currentStep
==
1
)
{
// optional step -> only validate if something filled
if
(
provider
.
stateSearchController
.
text
.
trim
().
isNotEmpty
||
provider
.
districtSearchController
.
text
.
trim
().
isNotEmpty
||
provider
.
addressController
.
text
.
trim
().
isNotEmpty
)
{
if
(
provider
.
validateStep1
(
context
))
{
setState
(()
=>
_currentStep
=
2
);
}
else
{
provider
.
notifyListeners
();
}
}
else
{
setState
(()
=>
_currentStep
=
2
);
}
}
else
if
(
_currentStep
==
2
)
{
// bank/gst step: if fields present, validate
if
(
provider
.
gstNumberController
.
text
.
trim
().
isNotEmpty
)
{
await
_validateGstIfNeeded
(
provider
);
}
provider
.
validateStep3
();
if
(
provider
.
bankAcNumberController
.
text
.
trim
().
isNotEmpty
||
provider
.
bankIfscCotroller
.
text
.
trim
().
isNotEmpty
)
{
await
_validateBankIfNeeded
(
provider
);
}
// if any errors remain, stay
final
hasBankErrors
=
(
provider
.
gstNumberError
?.
isNotEmpty
??
false
)
||
(
provider
.
bankAcNumberError
?.
isNotEmpty
??
false
)
||
(
provider
.
bankIFSCError
?.
isNotEmpty
??
false
);
if
(
hasBankErrors
)
{
provider
.
notifyListeners
();
setState
(()
=>
_currentStep
=
2
);
}
else
{
setState
(()
=>
_currentStep
=
3
);
}
}
else
{
// last step - do nothing (submit handled by controlsBuilder)
}
},
onStepCancel:
()
{
if
(
_currentStep
>
0
)
setState
(()
=>
_currentStep
-=
1
);
},
onStepTapped:
(
i
)
async
{
// allow step tapping but guard jump if step0 invalid
if
(
i
==
0
)
{
setState
(()
=>
_currentStep
=
0
);
}
else
if
(
i
==
1
)
{
if
(
provider
.
validateStep1
(
context
))
{
setState
(()
=>
_currentStep
=
1
);
}
else
{
provider
.
notifyListeners
();
setState
(()
=>
_currentStep
=
0
);
}
}
else
if
(
i
==
2
)
{
if
(
provider
.
validateStep1
(
context
))
{
setState
(()
=>
_currentStep
=
2
);
}
else
{
provider
.
notifyListeners
();
setState
(()
=>
_currentStep
=
0
);
}
}
else
if
(
i
==
3
)
{
if
(!
provider
.
validateStep1
(
context
))
{
provider
.
notifyListeners
();
setState
(()
=>
_currentStep
=
0
);
return
;
}
setState
(()
=>
_currentStep
=
3
);
}
},
connectorColor:
WidgetStatePropertyAll
(
AppColors
.
app_blue
),
stepIconBuilder:
(
stepIndex
,
stepState
)
{
return
CircleAvatar
(
radius:
12
,
backgroundColor:
stepIndex
<=
_currentStep
?
Colors
.
transparent
:
Colors
.
grey
[
300
],
);
},
steps:
[
// ---------------- Step 1 ----------------
Step
(
title:
const
Text
(
''
),
label:
const
Text
(
"Step 1"
,
style:
TextStyle
(
fontSize:
12
)),
content:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
)),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
"Account"
,
style:
TextStyle
(
color:
AppColors
.
app_blue
,
fontSize:
16
)),
const
SizedBox
(
height:
8
),
// Account dropdown (keeps DropdownButton2 style)
errorWidget
(
context
,
provider
.
accountError
),
const
SizedBox
(
height:
10
),
// Company Name (debounced uniqueness check)
textControllerWidget
(
context
,
provider
.
nameController
,
"Company Name"
,
"Enter Company Name"
,
(
p0
)
{
// local update + recheck with GST
provider
.
updateName
(
p0
);
provider
.
recheckNameWithGst
();
// debounce uniqueness API call
_nameDebounce
?.
cancel
();
_nameDebounce
=
Timer
(
const
Duration
(
milliseconds:
600
),
()
{
final
val
=
provider
.
nameController
.
text
.
trim
();
if
(
val
.
isNotEmpty
)
provider
.
checkInputsAPI
(
context
,
"name"
,
val
);
});
},
TextInputType
.
text
,
false
,
null
,
focusNodes
[
FN_NAME
],
focusNodes
[
FN_NAME_NEXT
],
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
nameError
),
const
SizedBox
(
height:
8
),
// Mobile (debounced uniqueness check)
textControllerWidget
(
context
,
provider
.
mobileController
,
"Mobile Number"
,
"Enter Mobile"
,
(
p0
)
{
provider
.
updateMobile
(
p0
);
// debounce mobile check
_nameDebounce
?.
cancel
();
_nameDebounce
=
Timer
(
const
Duration
(
milliseconds:
600
),
()
{
final
val
=
provider
.
mobileController
.
text
.
trim
();
if
(
val
.
isNotEmpty
)
provider
.
checkInputsAPI
(
context
,
"mob1"
,
val
);
});
},
TextInputType
.
phone
,
false
,
FilteringTextInputFormatter
.
digitsOnly
,
focusNodes
[
FN_MOBILE
],
focusNodes
[
FN_CONTACT
],
TextInputAction
.
next
,
10
,
),
errorWidget
(
context
,
provider
.
mobileError
),
const
SizedBox
(
height:
8
),
// Contact Person - explicit TextFormField to avoid helper-side reassignment
Text
(
"Contact Person Name"
),
const
SizedBox
(
height:
6
),
TextFormField
(
controller:
provider
.
contactPersonController
,
focusNode:
focusNodes
[
FN_CONTACT
],
textInputAction:
TextInputAction
.
next
,
keyboardType:
TextInputType
.
text
,
onChanged:
(
v
)
{
// only update provider state (provider may call notifyListeners inside)
provider
.
updateContactPerson
(
v
);
// do not call heavy APIs here
},
decoration:
InputDecoration
(
hintText:
"Enter Contact Person Name"
,
hintStyle:
TextStyle
(
height:
1.2
,
backgroundColor:
AppColors
.
text_field_color
,
color:
AppColors
.
grey_semi
,
),
filled:
true
,
fillColor:
AppColors
.
text_field_color
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
14
,
vertical:
14
),
enabledBorder:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
16
),
borderSide:
BorderSide
.
none
),
focusedBorder:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
16
),
borderSide:
BorderSide
.
none
),
),
),
errorWidget
(
context
,
provider
.
contactPersonError
),
const
SizedBox
(
height:
12
),
// GST (debounced validation + autofill). Typing + deletion will work now.
Text
(
"GST Number"
),
const
SizedBox
(
height:
6
),
TextFormField
(
controller:
provider
.
gstNumberController
,
focusNode:
focusNodes
[
FN_GST
],
textInputAction:
TextInputAction
.
done
,
keyboardType:
TextInputType
.
text
,
onChanged:
(
value
)
{
provider
.
updateGSTNumber
(
value
);
// if cleared -> reset responses immediately (keeps UI clean)
if
(
value
.
trim
().
isEmpty
)
{
provider
.
gstResponse
=
null
;
provider
.
gstNumberError
=
null
;
provider
.
nameError
=
null
;
provider
.
notifyListeners
();
return
;
}
// immediate apply when full GST length typed (fast feedback)
if
(
value
.
trim
().
length
==
15
)
{
_gstDebounce
?.
cancel
();
provider
.
checkAndApplyGst
(
context
,
value
.
trim
());
return
;
}
// otherwise debounce (user typing)
_gstDebounce
?.
cancel
();
_gstDebounce
=
Timer
(
const
Duration
(
milliseconds:
700
),
()
{
final
trimmed
=
provider
.
gstNumberController
.
text
.
trim
();
if
(
trimmed
.
isNotEmpty
&&
trimmed
.
length
==
15
)
{
provider
.
checkAndApplyGst
(
context
,
trimmed
);
}
});
},
onFieldSubmitted:
(
value
)
async
{
final
trimmed
=
value
.
trim
();
if
(
trimmed
.
isNotEmpty
)
await
provider
.
checkAndApplyGst
(
context
,
trimmed
);
FocusScope
.
of
(
context
).
requestFocus
(
focusNodes
[
FN_BANK_ACC
]);
},
decoration:
InputDecoration
(
hintText:
"Enter GST Number"
,
hintStyle:
TextStyle
(
height:
1.2
,
backgroundColor:
AppColors
.
text_field_color
,
color:
AppColors
.
grey_semi
,
),
filled:
true
,
fillColor:
AppColors
.
text_field_color
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
14
,
vertical:
14
),
enabledBorder:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
16
),
borderSide:
BorderSide
.
none
),
focusedBorder:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
16
),
borderSide:
BorderSide
.
none
),
),
),
const
SizedBox
(
height:
4
),
errorWidget
(
context
,
provider
.
gstNumberError
),
],
),
),
),
// ---------------- Step 2 ----------------
Step
(
title:
const
Text
(
''
),
label:
const
Text
(
"Step 2"
,
style:
TextStyle
(
fontSize:
12
)),
isActive:
_currentStep
>=
1
,
content:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Container
(
margin:
const
EdgeInsets
.
only
(
bottom:
10
),
child:
Text
(
"Address Details"
,
style:
TextStyle
(
color:
AppColors
.
app_blue
,
fontSize:
16
,
fontFamily:
"JakartaMedium"
),
),
),
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
)),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
// State
Text
(
"State"
),
const
SizedBox
(
height:
6
),
DropdownButtonHideUnderline
(
child:
Row
(
children:
[
Expanded
(
child:
DropdownButton2
<
States
>(
focusNode:
focusNodes
[
FN_STATE
],
isExpanded:
true
,
hint:
const
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
)
{
provider
.
selectedState
=
value
;
// Clear dependent district/sub-location
provider
.
districts
.
clear
();
provider
.
subLocations
.
clear
();
provider
.
getDistrictAPI
(
context
,
provider
.
selectedStateID
);
}
},
dropdownSearchData:
DropdownSearchData
(
searchInnerWidgetHeight:
50
,
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
))),
),
),
searchMatchFn:
(
item
,
searchValue
)
{
return
item
.
value
?.
name
?.
toLowerCase
().
contains
(
searchValue
.
toLowerCase
())
??
false
;
},
),
onMenuStateChange:
(
isOpen
)
{
if
(!
isOpen
)
provider
.
stateSearchController
.
clear
();
},
buttonStyleData:
ddtheme
.
buttonStyleData
,
iconStyleData:
ddtheme
.
iconStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
),
),
],
),
),
errorWidget
(
context
,
provider
.
stateError
),
const
SizedBox
(
height:
12
),
// District
Text
(
"District"
),
const
SizedBox
(
height:
6
),
DropdownButtonHideUnderline
(
child:
Row
(
children:
[
Expanded
(
child:
DropdownButton2
<
Districts
>(
focusNode:
focusNodes
[
FN_DISTRICT
],
isExpanded:
true
,
hint:
const
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
)
{
provider
.
selectedDistricts
=
value
;
provider
.
getSubLocationAPI
(
context
,
provider
.
selectedDistrictId
);
}
},
dropdownSearchData:
DropdownSearchData
(
searchInnerWidgetHeight:
50
,
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
))),
),
),
searchMatchFn:
(
item
,
searchValue
)
{
return
item
.
value
?.
district
?.
toLowerCase
().
contains
(
searchValue
.
toLowerCase
())
??
false
;
},
),
onMenuStateChange:
(
isOpen
)
{
if
(!
isOpen
)
provider
.
districtSearchController
.
clear
();
},
buttonStyleData:
ddtheme
.
buttonStyleData
,
iconStyleData:
ddtheme
.
iconStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
),
),
],
),
),
errorWidget
(
context
,
provider
.
districtError
),
const
SizedBox
(
height:
12
),
// Sub Locality
Text
(
"Sub Locality"
),
const
SizedBox
(
height:
6
),
DropdownButtonHideUnderline
(
child:
Row
(
children:
[
Expanded
(
child:
DropdownButton2
<
SubLocations
>(
focusNode:
focusNodes
[
FN_SUBLOC
],
isExpanded:
true
,
hint:
const
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
)
{
provider
.
selectedSubLocations
=
value
;
}
},
dropdownSearchData:
DropdownSearchData
(
searchInnerWidgetHeight:
50
,
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
))),
),
),
searchMatchFn:
(
item
,
searchValue
)
{
return
item
.
value
?.
subLocality
?.
toLowerCase
().
contains
(
searchValue
.
toLowerCase
())
??
false
;
},
),
onMenuStateChange:
(
isOpen
)
{
if
(!
isOpen
)
provider
.
subLocSearchController
.
clear
();
},
buttonStyleData:
ddtheme
.
buttonStyleData
,
iconStyleData:
ddtheme
.
iconStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
),
),
],
),
),
errorWidget
(
context
,
provider
.
localityError
),
const
SizedBox
(
height:
12
),
// Address text field (same UI as your other address field)
textControllerWidget
(
context
,
provider
.
addressController
,
"Address"
,
"Enter Address"
,
provider
.
updateAddress
,
TextInputType
.
text
,
false
,
null
,
focusNodes
[
FN_ADDRESS
],
focusNodes
[
FN_BANK_ACC
],
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
addressError
),
],
),
),
],
),
),
// ---------------- Step 3 ----------------
Step
(
title:
const
Text
(
''
),
label:
const
Text
(
"Step 3"
,
style:
TextStyle
(
fontSize:
12
)),
content:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
)),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
"Bank Details"
,
style:
TextStyle
(
color:
AppColors
.
app_blue
,
fontSize:
16
)),
const
SizedBox
(
height:
8
),
const
SizedBox
(
height:
12
),
// Bank Account Number
textControllerWidget
(
context
,
provider
.
bankAcNumberController
,
"Bank Account Number"
,
"Enter Bank Account Number"
,
(
p0
)
{
provider
.
updateNumber
(
p0
);
// IFSC required if account entered
if
(
p0
.
trim
().
isNotEmpty
&&
provider
.
bankIfscCotroller
.
text
.
trim
().
isEmpty
)
{
provider
.
bankIFSCError
=
"IFSC is required when account number is entered"
;
provider
.
notifyListeners
();
}
else
if
(
p0
.
trim
().
isNotEmpty
&&
provider
.
bankIfscCotroller
.
text
.
trim
().
isNotEmpty
)
{
// both present -> validate bank
provider
.
checkAndApplyBank
(
context
,
p0
.
trim
());
}
else
{
// cleared -> reset bank response/errors
if
(
p0
.
trim
().
isEmpty
)
{
provider
.
bankResponse
=
null
;
provider
.
bankAcNumberError
=
null
;
provider
.
bankIFSCError
=
null
;
provider
.
notifyListeners
();
}
}
},
TextInputType
.
number
,
false
,
FilteringTextInputFormatter
.
digitsOnly
,
focusNodes
[
FN_BANK_ACC
],
focusNodes
[
FN_IFSC
],
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
bankAcNumberError
),
// IFSC
textControllerWidget
(
context
,
provider
.
bankIfscCotroller
,
"Bank IFSC"
,
"Enter Bank IFSC"
,
(
p0
)
async
{
provider
.
updateIFSC
(
p0
);
if
(
p0
.
trim
().
isEmpty
)
{
if
(
provider
.
bankAcNumberController
.
text
.
trim
().
isNotEmpty
)
{
provider
.
bankIFSCError
=
"IFSC is required when account number is entered"
;
provider
.
notifyListeners
();
}
else
{
provider
.
bankIFSCError
=
null
;
provider
.
notifyListeners
();
}
return
;
}
if
(!
_isIfscValidFormat
(
p0
))
{
provider
.
bankIFSCError
=
"Invalid IFSC format"
;
provider
.
notifyListeners
();
return
;
}
else
{
provider
.
bankIFSCError
=
null
;
provider
.
notifyListeners
();
}
// if both present -> validate
if
(
provider
.
bankAcNumberController
.
text
.
trim
().
isNotEmpty
)
{
await
provider
.
checkAndApplyBank
(
context
,
provider
.
bankAcNumberController
.
text
.
trim
());
}
},
TextInputType
.
text
,
false
,
null
,
focusNodes
[
FN_IFSC
],
focusNodes
[
FN_BANK_NAME
],
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
bankIFSCError
),
const
SizedBox
(
height:
8
),
// Bank Name (autofilled, readonly)
Text
(
"Bank Name"
),
const
SizedBox
(
height:
6
),
TextFormField
(
controller:
provider
.
bankNameController
,
focusNode:
focusNodes
[
FN_BANK_NAME
],
readOnly:
true
,
decoration:
InputDecoration
(
hintText:
"Bank Name"
,
hintStyle:
TextStyle
(
height:
1.2
,
backgroundColor:
AppColors
.
text_field_color
,
color:
AppColors
.
grey_semi
,
),
filled:
true
,
fillColor:
AppColors
.
text_field_color
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
14
,
vertical:
14
),
enabledBorder:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
16
),
borderSide:
BorderSide
.
none
),
),
),
errorWidget
(
context
,
provider
.
banknameError
),
const
SizedBox
(
height:
8
),
// Branch (read-only)
Text
(
"Bank Branch"
),
const
SizedBox
(
height:
6
),
TextFormField
(
controller:
provider
.
branchNameController
,
focusNode:
focusNodes
[
FN_BANK_BRANCH
],
readOnly:
true
,
decoration:
InputDecoration
(
hintText:
"Branch "
,
hintStyle:
TextStyle
(
height:
1.2
,
backgroundColor:
AppColors
.
text_field_color
,
color:
AppColors
.
grey_semi
,
),
filled:
true
,
fillColor:
AppColors
.
text_field_color
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
14
,
vertical:
14
),
enabledBorder:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
16
),
borderSide:
BorderSide
.
none
),
),
),
errorWidget
(
context
,
provider
.
bankBranchError
),
const
SizedBox
(
height:
8
),
// Bank Holder (read-only)
Text
(
"Bank Holder Name"
),
const
SizedBox
(
height:
6
),
TextFormField
(
controller:
provider
.
bankHolderNameController
,
focusNode:
focusNodes
[
FN_BANK_HOLDER
],
readOnly:
true
,
decoration:
InputDecoration
(
hintText:
"Holder "
,
hintStyle:
TextStyle
(
height:
1.2
,
backgroundColor:
AppColors
.
text_field_color
,
color:
AppColors
.
grey_semi
,
),
filled:
true
,
fillColor:
AppColors
.
text_field_color
,
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
14
,
vertical:
14
),
enabledBorder:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
16
),
borderSide:
BorderSide
.
none
),
),
),
errorWidget
(
context
,
provider
.
bankHolderNameError
),
const
SizedBox
(
height:
8
),
// UPI (editable)
textControllerWidget
(
context
,
provider
.
bankUpiController
,
"Bank UPI ID"
,
"Enter Bank UPI ID"
,
provider
.
updateUPI
,
TextInputType
.
text
,
false
,
null
,
focusNodes
[
FN_UPI
],
focusNodes
[
FN_CONTACT_MAIL
],
TextInputAction
.
next
,
),
errorWidget
(
context
,
provider
.
upiError
),
],
),
),
),
// ---------------- Step 4 ----------------
Step
(
title:
const
Text
(
''
),
label:
const
Text
(
"Step 4"
,
style:
TextStyle
(
fontSize:
12
)),
content:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
)),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
"Contact Details"
,
style:
TextStyle
(
color:
AppColors
.
app_blue
,
fontSize:
16
)),
const
SizedBox
(
height:
8
),
textControllerWidget
(
context
,
provider
.
contectPersonMailController
,
"Mail ID"
,
"Enter Customer Mail ID"
,
provider
.
updateMail
,
TextInputType
.
emailAddress
,
false
,
null
,
focusNodes
[
FN_CONTACT_MAIL
],
FocusNode
(),
TextInputAction
.
done
,
),
errorWidget
(
context
,
provider
.
mailError
),
],
),
),
),
],
controlsBuilder:
(
context
,
details
)
{
return
Column
(
children:
[
if
(
_currentStep
==
3
)
...[
InkResponse
(
onTap:
provider
.
isSubmitting
?
null
:
()
async
{
// trigger validations for gst/bank if present
if
(
provider
.
gstNumberController
.
text
.
trim
().
isNotEmpty
)
{
await
_validateGstIfNeeded
(
provider
);
}
if
(
provider
.
bankAcNumberController
.
text
.
trim
().
isNotEmpty
&&
provider
.
bankIfscCotroller
.
text
.
trim
().
isNotEmpty
)
{
await
_validateBankIfNeeded
(
provider
);
}
final
ok
=
provider
.
validatereceiptForm
(
context
);
if
(!
ok
)
{
final
err
=
_firstErrorStep
(
provider
);
if
(
err
!=
null
)
setState
(()
=>
_currentStep
=
err
);
provider
.
notifyListeners
();
return
;
}
// call update API
provider
.
isLoading
=
true
;
final
success
=
await
provider
.
updateAccountDetailsAPIFunction
(
context
,
accId:
widget
.
accountID
,
name:
provider
.
nameController
.
text
.
trim
(),
mob1:
provider
.
mobileController
.
text
.
trim
(),
email:
provider
.
contectPersonMailController
.
text
.
trim
(),
address:
provider
.
addressController
.
text
.
trim
(),
state:
provider
.
selectedStateID
,
district:
provider
.
selectedDistrictId
,
subLocality:
provider
.
selectedSubLocID
,
bankName:
provider
.
bankNameController
.
text
.
trim
(),
branchName:
provider
.
branchNameController
.
text
.
trim
(),
bankIfscCode:
provider
.
bankIfscCotroller
.
text
.
trim
(),
accHolderName:
provider
.
bankHolderNameController
.
text
.
trim
(),
bankAccNumber:
provider
.
bankAcNumberController
.
text
.
trim
(),
bankUpiId:
provider
.
bankUpiController
.
text
.
trim
(),
);
provider
.
isLoading
=
false
;
if
(
success
)
{
Navigator
.
pop
(
context
,
true
);
// or pass updated id as you wish
}
else
{
if
(
kDebugMode
)
debugPrint
(
"update failed:
${provider.updateErrorMessage}
"
);
}
},
child:
Container
(
height:
45
,
alignment:
Alignment
.
center
,
margin:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
padding:
const
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
...[
InkResponse
(
onTap:
()
{
final
error
=
provider
.
gstNumberError
??
""
;
// proceed to next step (uses Stepper.onStepContinue logic)
if
(
error
.
isEmpty
)
{
details
.
onStepContinue
!();
}
},
child:
Container
(
height:
45
,
alignment:
Alignment
.
center
,
margin:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
padding:
const
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
)),
),
),
],
if
(
_currentStep
>
0
)
TextButton
(
onPressed:
details
.
onStepCancel
,
child:
Text
(
'Back'
,
style:
TextStyle
(
color:
AppColors
.
app_blue
)))
],
);
},
),
),
);
});
}
}
lib/screens/crm/CrmNearbyGenerators.dart
0 → 100644
View file @
7ba7402c
import
'dart:io'
;
import
'package:dropdown_button2/dropdown_button2.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_svg/svg.dart'
;
import
'package:generp/Utils/app_colors.dart'
;
import
'package:generp/Utils/commonWidgets.dart'
;
import
'package:google_maps_flutter/google_maps_flutter.dart'
;
import
'package:interactive_slider/interactive_slider.dart'
;
import
'package:provider/provider.dart'
;
import
'../../Notifiers/crmProvider/CrmNearByGeneratorsProvider.dart'
;
import
'../../Utils/dropdownTheme.dart'
;
class
CrmNearbyGenerators
extends
StatefulWidget
{
const
CrmNearbyGenerators
({
super
.
key
});
@override
State
<
CrmNearbyGenerators
>
createState
()
=>
_CrmNearbyGeneratorsState
();
}
class
_CrmNearbyGeneratorsState
extends
State
<
CrmNearbyGenerators
>
{
Dropdowntheme
ddtheme
=
Dropdowntheme
();
@override
void
initState
()
{
// TODO: implement initState
super
.
initState
();
WidgetsBinding
.
instance
.
addPostFrameCallback
((
_
)
{
var
provider
=
Provider
.
of
<
CrmNearByGeneratorsProvider
>(
context
,
listen:
false
,
);
provider
.
getLocationPermission
(
context
);
});
}
@override
Widget
build
(
BuildContext
context
)
{
debugPrint
(
"Nearbygenerators widget rebuilt"
);
return
Consumer
<
CrmNearByGeneratorsProvider
>(
builder:
(
context
,
provider
,
child
)
{
var
sendWidget
=
GestureDetector
(
onTap:
()
{
_showFilterBottomSheet
(
context
);
},
child:
SvgPicture
.
asset
(
"assets/svg/filter_ic.svg"
,
height:
25
),
);
return
WillPopScope
(
onWillPop:
()
=>
onBackPressed
(
context
),
child:
SafeArea
(
top:
false
,
bottom:
Platform
.
isIOS
?
false
:
true
,
child:
Scaffold
(
resizeToAvoidBottomInset:
true
,
appBar:
appbar2
(
context
,
"Nearby Generators"
,
provider
.
resetAll
,
sendWidget
,
),
backgroundColor:
AppColors
.
scaffold_bg_color
,
body:
Container
(
child:
SingleChildScrollView
(
child:
Column
(
children:
[
ClipRRect
(
// Apply border radius using ClipRRect
borderRadius:
BorderRadius
.
only
(
topLeft:
Radius
.
circular
(
30.0
),
topRight:
Radius
.
circular
(
30.0
),
),
// padding: EdgeInsets.fromLTRB(10, 20, 10, 20),
child:
SizedBox
(
height:
MediaQuery
.
of
(
context
).
size
.
height
,
child:
Stack
(
children:
[
GoogleMap
(
scrollGesturesEnabled:
true
,
rotateGesturesEnabled:
true
,
myLocationEnabled:
true
,
zoomGesturesEnabled:
true
,
zoomControlsEnabled:
true
,
gestureRecognizers:
{
Factory
<
OneSequenceGestureRecognizer
>(
()
=>
EagerGestureRecognizer
(),
),
Factory
<
PanGestureRecognizer
>(
()
=>
PanGestureRecognizer
(),
),
Factory
<
ScaleGestureRecognizer
>(
()
=>
ScaleGestureRecognizer
(),
),
// Prioritize pinch-to-zoom
},
initialCameraPosition:
CameraPosition
(
target:
provider
.
startLocation
,
zoom:
14.0
,
),
markers:
provider
.
markers
.
toSet
(),
mapType:
MapType
.
normal
,
onMapCreated:
(
controller
)
{
setState
(()
{
provider
.
mapController
=
controller
;
});
},
onCameraMove:
(
position
)
{
provider
.
onCameraMove
(
context
,
position
);
},
),
],
),
),
),
],
),
),
),
),
),
);
},
);
}
Future
<
void
>
_showFilterBottomSheet
(
BuildContext
context
)
{
return
showModalBottomSheet
(
useSafeArea:
true
,
isDismissible:
true
,
isScrollControlled:
true
,
showDragHandle:
true
,
enableDrag:
true
,
context:
context
,
builder:
(
context
)
{
return
StatefulBuilder
(
builder:
(
context
,
setState
)
{
return
SafeArea
(
child:
Consumer
<
CrmNearByGeneratorsProvider
>(
builder:
(
context
,
provider
,
child
)
{
return
Container
(
margin:
EdgeInsets
.
only
(
bottom:
15
,
left:
15
,
right:
15
,
top:
15
,
),
padding:
EdgeInsets
.
only
(
bottom:
MediaQuery
.
of
(
context
).
viewInsets
.
bottom
,
),
child:
SingleChildScrollView
(
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
children:
[
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
"Filter"
,
style:
TextStyle
(
color:
AppColors
.
app_blue
,
fontFamily:
"JakartaSemiBold"
,
fontSize:
16
,
),
),
SizedBox
(
height:
15
),
Align
(
alignment:
Alignment
.
centerLeft
,
child:
Text
(
'Status'
,
style:
TextStyle
(
fontSize:
18.0
,
fontWeight:
FontWeight
.
w500
,
),
),
),
DropdownButtonHideUnderline
(
child:
Row
(
children:
[
Expanded
(
child:
DropdownButton2
<
String
>(
isExpanded:
true
,
hint:
const
Row
(
children:
[
Expanded
(
child:
Text
(
'Select Complaint Status'
,
style:
TextStyle
(
fontSize:
14
),
overflow:
TextOverflow
.
ellipsis
,
),
),
],
),
items:
<
String
>[
'Active'
,
'Inactive'
,
'Suspense'
,
]
.
map
(
(
value
,
)
=>
DropdownMenuItem
<
String
>(
value:
value
,
child:
Text
(
value
??
''
,
style:
const
TextStyle
(
fontSize:
14
,
),
overflow:
TextOverflow
.
ellipsis
,
),
),
)
.
toList
(),
value:
provider
.
selectedItem
,
onChanged:
(
String
?
newValue
)
{
setState
(()
{
provider
.
selectedItem
=
newValue
!;
});
},
buttonStyleData:
ddtheme
.
buttonStyleData
,
iconStyleData:
ddtheme
.
iconStyleData
,
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
),
),
],
),
),
SizedBox
(
height:
10
),
Row
(
children:
[
Text
(
"Radius"
,
style:
TextStyle
(
fontSize:
18.0
,
fontWeight:
FontWeight
.
w500
,
),
),
Spacer
(),
Text
(
'
${provider.currentValue.toStringAsFixed(2)}
KM'
,
style:
TextStyle
(
fontSize:
18.0
,
fontWeight:
FontWeight
.
w500
,
),
),
],
),
InteractiveSlider
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
4
,
vertical:
0
),
min:
1.0
,
max:
5.0
,
// MAX 5 KM
enabled:
true
,
foregroundColor:
AppColors
.
app_blue
,
segmentDividerColor:
Color
(
0xFFF6F6F8
),
onChanged:
(
value
)
{
// just to be extra safe, clamp in provider too
provider
.
currentValue
=
value
;
},
),
// Slider(
// value: provider.currentValue,
// max: 100,
// divisions: 100,
//
// label: provider.currentValue.toStringAsFixed(2),
// inactiveColor: Color(0xFFD7D7D7),
// activeColor: AppColors.cyan_blue,
// onChanged: (value) {
// provider.currentValue = value;
// provider.debounce(() {
// provider.LoadNearbyGeneratorsAPI(context);
// }, Duration(milliseconds: 200));
// },
// ),
SizedBox
(
height:
30.0
),
Container
(
child:
InkWell
(
onTap:
()
{
provider
.
debounce
(()
{
provider
.
LoadNearbyGeneratorsAPI
(
context
,
provider
.
currentValue
,
);
Navigator
.
pop
(
context
);
},
Duration
(
milliseconds:
500
));
},
child:
Container
(
alignment:
Alignment
.
center
,
height:
45
,
margin:
EdgeInsets
.
only
(
left:
15.0
,
right:
15.0
,
),
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
14.0
),
color:
AppColors
.
app_blue
,
),
child:
Text
(
"Search"
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
fontFamily:
'JakartaMedium'
,
color:
Colors
.
white
,
),
),
),
),
),
],
),
],
),
),
);
},
),
);
},
);
},
);
}
}
lib/screens/crm/LeadListByMode.dart
View file @
7ba7402c
...
@@ -357,8 +357,21 @@ class _LeadlistbymodeState extends State<Leadlistbymode> {
...
@@ -357,8 +357,21 @@ class _LeadlistbymodeState extends State<Leadlistbymode> {
),
),
child:
Consumer
<
Leadlistprovider
>(
child:
Consumer
<
Leadlistprovider
>(
builder:
(
context
,
provider
,
child
)
{
builder:
(
context
,
provider
,
child
)
{
// 🔹 Initialize filter selections from widget.filter only once
if
(
provider
.
selectedLeadStatus
==
null
&&
widget
.
filter
?.
status
!=
null
&&
widget
.
filter
!.
status
!.
toString
().
isNotEmpty
)
{
provider
.
selectedLeadStatus
=
widget
.
filter
!.
status
;
}
if
(
provider
.
selectedOpenStatus
==
null
&&
widget
.
filter
?.
openStatus
!=
null
&&
widget
.
filter
!.
openStatus
!.
toString
().
isNotEmpty
)
{
provider
.
selectedOpenStatus
=
widget
.
filter
!.
openStatus
;
}
int
selectedIndex
=
isSelected
.
indexWhere
(
int
selectedIndex
=
isSelected
.
indexWhere
(
(
element
)
=>
element
==
true
,
(
element
)
=>
element
==
true
,
);
);
final
headings
=
[
final
headings
=
[
"Lead Status"
,
"Lead Status"
,
...
@@ -373,6 +386,22 @@ class _LeadlistbymodeState extends State<Leadlistbymode> {
...
@@ -373,6 +386,22 @@ class _LeadlistbymodeState extends State<Leadlistbymode> {
if
(
widget
.
mode
!=
"executive"
)
{
if
(
widget
.
mode
!=
"executive"
)
{
headings
.
add
(
"Employee"
);
headings
.
add
(
"Employee"
);
}
}
// int selectedIndex = isSelected.indexWhere(
// (element) => element == true,
// );
// final headings = [
// "Lead Status",
// "Open/Close Status",
// "Mobile Number",
// "Company Name",
// "Source",
// "Reference",
// "Team",
// "Segment",
// ];
if
(
widget
.
mode
!=
"executive"
)
{
headings
.
add
(
"Employee"
);
}
return
SizedBox
(
return
SizedBox
(
height:
MediaQuery
.
of
(
context
).
size
.
height
*
0.7
,
height:
MediaQuery
.
of
(
context
).
size
.
height
*
0.7
,
child:
Column
(
child:
Column
(
...
@@ -512,17 +541,12 @@ class _LeadlistbymodeState extends State<Leadlistbymode> {
...
@@ -512,17 +541,12 @@ class _LeadlistbymodeState extends State<Leadlistbymode> {
mainAxisSize:
MainAxisSize
.
min
,
mainAxisSize:
MainAxisSize
.
min
,
children:
[
children:
[
if
(
selectedIndex
==
0
)
...[
if
(
selectedIndex
==
0
)
...[
...
provider
.
leadStatusList
.
map
((
...
provider
.
leadStatusList
.
map
((
status
,)
{
// here i want to do that i want to show selected from widget.filter!.status,
status
,
)
{
return
SizedBox
(
return
SizedBox
(
height:
35
,
height:
35
,
child:
CheckboxListTile
(
child:
CheckboxListTile
(
activeColor:
activeColor:
AppColors
.
app_blue
,
AppColors
.
app_blue
,
controlAffinity:
ListTileControlAffinity
.
leading
,
controlAffinity:
ListTileControlAffinity
.
leading
,
checkboxShape:
CircleBorder
(
checkboxShape:
CircleBorder
(
side:
BorderSide
(
side:
BorderSide
(
width:
0.5
,
width:
0.5
,
...
@@ -568,7 +592,7 @@ class _LeadlistbymodeState extends State<Leadlistbymode> {
...
@@ -568,7 +592,7 @@ class _LeadlistbymodeState extends State<Leadlistbymode> {
width:
0.5
,
width:
0.5
,
),
),
),
),
title:
Text
(
title:
Text
(
// same here widget.filter!.openStatus,
status
??
'Unknown Status'
,
status
??
'Unknown Status'
,
style:
const
TextStyle
(
style:
const
TextStyle
(
fontSize:
14
,
fontSize:
14
,
...
@@ -963,6 +987,7 @@ class _LeadlistbymodeState extends State<Leadlistbymode> {
...
@@ -963,6 +987,7 @@ class _LeadlistbymodeState extends State<Leadlistbymode> {
},
},
);
);
}
}
void
_showContactOptions
(
BuildContext
context
,
String
?
phoneNumber
)
{
void
_showContactOptions
(
BuildContext
context
,
String
?
phoneNumber
)
{
if
(
phoneNumber
==
null
||
phoneNumber
.
isEmpty
)
{
if
(
phoneNumber
==
null
||
phoneNumber
.
isEmpty
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
...
...
lib/screens/crm/crmDashboard.dart
View file @
7ba7402c
...
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
...
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
import
'package:flutter/services.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_svg/svg.dart'
;
import
'package:flutter_svg/svg.dart'
;
import
'package:generp/Notifiers/crmProvider/addNewLeadsandProspectsProvider.dart'
;
import
'package:generp/Notifiers/crmProvider/addNewLeadsandProspectsProvider.dart'
;
import
'package:generp/screens/crm/CrmNearbyGenerators.dart'
;
import
'package:generp/screens/crm/addLeadsProspectsScreen.dart'
;
import
'package:generp/screens/crm/addLeadsProspectsScreen.dart'
;
import
'package:generp/screens/crm/appointmentCalendar.dart'
;
import
'package:generp/screens/crm/appointmentCalendar.dart'
;
import
'package:generp/screens/crm/followUpListonType.dart'
;
import
'package:generp/screens/crm/followUpListonType.dart'
;
...
@@ -741,6 +742,69 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
...
@@ -741,6 +742,69 @@ class _CrmdashboardScreenState extends State<CrmdashboardScreen> {
],
],
),
),
),
),
SizedBox
(
height:
10
,),
Align
(
alignment:
Alignment
.
centerLeft
,
child:
Padding
(
padding:
EdgeInsets
.
only
(
left:
15
,
top:
10
,
right:
15
),
child:
Text
(
"Nearby Generators"
,
style:
TextStyle
(
fontSize:
16
,
color:
AppColors
.
grey_semi
,
),
),
),
),
SizedBox
(
height:
12
,),
InkResponse
(
onTap:
()
{
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
CrmNearbyGenerators
(),
),
);
},
child:
Container
(
height:
60
,
margin:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
0
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
20
),
),
child:
Row
(
children:
[
Expanded
(
flex:
1
,
child:
Container
(
height:
35
,
width:
35
,
padding:
EdgeInsets
.
all
(
8.0
),
decoration:
BoxDecoration
(
color:
Color
(
0xFFEDF8FF
),
shape:
BoxShape
.
circle
,
),
child:
SvgPicture
.
asset
(
"assets/svg/find_generator.svg"
,
),
),
),
Expanded
(
flex:
4
,
child:
Text
(
"Find Nearby Generators"
,
style:
TextStyle
(
fontSize:
14
,
color:
AppColors
.
app_blue
,
),
),
),
],
),
),
),
if
(
provider
.
nearByLeads
.
isNotEmpty
)
...[
if
(
provider
.
nearByLeads
.
isNotEmpty
)
...[
Align
(
Align
(
...
...
lib/screens/finance/AllPaymentRequesitionListsByModes.dart
View file @
7ba7402c
...
@@ -89,6 +89,12 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -89,6 +89,12 @@ class _AllpaymentrequesitionlistsbymodesState
);
);
}
}
});
});
final
providerclear
=
Provider
.
of
<
Requesitionlidtdetailsprovider
>(
context
,
listen:
false
,
);
providerclear
.
resetAll
();
});
});
}
}
...
@@ -859,6 +865,10 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -859,6 +865,10 @@ class _AllpaymentrequesitionlistsbymodesState
],
],
),
),
),
),
errorWidget
(
context
,
provider
.
selectpaymentAccountError
,
),
InkWell
(
InkWell
(
onTap:
provider
.
isLoading
onTap:
provider
.
isLoading
?
null
// Disable tap while loading
?
null
// Disable tap while loading
...
@@ -871,23 +881,30 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -871,23 +881,30 @@ class _AllpaymentrequesitionlistsbymodesState
// Small delay to ensure rebuild and show spinner before API starts
// Small delay to ensure rebuild and show spinner before API starts
await
Future
.
delayed
(
const
Duration
(
milliseconds:
300
));
await
Future
.
delayed
(
const
Duration
(
milliseconds:
300
));
// 🔄 Call API
// Call API
await
provider
.
paymentrequisitionApproveSubmitAPIFunction
(
if
(
remarks
.
text
.
isNotEmpty
)
{
await
provider
.
paymentrequisitionApproveSubmitAPIFunction
(
context
,
context
,
widget
.
mode
,
widget
.
mode
,
paymentID
,
paymentID
,
provider
.
approvedAmount
.
text
,
safeNormalizeAmount
(
provider
.
approvedAmount
.
text
)
,
remarks
.
text
,
remarks
.
text
,
provider
.
selectedID
,
provider
.
selectedID
,
);
);
await
Provider
.
of
<
Requesitionlidtdetailsprovider
>(
context
,
listen:
false
,
);
}
else
{
provider
.
remarksError
=
"Please Enter Remarks."
;
provider
.
selectpaymentAccountError
=
"Please Select Payment Account."
;
}
//
🔓
Stop loading only if context is still active
// Stop loading only if context is still active
if
(
context
.
mounted
)
{
if
(
context
.
mounted
)
{
provider
.
isLoading
=
false
;
provider
.
isLoading
=
false
;
}
}
},
},
child:
AnimatedContainer
(
child:
AnimatedContainer
(
duration:
const
Duration
(
milliseconds:
200
),
duration:
const
Duration
(
milliseconds:
200
),
...
@@ -926,9 +943,19 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -926,9 +943,19 @@ class _AllpaymentrequesitionlistsbymodesState
},
},
);
);
},
},
).
then
((
value
)
{
).
then
((
value
)
async
{
final
provider
=
Provider
.
of
<
Requesitionlidtdetailsprovider
>(
context
,
listen:
false
,
);
await
provider
.
resetRequired
();
var
providerpage
=
Provider
.
of
<
Requestionlistprovider
>(
context
,
listen:
false
,
);
providerpage
.
paymentRequestionListsAPIFunction
(
context
,
widget
.
mode
,
""
,
""
);
// This runs only when the bottom sheet is explicitly popped
// This runs only when the bottom sheet is explicitly popped
print
(
"closing Sheet"
);
// Use the original context with mounted check
// Use the original context with mounted check
if
(
context
.
mounted
)
{
if
(
context
.
mounted
)
{
...
@@ -962,6 +989,23 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -962,6 +989,23 @@ class _AllpaymentrequesitionlistsbymodesState
}
}
});
});
}
}
String
safeNormalizeAmount
(
String
?
input
)
{
if
(
input
==
null
||
input
.
trim
().
isEmpty
)
return
"0"
;
// Remove currency symbols, commas and spaces - keep digits and dots
String
cleaned
=
input
.
replaceAll
(
RegExp
(
r'[^0-9.]'
),
''
);
// Handle multiple decimal points: keep only first dot
int
firstDot
=
cleaned
.
indexOf
(
'.'
);
if
(
firstDot
!=
-
1
)
{
String
before
=
cleaned
.
substring
(
0
,
firstDot
+
1
);
String
after
=
cleaned
.
substring
(
firstDot
+
1
).
replaceAll
(
'.'
,
''
);
cleaned
=
before
+
after
;
}
return
cleaned
.
isEmpty
?
"0"
:
cleaned
;
}
Future
<
void
>
_showLevelRejectionSheet
(
BuildContext
context
,
paymentID
)
{
Future
<
void
>
_showLevelRejectionSheet
(
BuildContext
context
,
paymentID
)
{
return
showModalBottomSheet
(
return
showModalBottomSheet
(
...
@@ -1130,7 +1174,7 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -1130,7 +1174,7 @@ class _AllpaymentrequesitionlistsbymodesState
context
,
context
,
listen:
false
,
listen:
false
,
);
);
detailsprov
.
reset
All
();
detailsprov
.
reset
Required
();
provider
.
paymentRequestionListsAPIFunction
(
provider
.
paymentRequestionListsAPIFunction
(
context
,
context
,
...
...
lib/screens/finance/PaymentRequestionListDetails.dart
View file @
7ba7402c
...
@@ -82,6 +82,7 @@ class _PaymentrequestionlistdetailsState
...
@@ -82,6 +82,7 @@ class _PaymentrequestionlistdetailsState
provider
.
showMoreDetails
=
false
;
provider
.
showMoreDetails
=
false
;
provider
.
checkDropDownReset
();
provider
.
checkDropDownReset
();
print
(
widget
.
paymentRequestId
);
print
(
widget
.
paymentRequestId
);
provider
.
resetRequired
();
provider
.
paymentRequesitionDetails
(
context
,
widget
.
paymentRequestId
);
provider
.
paymentRequesitionDetails
(
context
,
widget
.
paymentRequestId
);
});
});
}
}
...
@@ -891,9 +892,9 @@ class _PaymentrequestionlistdetailsState
...
@@ -891,9 +892,9 @@ class _PaymentrequestionlistdetailsState
),
),
),
),
Text
(
Text
(
reqDet
.
amount
==
""
reqDet
.
amount
==
""
?
"-"
?
"-"
:
"
₹
${reqDet.amount}
"
,
:
"
${reqDet.amount
}
"
,
style:
TextStyle
(
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontFamily:
"JakartaRegular"
,
fontSize:
14
,
fontSize:
14
,
...
@@ -936,8 +937,7 @@ class _PaymentrequestionlistdetailsState
...
@@ -936,8 +937,7 @@ class _PaymentrequestionlistdetailsState
final
section
=
sections
[
sectionIndex
];
final
section
=
sections
[
sectionIndex
];
final
title
=
section
[
"title"
]
as
String
;
final
title
=
section
[
"title"
]
as
String
;
final
headings
=
section
[
"headings"
]
as
List
<
String
>;
final
headings
=
section
[
"headings"
]
as
List
<
String
>;
final
subHeadings
=
final
subHeadings
=
section
[
"subHeadings"
]
as
List
<
String
>;
section
[
"subHeadings"
]
as
List
<
String
>;
return
Column
(
return
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
...
@@ -1304,6 +1304,10 @@ class _PaymentrequestionlistdetailsState
...
@@ -1304,6 +1304,10 @@ class _PaymentrequestionlistdetailsState
}
}
Future
<
void
>
_showLevelApprovalSheet
(
BuildContext
context
,
paymentID
)
{
Future
<
void
>
_showLevelApprovalSheet
(
BuildContext
context
,
paymentID
)
{
final
provider
=
Provider
.
of
<
Requesitionlidtdetailsprovider
>(
context
,
listen:
false
,
);
return
showModalBottomSheet
(
return
showModalBottomSheet
(
useSafeArea:
true
,
useSafeArea:
true
,
isDismissible:
true
,
isDismissible:
true
,
...
@@ -1516,9 +1520,9 @@ class _PaymentrequestionlistdetailsState
...
@@ -1516,9 +1520,9 @@ class _PaymentrequestionlistdetailsState
context
,
context
,
widget
.
mode
,
widget
.
mode
,
paymentID
,
paymentID
,
provider
.
approvedAmount
.
text
,
safeNormalizeAmount
(
provider
.
approvedAmount
.
text
)
,
remarks
.
text
,
remarks
.
text
,
provider
.
selectedID
,
provider
.
selectedID
??
""
,
);
);
},
},
child:
Container
(
child:
Container
(
...
@@ -1580,9 +1584,30 @@ class _PaymentrequestionlistdetailsState
...
@@ -1580,9 +1584,30 @@ class _PaymentrequestionlistdetailsState
},
},
);
);
},
},
);
).
then
((
_
)
async
{
await
provider
.
resetRequired
();
});
}
}
String
safeNormalizeAmount
(
String
?
input
)
{
if
(
input
==
null
||
input
.
trim
().
isEmpty
)
return
"0"
;
// Remove currency symbols, commas and spaces - keep digits and dots
String
cleaned
=
input
.
replaceAll
(
RegExp
(
r'[^0-9.]'
),
''
);
// Handle multiple decimal points: keep only first dot
int
firstDot
=
cleaned
.
indexOf
(
'.'
);
if
(
firstDot
!=
-
1
)
{
String
before
=
cleaned
.
substring
(
0
,
firstDot
+
1
);
String
after
=
cleaned
.
substring
(
firstDot
+
1
).
replaceAll
(
'.'
,
''
);
cleaned
=
before
+
after
;
}
return
cleaned
.
isEmpty
?
"0"
:
cleaned
;
}
Future
<
void
>
_showLevelRejectionSheet
(
BuildContext
context
,
paymentID
)
{
Future
<
void
>
_showLevelRejectionSheet
(
BuildContext
context
,
paymentID
)
{
return
showModalBottomSheet
(
return
showModalBottomSheet
(
useSafeArea:
true
,
useSafeArea:
true
,
...
@@ -2268,6 +2293,7 @@ class _PaymentrequestionlistdetailsState
...
@@ -2268,6 +2293,7 @@ class _PaymentrequestionlistdetailsState
"Enter Proposed Payment Account"
,
"Enter Proposed Payment Account"
,
(
p0
)
{},
(
p0
)
{},
),
),
TextWidget
(
TextWidget
(
context
,
context
,
"Payment Account"
,
"Payment Account"
,
...
@@ -2323,9 +2349,7 @@ class _PaymentrequestionlistdetailsState
...
@@ -2323,9 +2349,7 @@ class _PaymentrequestionlistdetailsState
value
,
value
,
)
{
)
{
if
(
value
!=
null
&&
if
(
value
!=
null
&&
provider
provider
.
paymentsAccounts
.
isNotEmpty
)
{
.
paymentsAccounts
.
isNotEmpty
)
{
setState
(()
{
setState
(()
{
provider
.
selectedPaymentAccounts
=
provider
.
selectedPaymentAccounts
=
value
;
value
;
...
@@ -2415,6 +2439,8 @@ class _PaymentrequestionlistdetailsState
...
@@ -2415,6 +2439,8 @@ class _PaymentrequestionlistdetailsState
],
],
),
),
),
),
errorWidget
(
context
,
provider
.
selectpaymentAccountError
),
textControllerReadonlyWidget
(
textControllerReadonlyWidget
(
context
,
context
,
provider
.
approvedAmountReadonly
,
provider
.
approvedAmountReadonly
,
...
@@ -2652,8 +2678,9 @@ class _PaymentrequestionlistdetailsState
...
@@ -2652,8 +2678,9 @@ class _PaymentrequestionlistdetailsState
),
),
child:
InkWell
(
child:
InkWell
(
onTap:
()
{
onTap:
()
{
provider
HapticFeedback
.
mediumImpact
();
.
paymentrequisitionProcessSubmitAPIFunction
(
if
(
provider
.
selectedPaymentAccounts
!=
null
)
{
provider
.
paymentrequisitionProcessSubmitAPIFunction
(
context
,
context
,
widget
.
mode
,
widget
.
mode
,
paymentReferenceNumber
.
text
,
paymentReferenceNumber
.
text
,
...
@@ -2663,6 +2690,9 @@ class _PaymentrequestionlistdetailsState
...
@@ -2663,6 +2690,9 @@ class _PaymentrequestionlistdetailsState
remarks
.
text
,
remarks
.
text
,
provider
.
imagePath
,
provider
.
imagePath
,
);
);
}
else
{
provider
.
selectpaymentAccountError
=
"Please Select account"
;
}
},
},
child:
Container
(
child:
Container
(
height:
45
,
height:
45
,
...
...
lib/screens/hrm/AttendanceRequestDetail.dart
View file @
7ba7402c
...
@@ -359,16 +359,19 @@ class _AttendanceRequestDetailScreenState
...
@@ -359,16 +359,19 @@ class _AttendanceRequestDetailScreenState
"Other Details"
,
"Other Details"
,
scaleFactor
,
scaleFactor
,
),
),
if
(
details
.
type
==
"Check In"
||
details
.
type
==
"Check In/Out"
)
_buildDetailTile
(
_buildDetailTile
(
"Check In Type"
,
"Check In Type"
,
details
.
checkInType
,
details
.
checkInType
,
scaleFactor
,
scaleFactor
,
),
),
if
(
details
.
type
==
"Check Out"
||
details
.
type
==
"Check In/Out"
)
_buildDetailTile
(
_buildDetailTile
(
"Check Out Type"
,
"Check Out Type"
,
details
.
chechOutType
,
details
.
chechOutType
,
scaleFactor
,
scaleFactor
,
),
),
if
(
details
.
type
==
"Check Out"
||
details
.
type
==
"Check In/Out"
)
_buildDetailTile
(
_buildDetailTile
(
"Check Out Time"
,
"Check Out Time"
,
details
.
checkOutTime
,
details
.
checkOutTime
,
...
...
lib/screens/hrm/ContactList.dart
View file @
7ba7402c
...
@@ -72,12 +72,12 @@ class _ContactListScreenState extends State<ContactListScreen> {
...
@@ -72,12 +72,12 @@ class _ContactListScreenState extends State<ContactListScreen> {
// Clean phone number
// Clean phone number
final
cleanPhoneNumber
=
_cleanPhoneNumber
(
phoneNumber
);
final
cleanPhoneNumber
=
_cleanPhoneNumber
(
phoneNumber
);
//
✅
Instead of inserting contact, open system form
// Instead of inserting contact, open system form
final
newContact
=
Contact
()
final
newContact
=
Contact
()
..
name
=
Name
(
first:
name
)
..
name
=
Name
(
first:
name
)
..
phones
=
[
Phone
(
cleanPhoneNumber
)];
..
phones
=
[
Phone
(
cleanPhoneNumber
)];
//
🟢
This opens the phone’s native “Add contact” screen (prefilled)
// This opens the phone’s native “Add contact” screen (prefilled)
await
FlutterContacts
.
openExternalInsert
(
newContact
);
await
FlutterContacts
.
openExternalInsert
(
newContact
);
// Hide loading
// Hide loading
...
...
lib/screens/notifierExports.dart
View file @
7ba7402c
...
@@ -25,6 +25,7 @@ export 'package:generp/Notifiers/commonProvider/accountDetailsProvider.dart';
...
@@ -25,6 +25,7 @@ export 'package:generp/Notifiers/commonProvider/accountDetailsProvider.dart';
export
'package:generp/Notifiers/commonProvider/accountsListProvider.dart'
;
export
'package:generp/Notifiers/commonProvider/accountsListProvider.dart'
;
export
'package:generp/Notifiers/commonProvider/commonPagesProvider.dart'
;
export
'package:generp/Notifiers/commonProvider/commonPagesProvider.dart'
;
export
'package:generp/Notifiers/commonProvider/accountLedgerProvider.dart'
;
export
'package:generp/Notifiers/commonProvider/accountLedgerProvider.dart'
;
export
'package:generp/Notifiers/commonProvider/editCommonAccountProvider.dart'
;
export
'package:generp/Notifiers/financeProvider/DashboardProvider.dart'
;
export
'package:generp/Notifiers/financeProvider/DashboardProvider.dart'
;
export
'package:generp/Notifiers/financeProvider/RequestionListProvider.dart'
;
export
'package:generp/Notifiers/financeProvider/RequestionListProvider.dart'
;
...
@@ -56,6 +57,7 @@ export 'package:generp/Notifiers/crmProvider/addProspectLeadsProvider.dart';
...
@@ -56,6 +57,7 @@ export 'package:generp/Notifiers/crmProvider/addProspectLeadsProvider.dart';
export
'package:generp/Notifiers/crmProvider/followUpUpdateProvider.dart'
;
export
'package:generp/Notifiers/crmProvider/followUpUpdateProvider.dart'
;
export
'package:generp/Notifiers/crmProvider/appointmentCalendarProvider.dart'
;
export
'package:generp/Notifiers/crmProvider/appointmentCalendarProvider.dart'
;
export
'package:generp/Notifiers/crmProvider/addNewLeadsandProspectsProvider.dart'
;
export
'package:generp/Notifiers/crmProvider/addNewLeadsandProspectsProvider.dart'
;
export
'package:generp/Notifiers/crmProvider/CrmNearByGeneratorsProvider.dart'
;
export
'package:generp/Notifiers/hrmProvider/hrmAccessiblePagesProvider.dart'
;
export
'package:generp/Notifiers/hrmProvider/hrmAccessiblePagesProvider.dart'
;
export
'package:generp/Notifiers/hrmProvider/attendanceListProvider.dart'
;
export
'package:generp/Notifiers/hrmProvider/attendanceListProvider.dart'
;
...
...
lib/screens/serviceEngineer/PaymentDetails.dart
View file @
7ba7402c
...
@@ -362,7 +362,7 @@ class _PaymentdetailsState extends State<Paymentdetails> {
...
@@ -362,7 +362,7 @@ class _PaymentdetailsState extends State<Paymentdetails> {
),
),
errorWidget
(
context
,
provider
.
selectAmountError
),
errorWidget
(
context
,
provider
.
selectAmountError
),
SizedBox
(
height:
10
),
SizedBox
(
height:
10
),
if
(
provider
.
selectPaymentMode
?.
name
?.
toLowerCase
()
!=
'
upi
'
)
...[
if
(
provider
.
selectPaymentMode
?.
name
?.
toLowerCase
()
!=
'
qr
'
)
...[
Padding
(
Padding
(
padding:
const
EdgeInsets
.
only
(
bottom:
5.0
),
padding:
const
EdgeInsets
.
only
(
bottom:
5.0
),
child:
Text
(
"Reference Number"
),
child:
Text
(
"Reference Number"
),
...
@@ -481,7 +481,7 @@ class _PaymentdetailsState extends State<Paymentdetails> {
...
@@ -481,7 +481,7 @@ class _PaymentdetailsState extends State<Paymentdetails> {
:
()
{
:
()
{
HapticFeedback
.
selectionClick
();
HapticFeedback
.
selectionClick
();
//
🧩
Common validation
// Common validation
if
(
provider
.
selectContact
==
null
)
{
if
(
provider
.
selectContact
==
null
)
{
provider
.
selectContactError
=
"Please select phone number"
;
provider
.
selectContactError
=
"Please select phone number"
;
provider
.
notifyListeners
();
provider
.
notifyListeners
();
...
@@ -494,15 +494,15 @@ class _PaymentdetailsState extends State<Paymentdetails> {
...
@@ -494,15 +494,15 @@ class _PaymentdetailsState extends State<Paymentdetails> {
return
;
return
;
}
}
//
🧩
For
UPI
payment
// For
QR
payment
if
(
provider
.
selectPaymentMode
?.
name
?.
toLowerCase
()
==
'
upi
'
)
{
if
(
provider
.
selectPaymentMode
?.
name
?.
toLowerCase
()
==
'
qr
'
)
{
if
(
provider
.
imagePicked
==
0
||
provider
.
imagePath
==
null
)
{
if
(
provider
.
imagePicked
==
0
||
provider
.
imagePath
==
null
)
{
provider
.
imageError
=
"Please upload reference document"
;
provider
.
imageError
=
"Please upload reference document"
;
provider
.
notifyListeners
();
provider
.
notifyListeners
();
return
;
return
;
}
}
// All validations passed
✅
// All validations passed
var
homeProvider
=
Provider
.
of
<
HomescreenNotifier
>(
var
homeProvider
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
context
,
listen:
false
,
listen:
false
,
...
@@ -521,7 +521,7 @@ class _PaymentdetailsState extends State<Paymentdetails> {
...
@@ -521,7 +521,7 @@ class _PaymentdetailsState extends State<Paymentdetails> {
),
),
);
);
}
else
{
}
else
{
//
🧩
For non-
UPI
payments
// For non-
QR
payments
if
(
provider
.
Referencecontroller
.
text
.
isEmpty
)
{
if
(
provider
.
Referencecontroller
.
text
.
isEmpty
)
{
provider
.
ReferenceError
=
"Please enter reference number"
;
provider
.
ReferenceError
=
"Please enter reference number"
;
provider
.
notifyListeners
();
provider
.
notifyListeners
();
...
@@ -561,7 +561,7 @@ class _PaymentdetailsState extends State<Paymentdetails> {
...
@@ -561,7 +561,7 @@ class _PaymentdetailsState extends State<Paymentdetails> {
),
),
)
)
:
Text
(
:
Text
(
provider
.
selectPaymentMode
?.
name
?.
toLowerCase
()
==
'
upi
'
provider
.
selectPaymentMode
?.
name
?.
toLowerCase
()
==
'
qr
'
?
"Show QR"
?
"Show QR"
:
"Send OTP"
,
:
"Send OTP"
,
textAlign:
TextAlign
.
center
,
textAlign:
TextAlign
.
center
,
...
...
lib/screens/serviceEngineer/RazorpayQrScreen.dart
View file @
7ba7402c
import
'dart:async'
;
import
'dart:async'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_svg/svg.dart'
;
import
'package:fluttertoast/fluttertoast.dart'
;
import
'package:fluttertoast/fluttertoast.dart'
;
import
'package:provider/provider.dart'
;
import
'package:provider/provider.dart'
;
...
@@ -31,6 +32,8 @@ class RazorpayQrScreen extends StatefulWidget {
...
@@ -31,6 +32,8 @@ class RazorpayQrScreen extends StatefulWidget {
class
_RazorpayQrScreenState
extends
State
<
RazorpayQrScreen
>
{
class
_RazorpayQrScreenState
extends
State
<
RazorpayQrScreen
>
{
Timer
?
_statusTimer
;
Timer
?
_statusTimer
;
bool
_isCancelling
=
false
;
@override
@override
void
initState
()
{
void
initState
()
{
super
.
initState
();
super
.
initState
();
...
@@ -54,7 +57,6 @@ class _RazorpayQrScreenState extends State<RazorpayQrScreen> {
...
@@ -54,7 +57,6 @@ class _RazorpayQrScreenState extends State<RazorpayQrScreen> {
}
}
});
});
}
}
void
_startStatusPolling
(
QrProvider
provider
)
{
void
_startStatusPolling
(
QrProvider
provider
)
{
_statusTimer
=
Timer
.
periodic
(
const
Duration
(
seconds:
5
),
(
timer
)
async
{
_statusTimer
=
Timer
.
periodic
(
const
Duration
(
seconds:
5
),
(
timer
)
async
{
if
(!
mounted
)
return
;
if
(!
mounted
)
return
;
...
@@ -69,21 +71,15 @@ class _RazorpayQrScreenState extends State<RazorpayQrScreen> {
...
@@ -69,21 +71,15 @@ class _RazorpayQrScreenState extends State<RazorpayQrScreen> {
razorpayOrderId:
razorpayOrderId
,
razorpayOrderId:
razorpayOrderId
,
);
);
if
(
response
!=
null
&&
response
.
error
==
"0"
)
{
//
if
(
response
!=
null
&&
response
.
error
==
"0"
)
{
// success -> stop timer, notify user and pop
CustomSnackBar
.
showSuccess
(
CustomSnackBar
.
showSuccess
(
context:
context
,
context:
context
,
message:
"Payment received successfully
"
,
message:
"Payment received successfully"
,
);
);
// Fluttertoast.showToast(
// msg:
// backgroundColor: Colors.green,
// textColor: Colors.white,
// );
// Stop timer
timer
.
cancel
();
timer
.
cancel
();
// Go back two screens
if
(
mounted
)
{
if
(
mounted
)
{
Navigator
.
pop
(
context
);
// close QR screen
Navigator
.
pop
(
context
);
// close QR screen
Navigator
.
pop
(
context
);
// close previous screen
Navigator
.
pop
(
context
);
// close previous screen
...
@@ -92,6 +88,67 @@ class _RazorpayQrScreenState extends State<RazorpayQrScreen> {
...
@@ -92,6 +88,67 @@ class _RazorpayQrScreenState extends State<RazorpayQrScreen> {
});
});
}
}
/// Called when user explicitly cancels / presses close.
/// This stops polling and checks the final status once — shows failure snack only if payment not completed.
Future
<
void
>
_handleCancel
()
async
{
// Prevent re-entry
if
(
_isCancelling
)
return
;
_isCancelling
=
true
;
try
{
// Stop polling immediately
_statusTimer
?.
cancel
();
_statusTimer
=
null
;
final
provider
=
context
.
read
<
QrProvider
>();
final
razorpayOrderId
=
provider
.
qrResponse
?.
qrId
;
if
(
razorpayOrderId
!=
null
)
{
// Check status once more before showing failure
final
response
=
await
provider
.
fetchRazorpayUpiQrStatus
(
context:
context
,
sessionId:
widget
.
sessionId
,
empId:
widget
.
empId
,
razorpayOrderId:
razorpayOrderId
,
);
// If response == null or not successful -> show warning now (single time)
if
(
response
==
null
||
response
.
error
!=
"0"
)
{
if
(
mounted
)
{
CustomSnackBar
.
showWarning
(
context:
context
,
message:
"⚠️ Payment not yet completed or failed"
,
);
}
}
else
{
if
(
mounted
)
{
CustomSnackBar
.
showSuccess
(
context:
context
,
message:
"Payment received successfully"
,
);
}
}
}
else
{
// No order id — just show failure once
if
(
mounted
)
{
CustomSnackBar
.
showWarning
(
context:
context
,
message:
"⚠️ Payment not yet completed or failed"
,
);
}
}
}
catch
(
e
)
{
// ignore or log
debugPrint
(
'_handleCancel error:
$e
'
);
}
finally
{
// Finally pop the screen (single pop)
if
(
mounted
)
Navigator
.
pop
(
context
);
// small delay to reset guard if this screen somehow remains mounted longer
// but normally screen is popped so _isCancelling reset isn't necessary
}
}
@override
@override
void
dispose
()
{
void
dispose
()
{
_statusTimer
?.
cancel
();
_statusTimer
?.
cancel
();
...
@@ -100,33 +157,75 @@ class _RazorpayQrScreenState extends State<RazorpayQrScreen> {
...
@@ -100,33 +157,75 @@ class _RazorpayQrScreenState extends State<RazorpayQrScreen> {
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
return
WillPopScope
(
appBar:
appbarNew
(
context
,
"Scan QR to Pay"
,
0xFFFFFFFF
),
onWillPop:
()
async
{
backgroundColor:
Colors
.
black
,
await
_handleCancel
();
body:
SafeArea
(
return
false
;
child:
Consumer
<
QrProvider
>(
},
builder:
(
context
,
provider
,
_
)
{
child:
Scaffold
(
if
(
provider
.
isLoading
)
{
appBar:
AppBar
(
return
_buildLoadingState
();
backgroundColor:
Color
(
0xFFFFFFFF
),
}
automaticallyImplyLeading:
false
,
title:
SizedBox
(
if
(
provider
.
errorMessage
!=
null
)
{
child:
Row
(
return
_buildErrorState
(
provider
.
errorMessage
!);
mainAxisAlignment:
MainAxisAlignment
.
start
,
}
crossAxisAlignment:
CrossAxisAlignment
.
center
,
children:
[
if
(
provider
.
qrResponse
==
null
||
provider
.
qrResponse
?.
qrCode
==
null
)
{
InkResponse
(
return
_buildNoQrState
();
onTap:
()
=>
_handleCancel
(),
}
child:
SvgPicture
.
asset
(
"assets/svg/appbar_back_button.svg"
,
if
(
provider
.
secondsLeft
==
0
)
{
height:
25
,
Future
.
delayed
(
Duration
.
zero
,
()
{
),
if
(
mounted
)
Navigator
.
pop
(
context
);
),
});
SizedBox
(
width:
10
),
return
_buildExpiredState
();
InkResponse
(
}
onTap:
()
=>
_handleCancel
(),
child:
Text
(
return
_buildQrScreen
(
provider
);
"Scan QR to Pay"
,
},
style:
TextStyle
(
fontSize:
16
,
height:
1.1
,
fontFamily:
"JakartaSemiBold"
,
color:
AppColors
.
semi_black
,
),
),
),
],
),
),
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.vertical(
// bottom: Radius.circular(30), // Adjust the radius as needed
// ),
// ),
),
backgroundColor:
Colors
.
black
,
body:
SafeArea
(
child:
Consumer
<
QrProvider
>(
builder:
(
context
,
provider
,
_
)
{
if
(
provider
.
isLoading
)
{
return
_buildLoadingState
();
}
if
(
provider
.
errorMessage
!=
null
)
{
return
_buildErrorState
(
provider
.
errorMessage
!);
}
if
(
provider
.
qrResponse
==
null
||
provider
.
qrResponse
?.
qrCode
==
null
)
{
return
_buildNoQrState
();
}
if
(
provider
.
secondsLeft
==
0
)
{
Future
.
delayed
(
Duration
.
zero
,
()
{
if
(
mounted
)
Navigator
.
pop
(
context
);
});
return
_buildExpiredState
();
}
return
_buildQrScreen
(
provider
);
},
),
),
),
),
),
);
);
...
@@ -356,7 +455,7 @@ class _RazorpayQrScreenState extends State<RazorpayQrScreen> {
...
@@ -356,7 +455,7 @@ class _RazorpayQrScreenState extends State<RazorpayQrScreen> {
child:
IconButton
(
child:
IconButton
(
icon:
const
Icon
(
Icons
.
close
,
size:
18
),
icon:
const
Icon
(
Icons
.
close
,
size:
18
),
color:
Colors
.
transparent
,
color:
Colors
.
transparent
,
onPressed:
()
=>
Navigator
.
pop
(
context
),
onPressed:
()
=>
_handleCancel
(
),
),
),
),
),
),
),
...
@@ -432,7 +531,7 @@ class _RazorpayQrScreenState extends State<RazorpayQrScreen> {
...
@@ -432,7 +531,7 @@ class _RazorpayQrScreenState extends State<RazorpayQrScreen> {
// Cancel Button
// Cancel Button
Expanded
(
Expanded
(
child:
ElevatedButton
.
icon
(
child:
ElevatedButton
.
icon
(
onPressed:
()
=>
Navigator
.
pop
(
context
),
onPressed:
()
=>
_handleCancel
(
),
icon:
const
Icon
(
Icons
.
close
,
size:
18
),
icon:
const
Icon
(
Icons
.
close
,
size:
18
),
label:
const
Text
(
"Cancel"
),
label:
const
Text
(
"Cancel"
),
style:
ElevatedButton
.
styleFrom
(
style:
ElevatedButton
.
styleFrom
(
...
...
lib/screens/serviceEngineer/VisitDetails.dart
View file @
7ba7402c
...
@@ -7,9 +7,11 @@ import 'package:flutter_svg/svg.dart';
...
@@ -7,9 +7,11 @@ import 'package:flutter_svg/svg.dart';
import
'package:generp/Notifiers/VisitDetailsProvider.dart'
;
import
'package:generp/Notifiers/VisitDetailsProvider.dart'
;
import
'package:generp/Utils/app_colors.dart'
;
import
'package:generp/Utils/app_colors.dart'
;
import
'package:generp/Utils/commonWidgets.dart'
;
import
'package:generp/Utils/commonWidgets.dart'
;
import
'package:generp/screens/serviceEngineer/RazorpayQrScreen.dart'
;
import
'package:provider/provider.dart'
;
import
'package:provider/provider.dart'
;
import
'package:url_launcher/url_launcher.dart'
;
import
'package:url_launcher/url_launcher.dart'
;
import
'../../Notifiers/HomeScreenNotifier.dart'
;
import
'../../Utils/commonServices.dart'
;
import
'../../Utils/commonServices.dart'
;
import
'../finance/FileViewer.dart'
;
import
'../finance/FileViewer.dart'
;
import
'Followupdetails.dart'
;
import
'Followupdetails.dart'
;
...
@@ -46,6 +48,7 @@ class _VisitdetailsState extends State<Visitdetails> {
...
@@ -46,6 +48,7 @@ class _VisitdetailsState extends State<Visitdetails> {
visitdetails
.
showMoreDetails
=
false
;
visitdetails
.
showMoreDetails
=
false
;
visitdetails
.
LoadVisitDetailsAPI
(
context
,
widget
.
complaintID
);
visitdetails
.
LoadVisitDetailsAPI
(
context
,
widget
.
complaintID
);
visitdetails
.
LoadFollowupListAPI
(
context
,
widget
.
complaintID
);
visitdetails
.
LoadFollowupListAPI
(
context
,
widget
.
complaintID
);
visitdetails
.
serviceComplaintBillList
(
context
,
widget
.
complaintID
);
});
});
}
}
...
@@ -90,6 +93,7 @@ class _VisitdetailsState extends State<Visitdetails> {
...
@@ -90,6 +93,7 @@ class _VisitdetailsState extends State<Visitdetails> {
var
generatorDetails
=
provider
.
generatorDetails
;
var
generatorDetails
=
provider
.
generatorDetails
;
var
complaintDetails
=
provider
.
complaintDetailsNew
;
var
complaintDetails
=
provider
.
complaintDetailsNew
;
var
followups
=
provider
.
followUpList
;
var
followups
=
provider
.
followUpList
;
var
complaintBillList
=
provider
.
complaintList
;
return
WillPopScope
(
return
WillPopScope
(
onWillPop:
()
=>
onBackPressed
(
context
),
onWillPop:
()
=>
onBackPressed
(
context
),
child:
SafeArea
(
child:
SafeArea
(
...
@@ -994,6 +998,129 @@ class _VisitdetailsState extends State<Visitdetails> {
...
@@ -994,6 +998,129 @@ class _VisitdetailsState extends State<Visitdetails> {
),
),
),
),
],
],
if
(
complaintBillList
.
isNotEmpty
)
...[
Container
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
5
,
),
child:
Text
(
"Complaint Bill List"
,
style:
TextStyle
(
color:
Color
(
0xFF818181
),
fontFamily:
"JakartaMedium"
,
),
),
),
SizedBox
(
width:
double
.
infinity
,
height:
350
,
child:
ListView
.
builder
(
padding:
EdgeInsets
.
all
(
12
),
itemCount:
complaintBillList
!.
length
,
itemBuilder:
(
context
,
index
)
{
final
item
=
complaintBillList
![
index
];
return
Card
(
margin:
EdgeInsets
.
only
(
bottom:
12
),
elevation:
0
,
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
12
)),
child:
Padding
(
padding:
const
EdgeInsets
.
all
(
14
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
// _detailRow("Bill ID", item.billId),
// _detailRow("Total Amount", item.totalAmount),
// _detailRow("Raw Amount", item.rawAmount),
// _detailRow("Narration", item.narration),
// _detailRow("Bill Date", item.billDate),
// _detailRow("Due Date", item.dueDate),
// _detailRow("Bill Paid", item.billPaid == "1" ? "Yes" : "No"),
Row
(
children:
[
// 👤 Avatar
Container
(
height:
40
,
width:
40
,
decoration:
const
BoxDecoration
(
color:
Color
(
0xFFE6F6FF
),
shape:
BoxShape
.
circle
,
),
clipBehavior:
Clip
.
antiAlias
,
child:
SvgPicture
.
asset
(
"assets/svg/compliant_list_ic.svg"
,
),
),
const
SizedBox
(
width:
12
),
// 📝 Info
Expanded
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
item
.
narration
??
"-"
,
style:
const
TextStyle
(
fontFamily:
"Plus Jakarta Sans"
,
fontWeight:
FontWeight
.
w400
,
fontSize:
14
,
color:
Colors
.
black87
,
),
),
const
SizedBox
(
height:
3
),
Text
(
item
.
dueDate
??
"-"
,
style:
TextStyle
(
fontFamily:
"JakartaRegular"
,
fontSize:
12
,
fontWeight:
FontWeight
.
w400
,
color:
Colors
.
grey
.
shade600
,
height:
1.4
,
),
),
],
),
),
// Call
if
(
item
.
billPaid
==
"0"
)
InkResponse
(
onTap:
(){
var
homeProvider
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
,
);
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
RazorpayQrScreen
(
sessionId:
homeProvider
.
session
,
empId:
homeProvider
.
empId
,
amount:
item
.
rawAmount
.
toString
(),
refType:
"Bill"
,
refId:
item
.
billId
.
toString
()
))
);
},
child:
Text
(
"Pay Now"
,
style:
TextStyle
(
fontSize:
14
,
color:
AppColors
.
app_blue
,
),),
)
],
),
],
),
),
);
},
)
),
],
SizedBox
(
height:
75
),
SizedBox
(
height:
75
),
],
],
),
),
...
@@ -1215,6 +1342,28 @@ class _VisitdetailsState extends State<Visitdetails> {
...
@@ -1215,6 +1342,28 @@ class _VisitdetailsState extends State<Visitdetails> {
);
);
}
}
Widget
_detailRow
(
String
title
,
String
?
value
)
{
return
Padding
(
padding:
const
EdgeInsets
.
only
(
bottom:
8
),
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
"
$title
: "
,
style:
TextStyle
(
fontWeight:
FontWeight
.
bold
,
fontSize:
14
),
),
Expanded
(
child:
Text
(
value
??
"--"
,
style:
TextStyle
(
fontSize:
14
),
),
),
],
),
);
}
Widget
_scaffold
(
BuildContext
context
)
{
Widget
_scaffold
(
BuildContext
context
)
{
return
Consumer
<
Visitdetailsprovider
>(
return
Consumer
<
Visitdetailsprovider
>(
builder:
(
context
,
provider
,
child
)
{
builder:
(
context
,
provider
,
child
)
{
...
...
lib/services/api_calling.dart
View file @
7ba7402c
...
@@ -64,6 +64,7 @@ import '../Models/PaymentCollectionResponse.dart';
...
@@ -64,6 +64,7 @@ import '../Models/PaymentCollectionResponse.dart';
import
'../Models/PaymentCollectionValidateOTPResponse.dart'
;
import
'../Models/PaymentCollectionValidateOTPResponse.dart'
;
import
'../Models/PaymentCollectionWalletResponse.dart'
;
import
'../Models/PaymentCollectionWalletResponse.dart'
;
import
'../Models/ProfileResponse.dart'
;
import
'../Models/ProfileResponse.dart'
;
import
'../Models/ServiceComplaintBillListResponse.dart'
;
import
'../Models/SessionResponse.dart'
;
import
'../Models/SessionResponse.dart'
;
import
'../Models/StatusResponse.dart'
;
import
'../Models/StatusResponse.dart'
;
import
'../Models/SubmitComplaintResponse.dart'
;
import
'../Models/SubmitComplaintResponse.dart'
;
...
@@ -78,6 +79,7 @@ import '../Models/UpdateComplaintResponse.dart';
...
@@ -78,6 +79,7 @@ import '../Models/UpdateComplaintResponse.dart';
import
'../Models/UpdatePasswordResponse.dart'
;
import
'../Models/UpdatePasswordResponse.dart'
;
import
'../Models/VersionsResponse.dart'
;
import
'../Models/VersionsResponse.dart'
;
import
'../Models/ViewVisitDetailsResponse.dart'
;
import
'../Models/ViewVisitDetailsResponse.dart'
;
import
'../Models/commonModels/EditCommonAccFormDetailsResponse.dart'
;
import
'../Models/commonModels/commonAddAccountsSubmitResponse.dart'
;
import
'../Models/commonModels/commonAddAccountsSubmitResponse.dart'
;
import
'../Models/crmModels/appointmentCalendarResponse.dart'
;
import
'../Models/crmModels/appointmentCalendarResponse.dart'
;
import
'../Models/crmModels/crmAddFollowUpResponse.dart'
;
import
'../Models/crmModels/crmAddFollowUpResponse.dart'
;
...
@@ -928,7 +930,7 @@ class ApiCalling {
...
@@ -928,7 +930,7 @@ class ApiCalling {
};
};
final
res
=
await
post
(
data
,
technicianNearbyGeneratorsUrl
,
{});
final
res
=
await
post
(
data
,
technicianNearbyGeneratorsUrl
,
{});
if
(
res
!=
null
)
{
if
(
res
!=
null
)
{
//
print(
data
);
print
(
" input data:
$data
"
);
// debugPrint(res.body);
// debugPrint(res.body);
return
NearbyGeneratorsResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
return
NearbyGeneratorsResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
}
else
{
}
else
{
...
@@ -941,6 +943,36 @@ class ApiCalling {
...
@@ -941,6 +943,36 @@ class ApiCalling {
}
}
}
}
static
Future
<
NearbyGeneratorsResponse
?>
loadCrmNearbyGeneratorsAPI
(
empId
,
session
,
techLoc
,
radius
,
status
,
)
async
{
try
{
Map
<
String
,
String
>
data
=
{
'emp_id'
:
(
empId
).
toString
(),
'session_id'
:
(
session
).
toString
(),
'emp_loc'
:
(
techLoc
).
toString
(),
'radius'
:
(
radius
).
toString
(),
};
final
res
=
await
post
(
data
,
crmNearbyGeneratorsUrl
,
{});
if
(
res
!=
null
)
{
print
(
" input data:
$data
"
);
debugPrint
(
"Map api response
${res.body}
"
);
return
NearbyGeneratorsResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
}
else
{
debugPrint
(
"Null Response"
);
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
'hello bev=bug
$e
'
);
return
null
;
}
}
static
Future
<
AccountSuggestionResonse
?>
AccountSuggestionAPI
(
static
Future
<
AccountSuggestionResonse
?>
AccountSuggestionAPI
(
empId
,
empId
,
session
,
session
,
...
@@ -965,6 +997,34 @@ class ApiCalling {
...
@@ -965,6 +997,34 @@ class ApiCalling {
return
null
;
return
null
;
}
}
}
}
/// service Complaint Bill List Api
static
Future
<
ServiceComplaintBillListResponse
?>
serviceComplaintBillListAPI
(
empId
,
session
,
complaintId
,
)
async
{
try
{
Map
<
String
,
String
>
data
=
{
'emp_id'
:
(
empId
).
toString
(),
'session_id'
:
(
session
).
toString
(),
'complaint_id'
:
(
complaintId
).
toString
(),
};
debugPrint
(
"@@@@@@@@@@@@@@@@@@@@@@ input data:
$data
"
);
final
res
=
await
post
(
data
,
serviceComplaintBillListUrl
,
{});
if
(
res
!=
null
)
{
debugPrint
(
res
.
body
);
return
ServiceComplaintBillListResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
}
else
{
debugPrint
(
"Null Response"
);
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
'###########Exception
$e
'
);
return
null
;
}
}
static
Future
<
TechnicianPendingComplaintsResponse
?>
static
Future
<
TechnicianPendingComplaintsResponse
?>
LoadTechnicianComplaintsAPI
(
empId
,
session
)
async
{
LoadTechnicianComplaintsAPI
(
empId
,
session
)
async
{
...
@@ -1218,15 +1278,17 @@ class ApiCalling {
...
@@ -1218,15 +1278,17 @@ class ApiCalling {
session
,
session
,
compId
,
compId
,
)
async
{
)
async
{
try
{
try
{
Map
<
String
,
String
>
data
=
{
Map
<
String
,
String
>
data
=
{
'emp_id'
:
(
empId
).
toString
(),
'emp_id'
:
(
empId
).
toString
(),
'session_id'
:
(
session
).
toString
(),
'session_id'
:
(
session
).
toString
(),
'comp_id'
:
(
compId
).
toString
(),
'comp_id'
:
(
compId
).
toString
(),
};
};
debugPrint
(
"&&&&&&&&&&&&&&&&&&&&&&& input:
$data
"
);
final
res
=
await
post
(
data
,
technicianComplaintFollowUpUrl
,
{});
final
res
=
await
post
(
data
,
technicianComplaintFollowUpUrl
,
{});
if
(
res
!=
null
)
{
if
(
res
!=
null
)
{
debugPrint
(
res
.
body
);
debugPrint
(
"followup response
${
res.body
}
"
);
return
FollowupListResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
return
FollowupListResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
}
else
{
}
else
{
debugPrint
(
"Null Response"
);
debugPrint
(
"Null Response"
);
...
@@ -1750,6 +1812,68 @@ class ApiCalling {
...
@@ -1750,6 +1812,68 @@ class ApiCalling {
}
}
}
}
static
Future
<
CommonResponse
?>
commonUpdateAccountDetailsAPI
(
empId
,
sessionId
,
accId
,
name
,
mob1
,
mob2
,
tel
,
email
,
designation
,
address
,
state
,
district
,
subLocality
,
bankName
,
branchName
,
bankIfscCode
,
accHolderName
,
bankAccNumber
,
bankUpiId
,
)
async
{
try
{
Map
<
String
,
String
>
data
=
{
'emp_id'
:
empId
.
toString
(),
'session_id'
:
sessionId
.
toString
(),
'acc_id'
:
accId
.
toString
(),
'name'
:
name
.
toString
(),
'mob1'
:
mob1
.
toString
(),
'mob2'
:
mob2
.
toString
(),
'tel'
:
tel
.
toString
(),
'email'
:
email
.
toString
(),
'designation'
:
designation
.
toString
(),
'address'
:
address
.
toString
(),
'state'
:
state
.
toString
(),
'district'
:
district
.
toString
(),
'sub_locality'
:
subLocality
.
toString
(),
'bank_name'
:
bankName
.
toString
(),
'bank_branch_name'
:
branchName
.
toString
(),
'bank_ifsc_code'
:
bankIfscCode
.
toString
(),
'bank_account_holder_name'
:
accHolderName
.
toString
(),
'bank_account_number'
:
bankAccNumber
.
toString
(),
'bank_upi_id'
:
bankUpiId
.
toString
(),
};
var
res
=
await
post
(
data
,
commonUpdateAccountDetailsUrl
,
{});
if
(
res
!=
null
)
{
print
(
"Input Date:
$data
"
);
debugPrint
(
res
.
body
);
return
CommonResponse
.
fromJson
(
jsonDecode
(
res
.
body
),
);
}
else
{
debugPrint
(
"Null Response"
);
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
'hello bev=bug
$e
'
);
return
null
;
}
}
static
Future
<
paymentRequestionBankDetailsResponse
?>
static
Future
<
paymentRequestionBankDetailsResponse
?>
paymentRequestionBankDetailsAPI
(
empId
,
session
,
accountId
)
async
{
paymentRequestionBankDetailsAPI
(
empId
,
session
,
accountId
)
async
{
try
{
try
{
...
@@ -2300,6 +2424,31 @@ class ApiCalling {
...
@@ -2300,6 +2424,31 @@ class ApiCalling {
}
}
}
}
static
Future
<
EditCommonAccFormDetailsResponse
?>
commonAccountDetailsListAPI
(
empId
,
session
,
accountId
,
)
async
{
try
{
Map
<
String
,
String
>
data
=
{
'emp_id'
:
(
empId
).
toString
(),
'session_id'
:
(
session
).
toString
(),
'acc_id'
:
accountId
.
toString
(),
};
final
res
=
await
post
(
data
,
commonAccountDetailsUrl
,
{});
if
(
res
!=
null
)
{
debugPrint
(
res
.
body
);
return
EditCommonAccFormDetailsResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
}
else
{
debugPrint
(
"Null Response"
);
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
'hello bev=bug
$e
'
);
return
null
;
}
}
static
Future
<
commonAccountLedgerFilterResponse
?>
static
Future
<
commonAccountLedgerFilterResponse
?>
commonAccountLedgerDropDownAPI
(
empId
,
session
)
async
{
commonAccountLedgerDropDownAPI
(
empId
,
session
)
async
{
try
{
try
{
...
@@ -5701,7 +5850,7 @@ class ApiCalling {
...
@@ -5701,7 +5850,7 @@ class ApiCalling {
empId
,
empId
,
pageNumber
pageNumber
)
async
{
)
async
{
debugPrint
(
"
🔥🔥🔥🔥🔥🔥🔥
Response"
);
debugPrint
(
"Response"
);
try
{
try
{
Map
<
String
,
String
>
data
=
{
Map
<
String
,
String
>
data
=
{
'session_id'
:
(
session
).
toString
(),
'session_id'
:
(
session
).
toString
(),
...
@@ -5710,7 +5859,7 @@ class ApiCalling {
...
@@ -5710,7 +5859,7 @@ class ApiCalling {
final
res
=
await
post
(
data
,
EmployeeContactListUrl
,
{});
final
res
=
await
post
(
data
,
EmployeeContactListUrl
,
{});
if
(
res
!=
null
)
{
if
(
res
!=
null
)
{
print
(
"Request Data:
$data
"
);
print
(
"Request Data:
$data
"
);
debugPrint
(
"
🔥🔥🔥🔥🔥🔥🔥
Response:
${res.body}
"
);
debugPrint
(
" Response:
${res.body}
"
);
return
ContactListResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
return
ContactListResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
}
else
{
}
else
{
debugPrint
(
"Null Response"
);
debugPrint
(
"Null Response"
);
...
@@ -5739,6 +5888,7 @@ class ApiCalling {
...
@@ -5739,6 +5888,7 @@ class ApiCalling {
'ref_id'
:
(
refId
),
'ref_id'
:
(
refId
),
};
};
debugPrint
(
"Input to QR :
$data
"
);
final
res
=
await
post
(
data
,
createRazorpayUpiQrUrl
,
{});
final
res
=
await
post
(
data
,
createRazorpayUpiQrUrl
,
{});
if
(
res
!=
null
)
{
if
(
res
!=
null
)
{
print
(
data
);
print
(
data
);
...
@@ -5821,4 +5971,29 @@ class ApiCalling {
...
@@ -5821,4 +5971,29 @@ class ApiCalling {
// return null;
// return null;
// }
// }
// }
// }
static
Future
<
CommonResponse
?>
trackLiveLocationEmpolyeeAPI
(
empId
,
session
,
location
)
async
{
try
{
Map
<
String
,
String
>
data
=
{
'emp_id'
:
(
empId
).
toString
(),
'session_id'
:
(
session
).
toString
(),
'location'
:
(
location
),
};
// print(data);
final
res
=
await
post
(
data
,
liveLocationStatusUrl
,
{});
if
(
res
!=
null
)
{
print
(
"BACKGROUND LOCATION DATA :
${data}
"
);
debugPrint
(
"BACKGROUND LOCATION:
${res.body}
"
);
// print("check_session: ${res.body}");
return
CommonResponse
.
fromJson
(
jsonDecode
(
res
.
body
));
}
else
{
debugPrint
(
"Null Response"
);
return
null
;
}
}
catch
(
e
)
{
debugPrint
(
'hello bev=bug
$e
'
);
return
null
;
}
}
}
}
lib/services/api_names.dart
View file @
7ba7402c
const
baseUrl
=
"https://erp.gengroup.in/ci/app/"
;
const
baseUrl
=
"https://erp.gengroup.in/ci/app/"
;
const
baseUrl_test
=
"https://erp.gengroup.in/ci/app/Api_home/"
;
const
baseUrl_test
=
"https://erp.gengroup.in/ci/app/Api_home/"
;
const
trackingUrl
=
"https://erp.gengroup.in/ci/app/Home/"
;
// var WEB_SOCKET_URL = "wss://ws.erp.gengroup.in/?type=user&route=employe_live_location_update&session_id=${Sessionid}";
// var WEB_SOCKET_URL = "wss://ws.erp.gengroup.in/?type=user&route=employe_live_location_update&session_id=${Sessionid}";
const
getAppVersionUrl
=
"https://erp.gengroup.in/ci/assets/appversion.json"
;
const
getAppVersionUrl
=
"https://erp.gengroup.in/ci/assets/appversion.json"
;
...
@@ -31,6 +32,7 @@ const genTrackerRegisterComplaint = "${baseUrl}home/gen_tracker_register_complai
...
@@ -31,6 +32,7 @@ const genTrackerRegisterComplaint = "${baseUrl}home/gen_tracker_register_complai
///complaint
///complaint
const
complaintsSelectionUrl
=
"
${baseUrl}
home/compliants_select_data"
;
const
complaintsSelectionUrl
=
"
${baseUrl}
home/compliants_select_data"
;
const
serviceComplaintBillListUrl
=
"
${baseUrl_test}
service_complaint_bill_list"
;
///inventory
///inventory
const
inventoryPartDetailsUrl
=
"
${baseUrl}
home/inventory_part_details"
;
const
inventoryPartDetailsUrl
=
"
${baseUrl}
home/inventory_part_details"
;
...
@@ -51,7 +53,7 @@ const technicianPaymentCollectionOtpUrl= "${baseUrl}home/technician_payment_coll
...
@@ -51,7 +53,7 @@ const technicianPaymentCollectionOtpUrl= "${baseUrl}home/technician_payment_coll
const
technicianPaymentCollectionUrl
=
"
${baseUrl}
home/technician_payment_collection_list"
;
const
technicianPaymentCollectionUrl
=
"
${baseUrl}
home/technician_payment_collection_list"
;
const
technicianWalletCollectionUrl
=
"
${baseUrl}
home/technician_payment_collection_wallet"
;
const
technicianWalletCollectionUrl
=
"
${baseUrl}
home/technician_payment_collection_wallet"
;
const
technicianComplaintDetailsUrl
=
"
${baseUrl}
home/technician_complaint_details"
;
const
technicianComplaintDetailsUrl
=
"
${baseUrl}
home/technician_complaint_details"
;
const
technicianComplaintFollowUpUrl
=
"
${baseUrl}
h
ome/technician_complaint_followup_list"
;
const
technicianComplaintFollowUpUrl
=
"
${baseUrl}
H
ome/technician_complaint_followup_list"
;
const
technicianAddContactUrl
=
"
${baseUrl}
home/technician_add_contact"
;
const
technicianAddContactUrl
=
"
${baseUrl}
home/technician_add_contact"
;
const
technicianUpdateVisitUrl
=
"
${baseUrl}
home/technician_update_visit"
;
const
technicianUpdateVisitUrl
=
"
${baseUrl}
home/technician_update_visit"
;
...
@@ -76,6 +78,8 @@ const paymentRequesitionPaymentsReceiptsDetailsUrl = "${baseUrl_test}payment_rec
...
@@ -76,6 +78,8 @@ const paymentRequesitionPaymentsReceiptsDetailsUrl = "${baseUrl_test}payment_rec
const
paymentRequesitionEditProcessedPaymentUrl
=
"
${baseUrl_test}
edit_processes_payment"
;
const
paymentRequesitionEditProcessedPaymentUrl
=
"
${baseUrl_test}
edit_processes_payment"
;
const
validateGstNumberUrl
=
"
${baseUrl_test}
validate_gst_number"
;
const
validateGstNumberUrl
=
"
${baseUrl_test}
validate_gst_number"
;
const
validateBankAccountDetailsUrl
=
"
${baseUrl_test}
validate_bank_account_details"
;
const
validateBankAccountDetailsUrl
=
"
${baseUrl_test}
validate_bank_account_details"
;
const
commonUpdateAccountDetailsUrl
=
"
${baseUrl_test}
common_update_account_details"
;
///common Module
///common Module
const
commonAccessiblePagesUrl
=
"
${baseUrl_test}
common_accessible_pages"
;
const
commonAccessiblePagesUrl
=
"
${baseUrl_test}
common_accessible_pages"
;
...
@@ -88,6 +92,7 @@ const commonAccountListUrl = "${baseUrl_test}common_account_list_v2";
...
@@ -88,6 +92,7 @@ const commonAccountListUrl = "${baseUrl_test}common_account_list_v2";
const
commonAccountLedgerDropDownUrl
=
"
${baseUrl_test}
common_account_ledger_list_view"
;
const
commonAccountLedgerDropDownUrl
=
"
${baseUrl_test}
common_account_ledger_list_view"
;
const
commonAccountLedgerListWithFilterUrl
=
"
${baseUrl_test}
common_account_ledger_list_submit_filter_v2"
;
const
commonAccountLedgerListWithFilterUrl
=
"
${baseUrl_test}
common_account_ledger_list_submit_filter_v2"
;
const
commonAccountLedgerAccountDetails
=
"
${baseUrl_test}
common_account_details"
;
const
commonAccountLedgerAccountDetails
=
"
${baseUrl_test}
common_account_details"
;
const
commonAccountDetailsUrl
=
"
${baseUrl_test}
common_account_list_v2"
;
///order Module
///order Module
const
ordersAccessiblePagesUrl
=
"
${baseUrl_test}
crm_order_accessible_pages"
;
const
ordersAccessiblePagesUrl
=
"
${baseUrl_test}
crm_order_accessible_pages"
;
...
@@ -183,6 +188,7 @@ const crmDashboardQuotationsUrl = "${baseUrl_test}crm_dashboard_quotations_list"
...
@@ -183,6 +188,7 @@ const crmDashboardQuotationsUrl = "${baseUrl_test}crm_dashboard_quotations_list"
const
ogcharturl
=
"
${baseUrl_test}
organisation_structures"
;
const
ogcharturl
=
"
${baseUrl_test}
organisation_structures"
;
const
JobDesciptionUrl
=
"
${baseUrl_test}
job_description"
;
const
JobDesciptionUrl
=
"
${baseUrl_test}
job_description"
;
const
crmNearbyGeneratorsUrl
=
"
${baseUrl_test}
crm_nearby_generators"
;
///HRM
///HRM
//Attendance
//Attendance
...
@@ -211,4 +217,5 @@ const AdvanceListUrl ="${baseUrl_test}advance_list";
...
@@ -211,4 +217,5 @@ const AdvanceListUrl ="${baseUrl_test}advance_list";
const
createRazorpayUpiQrUrl
=
"
${baseUrl_test}
create_razorpay_upi_qr"
;
const
createRazorpayUpiQrUrl
=
"
${baseUrl_test}
create_razorpay_upi_qr"
;
const
fetchRazorpayUpiQrStatusUrl
=
"
${baseUrl_test}
fetch_razorpay_upi_qr_status"
;
const
fetchRazorpayUpiQrStatusUrl
=
"
${baseUrl_test}
fetch_razorpay_upi_qr_status"
;
\ No newline at end of file
const
liveLocationStatusUrl
=
"
${trackingUrl}
sattendance_live_location_update"
;
\ No newline at end of file
pubspec.lock
View file @
7ba7402c
...
@@ -445,10 +445,10 @@ packages:
...
@@ -445,10 +445,10 @@ packages:
dependency: transitive
dependency: transitive
description:
description:
name: fake_async
name: fake_async
sha256: "
6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc
"
sha256: "
5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44
"
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "1.3.
2
"
version: "1.3.
3
"
ffi:
ffi:
dependency: transitive
dependency: transitive
description:
description:
...
@@ -598,6 +598,14 @@ packages:
...
@@ -598,6 +598,14 @@ packages:
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "1.12.0"
version: "1.12.0"
flutter_foreground_task:
dependency: "direct main"
description:
name: flutter_foreground_task
sha256: "9f1b25a81db95d7119d2c5cffc654048cbdd49d4056183e1beadc1a6a38f3e29"
url: "https://pub.dev"
source: hosted
version: "9.1.0"
flutter_html:
flutter_html:
dependency: "direct main"
dependency: "direct main"
description:
description:
...
@@ -1188,26 +1196,26 @@ packages:
...
@@ -1188,26 +1196,26 @@ packages:
dependency: transitive
dependency: transitive
description:
description:
name: leak_tracker
name: leak_tracker
sha256:
c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
sha256:
"33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "1
0
.0.
8
"
version: "1
1
.0.
2
"
leak_tracker_flutter_testing:
leak_tracker_flutter_testing:
dependency: transitive
dependency: transitive
description:
description:
name: leak_tracker_flutter_testing
name: leak_tracker_flutter_testing
sha256:
f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
sha256:
"1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "3.0.
9
"
version: "3.0.
10
"
leak_tracker_testing:
leak_tracker_testing:
dependency: transitive
dependency: transitive
description:
description:
name: leak_tracker_testing
name: leak_tracker_testing
sha256: "
6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3
"
sha256: "
8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1
"
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "3.0.
1
"
version: "3.0.
2
"
lints:
lints:
dependency: transitive
dependency: transitive
description:
description:
...
@@ -1889,10 +1897,10 @@ packages:
...
@@ -1889,10 +1897,10 @@ packages:
dependency: transitive
dependency: transitive
description:
description:
name: test_api
name: test_api
sha256:
fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
sha256:
"522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "0.7.
4
"
version: "0.7.
6
"
timezone:
timezone:
dependency: transitive
dependency: transitive
description:
description:
...
@@ -2033,10 +2041,10 @@ packages:
...
@@ -2033,10 +2041,10 @@ packages:
dependency: transitive
dependency: transitive
description:
description:
name: vector_math
name: vector_math
sha256:
"80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
sha256:
d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "2.
1.4
"
version: "2.
2.0
"
vm_service:
vm_service:
dependency: transitive
dependency: transitive
description:
description:
...
@@ -2134,5 +2142,5 @@ packages:
...
@@ -2134,5 +2142,5 @@ packages:
source: hosted
source: hosted
version: "3.1.3"
version: "3.1.3"
sdks:
sdks:
dart: ">=3.
7.2
<3.10.0-z"
dart: ">=3.
8.0-0
<3.10.0-z"
flutter: ">=3.27.0"
flutter: ">=3.27.0"
pubspec.yaml
View file @
7ba7402c
...
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
...
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
# of the product and file versions while build-number is used as the build suffix.
version
:
1.0.10
7
+11
5
version
:
1.0.10
8
+11
6
environment
:
environment
:
sdk
:
^3.7.2
sdk
:
^3.7.2
...
@@ -95,6 +95,7 @@ dependencies:
...
@@ -95,6 +95,7 @@ dependencies:
photo_view
:
^0.14.0
photo_view
:
^0.14.0
flutter_contacts
:
^1.1.9+2
flutter_contacts
:
^1.1.9+2
open_filex
:
^4.7.0
open_filex
:
^4.7.0
flutter_foreground_task
:
^9.1.0
dev_dependencies
:
dev_dependencies
:
...
...
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment