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_services
Commits
f3a137b2
Commit
f3a137b2
authored
Nov 12, 2025
by
Sai Srinivas
Committed by
Sai Srinivas
Nov 14, 2025
Browse files
12-11-2025 generator Details Screen and sub screens
parent
dd6e2bd2
Changes
220
Show whitespace changes
Inline
Side-by-side
assets/svg/phone_ic.svg
0 → 100644
View file @
f3a137b2
<svg
width=
"25"
height=
"25"
viewBox=
"0 0 25 25"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<path
d=
"M24.2449 17.7605C24.2573 17.6726 19.5713 13.8442 18.0874 14.2192C17.4019 14.373 16.98 14.866 16.1392 15.8474C16.0549 15.9456 15.8989 16.1279 15.7327 16.3169C15.6414 16.4211 15.5215 16.4961 15.3879 16.5327C15.2543 16.5693 15.1129 16.5658 14.9812 16.5227C14.6516 16.4143 14.3277 16.2891 14.0108 16.1477C11.6624 15.1267 9.78878 13.2528 8.76808 10.9043C8.62636 10.5878 8.50119 10.2641 8.39308 9.93457C8.34992 9.80288 8.34634 9.66142 8.3828 9.52771C8.41925 9.39401 8.49413 9.27394 8.59815 9.18237C8.78785 9.01538 8.97169 8.85791 9.07276 8.77149C10.0505 7.93506 10.5449 7.51245 10.6973 6.82617C11.0635 5.34961 7.24391 0.658447 7.15601 0.669434C6.7898 0.244629 6.22071 0.00439453 5.61793 0C4.10328 0.0783692 0.0654383 5.3335 0.00171762 6.2959C-0.00633902 6.33106 -0.0136634 7.6875 0.668221 10.0027C1.37135 12.2966 2.76368 15.5479 6.02223 18.8987C9.37013 22.1536 12.6192 23.5444 14.9116 24.2454C17.2254 24.9265 18.5825 24.9192 18.6177 24.9111C19.5801 24.8438 24.8359 20.8037 24.9165 19.2927C24.9041 18.6929 24.6668 18.1245 24.2449 17.7605Z"
fill=
"url(#paint0_linear_1066_355)"
/>
<defs>
<linearGradient
id=
"paint0_linear_1066_355"
x1=
"20.8347"
y1=
"24.0286"
x2=
"-0.247304"
y2=
"2.94727"
gradientUnits=
"userSpaceOnUse"
>
<stop
stop-color=
"#13B601"
/>
<stop
offset=
"0.57"
stop-color=
"#13B601"
/>
<stop
offset=
"1"
stop-color=
"#CBF4B4"
/>
</linearGradient>
</defs>
</svg>
assets/svg/route_ic.svg
0 → 100644
View file @
f3a137b2
<svg
width=
"42"
height=
"42"
viewBox=
"0 0 42 42"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<circle
cx=
"21"
cy=
"21"
r=
"20.5434"
stroke=
"#1487C9"
stroke-width=
"0.913206"
/>
<g
clip-path=
"url(#clip0_335_3130)"
>
<path
d=
"M30.6512 22.5513L23.8542 19.1922C23.7932 19.1622 23.7213 19.1658 23.664 19.2012C23.6062 19.2369 23.5712 19.3 23.5712 19.3678V21.406H23.2622C21.9389 21.406 20.7139 21.8264 19.7061 22.5358V15.6327H21.7165C21.7844 15.6327 21.8474 15.5977 21.8833 15.5401C21.9191 15.4827 21.9223 15.4108 21.8921 15.3499L18.5346 8.5528C18.5018 8.48611 18.4334 8.44385 18.3591 8.44385C18.2847 8.44385 18.2164 8.48611 18.1834 8.5528L14.8227 15.3498C14.7927 15.4107 14.7963 15.4827 14.8321 15.54C14.8678 15.5977 14.9305 15.6327 14.9984 15.6327H17.0641C17.0641 15.6327 17.0641 26.8763 17.0641 33.5558H19.7061C19.7061 29.3844 19.7061 27.6041 19.7061 27.6041C19.7061 25.6432 21.3014 24.0478 23.2622 24.0478H23.5712V26.0867C23.5712 26.1546 23.6061 26.2176 23.6639 26.253C23.7212 26.2889 23.7931 26.2925 23.8542 26.2624L30.6512 22.9026C30.7178 22.8696 30.7601 22.8013 30.7601 22.7269C30.7601 22.6525 30.7179 22.5842 30.6512 22.5513Z"
fill=
"#1487C9"
/>
</g>
<defs>
<clipPath
id=
"clip0_335_3130"
>
<rect
width=
"25.112"
height=
"25.112"
fill=
"white"
transform=
"translate(10.2253 8.44385)"
/>
</clipPath>
</defs>
</svg>
lib/Models/CommonResponse.dart
View file @
f3a137b2
...
...
@@ -10,7 +10,7 @@ class CommonResponse {
error
=
int
.
tryParse
(
json
[
'error'
]?.
toString
()
??
''
);
balance
=
int
.
tryParse
(
json
[
'balance'
]?.
toString
()
??
''
);
message
=
json
[
'message'
]?.
toString
();
filePath
=
json
[
'file
_
path'
]?.
toString
();
filePath
=
json
[
'
bill_
filepath'
]?.
toString
();
}
Map
<
String
,
dynamic
>
toJson
()
{
...
...
@@ -18,7 +18,7 @@ class CommonResponse {
'error'
:
error
,
'balance'
:
balance
,
'message'
:
message
,
'file
_
path'
:
filePath
,
'
bill_
filepath'
:
filePath
,
};
}
}
...
...
lib/Models/GetInTouchListResponse.dart
0 → 100644
View file @
f3a137b2
class
GetInTouchListResponse
{
String
?
error
;
List
<
GetInTouchList
>?
getInTouchList
;
String
?
message
;
String
?
sessionExists
;
GetInTouchListResponse
(
{
this
.
error
,
this
.
getInTouchList
,
this
.
message
,
this
.
sessionExists
});
GetInTouchListResponse
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
error
=
json
[
'error'
];
if
(
json
[
'get_in_touch_list'
]
!=
null
)
{
getInTouchList
=
<
GetInTouchList
>[];
json
[
'get_in_touch_list'
].
forEach
((
v
)
{
getInTouchList
!.
add
(
new
GetInTouchList
.
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
.
getInTouchList
!=
null
)
{
data
[
'get_in_touch_list'
]
=
this
.
getInTouchList
!.
map
((
v
)
=>
v
.
toJson
()).
toList
();
}
data
[
'message'
]
=
this
.
message
;
data
[
'session_exists'
]
=
this
.
sessionExists
;
return
data
;
}
}
class
GetInTouchList
{
String
?
id
;
String
?
branchName
;
String
?
googleReviewLink
;
String
?
address
;
String
?
loc
;
String
?
stateName
;
String
?
telephoneNo
;
String
?
mail
;
String
?
latitude
;
String
?
longitude
;
GetInTouchList
(
{
this
.
id
,
this
.
branchName
,
this
.
googleReviewLink
,
this
.
address
,
this
.
loc
,
this
.
stateName
,
this
.
telephoneNo
,
this
.
mail
,
this
.
latitude
,
this
.
longitude
});
GetInTouchList
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
id
=
json
[
'id'
];
branchName
=
json
[
'branch_name'
];
googleReviewLink
=
json
[
'google_review_link'
];
address
=
json
[
'address'
];
loc
=
json
[
'loc'
];
stateName
=
json
[
'state_name'
];
telephoneNo
=
json
[
'telephone_no'
];
mail
=
json
[
'mail'
];
latitude
=
json
[
'latitude'
];
longitude
=
json
[
'longitude'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'id'
]
=
this
.
id
;
data
[
'branch_name'
]
=
this
.
branchName
;
data
[
'google_review_link'
]
=
this
.
googleReviewLink
;
data
[
'address'
]
=
this
.
address
;
data
[
'loc'
]
=
this
.
loc
;
data
[
'state_name'
]
=
this
.
stateName
;
data
[
'telephone_no'
]
=
this
.
telephoneNo
;
data
[
'mail'
]
=
this
.
mail
;
data
[
'latitude'
]
=
this
.
latitude
;
data
[
'longitude'
]
=
this
.
longitude
;
return
data
;
}
}
lib/Models/ProfileDataResponse.dart
0 → 100644
View file @
f3a137b2
class
ProfileDataResponse
{
String
?
error
;
Details
?
details
;
String
?
message
;
String
?
sessionExists
;
ProfileDataResponse
(
{
this
.
error
,
this
.
details
,
this
.
message
,
this
.
sessionExists
});
ProfileDataResponse
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
error
=
json
[
'error'
];
details
=
json
[
'details'
]
!=
null
?
new
Details
.
fromJson
(
json
[
'details'
])
:
null
;
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
.
details
!=
null
)
{
data
[
'details'
]
=
this
.
details
!.
toJson
();
}
data
[
'message'
]
=
this
.
message
;
data
[
'session_exists'
]
=
this
.
sessionExists
;
return
data
;
}
}
class
Details
{
String
?
name
;
String
?
mobNum
;
String
?
email
;
String
?
address
;
String
?
profileImg
;
String
?
state
;
String
?
locality
;
Details
(
{
this
.
name
,
this
.
mobNum
,
this
.
email
,
this
.
address
,
this
.
profileImg
,
this
.
state
,
this
.
locality
});
Details
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
name
=
json
[
'name'
];
mobNum
=
json
[
'mob_num'
];
email
=
json
[
'email'
];
address
=
json
[
'address'
];
profileImg
=
json
[
'profile_img'
];
state
=
json
[
'state'
];
locality
=
json
[
'locality'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'name'
]
=
this
.
name
;
data
[
'mob_num'
]
=
this
.
mobNum
;
data
[
'email'
]
=
this
.
email
;
data
[
'address'
]
=
this
.
address
;
data
[
'profile_img'
]
=
this
.
profileImg
;
data
[
'state'
]
=
this
.
state
;
data
[
'locality'
]
=
this
.
locality
;
return
data
;
}
}
lib/Models/amcQuotationListResponse.dart
0 → 100644
View file @
f3a137b2
class
amcQuotationListResponse
{
String
?
error
;
List
<
AmcQuotations
>?
amcQuotations
;
String
?
message
;
amcQuotationListResponse
({
this
.
error
,
this
.
amcQuotations
,
this
.
message
});
amcQuotationListResponse
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
error
=
json
[
'error'
];
if
(
json
[
'amc_quotations'
]
!=
null
)
{
amcQuotations
=
<
AmcQuotations
>[];
json
[
'amc_quotations'
].
forEach
((
v
)
{
amcQuotations
!.
add
(
new
AmcQuotations
.
fromJson
(
v
));
});
}
message
=
json
[
'message'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'error'
]
=
this
.
error
;
if
(
this
.
amcQuotations
!=
null
)
{
data
[
'amc_quotations'
]
=
this
.
amcQuotations
!.
map
((
v
)
=>
v
.
toJson
()).
toList
();
}
data
[
'message'
]
=
this
.
message
;
return
data
;
}
}
class
AmcQuotations
{
String
?
id
;
String
?
noOfVisits
;
String
?
price
;
String
?
amcStatus
;
String
?
expNote
;
String
?
noOfOilServices
;
String
?
purchaseDate
;
AmcQuotations
(
{
this
.
id
,
this
.
noOfVisits
,
this
.
price
,
this
.
amcStatus
,
this
.
expNote
,
this
.
noOfOilServices
,
this
.
purchaseDate
});
AmcQuotations
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
id
=
json
[
'id'
];
noOfVisits
=
json
[
'no_of_visits'
];
price
=
json
[
'price'
];
amcStatus
=
json
[
'amc_status'
];
expNote
=
json
[
'exp_note'
];
noOfOilServices
=
json
[
'no_of_oil_services'
];
purchaseDate
=
json
[
'purchase_Date'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'id'
]
=
this
.
id
;
data
[
'no_of_visits'
]
=
this
.
noOfVisits
;
data
[
'price'
]
=
this
.
price
;
data
[
'amc_status'
]
=
this
.
amcStatus
;
data
[
'exp_note'
]
=
this
.
expNote
;
data
[
'no_of_oil_services'
]
=
this
.
noOfOilServices
;
data
[
'purchase_Date'
]
=
this
.
purchaseDate
;
return
data
;
}
}
lib/Models/complaintListResponse.dart
0 → 100644
View file @
f3a137b2
class
complaintListResponse
{
String
?
error
;
List
<
ComplaintList
>?
complaintList
;
String
?
message
;
complaintListResponse
({
this
.
error
,
this
.
complaintList
,
this
.
message
});
complaintListResponse
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
error
=
json
[
'error'
];
if
(
json
[
'complaint_list'
]
!=
null
)
{
complaintList
=
<
ComplaintList
>[];
json
[
'complaint_list'
].
forEach
((
v
)
{
complaintList
!.
add
(
new
ComplaintList
.
fromJson
(
v
));
});
}
message
=
json
[
'message'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'error'
]
=
this
.
error
;
if
(
this
.
complaintList
!=
null
)
{
data
[
'complaint_list'
]
=
this
.
complaintList
!.
map
((
v
)
=>
v
.
toJson
()).
toList
();
}
data
[
'message'
]
=
this
.
message
;
return
data
;
}
}
class
ComplaintList
{
String
?
id
;
String
?
openStatus
;
String
?
modelName
;
String
?
registredDate
;
String
?
hashId
;
String
?
productName
;
String
?
complaintName
;
ComplaintList
(
{
this
.
id
,
this
.
openStatus
,
this
.
modelName
,
this
.
registredDate
,
this
.
hashId
,
this
.
productName
,
this
.
complaintName
});
ComplaintList
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
id
=
json
[
'id'
];
openStatus
=
json
[
'open_status'
];
modelName
=
json
[
'model_name'
];
registredDate
=
json
[
'registred_date'
];
hashId
=
json
[
'hash_id'
];
productName
=
json
[
'product_name'
];
complaintName
=
json
[
'complaint_name'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'id'
]
=
this
.
id
;
data
[
'open_status'
]
=
this
.
openStatus
;
data
[
'model_name'
]
=
this
.
modelName
;
data
[
'registred_date'
]
=
this
.
registredDate
;
data
[
'hash_id'
]
=
this
.
hashId
;
data
[
'product_name'
]
=
this
.
productName
;
data
[
'complaint_name'
]
=
this
.
complaintName
;
return
data
;
}
}
lib/Models/generatorDetailsResponse.dart
0 → 100644
View file @
f3a137b2
class
generatorDetailsResponse
{
String
?
error
;
String
?
message
;
String
?
id
;
String
?
hashId
;
String
?
engine
;
String
?
prodName
;
String
?
prodImg
;
String
?
amc
;
String
?
warranty
;
GenDetails
?
genDetails
;
LocationDetails
?
locationDetails
;
List
<
Schedule
>?
schedule
;
List
<
Quotations
>?
quotations
;
List
<
AmcQuotations
>?
amcQuotations
;
List
<
Complaints
>?
complaints
;
generatorDetailsResponse
(
{
this
.
error
,
this
.
message
,
this
.
id
,
this
.
hashId
,
this
.
engine
,
this
.
prodName
,
this
.
prodImg
,
this
.
amc
,
this
.
warranty
,
this
.
genDetails
,
this
.
locationDetails
,
this
.
schedule
,
this
.
quotations
,
this
.
amcQuotations
,
this
.
complaints
});
generatorDetailsResponse
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
error
=
json
[
'error'
];
message
=
json
[
'message'
];
id
=
json
[
'id'
];
hashId
=
json
[
'hash_id'
];
engine
=
json
[
'engine'
];
prodName
=
json
[
'prod_name'
];
prodImg
=
json
[
'prod_img'
];
amc
=
json
[
'amc'
];
warranty
=
json
[
'warranty'
];
genDetails
=
json
[
'gen_details'
]
!=
null
?
new
GenDetails
.
fromJson
(
json
[
'gen_details'
])
:
null
;
locationDetails
=
json
[
'location_details'
]
!=
null
?
new
LocationDetails
.
fromJson
(
json
[
'location_details'
])
:
null
;
if
(
json
[
'schedule'
]
!=
null
)
{
schedule
=
<
Schedule
>[];
json
[
'schedule'
].
forEach
((
v
)
{
schedule
!.
add
(
new
Schedule
.
fromJson
(
v
));
});
}
if
(
json
[
'quotations'
]
!=
null
)
{
quotations
=
<
Quotations
>[];
json
[
'quotations'
].
forEach
((
v
)
{
quotations
!.
add
(
new
Quotations
.
fromJson
(
v
));
});
}
if
(
json
[
'amc_quotations'
]
!=
null
)
{
amcQuotations
=
<
AmcQuotations
>[];
json
[
'amc_quotations'
].
forEach
((
v
)
{
amcQuotations
!.
add
(
new
AmcQuotations
.
fromJson
(
v
));
});
}
if
(
json
[
'complaints'
]
!=
null
)
{
complaints
=
<
Complaints
>[];
json
[
'complaints'
].
forEach
((
v
)
{
complaints
!.
add
(
new
Complaints
.
fromJson
(
v
));
});
}
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'error'
]
=
this
.
error
;
data
[
'message'
]
=
this
.
message
;
data
[
'id'
]
=
this
.
id
;
data
[
'hash_id'
]
=
this
.
hashId
;
data
[
'engine'
]
=
this
.
engine
;
data
[
'prod_name'
]
=
this
.
prodName
;
data
[
'prod_img'
]
=
this
.
prodImg
;
data
[
'amc'
]
=
this
.
amc
;
data
[
'warranty'
]
=
this
.
warranty
;
if
(
this
.
genDetails
!=
null
)
{
data
[
'gen_details'
]
=
this
.
genDetails
!.
toJson
();
}
if
(
this
.
locationDetails
!=
null
)
{
data
[
'location_details'
]
=
this
.
locationDetails
!.
toJson
();
}
if
(
this
.
schedule
!=
null
)
{
data
[
'schedule'
]
=
this
.
schedule
!.
map
((
v
)
=>
v
.
toJson
()).
toList
();
}
if
(
this
.
quotations
!=
null
)
{
data
[
'quotations'
]
=
this
.
quotations
!.
map
((
v
)
=>
v
.
toJson
()).
toList
();
}
if
(
this
.
amcQuotations
!=
null
)
{
data
[
'amc_quotations'
]
=
this
.
amcQuotations
!.
map
((
v
)
=>
v
.
toJson
()).
toList
();
}
if
(
this
.
complaints
!=
null
)
{
data
[
'complaints'
]
=
this
.
complaints
!.
map
((
v
)
=>
v
.
toJson
()).
toList
();
}
return
data
;
}
}
class
GenDetails
{
String
?
purchaseDate
;
String
?
altNo
;
String
?
modelName
;
String
?
batterNo
;
String
?
commisDate
;
String
?
dispDate
;
GenDetails
(
{
this
.
purchaseDate
,
this
.
altNo
,
this
.
modelName
,
this
.
batterNo
,
this
.
commisDate
,
this
.
dispDate
});
GenDetails
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
purchaseDate
=
json
[
'purchase_date'
];
altNo
=
json
[
'alt_no'
];
modelName
=
json
[
'model_name'
];
batterNo
=
json
[
'batter_no'
];
commisDate
=
json
[
'commis_date'
];
dispDate
=
json
[
'disp_date'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'purchase_date'
]
=
this
.
purchaseDate
;
data
[
'alt_no'
]
=
this
.
altNo
;
data
[
'model_name'
]
=
this
.
modelName
;
data
[
'batter_no'
]
=
this
.
batterNo
;
data
[
'commis_date'
]
=
this
.
commisDate
;
data
[
'disp_date'
]
=
this
.
dispDate
;
return
data
;
}
}
class
LocationDetails
{
String
?
stateName
;
String
?
districtName
;
String
?
address
;
LocationDetails
({
this
.
stateName
,
this
.
districtName
,
this
.
address
});
LocationDetails
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
stateName
=
json
[
'state_name'
];
districtName
=
json
[
'district_name'
];
address
=
json
[
'address'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'state_name'
]
=
this
.
stateName
;
data
[
'district_name'
]
=
this
.
districtName
;
data
[
'address'
]
=
this
.
address
;
return
data
;
}
}
class
Schedule
{
String
?
id
;
String
?
date
;
String
?
type
;
String
?
complaintType
;
String
?
reason
;
String
?
status
;
Schedule
(
{
this
.
id
,
this
.
date
,
this
.
type
,
this
.
complaintType
,
this
.
reason
,
this
.
status
});
Schedule
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
id
=
json
[
'id'
];
date
=
json
[
'date'
];
type
=
json
[
'type'
];
complaintType
=
json
[
'complaint_type'
];
reason
=
json
[
'reason'
];
status
=
json
[
'status'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'id'
]
=
this
.
id
;
data
[
'date'
]
=
this
.
date
;
data
[
'type'
]
=
this
.
type
;
data
[
'complaint_type'
]
=
this
.
complaintType
;
data
[
'reason'
]
=
this
.
reason
;
data
[
'status'
]
=
this
.
status
;
return
data
;
}
}
class
Quotations
{
String
?
id
;
String
?
title
;
String
?
filePath
;
String
?
date
;
Quotations
({
this
.
id
,
this
.
title
,
this
.
filePath
,
this
.
date
});
Quotations
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
id
=
json
[
'id'
];
title
=
json
[
'title'
];
filePath
=
json
[
'file_path'
];
date
=
json
[
'date'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'id'
]
=
this
.
id
;
data
[
'title'
]
=
this
.
title
;
data
[
'file_path'
]
=
this
.
filePath
;
data
[
'date'
]
=
this
.
date
;
return
data
;
}
}
class
AmcQuotations
{
String
?
id
;
String
?
noOfVisits
;
String
?
price
;
String
?
amcStatus
;
String
?
expNote
;
String
?
noOfOilServices
;
String
?
purchaseDate
;
AmcQuotations
(
{
this
.
id
,
this
.
noOfVisits
,
this
.
price
,
this
.
amcStatus
,
this
.
expNote
,
this
.
noOfOilServices
,
this
.
purchaseDate
});
AmcQuotations
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
id
=
json
[
'id'
];
noOfVisits
=
json
[
'no_of_visits'
];
price
=
json
[
'price'
];
amcStatus
=
json
[
'amc_status'
];
expNote
=
json
[
'exp_note'
];
noOfOilServices
=
json
[
'no_of_oil_services'
];
purchaseDate
=
json
[
'purchase_Date'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'id'
]
=
this
.
id
;
data
[
'no_of_visits'
]
=
this
.
noOfVisits
;
data
[
'price'
]
=
this
.
price
;
data
[
'amc_status'
]
=
this
.
amcStatus
;
data
[
'exp_note'
]
=
this
.
expNote
;
data
[
'no_of_oil_services'
]
=
this
.
noOfOilServices
;
data
[
'purchase_Date'
]
=
this
.
purchaseDate
;
return
data
;
}
}
class
Complaints
{
String
?
id
;
String
?
openStatus
;
String
?
modelName
;
String
?
registredDate
;
String
?
hashId
;
String
?
productName
;
String
?
complaintName
;
Complaints
(
{
this
.
id
,
this
.
openStatus
,
this
.
modelName
,
this
.
registredDate
,
this
.
hashId
,
this
.
productName
,
this
.
complaintName
});
Complaints
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
id
=
json
[
'id'
];
openStatus
=
json
[
'open_status'
];
modelName
=
json
[
'model_name'
];
registredDate
=
json
[
'registred_date'
];
hashId
=
json
[
'hash_id'
];
productName
=
json
[
'product_name'
];
complaintName
=
json
[
'complaint_name'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'id'
]
=
this
.
id
;
data
[
'open_status'
]
=
this
.
openStatus
;
data
[
'model_name'
]
=
this
.
modelName
;
data
[
'registred_date'
]
=
this
.
registredDate
;
data
[
'hash_id'
]
=
this
.
hashId
;
data
[
'product_name'
]
=
this
.
productName
;
data
[
'complaint_name'
]
=
this
.
complaintName
;
return
data
;
}
}
lib/Models/quotationListResponse.dart
0 → 100644
View file @
f3a137b2
class
quotationListResponse
{
String
?
error
;
List
<
ServiceQuotation
>?
serviceQuotation
;
String
?
message
;
quotationListResponse
({
this
.
error
,
this
.
serviceQuotation
,
this
.
message
});
quotationListResponse
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
error
=
json
[
'error'
];
if
(
json
[
'service_quotation'
]
!=
null
)
{
serviceQuotation
=
<
ServiceQuotation
>[];
json
[
'service_quotation'
].
forEach
((
v
)
{
serviceQuotation
!.
add
(
new
ServiceQuotation
.
fromJson
(
v
));
});
}
message
=
json
[
'message'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'error'
]
=
this
.
error
;
if
(
this
.
serviceQuotation
!=
null
)
{
data
[
'service_quotation'
]
=
this
.
serviceQuotation
!.
map
((
v
)
=>
v
.
toJson
()).
toList
();
}
data
[
'message'
]
=
this
.
message
;
return
data
;
}
}
class
ServiceQuotation
{
String
?
id
;
String
?
title
;
String
?
date
;
String
?
fileLoc
;
ServiceQuotation
({
this
.
id
,
this
.
title
,
this
.
date
,
this
.
fileLoc
});
ServiceQuotation
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
id
=
json
[
'id'
];
title
=
json
[
'title'
];
date
=
json
[
'date'
];
fileLoc
=
json
[
'file_loc'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'id'
]
=
this
.
id
;
data
[
'title'
]
=
this
.
title
;
data
[
'date'
]
=
this
.
date
;
data
[
'file_loc'
]
=
this
.
fileLoc
;
return
data
;
}
}
lib/Models/scheduleListResponse.dart
0 → 100644
View file @
f3a137b2
class
scheduleListResponse
{
String
?
error
;
List
<
AllScheduleServices
>?
allScheduleServices
;
String
?
message
;
scheduleListResponse
({
this
.
error
,
this
.
allScheduleServices
,
this
.
message
});
scheduleListResponse
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
error
=
json
[
'error'
];
if
(
json
[
'all_schedule_services'
]
!=
null
)
{
allScheduleServices
=
<
AllScheduleServices
>[];
json
[
'all_schedule_services'
].
forEach
((
v
)
{
allScheduleServices
!.
add
(
new
AllScheduleServices
.
fromJson
(
v
));
});
}
message
=
json
[
'message'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'error'
]
=
this
.
error
;
if
(
this
.
allScheduleServices
!=
null
)
{
data
[
'all_schedule_services'
]
=
this
.
allScheduleServices
!.
map
((
v
)
=>
v
.
toJson
()).
toList
();
}
data
[
'message'
]
=
this
.
message
;
return
data
;
}
}
class
AllScheduleServices
{
String
?
id
;
String
?
dueDate
;
String
?
complaintType
;
String
?
comType
;
String
?
status
;
AllScheduleServices
(
{
this
.
id
,
this
.
dueDate
,
this
.
complaintType
,
this
.
comType
,
this
.
status
});
AllScheduleServices
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
id
=
json
[
'id'
];
dueDate
=
json
[
'due_date'
];
complaintType
=
json
[
'complaint_type'
];
comType
=
json
[
'com_type'
];
status
=
json
[
'status'
];
}
Map
<
String
,
dynamic
>
toJson
()
{
final
Map
<
String
,
dynamic
>
data
=
new
Map
<
String
,
dynamic
>();
data
[
'id'
]
=
this
.
id
;
data
[
'due_date'
]
=
this
.
dueDate
;
data
[
'complaint_type'
]
=
this
.
complaintType
;
data
[
'com_type'
]
=
this
.
comType
;
data
[
'status'
]
=
this
.
status
;
return
data
;
}
}
lib/Notifiers/AuthProvider.dart
View file @
f3a137b2
...
...
@@ -139,16 +139,30 @@ class AuthProvider with ChangeNotifier {
}
/// 🔹 Logout API
Future
<
void
>
logout
(
String
accId
,
String
sessionId
)
async
{
Future
<
bool
>
logout
(
String
accId
,
String
sessionId
)
async
{
_setLoading
(
true
);
try
{
final
res
=
await
ApiCalling
.
logoutApi
(
accId
,
sessionId
);
_logoutResponse
=
res
;
notifyListeners
();
// Defensive check — handle both string and int
final
errorValue
=
res
?.
error
?.
toString
().
trim
();
if
(
res
!=
null
&&
errorValue
==
"0"
)
{
debugPrint
(
"✅ Logout success:
${res.message ?? 'Success'}
"
);
return
true
;
}
else
{
debugPrint
(
"❌ Logout failed:
${res?.message ?? 'Unknown error'}
"
);
return
false
;
}
}
catch
(
e
)
{
debugPrint
(
"❌ logout Provider Error:
$e
"
);
debugPrint
(
"❌ Logout Provider Error:
$e
"
);
return
false
;
}
finally
{
_setLoading
(
false
);
}
}
}
lib/Notifiers/ContactUsProvider.dart
0 → 100644
View file @
f3a137b2
import
'package:flutter/foundation.dart'
;
import
'../Models/GetInTouchListResponse.dart'
;
import
'../Services/api_calling.dart'
;
class
ContactUsProvider
extends
ChangeNotifier
{
/// 🔹 State Variables
bool
_isLoading
=
false
;
String
?
_errorMessage
;
GetInTouchListResponse
?
_response
;
/// 🔹 Getters
bool
get
isLoading
=>
_isLoading
;
String
?
get
errorMessage
=>
_errorMessage
;
GetInTouchListResponse
?
get
response
=>
_response
;
List
<
GetInTouchList
>?
get
contactList
=>
_response
?.
getInTouchList
;
/// 🔹 Internal Setter for Loading State
void
_setLoading
(
bool
value
)
{
_isLoading
=
value
;
notifyListeners
();
}
/// 🔹 Fetch Contact Us / Get In Touch List API
Future
<
void
>
fetchContactUs
(
String
accId
,
String
sessionId
)
async
{
_setLoading
(
true
);
_errorMessage
=
null
;
try
{
debugPrint
(
"📡 Fetching Get In Touch list..."
);
final
res
=
await
ApiCalling
.
fetchGetInTouchListApi
(
accId
,
sessionId
);
_response
=
res
;
if
(
res
==
null
)
{
_errorMessage
=
"No response from server."
;
}
else
if
(
res
.
error
?.
toString
().
trim
()
!=
"0"
)
{
_errorMessage
=
res
.
message
?.
trim
().
isNotEmpty
==
true
?
res
.
message
:
"Something went wrong. Please try again."
;
}
}
catch
(
e
)
{
debugPrint
(
"❌ ContactUsProvider Error:
$e
"
);
_errorMessage
=
"An unexpected error occurred. Please try again."
;
}
finally
{
_setLoading
(
false
);
}
}
/// 🔹 Optional: Refresh list (shortcut method)
Future
<
void
>
refresh
(
String
accId
,
String
sessionId
)
async
{
await
fetchContactUs
(
accId
,
sessionId
);
}
/// 🔹 Clear data (useful when logging out or leaving screen)
void
clearData
()
{
_response
=
null
;
_errorMessage
=
null
;
notifyListeners
();
}
}
lib/Notifiers/DashboardProvider.dart
View file @
f3a137b2
import
'package:flutter/material.dart'
;
import
'package:gen_service/Models/ProfileDataResponse.dart'
;
import
'package:gen_service/Services/api_calling.dart'
;
import
'../Models/DashboardResponse.dart'
;
...
...
@@ -48,6 +49,38 @@ class DashboardProvider extends ChangeNotifier {
}
}
// Fetch Profile provider
// =======================
ProfileDataResponse
?
_profileData
;
ProfileDataResponse
?
get
profileData
=>
_profileData
;
Future
<
void
>
fetchProfile
(
String
accId
,
String
sessionId
)
async
{
_isLoading
=
true
;
_errorMessage
=
null
;
notifyListeners
();
try
{
final
response
=
await
ApiCalling
.
fetchProfileDataApi
(
accId
,
sessionId
);
if
(
response
!=
null
)
{
if
(
response
.
error
?.
toString
()
==
"0"
)
{
_profileData
=
response
;
}
else
{
_errorMessage
=
response
.
message
??
"Something went wrong!"
;
}
}
else
{
_errorMessage
=
"No response from server."
;
}
}
catch
(
e
)
{
debugPrint
(
"❌ fetchProfile error:
$e
"
);
_errorMessage
=
"Failed to fetch profile data:
${e.toString()}
"
;
}
finally
{
_isLoading
=
false
;
notifyListeners
();
}
}
// =======================
// Refresh Dashboard
// =======================
...
...
@@ -64,4 +97,6 @@ class DashboardProvider extends ChangeNotifier {
_isLoading
=
false
;
notifyListeners
();
}
}
lib/Notifiers/TransactionsProvider.dart
View file @
f3a137b2
import
'dart:io'
;
import
'package:flutter/cupertino.dart'
;
import
'package:gen_service/Services/api_calling.dart'
;
import
'package:open_filex/open_filex.dart'
;
import
'package:path_provider/path_provider.dart'
;
import
'../Models/TransactionModels/BillDetailResponse.dart'
;
import
'../Models/TransactionModels/PaymentDetailResponse.dart'
;
import
'../Models/TransactionModels/TransactionListResponse.dart'
;
import
'../Services/api_post_request.dart'
;
import
'../Utility/CustomSnackbar.dart'
;
class
TransactionsProvider
with
ChangeNotifier
{
bool
_isLoading
=
false
;
...
...
@@ -108,6 +114,132 @@ class TransactionsProvider with ChangeNotifier {
notifyListeners
();
}
bool
_isDownloading
=
false
;
bool
get
isDownloading
=>
_isDownloading
;
void
setDownloading
(
bool
value
)
{
_isDownloading
=
value
;
notifyListeners
();
}
/// Download Bill
Future
<
void
>
downloadBill
(
BuildContext
context
,
String
sessionId
,
String
billId
,
String
accId
)
async
{
setDownloading
(
true
);
try
{
// Step 1: Call billDownloadApi to get file path
final
res
=
await
ApiCalling
.
billDownloadApi
(
sessionId
,
billId
,
accId
);
if
(
res
==
null
||
res
.
error
!=
0
||
res
.
filePath
==
null
)
{
// showToast(res?.message ?? "Download failed");
setDownloading
(
false
);
return
;
}
final
fileUrl
=
res
.
filePath
!;
final
dir
=
await
getApplicationDocumentsDirectory
();
final
savePath
=
'
${dir.path}
/receipt_
${billId}
.pdf'
;
// Step 2: Download file
final
success
=
await
downloadFile
(
fileUrl
,
savePath
);
if
(
success
)
{
CustomSnackBar
.
showSuccess
(
context:
context
,
message:
"File downloaded successfully!"
);
// showToast("File downloaded successfully!");
await
OpenFilex
.
open
(
savePath
);
}
else
{
CustomSnackBar
.
showError
(
context:
context
,
message:
"Failed to download file"
);
// showToast("Failed to download file");
}
}
catch
(
e
)
{
debugPrint
(
"❌ Bill download error:
$e
"
);
CustomSnackBar
.
showError
(
context:
context
,
message:
"Error downloading file"
);
// showToast("Error downloading file");
}
finally
{
setDownloading
(
false
);
}
}
/// File Downloader
Future
<
bool
>
downloadFile
(
String
apiUrl
,
String
savePath
)
async
{
try
{
final
response
=
await
get
(
apiUrl
,
{});
// Using your get() helper
if
(
response
!=
null
&&
response
.
statusCode
==
200
)
{
final
file
=
File
(
savePath
);
await
file
.
writeAsBytes
(
response
.
bodyBytes
);
return
true
;
}
else
{
debugPrint
(
"❌ Failed to download file:
${response?.statusCode}
"
);
return
false
;
}
}
catch
(
e
)
{
debugPrint
(
"❌ File download error:
$e
"
);
return
false
;
}
}
/// Download Payment Receipt
Future
<
void
>
downloadPaymentReceipt
(
BuildContext
context
,
String
sessionId
,
String
ledgerId
,
String
accId
,
)
async
{
setDownloading
(
true
);
try
{
// Step 1: Call paymentReceiptDownloadApi to get file URL/path
final
res
=
await
ApiCalling
.
paymentReceiptDownloadApi
(
sessionId
,
ledgerId
,
accId
);
if
(
res
==
null
||
res
.
error
!=
0
||
res
.
filePath
==
null
)
{
CustomSnackBar
.
showError
(
context:
context
,
message:
res
?.
message
??
"Download failed"
,
);
setDownloading
(
false
);
return
;
}
final
fileUrl
=
res
.
filePath
!;
final
dir
=
await
getApplicationDocumentsDirectory
();
final
savePath
=
'
${dir.path}
/payment_receipt_
$ledgerId
.pdf'
;
// Step 2: Download file using helper
final
success
=
await
downloadFile
(
fileUrl
,
savePath
);
if
(
success
)
{
CustomSnackBar
.
showSuccess
(
context:
context
,
message:
"Payment receipt downloaded successfully!"
,
);
await
OpenFilex
.
open
(
savePath
);
}
else
{
CustomSnackBar
.
showError
(
context:
context
,
message:
"Failed to download payment receipt"
,
);
}
}
catch
(
e
)
{
debugPrint
(
"❌ Payment receipt download error:
$e
"
);
CustomSnackBar
.
showError
(
context:
context
,
message:
"Error downloading payment receipt"
,
);
}
finally
{
setDownloading
(
false
);
}
}
// ---------------------------------------------------------------------------
// 🔹 Clear All Data (optional helper)
void
clearAll
()
{
...
...
lib/Notifiers/generatorDetailsProvider.dart
0 → 100644
View file @
f3a137b2
import
'package:flutter/foundation.dart'
;
import
'package:gen_service/Models/amcQuotationListResponse.dart'
;
import
'package:gen_service/Models/complaintListResponse.dart'
;
import
'package:gen_service/Models/generatorDetailsResponse.dart'
;
import
'package:gen_service/Models/quotationListResponse.dart'
;
import
'package:gen_service/Models/scheduleListResponse.dart'
;
import
'../Services/api_calling.dart'
;
class
Generatordetailsprovider
extends
ChangeNotifier
{
generatorDetailsResponse
?
_detailsResponse
;
scheduleListResponse
?
_scheduleResponse
;
quotationListResponse
?
_quotationResponse
;
complaintListResponse
?
_complaintResponse
;
amcQuotationListResponse
?
_amcQuotationResponse
;
bool
_isLoading
=
false
;
String
?
_errorMessage
;
bool
_showMoreDetails
=
false
;
generatorDetailsResponse
?
get
detailsResponse
=>
_detailsResponse
;
scheduleListResponse
?
get
scheduleResponse
=>
_scheduleResponse
;
quotationListResponse
?
get
quotationResponse
=>
_quotationResponse
;
complaintListResponse
?
get
complaintResponse
=>
_complaintResponse
;
amcQuotationListResponse
?
get
amcQuotationResponse
=>
_amcQuotationResponse
;
bool
get
isLoading
=>
_isLoading
;
String
?
get
errorMessage
=>
_errorMessage
;
bool
get
showMoreDetails
=>
_showMoreDetails
;
set
showMoreDetails
(
bool
value
)
{
_showMoreDetails
=
value
;
notifyListeners
();
}
Future
<
void
>
fetchGeneratorDetails
(
String
accId
,
String
sessionId
,
genId
)
async
{
_isLoading
=
true
;
_errorMessage
=
null
;
notifyListeners
();
try
{
final
response
=
await
ApiCalling
.
generatorDetailsAPI
(
accId
,
sessionId
,
genId
);
if
(
response
!=
null
)
{
if
(
response
.
error
==
"0"
)
{
_detailsResponse
=
response
;
}
else
{
_errorMessage
=
response
.
message
??
"Something went wrong!"
;
}
}
else
{
_errorMessage
=
"No response from server."
;
}
}
catch
(
e
)
{
_errorMessage
=
"Failed to fetch dashboard:
$e
"
;
}
finally
{
_isLoading
=
false
;
notifyListeners
();
}
}
Future
<
void
>
fetchScheduleList
(
String
accId
,
String
sessionId
,
gen_id
)
async
{
_isLoading
=
true
;
_errorMessage
=
null
;
notifyListeners
();
try
{
final
response
=
await
ApiCalling
.
scheduleListAPI
(
accId
,
sessionId
,
gen_id
);
if
(
response
!=
null
)
{
if
(
response
.
error
==
"0"
)
{
_scheduleResponse
=
response
;
notifyListeners
();
}
else
{
_errorMessage
=
response
.
message
??
"Something went wrong!"
;
}
}
else
{
_errorMessage
=
"No response from server."
;
}
}
catch
(
e
)
{
_errorMessage
=
"Failed to fetch dashboard:
$e
"
;
}
finally
{
_isLoading
=
false
;
notifyListeners
();
}
}
Future
<
void
>
fetchQuotationList
(
String
accId
,
String
sessionId
,
genID
)
async
{
_isLoading
=
true
;
_errorMessage
=
null
;
notifyListeners
();
try
{
final
response
=
await
ApiCalling
.
quotationListAPI
(
accId
,
sessionId
,
genID
);
if
(
response
!=
null
)
{
if
(
response
.
error
==
"0"
)
{
_quotationResponse
=
response
;
notifyListeners
();
}
else
{
_errorMessage
=
response
.
message
??
"Something went wrong!"
;
}
}
else
{
_errorMessage
=
"No response from server."
;
}
}
catch
(
e
)
{
_errorMessage
=
"Failed to fetch dashboard:
$e
"
;
}
finally
{
_isLoading
=
false
;
notifyListeners
();
}
}
Future
<
void
>
fetchComplaintList
(
String
accId
,
String
sessionId
)
async
{
_isLoading
=
true
;
_errorMessage
=
null
;
notifyListeners
();
try
{
final
response
=
await
ApiCalling
.
complaintListAPI
(
accId
,
sessionId
);
if
(
response
!=
null
)
{
if
(
response
.
error
==
"0"
)
{
_complaintResponse
=
response
;
notifyListeners
();
}
else
{
_errorMessage
=
response
.
message
??
"Something went wrong!"
;
}
}
else
{
_errorMessage
=
"No response from server."
;
}
}
catch
(
e
)
{
_errorMessage
=
"Failed to fetch dashboard:
$e
"
;
}
finally
{
_isLoading
=
false
;
notifyListeners
();
}
}
Future
<
void
>
fetchAmcQuotationList
(
String
accId
,
String
sessionId
,
genId
)
async
{
_isLoading
=
true
;
_errorMessage
=
null
;
notifyListeners
();
try
{
final
response
=
await
ApiCalling
.
amcQuoteListAPI
(
accId
,
sessionId
,
genId
);
if
(
response
!=
null
)
{
if
(
response
.
error
==
"0"
)
{
_amcQuotationResponse
=
response
;
notifyListeners
();
}
else
{
_errorMessage
=
response
.
message
??
"Something went wrong!"
;
}
}
else
{
_errorMessage
=
"No response from server."
;
}
}
catch
(
e
)
{
_errorMessage
=
"Failed to fetch dashboard:
$e
"
;
}
finally
{
_isLoading
=
false
;
notifyListeners
();
}
}
}
\ No newline at end of file
lib/Screens/ContactUsScreen.dart
0 → 100644
View file @
f3a137b2
import
'dart:ui'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_svg/svg.dart'
;
import
'package:gen_service/Notifiers/ContactUsProvider.dart'
;
import
'package:provider/provider.dart'
;
import
'package:url_launcher/url_launcher.dart'
;
import
'../Utility/AppColors.dart'
;
class
ContactUsScreen
extends
StatefulWidget
{
final
String
accId
;
final
String
sessionId
;
const
ContactUsScreen
({
Key
?
key
,
required
this
.
accId
,
required
this
.
sessionId
,
})
:
super
(
key:
key
);
@override
State
<
ContactUsScreen
>
createState
()
=>
_ContactUsScreenState
();
}
class
_ContactUsScreenState
extends
State
<
ContactUsScreen
>
{
bool
_stretch
=
true
;
@override
void
initState
()
{
super
.
initState
();
Future
.
microtask
(()
{
final
getInTouchProvider
=
Provider
.
of
<
ContactUsProvider
>(
context
,
listen:
false
);
getInTouchProvider
.
fetchContactUs
(
widget
.
accId
,
widget
.
sessionId
);
});
}
@override
Widget
build
(
BuildContext
context
)
{
final
getInTouchProvider
=
Provider
.
of
<
ContactUsProvider
>(
context
);
final
isLoading
=
getInTouchProvider
.
isLoading
;
final
error
=
getInTouchProvider
.
errorMessage
;
final
data
=
getInTouchProvider
.
response
?.
getInTouchList
;
if
(
isLoading
)
{
return
const
Scaffold
(
backgroundColor:
AppColors
.
backgroundRegular
,
body:
Center
(
child:
CircularProgressIndicator
(
color:
AppColors
.
buttonColor
),
),
);
}
if
(
error
!=
null
)
{
return
Scaffold
(
backgroundColor:
AppColors
.
backgroundRegular
,
body:
Center
(
child:
Text
(
error
,
style:
const
TextStyle
(
color:
Colors
.
red
,
fontSize:
16
),
),
),
);
}
if
(
data
==
null
||
data
.
isEmpty
)
{
return
const
Scaffold
(
backgroundColor:
AppColors
.
backgroundRegular
,
body:
Center
(
child:
Text
(
"No data found."
),
),
);
}
return
RefreshIndicator
.
adaptive
(
color:
AppColors
.
amountText
,
onRefresh:
()
async
{
await
Future
.
delayed
(
const
Duration
(
milliseconds:
600
));
getInTouchProvider
.
fetchContactUs
(
widget
.
accId
,
widget
.
sessionId
);
},
child:
Scaffold
(
backgroundColor:
const
Color
(
0xFF4076FF
),
body:
CustomScrollView
(
physics:
const
ClampingScrollPhysics
(),
slivers:
<
Widget
>[
SliverAppBar
(
leading:
Container
(),
stretch:
_stretch
,
backgroundColor:
const
Color
(
0xFF4076FF
),
onStretchTrigger:
()
async
{
final
provider
=
Provider
.
of
<
ContactUsProvider
>(
context
,
listen:
false
);
provider
.
fetchContactUs
(
widget
.
accId
,
widget
.
sessionId
);
},
stretchTriggerOffset:
300.0
,
expandedHeight:
245.0
,
flexibleSpace:
FlexibleSpaceBar
(
stretchModes:
const
[
StretchMode
.
zoomBackground
,
StretchMode
.
blurBackground
,
],
background:
Container
(
width:
double
.
infinity
,
decoration:
const
BoxDecoration
(
gradient:
AppColors
.
backgroundGradient
),
child:
SafeArea
(
bottom:
false
,
child:
Padding
(
padding:
const
EdgeInsets
.
only
(
top:
20
,
bottom:
25
,
left:
20
,
right:
20
),
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
crossAxisAlignment:
CrossAxisAlignment
.
center
,
children:
const
[
SizedBox
(
height:
16
),
SizedBox
(
height:
8
),
Text
(
"Map view!....."
,
style:
TextStyle
(
fontSize:
22
,
color:
Colors
.
white
),
),
SizedBox
(
height:
12
),
SizedBox
(
height:
2
),
],
),
),
),
),
),
),
// Body content
SliverToBoxAdapter
(
child:
Container
(
padding:
const
EdgeInsets
.
only
(
top:
1
,
bottom:
0
),
color:
Colors
.
transparent
,
child:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
0
),
decoration:
const
BoxDecoration
(
color:
AppColors
.
backgroundRegular
,
borderRadius:
BorderRadius
.
only
(
topLeft:
Radius
.
circular
(
30
),
topRight:
Radius
.
circular
(
30
),
),
),
child:
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
12
,
vertical:
10
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
const
SizedBox
(
height:
20
),
/// Build dynamic branch list
for
(
var
item
in
data
)
Padding
(
padding:
const
EdgeInsets
.
only
(
bottom:
8.0
),
child:
_buildItemRow
(
branchName:
item
.
branchName
??
"Unknown Branch"
,
address:
item
.
address
??
"No address available"
,
phoneNo:
item
.
telephoneNo
??
""
,
lat:
item
.
latitude
??
""
,
long:
item
.
longitude
??
""
,
),
),
const
SizedBox
(
height:
30
),
],
),
),
),
),
),
],
),
),
);
}
/// Branch card widget
Widget
_buildItemRow
({
required
String
branchName
,
required
String
address
,
required
String
phoneNo
,
required
String
lat
,
required
String
long
,
})
{
return
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
12
,
vertical:
14
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
22
)),
child:
Row
(
children:
[
const
SizedBox
(
width:
14
),
Expanded
(
flex:
6
,
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
branchName
,
style:
const
TextStyle
(
color:
AppColors
.
normalText
,
fontWeight:
FontWeight
.
w600
,
fontSize:
14
,
overflow:
TextOverflow
.
ellipsis
,
),
),
const
SizedBox
(
height:
4
),
Text
(
address
,
maxLines:
4
,
style:
const
TextStyle
(
color:
AppColors
.
subtitleText
,
fontWeight:
FontWeight
.
w400
,
fontSize:
14
,
overflow:
TextOverflow
.
ellipsis
,
),
),
],
),
),
const
SizedBox
(
width:
8
),
Row
(
children:
[
InkResponse
(
onTap:
()
{
// map lat & long
},
child:
Container
(
padding:
const
EdgeInsets
.
all
(
1
),
decoration:
BoxDecoration
(
color:
Colors
.
transparent
,
borderRadius:
BorderRadius
.
circular
(
30
)),
child:
SvgPicture
.
asset
(
"assets/svg/route_ic.svg"
,
height:
42
,
fit:
BoxFit
.
contain
,
),
),
),
const
SizedBox
(
width:
6
),
InkResponse
(
onTap:
()
async
{
final
phone
=
phoneNo
.
trim
();
if
(
phone
.
isEmpty
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
backgroundColor:
Colors
.
redAccent
,
content:
const
Text
(
"Phone number not available"
,
style:
TextStyle
(
color:
Colors
.
white
),
),
duration:
Duration
(
seconds:
2
),
behavior:
SnackBarBehavior
.
floating
,
),
);
return
;
}
final
Uri
phoneUri
=
Uri
(
scheme:
'tel'
,
path:
phone
);
try
{
if
(
await
canLaunchUrl
(
phoneUri
))
{
await
launchUrl
(
phoneUri
);
}
else
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
backgroundColor:
Colors
.
redAccent
,
content:
const
Text
(
"Unable to start the call"
,
style:
TextStyle
(
color:
Colors
.
white
),
),
duration:
Duration
(
seconds:
2
),
behavior:
SnackBarBehavior
.
floating
,
),
);
}
}
catch
(
e
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
backgroundColor:
Colors
.
redAccent
,
content:
Text
(
"Error while trying to call:
$e
"
,
style:
const
TextStyle
(
color:
Colors
.
white
),
),
duration:
const
Duration
(
seconds:
2
),
behavior:
SnackBarBehavior
.
floating
,
),
);
}
},
child:
Container
(
padding:
const
EdgeInsets
.
all
(
14
),
decoration:
BoxDecoration
(
color:
const
Color
(
0xFF4CAF50
),
borderRadius:
BorderRadius
.
circular
(
30
),
),
child:
SvgPicture
.
asset
(
"assets/svg/phone_ic.svg"
,
height:
16
,
color:
Colors
.
white
,
fit:
BoxFit
.
contain
,
),
),
),
],
),
],
),
);
}
}
lib/Screens/HelpAndComplaintScreens/ComplaintListScreen.dart
0 → 100644
View file @
f3a137b2
import
'package:flutter/material.dart'
;
import
'package:flutter_svg/svg.dart'
;
import
'package:gen_service/Notifiers/HelpAndComplaintProvider.dart'
;
import
'package:gen_service/Screens/HelpAndComplaintScreens/SelectOrderHelpScreen.dart'
;
import
'package:gen_service/Screens/ProfileScreen.dart'
;
import
'package:provider/provider.dart'
;
import
'../../Utility/AppColors.dart'
;
class
ComplaintListScreen
extends
StatefulWidget
{
final
String
accId
;
final
String
sessionId
;
const
ComplaintListScreen
({
Key
?
key
,
required
this
.
accId
,
required
this
.
sessionId
,
})
:
super
(
key:
key
);
@override
State
<
ComplaintListScreen
>
createState
()
=>
_ComplaintListScreenState
();
}
class
_ComplaintListScreenState
extends
State
<
ComplaintListScreen
>
{
bool
_stretch
=
true
;
@override
void
initState
()
{
super
.
initState
();
Future
.
microtask
(()
{
final
provider
=
Provider
.
of
<
HelpAndComplaintProvider
>(
context
,
listen:
false
);
provider
.
fetchComplaintsList
(
accId:
widget
.
accId
,
sessionId:
widget
.
sessionId
,
);
});
}
@override
Widget
build
(
BuildContext
context
)
{
final
provider
=
Provider
.
of
<
HelpAndComplaintProvider
>(
context
);
final
isLoading
=
provider
.
isLoading
;
final
error
=
provider
.
errorMessage
;
final
data
=
provider
.
complaintListResponse
;
if
(
isLoading
)
{
return
const
Scaffold
(
backgroundColor:
AppColors
.
backgroundRegular
,
body:
Center
(
child:
CircularProgressIndicator
(
color:
AppColors
.
buttonColor
),
),
);
}
if
(
error
!=
null
)
{
return
Scaffold
(
backgroundColor:
AppColors
.
backgroundRegular
,
body:
Center
(
child:
Text
(
error
,
style:
const
TextStyle
(
color:
Colors
.
red
,
fontSize:
16
),
),
),
);
}
if
(
data
==
null
)
{
return
const
Scaffold
(
backgroundColor:
AppColors
.
backgroundRegular
,
body:
Center
(
child:
Text
(
"No data found."
),
),
);
}
// Separate open and closed complaints
final
openComplaints
=
data
.
complaintList
!
.
where
((
c
)
=>
c
.
openStatus
?.
toLowerCase
()
==
"open"
)
.
toList
();
final
closedComplaints
=
data
.
complaintList
!
.
where
((
c
)
=>
c
.
openStatus
?.
toLowerCase
()
==
"closed"
)
.
toList
();
return
RefreshIndicator
.
adaptive
(
color:
AppColors
.
amountText
,
onRefresh:
()
async
{
await
provider
.
fetchComplaintsList
(
accId:
widget
.
accId
,
sessionId:
widget
.
sessionId
,
);
},
child:
Scaffold
(
backgroundColor:
AppColors
.
backgroundRegular
,
body:
CustomScrollView
(
physics:
const
ClampingScrollPhysics
(),
slivers:
<
Widget
>[
SliverAppBar
(
leading:
Container
(),
stretch:
_stretch
,
backgroundColor:
const
Color
(
0xFF4076FF
),
onStretchTrigger:
()
async
{
await
provider
.
fetchComplaintsList
(
accId:
widget
.
accId
,
sessionId:
widget
.
sessionId
,
);
},
stretchTriggerOffset:
300.0
,
// expandedHeight: 60.0,
flexibleSpace:
FlexibleSpaceBar
(
stretchModes:
const
[
StretchMode
.
zoomBackground
,
StretchMode
.
blurBackground
,
],
background:
Container
(
decoration:
const
BoxDecoration
(
color:
AppColors
.
primary
),
child:
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
16
),
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
end
,
children:
[
InkResponse
(
onTap:
()
=>
Navigator
.
pop
(
context
,
true
),
child:
SvgPicture
.
asset
(
color:
Colors
.
white
,
"assets/svg/continue_left_ic.svg"
,
height:
30
,
),
),
const
SizedBox
(
width:
10
),
const
Text
(
"Help?"
,
style:
TextStyle
(
fontSize:
16
,
fontFamily:
"Poppins"
,
fontWeight:
FontWeight
.
w400
,
color:
Colors
.
white
,
),
),
],
),
),
),
),
),
/// Main body container
SliverToBoxAdapter
(
child:
Container
(
padding:
const
EdgeInsets
.
only
(
top:
1
),
color:
AppColors
.
primary
,
child:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
20
),
decoration:
const
BoxDecoration
(
color:
AppColors
.
backgroundRegular
,
borderRadius:
BorderRadius
.
only
(
topLeft:
Radius
.
circular
(
30
),
topRight:
Radius
.
circular
(
30
),
),
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
/// Top Tile
InkResponse
(
onTap:
()
{
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)=>
SelectOrderHelpScreen
(
accId:
widget
.
accId
,
sessionId:
widget
.
sessionId
))
).
then
((
_
)
async
{
await
provider
.
fetchComplaintsList
(
accId:
widget
.
accId
,
sessionId:
widget
.
sessionId
,
);
});
},
child:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
16
,
horizontal:
14
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
14
),
),
child:
Row
(
children:
[
SizedBox
(
height:
42
,
width:
42
,
child:
SvgPicture
.
asset
(
"assets/svg/help_ic.svg"
,
fit:
BoxFit
.
contain
,
),
),
const
SizedBox
(
width:
12
),
Expanded
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
const
[
Text
(
"Get help for an order"
,
style:
TextStyle
(
fontFamily:
"Poppins"
,
fontSize:
14
,
fontWeight:
FontWeight
.
w400
,
color:
Colors
.
black
,
),
),
SizedBox
(
height:
4
),
Text
(
"Select a Generator"
,
style:
TextStyle
(
fontFamily:
"Poppins"
,
fontSize:
12
,
fontWeight:
FontWeight
.
w400
,
color:
Colors
.
grey
,
),
),
],
),
),
SvgPicture
.
asset
(
"assets/svg/continue_ic.svg"
,
color:
Colors
.
black
,
height:
32
,
),
],
),
),
),
const
SizedBox
(
height:
25
),
/// Raised Complaints
if
(
openComplaints
.
isNotEmpty
)
const
Text
(
"Raised Complaints"
,
style:
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
w500
,
color:
Colors
.
black87
,
),
),
const
SizedBox
(
height:
8
),
...
openComplaints
.
map
(
(
c
)
=>
ComplaintCard
(
title:
c
.
complaintName
??
"-"
,
id:
c
.
id
??
"-"
,
product:
c
.
productName
??
""
,
status:
c
.
openStatus
??
"Open"
,
date:
c
.
registredDate
??
""
,
engModel:
c
.
modelName
??
"-"
,
),
),
const
SizedBox
(
height:
25
),
/// Resolved Complaints
if
(
closedComplaints
.
isNotEmpty
)
const
Text
(
"Resolved Complaints"
,
style:
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
w500
,
color:
Colors
.
black87
,
),
),
const
SizedBox
(
height:
8
),
...
closedComplaints
.
map
(
(
c
)
=>
ComplaintCard
(
title:
c
.
complaintName
??
"-"
,
id:
c
.
id
??
""
,
product:
c
.
productName
??
""
,
status:
c
.
openStatus
??
"Closed"
,
date:
c
.
registredDate
??
""
,
engModel:
c
.
modelName
??
""
,
),
),
],
),
),
),
),
],
),
),
);
}
}
/// Reusable Complaint Item Card
class
ComplaintCard
extends
StatelessWidget
{
final
String
title
;
final
String
id
;
final
String
product
;
final
String
status
;
final
String
date
;
final
String
engModel
;
const
ComplaintCard
({
super
.
key
,
required
this
.
title
,
required
this
.
id
,
required
this
.
product
,
required
this
.
status
,
required
this
.
date
,
required
this
.
engModel
,
});
@override
Widget
build
(
BuildContext
context
)
{
return
Container
(
margin:
const
EdgeInsets
.
symmetric
(
vertical:
6
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
14
,
vertical:
14
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
12
),
border:
Border
.
all
(
color:
Colors
.
grey
.
shade200
),
boxShadow:
[
BoxShadow
(
color:
Colors
.
grey
.
shade200
,
blurRadius:
4
,
offset:
const
Offset
(
0
,
2
),
)
],
),
child:
Column
(
children:
[
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Row
(
children:
[
Text
(
"#
${id}
| "
,
style:
TextStyle
(
fontFamily:
"Poppins"
,
fontSize:
14
,
fontWeight:
FontWeight
.
w400
,
color:
AppColors
.
amountText
,
),
),
Text
(
title
,
style:
TextStyle
(
fontFamily:
"Poppins"
,
fontSize:
14
,
fontWeight:
FontWeight
.
w400
,
color:
AppColors
.
amountText
,
),
),
],
),
const
SizedBox
(
height:
4
),
Text
(
"Date:
$date
"
,
style:
TextStyle
(
fontFamily:
"Poppins"
,
fontSize:
12
,
fontWeight:
FontWeight
.
w400
,
color:
AppColors
.
subtitleText
,
),
),
const
SizedBox
(
height:
2
),
],
),
Container
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
15
,
vertical:
7
),
decoration:
BoxDecoration
(
color:
status
==
"Open"
?
AppColors
.
successBG
:
AppColors
.
yellowBG
,
borderRadius:
BorderRadius
.
circular
(
10
),
),
child:
Text
(
status
,
style:
TextStyle
(
fontFamily:
"Poppins"
,
fontSize:
14
,
fontWeight:
FontWeight
.
w400
,
color:
status
==
"Open"
?
AppColors
.
success
:
AppColors
.
normalText
,
),
),
),
],
),
Divider
(),
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
Expanded
(
flex:
6
,
child:
Text
(
product
,
maxLines:
2
,
style:
TextStyle
(
fontFamily:
"Poppins"
,
fontSize:
12
,
fontWeight:
FontWeight
.
w400
,
color:
Colors
.
black87
,
),
),
),
Text
(
"#
${id}
| Engine :
$engModel
"
,
style:
TextStyle
(
fontFamily:
"Poppins"
,
fontSize:
12
,
fontWeight:
FontWeight
.
w400
,
color:
AppColors
.
subtitleText
,
),
),
],
),
],
),
);
}
}
lib/Screens/HelpAndComplaintScreens/SelectOrderHelpScreen.dart
View file @
f3a137b2
...
...
@@ -26,7 +26,10 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
void
initState
()
{
super
.
initState
();
Future
.
microtask
(()
{
final
provider
=
Provider
.
of
<
HelpAndComplaintProvider
>(
context
,
listen:
false
);
final
provider
=
Provider
.
of
<
HelpAndComplaintProvider
>(
context
,
listen:
false
,
);
provider
.
fetchGeneratorList
(
accId:
widget
.
accId
,
sessionId:
widget
.
sessionId
,
...
...
@@ -63,12 +66,12 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
);
}
if
(
generatorData
==
null
||
generatorData
.
orders
==
null
||
generatorData
.
orders
!.
isEmpty
)
{
if
(
generatorData
==
null
||
generatorData
.
orders
==
null
||
generatorData
.
orders
!.
isEmpty
)
{
return
const
Scaffold
(
backgroundColor:
AppColors
.
backgroundRegular
,
body:
Center
(
child:
Text
(
"No Generators Found."
),
),
body:
Center
(
child:
Text
(
"No Generators Found."
)),
);
}
...
...
@@ -107,7 +110,10 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
background:
Container
(
decoration:
const
BoxDecoration
(
color:
AppColors
.
primary
),
child:
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
16
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
16
,
),
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
end
,
children:
[
...
...
@@ -141,7 +147,10 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
child:
Container
(
color:
AppColors
.
primary
,
child:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
20
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
20
,
),
decoration:
const
BoxDecoration
(
color:
AppColors
.
backgroundRegular
,
borderRadius:
BorderRadius
.
only
(
...
...
@@ -166,7 +175,7 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
),
const
SizedBox
(
height:
16
),
///
🧾
Generator List from Provider
/// Generator List from Provider
...
genList
.
map
((
order
)
{
return
Column
(
children:
[
...
...
@@ -174,13 +183,16 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
onTap:
()
{
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
AddComplaintScreen
(
MaterialPageRoute
(
builder:
(
context
)
=>
AddComplaintScreen
(
accId:
widget
.
accId
,
sessionId:
widget
.
sessionId
,
product:
order
.
prodName
.
toString
(),
hashId:
order
.
hashId
.
toString
(),
modolNo:
order
.
engine
.
toString
())
)
modolNo:
order
.
engine
.
toString
(),
),
),
).
then
((
_
)
async
{
await
provider
.
fetchGeneratorList
(
accId:
widget
.
accId
,
...
...
@@ -189,15 +201,18 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
});
},
child:
_buildOrderItem
(
assetId:
"#
${order.hashId ?? ''}
| Engine :
${order.engine ?? ''}
"
,
assetId:
"#
${order.hashId ?? ''}
| Engine :
${order.engine ?? ''}
"
,
description:
order
.
prodName
??
''
,
amc:
order
.
amc
??
''
,
warranty:
order
.
warranty
??
''
,
pImage:
order
.
productImage
??
''
,
date:
order
.
schedule
?.
isNotEmpty
==
true
date:
order
.
schedule
?.
isNotEmpty
==
true
?
order
.
schedule
!.
first
:
null
,
serviceText:
order
.
schedule
?.
isNotEmpty
==
true
serviceText:
order
.
schedule
?.
isNotEmpty
==
true
?
'Upcoming Service Scheduled'
:
null
,
),
...
...
@@ -270,9 +285,13 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
children:
[
if
(
amc
==
"1"
||
amc
==
"2"
)
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
8
,
vertical:
4
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
8
,
vertical:
4
,
),
decoration:
BoxDecoration
(
gradient:
amc
==
"1"
gradient:
amc
==
"1"
?
AppColors
.
greenStripGradient
:
AppColors
.
fadeGradient
,
borderRadius:
BorderRadius
.
circular
(
12
),
...
...
@@ -283,7 +302,8 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
SvgPicture
.
asset
(
"assets/svg/tick_ic.svg"
,
height:
14
,
color:
amc
==
"1"
color:
amc
==
"1"
?
AppColors
.
greenICBg
:
AppColors
.
subtitleText
,
),
...
...
@@ -295,7 +315,8 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
fontFamily:
"PoppinsBold"
,
fontStyle:
FontStyle
.
italic
,
fontWeight:
FontWeight
.
w700
,
color:
amc
==
"1"
color:
amc
==
"1"
?
AppColors
.
greenICBg
:
AppColors
.
subtitleText
,
),
...
...
@@ -305,9 +326,13 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
),
if
(
warranty
==
"1"
||
warranty
==
"2"
)
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
8
,
vertical:
4
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
8
,
vertical:
4
,
),
decoration:
BoxDecoration
(
gradient:
warranty
==
"1"
gradient:
warranty
==
"1"
?
AppColors
.
yellowStripGradient
:
AppColors
.
fadeGradient
,
borderRadius:
BorderRadius
.
circular
(
12
),
...
...
@@ -318,7 +343,8 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
SvgPicture
.
asset
(
"assets/svg/tick2_ic.svg"
,
height:
14
,
color:
warranty
==
"1"
color:
warranty
==
"1"
?
AppColors
.
warning
:
AppColors
.
subtitleText
,
),
...
...
@@ -330,7 +356,8 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
fontFamily:
"PoppinsBold"
,
fontStyle:
FontStyle
.
italic
,
fontWeight:
FontWeight
.
w700
,
color:
warranty
==
"1"
color:
warranty
==
"1"
?
AppColors
.
normalText
:
AppColors
.
subtitleText
,
),
...
...
@@ -359,7 +386,8 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
height:
50
,
width:
50
,
fit:
BoxFit
.
contain
,
errorBuilder:
(
context
,
error
,
stack
)
=>
Image
.
asset
(
errorBuilder:
(
context
,
error
,
stack
)
=>
Image
.
asset
(
'assets/images/dashboard_gen.png'
,
height:
40
,
width:
40
,
...
...
@@ -370,48 +398,48 @@ class _SelectOrderHelpScreenState extends State<SelectOrderHelpScreen> {
),
/// Service info (optional)
if
(
date
!=
null
&&
serviceText
!=
null
)
...[
const
SizedBox
(
height:
12
),
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
14
,
vertical:
12
),
decoration:
BoxDecoration
(
color:
const
Color
(
0xffF2F2F2
),
borderRadius:
BorderRadius
.
circular
(
16
),
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
start
,
children:
[
SvgPicture
.
asset
(
"assets/svg/checked_ic.svg"
,
height:
30
,
fit:
BoxFit
.
contain
,
),
const
SizedBox
(
width:
10
),
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
date
,
style:
const
TextStyle
(
fontSize:
12
,
color:
AppColors
.
normalText
,
fontWeight:
FontWeight
.
w500
,
),
),
Text
(
serviceText
,
style:
const
TextStyle
(
fontSize:
12
,
color:
AppColors
.
subtitleText
,
fontWeight:
FontWeight
.
w500
,
),
),
],
),
],
),
),
],
//
if (date != null && serviceText != null) ...[
//
const SizedBox(height: 12),
//
Container(
//
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
//
decoration: BoxDecoration(
//
color: const Color(0xffF2F2F2),
//
borderRadius: BorderRadius.circular(16),
//
),
//
child: Row(
//
mainAxisAlignment: MainAxisAlignment.start,
//
children: [
//
SvgPicture.asset(
//
"assets/svg/checked_ic.svg",
//
height: 30,
//
fit: BoxFit.contain,
//
),
//
const SizedBox(width: 10),
//
Column(
//
crossAxisAlignment: CrossAxisAlignment.start,
//
children: [
//
Text(
//
date,
//
style: const TextStyle(
//
fontSize: 12,
//
color: AppColors.normalText,
//
fontWeight: FontWeight.w500,
//
),
//
),
//
Text(
//
serviceText,
//
style: const TextStyle(
//
fontSize: 12,
//
color: AppColors.subtitleText,
//
fontWeight: FontWeight.w500,
//
),
//
),
//
],
//
),
//
],
//
),
//
),
//
],
],
),
);
...
...
lib/Screens/HomeScreen.dart
View file @
f3a137b2
import
'dart:io'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_svg/svg.dart'
;
import
'package:gen_service/Screens/ContactUsScreen.dart'
;
import
'package:gen_service/Screens/HelpAndComplaintScreens/SelectOrderHelpScreen.dart'
;
import
'package:gen_service/Screens/HelpAndComplaintScreens/ComplaintListScreen.dart'
;
import
'package:gen_service/Screens/ProfileScreen.dart'
;
import
'package:gen_service/Screens/TransactionListScreen.dart'
;
import
'package:gen_service/Screens/TransactionScreens/TransactionListScreen.dart'
;
import
'package:provider/provider.dart'
;
import
'../Notifiers/DashboardProvider.dart'
;
import
'../Utility/AppColors.dart'
;
import
'../Utility/CustomSnackbar.dart'
;
import
'generatorDetailsScreen.dart'
;
class
HomeScreen
extends
StatefulWidget
{
final
String
accId
;
final
String
sessionId
;
...
...
@@ -22,9 +31,12 @@ class HomeScreen extends StatefulWidget {
State
<
HomeScreen
>
createState
()
=>
_HomeScreenState
();
}
class
_HomeScreenState
extends
State
<
HomeScreen
>
{
bool
_stretch
=
true
;
DateTime
?
currentBackPressTime
;
@override
void
initState
()
{
super
.
initState
();
...
...
@@ -35,6 +47,24 @@ class _HomeScreenState extends State<HomeScreen> {
});
}
Future
<
bool
>
_onWillPop
()
async
{
DateTime
now
=
DateTime
.
now
();
if
(
currentBackPressTime
==
null
||
now
.
difference
(
currentBackPressTime
!)
>
Duration
(
seconds:
2
))
{
currentBackPressTime
=
now
;
CustomSnackBar
.
showExit
(
context:
context
,
title:
"Exit"
,
message:
'Press back again to exit'
);
return
false
;
}
// Close the entire app immediately
exit
(
0
);
}
@override
Widget
build
(
BuildContext
context
)
{
final
dashboardProvider
=
Provider
.
of
<
DashboardProvider
>(
context
);
...
...
@@ -73,7 +103,9 @@ class _HomeScreenState extends State<HomeScreen> {
);
}
return
RefreshIndicator
.
adaptive
(
return
WillPopScope
(
onWillPop:
_onWillPop
,
child:
RefreshIndicator
.
adaptive
(
color:
AppColors
.
amountText
,
onRefresh:
()
async
{
await
Future
.
delayed
(
const
Duration
(
milliseconds:
600
));
...
...
@@ -277,7 +309,14 @@ class _HomeScreenState extends State<HomeScreen> {
const
SizedBox
(
height:
20
),
// Get in Touch Card
Container
(
InkResponse
(
onTap:
()
{
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
ContactUsScreen
(
accId:
widget
.
accId
,
sessionId:
widget
.
sessionId
))
);
},
child:
Container
(
width:
double
.
infinity
,
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
20
,
vertical:
30
),
decoration:
BoxDecoration
(
...
...
@@ -319,6 +358,7 @@ class _HomeScreenState extends State<HomeScreen> {
],
),
)
),
),
// Add bottom padding
],
),
...
...
@@ -328,6 +368,7 @@ class _HomeScreenState extends State<HomeScreen> {
],
),
),
),
);
}
...
...
@@ -343,7 +384,8 @@ class _HomeScreenState extends State<HomeScreen> {
);
}
return
Padding
(
return
InkResponse
(
child:
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
14
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
...
...
@@ -352,7 +394,20 @@ class _HomeScreenState extends State<HomeScreen> {
...
orders
.
map
<
Widget
>((
order
)
{
return
Column
(
children:
[
_buildOrderItem
(
InkResponse
(
onTap:
()
async
{
await
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
Generatordetailsscreen
(
accId:
widget
.
accId
,
sessionId:
widget
.
sessionId
,
genId:
order
.
id
,
),
),
);
},
child:
_buildOrderItem
(
assetId:
"#
${order.hashId ?? ''}
| Engine :
${order.engine ?? ''}
"
,
description:
order
.
prodName
??
''
,
amc:
(
order
.
amc
?.
toString
()
??
''
),
...
...
@@ -365,6 +420,7 @@ class _HomeScreenState extends State<HomeScreen> {
?
'Upcoming Service Scheduled'
:
null
,
),
),
const
SizedBox
(
height:
12
),
],
);
...
...
@@ -373,6 +429,7 @@ class _HomeScreenState extends State<HomeScreen> {
],
),
),
);
}
...
...
@@ -640,7 +697,7 @@ class _HomeScreenState extends State<HomeScreen> {
width:
double
.
infinity
,
padding:
const
EdgeInsets
.
all
(
22
),
decoration:
BoxDecoration
(
gradient:
AppColors
.
balanceCardGradientP
,
gradient:
dashboardData
.
balanceType
==
'Pending Balance'
?
AppColors
.
balanceCardGradientP
:
AppColors
.
balanceCardGradientA
,
borderRadius:
BorderRadius
.
circular
(
16
),
),
child:
Row
(
...
...
@@ -700,6 +757,7 @@ class _HomeScreenState extends State<HomeScreen> {
),
),
const
SizedBox
(
height:
10
),
if
(
dashboardData
.
balanceType
==
'Pending Balance'
)
InkResponse
(
onTap:
()
{
// Add pay now logic
...
...
lib/Screens/ProfileScreen.dart
View file @
f3a137b2
import
'dart:ui'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_svg/svg.dart'
;
import
'package:gen_service/Screens/AuthScreen/LoginScreen.dart'
;
import
'package:gen_service/Utility/CustomSnackbar.dart'
;
import
'package:provider/provider.dart'
;
import
'package:shared_preferences/shared_preferences.dart'
;
import
'../Notifiers/AuthProvider.dart'
;
import
'../Notifiers/DashboardProvider.dart'
;
import
'../Utility/AppColors.dart'
;
import
'../Utility/SharedpreferencesService.dart'
;
class
ProfileScreen
extends
StatefulWidget
{
final
String
accId
;
...
...
@@ -20,168 +27,353 @@ class ProfileScreen extends StatefulWidget {
}
class
_ProfileScreenState
extends
State
<
ProfileScreen
>
{
bool
_stretch
=
true
;
@override
void
initState
()
{
super
.
initState
();
Future
.
microtask
(()
{
final
dashboardProvider
=
Provider
.
of
<
DashboardProvider
>(
context
,
listen:
false
);
dashboardProvider
.
fetchDashboard
(
widget
.
accId
,
widget
.
sessionId
);
final
profileProvider
=
Provider
.
of
<
DashboardProvider
>(
context
,
listen:
false
);
profileProvider
.
fetchProfile
(
widget
.
accId
,
widget
.
sessionId
);
});
}
@override
Widget
build
(
BuildContext
context
)
{
final
dashboardProvider
=
Provider
.
of
<
DashboardProvider
>(
context
);
final
isLoading
=
dashboardProvider
.
isLoading
;
final
error
=
dashboardProvider
.
errorMessage
;
final
data
=
dashboardProvider
.
dashboardData
;
Future
<
void
>
onLogout
(
BuildContext
context
)
async
{
final
provider
=
Provider
.
of
<
AuthProvider
>(
context
,
listen:
false
);
return
Scaffold
(
backgroundColor:
AppColors
.
backgroundRegular
,
body:
Stack
(
children:
[
if
(
isLoading
)
const
Center
(
child:
CircularProgressIndicator
(),
)
else
if
(
error
!=
null
)
Center
(
child:
Text
(
error
,
style:
const
TextStyle
(
color:
Colors
.
red
,
fontSize:
16
),
// 🧭 Step 1: Ask confirmation
final
confirm
=
await
showDialog
<
bool
>(
context:
context
,
builder:
(
context
)
{
return
Dialog
(
backgroundColor:
Colors
.
white
,
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
20
),
),
elevation:
0
,
child:
Container
(
padding:
const
EdgeInsets
.
all
(
24
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
20
),
boxShadow:
[
BoxShadow
(
color:
Colors
.
black
.
withOpacity
(
0.1
),
blurRadius:
20
,
offset:
const
Offset
(
0
,
4
),
),
],
),
)
else
if
(
data
==
null
)
const
Center
(
child:
Text
(
"No data found."
),
)
else
Stack
(
children:
[
/// 🔹 Profile Section
Positioned
(
top:
0
,
left:
0
,
right:
0
,
child:
_buildProfileSection
(
data
.
userProfile
??
""
,
data
.
userName
??
"User"
,
data
.
mobNum
??
""
,
),
),
/// 🔹 Scrollable Content
SafeArea
(
child:
SingleChildScrollView
(
physics:
const
ClampingScrollPhysics
(),
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
children:
[
const
SizedBox
(
height:
200
),
/// Bottom Sheet style container
// Icon
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
14
),
width:
double
.
infinity
,
decoration:
const
BoxDecoration
(
color:
AppColors
.
backgroundRegular
,
borderRadius:
BorderRadius
.
only
(
topLeft:
Radius
.
circular
(
30
),
topRight:
Radius
.
circular
(
30
),
width:
60
,
height:
60
,
decoration:
BoxDecoration
(
color:
AppColors
.
buttonColor
.
withOpacity
(
0.1
),
shape:
BoxShape
.
circle
,
),
child:
Icon
(
Icons
.
logout_rounded
,
color:
AppColors
.
buttonColor
,
size:
30
,
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
const
SizedBox
(
height:
20
),
// 🔹 Orders Section
_buildOrdersSection
(
data
),
const
SizedBox
(
height:
4
),
// 🔹 Transactions Card
_buildTransactionsCard
(
data
),
const
SizedBox
(
height:
18
),
const
Divider
(),
// 🔹 Complaints Section
_buildComplaintsSection
(
data
),
),
const
SizedBox
(
height:
16
),
const
SizedBox
(
height:
20
),
// Title
Text
(
"Logout"
,
style:
TextStyle
(
fontFamily:
"Poppins"
,
fontWeight:
FontWeight
.
w700
,
fontSize:
20
,
color:
Colors
.
black87
,
),
),
const
SizedBox
(
height:
8
),
_buildFixIssuesCard
(),
const
SizedBox
(
height:
20
),
// _buildGetInTouchCard(),
// const SizedBox(height: 30),
],
// Subtitle
Text
(
"Are you sure you want to logout?"
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
fontFamily:
"Poppins"
,
fontSize:
14
,
fontWeight:
FontWeight
.
w400
,
color:
Colors
.
grey
[
600
],
height:
1.4
,
),
),
const
SizedBox
(
height:
24
),
// Buttons Row
Row
(
children:
[
// Cancel Button
Expanded
(
child:
OutlinedButton
(
onPressed:
()
=>
Navigator
.
pop
(
context
,
false
),
style:
OutlinedButton
.
styleFrom
(
backgroundColor:
Colors
.
transparent
,
foregroundColor:
Colors
.
grey
[
600
],
side:
BorderSide
(
color:
Colors
.
grey
[
300
]!,
width:
1.5
,
),
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
12
),
),
padding:
const
EdgeInsets
.
symmetric
(
vertical:
14
),
elevation:
0
,
),
child:
Text
(
"Cancel"
,
style:
TextStyle
(
fontFamily:
"Poppins"
,
fontWeight:
FontWeight
.
w600
,
fontSize:
14
,
color:
Colors
.
grey
[
700
],
),
),
),
),
const
SizedBox
(
width:
12
),
Container
(
width:
double
.
infinity
,
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
20
,
vertical:
30
),
decoration:
BoxDecoration
(
color:
AppColors
.
amountText
,
borderRadius:
BorderRadius
.
only
(
topLeft:
Radius
.
circular
(
24
),
topRight:
Radius
.
circular
(
24
),
// Logout Button
Expanded
(
child:
ElevatedButton
(
onPressed:
()
=>
Navigator
.
pop
(
context
,
true
),
style:
ElevatedButton
.
styleFrom
(
backgroundColor:
AppColors
.
buttonColor
,
foregroundColor:
Colors
.
white
,
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
12
),
),
padding:
const
EdgeInsets
.
symmetric
(
vertical:
14
),
elevation:
0
,
shadowColor:
Colors
.
transparent
,
),
child:
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
Text
(
'Get in touch With Us'
,
"Logout"
,
style:
TextStyle
(
fontFamily:
"Poppins"
,
fontWeight:
FontWeight
.
w600
,
fontSize:
14
,
fontWeight:
FontWeight
.
w500
,
color:
Colors
.
white
),
color:
Colors
.
white
,
),
Text
(
'Please feel free to reach out to us anytime'
,
style:
TextStyle
(
fontSize:
12
,
fontWeight:
FontWeight
.
w400
,
color:
Color
(
0xAAFFFFFF
)),
),
],
),
Icon
(
Icons
.
arrow_circle_right_rounded
,
color:
Color
(
0xFFFFFFFF
),
size:
30
),
],
),
)
),
],
),
],
),
),
);
},
);
// Step 2: If user cancelled, just return
if
(
confirm
!=
true
)
return
;
// Step 3: Show loading indicator
showDialog
(
context:
context
,
barrierDismissible:
false
,
builder:
(
context
)
{
return
BackdropFilter
(
filter:
ImageFilter
.
blur
(
sigmaX:
3
,
sigmaY:
3
),
child:
Dialog
(
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
16
),
),
backgroundColor:
Colors
.
white
.
withOpacity
(
0.9
),
child:
Padding
(
padding:
const
EdgeInsets
.
all
(
24
),
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
children:
[
CircularProgressIndicator
(
color:
AppColors
.
buttonColor
,
strokeWidth:
3
,
),
const
SizedBox
(
height:
20
),
Text
(
"Logging out..."
,
style:
TextStyle
(
fontFamily:
"Poppins"
,
fontWeight:
FontWeight
.
w600
,
fontSize:
16
,
color:
Colors
.
grey
[
800
],
),
),
],
),
),
),
);
},
);
try
{
final
success
=
await
provider
.
logout
(
widget
.
accId
,
widget
.
sessionId
,
);
// Close loading dialog
if
(
context
.
mounted
)
Navigator
.
pop
(
context
);
if
(
success
)
{
// ✅ Success — clear shared prefs
final
prefs
=
SharedPreferencesService
.
instance
;
await
prefs
.
clearPreferences
();
if
(
context
.
mounted
)
{
CustomSnackBar
.
showSuccess
(
context:
context
,
message:
"Logged out successfully"
);
await
Future
.
delayed
(
const
Duration
(
milliseconds:
1500
));
Navigator
.
pushAndRemoveUntil
(
context
,
MaterialPageRoute
(
builder:
(
_
)
=>
const
LoginScreen
()),
(
route
)
=>
false
,
);
}
}
else
{
// ❌ Logout failed — show error snackbar
if
(
context
.
mounted
)
{
CustomSnackBar
.
showError
(
context:
context
,
message:
"Logout failed. Please try again."
);
}
}
}
catch
(
e
)
{
// Handle exceptions
if
(
context
.
mounted
)
Navigator
.
pop
(
context
);
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
backgroundColor:
Colors
.
redAccent
,
content:
Row
(
children:
[
const
Icon
(
Icons
.
error_outline
,
color:
Colors
.
white
,
size:
20
),
const
SizedBox
(
width:
8
),
Text
(
"Logout failed:
${e.toString()}
"
,
style:
const
TextStyle
(
fontFamily:
"Poppins"
,
fontWeight:
FontWeight
.
w500
,
),
),
],
),
duration:
const
Duration
(
seconds:
3
),
behavior:
SnackBarBehavior
.
floating
,
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
8
),
),
),
);
}
}
// PROFILE SECTION
// ===============================
Widget
_buildProfileSection
(
String
userProfile
,
String
userName
,
String
userContact
)
{
return
Container
(
@override
Widget
build
(
BuildContext
context
)
{
final
profileProvider
=
Provider
.
of
<
DashboardProvider
>(
context
);
final
authProvider
=
Provider
.
of
<
AuthProvider
>(
context
);
final
isLoading
=
profileProvider
.
isLoading
;
final
error
=
profileProvider
.
errorMessage
;
final
data
=
profileProvider
.
profileData
?.
details
;
if
(
isLoading
)
{
return
const
Scaffold
(
backgroundColor:
AppColors
.
backgroundRegular
,
body:
Center
(
child:
CircularProgressIndicator
(
color:
AppColors
.
buttonColor
,),
),
);
}
if
(
error
!=
null
)
{
return
Scaffold
(
backgroundColor:
AppColors
.
backgroundRegular
,
body:
Center
(
child:
Text
(
error
,
style:
const
TextStyle
(
color:
Colors
.
red
,
fontSize:
16
),
),
),
);
}
if
(
data
==
null
)
{
return
const
Scaffold
(
backgroundColor:
AppColors
.
backgroundRegular
,
body:
Center
(
child:
Text
(
"No data found."
),
),
);
}
return
RefreshIndicator
.
adaptive
(
color:
AppColors
.
amountText
,
onRefresh:
()
async
{
await
Future
.
delayed
(
const
Duration
(
milliseconds:
600
));
Provider
.
of
<
DashboardProvider
>(
context
,
listen:
false
);
profileProvider
.
fetchDashboard
(
widget
.
accId
,
widget
.
sessionId
);
},
child:
Scaffold
(
backgroundColor:
Color
(
0xFF4076FF
),
body:
CustomScrollView
(
physics:
ClampingScrollPhysics
(),
slivers:
<
Widget
>[
SliverAppBar
(
leading:
Container
(),
stretch:
_stretch
,
backgroundColor:
Color
(
0xFF4076FF
),
onStretchTrigger:
()
async
{
// Refresh data when pulled down
final
profileProvider
=
Provider
.
of
<
DashboardProvider
>(
context
,
listen:
false
);
profileProvider
.
fetchProfile
(
widget
.
accId
,
widget
.
sessionId
);
},
stretchTriggerOffset:
300.0
,
expandedHeight:
245.0
,
flexibleSpace:
LayoutBuilder
(
builder:
(
context
,
constraints
)
{
final
top
=
constraints
.
biggest
.
height
;
return
FlexibleSpaceBar
(
stretchModes:
const
[
StretchMode
.
zoomBackground
,
StretchMode
.
blurBackground
,
],
background:
GestureDetector
(
child:
Container
(
width:
double
.
infinity
,
height:
275
,
padding:
const
EdgeInsets
.
only
(
top:
60
,
bottom:
60
,
left:
20
,
right:
20
),
decoration:
const
BoxDecoration
(
gradient:
AppColors
.
backgroundGradient
),
child:
SafeArea
(
bottom:
false
,
child:
Padding
(
padding:
const
EdgeInsets
.
only
(
top:
20
,
bottom:
25
,
left:
20
,
right:
20
),
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
crossAxisAlignment:
CrossAxisAlignment
.
center
,
...
...
@@ -195,572 +387,263 @@ class _ProfileScreenState extends State<ProfileScreen> {
shape:
BoxShape
.
circle
,
),
clipBehavior:
Clip
.
antiAlias
,
child:
(
userP
rofile
.
isNotEmpty
)
child:
(
data
.
p
rofile
Img
?
.
isNotEmpty
==
true
)
?
Image
.
network
(
userProfile
,
data
.
profileImg
.
toString
()
,
fit:
BoxFit
.
cover
,
errorBuilder:
(
context
,
error
,
stackTrace
)
=>
const
Icon
(
Icons
.
person
,
color:
Color
(
0xFF2d2d2d
),
size:
100
),
CircleAvatar
(
radius:
40
,
backgroundColor:
const
Color
(
0xFFE0F4FF
),
child:
SvgPicture
.
asset
(
height:
40
,
"assets/svg/person_ic.svg"
,
fit:
BoxFit
.
contain
,
),
),
)
:
CircleAvatar
(
radius:
8
0
,
radius:
4
0
,
backgroundColor:
const
Color
(
0xFFE0F4FF
),
child:
SvgPicture
.
asset
(
height:
8
0
,
height:
4
0
,
"assets/svg/person_ic.svg"
,
fit:
BoxFit
.
contain
,
),
),
),
const
SizedBox
(
height:
16
),
Text
(
userName
,
Flexible
(
child:
Text
(
data
.
name
.
toString
(),
style:
const
TextStyle
(
color:
Colors
.
white
,
fontSize:
20
,
fontWeight:
FontWeight
.
w600
,
),
maxLines:
1
,
overflow:
TextOverflow
.
ellipsis
,
),
),
const
SizedBox
(
height:
8
),
Text
(
'+91
$
userContact
'
,
'+91
$
{data.mobNum}
'
,
style:
TextStyle
(
color:
Colors
.
white
.
withOpacity
(
0.9
),
fontSize:
14
,
),
)
]
,
maxLines:
1
,
overflow:
TextOverflow
.
ellipsis
,
),
);
}
// ORDERS SECTION
// ===============================
Widget
_buildOrdersSection
(
dashboardData
)
{
final
orders
=
dashboardData
.
orders
??
[];
if
(
orders
.
isEmpty
)
{
return
const
Center
(
child:
Text
(
"No Orders Found"
),
);
}
return
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
orders
.
map
<
Widget
>((
order
)
{
return
Column
(
children:
[
_buildOrderItem
(
assetId:
"#
${order.hashId ?? ''}
| Engine :
${order.engine ?? ''}
"
,
description:
order
.
prodName
??
''
,
status:
(
order
.
amc
?.
isNotEmpty
??
false
)
?
'AMC Protected'
:
(
order
.
warranty
?.
isNotEmpty
??
false
)
?
'WARRANTY'
:
'Unknown'
,
statusColor:
(
order
.
amc
?.
isNotEmpty
??
false
)
?
Colors
.
green
:
(
order
.
warranty
?.
isNotEmpty
??
false
)
?
Colors
.
orange
:
Colors
.
grey
,
p_imagae:
order
.
productImage
??
''
,
date:
order
.
schedule
?.
isNotEmpty
==
true
?
order
.
schedule
!.
first
:
null
,
serviceText:
order
.
schedule
?.
isNotEmpty
==
true
?
'Upcoming Service Scheduled'
:
null
,
),
const
SizedBox
(
height:
12
),
],
);
}).
toList
(),
);
}
Widget
_buildOrderItem
({
required
String
assetId
,
required
String
description
,
required
String
status
,
required
Color
statusColor
,
required
String
p_imagae
,
String
?
date
,
String
?
serviceText
,
})
{
return
Container
(
padding:
const
EdgeInsets
.
all
(
16
),
SizedBox
(
height:
12
,),
InkResponse
(
onTap:
()
=>
onLogout
(
context
),
child:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
20
,
vertical:
8
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
20
),
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
Expanded
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
assetId
,
child:
const
Text
(
" Logout "
,
style:
TextStyle
(
fontSize:
12
,
color:
AppColors
.
normalText
,
fontWeight:
FontWeight
.
w400
,
color:
AppColors
.
amountText
,
),
),
const
SizedBox
(
height:
4
),
Text
(
description
,
style:
TextStyle
(
fontSize:
14
,
color:
AppColors
.
normalText
,
height:
1.4
,
overflow:
TextOverflow
.
ellipsis
,
),
),
const
SizedBox
(
height:
8
),
// Status Badge with checkmark for AMC Protected
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
8
,
vertical:
4
),
decoration:
BoxDecoration
(
color:
statusColor
.
withOpacity
(
0.1
),
borderRadius:
BorderRadius
.
circular
(
6
),
border:
Border
.
all
(
color:
statusColor
.
withOpacity
(
0.3
),
),
),
child:
Row
(
mainAxisSize:
MainAxisSize
.
min
,
children:
[
if
(
status
==
'AMC Protected'
)
const
Icon
(
Icons
.
check_circle
,
color:
Colors
.
green
,
size:
12
,
),
if
(
status
==
'AMC Protected'
)
const
SizedBox
(
width:
4
),
Text
(
status
,
style:
TextStyle
(
fontSize:
10
,
fontWeight:
FontWeight
.
w600
,
color:
statusColor
,
),
),
],
),
),
],
),
),
const
SizedBox
(
width:
12
),
Container
(
padding:
const
EdgeInsets
.
all
(
8
),
decoration:
BoxDecoration
(
color:
const
Color
(
0xffF2F2F2
),
borderRadius:
BorderRadius
.
circular
(
12
),
),
child:
Image
.
network
(
p_imagae
??
"https://erp.gengroup.in/assets/upload/inventory_add_genesis_product_pic/_1761047459_6425.png"
,
height:
50
,
width:
50
,
fit:
BoxFit
.
contain
,
errorBuilder:
(
context
,
error
,
stack
)
=>
Image
.
asset
(
'assets/images/dashboard_gen.png'
,
height:
40
,
width:
40
),
),
),
SizedBox
(
height:
2
,),
],
),
// Date and Service Text for first item
if
(
date
!=
null
&&
serviceText
!=
null
)
...[
const
SizedBox
(
height:
12
),
Container
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
14
,
vertical:
12
),
decoration:
BoxDecoration
(
color:
const
Color
(
0xffF2F2F2
),
borderRadius:
BorderRadius
.
circular
(
16
),
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
start
,
children:
[
SvgPicture
.
asset
(
height:
30
,
"assets/svg/checked_ic.svg"
,
fit:
BoxFit
.
contain
,
),
SizedBox
(
width:
10
,),
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
date
,
style:
TextStyle
(
fontSize:
12
,
color:
AppColors
.
normalText
,
fontWeight:
FontWeight
.
w500
,
),
),
Text
(
serviceText
,
style:
TextStyle
(
fontSize:
12
,
color:
AppColors
.
subtitleText
,
fontWeight:
FontWeight
.
w500
,
),
);
},
),
],
),
],
),
// Body content
SliverToBoxAdapter
(
child:
Container
(
padding:
const
EdgeInsets
.
only
(
top:
1
,
bottom:
0
),
color:
Colors
.
transparent
,
child:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
0
),
decoration:
const
BoxDecoration
(
color:
AppColors
.
backgroundRegular
,
borderRadius:
BorderRadius
.
only
(
topLeft:
Radius
.
circular
(
30
),
topRight:
Radius
.
circular
(
30
),
),
],
],
),
);
}
// TRANSACTIONS CARD
// ===============================
Widget
_buildTransactionsCard
(
dashboardData
)
{
return
Column
(
child:
Padding
(
padding:
const
EdgeInsets
.
all
(
8.0
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
const
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
Text
(
'Transactions'
,
style:
TextStyle
(
fontSize:
18
,
fontWeight:
FontWeight
.
w600
,
color:
Colors
.
black87
,
),
),
],
const
SizedBox
(
height:
20
),
// email
_buildItemRow
(
icon:
"assets/svg/message_ic.svg"
,
iconBg:
Color
(
0xFFDFF8FF
),
title:
"Email ID"
,
subTitle:
data
.
email
.
toString
()
),
const
SizedBox
(
height:
8
),
Container
(
width:
double
.
infinity
,
padding:
const
EdgeInsets
.
all
(
22
)
,
decoration:
BoxDecoration
(
gradient:
AppColors
.
balanceCardGradientP
,
borderRadius:
BorderRadius
.
circular
(
16
),
// address
_buildItemRow
(
icon:
"assets/svg/lolipop_ic.svg"
,
iconBg:
Color
(
0xFFFFE5E5
),
title:
"Address"
,
subTitle:
data
.
address
.
toString
()
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
"₹"
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
20
,
height:
2
,
fontWeight:
FontWeight
.
w500
,
const
SizedBox
(
height:
4
),
// state
_buildItemRow
(
icon:
"assets/svg/pay_card_ic.svg"
,
iconBg:
Color
(
0xFFDFF8FF
),
title:
"State"
,
subTitle:
data
.
state
.
toString
()
),
const
SizedBox
(
height:
4
),
// sub local
_buildItemRow
(
icon:
"assets/svg/pay_card_ic.svg"
,
iconBg:
Color
(
0xFFDFF8FF
),
title:
"Sub Locality"
,
subTitle:
data
.
locality
.
toString
()
),
const
SizedBox
(
height:
120
),
Padding
(
padding:
const
EdgeInsets
.
only
(
bottom:
10
,
left:
20
,
right:
20
),
child:
Center
(
child:
Column
(
children:
[
SvgPicture
.
asset
(
"assets/svg/genesis_logo_2io.svg"
,
height:
55
,
color:
AppColors
.
buttonColor
,
),
SizedBox
(
height:
12
,),
Text
(
dashboardData
?.
balanceAmount
?.
toString
()
??
"0"
,
'Genesis Poweronics PVT. Ltd.'
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
34
,
fontWeight:
FontWeight
.
w500
,
),
),
],
fontSize:
14
,
fontWeight:
FontWeight
.
w400
,
color:
AppColors
.
subtitleText
),
),
const
SizedBox
(
height:
4
),
Row
(
children:
[
const
Icon
(
Icons
.
info_outline
,
color:
Colors
.
white
,
size:
16
),
const
SizedBox
(
width:
6
),
Text
(
dashboardData
.
balanceType
??
'Pending Balance'
,
style:
const
TextStyle
(
color:
Colors
.
white
,
'App Version 1.0'
,
style:
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
w400
,
color:
AppColors
.
subtitleText
),
),
),
],
),
],
),
Column
(
children:
[
Text
(
"*Make sure to pay before
\n
you incur any fines."
,
maxLines:
2
,
style:
TextStyle
(
color:
Color
(
0xAAFFFFFF
),
fontSize:
12
,
fontWeight:
FontWeight
.
w500
,
),
),
SizedBox
(
height:
10
,),
InkResponse
(
child:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
20
,
vertical:
8
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
20
),
),
child:
const
Text
(
" Pay Now "
,
style:
TextStyle
(
color:
Colors
.
blue
,
fontFamily:
"Poppins"
,
fontSize:
14
,
fontWeight:
FontWeight
.
w500
,
const
SizedBox
(
height:
80
),
],
),
),
),
),
],
),
],
),
),
],
);
}
// COMPLAINTS SECTION
// ===============================
Widget
_buildComplaintsSection
(
dashboardData
)
{
final
complaints
=
dashboardData
.
complaints
??
[];
if
(
complaints
.
isEmpty
)
{
return
const
Center
(
child:
Text
(
"No Complaints Found"
,
style:
TextStyle
(
fontSize:
14
,
color:
Colors
.
grey
),
),
);
}
return
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
const
SizedBox
(
height:
8
),
const
Text
(
"Complaints"
,
style:
TextStyle
(
fontSize:
18
,
fontWeight:
FontWeight
.
w600
,
color:
Colors
.
black87
,
),
),
const
SizedBox
(
height:
8
),
...
complaints
.
map
<
Widget
>((
c
)
{
Widget
_buildItemRow
({
required
String
icon
,
required
Color
iconBg
,
required
String
title
,
required
String
subTitle
,
})
{
return
Container
(
margin:
const
EdgeInsets
.
only
(
bottom:
10
),
padding:
const
EdgeInsets
.
all
(
16
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
12
),
border:
Border
.
all
(
color:
Colors
.
grey
.
shade200
),
boxShadow:
[
BoxShadow
(
color:
Colors
.
black
.
withOpacity
(
0.03
),
blurRadius:
6
,
offset:
const
Offset
(
0
,
2
),
),
],
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
/// 🔹 Top row — Complaint name and status
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
// Complaint info
Expanded
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
padding:
EdgeInsets
.
all
(
16
),
child:
Row
(
children:
[
Text
(
"#
${c.hashId ?? ''}
|
${c.complaintName ?? ''}
"
,
style:
const
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
w600
,
color:
AppColors
.
amountText
,
),
),
const
SizedBox
(
height:
4
),
Text
(
c
.
registredDate
??
''
,
style:
TextStyle
(
fontSize:
12
,
color:
Colors
.
grey
.
shade600
,
),
),
],
),
),
// Status badge
if
(
title
!=
"State"
&&
title
!=
"Sub Locality"
)
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
8
),
padding:
EdgeInsets
.
all
(
title
==
"Address"
?
8
:
12
),
decoration:
BoxDecoration
(
color:
(
c
.
openStatus
?.
toLowerCase
()
==
'open'
)
?
AppColors
.
successBG
:
AppColors
.
warningBg2
,
borderRadius:
BorderRadius
.
circular
(
10
),
color:
iconBg
,
borderRadius:
BorderRadius
.
circular
(
18
)
),
child:
Text
(
c
.
openStatus
??
''
,
style:
TextStyle
(
fontSize:
12
,
fontWeight:
FontWeight
.
w600
,
color:
(
c
.
openStatus
?.
toLowerCase
()
==
'open'
)
?
AppColors
.
success
:
AppColors
.
warningText
,
child:
SvgPicture
.
asset
(
height:
title
==
"Address"
?
34
:
26
,
icon
,
fit:
BoxFit
.
contain
,
),
),
if
(
title
!=
"Email ID"
&&
title
!=
"Address"
)
Expanded
(
flex:
1
,
child:
Container
(
padding:
EdgeInsets
.
all
(
14
),
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
18
)
),
],
child:
SizedBox
(
width:
24
,
height:
24
,
),
const
SizedBox
(
height:
12
),
const
Divider
(),
/// 🔹 Product Info Row
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
// Product details
Text
(
c
.
productName
??
"Unknown Product"
,
style:
const
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
w500
,
color:
AppColors
.
normalText
,
),
),
// Product ID
Row
(
SizedBox
(
width:
14
,),
Expanded
(
flex:
7
,
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
"#
${c.id ?? ''}
| "
,
style:
const
TextStyle
(
fontSize:
12
,
fontWeight:
FontWeight
.
w500
,
color:
AppColors
.
subtitleText
,
title
,
style:
TextStyle
(
color:
AppColors
.
normalText
,
fontWeight:
FontWeight
.
w400
,
fontSize:
14
,
overflow:
TextOverflow
.
ellipsis
,
),
),
if
((
c
.
modelName
??
''
).
isNotEmpty
)
Text
(
"Engine:
${c.modelName}
"
,
subTitle
,
maxLines:
4
,
style:
TextStyle
(
fontSize:
12
,
color:
AppColors
.
subtitleText
,
fontWeight:
FontWeight
.
w400
,
fontSize:
14
,
overflow:
TextOverflow
.
ellipsis
,
),
),
],
),
],
),
],
),
);
}).
toList
(),
],
);
}
// ===============================
// The remaining helper cards (no changes)
// ===============================
Widget
_buildFixIssuesCard
()
=>
// same as before
Container
(
padding:
const
EdgeInsets
.
all
(
20
),
decoration:
BoxDecoration
(
color:
Color
(
0xFFD7F0FF
),
borderRadius:
BorderRadius
.
circular
(
16
),
border:
Border
.
all
(
width:
1.5
,
color:
AppColors
.
buttonColor
),
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
const
[
Text
(
'Facing Issues?'
,
style:
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
w500
,
color:
AppColors
.
amountText
)),
Text
(
'Raise a ticket to resolve your issues.'
,
style:
TextStyle
(
fontSize:
12
,
fontWeight:
FontWeight
.
w400
,
color:
AppColors
.
subtitleText
),
),
],
),
SvgPicture
.
asset
(
"assets/svg/requirements.svg"
,
height:
22
,
width:
22
),
],
),
);
Widget
_buildGetInTouchCard
()
=>
// same as before
Container
(
padding:
const
EdgeInsets
.
all
(
20
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
16
),
border:
Border
.
all
(
color:
Colors
.
grey
.
shade200
),
boxShadow:
[
BoxShadow
(
color:
Colors
.
black
.
withOpacity
(
0.05
),
blurRadius:
8
,
offset:
const
Offset
(
0
,
2
),
),
],
),
child:
const
Row
(
children:
[
Icon
(
Icons
.
support_agent
,
color:
Color
(
0xFF1487C9
),
size:
24
),
SizedBox
(
width:
16
),
Expanded
(
child:
Text
(
'Get in touch With Us'
,
style:
TextStyle
(
fontSize:
16
,
fontWeight:
FontWeight
.
w600
,
color:
Colors
.
black87
),
),
),
],
),
);
}
Prev
1
…
6
7
8
9
10
11
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