Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Hoàng Văn Đạt
mypoint_flutter_app
Commits
f1723336
Commit
f1723336
authored
Sep 12, 2025
by
DatHV
Browse files
cập nhật ui, lịch sử điểm.. base networking
parent
38520c1e
Changes
47
Show whitespace changes
Inline
Side-by-side
lib/networking/restful_api_client_all_request.dart
View file @
f1723336
...
@@ -9,6 +9,7 @@ import 'package:mypoint_flutter_app/screen/game/models/game_bundle_response.dart
...
@@ -9,6 +9,7 @@ import 'package:mypoint_flutter_app/screen/game/models/game_bundle_response.dart
import
'package:mypoint_flutter_app/screen/voucher/models/product_model.dart'
;
import
'package:mypoint_flutter_app/screen/voucher/models/product_model.dart'
;
import
'../configs/callbacks.dart'
;
import
'../configs/callbacks.dart'
;
import
'../configs/device_info.dart'
;
import
'../configs/device_info.dart'
;
import
'../directional/directional_screen.dart'
;
import
'../model/auth/biometric_register_response_model.dart'
;
import
'../model/auth/biometric_register_response_model.dart'
;
import
'../model/auth/login_token_response_model.dart'
;
import
'../model/auth/login_token_response_model.dart'
;
import
'../model/auth/profile_response_model.dart'
;
import
'../model/auth/profile_response_model.dart'
;
...
@@ -960,4 +961,11 @@ extension RestfulAPIClientAllRequest on RestfulAPIClient {
...
@@ -960,4 +961,11 @@ extension RestfulAPIClientAllRequest on RestfulAPIClient {
return
ListHistoryResponseModel
.
fromJson
(
data
as
Json
);
return
ListHistoryResponseModel
.
fromJson
(
data
as
Json
);
});
});
}
}
Future
<
BaseResponseModel
<
DirectionalScreen
>>
getDirectionOfflineBrand
(
String
id
)
async
{
final
body
=
{
"bank_account"
:
id
};
return
requestNormal
(
APIPaths
.
getOfflineBrand
,
Method
.
GET
,
body
,
(
data
)
{
return
DirectionalScreen
.
fromJson
(
data
as
Json
);
});
}
}
}
\ No newline at end of file
lib/networking/restful_api_viewmodel.dart
View file @
f1723336
import
'dart:async'
;
import
'package:dio/dio.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_client.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_client.dart'
;
import
'../base/base_response_model.dart'
;
import
'../base/base_view_model.dart'
;
import
'../base/base_view_model.dart'
;
import
'../configs/constants.dart'
;
import
'app_navigator.dart'
;
import
'dio_http_service.dart'
;
import
'dio_http_service.dart'
;
import
'error_mapper.dart'
;
import
'interceptor/network_error_gate.dart'
;
typedef
ApiCall
<
T
>
=
Future
<
BaseResponseModel
<
T
>>
Function
();
typedef
OnSuccess
<
T
>
=
FutureOr
<
void
>
Function
(
T
data
,
BaseResponseModel
<
T
>
res
);
typedef
OnFailure
<
T
>
=
FutureOr
<
void
>
Function
(
String
message
,
BaseResponseModel
<
T
>?
res
,
Object
?
error
);
typedef
OnComplete
=
FutureOr
<
void
>
Function
();
typedef
ApiTask
=
Future
<
void
>
Function
();
class
RestfulApiViewModel
extends
BaseViewModel
{
class
RestfulApiViewModel
extends
BaseViewModel
{
final
RestfulAPIClient
_apiService
=
RestfulAPIClient
(
DioHttpService
().
dio
);
final
RestfulAPIClient
_apiService
=
RestfulAPIClient
(
DioHttpService
().
dio
);
RestfulAPIClient
get
client
=>
_apiService
;
RestfulAPIClient
get
client
=>
_apiService
;
Future
<
void
>
callApi
<
T
>({
required
ApiCall
<
T
>
request
,
required
OnSuccess
<
T
>
onSuccess
,
OnFailure
<
T
>?
onFailure
,
OnComplete
?
onComplete
,
bool
showAppNavigatorDialog
=
false
,
bool
withLoading
=
true
,
String
defaultError
=
ErrorCodes
.
commonError
,
})
async
{
if
(
withLoading
)
showLoading
();
BaseResponseModel
<
T
>?
res
;
try
{
res
=
await
request
();
if
(
res
.
isSuccess
)
{
final
T
data
=
res
.
data
as
T
;
await
onSuccess
(
data
,
res
);
}
else
{
final
msg
=
res
.
errorMessage
??
defaultError
;
final
hasInternet
=
await
NetworkConnectivity
().
hasInternet
();
if
(
hasInternet
)
{
if
(
showAppNavigatorDialog
)
{
AppNavigator
.
showAlertError
(
content:
msg
);
}
else
{
await
onFailure
?.
call
(
msg
,
res
,
null
);
}
}
}
}
catch
(
e
)
{
String
msg
=
defaultError
;
if
(
e
is
DioException
)
{
final
mapped
=
e
.
requestOptions
.
extra
[
'mapped_error'
];
msg
=
(
mapped
is
String
&&
mapped
.
isNotEmpty
)
?
mapped
:
ErrorMapper
.
map
(
e
);
}
else
{
msg
=
ErrorMapper
.
map
(
e
);
}
final
hasInternet
=
await
NetworkConnectivity
().
hasInternet
();
if
(
hasInternet
)
{
if
(
showAppNavigatorDialog
)
{
AppNavigator
.
showAlertError
(
content:
msg
);
}
else
{
await
onFailure
?.
call
(
msg
,
res
,
null
);
}
}
}
finally
{
if
(
withLoading
)
hideLoading
();
onComplete
?.
call
();
}
}
Future
<
void
>
runAllApis
({
required
List
<
ApiTask
>
tasks
,
OnComplete
?
onComplete
,
bool
withLoading
=
true
,
})
async
{
if
(
withLoading
)
showLoading
();
try
{
final
futures
=
tasks
.
map
((
t
)
=>
t
()).
toList
();
await
Future
.
wait
(
futures
);
}
finally
{
if
(
withLoading
)
hideLoading
();
onComplete
?.
call
();
}
}
}
}
\ No newline at end of file
lib/preference/point/point_manager.dart
View file @
f1723336
...
@@ -14,18 +14,21 @@ class UserPointManager extends RestfulApiViewModel {
...
@@ -14,18 +14,21 @@ class UserPointManager extends RestfulApiViewModel {
get
point
=>
_userPoint
.
value
;
get
point
=>
_userPoint
.
value
;
Future
fetchUserPoint
()
async
{
Future
<
int
?>
fetchUserPoint
()
async
{
if
(!
DataPreference
.
instance
.
logged
)
return
;
if
(!
DataPreference
.
instance
.
logged
)
return
null
;
try
{
try
{
final
response
=
await
client
.
getHomeHeaderData
();
final
response
=
await
client
.
getHomeHeaderData
();
if
(
response
.
isSuccess
&&
response
.
data
!=
null
)
{
if
(
response
.
isSuccess
&&
response
.
data
!=
null
)
{
_headerInfo
=
response
.
data
;
_headerInfo
=
response
.
data
;
_userPoint
.
value
=
_headerInfo
?.
totalPointActive
??
0
;
_userPoint
.
value
=
_headerInfo
?.
totalPointActive
??
0
;
return
_userPoint
.
value
;
}
else
{
}
else
{
_userPoint
.
value
=
0
;
_userPoint
.
value
=
0
;
return
null
;
}
}
}
catch
(
e
)
{
}
catch
(
e
)
{
_userPoint
.
value
=
0
;
_userPoint
.
value
=
0
;
return
null
;
}
}
}
}
}
}
lib/screen/achievement/achievement_viewmodel.dart
View file @
f1723336
...
@@ -23,16 +23,12 @@ class AchievementViewModel extends RestfulApiViewModel {
...
@@ -23,16 +23,12 @@ class AchievementViewModel extends RestfulApiViewModel {
"start"
:
0
,
"start"
:
0
,
"limit"
:
1000
,
"limit"
:
1000
,
};
};
showLoading
();
await
callApi
<
AchievementListResponse
>(
try
{
request:
()
=>
client
.
getAchievementList
(
body
),
final
response
=
await
client
.
getAchievementList
(
body
);
onSuccess:
(
data
,
_
)
{
if
(
response
.
data
!=
null
)
{
achievements
.
value
=
data
.
achievements
??
[];
achievements
.
value
=
response
.
data
?.
achievements
??
[];
},
}
showAppNavigatorDialog:
true
,
}
catch
(
error
)
{
);
print
(
"Error fetching achievements:
$error
"
);
}
finally
{
hideLoading
();
}
}
}
}
}
\ No newline at end of file
lib/screen/affiliate/affiliate_tab_viewmodel.dart
View file @
f1723336
import
'package:get/get_rx/src/rx_types/rx_types.dart'
;
import
'package:get/get_rx/src/rx_types/rx_types.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
import
'affiliate_popup_brands.dart'
;
import
'model/affiliate_brand_model.dart'
;
import
'model/affiliate_brand_model.dart'
;
import
'model/affiliate_category_model.dart'
;
import
'model/affiliate_category_model.dart'
;
import
'model/affiliate_category_type.dart'
;
import
'model/affiliate_category_type.dart'
;
...
...
lib/screen/affiliate/sub_widget/build_affiliate_product_topsale.dart
View file @
f1723336
...
@@ -53,10 +53,7 @@ class AffiliateProductTopSale extends StatelessWidget {
...
@@ -53,10 +53,7 @@ class AffiliateProductTopSale extends StatelessWidget {
final
title
=
product
.
productName
??
''
;
final
title
=
product
.
productName
??
''
;
return
GestureDetector
(
return
GestureDetector
(
onTap:
()
{
onTap:
()
=>
product
.
direcionalScreen
?.
begin
(),
print
(
"name
${product.productLink}
"
);
product
.
direcionalScreen
?.
begin
();
},
child:
Container
(
child:
Container
(
width:
160
,
width:
160
,
padding:
const
EdgeInsets
.
all
(
8
),
padding:
const
EdgeInsets
.
all
(
8
),
...
@@ -70,14 +67,15 @@ class AffiliateProductTopSale extends StatelessWidget {
...
@@ -70,14 +67,15 @@ class AffiliateProductTopSale extends StatelessWidget {
children:
[
children:
[
ClipRRect
(
ClipRRect
(
borderRadius:
BorderRadius
.
circular
(
8
),
borderRadius:
BorderRadius
.
circular
(
8
),
child:
AspectRatio
(
aspectRatio:
1
,
child:
Image
.
network
(
child:
Image
.
network
(
imageUrl
,
imageUrl
,
scale:
1
,
width:
double
.
infinity
,
fit:
BoxFit
.
cover
,
fit:
BoxFit
.
cover
,
errorBuilder:
(
_
,
__
,
___
)
=>
Image
.
asset
(
'assets/images/ic_logo.png'
),
errorBuilder:
(
_
,
__
,
___
)
=>
Image
.
asset
(
'assets/images/ic_logo.png'
),
),
),
),
),
),
const
SizedBox
(
height:
6
),
const
SizedBox
(
height:
6
),
Text
(
title
,
maxLines:
2
,
overflow:
TextOverflow
.
ellipsis
,
style:
const
TextStyle
(
fontSize:
13
)),
Text
(
title
,
maxLines:
2
,
overflow:
TextOverflow
.
ellipsis
,
style:
const
TextStyle
(
fontSize:
13
)),
const
SizedBox
(
height:
4
),
const
SizedBox
(
height:
4
),
...
...
lib/screen/daily_checkin/daily_checkin_screen.dart
View file @
f1723336
...
@@ -71,7 +71,7 @@ class _DailyCheckInScreenState extends BaseState<DailyCheckInScreen> with BasicS
...
@@ -71,7 +71,7 @@ class _DailyCheckInScreenState extends BaseState<DailyCheckInScreen> with BasicS
_buildCheckInList
(),
_buildCheckInList
(),
const
SizedBox
(
height:
16
),
const
SizedBox
(
height:
16
),
Padding
(
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
24
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
),
child:
SizedBox
(
child:
SizedBox
(
width:
double
.
infinity
,
width:
double
.
infinity
,
height:
48
,
height:
48
,
...
...
lib/screen/game/game_tab_screen.dart
View file @
f1723336
...
@@ -64,7 +64,7 @@ class _GameTabScreenState extends BaseState<GameTabScreen> with BasicState, Popu
...
@@ -64,7 +64,7 @@ class _GameTabScreenState extends BaseState<GameTabScreen> with BasicState, Popu
link:
_layerLink
,
link:
_layerLink
,
child:
IconButton
(
child:
IconButton
(
key:
_infoKey
,
key:
_infoKey
,
icon:
const
Icon
(
Icons
.
info
_outline
,
color:
Colors
.
white
),
icon:
const
Icon
(
Icons
.
info
,
color:
Colors
.
white
),
onPressed:
_togglePopup
,
onPressed:
_togglePopup
,
),
),
),
),
...
...
lib/screen/home/home_screen.dart
View file @
f1723336
...
@@ -208,15 +208,13 @@ class _HomeScreenState extends State<HomeScreen> with PopupOnInit {
...
@@ -208,15 +208,13 @@ class _HomeScreenState extends State<HomeScreen> with PopupOnInit {
),
),
Obx
(()
{
Obx
(()
{
if
(!
_showHover
.
value
)
return
SizedBox
.
shrink
();
if
(!
_showHover
.
value
)
return
SizedBox
.
shrink
();
return
Positioned
.
fill
(
return
HoverView
(
child:
HoverView
(
imagePath:
_viewModel
.
hoverData
.
value
?.
icon
??
''
,
imagePath:
_viewModel
.
hoverData
.
value
?.
icon
??
''
,
onTap:
_handleHoverViewTap
,
onTap:
_handleHoverViewTap
,
onClose:
_handleCloseHoverView
,
onClose:
_handleCloseHoverView
,
backgroundColor:
Colors
.
transparent
,
backgroundColor:
Colors
.
transparent
,
size:
80
,
size:
80
,
countDownTime:
_viewModel
.
hoverData
.
value
?.
countDownTime
??
0.0
,
countDownTime:
_viewModel
.
hoverData
.
value
?.
countDownTime
??
0.0
,
),
);
);
}),
}),
],
],
...
...
lib/screen/login/login_screen.dart
View file @
f1723336
...
@@ -296,6 +296,7 @@ class _LoginScreenState extends BaseState<LoginScreen> with BasicState {
...
@@ -296,6 +296,7 @@ class _LoginScreenState extends BaseState<LoginScreen> with BasicState {
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
8
)),
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
8
)),
),
),
onPressed:
()
{
onPressed:
()
{
hideKeyboard
();
enabled
?
vm
.
onLoginPressed
(
phoneNumber
)
:
null
;
enabled
?
vm
.
onLoginPressed
(
phoneNumber
)
:
null
;
},
},
child:
const
Text
(
child:
const
Text
(
...
...
lib/screen/membership/membership_screen.dart
View file @
f1723336
...
@@ -189,7 +189,7 @@ class _MembershipScreenState extends BaseState<MembershipScreen> with BasicState
...
@@ -189,7 +189,7 @@ class _MembershipScreenState extends BaseState<MembershipScreen> with BasicState
Get
.
toNamed
(
campaignDetailScreen
,
arguments:
{
"id"
:
pageId
});
Get
.
toNamed
(
campaignDetailScreen
,
arguments:
{
"id"
:
pageId
});
}
}
},
},
child:
SizedBox
(
width:
40
,
height:
40
,
child:
Icon
(
Icons
.
info
_outline
,
color:
Colors
.
white
,
size:
24
)),
child:
SizedBox
(
width:
40
,
height:
40
,
child:
Icon
(
Icons
.
info
,
color:
Colors
.
white
,
size:
24
)),
),
),
),
),
);
);
...
...
lib/screen/notification/models/notification_item_model.dart
View file @
f1723336
...
@@ -15,7 +15,7 @@ class NotificationItemModel {
...
@@ -15,7 +15,7 @@ class NotificationItemModel {
@JsonKey
(
name:
'click_action_param'
)
@JsonKey
(
name:
'click_action_param'
)
final
String
?
clickActionParam
;
final
String
?
clickActionParam
;
@JsonKey
(
name:
'seen_at'
)
@JsonKey
(
name:
'seen_at'
)
final
String
?
seenAt
;
String
?
seenAt
;
final
String
?
status
;
final
String
?
status
;
@JsonKey
(
name:
'create_time'
)
@JsonKey
(
name:
'create_time'
)
final
String
?
createTime
;
final
String
?
createTime
;
...
...
lib/screen/notification/notification_screen.dart
View file @
f1723336
...
@@ -167,7 +167,8 @@ class _NotificationScreenState extends BaseState<NotificationScreen> with BasicS
...
@@ -167,7 +167,8 @@ class _NotificationScreenState extends BaseState<NotificationScreen> with BasicS
title:
"Xoá tất cả"
,
title:
"Xoá tất cả"
,
description:
"Bạn có muốn xoá hết tất cả thông báo không?
\n
Lưu ý: bạn sẽ không thể xem lại thông báo đã xoá"
,
description:
"Bạn có muốn xoá hết tất cả thông báo không?
\n
Lưu ý: bạn sẽ không thể xem lại thông báo đã xoá"
,
localHeaderImage:
"assets/images/ic_pipi_03.png"
,
localHeaderImage:
"assets/images/ic_pipi_03.png"
,
buttons:
[
AlertButton
(
buttons:
[
AlertButton
(
text:
"Xoá"
,
text:
"Xoá"
,
onPressed:
()
{
onPressed:
()
{
Get
.
back
();
Get
.
back
();
...
@@ -176,12 +177,8 @@ class _NotificationScreenState extends BaseState<NotificationScreen> with BasicS
...
@@ -176,12 +177,8 @@ class _NotificationScreenState extends BaseState<NotificationScreen> with BasicS
bgColor:
BaseColor
.
primary500
,
bgColor:
BaseColor
.
primary500
,
textColor:
Colors
.
white
,
textColor:
Colors
.
white
,
),
),
AlertButton
(
AlertButton
(
text:
"Huỷ"
,
onPressed:
()
=>
Get
.
back
(),
bgColor:
Colors
.
white
,
textColor:
BaseColor
.
second500
),
text:
"Huỷ"
,
],
onPressed:
()
=>
Get
.
back
(),
bgColor:
Colors
.
white
,
textColor:
BaseColor
.
second500
,
),],
);
);
showAlert
(
data:
dataAlert
);
showAlert
(
data:
dataAlert
);
}
}
...
@@ -271,9 +268,11 @@ class _NotificationScreenState extends BaseState<NotificationScreen> with BasicS
...
@@ -271,9 +268,11 @@ class _NotificationScreenState extends BaseState<NotificationScreen> with BasicS
},
},
child:
GestureDetector
(
child:
GestureDetector
(
onTap:
()
{
onTap:
()
{
print
(
"Click item
${item.title}
"
);
_viewModel
.
handleClickNotification
(
item
);
_viewModel
.
handleClickNotification
(
item
);
// item.directionalScreen?.begin();
// item.directionalScreen?.begin();
setState
(()
{
item
.
seenAt
=
DateTime
.
now
().
toString
();
});
},
},
child:
Container
(
child:
Container
(
margin:
const
EdgeInsets
.
only
(
bottom:
12
),
margin:
const
EdgeInsets
.
only
(
bottom:
12
),
...
...
lib/screen/pageDetail/campaign_detail_screen.dart
View file @
f1723336
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_widget_from_html/flutter_widget_from_html.dart'
;
import
'package:flutter_widget_from_html/flutter_widget_from_html.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/widgets/custom_empty_widget.dart'
;
import
'../../base/base_screen.dart'
;
import
'../../base/base_screen.dart'
;
import
'../../base/basic_state.dart'
;
import
'../../base/basic_state.dart'
;
import
'../../extensions/string_extension.dart'
;
import
'../../extensions/string_extension.dart'
;
...
@@ -52,7 +53,7 @@ class _CampaignDetailScreenState extends BaseState<CampaignDetailScreen> with Ba
...
@@ -52,7 +53,7 @@ class _CampaignDetailScreenState extends BaseState<CampaignDetailScreen> with Ba
body:
Obx
(()
{
body:
Obx
(()
{
CampaignDetailModel
?
pageDetail
=
_viewModel
.
campaignDetail
.
value
.
data
?.
pageDetail
;
CampaignDetailModel
?
pageDetail
=
_viewModel
.
campaignDetail
.
value
.
data
?.
pageDetail
;
if
(
pageDetail
==
null
)
{
if
(
pageDetail
==
null
)
{
return
const
Center
(
child:
CircularProgressIndicator
());
return
const
Center
(
child:
EmptyWidget
());
}
}
final
thumbnail
=
pageDetail
.
thumbnail
??
""
;
final
thumbnail
=
pageDetail
.
thumbnail
??
""
;
final
publishDate
=
pageDetail
.
publishDate
??
""
;
final
publishDate
=
pageDetail
.
publishDate
??
""
;
...
...
lib/screen/personal/personal_screen.dart
View file @
f1723336
...
@@ -183,7 +183,7 @@ class _PersonalScreenState extends BaseState<PersonalScreen> with BasicState, Po
...
@@ -183,7 +183,7 @@ class _PersonalScreenState extends BaseState<PersonalScreen> with BasicState, Po
const
Expanded
(
const
Expanded
(
child:
Text
(
child:
Text
(
'Mời bạn nhận quà liền tay 🎁'
,
'Mời bạn nhận quà liền tay 🎁'
,
style:
TextStyle
(
fontSize:
1
8
,
fontWeight:
FontWeight
.
w500
,
color:
Colors
.
black87
),
style:
TextStyle
(
fontSize:
1
6
,
fontWeight:
FontWeight
.
w500
,
color:
Colors
.
black87
),
),
),
),
),
const
Icon
(
Icons
.
chevron_right
,
color:
Colors
.
black87
,
size:
24
),
const
Icon
(
Icons
.
chevron_right
,
color:
Colors
.
black87
,
size:
24
),
...
@@ -202,6 +202,7 @@ class _PersonalScreenState extends BaseState<PersonalScreen> with BasicState, Po
...
@@ -202,6 +202,7 @@ class _PersonalScreenState extends BaseState<PersonalScreen> with BasicState, Po
'title'
:
'Săn điểm'
,
'title'
:
'Săn điểm'
,
'type'
:
'APP_SCREEN_POINT_HUNTING'
,
'type'
:
'APP_SCREEN_POINT_HUNTING'
,
},
},
{
'icon'
:
Icons
.
qr_code_2
,
'title'
:
'QR Code'
,
'type'
:
'APP_SCREEN_QR_CODE'
},
{
'icon'
:
Icons
.
check_box_outlined
,
'title'
:
'Check-in nhận quà'
,
'type'
:
'DAILY_CHECKIN'
},
{
'icon'
:
Icons
.
check_box_outlined
,
'title'
:
'Check-in nhận quà'
,
'type'
:
'DAILY_CHECKIN'
},
{
'icon'
:
Icons
.
border_right
,
'title'
:
'Hoá đơn điện'
,
'type'
:
'APP_SCREEN_LIST_PAYMENT_OF_ELECTRIC'
},
{
'icon'
:
Icons
.
border_right
,
'title'
:
'Hoá đơn điện'
,
'type'
:
'APP_SCREEN_LIST_PAYMENT_OF_ELECTRIC'
},
// {'icon': Icons.emoji_events_outlined, 'title': 'Bảng xếp hạng', 'type': 'APP_SCREEN_LIST_PAYMENT_OF_ELECTRIC'},
// {'icon': Icons.emoji_events_outlined, 'title': 'Bảng xếp hạng', 'type': 'APP_SCREEN_LIST_PAYMENT_OF_ELECTRIC'},
...
...
lib/screen/qr_code/qr_code_screen.dart
0 → 100644
View file @
f1723336
import
'package:barcode_widget/barcode_widget.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/extensions/num_extension.dart'
;
import
'package:mypoint_flutter_app/extensions/string_extension.dart'
;
import
'package:mypoint_flutter_app/preference/point/point_manager.dart'
;
import
'package:mypoint_flutter_app/screen/qr_code/qr_code_viewmodel.dart'
;
import
'package:mypoint_flutter_app/screen/qr_code/scan_code_screen.dart'
;
import
'package:mypoint_flutter_app/widgets/custom_navigation_bar.dart'
;
import
'package:mypoint_flutter_app/widgets/dashed_line.dart'
;
import
'package:qr_flutter/qr_flutter.dart'
;
import
'../../base/base_screen.dart'
;
import
'../../base/basic_state.dart'
;
import
'../../preference/data_preference.dart'
;
class
QRCodeScreen
extends
BaseScreen
{
const
QRCodeScreen
({
super
.
key
});
@override
State
<
QRCodeScreen
>
createState
()
=>
_QRCodeScreenState
();
}
class
_QRCodeScreenState
extends
BaseState
<
QRCodeScreen
>
with
BasicState
{
final
_viewModel
=
Get
.
put
(
QRCodeViewModel
());
final
_scanCtl
=
ScanTabController
();
int
_tab
=
0
;
final
RxInt
_points
=
0
.
obs
;
final
String
_code
=
DataPreference
.
instance
.
profile
?.
workerSite
?.
id
??
''
;
final
RxBool
_isShowPoint
=
true
.
obs
;
@override
void
initState
()
{
super
.
initState
();
_freshPoint
();
_viewModel
.
onShowAlertError
=
(
message
)
{
if
(
message
.
isEmpty
)
{
_scanCtl
.
resume
();
return
;
}
_showAlertAndResumeScanCode
(
message
);
};
}
_freshPoint
()
async
{
_points
.
value
=
(
await
UserPointManager
().
fetchUserPoint
())
??
0
;
}
@override
Widget
createBody
()
{
return
Scaffold
(
appBar:
CustomNavigationBar
(
title:
_tab
==
0
?
'Mã tích điểm'
:
'Quét mã'
),
backgroundColor:
Color
(
0xFFF3F4F6
),
body:
SafeArea
(
child:
Stack
(
children:
[
_tab
==
0
?
_buildYourCode
()
:
_buildScanQRCode
(),
Positioned
(
top:
12
,
left:
16
,
right:
16
,
child:
SegmentedTabs
(
tabs:
const
[
'Mã của bạn'
,
'Quét mã'
],
index:
_tab
,
onChanged:
(
i
)
=>
setState
(()
=>
_tab
=
i
),
),
),
],
),
),
);
}
Widget
_buildYourCode
()
{
final
width
=
MediaQuery
.
of
(
context
).
size
.
width
;
return
SingleChildScrollView
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
8
),
child:
Column
(
children:
[
const
SizedBox
(
height:
64
),
Image
.
asset
(
'assets/images/ic_pipi_04.png'
,
width:
120
,
height:
120
),
Container
(
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
20
),
boxShadow:
const
[
BoxShadow
(
color:
Color
(
0x14000000
),
blurRadius:
16
,
offset:
Offset
(
0
,
6
))],
),
padding:
const
EdgeInsets
.
all
(
16
),
child:
Column
(
children:
[
const
Text
(
'Vui lòng đưa nhân viên thu ngân quét mã để tích điểm'
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
fontSize:
16
,
fontWeight:
FontWeight
.
w600
,
color:
Color
(
0xFF0C2B4C
)),
),
const
SizedBox
(
height:
12
),
BarcodeWidget
(
barcode:
Barcode
.
code128
(),
data:
_code
,
width:
double
.
infinity
,
height:
80
,
drawText:
false
,
color:
Colors
.
black
,
backgroundColor:
Colors
.
white
,
style:
const
TextStyle
(
fontSize:
14
),
),
const
SizedBox
(
height:
16
),
QrImageView
(
data:
_code
,
version:
QrVersions
.
auto
,
size:
width
/
1.7
,
embeddedImage:
const
AssetImage
(
'assets/images/ic_logo.png'
),
embeddedImageStyle:
const
QrEmbeddedImageStyle
(
size:
Size
(
64
,
64
)),
),
const
SizedBox
(
height:
12
),
DashedLine
(),
const
SizedBox
(
height:
12
),
Row
(
children:
[
const
Text
(
'MyPoint'
,
style:
TextStyle
(
fontSize:
16
,
fontWeight:
FontWeight
.
w600
,
color:
Color
(
0xFF0C2B4C
)),
),
const
Spacer
(),
Obx
(
()
=>
Row
(
children:
[
Image
.
asset
(
'assets/images/ic_point.png'
,
width:
24
,
height:
24
),
const
SizedBox
(
width:
6
),
Text
(
_isShowPoint
.
value
?
'******'
:
_points
.
value
.
money
(
CurrencyUnit
.
point
),
style:
const
TextStyle
(
fontSize:
16
,
fontWeight:
FontWeight
.
w700
),
),
const
SizedBox
(
width:
6
),
GestureDetector
(
onTap:
()
{
setState
(()
{
_isShowPoint
.
toggle
();
});
},
child:
Icon
(
_isShowPoint
.
value
?
Icons
.
visibility_outlined
:
Icons
.
visibility_off_outlined
,
color:
Colors
.
black38
,
size:
24
,
),
),
],
),
),
],
),
],
),
),
],
),
);
}
_showAlertAndResumeScanCode
(
String
message
)
{
showAlertError
(
content:
message
,
showCloseButton:
false
,
onConfirmed:
()
{
_scanCtl
.
resume
();
},
);
}
Widget
_buildScanQRCode
()
{
return
ScanTabView
(
controller:
_scanCtl
,
onCodeDetected:
(
code
,
format
)
async
{
final
id
=
_viewModel
.
getResultCodeID
(
code
)
??
''
;
// if (id.isEmpty) {
// final url = code.toUri();
// if (url == null) {
// _showAlertAndResumeScanCode('Mã QR không hợp lệ');
// } else {
// print('_buildScanQRCode $url');
// _scanCtl.resume();
// }
// return;
// }
_viewModel
.
getDirectionFromId
(
code
);
},
);
}
}
/// Segmented control (pill) giống iOS
class
SegmentedTabs
extends
StatelessWidget
{
const
SegmentedTabs
({
super
.
key
,
required
this
.
tabs
,
required
this
.
index
,
required
this
.
onChanged
});
final
List
<
String
>
tabs
;
final
int
index
;
final
ValueChanged
<
int
>
onChanged
;
@override
Widget
build
(
BuildContext
context
)
{
return
Center
(
child:
Container
(
decoration:
BoxDecoration
(
color:
Color
(
0x22000000
),
borderRadius:
BorderRadius
.
circular
(
24
)),
child:
Row
(
mainAxisSize:
MainAxisSize
.
min
,
children:
List
.
generate
(
tabs
.
length
,
(
i
)
{
final
selected
=
i
==
index
;
return
SizedBox
(
width:
160
,
child:
InkWell
(
borderRadius:
BorderRadius
.
circular
(
20
),
onTap:
()
=>
onChanged
(
i
),
child:
AnimatedContainer
(
margin:
EdgeInsets
.
symmetric
(
horizontal:
8
,
vertical:
4
),
duration:
const
Duration
(
milliseconds:
180
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
10
),
decoration:
BoxDecoration
(
color:
selected
?
Colors
.
white
:
Colors
.
transparent
,
borderRadius:
BorderRadius
.
circular
(
20
),
boxShadow:
selected
?
const
[
BoxShadow
(
color:
Color
(
0x22000000
),
blurRadius:
8
,
offset:
Offset
(
0
,
3
))]
:
const
[],
),
child:
Text
(
tabs
[
i
],
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
fontSize:
15
,
fontWeight:
FontWeight
.
w700
,
color:
selected
?
const
Color
(
0xFF0C2B4C
)
:
Colors
.
white
,
),
),
),
),
);
}),
),
),
);
}
}
lib/screen/qr_code/qr_code_viewmodel.dart
0 → 100644
View file @
f1723336
import
'package:mypoint_flutter_app/configs/constants.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
class
QRPackageCodeValue
{
final
String
type
;
final
String
length
;
final
String
value
;
const
QRPackageCodeValue
({
required
this
.
type
,
required
this
.
length
,
required
this
.
value
});
}
class
QRCodeViewModel
extends
RestfulApiViewModel
{
void
Function
(
String
message
)?
onShowAlertError
;
getDirectionFromId
(
String
id
)
async
{
showLoading
();
final
response
=
await
client
.
getDirectionOfflineBrand
(
id
);
final
direction
=
response
.
data
;
if
(
response
.
isSuccess
&&
direction
!=
null
)
{
hideLoading
();
final
directionSuccess
=
await
direction
.
begin
();
if
(
directionSuccess
!=
true
)
{
onShowAlertError
?.
call
(
ErrorCodes
.
serverErrorMessage
);
}
else
{
onShowAlertError
?.
call
(
''
);
}
}
else
{
hideLoading
();
onShowAlertError
?.
call
(
response
.
errorMessage
??
ErrorCodes
.
serverErrorMessage
);
}
}
int
_crc16CcittEmv
(
List
<
int
>
bytes
)
{
const
poly
=
0x1021
;
var
crc
=
0xFFFF
;
for
(
final
b
in
bytes
)
{
crc
^=
(
b
&
0xFF
)
<<
8
;
for
(
var
i
=
0
;
i
<
8
;
i
++)
{
final
carry
=
(
crc
&
0x8000
)
!=
0
;
crc
=
(
crc
<<
1
)
&
0xFFFF
;
if
(
carry
)
crc
^=
poly
;
}
}
return
crc
&
0xFFFF
;
}
bool
emvCrcValid
(
String
full
,
String
crcHexFromPayload
)
{
final
idx
=
full
.
lastIndexOf
(
'63'
);
if
(
idx
<
0
||
idx
+
4
>
full
.
length
)
return
false
;
// không có "63" + "LEN"
final
lenStr
=
full
.
substring
(
idx
+
2
,
idx
+
4
);
final
len
=
int
.
tryParse
(
lenStr
)
??
0
;
if
(
len
!=
4
)
return
false
;
// dữ liệu tham gia CRC: từ đầu → sau "63" + "04" (không gồm value CRC)
final
data
=
full
.
substring
(
0
,
idx
+
4
);
final
crc
=
_crc16CcittEmv
(
data
.
codeUnits
)
.
toRadixString
(
16
)
.
toUpperCase
()
.
padLeft
(
4
,
'0'
);
return
crc
==
crcHexFromPayload
.
toUpperCase
();
}
QRPackageCodeValue
?
_findByType
(
List
<
QRPackageCodeValue
>
list
,
String
type
)
{
for
(
final
e
in
list
)
{
if
(
e
.
type
==
type
)
return
e
;
}
return
null
;
}
String
?
getResultCodeID
(
String
code
)
{
final
codes
=
getPackageCode
(
code
);
final
crcField
=
_findByType
(
codes
,
'63'
);
final
merchantAccountInfo
=
_findByType
(
codes
,
'38'
);
if
(
crcField
==
null
||
merchantAccountInfo
==
null
)
return
null
;
if
(!
emvCrcValid
(
code
,
crcField
.
value
))
return
null
;
final
merchantInfoValue
=
getPackageCode
(
merchantAccountInfo
.
value
);
final
merchantIdInfo
=
_findByType
(
merchantInfoValue
,
'01'
);
if
(
merchantIdInfo
==
null
)
return
null
;
final
merchantData
=
getPackageCode
(
merchantIdInfo
.
value
);
final
bankIdField
=
_findByType
(
merchantData
,
'01'
);
return
bankIdField
?.
value
;
}
List
<
QRPackageCodeValue
>
getPackageCode
(
String
input
)
{
final
codes
=
<
QRPackageCodeValue
>[];
var
s
=
input
;
while
(
s
.
isNotEmpty
)
{
if
(
s
.
length
<
4
)
break
;
final
id
=
s
.
substring
(
0
,
2
);
s
=
s
.
substring
(
2
);
final
lenStr
=
s
.
substring
(
0
,
2
);
s
=
s
.
substring
(
2
);
final
len
=
int
.
tryParse
(
lenStr
)
??
0
;
if
(
len
<
0
||
s
.
length
<
len
)
break
;
final
value
=
s
.
substring
(
0
,
len
);
s
=
s
.
substring
(
len
);
codes
.
add
(
QRPackageCodeValue
(
type:
id
,
length:
lenStr
,
value:
value
));
}
return
codes
;
}
}
\ No newline at end of file
lib/screen/qr_code/scan_code_screen.dart
0 → 100644
View file @
f1723336
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:mobile_scanner/mobile_scanner.dart'
;
class
ScanTabController
{
Future
<
void
>
Function
()?
_resume
;
Future
<
void
>
Function
()?
_pause
;
Future
<
void
>
Function
()?
_toggleTorch
;
Future
<
void
>
resume
()
async
=>
await
(
_resume
?.
call
()
??
Future
.
value
());
Future
<
void
>
pause
()
async
=>
await
(
_pause
?.
call
()
??
Future
.
value
());
Future
<
void
>
toggleTorch
()
async
=>
await
(
_toggleTorch
?.
call
()
??
Future
.
value
());
}
class
ScanTabView
extends
StatefulWidget
{
const
ScanTabView
({
super
.
key
,
this
.
onCodeDetected
,
this
.
controller
,
});
final
void
Function
(
String
code
,
BarcodeFormat
format
)?
onCodeDetected
;
final
ScanTabController
?
controller
;
@override
State
<
ScanTabView
>
createState
()
=>
_ScanTabViewState
();
}
class
_ScanTabViewState
extends
State
<
ScanTabView
>
{
final
MobileScannerController
_cam
=
MobileScannerController
(
detectionSpeed:
DetectionSpeed
.
noDuplicates
,
formats:
[
BarcodeFormat
.
ean8
,
BarcodeFormat
.
ean13
,
BarcodeFormat
.
pdf417
,
BarcodeFormat
.
code128
,
BarcodeFormat
.
code39
,
BarcodeFormat
.
qrCode
,
],
);
bool
_locked
=
false
;
@override
void
initState
()
{
super
.
initState
();
widget
.
controller
?.
_resume
=
_resume
;
widget
.
controller
?.
_pause
=
_pause
;
widget
.
controller
?.
_toggleTorch
=
()
=>
_cam
.
toggleTorch
();
}
@override
void
dispose
()
{
_cam
.
dispose
();
super
.
dispose
();
}
Future
<
void
>
_resume
()
async
{
_locked
=
false
;
await
_cam
.
start
();
}
Future
<
void
>
_pause
()
async
=>
_cam
.
stop
();
@override
Widget
build
(
BuildContext
context
)
{
return
LayoutBuilder
(
builder:
(
context
,
c
)
{
final
size
=
c
.
biggest
;
final
side
=
(
size
.
width
-
64
).
clamp
(
220.0
,
size
.
height
*
0.6
);
final
left
=
(
size
.
width
-
side
)
/
2
;
final
top
=
(
size
.
height
-
side
)
/
2
;
final
scanRect
=
Rect
.
fromLTWH
(
left
,
top
,
side
,
side
);
return
Stack
(
children:
[
Positioned
.
fill
(
child:
MobileScanner
(
controller:
_cam
,
fit:
BoxFit
.
cover
,
scanWindow:
scanRect
,
onDetect:
(
capture
)
async
{
if
(
_locked
)
return
;
final
b
=
capture
.
barcodes
.
firstOrNull
;
final
code
=
b
?.
rawValue
??
''
;
final
format
=
b
?.
format
??
BarcodeFormat
.
unknown
;
if
(
code
.
isEmpty
)
return
;
_locked
=
true
;
await
_cam
.
stop
();
widget
.
onCodeDetected
?.
call
(
code
,
format
);
},
),
),
Positioned
.
fill
(
child:
IgnorePointer
(
child:
CustomPaint
(
painter:
_ScannerOverlayPainter
(
scanWindow:
scanRect
),
),
),
),
// Caption hướng dẫn
Positioned
(
left:
16
,
right:
16
,
bottom:
90
,
child:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
10
),
decoration:
BoxDecoration
(
color:
Colors
.
black
.
withOpacity
(
0.35
),
borderRadius:
BorderRadius
.
circular
(
24
),
),
child:
const
Text
(
'Căn chỉnh mã QR vào vị trí trong khung hình.'
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
13
,
fontWeight:
FontWeight
.
w600
),
),
),
),
// Nút bật đèn
Positioned
(
bottom:
32
,
left:
0
,
right:
0
,
child:
Center
(
child:
ValueListenableBuilder
<
TorchState
>(
valueListenable:
_cam
.
torchState
,
builder:
(
_
,
state
,
__
)
{
final
on
=
state
==
TorchState
.
on
;
return
InkWell
(
onTap:
()
=>
_cam
.
toggleTorch
(),
borderRadius:
BorderRadius
.
circular
(
32
),
child:
Container
(
width:
48
,
height:
48
,
decoration:
BoxDecoration
(
color:
Colors
.
black
.
withOpacity
(
0.25
),
shape:
BoxShape
.
circle
,
border:
Border
.
all
(
color:
Colors
.
white70
),
),
alignment:
Alignment
.
center
,
child:
Icon
(
on
?
Icons
.
flashlight_off_outlined
:
Icons
.
flashlight_on_outlined
,
color:
Colors
.
white
,
size:
24
,
),
),
);
},
),
),
),
],
);
});
}
}
class
_ScannerOverlayPainter
extends
CustomPainter
{
_ScannerOverlayPainter
({
required
this
.
scanWindow
});
final
Rect
scanWindow
;
@override
void
paint
(
Canvas
canvas
,
Size
size
)
{
// nền mờ
final
bg
=
Path
()..
addRect
(
Offset
.
zero
&
size
);
final
hole
=
Path
()..
addRRect
(
RRect
.
fromRectAndRadius
(
scanWindow
,
const
Radius
.
circular
(
2
)));
final
mask
=
Path
.
combine
(
PathOperation
.
difference
,
bg
,
hole
);
final
paintMask
=
Paint
()..
color
=
Colors
.
black
.
withOpacity
(
0.65
);
canvas
.
drawPath
(
mask
,
paintMask
);
// viền trắng
final
border
=
Paint
()
..
color
=
Colors
.
white
..
style
=
PaintingStyle
.
stroke
..
strokeWidth
=
2
;
canvas
.
drawRRect
(
RRect
.
fromRectAndRadius
(
scanWindow
,
const
Radius
.
circular
(
2
)),
border
);
// 4 góc xanh
const
cornerLen
=
18.0
;
final
corner
=
Paint
()
..
color
=
const
Color
(
0xFF247CFF
)
..
style
=
PaintingStyle
.
stroke
..
strokeWidth
=
3
;
// TL
canvas
.
drawLine
(
scanWindow
.
topLeft
+
const
Offset
(
0
,
0
),
scanWindow
.
topLeft
+
const
Offset
(
cornerLen
,
0
),
corner
);
canvas
.
drawLine
(
scanWindow
.
topLeft
+
const
Offset
(
0
,
0
),
scanWindow
.
topLeft
+
const
Offset
(
0
,
cornerLen
),
corner
);
// TR
canvas
.
drawLine
(
scanWindow
.
topRight
+
const
Offset
(-
cornerLen
,
0
),
scanWindow
.
topRight
,
corner
);
canvas
.
drawLine
(
scanWindow
.
topRight
+
const
Offset
(
0
,
0
),
scanWindow
.
topRight
+
const
Offset
(
0
,
cornerLen
),
corner
);
// BL
canvas
.
drawLine
(
scanWindow
.
bottomLeft
+
const
Offset
(
0
,
-
cornerLen
),
scanWindow
.
bottomLeft
,
corner
);
canvas
.
drawLine
(
scanWindow
.
bottomLeft
+
const
Offset
(
0
,
0
),
scanWindow
.
bottomLeft
+
const
Offset
(
cornerLen
,
0
),
corner
);
// BR
canvas
.
drawLine
(
scanWindow
.
bottomRight
+
const
Offset
(-
cornerLen
,
0
),
scanWindow
.
bottomRight
,
corner
);
canvas
.
drawLine
(
scanWindow
.
bottomRight
+
const
Offset
(
0
,
-
cornerLen
),
scanWindow
.
bottomRight
,
corner
);
}
@override
bool
shouldRepaint
(
covariant
_ScannerOverlayPainter
oldDelegate
)
=>
oldDelegate
.
scanWindow
!=
scanWindow
;
}
lib/screen/topup/topup_screen.dart
View file @
f1723336
...
@@ -4,6 +4,8 @@ import 'package:intl/intl.dart';
...
@@ -4,6 +4,8 @@ import 'package:intl/intl.dart';
import
'package:mypoint_flutter_app/screen/topup/topup_viewmodel.dart'
;
import
'package:mypoint_flutter_app/screen/topup/topup_viewmodel.dart'
;
import
'package:mypoint_flutter_app/widgets/custom_navigation_bar.dart'
;
import
'package:mypoint_flutter_app/widgets/custom_navigation_bar.dart'
;
import
'package:mypoint_flutter_app/widgets/image_loader.dart'
;
import
'package:mypoint_flutter_app/widgets/image_loader.dart'
;
import
'../../base/base_screen.dart'
;
import
'../../base/basic_state.dart'
;
import
'../../extensions/debouncer.dart'
;
import
'../../extensions/debouncer.dart'
;
import
'../../preference/data_preference.dart'
;
import
'../../preference/data_preference.dart'
;
import
'../../resources/base_color.dart'
;
import
'../../resources/base_color.dart'
;
...
@@ -11,14 +13,15 @@ import '../../shared/router_gage.dart';
...
@@ -11,14 +13,15 @@ import '../../shared/router_gage.dart';
import
'../contacts/contacts_picker.dart'
;
import
'../contacts/contacts_picker.dart'
;
import
'brand_select_sheet_widget.dart'
;
import
'brand_select_sheet_widget.dart'
;
class
PhoneTopUpScreen
extends
StatefulWidget
{
class
PhoneTopUpScreen
extends
BaseScreen
{
const
PhoneTopUpScreen
({
super
.
key
});
const
PhoneTopUpScreen
({
super
.
key
});
@override
@override
State
<
PhoneTopUpScreen
>
createState
()
=>
_PhoneTopUpScreenState
();
State
<
PhoneTopUpScreen
>
createState
()
=>
_PhoneTopUpScreenState
();
}
}
class
_PhoneTopUpScreenState
extends
State
<
PhoneTopUpScreen
>
{
class
_PhoneTopUpScreenState
extends
Base
State
<
PhoneTopUpScreen
>
with
BasicState
{
final
TopUpViewModel
_viewModel
=
Get
.
put
(
TopUpViewModel
());
final
TopUpViewModel
_viewModel
=
Get
.
put
(
TopUpViewModel
());
late
final
TextEditingController
_phoneController
;
late
final
TextEditingController
_phoneController
;
final
_deb
=
Debouncer
(
ms:
500
);
final
_deb
=
Debouncer
(
ms:
500
);
...
@@ -39,7 +42,7 @@ class _PhoneTopUpScreenState extends State<PhoneTopUpScreen> {
...
@@ -39,7 +42,7 @@ class _PhoneTopUpScreenState extends State<PhoneTopUpScreen> {
}
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
createBody
(
)
{
return
Scaffold
(
return
Scaffold
(
appBar:
CustomNavigationBar
(
title:
"Nạp tiền điện thoại"
),
appBar:
CustomNavigationBar
(
title:
"Nạp tiền điện thoại"
),
body:
Obx
(()
{
body:
Obx
(()
{
...
...
lib/screen/topup/topup_viewmodel.dart
View file @
f1723336
...
@@ -2,6 +2,7 @@ import 'package:get/get.dart';
...
@@ -2,6 +2,7 @@ import 'package:get/get.dart';
import
'package:get/get_rx/src/rx_types/rx_types.dart'
;
import
'package:get/get_rx/src/rx_types/rx_types.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart'
;
import
'package:mypoint_flutter_app/preference/data_preference.dart'
;
import
'package:mypoint_flutter_app/preference/data_preference.dart'
;
import
'package:mypoint_flutter_app/screen/topup/models/brand_network_model.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
import
'../../preference/contact_storage_service.dart'
;
import
'../../preference/contact_storage_service.dart'
;
import
'../voucher/models/product_brand_model.dart'
;
import
'../voucher/models/product_brand_model.dart'
;
...
@@ -45,39 +46,32 @@ class TopUpViewModel extends RestfulApiViewModel {
...
@@ -45,39 +46,32 @@ class TopUpViewModel extends RestfulApiViewModel {
_getTopUpBrands
();
_getTopUpBrands
();
}
}
_getTopUpBrands
()
{
_getTopUpBrands
()
async
{
showLoading
();
await
callApi
<
List
<
ProductBrandModel
>>(
client
.
getTopUpBrands
(
ProductType
.
topupMobile
)
.
then
((
response
)
{
request:
()
=>
client
.
getTopUpBrands
(
ProductType
.
topupMobile
)
,
topUpBrands
.
value
=
response
.
data
??
[];
onSuccess:
(
data
,
_
)
{
hideLoading
()
;
topUpBrands
.
value
=
data
;
checkMobileNetwork
();
checkMobileNetwork
();
}).
catchError
((
error
)
{
},
hideLoading
();
showAppNavigatorDialog:
true
,
}
);
);
}
}
checkMobileNetwork
()
{
checkMobileNetwork
()
async
{
showLoading
();
await
callApi
<
BrandNameCheckResponse
>(
client
.
checkMobileNetwork
(
phoneNumber
.
value
).
then
((
response
)
{
request:
()
=>
client
.
checkMobileNetwork
(
phoneNumber
.
value
),
final
brandCode
=
response
.
data
?.
brand
??
''
;
onSuccess:
(
data
,
_
)
{
final
brand
=
topUpBrands
.
isNotEmpty
final
brandCode
=
data
?.
brand
??
''
;
var
brand
=
topUpBrands
.
isNotEmpty
?
topUpBrands
.
firstWhere
(
?
topUpBrands
.
firstWhere
(
(
brand
)
=>
brand
.
code
==
brandCode
,
(
brand
)
=>
brand
.
code
==
brandCode
,
orElse:
()
=>
topUpBrands
.
first
,
orElse:
()
=>
topUpBrands
.
first
,
)
)
:
topUpBrands
.
value
.
firstOrNull
;
:
null
;
selectedBrand
.
value
=
brand
;
selectedBrand
.
value
=
brand
;
hideLoading
();
getTelcoDetail
();
getTelcoDetail
();
}).
catchError
((
error
)
{
},
final
first
=
topUpBrands
.
value
.
firstOrNull
;
showAppNavigatorDialog:
true
,
if
(
first
!=
null
)
{
);
selectedBrand
.
value
=
first
;
}
hideLoading
();
getTelcoDetail
();
print
(
'Error checking mobile network:
$error
'
);
});
}
}
Future
<
void
>
getTelcoDetail
({
String
?
selected
})
async
{
Future
<
void
>
getTelcoDetail
({
String
?
selected
})
async
{
...
@@ -112,23 +106,20 @@ class TopUpViewModel extends RestfulApiViewModel {
...
@@ -112,23 +106,20 @@ class TopUpViewModel extends RestfulApiViewModel {
makeSelected
(
cached
);
makeSelected
(
cached
);
return
;
return
;
}
}
showLoading
();
final
body
=
{
final
body
=
{
"type"
:
ProductType
.
topupMobile
.
value
,
"type"
:
ProductType
.
topupMobile
.
value
,
"size"
:
200
,
"size"
:
200
,
"index"
:
0
,
"index"
:
0
,
"brand_id"
:
selectedBrand
.
value
?.
id
??
0
,
"brand_id"
:
selectedBrand
.
value
?.
id
??
0
,
};
};
try
{
await
callApi
<
List
<
ProductModel
>>(
final
result
=
await
client
.
getProducts
(
body
)
;
request:
()
=>
client
.
getProducts
(
body
)
,
final
data
=
result
.
data
??
[];
onSuccess:
(
data
,
_
)
{
_allValue
[
code
]
=
data
;
_allValue
[
code
]
=
data
;
products
.
value
=
result
.
data
??
[];
products
.
value
=
data
;
hideLoading
();
makeSelected
(
data
);
makeSelected
(
data
);
}
catch
(
error
)
{
},
print
(
"Error fetching all products:
$error
"
);
showAppNavigatorDialog:
true
,
hideLoading
();
);
}
}
}
}
}
\ No newline at end of file
Prev
1
2
3
Next
Write
Preview
Supports
Markdown
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