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
0bf528a4
Commit
0bf528a4
authored
Oct 17, 2025
by
DatHV
Browse files
refactor logic
parent
89983084
Changes
54
Hide whitespace changes
Inline
Side-by-side
lib/
networking
/app_navigator.dart
→
lib/
base
/app_navigator.dart
View file @
0bf528a4
...
@@ -16,13 +16,17 @@ class AppNavigator {
...
@@ -16,13 +16,17 @@ class AppNavigator {
static
bool
_authDialogShown
=
false
;
static
bool
_authDialogShown
=
false
;
static
bool
_networkDialogShown
=
false
;
static
bool
_networkDialogShown
=
false
;
static
bool
_errorDialogShown
=
false
;
static
bool
_errorDialogShown
=
false
;
static
bool
_defaultDialogShown
=
false
;
static
bool
get
isShowingDialog
=>
_authDialogShown
||
_networkDialogShown
||
_errorDialogShown
||
_defaultDialogShown
;
static
bool
get
isShowingDialog
=>
_authDialogShown
||
_networkDialogShown
||
_errorDialogShown
;
static
BuildContext
?
get
_ctx
=>
key
.
currentContext
;
static
BuildContext
?
get
_ctx
=>
key
.
currentContext
;
static
Future
<
void
>
showAuthAlertAndGoLogin
(
String
message
)
async
{
static
Future
<
void
>
showAuthAlertAndGoLogin
(
String
message
)
async
{
final
description
=
'Phiên đăng nhập của bạn đã hết hạn. Vui lòng đăng nhập lại để tiếp tục sử dụng ứng dụng.'
;
final
description
=
'Phiên đăng nhập của bạn đã hết hạn. Vui lòng đăng nhập lại để tiếp tục sử dụng ứng dụng.'
;
if
(
_authDialogShown
||
_ctx
==
null
)
return
;
if
(
_authDialogShown
||
_ctx
==
null
)
return
;
if
(
Get
.
isDialogOpen
??
false
)
Get
.
back
();
_authDialogShown
=
true
;
_authDialogShown
=
true
;
final
dataAlert
=
DataAlertModel
(
final
dataAlert
=
DataAlertModel
(
title:
"Thông Báo"
,
title:
"Thông Báo"
,
...
@@ -32,12 +36,12 @@ class AppNavigator {
...
@@ -32,12 +36,12 @@ class AppNavigator {
AlertButton
(
AlertButton
(
text:
"Đã hiểu"
,
text:
"Đã hiểu"
,
onPressed:
()
{
onPressed:
()
{
_authDialogShown
=
false
;
if
(
kIsWeb
)
{
if
(
kIsWeb
)
{
webCloseApp
({
webCloseApp
({
'message'
:
message
.
isNotEmpty
?
message
:
description
,
'message'
:
message
.
isNotEmpty
?
message
:
description
,
'timestamp'
:
DateTime
.
now
().
millisecondsSinceEpoch
,
'timestamp'
:
DateTime
.
now
().
millisecondsSinceEpoch
,
});
});
_authDialogShown
=
false
;
return
;
return
;
}
}
final
phone
=
DataPreference
.
instance
.
phoneNumberUsedForLoginScreen
;
final
phone
=
DataPreference
.
instance
.
phoneNumberUsedForLoginScreen
;
...
@@ -47,14 +51,18 @@ class AppNavigator {
...
@@ -47,14 +51,18 @@ class AppNavigator {
DataPreference
.
instance
.
clearData
();
DataPreference
.
instance
.
clearData
();
Get
.
offAllNamed
(
onboardingScreen
);
Get
.
offAllNamed
(
onboardingScreen
);
}
}
_authDialogShown
=
false
;
},
},
bgColor:
BaseColor
.
primary500
,
bgColor:
BaseColor
.
primary500
,
textColor:
Colors
.
white
,
textColor:
Colors
.
white
,
),
),
],
],
);
);
Get
.
dialog
(
CustomAlertDialog
(
alertData:
dataAlert
,
showCloseButton:
false
),
barrierDismissible:
false
);
Get
.
dialog
(
CustomAlertDialog
(
alertData:
dataAlert
,
showCloseButton:
false
),
barrierDismissible:
false
).
then
((
_
)
{
// Reset flag khi dialog đóng bằng barrierDismissible hoặc cách khác
if
(
_authDialogShown
)
{
_authDialogShown
=
false
;
}
});
}
}
static
Future
<
void
>
showNoInternetAlert
(
String
message
,
Callback
retry
,
Callback
close
)
async
{
static
Future
<
void
>
showNoInternetAlert
(
String
message
,
Callback
retry
,
Callback
close
)
async
{
...
@@ -90,7 +98,12 @@ class AppNavigator {
...
@@ -90,7 +98,12 @@ class AppNavigator {
Get
.
dialog
(
Get
.
dialog
(
CustomAlertDialog
(
alertData:
dataAlert
,
showCloseButton:
false
,
direction:
ButtonsDirection
.
row
),
CustomAlertDialog
(
alertData:
dataAlert
,
showCloseButton:
false
,
direction:
ButtonsDirection
.
row
),
barrierDismissible:
false
,
barrierDismissible:
false
,
);
).
then
((
_
)
{
// Reset flag khi dialog đóng bằng barrierDismissible hoặc cách khác
if
(
_networkDialogShown
)
{
_networkDialogShown
=
false
;
}
});
}
}
static
void
showAlertError
({
static
void
showAlertError
({
...
@@ -100,6 +113,7 @@ class AppNavigator {
...
@@ -100,6 +113,7 @@ class AppNavigator {
bool
showCloseButton
=
false
,
bool
showCloseButton
=
false
,
VoidCallback
?
onConfirmed
,
VoidCallback
?
onConfirmed
,
})
{
})
{
print
(
"Show alert error:
$_errorDialogShown
"
);
if
(
_errorDialogShown
||
_ctx
==
null
)
return
;
if
(
_errorDialogShown
||
_ctx
==
null
)
return
;
_errorDialogShown
=
true
;
_errorDialogShown
=
true
;
Get
.
dialog
(
Get
.
dialog
(
...
@@ -126,18 +140,76 @@ class AppNavigator {
...
@@ -126,18 +140,76 @@ class AppNavigator {
),
),
),
),
barrierDismissible:
barrierDismissible
??
false
,
barrierDismissible:
barrierDismissible
??
false
,
);
).
then
((
_
)
{
// Reset flag khi dialog đóng bằng barrierDismissible hoặc cách khác
if
(
_errorDialogShown
)
{
_errorDialogShown
=
false
;
}
});
}
}
static
void
showPopup
({
static
void
showPopup
({
required
PopupDataModel
data
,
required
PopupDataModel
data
,
bool
?
barrierDismissibl
,
bool
?
barrierDismissibl
e
,
bool
showCloseButton
=
false
,
bool
showCloseButton
=
false
,
ButtonsDirection
direction
=
ButtonsDirection
.
column
,
ButtonsDirection
direction
=
ButtonsDirection
.
column
,
bool
force
=
false
,
})
{
})
{
Get
.
dialog
(
showAlert
(
CustomAlertDialog
(
alertData:
data
.
dataAlertModel
,
showCloseButton:
showCloseButton
,
direction:
direction
),
data:
data
.
dataAlertModel
,
barrierDismissible:
barrierDismissibl
??
true
,
barrierDismissible:
barrierDismissible
??
true
,
showCloseButton:
showCloseButton
,
direction:
direction
,
force:
force
,
);
);
}
}
static
void
showAlert
({
required
DataAlertModel
data
,
bool
?
barrierDismissible
,
bool
showCloseButton
=
true
,
ButtonsDirection
direction
=
ButtonsDirection
.
column
,
bool
force
=
false
,
})
{
if
(
force
)
{
_defaultDialogShown
=
false
;
if
(
Get
.
isDialogOpen
??
false
)
Get
.
back
();
}
if
(
_defaultDialogShown
||
_ctx
==
null
)
return
;
_defaultDialogShown
=
true
;
// Wrap buttons với callback để reset flag
final
wrappedData
=
DataAlertModel
(
localHeaderImage:
data
.
localHeaderImage
,
urlHeaderImage:
data
.
urlHeaderImage
,
title:
data
.
title
,
description:
data
.
description
,
content:
data
.
content
,
buttons:
data
.
buttons
?.
map
((
button
)
{
if
(
button
==
null
)
return
null
;
return
AlertButton
(
text:
button
.
text
,
textColor:
button
.
textColor
,
bgColor:
button
.
bgColor
,
onPressed:
()
{
// Gọi callback gốc trước
button
.
onPressed
();
// Sau đó reset flag
_defaultDialogShown
=
false
;
},
);
}).
toList
(),
);
Get
.
dialog
(
CustomAlertDialog
(
alertData:
wrappedData
,
showCloseButton:
showCloseButton
,
direction:
direction
),
barrierDismissible:
barrierDismissible
??
false
,
).
then
((
_
)
{
// Reset flag khi dialog đóng bằng barrierDismissible hoặc cách khác
if
(
_defaultDialogShown
)
{
_defaultDialogShown
=
false
;
}
});
}
}
}
lib/base/base_screen.dart
View file @
0bf528a4
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/base/app_navigator.dart'
;
import
'package:mypoint_flutter_app/networking/app_navigator.dart'
;
import
'package:mypoint_flutter_app/main.dart'
show
routeObserver
;
import
'package:mypoint_flutter_app/main.dart'
show
routeObserver
;
import
'../resources/base_color.dart'
;
import
'../widgets/alert/custom_alert_dialog.dart'
;
import
'../widgets/alert/custom_alert_dialog.dart'
;
import
'../widgets/alert/data_alert_model.dart'
;
import
'../widgets/alert/data_alert_model.dart'
;
import
'../widgets/alert/popup_data_model.dart'
;
import
'../widgets/alert/popup_data_model.dart'
;
...
@@ -14,7 +12,6 @@ abstract class BaseScreen extends StatefulWidget {
...
@@ -14,7 +12,6 @@ abstract class BaseScreen extends StatefulWidget {
abstract
class
BaseState
<
Screen
extends
BaseScreen
>
extends
State
<
Screen
>
abstract
class
BaseState
<
Screen
extends
BaseScreen
>
extends
State
<
Screen
>
with
WidgetsBindingObserver
,
RouteAware
{
with
WidgetsBindingObserver
,
RouteAware
{
bool
_isVisible
=
false
;
ModalRoute
<
dynamic
>?
_route
;
ModalRoute
<
dynamic
>?
_route
;
@override
@override
...
@@ -125,13 +122,11 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen>
...
@@ -125,13 +122,11 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen>
bool
showCloseButton
=
false
,
bool
showCloseButton
=
false
,
ButtonsDirection
direction
=
ButtonsDirection
.
column
,
ButtonsDirection
direction
=
ButtonsDirection
.
column
,
})
{
})
{
Get
.
dialog
(
showAlert
(
CustomAlertDialog
(
data:
data
.
dataAlertModel
,
alertData:
data
.
dataAlertModel
,
showCloseButton:
showCloseButton
,
direction:
direction
,
),
barrierDismissible:
barrierDismissible
??
true
,
barrierDismissible:
barrierDismissible
??
true
,
showCloseButton:
showCloseButton
,
direction:
direction
,
);
);
}
}
...
@@ -142,13 +137,11 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen>
...
@@ -142,13 +137,11 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen>
bool
showCloseButton
=
true
,
bool
showCloseButton
=
true
,
ButtonsDirection
direction
=
ButtonsDirection
.
column
,
ButtonsDirection
direction
=
ButtonsDirection
.
column
,
})
{
})
{
Get
.
dialog
(
AppNavigator
.
showAlert
(
CustomAlertDialog
(
data:
data
,
alertData:
data
,
barrierDismissible:
barrierDismissible
,
showCloseButton:
showCloseButton
,
showCloseButton:
showCloseButton
,
direction:
direction
,
direction:
direction
),
barrierDismissible:
barrierDismissible
??
false
,
);
);
}
}
...
@@ -160,28 +153,12 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen>
...
@@ -160,28 +153,12 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen>
bool
showCloseButton
=
true
,
bool
showCloseButton
=
true
,
VoidCallback
?
onConfirmed
,
VoidCallback
?
onConfirmed
,
})
{
})
{
if
(
AppNavigator
.
isShowingDialog
)
return
;
AppNavigator
.
showAlertError
(
Get
.
dialog
(
content:
content
,
CustomAlertDialog
(
barrierDismissible:
barrierDismissible
,
showCloseButton:
showCloseButton
,
headerImage:
headerImage
,
alertData:
DataAlertModel
(
showCloseButton:
showCloseButton
,
localHeaderImage:
headerImage
,
onConfirmed:
onConfirmed
,
title:
""
,
description:
content
,
buttons:
[
AlertButton
(
text:
"Đã Hiểu"
,
onPressed:
()
{
Get
.
back
();
onConfirmed
?.
call
();
},
bgColor:
BaseColor
.
primary500
,
textColor:
Colors
.
white
,
),
],
),
),
barrierDismissible:
barrierDismissible
??
false
,
);
);
}
}
...
@@ -193,7 +170,6 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen>
...
@@ -193,7 +170,6 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen>
// MARK: - RouteAware Implementation
// MARK: - RouteAware Implementation
@override
@override
void
didPush
()
{
void
didPush
()
{
_isVisible
=
true
;
_handleRouteAppear
();
_handleRouteAppear
();
}
}
...
...
lib/directional/directional_screen.dart
View file @
0bf528a4
...
@@ -9,7 +9,7 @@ import 'package:mypoint_flutter_app/widgets/alert/popup_data_model.dart';
...
@@ -9,7 +9,7 @@ import 'package:mypoint_flutter_app/widgets/alert/popup_data_model.dart';
import
'package:url_launcher/url_launcher.dart'
;
import
'package:url_launcher/url_launcher.dart'
;
import
'package:uuid/uuid.dart'
;
import
'package:uuid/uuid.dart'
;
import
'../configs/constants.dart'
;
import
'../configs/constants.dart'
;
import
'../
networking
/app_navigator.dart'
;
import
'../
base
/app_navigator.dart'
;
import
'../networking/restful_api_viewmodel.dart'
;
import
'../networking/restful_api_viewmodel.dart'
;
import
'../screen/pageDetail/model/detail_page_rule_type.dart'
;
import
'../screen/pageDetail/model/detail_page_rule_type.dart'
;
import
'../screen/pipi/pipi_detail_screen.dart'
;
import
'../screen/pipi/pipi_detail_screen.dart'
;
...
...
lib/main.dart
View file @
0bf528a4
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_localizations/flutter_localizations.dart'
;
import
'package:flutter_localizations/flutter_localizations.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/
networking
/app_navigator.dart'
;
import
'package:mypoint_flutter_app/
base
/app_navigator.dart'
;
import
'package:mypoint_flutter_app/resources/base_color.dart'
;
import
'package:mypoint_flutter_app/resources/base_color.dart'
;
import
'package:mypoint_flutter_app/shared/router_gage.dart'
;
import
'package:mypoint_flutter_app/shared/router_gage.dart'
;
import
'package:mypoint_flutter_app/core/app_initializer.dart'
;
import
'package:mypoint_flutter_app/core/app_initializer.dart'
;
...
...
lib/networking/interceptor/auth_interceptor.dart
View file @
0bf528a4
import
'package:dio/dio.dart'
;
import
'package:dio/dio.dart'
;
import
'../../configs/constants.dart'
;
import
'../../configs/constants.dart'
;
import
'../app_navigator.dart'
;
import
'../
../base/
app_navigator.dart'
;
import
'../dio_http_service.dart'
;
import
'../dio_http_service.dart'
;
import
'package:mypoint_flutter_app/preference/data_preference.dart'
;
import
'package:mypoint_flutter_app/preference/data_preference.dart'
;
import
'../../services/token_refresh_service.dart'
;
import
'../../services/token_refresh_service.dart'
;
...
...
lib/networking/interceptor/exception_interceptor.dart
View file @
0bf528a4
import
'dart:async'
;
import
'dart:async'
;
import
'package:dio/dio.dart'
;
import
'package:dio/dio.dart'
;
import
'package:mypoint_flutter_app/base/app_loading.dart'
;
import
'package:mypoint_flutter_app/base/app_loading.dart'
;
import
'../app_navigator.dart'
;
import
'../
../base/
app_navigator.dart'
;
import
'../dio_http_service.dart'
;
import
'../dio_http_service.dart'
;
import
'../error_mapper.dart'
;
import
'../error_mapper.dart'
;
...
...
lib/networking/restful_api_client_all_request.dart
View file @
0bf528a4
...
@@ -63,7 +63,6 @@ import '../screen/pageDetail/model/detail_page_rule_type.dart';
...
@@ -63,7 +63,6 @@ import '../screen/pageDetail/model/detail_page_rule_type.dart';
import
'../screen/popup_manager/popup_manager_model.dart'
;
import
'../screen/popup_manager/popup_manager_model.dart'
;
import
'../screen/quiz_campaign/quiz_campaign_model.dart'
;
import
'../screen/quiz_campaign/quiz_campaign_model.dart'
;
import
'../screen/register_campaign/model/registration_form_package_model.dart'
;
import
'../screen/register_campaign/model/registration_form_package_model.dart'
;
import
'../screen/splash/splash_screen_viewmodel.dart'
;
import
'../screen/topup/models/brand_network_model.dart'
;
import
'../screen/topup/models/brand_network_model.dart'
;
import
'../screen/traffic_service/traffic_service_model.dart'
;
import
'../screen/traffic_service/traffic_service_model.dart'
;
import
'../screen/transaction/history/transaction_category_model.dart'
;
import
'../screen/transaction/history/transaction_category_model.dart'
;
...
...
lib/networking/restful_api_viewmodel.dart
View file @
0bf528a4
...
@@ -4,7 +4,7 @@ import 'package:mypoint_flutter_app/networking/restful_api_client.dart';
...
@@ -4,7 +4,7 @@ import 'package:mypoint_flutter_app/networking/restful_api_client.dart';
import
'../base/base_response_model.dart'
;
import
'../base/base_response_model.dart'
;
import
'../base/base_view_model.dart'
;
import
'../base/base_view_model.dart'
;
import
'../configs/constants.dart'
;
import
'../configs/constants.dart'
;
import
'app_navigator.dart'
;
import
'
../base/
app_navigator.dart'
;
import
'dio_http_service.dart'
;
import
'dio_http_service.dart'
;
import
'error_mapper.dart'
;
import
'error_mapper.dart'
;
import
'interceptor/network_error_gate.dart'
;
import
'interceptor/network_error_gate.dart'
;
...
...
lib/screen/affiliate/affiliate_tab_viewmodel.dart
View file @
0bf528a4
...
@@ -42,7 +42,6 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
...
@@ -42,7 +42,6 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
onFailure:
(
msg
,
_
,
__
)
async
{
onFailure:
(
msg
,
_
,
__
)
async
{
affiliateBrands
.
clear
();
affiliateBrands
.
clear
();
},
},
showAppNavigatorDialog:
true
,
);
);
}
}
...
@@ -65,7 +64,6 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
...
@@ -65,7 +64,6 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
affiliateCategories
.
clear
();
affiliateCategories
.
clear
();
allAffiliateCategories
.
clear
();
allAffiliateCategories
.
clear
();
},
},
showAppNavigatorDialog:
true
,
);
);
}
}
...
@@ -78,7 +76,6 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
...
@@ -78,7 +76,6 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
onFailure:
(
msg
,
_
,
__
)
async
{
onFailure:
(
msg
,
_
,
__
)
async
{
affiliateProducts
.
clear
();
affiliateProducts
.
clear
();
},
},
showAppNavigatorDialog:
true
,
);
);
}
}
...
@@ -103,10 +100,6 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
...
@@ -103,10 +100,6 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
onShowAffiliateBrandPopup
?.
call
((
data
,
category
.
name
??
''
));
onShowAffiliateBrandPopup
?.
call
((
data
,
category
.
name
??
''
));
}
}
},
},
onFailure:
(
msg
,
_
,
__
)
async
{
// Không cần làm gì, error đã được handle bởi callApi
},
showAppNavigatorDialog:
true
,
);
);
}
}
}
}
\ No newline at end of file
lib/screen/affiliate_brand_detail/affiliate_brand_detail_viewmodel.dart
View file @
0bf528a4
...
@@ -5,36 +5,28 @@ import '../../networking/restful_api_viewmodel.dart';
...
@@ -5,36 +5,28 @@ import '../../networking/restful_api_viewmodel.dart';
import
'models/affiliate_brand_detail_model.dart'
;
import
'models/affiliate_brand_detail_model.dart'
;
class
AffiliateBrandDetailViewModel
extends
RestfulApiViewModel
{
class
AffiliateBrandDetailViewModel
extends
RestfulApiViewModel
{
String
brandId
;
final
String
brandId
;
AffiliateBrandDetailViewModel
(
this
.
brandId
);
AffiliateBrandDetailViewModel
(
this
.
brandId
);
void
Function
(
String
message
)?
onShowAlertError
;
void
Function
(
String
message
)?
onShowAlertError
;
var
isLoading
=
false
.
obs
;
final
Rxn
<
AffiliateBrandDetailModel
>
brandDetailData
=
Rxn
<
AffiliateBrandDetailModel
>();
var
brandDetailData
=
Rxn
<
AffiliateBrandDetailModel
>();
@override
@override
void
onInit
()
{
void
onInit
()
{
super
.
onInit
();
super
.
onInit
();
_
getAffiliateBrand
Detail
();
_
fetch
Detail
();
}
}
Future
<
void
>
_getAffiliateBrandDetail
()
async
{
Future
<
void
>
_fetchDetail
()
async
{
showLoading
();
await
callApi
<
AffiliateBrandDetailModel
>(
if
(
isLoading
.
value
)
return
;
request:
()
=>
client
.
getAffiliateBrandDetail
(
brandId
),
try
{
onSuccess:
(
data
,
_
)
{
isLoading
.
value
=
true
;
brandDetailData
.
value
=
data
;
final
response
=
await
client
.
getAffiliateBrandDetail
(
brandId
);
},
hideLoading
();
onFailure:
(
msg
,
_
,
_
)
async
{
if
(
response
.
isSuccess
)
{
brandDetailData
.
value
=
null
;
brandDetailData
.
value
=
response
.
data
;
onShowAlertError
?.
call
(
msg
.
isNotEmpty
?
msg
:
Constants
.
commonError
);
}
else
{
},
onShowAlertError
?.
call
(
response
.
errorMessage
??
Constants
.
commonError
);
);
}
}
catch
(
error
)
{
showLoading
();
onShowAlertError
?.
call
(
"Error fetching product detail:
$error
"
);
}
finally
{
isLoading
.
value
=
false
;
}
}
}
}
}
lib/screen/affiliate_brand_detail/affiliate_category_grid_viewmodel.dart
View file @
0bf528a4
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/configs/constants.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/model/affiliate_brand_model.dart'
;
import
'../affiliate/model/affiliate_brand_model.dart'
;
import
'../affiliate/model/affiliate_category_model.dart'
;
import
'../affiliate/model/affiliate_category_model.dart'
;
class
AffiliateCategoryGridViewModel
extends
RestfulApiViewModel
{
class
AffiliateCategoryGridViewModel
extends
RestfulApiViewModel
{
final
RxBool
isLoading
=
false
.
obs
;
void
Function
((
List
<
AffiliateBrandModel
>,
String
)
data
)?
onShowAffiliateBrandPopup
;
void
Function
((
List
<
AffiliateBrandModel
>,
String
)
data
)?
onShowAffiliateBrandPopup
;
void
Function
(
String
message
)?
onShowAlertError
;
affiliateBrandGetListBuyCategory
(
AffiliateCategoryModel
category
)
async
{
Future
<
void
>
affiliateBrandGetListBuyCategory
(
AffiliateCategoryModel
category
)
async
{
showLoading
();
await
callApi
<
List
<
AffiliateBrandModel
>>(
try
{
request:
()
=>
client
.
affiliateBrandGetList
(
final
result
=
await
client
.
affiliateBrandGetList
(
categoryCode:
AffiliateCategoryModel
.
codeToJson
(
category
.
code
));
categoryCode:
AffiliateCategoryModel
.
codeToJson
(
category
.
code
),
hideLoading
();
),
final
data
=
result
.
data
??
[];
onSuccess:
(
data
,
_
)
{
if
(
result
.
isSuccess
&&
data
.
isNotEmpty
)
{
if
(
data
.
isNotEmpty
)
{
onShowAffiliateBrandPopup
?.
call
((
data
,
category
.
name
??
''
));
onShowAffiliateBrandPopup
?.
call
((
data
,
category
.
name
??
''
));
}
}
}
catch
(
error
)
{
},
hideLoading
();
onFailure:
(
msg
,
_
,
_
)
async
{
print
(
"Error fetching affiliate brands:
$error
"
);
onShowAlertError
?.
call
(
msg
);
}
},
);
}
}
}
}
\ No newline at end of file
lib/screen/bank_account_manager/bank_account_detail_screen.dart
View file @
0bf528a4
...
@@ -108,7 +108,7 @@ class _BankAccountDetailScreenState extends BaseState<BankAccountDetailScreen> w
...
@@ -108,7 +108,7 @@ class _BankAccountDetailScreenState extends BaseState<BankAccountDetailScreen> w
);
);
}
}
_showAlertConfirmLogout
()
{
void
_showAlertConfirmLogout
()
{
final
dataAlert
=
DataAlertModel
(
final
dataAlert
=
DataAlertModel
(
title:
"Xoá thẻ?"
,
title:
"Xoá thẻ?"
,
description:
"Bạn có chắc muốn xoá thẻ/tài khoản này?"
,
description:
"Bạn có chắc muốn xoá thẻ/tài khoản này?"
,
...
...
lib/screen/bank_account_manager/bank_account_detail_viewmodel.dart
View file @
0bf528a4
...
@@ -14,41 +14,31 @@ class BankAccountDetailViewModel extends RestfulApiViewModel {
...
@@ -14,41 +14,31 @@ class BankAccountDetailViewModel extends RestfulApiViewModel {
BankAccountDetailViewModel
({
required
this
.
model
});
BankAccountDetailViewModel
({
required
this
.
model
});
changeDefaultBankAccount
()
async
{
Future
<
void
>
changeDefaultBankAccount
()
async
{
final
revertDefault
=
!
isDefault
.
value
;
final
revertDefault
=
!
isDefault
.
value
;
final
accountId
=
model
.
id
.
toString
();
final
accountId
=
model
.
id
.
toString
();
showLoading
();
await
callApi
<
String
?>(
try
{
request:
()
=>
client
.
setDefaultBankAccount
(
accountId
,
revertDefault
),
final
response
=
await
client
.
setDefaultBankAccount
(
accountId
,
revertDefault
);
onSuccess:
(
data
,
_
)
{
hideLoading
();
if
(
response
.
isSuccess
)
{
isDefault
.
value
=
revertDefault
;
isDefault
.
value
=
revertDefault
;
showToastMessage
(
response
.
data
??
response
.
message
??
"Cập nhật thành công"
);
showToastMessage
(
data
??
"Cập nhật thành công"
);
}
else
{
},
onShowAlertError
?.
call
(
response
.
message
??
Constants
.
commonError
);
onFailure:
(
msg
,
_
,
_
)
async
{
}
onShowAlertError
?.
call
(
msg
.
isNotEmpty
?
msg
:
Constants
.
commonError
);
}
catch
(
error
)
{
},
hideLoading
();
);
onShowAlertError
?.
call
(
Constants
.
commonError
);
}
}
}
deleteBankAccount
()
async
{
Future
<
void
>
deleteBankAccount
()
async
{
final
accountId
=
model
.
id
.
toString
();
final
accountId
=
model
.
id
.
toString
();
showLoading
();
await
callApi
<
String
?>(
try
{
request:
()
=>
client
.
deleteBankAccount
(
accountId
),
final
response
=
await
client
.
deleteBankAccount
(
accountId
);
onSuccess:
(
data
,
_
)
{
hideLoading
();
deleteBackAccountSuccess
?.
call
(
data
??
"Xoá tài khoản thành công"
);
if
(
response
.
isSuccess
)
{
},
deleteBackAccountSuccess
?.
call
(
response
.
data
??
response
.
message
??
"Xoá tài khoản thành công"
);
onFailure:
(
msg
,
_
,
_
)
async
{
}
else
{
onShowAlertError
?.
call
(
msg
.
isNotEmpty
?
msg
:
Constants
.
commonError
);
onShowAlertError
?.
call
(
response
.
message
??
Constants
.
commonError
);
},
}
);
}
catch
(
error
)
{
hideLoading
();
onShowAlertError
?.
call
(
Constants
.
commonError
);
}
finally
{
hideLoading
();
}
}
}
}
}
\ No newline at end of file
lib/screen/bank_account_manager/bank_account_manager_viewmodel.dart
View file @
0bf528a4
import
'package:flutter/foundation.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.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'
;
...
@@ -13,16 +12,15 @@ class BankAccountManagerViewModel extends RestfulApiViewModel {
...
@@ -13,16 +12,15 @@ class BankAccountManagerViewModel extends RestfulApiViewModel {
getBankAccountList
();
getBankAccountList
();
}
}
getBankAccountList
()
async
{
Future
<
void
>
getBankAccountList
()
async
{
showLoading
();
await
callApi
<
List
<
BankAccountInfoModel
>>(
try
{
request:
()
=>
client
.
getOrderPaymentMyAccounts
(),
final
result
=
await
client
.
getOrderPaymentMyAccounts
();
onSuccess:
(
data
,
_
)
{
hideLoading
();
bankAccounts
.
assignAll
(
data
);
bankAccounts
.
value
=
result
.
data
??
[];
},
}
catch
(
error
)
{
onFailure:
(
_
,
_
,
_
)
async
{
hideLoading
();
bankAccounts
.
clear
();
}
finally
{
},
hideLoading
();
);
}
}
}
}
}
\ No newline at end of file
lib/screen/campaign7day/campaign_7day_screen.dart
View file @
0bf528a4
...
@@ -43,10 +43,14 @@ class _Campaign7DayScreenState extends BaseState<Campaign7DayScreen> with BasicS
...
@@ -43,10 +43,14 @@ class _Campaign7DayScreenState extends BaseState<Campaign7DayScreen> with BasicS
_viewModel
=
Get
.
put
(
Campaign7DayViewModel
(
campaignId:
campaignId
));
_viewModel
=
Get
.
put
(
Campaign7DayViewModel
(
campaignId:
campaignId
));
_viewModel
.
getLiveTransactions
();
_viewModel
.
getLiveTransactions
();
_viewModel
.
getCampaign7DayInfo
();
_viewModel
.
getCampaign7DayInfo
();
_viewModel
.
onShowAlertError
=
(
message
)
{
_viewModel
.
onShowAlertError
=
(
message
,
onBack
)
{
if
(
message
.
isNotEmpty
)
{
if
(
message
.
isEmpty
)
return
;
showAlertError
(
content:
message
);
showAlertError
(
}
content:
message
,
showCloseButton:
!
onBack
,
onConfirmed:
()
{
if
(
onBack
)
Get
.
back
();
});
};
};
_viewModel
.
submitPerformMissionResponse
=
(
mission
)
{
_viewModel
.
submitPerformMissionResponse
=
(
mission
)
{
final
popup
=
mission
.
popup
;
final
popup
=
mission
.
popup
;
...
...
lib/screen/campaign7day/campaign_7day_viewmodel.dart
View file @
0bf528a4
...
@@ -7,63 +7,69 @@ import 'models/campaign_7day_mission_model.dart';
...
@@ -7,63 +7,69 @@ import 'models/campaign_7day_mission_model.dart';
import
'models/campaign_7day_reward_model.dart'
;
import
'models/campaign_7day_reward_model.dart'
;
class
Campaign7DayViewModel
extends
RestfulApiViewModel
{
class
Campaign7DayViewModel
extends
RestfulApiViewModel
{
String
campaignId
;
final
String
campaignId
;
var
liveTransactions
=
RxList
<
String
>
()
;
final
RxList
<
String
>
liveTransactions
=
<
String
>
[].
obs
;
var
campaign7DayInfo
=
Rxn
<
Campaign7DayInfoModel
>();
final
Rxn
<
Campaign7DayInfoModel
>
campaign7DayInfo
=
Rxn
<
Campaign7DayInfoModel
>();
void
Function
(
String
message
)?
onShowAlertError
;
void
Function
(
String
message
,
bool
onBack
)?
onShowAlertError
;
void
Function
(
Campaign7DayMissionModel
mission
)?
submitPerformMissionResponse
;
void
Function
(
Campaign7DayMissionModel
mission
)?
submitPerformMissionResponse
;
void
Function
(
List
<
Campaign7DayRewardModel
>
rewards
)?
getCampaignRewardsResponse
;
void
Function
(
List
<
Campaign7DayRewardModel
>
rewards
)?
getCampaignRewardsResponse
;
Campaign7DayViewModel
({
required
this
.
campaignId
});
Campaign7DayViewModel
({
required
this
.
campaignId
});
void
getLiveTransactions
()
{
void
getLiveTransactions
()
{
client
.
getCampaignLiveTransactions
(
campaignId
).
then
((
value
)
{
callApi
<
List
<
String
>>(
liveTransactions
.
value
=
value
.
data
??
[];
request:
()
=>
client
.
getCampaignLiveTransactions
(
campaignId
),
});
onSuccess:
(
data
,
_
)
{
liveTransactions
.
assignAll
(
data
);
},
withLoading:
false
,
);
}
}
void
getCampaignRewards
()
{
void
getCampaignRewards
()
{
showLoading
();
callApi
<
List
<
Campaign7DayRewardModel
>>(
client
.
getCampaignRewards
(
campaignId
).
then
((
value
)
{
request:
()
=>
client
.
getCampaignRewards
(
campaignId
),
hideLoading
();
onSuccess:
(
data
,
_
)
{
final
data
=
value
.
data
??
[];
if
(
data
.
isEmpty
)
{
if
(!
value
.
isSuccess
)
{
onShowAlertError
?.
call
(
"Bạn chưa có phần thưởng nào. Vui lòng hoàn thành các nhiệm vụ để nhận thưởng!"
,
false
);
onShowAlertError
?.
call
(
value
.
errorMessage
??
Constants
.
commonError
);
}
else
{
return
;
getCampaignRewardsResponse
?.
call
(
data
);
}
}
if
(
data
.
isEmpty
)
{
},
onShowAlertError
?.
call
(
"Bạn chưa có phần thưởng nào. Vui lòng hoàn thành các nhiệm vụ để nhận thưởng!"
);
onFailure:
(
msg
,
_
,
_
)
async
{
}
else
{
onShowAlertError
?.
call
(
msg
.
isNotEmpty
?
msg
:
Constants
.
commonError
,
false
);
getCampaignRewardsResponse
?.
call
(
data
);
},
}
);
});
}
}
void
getCampaign7DayInfo
({
bool
silent
=
false
})
{
void
getCampaign7DayInfo
({
bool
silent
=
false
})
{
client
.
getCampaignMissions
(
campaignId
).
then
((
value
)
{
callApi
<
Campaign7DayInfoModel
>(
if
(!
value
.
isSuccess
&&
!
silent
)
{
request:
()
=>
client
.
getCampaignMissions
(
campaignId
),
onShowAlertError
?.
call
(
value
.
errorMessage
??
Constants
.
commonError
);
onSuccess:
(
data
,
_
)
{
}
campaign7DayInfo
.
value
=
data
;
campaign7DayInfo
.
value
=
value
.
data
;
},
});
onFailure:
(
msg
,
_
,
_
)
async
{
if
(!
silent
)
onShowAlertError
?.
call
(
msg
.
isNotEmpty
?
msg
:
Constants
.
commonError
,
true
);
},
);
}
}
void
submitPerformMission
(
Campaign7DayMissionModel
mission
)
{
void
submitPerformMission
(
Campaign7DayMissionModel
mission
)
{
if
(!
mission
.
isReady
)
return
;
if
(!
mission
.
isReady
)
return
;
showLoading
();
callApi
<
void
>(
client
.
submitPerformMission
(
mission
,
campaignId
).
then
((
value
)
{
request:
()
=>
client
.
submitPerformMission
(
mission
,
campaignId
),
hideLoading
();
onSuccess:
(
_
,
__
)
{
if
(
value
.
isSuccess
)
{
getCampaign7DayInfo
(
silent:
true
);
getCampaign7DayInfo
(
silent:
true
);
if
(
mission
.
popup
!=
null
)
{
if
(
mission
.
popup
!=
null
)
{
submitPerformMissionResponse
?.
call
(
mission
);
submitPerformMissionResponse
?.
call
(
mission
);
}
else
{
}
else
{
mission
.
directionScreen
?.
begin
();
mission
.
directionScreen
?.
begin
();
}
}
}
else
{
},
onShowAlertError
?.
call
(
value
.
errorMessage
??
Constants
.
commonError
);
onFailure:
(
msg
,
_
,
_
)
async
{
}
onShowAlertError
?.
call
(
msg
.
isNotEmpty
?
msg
:
Constants
.
commonError
,
false
);
});
},
);
}
}
}
}
lib/screen/change_pass/change_pass_viewmodel.dart
View file @
0bf528a4
import
'package:get/get.dart'
;
import
'package:get/get.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
'../../base/base_response_model.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
import
'../../configs/constants.dart'
;
import
'../../configs/constants.dart'
;
import
'../../preference/data_preference.dart'
;
import
'../../preference/data_preference.dart'
;
...
@@ -7,12 +8,13 @@ import '../create_pass/change_pass_repository.dart';
...
@@ -7,12 +8,13 @@ import '../create_pass/change_pass_repository.dart';
import
'../create_pass/create_pass_screen.dart'
;
import
'../create_pass/create_pass_screen.dart'
;
import
'../login/login_viewmodel.dart'
;
import
'../login/login_viewmodel.dart'
;
import
'../otp/forgot_pass_otp_repository.dart'
;
import
'../otp/forgot_pass_otp_repository.dart'
;
import
'../otp/model/create_otp_response_model.dart'
;
import
'../otp/otp_screen.dart'
;
import
'../otp/otp_screen.dart'
;
class
ChangePassViewModel
extends
RestfulApiViewModel
{
class
ChangePassViewModel
extends
RestfulApiViewModel
{
var
isPasswordVisible
=
false
.
obs
;
final
RxBool
isPasswordVisible
=
false
.
obs
;
var
password
=
""
.
obs
;
final
RxString
password
=
""
.
obs
;
var
loginState
=
LoginState
.
idle
.
obs
;
final
Rx
<
LoginState
>
loginState
=
LoginState
.
idle
.
obs
;
void
Function
(
String
message
)?
onShowAlertError
;
void
Function
(
String
message
)?
onShowAlertError
;
void
onPasswordChanged
(
String
value
)
{
void
onPasswordChanged
(
String
value
)
{
...
@@ -28,27 +30,29 @@ class ChangePassViewModel extends RestfulApiViewModel {
...
@@ -28,27 +30,29 @@ class ChangePassViewModel extends RestfulApiViewModel {
isPasswordVisible
.
value
=
!
isPasswordVisible
.
value
;
isPasswordVisible
.
value
=
!
isPasswordVisible
.
value
;
}
}
void
onForgotPassPressed
(
String
phone
)
{
// void onForgotPassPressed(String phone) {
showLoading
();
// callApi<CreateOTPResponseModel>(
client
.
otpCreateNew
(
phone
).
then
((
value
)
{
// request: () => client.otpCreateNew(phone),
hideLoading
();
// onSuccess: (data, _) {
// TODO: handle error later
// final ttl = data.resendAfterSecond ?? Constants.otpTtl;
if
(
value
.
isSuccess
)
{
// Get.to(OtpScreen(repository: ForgotPassOTPRepository(phone, ttl)));
Get
.
to
(
OtpScreen
(
repository:
ForgotPassOTPRepository
(
phone
,
value
.
data
?.
resendAfterSecond
??
Constants
.
otpTtl
)));
// },
}
// onFailure: (msg, _, _) async {
});
// onShowAlertError?.call(msg.isNotEmpty ? msg : Constants.commonError);
}
// },
// );
// }
Future
<
void
>
accountCheckForPasswordChange
()
async
{
Future
<
void
>
accountCheckForPasswordChange
()
async
{
showLoading
();
final
phone
=
DataPreference
.
instance
.
phone
??
""
;
final
phone
=
await
DataPreference
.
instance
.
phone
??
""
;
await
callApi
<
EmptyCodable
>(
client
.
accountLoginForPasswordChange
(
phone
,
password
.
value
).
then
((
value
)
{
request:
()
=>
client
.
accountLoginForPasswordChange
(
phone
,
password
.
value
),
hideLoading
();
onSuccess:
(
_
,
_
)
{
if
(
value
.
isSuccess
)
{
Get
.
to
(
CreatePasswordScreen
(
repository:
ChangePasswordRepository
(
phone
)));
Get
.
to
(
CreatePasswordScreen
(
repository:
ChangePasswordRepository
(
phone
)));
}
else
{
},
onShowAlertError
?.
call
(
value
.
errorMessage
??
Constants
.
commonError
);
onFailure:
(
msg
,
_
,
_
)
async
{
}
onShowAlertError
?.
call
(
msg
.
isNotEmpty
?
msg
:
Constants
.
commonError
);
});
},
);
}
}
}
}
lib/screen/chart/energy_month_bar_chart.dart
deleted
100644 → 0
View file @
89983084
// import 'dart:math';
// import 'package:fl_chart/fl_chart.dart';
// import 'package:flutter/material.dart';
//
// /// Dữ liệu 30 ngày, mỗi phần tử là kWh (double).
// class EnergyMonthBarChart extends StatefulWidget {
// final List<double> values; // length 28-31 (tháng)
// final DateTime startDate; // ngày đầu (ví dụ: 1/9/2025)
// final Color barColor;
// final String unit; // "kWh"
// final double? maxY; // nếu null sẽ auto
// final bool showGrid;
//
// const EnergyMonthBarChart({
// super.key,
// required this.values,
// required this.startDate,
// this.barColor = const Color(0xFF3B5AFB),
// this.unit = 'kWh',
// this.maxY,
// this.showGrid = true,
// });
//
// @override
// State<EnergyMonthBarChart> createState() => _EnergyMonthBarChartState();
// }
//
// class _EnergyMonthBarChartState extends State<EnergyMonthBarChart> {
// int? _touchedIndex;
//
// int get length => widget.values.length;
// double get _computedMaxY {
// final m = widget.values.fold<double>(0, (p, v) => max(p, v));
// if (m == 0) return 10;
// final step = 4; // nấc hiển thị
// return (m / step).ceil() * step.toDouble() + 2; // dư chút cho đẹp
// }
//
// // Ngày hiện tại nằm trong dải?
// int? get _todayIndex {
// final today = DateTime.now();
// final s = DateUtils.dateOnly(widget.startDate);
// for (int i = 0; i < length; i++) {
// final d = DateUtils.addDaysToDate(s, i);
// if (DateUtils.isSameDay(d, today)) return i;
// }
// return null;
// }
//
// String _weekdayLabel(DateTime d) {
// const labels = ['CN','T2','T3','T4','T5','T6','T7'];
// return labels[d.weekday % 7];
// }
//
// @override
// Widget build(BuildContext context) {
// final theme = Theme.of(context);
// final maxY = widget.maxY ?? _computedMaxY;
// final sDate = DateUtils.dateOnly(widget.startDate);
//
// // barWidth để fit 30 cột gọn trong thẻ:
// final barWidth = 12.0;
// final groups = List.generate(length, (i) {
// final v = widget.values[i];
// return BarChartGroupData(
// x: i,
// barRods: [
// BarChartRodData(
// toY: v,
// width: barWidth,
// borderRadius: const BorderRadius.vertical(top: Radius.circular(8)),
// gradient: LinearGradient(
// begin: Alignment.bottomCenter,
// end: Alignment.topCenter,
// colors: [
// widget.barColor.withOpacity(0.25),
// widget.barColor,
// ],
// ),
// ),
// ],
// );
// });
//
// // trục dưới: hiển thị thứ & ngày (thưa để đỡ rối)
// Widget bottomTitles(double value, TitleMeta meta) {
// final i = value.toInt();
// if (i < 0 || i >= length) return const SizedBox.shrink();
// final d = DateUtils.addDaysToDate(sDate, i);
// // hiển thị cách 2 ngày 1 lần cho gọn
// if (i % 2 != 0) return const SizedBox.shrink();
// final isToday = _todayIndex == i;
// return Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// Text(
// _weekdayLabel(d),
// style: theme.textTheme.labelSmall?.copyWith(
// color: isToday ? widget.barColor : Colors.black54,
// fontWeight: isToday ? FontWeight.w600 : FontWeight.w400,
// ),
// ),
// const SizedBox(height: 2),
// Text(
// '${d.day}',
// style: theme.textTheme.labelSmall?.copyWith(
// color: isToday ? widget.barColor : Colors.black54,
// fontWeight: isToday ? FontWeight.w600 : FontWeight.w400,
// ),
// ),
// ],
// );
// }
//
// // trục trái: 0,4,8,...
// Widget leftTitles(double value, TitleMeta meta) {
// if (value % 4 != 0) return const SizedBox.shrink();
// return Text(
// value.toInt().toString(),
// style: theme.textTheme.labelSmall?.copyWith(color: Colors.black45),
// );
// }
//
// final chart = BarChart(
// BarChartData(
// maxY: maxY,
// minY: 0,
// barGroups: groups,
// gridData: FlGridData(
// show: widget.showGrid,
// horizontalInterval: 4,
// getDrawingHorizontalLine: (v) => FlLine(
// color: Colors.black12,
// strokeWidth: 1,
// dashArray: [4, 4],
// ),
// drawVerticalLine: false,
// ),
// borderData: FlBorderData(show: false),
// titlesData: FlTitlesData(
// leftTitles: AxisTitles(
// sideTitles: SideTitles(showTitles: true, reservedSize: 28, getTitlesWidget: leftTitles),
// ),
// rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
// topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
// bottomTitles: AxisTitles(
// sideTitles: SideTitles(
// showTitles: true,
// reservedSize: 34,
// getTitlesWidget: bottomTitles,
// ),
// ),
// ),
// barTouchData: BarTouchData(
// enabled: true,
// handleBuiltInTouches: false, // tự custom tooltip
// touchCallback: (evt, resp) {
// setState(() {
// _touchedIndex = resp?.spot?.touchedBarGroupIndex;
// });
// if (resp?.spot != null && evt.isInterestedForInteractions) {
// final i = resp!.spot!.touchedBarGroupIndex;
// final v = widget.values[i];
// final d = DateUtils.addDaysToDate(sDate, i);
// final text = 'Số điện: ${v.toStringAsFixed(v % 1 == 0 ? 0 : 1)} ${widget.unit}';
// final overlay = Overlay.of(context);
// final entry = OverlayEntry(
// builder: (_) => _TooltipBubble(
// text: text,
// anchor: evt.localPosition,
// ),
// );
// overlay.insert(entry);
// Future.delayed(const Duration(milliseconds: 900), entry.remove);
// }
// },
// ),
// ),
// swapAnimationDuration: const Duration(milliseconds: 300),
// );
//
// // Vạch dọc nét đứt tại ngày hiện tại (nếu nằm trong dải)
// final todayIndex = _todayIndex;
//
// return Container(
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(24),
// boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 12, offset: Offset(0, 4))],
// ),
// padding: const EdgeInsets.fromLTRB(16, 16, 16, 12),
// child: SizedBox(
// height: 260,
// child: LayoutBuilder(
// builder: (ctx, cons) {
// final chartWidget = Padding(
// padding: const EdgeInsets.only(right: 8),
// child: chart,
// );
//
// if (todayIndex == null) return chartWidget;
//
// // Tính vị trí X ước lượng của cột today để vẽ vạch (theo tổng chiều rộng)
// // fl_chart không expose trực tiếp nên ta ước lượng theo spacing mặc định:
// final groupSpace = 8.0;
// final totalW = length * barWidth + (length - 1) * groupSpace;
// final usableW = cons.maxWidth - 28 /*left titles approx*/ - 8 /*right pad*/;
// final scale = usableW / totalW;
// final x = 28 + (todayIndex * (barWidth + groupSpace) + barWidth / 2) * scale;
//
// return Stack(
// children: [
// chartWidget,
// // vạch dọc nét đứt
// Positioned.fill(
// child: IgnorePointer(
// child: CustomPaint(
// painter: _DashedVerticalLinePainter(
// x: x,
// color: widget.barColor.withOpacity(0.5),
// ),
// ),
// ),
// ),
// ],
// );
// },
// ),
// ),
// );
// }
// }
//
// /// Tooltip đơn giản đặt gần vị trí chạm
// class _TooltipBubble extends StatelessWidget {
// final String text;
// final Offset anchor;
// const _TooltipBubble({required this.text, required this.anchor});
//
// @override
// Widget build(BuildContext context) {
// final theme = Theme.of(context);
// return Positioned(
// left: anchor.dx + 8,
// top: max(8, anchor.dy - 36),
// child: Material(
// color: Colors.transparent,
// child: Container(
// padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(10),
// boxShadow: const [BoxShadow(color: Colors.black26, blurRadius: 8)],
// ),
// child: Text(
// text,
// style: theme.textTheme.labelMedium?.copyWith(fontWeight: FontWeight.w600),
// ),
// ),
// ),
// );
// }
// }
//
// class _DashedVerticalLinePainter extends CustomPainter {
// final double x;
// final Color color;
// const _DashedVerticalLinePainter({required this.x, required this.color});
// @override
// void paint(Canvas canvas, Size size) {
// final paint = Paint()
// ..color = color
// ..strokeWidth = 2;
// const dash = 6.0;
// const gap = 6.0;
// double y = 0;
// while (y < size.height) {
// canvas.drawLine(Offset(x, y), Offset(x, min(y + dash, size.height)), paint);
// y += dash + gap;
// }
// }
// @override
// bool shouldRepaint(covariant _DashedVerticalLinePainter old) => old.x != x || old.color != color;
// }
lib/screen/contacts/contacts_list_screen.dart
View file @
0bf528a4
...
@@ -34,7 +34,7 @@ class _ContactsListScreenState extends State<ContactsListScreen> {
...
@@ -34,7 +34,7 @@ class _ContactsListScreenState extends State<ContactsListScreen> {
};
};
}
}
_openSMS
(
String
sms
,
String
phone
)
async
{
Future
<
void
>
_openSMS
(
String
sms
,
String
phone
)
async
{
final
uri
=
Uri
(
scheme:
'sms'
,
path:
phone
,
queryParameters:
<
String
,
String
>{
'body'
:
sms
});
final
uri
=
Uri
(
scheme:
'sms'
,
path:
phone
,
queryParameters:
<
String
,
String
>{
'body'
:
sms
});
if
(
await
canLaunchUrl
(
uri
))
{
if
(
await
canLaunchUrl
(
uri
))
{
...
@@ -42,7 +42,7 @@ class _ContactsListScreenState extends State<ContactsListScreen> {
...
@@ -42,7 +42,7 @@ class _ContactsListScreenState extends State<ContactsListScreen> {
}
}
}
}
_onSearchChanged
(
String
query
)
{
void
_onSearchChanged
(
String
query
)
{
setState
(()
{
setState
(()
{
displayContacts
=
searchContacts
(
query
);
displayContacts
=
searchContacts
(
query
);
});
});
...
...
lib/screen/data_network_service/data_network_service_screen.dart
View file @
0bf528a4
...
@@ -93,7 +93,7 @@ class _DataNetworkServiceScreenState extends BaseState<DataNetworkServiceScreen>
...
@@ -93,7 +93,7 @@ class _DataNetworkServiceScreenState extends BaseState<DataNetworkServiceScreen>
});
});
}
}
_redeemProductMobileCard
()
{
void
_redeemProductMobileCard
()
{
print
(
"redeem
${UserPointManager().point}
>=
${_viewModel.payPoint}
"
);
print
(
"redeem
${UserPointManager().point}
>=
${_viewModel.payPoint}
"
);
final
isValidInput
=
final
isValidInput
=
(
_viewModel
.
phoneNumber
.
value
.
trim
().
length
>=
10
)
&&
(
_viewModel
.
selectedProduct
.
value
!=
null
);
(
_viewModel
.
phoneNumber
.
value
.
trim
().
length
>=
10
)
&&
(
_viewModel
.
selectedProduct
.
value
!=
null
);
...
@@ -108,7 +108,7 @@ class _DataNetworkServiceScreenState extends BaseState<DataNetworkServiceScreen>
...
@@ -108,7 +108,7 @@ class _DataNetworkServiceScreenState extends BaseState<DataNetworkServiceScreen>
_showAlertConfirmRedeemProduct
();
_showAlertConfirmRedeemProduct
();
}
}
_showAlertConfirmRedeemProduct
()
{
void
_showAlertConfirmRedeemProduct
()
{
final
dataAlert
=
DataAlertModel
(
final
dataAlert
=
DataAlertModel
(
title:
"Xác nhận"
,
title:
"Xác nhận"
,
description:
"Bạn có muốn sử dụng
${_viewModel.payPoint.money(CurrencyUnit.point)}
MyPoint để đổi gói cước này không?"
,
description:
"Bạn có muốn sử dụng
${_viewModel.payPoint.money(CurrencyUnit.point)}
MyPoint để đổi gói cước này không?"
,
...
...
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