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
77774bea
Commit
77774bea
authored
Oct 16, 2025
by
Sai Srinivas
Browse files
Few Correction and fixes
parents
2a8fa440
3ac9e198
Changes
29
Hide whitespace changes
Inline
Side-by-side
android/app/src/main/AndroidManifest.xml
View file @
77774bea
...
@@ -20,6 +20,8 @@
...
@@ -20,6 +20,8 @@
<uses-permission
android:name=
"com.google.android.gms.permission.AD_ID"
/>
<uses-permission
android:name=
"com.google.android.gms.permission.AD_ID"
/>
<uses-permission
android:name=
"android.permission.POST_NOTIFICATIONS"
/>
<uses-permission
android:name=
"android.permission.POST_NOTIFICATIONS"
/>
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.READ_CONTACTS"
/>
<uses-permission
android:name=
"android.permission.WRITE_CONTACTS"
/>
<application
<application
android:name=
"${applicationName}"
android:name=
"${applicationName}"
...
...
assets/svg/hrm/emp_contact_list.svg
0 → 100644
View file @
77774bea
<svg
width=
"19"
height=
"20"
viewBox=
"0 0 19 20"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<g
clip-path=
"url(#clip0_1_6785)"
>
<path
d=
"M18.0696 4.83764C17.9731 3.8836 17.5599 2.99266 16.8994 2.31433C16.2388 1.63599 15.3711 1.21154 14.4419 1.1122L14.4135 1.10929C13.1486 0.969881 11.8774 0.898034 10.6052 0.894043C9.33305 0.8981 8.06197 0.970921 6.79726 1.1122L6.76857 1.11511C5.83994 1.21474 4.97284 1.63891 4.31249 2.31659C3.65214 2.99427 3.23864 3.8843 3.14123 4.83764C3.10581 5.19906 3.07252 5.58848 3.04525 6.00371C2.75509 6.00153 2.46501 6.01452 2.17614 6.04261C2.01088 6.06029 1.85657 6.13577 1.73908 6.25639C1.62159 6.37701 1.54807 6.53543 1.53085 6.70509V6.71018C1.51892 6.81617 1.51253 6.92273 1.51173 7.02942C1.51178 7.15729 1.51816 7.28508 1.53085 7.41229V7.41774C1.54807 7.5874 1.62159 7.74583 1.73908 7.86644C1.85657 7.98706 2.01088 8.06254 2.17614 8.08022C2.39218 8.10313 2.63655 8.11658 2.95282 8.1184C2.93629 8.7707 2.92791 9.46529 2.92767 10.2022C2.92767 10.911 2.93534 11.5802 2.95069 12.21C2.63549 12.2125 2.39182 12.2253 2.17614 12.2485C2.01088 12.2662 1.85657 12.3417 1.73908 12.4623C1.62159 12.5829 1.54807 12.7413 1.53085 12.911V12.9161C1.51892 13.022 1.51254 13.1284 1.51173 13.235C1.51148 13.3636 1.51763 13.4921 1.53014 13.62V13.6251C1.54778 13.7946 1.62157 13.9526 1.73916 14.0729C1.85676 14.1932 2.01102 14.2683 2.17614 14.2858C2.46336 14.3138 2.75178 14.3268 3.04029 14.3247C3.06863 14.7683 3.10192 15.1835 3.14088 15.5667C3.23769 16.5207 3.65097 17.4114 4.31145 18.0897C4.97192 18.768 5.83944 19.1925 6.76857 19.2922L6.7969 19.2951C7.92775 19.4151 9.45809 19.5103 10.6052 19.5103C11.7679 19.5103 13.2834 19.4151 14.4135 19.294L14.4419 19.2911C15.371 19.1918 16.2385 18.7675 16.8991 18.0894C17.5596 17.4113 17.9728 16.5206 18.0696 15.5667C18.2112 14.1691 18.2821 12.3642 18.2821 10.2022C18.2821 8.04023 18.2112 6.23532 18.0696 4.83764ZM10.5539 4.95872C11.0429 4.95872 11.5209 5.10759 11.9275 5.3865C12.3341 5.66541 12.651 6.06184 12.8381 6.52565C13.0252 6.98946 13.0742 7.49982 12.9788 7.9922C12.8834 8.48458 12.6479 8.93686 12.3021 9.29185C11.9564 9.64683 11.5158 9.88858 11.0362 9.98652C10.5566 10.0845 10.0595 10.0342 9.60772 9.84208C9.15594 9.64996 8.7698 9.32463 8.49813 8.90721C8.22646 8.48979 8.08145 7.99903 8.08145 7.49701C8.08141 7.16366 8.14533 6.83357 8.26956 6.52559C8.3938 6.21761 8.57591 5.93777 8.8055 5.70206C9.0351 5.46635 9.30767 5.27938 9.60766 5.15184C9.90765 5.0243 10.2292 4.95867 10.5539 4.95872ZM14.6792 13.624V13.6349C14.6374 14.0088 14.4847 14.3604 14.2418 14.6421C14.0026 14.9292 13.6797 15.1296 13.3209 15.2137C12.811 15.3326 11.5388 15.4493 10.7451 15.4435C9.95108 15.4638 8.39135 15.3373 7.88171 15.213C7.52297 15.1286 7.20016 14.9281 6.96088 14.641C6.71794 14.3593 6.56524 14.0077 6.52349 13.6338V13.6226C6.49677 13.353 6.48849 13.0818 6.4987 12.811C6.4987 12.811 6.47922 12.5721 6.52349 12.1387V12.1278C6.56045 11.7718 6.71551 11.4397 6.96265 11.1872C7.21107 10.9319 7.53667 10.771 7.88596 10.7309C8.39737 10.6752 9.95321 10.6451 10.7444 10.6451C11.5356 10.6451 12.8046 10.6752 13.316 10.7309C13.6653 10.771 13.9908 10.9321 14.2389 11.1875C14.4864 11.4403 14.6415 11.7729 14.6781 12.1293V12.1402C14.7036 12.3632 14.7164 12.5876 14.7163 12.8121C14.718 13.0832 14.7056 13.3543 14.6792 13.624Z"
fill=
"url(#paint0_linear_1_6785)"
/>
<path
d=
"M18.0696 4.83764C17.9731 3.8836 17.5599 2.99266 16.8994 2.31433C16.2388 1.63599 15.3711 1.21154 14.4419 1.1122L14.4135 1.10929C13.1486 0.969881 11.8774 0.898034 10.6052 0.894043C9.33305 0.8981 8.06197 0.970921 6.79726 1.1122L6.76857 1.11511C5.83994 1.21474 4.97284 1.63891 4.31249 2.31659C3.65214 2.99427 3.23864 3.8843 3.14123 4.83764C3.10581 5.19906 3.07252 5.58848 3.04525 6.00371C2.75509 6.00153 2.46501 6.01452 2.17614 6.04261C2.01088 6.06029 1.85657 6.13577 1.73908 6.25639C1.62159 6.37701 1.54807 6.53543 1.53085 6.70509V6.71018C1.51892 6.81617 1.51253 6.92273 1.51173 7.02942C1.51178 7.15729 1.51816 7.28508 1.53085 7.41229V7.41774C1.54807 7.5874 1.62159 7.74583 1.73908 7.86644C1.85657 7.98706 2.01088 8.06254 2.17614 8.08022C2.39218 8.10313 2.63655 8.11658 2.95282 8.1184C2.93629 8.7707 2.92791 9.46529 2.92767 10.2022C2.92767 10.911 2.93534 11.5802 2.95069 12.21C2.63549 12.2125 2.39182 12.2253 2.17614 12.2485C2.01088 12.2662 1.85657 12.3417 1.73908 12.4623C1.62159 12.5829 1.54807 12.7413 1.53085 12.911V12.9161C1.51892 13.022 1.51254 13.1284 1.51173 13.235C1.51148 13.3636 1.51763 13.4921 1.53014 13.62V13.6251C1.54778 13.7946 1.62157 13.9526 1.73916 14.0729C1.85676 14.1932 2.01102 14.2683 2.17614 14.2858C2.46336 14.3138 2.75178 14.3268 3.04029 14.3247C3.06863 14.7683 3.10192 15.1835 3.14088 15.5667C3.23769 16.5207 3.65097 17.4114 4.31145 18.0897C4.97192 18.768 5.83944 19.1925 6.76857 19.2922L6.7969 19.2951C7.92775 19.4151 9.45809 19.5103 10.6052 19.5103C11.7679 19.5103 13.2834 19.4151 14.4135 19.294L14.4419 19.2911C15.371 19.1918 16.2385 18.7675 16.8991 18.0894C17.5596 17.4113 17.9728 16.5206 18.0696 15.5667C18.2112 14.1691 18.2821 12.3642 18.2821 10.2022C18.2821 8.04023 18.2112 6.23532 18.0696 4.83764ZM10.5539 4.95872C11.0429 4.95872 11.5209 5.10759 11.9275 5.3865C12.3341 5.66541 12.651 6.06184 12.8381 6.52565C13.0252 6.98946 13.0742 7.49982 12.9788 7.9922C12.8834 8.48458 12.6479 8.93686 12.3021 9.29185C11.9564 9.64683 11.5158 9.88858 11.0362 9.98652C10.5566 10.0845 10.0595 10.0342 9.60772 9.84208C9.15594 9.64996 8.7698 9.32463 8.49813 8.90721C8.22646 8.48979 8.08145 7.99903 8.08145 7.49701C8.08141 7.16366 8.14533 6.83357 8.26956 6.52559C8.3938 6.21761 8.57591 5.93777 8.8055 5.70206C9.0351 5.46635 9.30767 5.27938 9.60766 5.15184C9.90765 5.0243 10.2292 4.95867 10.5539 4.95872ZM14.6792 13.624V13.6349C14.6374 14.0088 14.4847 14.3604 14.2418 14.6421C14.0026 14.9292 13.6797 15.1296 13.3209 15.2137C12.811 15.3326 11.5388 15.4493 10.7451 15.4435C9.95108 15.4638 8.39135 15.3373 7.88171 15.213C7.52297 15.1286 7.20016 14.9281 6.96088 14.641C6.71794 14.3593 6.56524 14.0077 6.52349 13.6338V13.6226C6.49677 13.353 6.48849 13.0818 6.4987 12.811C6.4987 12.811 6.47922 12.5721 6.52349 12.1387V12.1278C6.56045 11.7718 6.71551 11.4397 6.96265 11.1872C7.21107 10.9319 7.53667 10.771 7.88596 10.7309C8.39737 10.6752 9.95321 10.6451 10.7444 10.6451C11.5356 10.6451 12.8046 10.6752 13.316 10.7309C13.6653 10.771 13.9908 10.9321 14.2389 11.1875C14.4864 11.4403 14.6415 11.7729 14.6781 12.1293V12.1402C14.7036 12.3632 14.7164 12.5876 14.7163 12.8121C14.718 13.0832 14.7056 13.3543 14.6792 13.624Z"
fill=
"url(#paint1_linear_1_6785)"
/>
<path
d=
"M18.0696 4.83764C17.9731 3.8836 17.5599 2.99266 16.8994 2.31433C16.2388 1.63599 15.3711 1.21154 14.4419 1.1122L14.4135 1.10929C13.1486 0.969881 11.8774 0.898034 10.6052 0.894043C9.33305 0.8981 8.06197 0.970921 6.79726 1.1122L6.76857 1.11511C5.83994 1.21474 4.97284 1.63891 4.31249 2.31659C3.65214 2.99427 3.23864 3.8843 3.14123 4.83764C3.10581 5.19906 3.07252 5.58848 3.04525 6.00371C2.75509 6.00153 2.46501 6.01452 2.17614 6.04261C2.01088 6.06029 1.85657 6.13577 1.73908 6.25639C1.62159 6.37701 1.54807 6.53543 1.53085 6.70509V6.71018C1.51892 6.81617 1.51253 6.92273 1.51173 7.02942C1.51178 7.15729 1.51816 7.28508 1.53085 7.41229V7.41774C1.54807 7.5874 1.62159 7.74583 1.73908 7.86644C1.85657 7.98706 2.01088 8.06254 2.17614 8.08022C2.39218 8.10313 2.63655 8.11658 2.95282 8.1184C2.93629 8.7707 2.92791 9.46529 2.92767 10.2022C2.92767 10.911 2.93534 11.5802 2.95069 12.21C2.63549 12.2125 2.39182 12.2253 2.17614 12.2485C2.01088 12.2662 1.85657 12.3417 1.73908 12.4623C1.62159 12.5829 1.54807 12.7413 1.53085 12.911V12.9161C1.51892 13.022 1.51254 13.1284 1.51173 13.235C1.51148 13.3636 1.51763 13.4921 1.53014 13.62V13.6251C1.54778 13.7946 1.62157 13.9526 1.73916 14.0729C1.85676 14.1932 2.01102 14.2683 2.17614 14.2858C2.46336 14.3138 2.75178 14.3268 3.04029 14.3247C3.06863 14.7683 3.10192 15.1835 3.14088 15.5667C3.23769 16.5207 3.65097 17.4114 4.31145 18.0897C4.97192 18.768 5.83944 19.1925 6.76857 19.2922L6.7969 19.2951C7.92775 19.4151 9.45809 19.5103 10.6052 19.5103C11.7679 19.5103 13.2834 19.4151 14.4135 19.294L14.4419 19.2911C15.371 19.1918 16.2385 18.7675 16.8991 18.0894C17.5596 17.4113 17.9728 16.5206 18.0696 15.5667C18.2112 14.1691 18.2821 12.3642 18.2821 10.2022C18.2821 8.04023 18.2112 6.23532 18.0696 4.83764ZM10.5539 4.95872C11.0429 4.95872 11.5209 5.10759 11.9275 5.3865C12.3341 5.66541 12.651 6.06184 12.8381 6.52565C13.0252 6.98946 13.0742 7.49982 12.9788 7.9922C12.8834 8.48458 12.6479 8.93686 12.3021 9.29185C11.9564 9.64683 11.5158 9.88858 11.0362 9.98652C10.5566 10.0845 10.0595 10.0342 9.60772 9.84208C9.15594 9.64996 8.7698 9.32463 8.49813 8.90721C8.22646 8.48979 8.08145 7.99903 8.08145 7.49701C8.08141 7.16366 8.14533 6.83357 8.26956 6.52559C8.3938 6.21761 8.57591 5.93777 8.8055 5.70206C9.0351 5.46635 9.30767 5.27938 9.60766 5.15184C9.90765 5.0243 10.2292 4.95867 10.5539 4.95872ZM14.6792 13.624V13.6349C14.6374 14.0088 14.4847 14.3604 14.2418 14.6421C14.0026 14.9292 13.6797 15.1296 13.3209 15.2137C12.811 15.3326 11.5388 15.4493 10.7451 15.4435C9.95108 15.4638 8.39135 15.3373 7.88171 15.213C7.52297 15.1286 7.20016 14.9281 6.96088 14.641C6.71794 14.3593 6.56524 14.0077 6.52349 13.6338V13.6226C6.49677 13.353 6.48849 13.0818 6.4987 12.811C6.4987 12.811 6.47922 12.5721 6.52349 12.1387V12.1278C6.56045 11.7718 6.71551 11.4397 6.96265 11.1872C7.21107 10.9319 7.53667 10.771 7.88596 10.7309C8.39737 10.6752 9.95321 10.6451 10.7444 10.6451C11.5356 10.6451 12.8046 10.6752 13.316 10.7309C13.6653 10.771 13.9908 10.9321 14.2389 11.1875C14.4864 11.4403 14.6415 11.7729 14.6781 12.1293V12.1402C14.7036 12.3632 14.7164 12.5876 14.7163 12.8121C14.718 13.0832 14.7056 13.3543 14.6792 13.624Z"
fill=
"url(#paint2_linear_1_6785)"
/>
</g>
<defs>
<linearGradient
id=
"paint0_linear_1_6785"
x1=
"1.51102"
y1=
"10.2022"
x2=
"18.2831"
y2=
"10.2022"
gradientUnits=
"userSpaceOnUse"
>
<stop
stop-color=
"#0080DE"
/>
<stop
offset=
"0.6"
stop-color=
"#49BCFF"
/>
<stop
offset=
"1"
stop-color=
"#61CAFF"
/>
</linearGradient>
<linearGradient
id=
"paint1_linear_1_6785"
x1=
"9.89689"
y1=
"9.14823"
x2=
"19.7339"
y2=
"31.5884"
gradientUnits=
"userSpaceOnUse"
>
<stop
stop-color=
"#B2B1FF"
/>
<stop
offset=
"1"
stop-color=
"#6563FF"
/>
</linearGradient>
<linearGradient
id=
"paint2_linear_1_6785"
x1=
"-4.27562"
y1=
"-3.49093"
x2=
"17.2947"
y2=
"29.8665"
gradientUnits=
"userSpaceOnUse"
>
<stop
stop-color=
"#B2B1FF"
/>
<stop
offset=
"1"
stop-color=
"#6563FF"
/>
</linearGradient>
<clipPath
id=
"clip0_1_6785"
>
<rect
width=
"18.1332"
height=
"18.6163"
fill=
"white"
transform=
"translate(0.808594 0.894043)"
/>
</clipPath>
</defs>
</svg>
ios/Runner/Info.plist
View file @
77774bea
...
@@ -2,6 +2,10 @@
...
@@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist
version=
"1.0"
>
<plist
version=
"1.0"
>
<dict>
<dict>
<!-- here is ok or not this BELOW the URL types section, NOT inside it -->
<key>
NSContactsUsageDescription
</key>
<string>
This app needs access to your contacts to add and view contacts.
</string>
<key>
CFBundleDevelopmentRegion
</key>
<key>
CFBundleDevelopmentRegion
</key>
<string>
$(DEVELOPMENT_LANGUAGE)
</string>
<string>
$(DEVELOPMENT_LANGUAGE)
</string>
<key>
CFBundleDisplayName
</key>
<key>
CFBundleDisplayName
</key>
...
...
lib/Models/MissedCheckoutStripResponse.dart
View file @
77774bea
...
@@ -5,7 +5,10 @@ class MissedCheckoutStripResponse {
...
@@ -5,7 +5,10 @@ class MissedCheckoutStripResponse {
int
?
sessionExists
;
int
?
sessionExists
;
MissedCheckoutStripResponse
(
MissedCheckoutStripResponse
(
{
this
.
error
,
this
.
visibleText
,
this
.
message
,
this
.
sessionExists
});
{
this
.
error
,
this
.
visibleText
,
this
.
message
,
this
.
sessionExists
}
);
MissedCheckoutStripResponse
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
MissedCheckoutStripResponse
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
error
=
json
[
'error'
];
error
=
json
[
'error'
];
...
...
lib/Models/hrmModels/contactListResponse.dart
0 → 100644
View file @
77774bea
class
ContactListResponse
{
String
?
error
;
List
<
EmpContactList
>?
empContactList
;
String
?
message
;
int
?
sessionExists
;
ContactListResponse
(
{
this
.
error
,
this
.
empContactList
,
this
.
message
,
this
.
sessionExists
});
ContactListResponse
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
error
=
json
[
'error'
];
if
(
json
[
'emp_contact_list'
]
!=
null
)
{
empContactList
=
<
EmpContactList
>[];
json
[
'emp_contact_list'
].
forEach
((
v
)
{
empContactList
!.
add
(
new
EmpContactList
.
fromJson
(
v
));
});
}
message
=
json
[
'message'
];
sessionExists
=
json
[
'session_exists'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'error'
]
=
this
.
error
;
if
(
this
.
empContactList
!=
null
)
{
data
[
'emp_contact_list'
]
=
this
.
empContactList
!.
map
((
v
)
=>
v
.
toJson
()).
toList
();
}
data
[
'message'
]
=
this
.
message
;
data
[
'session_exists'
]
=
this
.
sessionExists
;
return
data
;
}
}
class
EmpContactList
{
String
?
name
;
String
?
mobileNumber
;
String
?
designation
;
String
?
branchName
;
String
?
profileImage
;
EmpContactList
(
{
this
.
name
,
this
.
mobileNumber
,
this
.
designation
,
this
.
branchName
});
EmpContactList
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
name
=
json
[
'name'
];
mobileNumber
=
json
[
'mobile_number'
];
designation
=
json
[
'designation'
];
branchName
=
json
[
'branch_name'
];
profileImage
=
json
[
'profile_image'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'name'
]
=
this
.
name
;
data
[
'mobile_number'
]
=
this
.
mobileNumber
;
data
[
'designation'
]
=
this
.
designation
;
data
[
'branch_name'
]
=
this
.
branchName
;
data
[
'profile_image'
]
=
this
.
profileImage
;
return
data
;
}
}
lib/Notifiers/PaymentDetailsProvider.dart
View file @
77774bea
...
@@ -223,19 +223,31 @@ class Paymentdetailsprovider extends ChangeNotifier {
...
@@ -223,19 +223,31 @@ class Paymentdetailsprovider extends ChangeNotifier {
}
}
}
}
Future
<
void
>
PaymentUpdateAPI
(
BuildContext
context
,
reference
,
amount
)
async
{
bool
_isPaymentUpdating
=
false
;
bool
get
isPaymentUpdating
=>
_isPaymentUpdating
;
set
isPaymentUpdating
(
bool
value
)
{
_isPaymentUpdating
=
value
;
notifyListeners
();
}
Future
<
void
>
PaymentUpdateAPI
(
BuildContext
context
,
reference
,
amount
,
)
async
{
if
(
_isPaymentUpdating
)
return
;
// 🛑 prevent re-tap
_isPaymentUpdating
=
true
;
notifyListeners
();
try
{
try
{
// if(!CheckValidations(context,reference, amount)){
// return;
// }
if
(!
validateSubmit
(
context
))
{
if
(!
validateSubmit
(
context
))
{
_isPaymentUpdating
=
false
;
notifyListeners
();
return
;
return
;
}
}
print
(
"came here"
);
var
homeProvider
=
Provider
.
of
<
HomescreenNotifier
>(
var
homeProvider
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
context
,
listen:
false
,
);
final
data
=
await
ApiCalling
.
TechnicianUpdatepaymentAPI
(
final
data
=
await
ApiCalling
.
TechnicianUpdatepaymentAPI
(
homeProvider
.
empId
,
homeProvider
.
empId
,
homeProvider
.
session
,
homeProvider
.
session
,
...
@@ -250,30 +262,40 @@ class Paymentdetailsprovider extends ChangeNotifier {
...
@@ -250,30 +262,40 @@ class Paymentdetailsprovider extends ChangeNotifier {
);
);
if
(
data
!=
null
)
{
if
(
data
!=
null
)
{
if
(
data
.
sessionExists
==
1
)
{
if
(
data
.
sessionExists
==
1
&&
data
.
error
==
0
)
{
if
(
data
.
error
==
0
)
{
_CollectionId
=
data
.
paymentCollectionId
??
0
;
print
(
data
.
paymentCollectionId
);
notifyListeners
();
_CollectionId
=
data
.
paymentCollectionId
??
0
;
notifyListeners
();
Future
.
delayed
(
const
Duration
(
milliseconds:
200
),
()
{
Future
.
delayed
(
Duration
(
microseconds:
200
),
()
{
if
(
_CollectionId
!=
0
&&
context
.
mounted
)
{
if
(
_CollectionId
!=
0
)
{
showOTPSheetSheet
(
context
);
showOTPSheetSheet
(
context
);
}
}
});
});
}
else
if
(
context
.
mounted
)
{
}
else
{}
toast
(
context
,
data
.
message
??
"Payment update failed"
);
}
else
{
// SharedpreferencesService().clearPreferences();
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => Splash()),
// );
}
}
}
else
{
if
(
context
.
mounted
)
toast
(
context
,
"No response from server"
);
}
}
}
on
Error
catch
(
e
)
{
}
catch
(
e
,
s
)
{
debugPrint
(
e
.
toString
());
debugPrint
(
"💥 PaymentUpdateAPI error:
$e
\n
$s
"
);
if
(
context
.
mounted
)
toast
(
context
,
"Something went wrong"
);
}
finally
{
_isPaymentUpdating
=
false
;
notifyListeners
();
}
}
}
}
bool
_isOtpProcessing
=
false
;
bool
get
isOtpProcessing
=>
_isOtpProcessing
;
set
isOtpProcessing
(
bool
value
)
{
_isOtpProcessing
=
value
;
notifyListeners
();
}
Future
<
void
>
showOTPSheetSheet
(
BuildContext
context
)
{
Future
<
void
>
showOTPSheetSheet
(
BuildContext
context
)
{
return
showModalBottomSheet
(
return
showModalBottomSheet
(
useSafeArea:
true
,
useSafeArea:
true
,
...
@@ -502,12 +524,32 @@ class Paymentdetailsprovider extends ChangeNotifier {
...
@@ -502,12 +524,32 @@ class Paymentdetailsprovider extends ChangeNotifier {
return
isValid
;
return
isValid
;
}
}
bool
_isResendingOtp
=
false
;
bool
get
isResendingOtp
=>
_isResendingOtp
;
bool
_isVerifyingOtp
=
false
;
bool
get
isVerifyingOtp
=>
_isVerifyingOtp
;
void
setResendingOtp
(
bool
value
)
{
print
(
"🔄 setResendingOtp:
$_isResendingOtp
→
$value
"
);
_isResendingOtp
=
value
;
notifyListeners
();
}
void
setVerifyingOtp
(
bool
value
)
{
print
(
"🔄 setVerifyingOtp:
$_isVerifyingOtp
→
$value
"
);
_isVerifyingOtp
=
value
;
notifyListeners
();
}
Future
<
void
>
OTPVerifyAPI
(
BuildContext
context
)
async
{
Future
<
void
>
OTPVerifyAPI
(
BuildContext
context
)
async
{
if
(
_isVerifyingOtp
)
return
;
print
(
"🎯 OTPVerifyAPI STARTED"
);
setVerifyingOtp
(
true
);
try
{
try
{
var
homeProvider
=
Provider
.
of
<
HomescreenNotifier
>(
var
homeProvider
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
context
,
listen:
false
,
);
final
data
=
await
ApiCalling
.
TechnicianPaymentOTPValidateAPI
(
final
data
=
await
ApiCalling
.
TechnicianPaymentOTPValidateAPI
(
homeProvider
.
empId
,
homeProvider
.
empId
,
homeProvider
.
session
,
homeProvider
.
session
,
...
@@ -515,81 +557,72 @@ class Paymentdetailsprovider extends ChangeNotifier {
...
@@ -515,81 +557,72 @@ class Paymentdetailsprovider extends ChangeNotifier {
_enteredOtp
,
_enteredOtp
,
);
);
if
(
data
!=
null
)
{
print
(
"📡 OTP API Response:
${data?.error}
-
${data?.message}
"
);
if
(
data
.
sessionExists
==
1
)
{
if
(
data
.
error
==
0
)
{
if
(
data
!=
null
&&
data
.
sessionExists
==
1
)
{
toast
(
context
,
data
.
message
);
if
(
data
.
error
==
0
)
{
_selectContact
=
null
;
print
(
"✅ OTP SUCCESS"
);
_selectPaymentModeList
=
null
;
toast
(
context
,
"✅
${data.message}
"
);
_paymentModeID
=
""
;
_PaymentMode
=
""
;
// Keep the loading visible for success feedback
_contactID
=
""
;
await
Future
.
delayed
(
const
Duration
(
milliseconds:
1000
));
_contact
=
""
;
Amountcontroller
.
clear
();
// Reset data
Referencecontroller
.
clear
();
_selectContact
=
null
;
nameController
.
clear
();
Amountcontroller
.
clear
();
designationController
.
clear
();
Referencecontroller
.
clear
();
mobController
.
clear
();
notifyListeners
();
altMobController
.
clear
();
telController
.
clear
();
// Only close the sheet after showing success
emailController
.
clear
();
if
(
context
.
mounted
&&
Navigator
.
canPop
(
context
))
{
_imageName
=
null
;
print
(
"🚪 Closing sheet on success"
);
_image_picked
=
0
;
selectContactError
=
null
;
selectPaymentError
=
null
;
selectAmountError
=
null
;
ReferenceError
=
null
;
imageError
=
null
;
notifyListeners
();
Navigator
.
pop
(
context
,
true
);
Navigator
.
pop
(
context
,
true
);
Navigator
.
pop
(
context
,
true
);
}
else
{
toast
(
context
,
data
.
message
);
}
}
}
else
{
}
else
{
// SharedpreferencesService().clearPreferences();
print
(
"❌ OTP ERROR:
${data.message}
"
);
// toast(context, data.message);
toast
(
context
,
"❌
${data.message}
"
);
// Navigator.push(
// Don't close the sheet - let user try again
// context,
// MaterialPageRoute(builder: (context) => Splash()),
// );
}
}
}
else
{}
}
else
{
}
on
Error
catch
(
e
)
{
print
(
"❌ API ERROR: Null response or session issue"
);
debugPrint
(
e
.
toString
());
toast
(
context
,
"Something went wrong"
);
}
}
catch
(
e
)
{
print
(
"💥 OTP EXCEPTION:
$e
"
);
toast
(
context
,
"Something went wrong"
);
}
finally
{
print
(
"🏁 OTPVerifyAPI COMPLETED"
);
setVerifyingOtp
(
false
);
}
}
}
}
Future
<
void
>
ResendOtpAPI
(
BuildContext
context
)
async
{
Future
<
void
>
ResendOtpAPI
(
BuildContext
context
)
async
{
if
(
_isResendingOtp
)
return
;
print
(
"🎯 ResendOtpAPI STARTED"
);
setResendingOtp
(
true
);
try
{
try
{
var
homeProvider
=
Provider
.
of
<
HomescreenNotifier
>(
var
homeProvider
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
context
,
listen:
false
,
);
final
data
=
await
ApiCalling
.
TechnicianPaymentOTPResendAPI
(
final
data
=
await
ApiCalling
.
TechnicianPaymentOTPResendAPI
(
homeProvider
.
empId
,
homeProvider
.
empId
,
homeProvider
.
session
,
homeProvider
.
session
,
_CollectionId
,
_CollectionId
,
);
);
if
(
data
!=
null
)
{
print
(
"📡 Resend API Response:
${data?.message}
"
);
if
(
data
.
sessionExists
==
1
)
{
if
(
data
.
error
==
0
)
{
if
(
data
!=
null
&&
data
.
sessionExists
==
1
)
{
toast
(
context
,
data
.
message
);
toast
(
context
,
data
.
message
??
"OTP resent successfully"
);
}
else
{
}
else
{
toast
(
context
,
data
.
message
);
toast
(
context
,
"Failed to resend OTP"
);
}
}
}
else
{
}
catch
(
e
)
{
// SharedpreferencesService().clearPreferences();
print
(
"💥 Resend EXCEPTION:
$e
"
);
// toast(context, data.message);
toast
(
context
,
"Something went wrong"
);
// Navigator.push(
}
finally
{
// context,
print
(
"🏁 ResendOtpAPI COMPLETED"
);
// MaterialPageRoute(builder: (context) => Splash()),
setResendingOtp
(
false
);
// );
}
}
else
{}
}
on
Error
catch
(
e
)
{
debugPrint
(
e
.
toString
());
}
}
}
}
...
...
lib/Notifiers/crmProvider/addNewLeadsandProspectsProvider.dart
View file @
77774bea
...
@@ -21,6 +21,7 @@ import '../../Models/crmModels/GetSourceOnReferenceResponse.dart';
...
@@ -21,6 +21,7 @@ import '../../Models/crmModels/GetSourceOnReferenceResponse.dart';
import
'../../Models/crmModels/GetSubLocOnDistrictResponse.dart'
;
import
'../../Models/crmModels/GetSubLocOnDistrictResponse.dart'
;
import
'../../Models/crmModels/crmNewLeadsProspectsViewResponse.dart'
;
import
'../../Models/crmModels/crmNewLeadsProspectsViewResponse.dart'
;
import
'../../Utils/commonServices.dart'
;
import
'../../Utils/commonServices.dart'
;
import
'../../Utils/custom_snackbar.dart'
;
import
'../../services/api_calling.dart'
;
import
'../../services/api_calling.dart'
;
import
'../HomeScreenNotifier.dart'
;
import
'../HomeScreenNotifier.dart'
;
...
@@ -614,21 +615,32 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
...
@@ -614,21 +615,32 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
}
catch
(
e
)
{}
}
catch
(
e
)
{}
}
}
bool
_isSubmitting
=
false
;
bool
get
isSubmitting
=>
_isSubmitting
;
set
isSubmitting
(
bool
value
)
{
_isSubmitting
=
value
;
notifyListeners
();
}
Future
<
void
>
crmAddNewLeadsAndProspectsAPIFunction
(
Future
<
void
>
crmAddNewLeadsAndProspectsAPIFunction
(
BuildContext
context
,
BuildContext
context
,
mode
,
mode
,
accManagerId
,
accManagerId
,
salutationName
,
salutationName
,
district
,
district
,
state
,
state
,
segment
,
segment
,
source
,
source
,
reference
,
reference
,
team
,
team
,
subLocality
,
subLocality
,
leadStatus
,
leadStatus
,
products
,
products
,
)
async
{
)
async
{
if
(
_isSubmitting
)
return
;
// 🛑 Prevent double taps
_isSubmitting
=
true
;
notifyListeners
();
try
{
try
{
final
prov
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
final
prov
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
final
data
=
await
ApiCalling
.
crmNewLeadsProspectsSubmitAPI
(
final
data
=
await
ApiCalling
.
crmNewLeadsProspectsSubmitAPI
(
...
@@ -655,33 +667,68 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
...
@@ -655,33 +667,68 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
leadStatus
,
leadStatus
,
products
,
products
,
);
);
if
(
data
!=
null
)
{
if
(
data
.
error
==
"0"
)
{
// ✅ Add debug print
Navigator
.
pushAndRemoveUntil
(
print
(
"🎯 API RESPONSE:
$data
"
);
context
,
if
(
data
==
null
)
{
print
(
"❌ API returned null response"
);
if
(
context
.
mounted
)
toast
(
context
,
"No response from server"
);
return
;
}
// ✅ Show debug info
print
(
"✅ API Error Code:
${data.error}
"
);
print
(
"✅ Message:
${data.message}
"
);
print
(
"✅ Lead ID:
${data.leadId}
"
);
if
(
data
.
error
==
"0"
)
{
// 🕓 Small delay helps if widget rebuilds before navigation
await
Future
.
delayed
(
const
Duration
(
milliseconds:
200
));
if
(
context
.
mounted
)
{
// ✅ Use root navigator so it always works
Navigator
.
of
(
context
,
rootNavigator:
true
).
pushAndRemoveUntil
(
MaterialPageRoute
(
MaterialPageRoute
(
builder:
builder:
(
_
)
=>
LeadDetailsByMode
(
(
context
)
=>
LeadDetailsByMode
(
mode:
"executive"
,
mode:
"executive"
,
pageTitleName:
"Lead Details"
,
pageTitleName:
"Lead Details"
,
leadId:
data
.
leadId
??
"-"
,
leadId:
data
.
leadId
??
"-"
,
),
),
settings:
const
RouteSettings
(
name:
"LeadDetailsByMode"
),
settings:
RouteSettings
(
name:
"LeadDetailsByMode"
),
),
),
(
Route
<
dynamic
>
route
)
{
(
Route
<
dynamic
>
route
)
=>
route
.
settings
.
name
==
'CrmdashboardScreen'
,
return
route
.
settings
.
name
==
'CrmdashboardScreen'
;
},
);
);
toast
(
context
,
data
.
message
);
resetForm
();
// ✅ Show success toast/snackbar AFTER navigation
notifyListeners
();
Future
.
delayed
(
const
Duration
(
milliseconds:
500
),
()
{
}
else
{}
if
(
context
.
mounted
)
{
}
else
{}
toast
(
context
,
data
.
message
??
"Lead added successfully"
);
}
});
}
resetForm
();
notifyListeners
();
}
else
{
// ❌ Server returned an error
if
(
context
.
mounted
)
{
toast
(
context
,
data
.
message
??
"Something went wrong"
);
}
}
}
catch
(
e
,
s
)
{
}
catch
(
e
,
s
)
{
print
(
"Error:
$e
, Stack:
$s
"
);
print
(
"💥 Exception during CRM submit:
$e
"
);
print
(
"📜 Stack:
$s
"
);
if
(
context
.
mounted
)
{
toast
(
context
,
"Unexpected error:
${e.toString()}
"
);
}
}
finally
{
_isSubmitting
=
false
;
notifyListeners
();
}
}
}
}
Future
<
void
>
crmSelectedProductDetailsApiFunction
(
Future
<
void
>
crmSelectedProductDetailsApiFunction
(
BuildContext
context
,
BuildContext
context
,
String
productId
,
String
productId
,
...
...
lib/Notifiers/financeProvider/RequesitionLidtDetailsProvider.dart
View file @
77774bea
...
@@ -357,20 +357,37 @@ class Requesitionlidtdetailsprovider extends ChangeNotifier {
...
@@ -357,20 +357,37 @@ class Requesitionlidtdetailsprovider extends ChangeNotifier {
notifyListeners
();
notifyListeners
();
}
}
Future
<
void
>
paymentrequisitionRejectSubmitAPIFunction
(
Future
<
bool
>
paymentrequisitionRejectSubmitAPIFunction
(
context
,
context
,
mode
,
mode
,
paymentRequestId
,
paymentRequestId
,
approveRemarks
,
approveRemarks
,
)
async
{
)
async
{
print
(
"🎯 === REJECT PROVIDER METHOD STARTED ==="
);
// Set loading to true at the start
_isLoading
=
true
;
notifyListeners
();
print
(
"🔄 Loading set to TRUE in reject method"
);
bool
success
=
false
;
try
{
try
{
print
(
"🔍 Starting validation for rejection..."
);
if
(
approveRemarks
.
toString
().
trim
().
isEmpty
)
{
if
(
approveRemarks
.
toString
().
trim
().
isEmpty
)
{
print
(
"❌ Remarks validation failed"
);
remarksError
=
"Please Enter Remarks"
;
remarksError
=
"Please Enter Remarks"
;
_isLoading
=
false
;
notifyListeners
();
notifyListeners
();
// toast(context,"Enter Remarks");
return
false
;
return
;
}
}
print
(
"✅ Validation passed"
);
var
provider
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
var
provider
=
Provider
.
of
<
HomescreenNotifier
>(
context
,
listen:
false
);
print
(
"🌐 Calling reject API..."
);
final
data
=
await
ApiCalling
.
RejectPaymentRequestSubmitAPI
(
final
data
=
await
ApiCalling
.
RejectPaymentRequestSubmitAPI
(
provider
.
empId
,
provider
.
empId
,
provider
.
session
,
provider
.
session
,
...
@@ -378,18 +395,60 @@ class Requesitionlidtdetailsprovider extends ChangeNotifier {
...
@@ -378,18 +395,60 @@ class Requesitionlidtdetailsprovider extends ChangeNotifier {
paymentRequestId
,
paymentRequestId
,
approveRemarks
,
approveRemarks
,
);
);
print
(
"🌐 Reject API call completed"
);
if
(
data
!=
null
)
{
if
(
data
!=
null
)
{
print
(
"📡 Reject API Response: error=
${data.error}
, message=
${data.message}
"
);
if
(
data
.
error
==
"0"
)
{
if
(
data
.
error
==
"0"
)
{
paymentRequesitionDetails
(
context
,
paymentRequestId
);
print
(
"✅ Reject API SUCCESS"
);
resetAll
();
success
=
true
;
toast
(
context
,
data
.
message
);
Navigator
.
pop
(
context
);
if
(
context
.
mounted
)
{
print
(
"🎯 Context mounted - performing UI operations"
);
paymentRequesitionDetails
(
context
,
paymentRequestId
);
resetAll
();
toast
(
context
,
data
.
message
);
Navigator
.
pop
(
context
,
true
);
// Pass true to indicate success
}
}
else
{
print
(
"❌ Reject API returned error:
${data.message}
"
);
if
(
context
.
mounted
)
{
toast
(
context
,
data
.
message
??
"Rejection failed"
);
}
}
}
else
{
print
(
"❌ NULL response from reject API"
);
if
(
context
.
mounted
)
{
toast
(
context
,
"No response from server"
);
}
}
}
}
}
catch
(
e
)
{}
}
catch
(
e
)
{
print
(
"💥 EXCEPTION in reject provider method:
$e
"
);
if
(
context
.
mounted
)
{
toast
(
context
,
"Error:
${e.toString()}
"
);
}
}
finally
{
// Always set loading to false when done
_isLoading
=
false
;
notifyListeners
();
print
(
"🔄 Loading set to FALSE in reject method finally block"
);
}
print
(
"🎯 === REJECT PROVIDER METHOD COMPLETED ==="
);
return
success
;
}
}
Future
<
void
>
paymentrequisitionApproveSubmitAPIFunction
(
bool
_isLoading
=
false
;
bool
get
isLoading
=>
_isLoading
;
set
isLoading
(
bool
value
)
{
_isLoading
=
value
;
notifyListeners
();
}
Future
<
void
>
paymentrequisitionApproveSubmitAPIFunction
(
//this is
BuildContext
context
,
BuildContext
context
,
String
mode
,
String
mode
,
String
payment_request_id
,
String
payment_request_id
,
...
@@ -399,10 +458,16 @@ class Requesitionlidtdetailsprovider extends ChangeNotifier {
...
@@ -399,10 +458,16 @@ class Requesitionlidtdetailsprovider extends ChangeNotifier {
)
async
{
)
async
{
print
(
"🎯 === PROVIDER METHOD STARTED ==="
);
print
(
"🎯 === PROVIDER METHOD STARTED ==="
);
// Set loading to true at the start
_isLoading
=
true
;
notifyListeners
();
try
{
try
{
print
(
"🔍 Starting validation..."
);
print
(
"🔍 Starting validation..."
);
if
(!
validateApproval
(
approved_amount
,
approve_remarks
,
proposed_payment_account_id
))
{
if
(!
validateApproval
(
approved_amount
,
approve_remarks
,
proposed_payment_account_id
))
{
print
(
"❌ VALIDATION FAILED - Stopping execution"
);
print
(
"❌ VALIDATION FAILED - Stopping execution"
);
_isLoading
=
false
;
notifyListeners
();
return
;
return
;
}
}
print
(
"✅ Validation passed"
);
print
(
"✅ Validation passed"
);
...
@@ -462,13 +527,17 @@ class Requesitionlidtdetailsprovider extends ChangeNotifier {
...
@@ -462,13 +527,17 @@ class Requesitionlidtdetailsprovider extends ChangeNotifier {
if
(
context
.
mounted
)
{
if
(
context
.
mounted
)
{
toast
(
context
,
"Error:
${e.toString()}
"
);
toast
(
context
,
"Error:
${e.toString()}
"
);
}
}
}
finally
{
// Set loading to false when everything is done (success or error)
_isLoading
=
false
;
notifyListeners
();
print
(
"🔄 Loading state set to false"
);
}
}
print
(
"🎯 === PROVIDER METHOD COMPLETED ==="
);
print
(
"🎯 === PROVIDER METHOD COMPLETED ==="
);
}
}
editPrevalues
()
{
editPrevalues
()
{
editPaymentRequestedAmountController
.
text
=
editPaymentRequestedAmountController
.
text
=
_requestDetails
.
requestedAmount
??
"-"
;
_requestDetails
.
requestedAmount
??
"-"
;
...
...
lib/Notifiers/hrmProvider/contact_provider.dart
0 → 100644
View file @
77774bea
import
'package:flutter/material.dart'
;
import
'../../Models/hrmModels/contactListResponse.dart'
;
import
'../../services/api_calling.dart'
;
class
ContactProvider
with
ChangeNotifier
{
bool
_isLoading
=
false
;
ContactListResponse
?
_contactResponse
;
bool
get
isLoading
=>
_isLoading
;
ContactListResponse
?
get
contactResponse
=>
_contactResponse
;
List
<
EmpContactList
>
get
contactList
=>
_contactResponse
?.
empContactList
??
[];
/// Fetch contact list from API
Future
<
void
>
fetchContactList
(
String
session
,
String
empId
,
int
pageNumber
)
async
{
_isLoading
=
true
;
notifyListeners
();
try
{
final
response
=
await
ApiCalling
.
contactListAPI
(
session
,
empId
,
pageNumber
);
_contactResponse
=
response
;
}
catch
(
e
)
{
debugPrint
(
"❌ Error fetching contact list:
$e
"
);
_contactResponse
=
null
;
}
finally
{
_isLoading
=
false
;
notifyListeners
();
}
}
/// Optional: To clear the list
void
clearContacts
()
{
_contactResponse
=
null
;
notifyListeners
();
}
}
lib/Utils/custom_snackbar.dart
0 → 100644
View file @
77774bea
import
'package:flutter/material.dart'
;
class
CustomSnackBar
{
static
void
showSuccess
({
required
BuildContext
context
,
required
String
message
,
Duration
duration
=
const
Duration
(
seconds:
3
),
})
{
_showCustomSnackBar
(
context:
context
,
message:
message
,
backgroundColor:
const
Color
(
0xFF4CAF50
),
// Green
icon:
Icons
.
check_circle
,
duration:
duration
,
);
}
static
void
showError
({
required
BuildContext
context
,
required
String
message
,
Duration
duration
=
const
Duration
(
seconds:
4
),
})
{
_showCustomSnackBar
(
context:
context
,
message:
message
,
backgroundColor:
const
Color
(
0xFFF44336
),
// Red
icon:
Icons
.
error
,
duration:
duration
,
);
}
static
void
showInfo
({
required
BuildContext
context
,
required
String
message
,
Duration
duration
=
const
Duration
(
seconds:
3
),
})
{
_showCustomSnackBar
(
context:
context
,
message:
message
,
backgroundColor:
const
Color
(
0xFF2196F3
),
// Blue
icon:
Icons
.
info
,
duration:
duration
,
);
}
static
void
showWarning
({
required
BuildContext
context
,
required
String
message
,
Duration
duration
=
const
Duration
(
seconds:
4
),
})
{
_showCustomSnackBar
(
context:
context
,
message:
message
,
backgroundColor:
const
Color
(
0xFFFF9800
),
// Orange
icon:
Icons
.
warning
,
duration:
duration
,
);
}
static
void
showLoading
({
required
BuildContext
context
,
required
String
message
,
Duration
duration
=
const
Duration
(
seconds:
5
),
})
{
_showCustomSnackBar
(
context:
context
,
message:
message
,
backgroundColor:
const
Color
(
0xFF2d2d2d
),
// Dark gray
icon:
Icons
.
hourglass_empty
,
isLoading:
true
,
duration:
duration
,
);
}
static
void
_showCustomSnackBar
({
required
BuildContext
context
,
required
String
message
,
required
Color
backgroundColor
,
required
IconData
icon
,
bool
isLoading
=
false
,
Duration
duration
=
const
Duration
(
seconds:
3
),
})
{
ScaffoldMessenger
.
of
(
context
).
hideCurrentSnackBar
();
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
backgroundColor:
backgroundColor
,
duration:
duration
,
elevation:
6
,
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
12
),
),
behavior:
SnackBarBehavior
.
floating
,
margin:
const
EdgeInsets
.
all
(
16
),
content:
Row
(
children:
[
if
(
isLoading
)
SizedBox
(
width:
20
,
height:
20
,
child:
CircularProgressIndicator
(
strokeWidth:
2
,
valueColor:
AlwaysStoppedAnimation
<
Color
>(
Colors
.
white
),
),
)
else
Icon
(
icon
,
color:
Colors
.
white
,
size:
20
,
),
const
SizedBox
(
width:
12
),
Expanded
(
child:
Text
(
message
,
style:
const
TextStyle
(
fontFamily:
"Plus Jakarta Sans"
,
fontWeight:
FontWeight
.
w500
,
fontSize:
14
,
color:
Colors
.
white
,
),
),
),
],
),
),
);
}
static
void
hide
(
BuildContext
context
)
{
ScaffoldMessenger
.
of
(
context
).
hideCurrentSnackBar
();
}
}
\ No newline at end of file
lib/main.dart
View file @
77774bea
...
@@ -423,6 +423,7 @@ class MyApp extends StatelessWidget {
...
@@ -423,6 +423,7 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider
(
create:
(
_
)
=>
Orgprovider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
Orgprovider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
AdvanceListProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
AdvanceListProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
CasualLeaveHistoryProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
CasualLeaveHistoryProvider
()),
ChangeNotifierProvider
(
create:
(
_
)
=>
ContactProvider
()),
],
],
child:
Builder
(
child:
Builder
(
...
...
lib/screens/AttendanceScreen.dart
View file @
77774bea
...
@@ -535,7 +535,7 @@ class _AttendanceScreenState extends State<AttendanceScreen> {
...
@@ -535,7 +535,7 @@ class _AttendanceScreenState extends State<AttendanceScreen> {
[
'S'
,
'M'
,
'T'
,
'W'
,
'T'
,
'F'
,
'S'
][
i
],
[
'S'
,
'M'
,
'T'
,
'W'
,
'T'
,
'F'
,
'S'
][
i
],
textAlign:
TextAlign
.
center
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
getResponsiveTextSize
(
context
,
1
5
),
fontSize:
getResponsiveTextSize
(
context
,
1
3
),
overflow:
TextOverflow
.
ellipsis
,
overflow:
TextOverflow
.
ellipsis
,
color:
color:
i
==
0
i
==
0
...
@@ -677,7 +677,7 @@ class _AttendanceScreenState extends State<AttendanceScreen> {
...
@@ -677,7 +677,7 @@ class _AttendanceScreenState extends State<AttendanceScreen> {
child:
Text
(
child:
Text
(
currentDay
.
toString
(),
currentDay
.
toString
(),
style:
TextStyle
(
style:
TextStyle
(
fontSize:
getResponsiveTextSize
(
context
,
1
3
),
fontSize:
getResponsiveTextSize
(
context
,
1
2
),
fontWeight:
FontWeight
.
w400
,
fontWeight:
FontWeight
.
w400
,
color:
color:
isFutureDate
isFutureDate
...
@@ -870,8 +870,8 @@ class _AttendanceScreenState extends State<AttendanceScreen> {
...
@@ -870,8 +870,8 @@ class _AttendanceScreenState extends State<AttendanceScreen> {
Expanded
(
Expanded
(
flex:
1
,
flex:
1
,
child:
Container
(
child:
Container
(
width:
2
5
,
width:
2
4
,
height:
2
5
,
height:
2
4
,
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
shape:
BoxShape
.
circle
,
shape:
BoxShape
.
circle
,
color:
colors
[
index
],
color:
colors
[
index
],
...
...
lib/screens/HomeScreen.dart
View file @
77774bea
...
@@ -11,6 +11,7 @@ import 'package:generp/Utils/commonWidgets.dart';
...
@@ -11,6 +11,7 @@ import 'package:generp/Utils/commonWidgets.dart';
import
'../Utils/commonServices.dart'
;
import
'../Utils/commonServices.dart'
;
import
'JobDescription.dart'
;
import
'JobDescription.dart'
;
import
'genTracker/ScanEnterGeneratorIDScreen.dart'
;
import
'genTracker/ScanEnterGeneratorIDScreen.dart'
;
import
'hrm/ContactList.dart'
;
import
'hrm/HrmDashboardScreen.dart'
;
import
'hrm/HrmDashboardScreen.dart'
;
import
'notifierExports.dart'
;
import
'notifierExports.dart'
;
import
'screensExports.dart'
;
import
'screensExports.dart'
;
...
@@ -264,7 +265,7 @@ class _MyHomePageState extends State<MyHomePage> {
...
@@ -264,7 +265,7 @@ class _MyHomePageState extends State<MyHomePage> {
clipBehavior:
Clip
.
none
,
clipBehavior:
Clip
.
none
,
children:
[
children:
[
// ---------------- MISSED CHECKOUT STRIP BACKGROUND ----------------
// ---------------- MISSED CHECKOUT STRIP BACKGROUND ----------------
if
(
profile
.
missedCheckoutData
?.
error
!
=
"
1
"
)
if
(
profile
.
missedCheckoutData
?.
error
=
=
"
0
"
)
Container
(
Container
(
height:
214
,
// Taller than the profile card
height:
214
,
// Taller than the profile card
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
...
@@ -672,6 +673,7 @@ class _MyHomePageState extends State<MyHomePage> {
...
@@ -672,6 +673,7 @@ class _MyHomePageState extends State<MyHomePage> {
),
),
),
),
),
),
Container
(
Container
(
padding:
EdgeInsets
.
symmetric
(
padding:
EdgeInsets
.
symmetric
(
vertical:
15
,
vertical:
15
,
...
@@ -835,6 +837,104 @@ class _MyHomePageState extends State<MyHomePage> {
...
@@ -835,6 +837,104 @@ class _MyHomePageState extends State<MyHomePage> {
),
),
),
),
],
],
SizedBox
(
height:
16
,),
// Emp contact list
InkResponse
(
onTap:
()
async
{
HapticFeedback
.
selectionClick
();
var
res
=
await
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
ContactListScreen
(),
),
);
if
(
res
==
true
)
{
homescreen
.
DashboardApiFunction
(
context
,
);
}
},
child:
Container
(
margin:
EdgeInsets
.
symmetric
(
horizontal:
10
,
),
padding:
EdgeInsets
.
symmetric
(
vertical:
15
,
horizontal:
15
,
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
14
),
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
Expanded
(
flex:
1
,
child:
Container
(
height:
42
,
width:
42
,
decoration:
BoxDecoration
(
shape:
BoxShape
.
circle
,
color:
const
Color
(
0xFFEDF8FF
),
),
child:
Center
(
child:
SvgPicture
.
asset
(
"assets/svg/hrm/emp_contact_list.svg"
,
color:
Color
(
0xFF1487C9
),
height:
24
,
width:
24
,
),
),
),
),
SizedBox
(
width:
10
),
Expanded
(
flex:
5
,
child:
SizedBox
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
"Employee Contacts"
,
style:
TextStyle
(
fontSize:
14
,
color:
AppColors
.
app_blue
,
fontFamily:
"JakartaMedium"
,
),
),
Text
(
"Contact Details, Whatsapp"
,
style:
TextStyle
(
fontSize:
14
,
color:
AppColors
.
grey_semi
,
fontFamily:
"JakartaMedium"
,
),
),
],
),
),
),
],
),
),
),
SizedBox
(
height:
4
,),
Container
(
Container
(
margin:
EdgeInsets
.
only
(
margin:
EdgeInsets
.
only
(
left:
10
,
left:
10
,
...
@@ -1151,6 +1251,102 @@ class _MyHomePageState extends State<MyHomePage> {
...
@@ -1151,6 +1251,102 @@ class _MyHomePageState extends State<MyHomePage> {
},
},
),
),
),
),
SizedBox
(
height:
16
,),
// Emp contact list
InkResponse
(
onTap:
()
async
{
HapticFeedback
.
selectionClick
();
var
res
=
await
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
ContactListScreen
(),
),
);
if
(
res
==
true
)
{
homescreen
.
DashboardApiFunction
(
context
,
);
}
},
child:
Container
(
margin:
EdgeInsets
.
symmetric
(
horizontal:
10
,
),
padding:
EdgeInsets
.
symmetric
(
vertical:
15
,
horizontal:
15
,
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
14
),
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
Expanded
(
flex:
1
,
child:
Container
(
height:
42
,
width:
42
,
decoration:
BoxDecoration
(
shape:
BoxShape
.
circle
,
color:
const
Color
(
0xFFEDF8FF
),
),
child:
Center
(
child:
SvgPicture
.
asset
(
"assets/svg/hrm/emp_contact_list.svg"
,
color:
Color
(
0xFF1487C9
),
height:
24
,
width:
24
,
),
),
),
),
SizedBox
(
width:
10
),
Expanded
(
flex:
5
,
child:
SizedBox
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
"Employee Contacts"
,
style:
TextStyle
(
fontSize:
14
,
color:
AppColors
.
app_blue
,
fontFamily:
"JakartaMedium"
,
),
),
Text
(
"Contact Details, Whatsapp"
,
style:
TextStyle
(
fontSize:
14
,
color:
AppColors
.
grey_semi
,
fontFamily:
"JakartaMedium"
,
),
),
],
),
),
),
],
),
),
),
SizedBox
(
height:
4
,),
],
],
],
],
...
...
lib/screens/crm/addLeadProductScreen.dart
View file @
77774bea
...
@@ -11,6 +11,7 @@ import 'package:provider/provider.dart';
...
@@ -11,6 +11,7 @@ import 'package:provider/provider.dart';
import
'../../Utils/app_colors.dart'
;
import
'../../Utils/app_colors.dart'
;
import
'../../Utils/commonServices.dart'
;
import
'../../Utils/commonServices.dart'
;
import
'../../Utils/commonWidgets.dart'
;
import
'../../Utils/commonWidgets.dart'
;
import
'../../Utils/custom_snackbar.dart'
;
import
'../../Utils/dropdownTheme.dart'
;
import
'../../Utils/dropdownTheme.dart'
;
class
Addleadproductscreen
extends
StatefulWidget
{
class
Addleadproductscreen
extends
StatefulWidget
{
...
@@ -286,35 +287,28 @@ class _AddleadproductscreenState extends State<Addleadproductscreen> {
...
@@ -286,35 +287,28 @@ class _AddleadproductscreenState extends State<Addleadproductscreen> {
// Validate required fields
// Validate required fields
if
(
provider
.
selectedProducts
==
null
)
{
if
(
provider
.
selectedProducts
==
null
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
//
SnackBar
(
CustomSnackBar
.
showWarning
(
content:
Text
(
"Please select a product"
),
context:
context
,
backgroundColor:
Colors
.
red
,
message:
"Please select a product"
,
duration:
Duration
(
seconds:
2
),
),
);
);
return
;
return
;
}
}
if
(
provider
.
addProductPriceController
.
text
.
isEmpty
)
{
if
(
provider
.
addProductPriceController
.
text
.
isEmpty
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
CustomSnackBar
.
showWarning
(
SnackBar
(
context:
context
,
content:
Text
(
"Please enter product price"
),
message:
"Please enter product price"
,
backgroundColor:
Colors
.
red
,
duration:
Duration
(
seconds:
2
),
),
);
);
return
;
return
;
}
}
if
(
provider
.
addQuantityController
.
text
.
isEmpty
)
{
if
(
provider
.
addQuantityController
.
text
.
isEmpty
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
CustomSnackBar
.
showWarning
(
SnackBar
(
context:
context
,
content:
Text
(
"Please enter quantity"
),
message:
"Please enter quantity"
,
backgroundColor:
Colors
.
red
,
duration:
Duration
(
seconds:
2
),
),
);
);
return
;
return
;
}
}
...
@@ -338,14 +332,11 @@ class _AddleadproductscreenState extends State<Addleadproductscreen> {
...
@@ -338,14 +332,11 @@ class _AddleadproductscreenState extends State<Addleadproductscreen> {
print
(
"Product data:
${provider.getJsonEncodedProducts()}
"
);
print
(
"Product data:
${provider.getJsonEncodedProducts()}
"
);
// Show success message
// Show success message
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
CustomSnackBar
.
showSuccess
(
SnackBar
(
context:
context
,
content:
Text
(
widget
.
editIndex
!=
null
message:
widget
.
editIndex
!=
null
?
"Product updated successfully!"
?
"Product updated successfully!"
:
"Product added successfully!"
),
:
"Product added successfully!"
,
backgroundColor:
Colors
.
green
,
duration:
Duration
(
seconds:
2
),
),
);
);
// Close screen after a short delay to show the success message
// Close screen after a short delay to show the success message
...
...
lib/screens/crm/addLeadsProspectsScreen.dart
View file @
77774bea
...
@@ -18,6 +18,8 @@ import '../../Models/crmModels/GetSegmentOnTeamResponse.dart';
...
@@ -18,6 +18,8 @@ import '../../Models/crmModels/GetSegmentOnTeamResponse.dart';
import
'../../Models/crmModels/GetSourceOnReferenceResponse.dart'
;
import
'../../Models/crmModels/GetSourceOnReferenceResponse.dart'
;
import
'../../Models/crmModels/GetSubLocOnDistrictResponse.dart'
;
import
'../../Models/crmModels/GetSubLocOnDistrictResponse.dart'
;
import
'../../Models/crmModels/crmNewLeadsProspectsViewResponse.dart'
;
import
'../../Models/crmModels/crmNewLeadsProspectsViewResponse.dart'
;
import
'../../Utils/custom_snackbar.dart'
;
import
'LeadDetailsByMode.dart'
;
import
'addLeadProductScreen.dart'
;
import
'addLeadProductScreen.dart'
;
class
Addleadsprospectsscreen
extends
StatefulWidget
{
class
Addleadsprospectsscreen
extends
StatefulWidget
{
...
@@ -1488,58 +1490,65 @@ class _AddleadsprospectsscreenState extends State<Addleadsprospectsscreen> {
...
@@ -1488,58 +1490,65 @@ class _AddleadsprospectsscreenState extends State<Addleadsprospectsscreen> {
return
Column
(
return
Column
(
children:
[
children:
[
if
(
_currentStep
==
2
)
...[
if
(
_currentStep
==
2
)
...[
InkResponse
(
InkResponse
(
onTap:
()
{
onTap:
provider
.
isSubmitting
HapticFeedback
.
selectionClick
();
?
null
// disable taps while submitting
if
(
provider
.
validateStep3
())
{
:
()
{
if
(
provider
.
productRows
.
isNotEmpty
)
{
HapticFeedback
.
selectionClick
();
provider
.
crmAddNewLeadsAndProspectsAPIFunction
(
if
(
provider
.
validateStep3
())
{
context
,
if
(
provider
.
productRows
.
isNotEmpty
)
{
""
,
provider
.
crmAddNewLeadsAndProspectsAPIFunction
(
provider
.
selectedEmployeesId
,
context
,
provider
.
selectedSalutation
,
""
,
provider
.
selectedDistrictId
,
provider
.
selectedEmployeesId
,
provider
.
selectedStatesId
,
provider
.
selectedSalutation
,
provider
.
selectedSegmentId
,
provider
.
selectedDistrictId
,
provider
.
selectedSourcesId
,
provider
.
selectedStatesId
,
provider
.
selectedReferenceId
,
provider
.
selectedSegmentId
,
provider
.
selectedReferenceId
,
provider
.
selectedSourcesId
,
provider
.
selectedSubLocationId
,
provider
.
selectedReferenceId
,
provider
.
selectedLeadStatus
,
provider
.
selectedReferenceId
,
provider
.
getJsonEncodedProducts
(),
provider
.
selectedSubLocationId
,
);
provider
.
selectedLeadStatus
,
}
else
{
provider
.
getJsonEncodedProducts
(),
toast
(
context
,
"Add min. 1 product"
);
);
}
}
else
{
}
toast
(
context
,
"Add min. 1 product"
);
}
}
details
.
onStepContinue
;
details
.
onStepContinue
;
},
},
child:
Container
(
child:
Container
(
height:
45
,
height:
45
,
alignment:
Alignment
.
center
,
alignment:
Alignment
.
center
,
margin:
EdgeInsets
.
symmetric
(
margin:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
10
),
horizontal:
10
,
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
vertical:
5
),
vertical:
10
,
decoration:
BoxDecoration
(
),
color:
provider
.
isSubmitting
padding:
EdgeInsets
.
symmetric
(
?
Colors
.
grey
.
shade400
// disable color
horizontal:
10
,
:
AppColors
.
app_blue
,
vertical:
5
,
borderRadius:
BorderRadius
.
circular
(
15
),
),
),
decoration:
BoxDecoration
(
child:
provider
.
isSubmitting
color:
AppColors
.
app_blue
,
?
const
SizedBox
(
borderRadius:
BorderRadius
.
circular
(
15
),
height:
22
,
),
width:
22
,
child:
Text
(
child:
CircularProgressIndicator
(
"Submit"
,
strokeWidth:
2.3
,
style:
TextStyle
(
valueColor:
AlwaysStoppedAnimation
<
Color
>(
Colors
.
white
),
fontSize:
15
,
fontFamily:
"JakartaMedium"
,
color:
Colors
.
white
,
),
),
),
),
),
)
:
const
Text
(
"Submit"
,
style:
TextStyle
(
fontSize:
15
,
fontFamily:
"JakartaMedium"
,
color:
Colors
.
white
,
),
),
),
),
]
else
...[
]
else
...[
InkResponse
(
InkResponse
(
onTap:
()
{
onTap:
()
{
...
...
lib/screens/finance/AllPaymentRequesitionListsByModes.dart
View file @
77774bea
...
@@ -444,9 +444,7 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -444,9 +444,7 @@ class _AllpaymentrequesitionlistsbymodesState
_showLevelRejectionSheet
(
_showLevelRejectionSheet
(
context
,
context
,
requestLists
[
index
].
id
,
requestLists
[
index
].
id
,
).
then
((
_
)
{
);
provider
.
paymentRequestionListsAPIFunction
(
context
,
widget
.
mode
,
""
,
""
);
});
},
},
backgroundColor:
Color
(
backgroundColor:
Color
(
0xFFFFE5E5
,
0xFFFFE5E5
,
...
@@ -524,10 +522,9 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -524,10 +522,9 @@ class _AllpaymentrequesitionlistsbymodesState
);
);
_showLevelApprovalSheet
(
_showLevelApprovalSheet
(
context
,
context
,
requestLists
[
index
].
id
,
requestLists
[
index
].
id
.
toString
(),
).
then
((
_
)
{
);
provider
.
paymentRequestionListsAPIFunction
(
context
,
widget
.
mode
,
""
,
""
);
});
},
},
backgroundColor:
Color
(
backgroundColor:
Color
(
0xFFE9FFE8
,
0xFFE9FFE8
,
...
@@ -654,7 +651,11 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -654,7 +651,11 @@ class _AllpaymentrequesitionlistsbymodesState
);
);
}
}
Future
<
void
>
_showLevelApprovalSheet
(
BuildContext
context
,
paymentID
)
{
Future
<
void
>
_showLevelApprovalSheet
(
BuildContext
context
,
String
paymentID
)
{
return
showModalBottomSheet
(
return
showModalBottomSheet
(
useSafeArea:
true
,
useSafeArea:
true
,
isDismissible:
true
,
isDismissible:
true
,
...
@@ -859,10 +860,19 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -859,10 +860,19 @@ class _AllpaymentrequesitionlistsbymodesState
),
),
),
),
InkWell
(
InkWell
(
onTap:
()
{
onTap:
provider
.
isLoading
?
null
// Disable tap while loading
:
()
async
{
HapticFeedback
.
selectionClick
();
HapticFeedback
.
selectionClick
();
provider
.
paymentrequisitionApproveSubmitAPIFunction
(
// Immediately show loading
provider
.
isLoading
=
true
;
// Small delay to ensure rebuild and show spinner before API starts
await
Future
.
delayed
(
const
Duration
(
milliseconds:
300
));
// 🔄 Call API
await
provider
.
paymentrequisitionApproveSubmitAPIFunction
(
context
,
context
,
widget
.
mode
,
widget
.
mode
,
paymentID
,
paymentID
,
...
@@ -870,25 +880,36 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -870,25 +880,36 @@ class _AllpaymentrequesitionlistsbymodesState
remarks
.
text
,
remarks
.
text
,
provider
.
selectedID
,
provider
.
selectedID
,
);
);
// 🔓 Stop loading only if context is still active
if
(
context
.
mounted
)
{
provider
.
isLoading
=
false
;
}
},
},
child:
Container
(
child:
AnimatedContainer
(
duration:
const
Duration
(
milliseconds:
200
),
alignment:
Alignment
.
center
,
alignment:
Alignment
.
center
,
height:
45
,
height:
45
,
margin:
EdgeInsets
.
only
(
margin:
const
EdgeInsets
.
symmetric
(
horizontal:
5
,
vertical:
5
),
left:
5.0
,
right:
5.0
,
top:
5.0
,
bottom:
5.0
,
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
AppColors
.
app_blue
,
//1487C9
color:
provider
.
isLoading
?
Colors
.
grey
:
AppColors
.
app_blue
,
borderRadius:
BorderRadius
.
circular
(
14.0
),
borderRadius:
BorderRadius
.
circular
(
14.0
),
),
),
child:
Center
(
child:
Center
(
child:
Text
(
child:
provider
.
isLoading
?
const
SizedBox
(
height:
20
,
width:
20
,
child:
CircularProgressIndicator
(
strokeWidth:
2
,
valueColor:
AlwaysStoppedAnimation
<
Color
>(
Colors
.
white
),
),
)
:
const
Text
(
"Submit"
,
"Submit"
,
///approve
textAlign:
TextAlign
.
center
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
color:
Colors
.
white
),
style:
TextStyle
(
color:
Colors
.
white
),
),
),
...
@@ -911,7 +932,7 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -911,7 +932,7 @@ class _AllpaymentrequesitionlistsbymodesState
// Use the original context with mounted check
// Use the original context with mounted check
if
(
context
.
mounted
)
{
if
(
context
.
mounted
)
{
WidgetsBinding
.
instance
.
addPostFrameCallback
((
timeStamp
)
{
WidgetsBinding
.
instance
.
addPostFrameCallback
((
timeStamp
)
async
{
if
(
context
.
mounted
)
{
if
(
context
.
mounted
)
{
var
provider
=
Provider
.
of
<
Requestionlistprovider
>(
var
provider
=
Provider
.
of
<
Requestionlistprovider
>(
context
,
context
,
...
@@ -929,6 +950,13 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -929,6 +950,13 @@ class _AllpaymentrequesitionlistsbymodesState
""
,
""
,
""
,
""
,
);
);
provider
.
resetPagination
();
await
provider
.
paymentRequestionListsAPIFunction
(
context
,
widget
.
mode
,
""
,
""
,
);
}
}
});
});
}
}
...
@@ -1000,7 +1028,10 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -1000,7 +1028,10 @@ class _AllpaymentrequesitionlistsbymodesState
remarks
,
remarks
,
"Remarks"
,
"Remarks"
,
"Enter Remarks"
,
"Enter Remarks"
,
(
p0
)
{},
(
p0
)
{
provider
.
remarksError
=
null
;
provider
.
notifyListeners
();
},
TextInputType
.
text
,
TextInputType
.
text
,
false
,
false
,
null
,
null
,
...
@@ -1009,11 +1040,20 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -1009,11 +1040,20 @@ class _AllpaymentrequesitionlistsbymodesState
TextInputAction
.
done
,
TextInputAction
.
done
,
),
),
errorWidget
(
context
,
provider
.
remarksError
),
errorWidget
(
context
,
provider
.
remarksError
),
const
SizedBox
(
height:
10
),
InkWell
(
InkWell
(
onTap:
()
{
onTap:
()
{
if
(
provider
.
isLoading
)
{
print
(
"⏸️ Reject button is loading - ignoring tap"
);
return
;
}
HapticFeedback
.
selectionClick
();
HapticFeedback
.
selectionClick
();
provider
.
paymentrequisitionRejectSubmitAPIFunction
(
// Close keyboard
FocusScope
.
of
(
context
).
unfocus
();
provider
.
paymentrequisitionRejectSubmitAPIFunction
(
context
,
context
,
widget
.
mode
,
widget
.
mode
,
paymentID
,
paymentID
,
...
@@ -1030,16 +1070,41 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -1030,16 +1070,41 @@ class _AllpaymentrequesitionlistsbymodesState
bottom:
5.0
,
bottom:
5.0
,
),
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
AppColors
.
app_blue
,
//1487C9
color:
provider
.
isLoading
?
Colors
.
grey
:
AppColors
.
app_blue
,
borderRadius:
BorderRadius
.
circular
(
14.0
),
borderRadius:
BorderRadius
.
circular
(
14.0
),
),
),
child:
Center
(
child:
Center
(
child:
Text
(
child:
provider
.
isLoading
?
Row
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
SizedBox
(
height:
20
,
width:
20
,
child:
CircularProgressIndicator
(
strokeWidth:
2
,
valueColor:
AlwaysStoppedAnimation
<
Color
>(
Colors
.
white
),
),
),
SizedBox
(
width:
10
),
Text
(
"Processing..."
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
16
,
),
),
],
)
:
Text
(
"Submit"
,
"Submit"
,
///reject
textAlign:
TextAlign
.
center
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
color:
Colors
.
white
),
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
16
,
fontWeight:
FontWeight
.
bold
,
),
),
),
),
),
),
),
...
@@ -1077,6 +1142,8 @@ class _AllpaymentrequesitionlistsbymodesState
...
@@ -1077,6 +1142,8 @@ class _AllpaymentrequesitionlistsbymodesState
});
});
}
}
Future
<
void
>
_showAddPaymentSheet
(
BuildContext
context
,
paymentID
)
{
Future
<
void
>
_showAddPaymentSheet
(
BuildContext
context
,
paymentID
)
{
return
showModalBottomSheet
(
return
showModalBottomSheet
(
useSafeArea:
true
,
useSafeArea:
true
,
...
...
lib/screens/finance/PaymentRequestionListDetails.dart
View file @
77774bea
...
@@ -1326,7 +1326,6 @@ class _PaymentrequestionlistdetailsState
...
@@ -1326,7 +1326,6 @@ class _PaymentrequestionlistdetailsState
padding:
EdgeInsets
.
only
(
padding:
EdgeInsets
.
only
(
bottom:
MediaQuery
.
of
(
context
).
viewInsets
.
bottom
,
bottom:
MediaQuery
.
of
(
context
).
viewInsets
.
bottom
,
),
),
child:
SingleChildScrollView
(
child:
SingleChildScrollView
(
child:
Column
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
...
@@ -1407,73 +1406,59 @@ class _PaymentrequestionlistdetailsState
...
@@ -1407,73 +1406,59 @@ class _PaymentrequestionlistdetailsState
style:
TextStyle
(
fontSize:
14
),
style:
TextStyle
(
fontSize:
14
),
overflow:
TextOverflow
.
ellipsis
,
overflow:
TextOverflow
.
ellipsis
,
),
),
items:
items:
provider
.
paymentsAccounts
provider
.
paymentsAccounts
.
map
(
.
map
(
(
paymenents
)
=>
DropdownMenuItem
<
(
paymenents
)
=>
DropdownMenuItem
<
PaymentAccounts
PaymentAccounts
>(
>(
value:
paymenents
,
value:
paymenents
,
child:
Text
(
child:
Text
(
paymenents
.
name
??
''
,
paymenents
.
name
??
''
,
style:
const
TextStyle
(
style:
const
TextStyle
(
fontSize:
14
,
fontSize:
14
,
),
),
overflow:
overflow:
TextOverflow
.
ellipsis
,
TextOverflow
.
ellipsis
,
),
),
),
),
)
)
.
toList
(),
.
toList
(),
value:
provider
.
paymentsAccounts
.
contains
(
value:
provider
.
paymentsAccounts
.
contains
(
provider
.
selectedPaymentAccounts
,
provider
.
selectedPaymentAccounts
,
)
)
?
provider
.
selectedPaymentAccounts
?
provider
.
selectedPaymentAccounts
:
null
,
:
null
,
// value: provider.selectedPaymentAccounts,
onChanged:
provider
.
isLoading
onChanged:
(
PaymentAccounts
?
value
)
{
?
null
// Disable dropdown when loading
:
(
PaymentAccounts
?
value
)
{
if
(
value
!=
null
)
{
if
(
value
!=
null
)
{
if
(
provider
if
(
provider
.
paymentsAccounts
.
isNotEmpty
)
{
.
paymentsAccounts
provider
.
selectedPaymentAccounts
=
value
;
.
isNotEmpty
)
{
provider
.
selectedPaymentAccounts
=
value
;
print
(
print
(
"Selected Complaint Type:
${value.name}
, ID:
${value.id}
"
,
"Selected Complaint Type:
${value.name}
, ID:
${value.id}
"
,
);
);
provider
.
selectedID
=
value
.
id
!;
provider
.
selectedID
=
value
.
id
!;
provider
.
selectedValue
=
value
.
name
!;
provider
.
selectedValue
=
value
.
name
!;
print
(
print
(
"hfjkshfg"
+
"hfjkshfg"
+
provider
.
selectedID
.
toString
(),
provider
.
selectedID
.
toString
(),
);
);
}
}
}
}
},
},
dropdownSearchData:
DropdownSearchData
(
dropdownSearchData:
DropdownSearchData
(
searchInnerWidgetHeight:
50
,
searchInnerWidgetHeight:
50
,
searchController:
searchController:
provider
.
paymentAccountSearchController
,
provider
.
paymentAccountSearchController
,
searchInnerWidget:
Padding
(
searchInnerWidget:
Padding
(
padding:
const
EdgeInsets
.
all
(
8
),
padding:
const
EdgeInsets
.
all
(
8
),
child:
TextFormField
(
child:
TextFormField
(
controller:
controller:
provider
.
paymentAccountSearchController
,
provider
.
paymentAccountSearchController
,
decoration:
InputDecoration
(
decoration:
InputDecoration
(
isDense:
true
,
isDense:
true
,
contentPadding:
contentPadding:
const
EdgeInsets
.
symmetric
(
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
horizontal:
10
,
vertical:
8
,
vertical:
8
,
),
),
hintText:
'Search account...'
,
hintText:
'Search account...'
,
border:
OutlineInputBorder
(
border:
OutlineInputBorder
(
borderRadius:
borderRadius:
BorderRadius
.
circular
(
8
),
BorderRadius
.
circular
(
8
),
),
),
),
),
),
),
...
@@ -1486,21 +1471,16 @@ class _PaymentrequestionlistdetailsState
...
@@ -1486,21 +1471,16 @@ class _PaymentrequestionlistdetailsState
)
??
)
??
false
;
false
;
},
},
// Optional: clear search text when dropdown closes
),
),
onMenuStateChange:
(
isOpen
)
{
onMenuStateChange:
(
isOpen
)
{
if
(!
isOpen
)
{
if
(!
isOpen
)
{
provider
.
paymentAccountSearchController
provider
.
paymentAccountSearchController
.
clear
();
.
clear
();
}
}
},
},
buttonStyleData:
ddtheme
.
buttonStyleData
,
buttonStyleData:
ddtheme
.
buttonStyleData
,
iconStyleData:
ddtheme
.
iconStyleData
,
iconStyleData:
ddtheme
.
iconStyleData
,
menuItemStyleData:
menuItemStyleData:
ddtheme
.
menuItemStyleData
,
ddtheme
.
menuItemStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
dropdownStyleData:
ddtheme
.
dropdownStyleData
,
),
),
),
),
],
],
...
@@ -1510,16 +1490,27 @@ class _PaymentrequestionlistdetailsState
...
@@ -1510,16 +1490,27 @@ class _PaymentrequestionlistdetailsState
context
,
context
,
provider
.
selectpaymentAccountError
,
provider
.
selectpaymentAccountError
,
),
),
const
SizedBox
(
height:
10
),
InkWell
(
InkWell
(
onTap:
()
{
onTap:
()
{
if
(
provider
.
isLoading
)
{
print
(
"⏸️ Button is loading - ignoring tap"
);
return
;
}
print
(
"🖱️ === SUBMIT BUTTON TAPPED ==="
);
print
(
"🖱️ === SUBMIT BUTTON TAPPED ==="
);
print
(
"📋 Mode:
${widget.mode}
"
);
print
(
"📋 Mode:
${widget.mode}
"
);
print
(
"📋 Payment ID:
$paymentID
"
);
print
(
"📋 Payment ID:
$paymentID
"
);
print
(
"📋 Approved Amount:
${provider.approvedAmount.text}
"
);
print
(
"📋 Approved Amount:
${provider.approvedAmount.text}
"
);
print
(
"📋 Remarks:
${remarks.text}
"
);
print
(
"📋 Remarks:
${remarks.text}
"
);
print
(
"📋 Selected Account ID:
${provider.selectedID}
"
);
print
(
"📋 Selected Account ID:
${provider.selectedID}
"
);
provider
.
paymentrequisitionApproveSubmitAPIFunction
(
HapticFeedback
.
selectionClick
();
// Close keyboard
FocusScope
.
of
(
context
).
unfocus
();
provider
.
paymentrequisitionApproveSubmitAPIFunction
(
context
,
context
,
widget
.
mode
,
widget
.
mode
,
paymentID
,
paymentID
,
...
@@ -1538,16 +1529,41 @@ class _PaymentrequestionlistdetailsState
...
@@ -1538,16 +1529,41 @@ class _PaymentrequestionlistdetailsState
bottom:
5.0
,
bottom:
5.0
,
),
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
AppColors
.
app_blue
,
//1487C9
color:
provider
.
isLoading
?
Colors
.
grey
:
AppColors
.
app_blue
,
borderRadius:
BorderRadius
.
circular
(
14.0
),
borderRadius:
BorderRadius
.
circular
(
14.0
),
),
),
child:
Center
(
child:
Center
(
child:
Text
(
child:
provider
.
isLoading
?
Row
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
SizedBox
(
height:
20
,
width:
20
,
child:
CircularProgressIndicator
(
strokeWidth:
2
,
valueColor:
AlwaysStoppedAnimation
<
Color
>(
Colors
.
white
),
),
),
SizedBox
(
width:
10
),
Text
(
"Processing..."
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
16
,
),
),
],
)
:
Text
(
"Submit"
,
"Submit"
,
///approve
textAlign:
TextAlign
.
center
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
color:
Colors
.
white
),
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
16
,
fontWeight:
FontWeight
.
bold
,
),
),
),
),
),
),
),
...
@@ -1575,112 +1591,152 @@ class _PaymentrequestionlistdetailsState
...
@@ -1575,112 +1591,152 @@ class _PaymentrequestionlistdetailsState
enableDrag:
true
,
enableDrag:
true
,
context:
context
,
context:
context
,
builder:
(
context
)
{
builder:
(
context
)
{
return
StatefulBuilder
(
// Remove StatefulBuilder and use only Provider
builder:
(
context
,
setState
)
{
return
SafeArea
(
return
SafeArea
(
child:
Consumer
<
Requesitionlidtdetailsprovider
>(
child:
Consumer
<
Requesitionlidtdetailsprovider
>(
builder:
(
context
,
provider
,
child
)
{
builder:
(
context
,
provider
,
child
)
{
return
Container
(
return
Container
(
margin:
EdgeInsets
.
only
(
margin:
EdgeInsets
.
only
(
bottom:
15
,
bottom:
15
,
left:
15
,
left:
15
,
right:
15
,
right:
15
,
top:
10
,
top:
10
,
),
),
padding:
EdgeInsets
.
only
(
padding:
EdgeInsets
.
only
(
bottom:
MediaQuery
.
of
(
context
).
viewInsets
.
bottom
,
bottom:
MediaQuery
.
of
(
context
).
viewInsets
.
bottom
,
),
),
child:
SingleChildScrollView
(
child:
SingleChildScrollView
(
child:
Column
(
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
mainAxisSize:
MainAxisSize
.
min
,
children:
[
children:
[
if
(
widget
.
mode
==
"apr_lvl1"
)
...[
if
(
widget
.
mode
==
"apr_lvl1"
)
...[
Align
(
Align
(
alignment:
Alignment
.
topLeft
,
alignment:
Alignment
.
topLeft
,
child:
Text
(
child:
Text
(
"Level 1 Rejection"
,
"Level 1 Rejection"
,
style:
TextStyle
(
style:
TextStyle
(
color:
AppColors
.
app_blue
,
color:
AppColors
.
app_blue
,
fontSize:
16
,
fontSize:
16
,
),
),
),
),
]
else
if
(
widget
.
mode
==
"apr_lvl2"
)
...[
),
Align
(
),
alignment:
Alignment
.
topLeft
,
]
else
if
(
widget
.
mode
==
"apr_lvl2"
)
...[
child:
Text
(
Align
(
"Level 2 Rejection"
,
alignment:
Alignment
.
topLeft
,
style
:
Text
Style
(
child
:
Text
(
color:
AppColors
.
app_blue
,
"Level 2 Rejection"
,
fontSize:
16
,
style:
TextStyle
(
)
,
color:
AppColors
.
app_blue
,
)
,
fontSize:
16
,
),
),
],
),
),
],
textControllerReadonlyWidget
(
textControllerReadonlyWidget
(
context
,
context
,
provider
.
requestedAmount
,
provider
.
requestedAmount
,
"Requested Amount"
,
"Requested Amount"
,
(
p0
)
{},
(
p0
)
{},
),
),
textControllerWidget
(
textControllerWidget
(
context
,
remarks
,
"Remarks"
,
"Enter Remarks"
,
(
p0
)
{
provider
.
remarksError
=
null
;
provider
.
notifyListeners
();
},
TextInputType
.
text
,
false
,
null
,
focusNodes
[
2
],
null
,
TextInputAction
.
done
,
),
errorWidget
(
context
,
provider
.
remarksError
),
const
SizedBox
(
height:
10
),
InkWell
(
onTap:
()
{
if
(
provider
.
isLoading
)
{
print
(
"⏸️ Reject button is loading - ignoring tap"
);
return
;
}
print
(
"🖱️ === REJECT BUTTON TAPPED ==="
);
print
(
"📋 Mode:
${widget.mode}
"
);
print
(
"📋 Payment ID:
$paymentID
"
);
print
(
"📋 Remarks:
${remarks.text}
"
);
HapticFeedback
.
selectionClick
();
// Close keyboard
FocusScope
.
of
(
context
).
unfocus
();
provider
.
paymentrequisitionRejectSubmitAPIFunction
(
context
,
context
,
remarks
,
widget
.
mode
,
"Remarks"
,
paymentID
,
"Enter Remarks"
,
remarks
.
text
,
(
p0
)
{},
);
TextInputType
.
text
,
},
false
,
child:
Container
(
null
,
alignment:
Alignment
.
center
,
focusNodes
[
2
],
height:
45
,
null
,
margin:
EdgeInsets
.
only
(
TextInputAction
.
done
,
left:
5.0
,
right:
5.0
,
top:
5.0
,
bottom:
5.0
,
),
),
errorWidget
(
context
,
provider
.
remarksError
),
decoration:
BoxDecoration
(
InkWell
(
color:
provider
.
isLoading
?
Colors
.
grey
:
AppColors
.
app_blue
,
onTap:
()
{
borderRadius:
BorderRadius
.
circular
(
14.0
),
provider
),
.
paymentrequisitionRejectSubmitAPIFunction
(
child:
Center
(
context
,
child:
provider
.
isLoading
widget
.
mode
,
?
Row
(
paymentID
,
mainAxisAlignment:
MainAxisAlignment
.
center
,
remarks
.
text
,
children:
[
);
SizedBox
(
},
height:
20
,
child:
Container
(
width:
20
,
alignment:
Alignment
.
center
,
child:
CircularProgressIndicator
(
height:
45
,
strokeWidth:
2
,
margin:
EdgeInsets
.
only
(
valueColor:
AlwaysStoppedAnimation
<
Color
>(
Colors
.
white
),
left:
5.0
,
),
right:
5.0
,
),
top:
5.0
,
SizedBox
(
width:
10
),
bottom:
5.0
,
Text
(
),
"Processing..."
,
decoration:
BoxDecoration
(
color:
AppColors
.
app_blue
,
//1487C9
borderRadius:
BorderRadius
.
circular
(
14.0
),
),
child:
Center
(
child:
Text
(
"Submit"
,
///reject
textAlign:
TextAlign
.
center
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
color:
Colors
.
white
),
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
16
,
),
),
),
],
)
:
Text
(
"Submit"
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
16
,
fontWeight:
FontWeight
.
bold
,
),
),
),
),
),
),
]
,
)
,
),
),
)
,
]
,
)
;
)
,
}
,
)
,
)
,
)
;
);
},
}
,
)
,
);
);
},
},
);
);
...
...
lib/screens/hrm/AddLiveAttendance.dart
View file @
77774bea
...
@@ -8,6 +8,7 @@ import 'package:image_picker/image_picker.dart';
...
@@ -8,6 +8,7 @@ import 'package:image_picker/image_picker.dart';
import
'package:provider/provider.dart'
;
import
'package:provider/provider.dart'
;
import
'../../Notifiers/hrmProvider/attendanceListProvider.dart'
;
import
'../../Notifiers/hrmProvider/attendanceListProvider.dart'
;
import
'../../Utils/app_colors.dart'
;
import
'../../Utils/app_colors.dart'
;
import
'../../Utils/custom_snackbar.dart'
;
import
'../../Utils/dropdownTheme.dart'
;
import
'../../Utils/dropdownTheme.dart'
;
class
AddLiveAttendanceScreen
extends
StatefulWidget
{
class
AddLiveAttendanceScreen
extends
StatefulWidget
{
...
@@ -224,8 +225,12 @@ class _AddLiveAttendanceScreenState extends State<AddLiveAttendanceScreen> {
...
@@ -224,8 +225,12 @@ class _AddLiveAttendanceScreenState extends State<AddLiveAttendanceScreen> {
}
}
void
_showSnack
(
BuildContext
context
,
String
msg
)
{
void
_showSnack
(
BuildContext
context
,
String
msg
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
// ScaffoldMessenger.of(context).showSnackBar(
SnackBar
(
content:
Text
(
msg
),
backgroundColor:
Colors
.
black87
),
// SnackBar(content: Text(msg), backgroundColor: Colors.black87),
// );
CustomSnackBar
.
showSuccess
(
context:
context
,
message:
"Status:
$msg
"
,
);
);
}
}
...
...
lib/screens/hrm/AddManualAttendance.dart
View file @
77774bea
...
@@ -16,6 +16,7 @@ import '../../Notifiers/hrmProvider/attendanceListProvider.dart';
...
@@ -16,6 +16,7 @@ import '../../Notifiers/hrmProvider/attendanceListProvider.dart';
import
'../../Utils/app_colors.dart'
;
import
'../../Utils/app_colors.dart'
;
import
'../../Utils/commonServices.dart'
;
import
'../../Utils/commonServices.dart'
;
import
'../../Utils/commonWidgets.dart'
;
import
'../../Utils/commonWidgets.dart'
;
import
'../../Utils/custom_snackbar.dart'
;
import
'../../Utils/dropdownTheme.dart'
;
import
'../../Utils/dropdownTheme.dart'
;
class
AddManualAttendanceScreen
extends
StatefulWidget
{
class
AddManualAttendanceScreen
extends
StatefulWidget
{
...
@@ -397,13 +398,10 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
...
@@ -397,13 +398,10 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
// --- Response handling ---
// --- Response handling ---
if
(
provider
.
addResponse
!=
null
&&
provider
.
addResponse
!.
error
==
"0"
)
{
if
(
provider
.
addResponse
!=
null
&&
provider
.
addResponse
!.
error
==
"0"
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
CustomSnackBar
.
showSuccess
(
SnackBar
(
context:
context
,
content:
Text
(
message:
provider
.
addResponse
!.
message
??
provider
.
addResponse
!.
message
??
"Attendance Submitted Successfully"
,
"Attendance Submitted Successfully"
,
),
),
);
);
// Reset fields
// Reset fields
...
...
lib/screens/hrm/AttendanceRequestDetail.dart
View file @
77774bea
...
@@ -398,7 +398,7 @@ class _AttendanceRequestDetailScreenState
...
@@ -398,7 +398,7 @@ class _AttendanceRequestDetailScreenState
provider
.
response
?.
requestDetails
?.
status
!=
provider
.
response
?.
requestDetails
?.
status
!=
"Level 1 Approved"
&&
"Level 1 Approved"
&&
provider
.
response
?.
requestDetails
?.
status
!=
provider
.
response
?.
requestDetails
?.
status
!=
"Rejected"
)
"
Level 1
Rejected"
)
?
Container
(
?
Container
(
decoration:
const
BoxDecoration
(
decoration:
const
BoxDecoration
(
gradient:
LinearGradient
(
gradient:
LinearGradient
(
...
...
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